Kern's ToDo List
- 29 December 2002
+ 01 January 2003
Documentation to do: (a little bit at a time)
- Document running a test version.
- Look at ua_prune.c in detail. Why did JobType work at all??????
- Figure out how to allow multiple simultaneous file Volumes on
a single device.
+- Why are save/restore of device different sizes (sparse?)
For 1.29 release:
+- Backup of raw partitions
+- Figure out some way to automatically backup all local partitions
- Enable avoid backing up archive device (findlib/find_one.c:128)
- Implement FileOptions (see end of this document)
- Implement Bacula plugins -- design API
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
*/
/*
- Copyright (C) 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2001-2003 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
int db_get_client_ids(B_DB *mdb, int *num_ids, uint32_t *ids[])
{ return 0; }
-
-int db_get_client_record(B_DB *mdb, CLIENT_DBR *cdbr)
-{ return 0; }
-
#endif /* HAVE_BACULA_DB */
*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
char dummy;
};
-#define IS_NUM(x) ((x) == 1)
-#define IS_NOT_NULL(x) ((x) == 1)
+#define IS_NUM(x) ((x) == 1)
+#define IS_NOT_NULL(x) ((x) == 1)
typedef struct s_sql_field {
- char *name; /* name of column */
- uint32_t length; /* length */
- uint32_t max_length; /* max length */
- uint32_t type; /* type */
- uint32_t flags; /* flags */
+ char *name; /* name of column */
+ uint32_t length; /* length */
+ uint32_t max_length; /* max length */
+ uint32_t type; /* type */
+ uint32_t flags; /* flags */
} SQL_FIELD;
/*
* This is the "real" definition that should only be
* used inside sql.c and associated database interface
* subroutines.
- * S Q L I T E
+ * S Q L I T E
*/
typedef struct s_db {
- BQUEUE bq; /* queue control */
- brwlock_t lock; /* transaction lock */
+ BQUEUE bq; /* queue control */
+ brwlock_t lock; /* transaction lock */
struct sqlite *db;
char **result;
- int nrow; /* nrow returned from sqlite */
- int ncolumn; /* ncolum returned from sqlite */
- int num_rows; /* used by code */
- int row; /* seek row */
- int have_insert_id; /* do not have insert id */
- int fields_defined; /* set when fields defined */
- int field; /* seek field */
- SQL_FIELD **fields; /* defined fields */
+ int nrow; /* nrow returned from sqlite */
+ int ncolumn; /* ncolum returned from sqlite */
+ int num_rows; /* used by code */
+ int row; /* seek row */
+ int have_insert_id; /* do not have insert id */
+ int fields_defined; /* set when fields defined */
+ int field; /* seek field */
+ SQL_FIELD **fields; /* defined fields */
int ref_count;
char *db_name;
char *db_user;
char *db_password;
int connected;
- char *sqlite_errmsg; /* error message returned by sqlite */
- POOLMEM *errmsg; /* nicely edited error message */
- POOLMEM *cmd; /* SQL command string */
- POOLMEM *cached_path;
- uint32_t cached_path_id;
- int transaction; /* transaction started */
- int changes; /* changes during transaction */
- void *jcr; /* JCR or NULL */
+ char *sqlite_errmsg; /* error message returned by sqlite */
+ POOLMEM *errmsg; /* nicely edited error message */
+ POOLMEM *cmd; /* SQL command string */
+ POOLMEM *cached_path; /* cached path name */
+ int cached_path_len; /* length of cached path */
+ uint32_t cached_path_id; /* cached path id */
+ int transaction; /* transaction started */
+ int changes; /* changes during transaction */
+ void *jcr; /* JCR or NULL */
+ POOLMEM *fname; /* Filename only */
+ POOLMEM *path; /* Path only */
+ POOLMEM *esc_name; /* Escaped file/path name */
+ int fnl; /* file name length */
+ int pnl; /* path name length */
} B_DB;
/*
* "Generic" names for easier conversion
*
- * S Q L I T E
+ * S Q L I T E
*/
#define sql_store_result(x) x->result
#define sql_free_result(x) my_sqlite_free_table(x)
#define sql_fetch_row(x) my_sqlite_fetch_row(x)
#define sql_query(x, y) my_sqlite_query(x, y)
-#define sql_close(x) sqlite_close(x->db)
+#define sql_close(x) sqlite_close(x->db)
#define sql_strerror(x) x->sqlite_errmsg?x->sqlite_errmsg:"unknown"
#define sql_num_rows(x) x->nrow
#define sql_data_seek(x, i) x->row = i
#define sql_field_seek(x, y) my_sqlite_field_seek(x, y)
#define sql_fetch_field(x) my_sqlite_fetch_field(x)
#define sql_num_fields(x) (unsigned)((x)->ncolumn)
-#define SQL_ROW char**
+#define SQL_ROW char**
* used inside sql.c and associated database interface
* subroutines.
*
- * M Y S Q L
+ * M Y S Q L
*/
typedef struct s_db {
- BQUEUE bq; /* queue control */
- brwlock_t lock; /* transaction lock */
+ BQUEUE bq; /* queue control */
+ brwlock_t lock; /* transaction lock */
MYSQL mysql;
MYSQL *db;
MYSQL_RES *result;
char *db_name;
char *db_user;
char *db_password;
- int have_insert_id; /* do have insert_id() */
+ int have_insert_id; /* do have insert_id() */
int connected;
- POOLMEM *errmsg; /* nicely edited error message */
- POOLMEM *cmd; /* SQL command string */
+ POOLMEM *errmsg; /* nicely edited error message */
+ POOLMEM *cmd; /* SQL command string */
POOLMEM *cached_path;
uint32_t cached_path_id;
- int changes; /* changes made to db */
- void *jcr; /* JCR or NULL */
+ int changes; /* changes made to db */
+ void *jcr; /* JCR or NULL */
+ POOLMEM *fname; /* Filename only */
+ POOLMEM *path; /* Path only */
+ POOLMEM *esc_name; /* Escaped file/path name */
+ int fnl; /* file name length */
+ int pnl; /* path name length */
} B_DB;
#define sql_free_result(x) mysql_free_result(x->result)
#define sql_fetch_row(x) mysql_fetch_row(x->result)
#define sql_query(x, y) mysql_query(x->db, y)
-#define sql_close(x) mysql_close(x->db)
+#define sql_close(x) mysql_close(x->db)
#define sql_strerror(x) mysql_error(x->db)
#define sql_num_rows(x) mysql_num_rows(x->result)
#define sql_data_seek(x, i) mysql_data_seek(x->result, i)
#define sql_field_seek(x, y) mysql_field_seek(x->result, y)
#define sql_fetch_field(x) mysql_fetch_field(x->result)
#define sql_num_fields(x) mysql_num_fields(x->result)
-#define SQL_ROW MYSQL_ROW
-#define SQL_FIELD MYSQL_FIELD
+#define SQL_ROW MYSQL_ROW
+#define SQL_FIELD MYSQL_FIELD
#else /* USE BACULA DB routines */
/* Change this each time there is some incompatible
* file format change!!!!
*/
-#define BDB_VERSION 11 /* file version number */
+#define BDB_VERSION 11 /* file version number */
struct s_control {
- int bdb_version; /* Version number */
- uint32_t JobId; /* next Job Id */
- uint32_t PoolId; /* next Pool Id */
- uint32_t MediaId; /* next Media Id */
- uint32_t JobMediaId; /* next JobMedia Id */
- uint32_t ClientId; /* next Client Id */
- uint32_t FileSetId; /* nest FileSet Id */
- time_t time; /* time file written */
+ int bdb_version; /* Version number */
+ uint32_t JobId; /* next Job Id */
+ uint32_t PoolId; /* next Pool Id */
+ uint32_t MediaId; /* next Media Id */
+ uint32_t JobMediaId; /* next JobMedia Id */
+ uint32_t ClientId; /* next Client Id */
+ uint32_t FileSetId; /* nest FileSet Id */
+ time_t time; /* time file written */
};
* Bacula internal DB
*/
typedef struct s_db {
- BQUEUE bq; /* queue control */
-/* pthread_mutex_t mutex; */ /* single thread lock */
- brwlock_t lock; /* transaction lock */
- int ref_count; /* number of times opened */
- struct s_control control; /* control file structure */
- int cfd; /* control file device */
- FILE *jobfd; /* Jobs records file descriptor */
- FILE *poolfd; /* Pool records fd */
- FILE *mediafd; /* Media records fd */
- FILE *jobmediafd; /* JobMedia records fd */
- FILE *clientfd; /* Client records fd */
- FILE *filesetfd; /* FileSet records fd */
- char *db_name; /* name of database */
- POOLMEM *errmsg; /* nicely edited error message */
- POOLMEM *cmd; /* Command string */
+ BQUEUE bq; /* queue control */
+/* pthread_mutex_t mutex; */ /* single thread lock */
+ brwlock_t lock; /* transaction lock */
+ int ref_count; /* number of times opened */
+ struct s_control control; /* control file structure */
+ int cfd; /* control file device */
+ FILE *jobfd; /* Jobs records file descriptor */
+ FILE *poolfd; /* Pool records fd */
+ FILE *mediafd; /* Media records fd */
+ FILE *jobmediafd; /* JobMedia records fd */
+ FILE *clientfd; /* Client records fd */
+ FILE *filesetfd; /* FileSet records fd */
+ char *db_name; /* name of database */
+ POOLMEM *errmsg; /* nicely edited error message */
+ POOLMEM *cmd; /* Command string */
POOLMEM *cached_path;
uint32_t cached_path_id;
- void *jcr; /* JCR or NULL */
+ void *jcr; /* JCR or NULL */
} B_DB;
#endif /* HAVE_MYSQL */
#define DELETE_DB(db, cmd) DeleteDB(__FILE__, __LINE__, db, cmd)
-#else /* not __SQL_C */
+#else /* not __SQL_C */
/* This is a "dummy" definition for use outside of sql.c
*/
-typedef struct s_db {
- int dummy; /* for SunOS compiler */
+typedef struct s_db {
+ int dummy; /* for SunOS compiler */
} B_DB;
#endif /* __SQL_C */
/* ***FIXME*** FileId_t should be uint64_t */
typedef uint32_t FileId_t;
-typedef uint32_t DBId_t; /* general DB id type */
+typedef uint32_t DBId_t; /* general DB id type */
typedef uint32_t JobId_t;
/* Job record */
typedef struct {
JobId_t JobId;
- char Job[MAX_NAME_LENGTH]; /* Job unique name */
- char Name[MAX_NAME_LENGTH]; /* Job base name */
- int Type; /* actually char(1) */
- int Level; /* actually char(1) */
- int JobStatus; /* actually char(1) */
- uint32_t ClientId; /* Id of client */
- uint32_t PoolId; /* Id of pool */
- uint32_t FileSetId; /* Id of FileSet */
- time_t SchedTime; /* Time job scheduled */
- time_t StartTime; /* Job start time */
- time_t EndTime; /* Job termination time */
- utime_t JobTDate; /* Backup time/date in seconds */
+ char Job[MAX_NAME_LENGTH]; /* Job unique name */
+ char Name[MAX_NAME_LENGTH]; /* Job base name */
+ int Type; /* actually char(1) */
+ int Level; /* actually char(1) */
+ int JobStatus; /* actually char(1) */
+ uint32_t ClientId; /* Id of client */
+ uint32_t PoolId; /* Id of pool */
+ uint32_t FileSetId; /* Id of FileSet */
+ time_t SchedTime; /* Time job scheduled */
+ time_t StartTime; /* Job start time */
+ time_t EndTime; /* Job termination time */
+ utime_t JobTDate; /* Backup time/date in seconds */
uint32_t VolSessionId;
uint32_t VolSessionTime;
uint32_t JobFiles;
/* Note, FirstIndex, LastIndex, Start/End File and Block
* are only used in the JobMedia record.
*/
- uint32_t FirstIndex; /* First index this Volume */
- uint32_t LastIndex; /* Last index this Volume */
+ uint32_t FirstIndex; /* First index this Volume */
+ uint32_t LastIndex; /* Last index this Volume */
uint32_t StartFile;
uint32_t EndFile;
uint32_t StartBlock;
*/
/* JobMedia record */
typedef struct {
- uint32_t JobMediaId; /* record id */
- JobId_t JobId; /* JobId */
- uint32_t MediaId; /* MediaId */
- uint32_t FirstIndex; /* First index this Volume */
- uint32_t LastIndex; /* Last index this Volume */
- uint32_t StartFile; /* File for start of data */
- uint32_t EndFile; /* End file on Volume */
- uint32_t StartBlock; /* start block on tape */
- uint32_t EndBlock; /* last block */
+ uint32_t JobMediaId; /* record id */
+ JobId_t JobId; /* JobId */
+ uint32_t MediaId; /* MediaId */
+ uint32_t FirstIndex; /* First index this Volume */
+ uint32_t LastIndex; /* Last index this Volume */
+ uint32_t StartFile; /* File for start of data */
+ uint32_t EndFile; /* End file on Volume */
+ uint32_t StartBlock; /* start block on tape */
+ uint32_t EndBlock; /* last block */
} JOBMEDIA_DBR;
/* Volume Parameter structure */
typedef struct {
char VolumeName[MAX_NAME_LENGTH]; /* Volume name */
- uint32_t FirstIndex; /* First index this Volume */
- uint32_t LastIndex; /* Last index this Volume */
- uint32_t StartFile; /* File for start of data */
- uint32_t EndFile; /* End file on Volume */
- uint32_t StartBlock; /* start block on tape */
- uint32_t EndBlock; /* last block */
+ uint32_t FirstIndex; /* First index this Volume */
+ uint32_t LastIndex; /* Last index this Volume */
+ uint32_t StartFile; /* File for start of data */
+ uint32_t EndFile; /* End file on Volume */
+ uint32_t StartBlock; /* start block on tape */
+ uint32_t EndBlock; /* last block */
} VOL_PARAMS;
* records (e.g. pathname, filename, fileattributes).
*/
typedef struct {
- char *fname; /* full path & filename */
- char *link; /* link if any */
- char *attr; /* attributes statp */
+ char *fname; /* full path & filename */
+ char *link; /* link if any */
+ char *attr; /* attributes statp */
uint32_t FileIndex;
uint32_t Stream;
JobId_t JobId;
/* Pool record -- same format as database */
typedef struct {
uint32_t PoolId;
- char Name[MAX_NAME_LENGTH]; /* Pool name */
- uint32_t NumVols; /* total number of volumes */
- uint32_t MaxVols; /* max allowed volumes */
- int UseOnce; /* set to use once only */
- int UseCatalog; /* set to use catalog */
- int AcceptAnyVolume; /* set to accept any volume sequence */
- int AutoPrune; /* set to prune automatically */
- int Recycle; /* default Vol recycle flag */
- utime_t VolRetention; /* retention period in seconds */
- utime_t VolUseDuration; /* time in secs volume can be used */
- uint32_t MaxVolJobs; /* Max Jobs on Volume */
- uint32_t MaxVolFiles; /* Max files on Volume */
- uint64_t MaxVolBytes; /* Max bytes on Volume */
- char PoolType[MAX_NAME_LENGTH];
+ char Name[MAX_NAME_LENGTH]; /* Pool name */
+ uint32_t NumVols; /* total number of volumes */
+ uint32_t MaxVols; /* max allowed volumes */
+ int UseOnce; /* set to use once only */
+ int UseCatalog; /* set to use catalog */
+ int AcceptAnyVolume; /* set to accept any volume sequence */
+ int AutoPrune; /* set to prune automatically */
+ int Recycle; /* default Vol recycle flag */
+ utime_t VolRetention; /* retention period in seconds */
+ utime_t VolUseDuration; /* time in secs volume can be used */
+ uint32_t MaxVolJobs; /* Max Jobs on Volume */
+ uint32_t MaxVolFiles; /* Max files on Volume */
+ uint64_t MaxVolBytes; /* Max bytes on Volume */
+ char PoolType[MAX_NAME_LENGTH];
char LabelFormat[MAX_NAME_LENGTH];
/* Extra stuff not in DB */
faddr_t rec_addr;
/* Media record -- same as the database */
typedef struct {
- uint32_t MediaId; /* Unique volume id */
+ uint32_t MediaId; /* Unique volume id */
char VolumeName[MAX_NAME_LENGTH]; /* Volume name */
char MediaType[MAX_NAME_LENGTH]; /* Media type */
- uint32_t PoolId; /* Pool id */
- time_t FirstWritten; /* Time Volume first written */
- time_t LastWritten; /* Time Volume last written */
- time_t LabelDate; /* Date/Time Volume labeled */
- uint32_t VolJobs; /* number of jobs on this medium */
- uint32_t VolFiles; /* Number of files */
- uint32_t VolBlocks; /* Number of blocks */
- uint32_t VolMounts; /* Number of times mounted */
- uint32_t VolErrors; /* Number of read/write errors */
- uint32_t VolWrites; /* Number of writes */
- uint32_t VolReads; /* Number of reads */
- uint64_t VolBytes; /* Number of bytes written */
- uint64_t MaxVolBytes; /* Max bytes to write to Volume */
- uint64_t VolCapacityBytes; /* capacity estimate */
- utime_t VolRetention; /* Volume retention in seconds */
- utime_t VolUseDuration; /* time in secs volume can be used */
- uint32_t MaxVolJobs; /* Max Jobs on Volume */
- uint32_t MaxVolFiles; /* Max files on Volume */
- int Recycle; /* recycle yes/no */
- int32_t Slot; /* slot in changer */
- char VolStatus[20]; /* Volume status */
+ uint32_t PoolId; /* Pool id */
+ time_t FirstWritten; /* Time Volume first written */
+ time_t LastWritten; /* Time Volume last written */
+ time_t LabelDate; /* Date/Time Volume labeled */
+ uint32_t VolJobs; /* number of jobs on this medium */
+ uint32_t VolFiles; /* Number of files */
+ uint32_t VolBlocks; /* Number of blocks */
+ uint32_t VolMounts; /* Number of times mounted */
+ uint32_t VolErrors; /* Number of read/write errors */
+ uint32_t VolWrites; /* Number of writes */
+ uint32_t VolReads; /* Number of reads */
+ uint64_t VolBytes; /* Number of bytes written */
+ uint64_t MaxVolBytes; /* Max bytes to write to Volume */
+ uint64_t VolCapacityBytes; /* capacity estimate */
+ utime_t VolRetention; /* Volume retention in seconds */
+ utime_t VolUseDuration; /* time in secs volume can be used */
+ uint32_t MaxVolJobs; /* Max Jobs on Volume */
+ uint32_t MaxVolFiles; /* Max files on Volume */
+ int Recycle; /* recycle yes/no */
+ int32_t Slot; /* slot in changer */
+ char VolStatus[20]; /* Volume status */
/* Extra stuff not in DB */
- faddr_t rec_addr; /* found record address */
+ faddr_t rec_addr; /* found record address */
/* Since the database returns times as strings, this is how we pass
- * them back.
+ * them back.
*/
char cFirstWritten[MAX_TIME_LENGTH]; /* FirstWritten returned from DB */
char cLastWritten[MAX_TIME_LENGTH]; /* LastWritten returned from DB */
/* Client record -- same as the database */
typedef struct {
- uint32_t ClientId; /* Unique Client id */
+ uint32_t ClientId; /* Unique Client id */
int AutoPrune;
utime_t FileRetention;
utime_t JobRetention;
- char Name[MAX_NAME_LENGTH]; /* Client name */
- char Uname[256]; /* Uname for client */
+ char Name[MAX_NAME_LENGTH]; /* Client name */
+ char Uname[256]; /* Uname for client */
} CLIENT_DBR;
/* FileSet record -- same as the database */
typedef struct {
- uint32_t FileSetId; /* Unique FileSet id */
+ uint32_t FileSetId; /* Unique FileSet id */
char FileSet[MAX_NAME_LENGTH]; /* FileSet name */
- char MD5[50]; /* MD5 signature of include/exclude */
+ char MD5[50]; /* MD5 signature of include/exclude */
} FILESET_DBR;
*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
mdb->cached_path = get_pool_memory(PM_FNAME);
mdb->cached_path_id = 0;
mdb->ref_count = 1;
+ mdb->fname = get_pool_memory(PM_FNAME);
+ mdb->path = get_pool_memory(PM_FNAME);
+ mdb->esc_name = get_pool_memory(PM_FNAME);
qinsert(&db_list, &mdb->bq); /* put db in list */
mdb->jcr = jcr;
V(mutex);
free_pool_memory(mdb->errmsg);
free_pool_memory(mdb->cmd);
free_pool_memory(mdb->cached_path);
+ free_pool_memory(mdb->fname);
+ free_pool_memory(mdb->path);
+ free_pool_memory(mdb->esc_name);
if (mdb->db_name) {
free(mdb->db_name);
}
*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
#endif
}
+void split_path_and_filename(B_DB *mdb, char *fname)
+{
+ char *p, *f;
+
+ /* Find path without the filename.
+ * I.e. everything after the last / is a "filename".
+ * OK, maybe it is a directory name, but we treat it like
+ * a filename. If we don't find a / then the whole name
+ * must be a path name (e.g. c:).
+ */
+ for (p=f=fname; *p; p++) {
+ if (*p == '/') {
+ f = p; /* set pos of last slash */
+ }
+ }
+ if (*f == '/') { /* did we find a slash? */
+ f++; /* yes, point to filename */
+ } else { /* no, whole thing must be path name */
+ f = p;
+ }
+
+ /* If filename doesn't exist (i.e. root directory), we
+ * simply create a blank name consisting of a single
+ * space. This makes handling zero length filenames
+ * easier.
+ */
+ mdb->fnl = p - f;
+ if (mdb->fnl > 0) {
+ mdb->fname = check_pool_memory_size(mdb->fname, mdb->fnl+1);
+ strncpy(mdb->fname, f, mdb->fnl); /* copy filename */
+ mdb->fname[mdb->fnl] = 0;
+ } else {
+ mdb->fname[0] = ' '; /* blank filename */
+ mdb->fname[1] = 0;
+ mdb->fnl = 1;
+ }
+
+ mdb->pnl = f - fname;
+ if (mdb->pnl > 0) {
+ mdb->path = check_pool_memory_size(mdb->path, mdb->pnl+1);
+ strncpy(mdb->path, fname, mdb->pnl);
+ mdb->path[mdb->pnl] = 0;
+ } else {
+ Mmsg1(&mdb->errmsg, _("Path length is zero. File=%s\n"), fname);
+ Jmsg(mdb->jcr, M_ERROR, 0, "%s", mdb->errmsg);
+ mdb->path[0] = ' ';
+ mdb->path[1] = 0;
+ mdb->pnl = 1;
+ }
+
+ Dmsg2(100, "sllit path=%s file=%s\n", mdb->path, mdb->fname);
+}
#endif /* HAVE_MYSQL | HAVE_SQLITE */
*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
/* Forward referenced subroutines */
static int db_create_file_record(B_DB *mdb, ATTR_DBR *ar);
-static int db_create_filename_record(B_DB *mdb, ATTR_DBR *ar, char *fname);
-static int db_create_path_record(B_DB *mdb, ATTR_DBR *ar, char *path);
+static int db_create_filename_record(B_DB *mdb, ATTR_DBR *ar);
+static int db_create_path_record(B_DB *mdb, ATTR_DBR *ar);
/* Imported subroutines */
extern void print_result(B_DB *mdb);
extern int QueryDB(char *file, int line, B_DB *db, char *select_cmd);
extern int InsertDB(char *file, int line, B_DB *db, char *select_cmd);
+extern void split_path_and_filename(B_DB *mdb, char *fname);
/* Create a new record for the Job
*/
int db_create_file_attributes_record(B_DB *mdb, ATTR_DBR *ar)
{
- int fnl, pnl;
- char *l, *p;
- /* ****FIXME***** malloc these */
- char file[MAXSTRING];
- char spath[MAXSTRING];
- char buf[MAXSTRING];
Dmsg1(100, "Fname=%s\n", ar->fname);
Dmsg0(50, "put_file_into_catalog\n");
- /* For the moment, we only handle Unix attributes. Note, we are
- * also getting any MD5 signature that was computed.
+ /*
+ * Make sure we have an acceptable attributes record.
*/
if (!(ar->Stream == STREAM_UNIX_ATTRIBUTES || ar->Stream == STREAM_WIN32_ATTRIBUTES)) {
Mmsg0(&mdb->errmsg, _("Attempt to put non-attributes into catalog\n"));
return 0;
}
- /* Find path without the filename.
- * I.e. everything after the last / is a "filename".
- * OK, maybe it is a directory name, but we treat it like
- * a filename. If we don't find a / then the whole name
- * must be a path name (e.g. c:).
- */
- for (p=l=ar->fname; *p; p++) {
- if (*p == '/') {
- l = p; /* set pos of last slash */
- }
- }
- if (*l == '/') { /* did we find a slash? */
- l++; /* yes, point to filename */
- } else { /* no, whole thing must be path name */
- l = p;
- }
-
- /* If filename doesn't exist (i.e. root directory), we
- * simply create a blank name consisting of a single
- * space. This makes handling zero length filenames
- * easier.
- */
- fnl = p - l;
- if (fnl > 255) {
- Jmsg(mdb->jcr, M_WARNING, 0, _("Filename truncated to 255 chars: %s\n"), l);
- fnl = 255;
- }
- if (fnl > 0) {
- strncpy(file, l, fnl); /* copy filename */
- file[fnl] = 0;
- } else {
- file[0] = ' '; /* blank filename */
- file[1] = 0;
- fnl = 1;
- }
-
- pnl = l - ar->fname;
- if (pnl > 255) {
- Jmsg(mdb->jcr, M_WARNING, 0, _("Path name truncated to 255 chars: %s\n"), ar->fname);
- pnl = 255;
- }
- strncpy(spath, ar->fname, pnl);
- spath[pnl] = 0;
-
- if (pnl == 0) {
- Mmsg1(&mdb->errmsg, _("Path length is zero. File=%s\n"), ar->fname);
- Jmsg(mdb->jcr, M_ERROR, 0, "%s", mdb->errmsg);
- spath[0] = ' ';
- spath[1] = 0;
- pnl = 1;
- }
-
- Dmsg1(100, "spath=%s\n", spath);
- Dmsg1(100, "file=%s\n", file);
+ db_lock(mdb);
- db_escape_string(buf, file, fnl);
+ split_path_and_filename(mdb, ar->fname);
- if (!db_create_filename_record(mdb, ar, buf)) {
+ if (!db_create_filename_record(mdb, ar)) {
+ db_unlock(mdb);
return 0;
}
- Dmsg1(100, "db_create_filename_record: %s\n", buf);
+ Dmsg1(100, "db_create_filename_record: %s\n", mdb->esc_name);
- db_escape_string(buf, spath, pnl);
- if (!db_create_path_record(mdb, ar, buf)) {
+ if (!db_create_path_record(mdb, ar)) {
+ db_unlock(mdb);
return 0;
}
- Dmsg1(100, "db_create_path_record\n", buf);
+ Dmsg1(100, "db_create_path_record\n", mdb->esc_name);
+ /* Now create master File record */
if (!db_create_file_record(mdb, ar)) {
+ db_unlock(mdb);
return 0;
}
Dmsg0(50, "db_create_file_record\n");
- Dmsg3(100, "Path=%s File=%s FilenameId=%d\n", spath, file, ar->FilenameId);
+ Dmsg3(100, "Path=%s File=%s FilenameId=%d\n", mdb->path, mdb->fname, ar->FilenameId);
+ db_unlock(mdb);
return 1;
}
+/*
+ * This is the master File entry containing the attributes.
+ * The filename and path records have already been created.
+ */
static int db_create_file_record(B_DB *mdb, ATTR_DBR *ar)
{
int stat;
ASSERT(ar->PathId);
ASSERT(ar->FilenameId);
- db_lock(mdb);
/* Must create it */
Mmsg(&mdb->cmd,
"INSERT INTO File (FileIndex, JobId, PathId, FilenameId, \
ar->FileId = sql_insert_id(mdb);
stat = 1;
}
- db_unlock(mdb);
return stat;
}
/* Create a Unique record for the Path -- no duplicates */
-static int db_create_path_record(B_DB *mdb, ATTR_DBR *ar, char *path)
+static int db_create_path_record(B_DB *mdb, ATTR_DBR *ar)
{
SQL_ROW row;
int stat;
- if (*path == 0) {
- Mmsg0(&mdb->errmsg, _("Null path given to db_create_path_record\n"));
- Jmsg(mdb->jcr, M_ERROR, 0, "%s", mdb->errmsg);
- ar->PathId = 0;
- ASSERT(ar->PathId);
- return 0;
- }
-
- db_lock(mdb);
+ mdb->esc_name = check_pool_memory_size(mdb->esc_name, mdb->pnl+1);
+ db_escape_string(mdb->esc_name, mdb->path, mdb->pnl);
- if (mdb->cached_path_id != 0 && strcmp(mdb->cached_path, path) == 0) {
+ if (mdb->cached_path_id != 0 && mdb->cached_path_len == mdb->pnl &&
+ strcmp(mdb->cached_path, mdb->path) == 0) {
ar->PathId = mdb->cached_path_id;
ASSERT(ar->PathId);
- db_unlock(mdb);
return 1;
}
- Mmsg(&mdb->cmd, "SELECT PathId FROM Path WHERE Path='%s'", path);
+ Mmsg(&mdb->cmd, "SELECT PathId FROM Path WHERE Path='%s'", mdb->path);
if (QUERY_DB(mdb, mdb->cmd)) {
if (mdb->num_rows > 1) {
char ed1[30];
Mmsg2(&mdb->errmsg, _("More than one Path!: %s for Path=%s\n"),
- edit_uint64(mdb->num_rows, ed1), path);
+ edit_uint64(mdb->num_rows, ed1), mdb->path);
Jmsg(mdb->jcr, M_ERROR, 0, "%s", mdb->errmsg);
}
if (mdb->num_rows >= 1) {
if ((row = sql_fetch_row(mdb)) == NULL) {
- db_unlock(mdb);
Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
Jmsg(mdb->jcr, M_ERROR, 0, "%s", mdb->errmsg);
sql_free_result(mdb);
/* Cache path */
if (ar->PathId != mdb->cached_path_id) {
mdb->cached_path_id = ar->PathId;
- mdb->cached_path = check_pool_memory_size(mdb->cached_path,
- strlen(path)+1);
- strcpy(mdb->cached_path, path);
+ mdb->cached_path_len = mdb->pnl;
+ pm_strcpy(&mdb->cached_path, mdb->path);
}
ASSERT(ar->PathId);
- db_unlock(mdb);
return 1;
}
sql_free_result(mdb);
}
- Mmsg(&mdb->cmd, "INSERT INTO Path (Path) VALUES ('%s')", path);
+ Mmsg(&mdb->cmd, "INSERT INTO Path (Path) VALUES ('%s')", mdb->path);
if (!INSERT_DB(mdb, mdb->cmd)) {
Mmsg2(&mdb->errmsg, _("Create db Path record %s failed. ERR=%s\n"),
/* Cache path */
if (ar->PathId != mdb->cached_path_id) {
mdb->cached_path_id = ar->PathId;
- mdb->cached_path = check_pool_memory_size(mdb->cached_path,
- strlen(path)+1);
- strcpy(mdb->cached_path, path);
+ mdb->cached_path_len = mdb->pnl;
+ pm_strcpy(&mdb->cached_path, mdb->path);
}
ASSERT(ar->PathId);
- db_unlock(mdb);
return stat;
}
/* Create a Unique record for the filename -- no duplicates */
-static int db_create_filename_record(B_DB *mdb, ATTR_DBR *ar, char *fname)
+static int db_create_filename_record(B_DB *mdb, ATTR_DBR *ar)
{
SQL_ROW row;
- db_lock(mdb);
- Mmsg(&mdb->cmd, "SELECT FilenameId FROM Filename WHERE Name='%s'", fname);
+
+ mdb->esc_name = check_pool_memory_size(mdb->esc_name, mdb->fnl+1);
+ db_escape_string(mdb->esc_name, mdb->fname, mdb->fnl);
+
+ Mmsg(&mdb->cmd, "SELECT FilenameId FROM Filename WHERE Name='%s'", mdb->esc_name);
if (QUERY_DB(mdb, mdb->cmd)) {
mdb->num_rows = sql_num_rows(mdb);
if (mdb->num_rows > 1) {
Mmsg2(&mdb->errmsg, _("More than one Filename!: %d File=%s\n"),
- (int)(mdb->num_rows), fname);
+ (int)(mdb->num_rows), mdb->esc_name);
Jmsg(mdb->jcr, M_ERROR, 0, "%s", mdb->errmsg);
}
if (mdb->num_rows >= 1) {
if ((row = sql_fetch_row(mdb)) == NULL) {
Mmsg2(&mdb->errmsg, _("error fetching row for file=%s: ERR=%s\n"),
- fname, sql_strerror(mdb));
+ mdb->fname, sql_strerror(mdb));
Jmsg(mdb->jcr, M_ERROR, 0, "%s", mdb->errmsg);
ar->FilenameId = 0;
} else {
ar->FilenameId = atoi(row[0]);
}
sql_free_result(mdb);
- db_unlock(mdb);
return ar->FilenameId > 0;
}
sql_free_result(mdb);
}
Mmsg(&mdb->cmd, "INSERT INTO Filename (Name) \
-VALUES ('%s')", fname);
+VALUES ('%s')", mdb->fname);
if (!INSERT_DB(mdb, mdb->cmd)) {
Mmsg2(&mdb->errmsg, _("Create db Filename record %s failed. ERR=%s\n"),
ar->FilenameId = sql_insert_id(mdb);
}
- db_unlock(mdb);
return ar->FilenameId > 0;
}
*/
/*
- Copyright (C) 2002 Kern Sibbald and John Walker
+ Copyright (C) 2002-2003 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
mdb->cached_path = get_pool_memory(PM_FNAME);
mdb->cached_path_id = 0;
mdb->ref_count = 1;
+ mdb->fname = get_pool_memory(PM_FNAME);
+ mdb->path = get_pool_memory(PM_FNAME);
+ mdb->esc_name = get_pool_memory(PM_FNAME);
qinsert(&db_list, &mdb->bq); /* put db in list */
mdb->jcr = jcr;
V(mutex);
free_pool_memory(mdb->errmsg);
free_pool_memory(mdb->cmd);
free_pool_memory(mdb->cached_path);
+ free_pool_memory(mdb->fname);
+ free_pool_memory(mdb->path);
+ free_pool_memory(mdb->esc_name);
if (mdb->db_name) {
free(mdb->db_name);
}
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
* Version $Id$
*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
Dmsg2(111, "dird<filed: stream=%d %s\n", stream, jcr->fname);
Dmsg1(120, "dird<filed: attr=%s\n", attr);
- /* ***FIXME*** fix link field */
if (!db_create_file_attributes_record(jcr->db, &ar)) {
Jmsg1(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
jcr->JobStatus = JS_Error;
*
*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
Dmsg0(110, "start find files\n");
/* Subroutine save_file() is called for each file */
- /* ***FIXME**** add FSM code */
if (!find_files(jcr->ff, save_file, (void *)jcr)) {
stat = 0; /* error */
}
case FT_SPEC:
Dmsg1(130, "FT_SPEC saving: %s\n", ff_pkt->fname);
break;
+ case FT_RAW:
+ Dmsg1(130, "FT_RAW saving: %s\n", ff_pkt->fname);
+ break;
case FT_NOACCESS:
Jmsg(jcr, M_NOTSAVED, -1, _(" Could not access %s: ERR=%s\n"), ff_pkt->fname,
strerror(ff_pkt->ff_errno));
return 1;
}
- if (ff_pkt->type != FT_LNKSAVED && S_ISREG(ff_pkt->statp.st_mode) &&
- ff_pkt->statp.st_size > 0) {
+ if (ff_pkt->type != FT_LNKSAVED && (S_ISREG(ff_pkt->statp.st_mode) &&
+ ff_pkt->statp.st_size > 0) || ff_pkt->type == FT_RAW) {
if ((ff_pkt->fid = open(ff_pkt->fname, O_RDONLY | O_BINARY)) < 0) {
ff_pkt->ff_errno = errno;
Jmsg(jcr, M_NOTSAVED, -1, _(" Cannot open %s: ERR=%s.\n"), ff_pkt->fname, strerror(ff_pkt->ff_errno));
*
*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
/*
* Called here by find() for each file included.
*
- * *****FIXME***** add FSMs File System Modules
- *
*/
static int tally_file(FF_PKT *ff_pkt, void *ijcr)
{
case FT_LNK:
case FT_DIR:
case FT_SPEC:
+ case FT_RAW:
break;
case FT_NOACCESS:
case FT_NOFOLLOW:
*
*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
/*
* Called here by find() for each file.
-
- *****FIXME***** add FSMs File System Modules
-
*
* Find the file, compute the MD5 and send it back to the Director
*/
case FT_SPEC:
Dmsg1(30, "FT_SPEC saving: %s\n", ff_pkt->fname);
break;
+ case FT_RAW:
+ Dmsg1(30, "FT_RAW saving: %s\n", ff_pkt->fname);
+ break;
case FT_NOACCESS:
Jmsg(jcr, M_NOTSAVED, -1, _(" Could not access %s: ERR=%s\n"), ff_pkt->fname, strerror(ff_pkt->ff_errno));
return 1;
}
- if (ff_pkt->type != FT_LNKSAVED && S_ISREG(ff_pkt->statp.st_mode) &&
- ff_pkt->statp.st_size > 0) {
+ if (ff_pkt->type != FT_LNKSAVED && (S_ISREG(ff_pkt->statp.st_mode) &&
+ ff_pkt->statp.st_size > 0) || ff_pkt->type == FT_RAW) {
if ((fid = open(ff_pkt->fname, O_RDONLY | O_BINARY)) < 0) {
ff_pkt->ff_errno = errno;
Jmsg(jcr, M_NOTSAVED, -1, _(" Cannot open %s: ERR=%s.\n"), ff_pkt->fname, strerror(ff_pkt->ff_errno));
*
*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
fnl = p - f;
if (fnl == 0) {
+ /* The filename length must not be zero here because we
+ * are dealing with a file (i.e. FT_REGE or FT_REG).
+ */
Jmsg1(jcr, M_ERROR, 0, _("Zero length filename: %s\n"), fname);
return CF_ERROR;
}
pnl = f - ofile - 1;
- if (pnl <= 0) {
- Jmsg1(jcr, M_ERROR, 0, _("Zero length path: %s\n"), fname);
- return CF_ERROR;
- }
- savechr = ofile[pnl];
- ofile[pnl] = 0; /* terminate path */
- Dmsg1(50, "Make path %s\n", ofile);
/*
- * If we need to make the directory, ensure that it is with
- * execute bit set (i.e. parent_mode), and preserve what already
- * exists. Normally, this should do nothing.
+ * If path length is <= 0 we are making a file in the root
+ * directory. Assume that the directory already exists.
*/
- stat = !make_path(jcr, ofile, parent_mode, parent_mode, uid, gid, 1, NULL);
- if (stat == 0) {
- Dmsg1(0, "Could not make path. %s\n", ofile);
- return CF_ERROR;
- }
+ if (pnl > 0) {
+ savechr = ofile[pnl];
+ ofile[pnl] = 0; /* terminate path */
+
+ Dmsg1(50, "Make path %s\n", ofile);
+ /*
+ * If we need to make the directory, ensure that it is with
+ * execute bit set (i.e. parent_mode), and preserve what already
+ * exists. Normally, this should do nothing.
+ */
+ stat = !make_path(jcr, ofile, parent_mode, parent_mode, uid, gid, 1, NULL);
+ if (stat == 0) {
+ Dmsg1(0, "Could not make path. %s\n", ofile);
+ return CF_ERROR;
+ }
- ofile[pnl] = savechr; /* restore full name */
+ ofile[pnl] = savechr; /* restore full name */
+ }
+
Dmsg1(100, "Create file %s\n", ofile);
mode = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY;
if (IS_CTG(statp->st_mode)) {
return CF_ERROR;
}
return CF_CREATED;
+ case FT_RAW:
case FT_SPEC:
if (S_ISFIFO(statp->st_mode)) {
Dmsg1(200, "Restore fifo: %s\n", ofile);
- if (mkfifo(ofile, statp->st_mode) != 0) {
+ if (mkfifo(ofile, statp->st_mode) != 0 && errno != EEXIST) {
Jmsg2(jcr, M_ERROR, 0, _("Cannot make fifo %s: ERR=%s\n"), ofile, strerror(errno));
return CF_ERROR;
}
} else {
Dmsg1(200, "Restore node: %s\n", ofile);
- if (mknod(ofile, statp->st_mode, statp->st_rdev) != 0) {
+ if (mknod(ofile, statp->st_mode, statp->st_rdev) != 0 && errno != EEXIST) {
Jmsg2(jcr, M_ERROR, 0, _("Cannot make node %s: ERR=%s\n"), ofile, strerror(errno));
return CF_ERROR;
}
}
+ if (type == FT_RAW) {
+ Dmsg1(200, "FT_RAW %s\n", ofile);
+ mode = O_WRONLY | O_BINARY;
+ if ((*ofd = open(ofile, mode)) < 0) {
+ Jmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"), ofile, strerror(errno));
+ return CF_ERROR;
+ }
+ return CF_EXTRACT;
+ }
Dmsg1(200, "FT_SPEC %s\n", ofile);
return CF_CREATED;
* Kern E. Sibbald, MM
*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
term_find_files(FF_PKT *ff)
{
term_include_exclude_files(ff);
- term_find_one(ff);
free_pool_memory(ff->sys_fname);
+ term_find_one(ff);
free(ff);
return;
}
* Kern Sibbald MIM
*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
#define FT_NORECURSE 13 /* No recursion into directory */
#define FT_NOFSCHG 14 /* Different file system, prohibited */
#define FT_NOOPEN 15 /* Could not open directory */
+#define FT_RAW 16 /* Raw block device */
/* Options saved in "flag" of ff packet */
#define FO_MD5 0x01 /* Do MD5 checksum */
return rtn_stat;
} /* end check for directory */
- /* The only remaining types are special (character, ...) files */
- ff_pkt->type = FT_SPEC;
+ /*
+ * If it is explicitly mentioned (i.e. top_level) and is
+ * a block device, we do a raw backup of it.
+ */
+ if (top_level && S_ISBLK(ff_pkt->statp.st_mode)) {
+ ff_pkt->type = FT_RAW; /* raw partition */
+ } else {
+ /* The only remaining types are special (character, ...) files */
+ ff_pkt->type = FT_SPEC;
+ }
return handle_file(ff_pkt, pkt);
}
/* */
#define VERSION "1.28"
#define VSTRING "1"
-#define DATE "30 December 2002"
-#define LSMDATE "30Dec02"
+#define DATE "2 January 2003"
+#define LSMDATE "02Jan03"
/* Debug flags */
#define DEBUG 1