From 72028bbcb832a059405074c480370224b95ae5c1 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Wed, 1 Jan 2003 22:37:49 +0000 Subject: [PATCH] Add Raw file save/restore git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@258 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/kernstodo | 5 +- bacula/src/c | 2 +- bacula/src/cats/bdb_get.c | 6 +- bacula/src/cats/cats.h | 301 ++++++++++++++++--------------- bacula/src/cats/mysql.c | 8 +- bacula/src/cats/sql.c | 54 +++++- bacula/src/cats/sql_create.c | 149 +++++---------- bacula/src/cats/sqlite.c | 8 +- bacula/src/cl | 2 +- bacula/src/dird/fd_cmds.c | 3 +- bacula/src/filed/backup.c | 10 +- bacula/src/filed/estimate.c | 5 +- bacula/src/filed/verify.c | 12 +- bacula/src/findlib/create_file.c | 55 ++++-- bacula/src/findlib/find.c | 4 +- bacula/src/findlib/find.h | 3 +- bacula/src/findlib/find_one.c | 12 +- bacula/src/version.h | 4 +- 18 files changed, 340 insertions(+), 303 deletions(-) diff --git a/bacula/kernstodo b/bacula/kernstodo index 18262346fb..0675f3cbbf 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -1,5 +1,5 @@ Kern's ToDo List - 29 December 2002 + 01 January 2003 Documentation to do: (a little bit at a time) - Document running a test version. @@ -15,8 +15,11 @@ For 1.28 release: - 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 diff --git a/bacula/src/c b/bacula/src/c index de15677c29..d57a7ad9ed 100644 --- a/bacula/src/c +++ b/bacula/src/c @@ -1,5 +1,5 @@ /* - 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 diff --git a/bacula/src/cats/bdb_get.c b/bacula/src/cats/bdb_get.c index 60dc10c5c0..dbd1953420 100644 --- a/bacula/src/cats/bdb_get.c +++ b/bacula/src/cats/bdb_get.c @@ -17,7 +17,7 @@ */ /* - 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 @@ -500,8 +500,4 @@ int db_get_job_volume_parameters(B_DB *mdb, uint32_t JobId, VOL_PARAMS **VolPara 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 */ diff --git a/bacula/src/cats/cats.h b/bacula/src/cats/cats.h index 31c6bfe201..4f72737f7b 100644 --- a/bacula/src/cats/cats.h +++ b/bacula/src/cats/cats.h @@ -15,7 +15,7 @@ */ /* - 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 @@ -57,62 +57,68 @@ struct sqlite { 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 @@ -121,7 +127,7 @@ typedef struct s_db { #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** @@ -143,11 +149,11 @@ extern void my_sqlite_free_table(B_DB *mdb); * 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; @@ -156,14 +162,19 @@ typedef struct s_db { 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; @@ -172,7 +183,7 @@ typedef struct s_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) @@ -181,8 +192,8 @@ typedef struct s_db { #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 */ @@ -191,17 +202,17 @@ typedef struct s_db { /* 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 */ }; @@ -209,24 +220,24 @@ struct s_control { * 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 */ @@ -239,19 +250,19 @@ typedef struct s_db { #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; @@ -263,18 +274,18 @@ 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; @@ -285,8 +296,8 @@ typedef struct { /* 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; @@ -304,26 +315,26 @@ typedef struct { */ /* 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; @@ -332,9 +343,9 @@ typedef struct { * 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; @@ -361,20 +372,20 @@ typedef struct { /* 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; @@ -382,34 +393,34 @@ typedef struct { /* 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 */ @@ -418,19 +429,19 @@ typedef struct { /* 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; diff --git a/bacula/src/cats/mysql.c b/bacula/src/cats/mysql.c index b4f139f65b..8e5736f1bf 100644 --- a/bacula/src/cats/mysql.c +++ b/bacula/src/cats/mysql.c @@ -9,7 +9,7 @@ */ /* - 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 @@ -83,6 +83,9 @@ db_init_database(void *jcr, char *db_name, char *db_user, char *db_password) 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); @@ -182,6 +185,9 @@ db_close_database(B_DB *mdb) 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); } diff --git a/bacula/src/cats/sql.c b/bacula/src/cats/sql.c index 29f9cb5e9e..131887723d 100644 --- a/bacula/src/cats/sql.c +++ b/bacula/src/cats/sql.c @@ -10,7 +10,7 @@ */ /* - 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 @@ -254,5 +254,57 @@ void db_end_transaction(B_DB *mdb) #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 */ diff --git a/bacula/src/cats/sql_create.c b/bacula/src/cats/sql_create.c index b4337c93da..be30de82b2 100644 --- a/bacula/src/cats/sql_create.c +++ b/bacula/src/cats/sql_create.c @@ -7,7 +7,7 @@ */ /* - 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 @@ -47,8 +47,8 @@ /* 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 */ @@ -56,6 +56,7 @@ extern void print_dashes(B_DB *mdb); 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 @@ -431,17 +432,11 @@ FileSet='%s' and MD5='%s'", fsr->FileSet, fsr->MD5); */ 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")); @@ -449,84 +444,39 @@ int db_create_file_attributes_record(B_DB *mdb, ATTR_DBR *ar) 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; @@ -535,7 +485,6 @@ static int db_create_file_record(B_DB *mdb, ATTR_DBR *ar) ASSERT(ar->PathId); ASSERT(ar->FilenameId); - db_lock(mdb); /* Must create it */ Mmsg(&mdb->cmd, "INSERT INTO File (FileIndex, JobId, PathId, FilenameId, \ @@ -553,34 +502,26 @@ LStat, MD5) VALUES (%u, %u, %u, %u, '%s', '0')", 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)) { @@ -589,12 +530,11 @@ static int db_create_path_record(B_DB *mdb, ATTR_DBR *ar, char *path) 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); @@ -607,19 +547,17 @@ static int db_create_path_record(B_DB *mdb, ATTR_DBR *ar, char *path) /* 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"), @@ -635,48 +573,48 @@ static int db_create_path_record(B_DB *mdb, ATTR_DBR *ar, char *path) /* 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"), @@ -687,7 +625,6 @@ VALUES ('%s')", fname); ar->FilenameId = sql_insert_id(mdb); } - db_unlock(mdb); return ar->FilenameId > 0; } diff --git a/bacula/src/cats/sqlite.c b/bacula/src/cats/sqlite.c index 1e9781906e..d26c69dea6 100644 --- a/bacula/src/cats/sqlite.c +++ b/bacula/src/cats/sqlite.c @@ -7,7 +7,7 @@ */ /* - 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 @@ -84,6 +84,9 @@ db_init_database(void *jcr, char *db_name, char *db_user, char *db_password) 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); @@ -169,6 +172,9 @@ db_close_database(B_DB *mdb) 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); } diff --git a/bacula/src/cl b/bacula/src/cl index c5431ee6b7..7e525864ce 100644 --- a/bacula/src/cl +++ b/bacula/src/cl @@ -1,5 +1,5 @@ /* - 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 diff --git a/bacula/src/dird/fd_cmds.c b/bacula/src/dird/fd_cmds.c index 8ec2304133..80079a6c2d 100644 --- a/bacula/src/dird/fd_cmds.c +++ b/bacula/src/dird/fd_cmds.c @@ -13,7 +13,7 @@ * 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 @@ -244,7 +244,6 @@ msglen=%d msg=%s\n"), len, fd->msglen, fd->msg); Dmsg2(111, "dirdfname); Dmsg1(120, "dirddb, &ar)) { Jmsg1(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db)); jcr->JobStatus = JS_Error; diff --git a/bacula/src/filed/backup.c b/bacula/src/filed/backup.c index 40c5143a27..bf834a40e2 100644 --- a/bacula/src/filed/backup.c +++ b/bacula/src/filed/backup.c @@ -8,7 +8,7 @@ * */ /* - 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 @@ -67,7 +67,6 @@ int blast_data_to_storage_daemon(JCR *jcr, char *addr) 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 */ } @@ -130,6 +129,9 @@ static int save_file(FF_PKT *ff_pkt, void *ijcr) 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)); @@ -166,8 +168,8 @@ static int save_file(FF_PKT *ff_pkt, void *ijcr) 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)); diff --git a/bacula/src/filed/estimate.c b/bacula/src/filed/estimate.c index c5821b69c2..95275fe9a3 100644 --- a/bacula/src/filed/estimate.c +++ b/bacula/src/filed/estimate.c @@ -8,7 +8,7 @@ * */ /* - 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 @@ -51,8 +51,6 @@ int make_estimate(JCR *jcr) /* * Called here by find() for each file included. * - * *****FIXME***** add FSMs File System Modules - * */ static int tally_file(FF_PKT *ff_pkt, void *ijcr) { @@ -66,6 +64,7 @@ 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: diff --git a/bacula/src/filed/verify.c b/bacula/src/filed/verify.c index 75e8d32bd0..1888bf5be4 100644 --- a/bacula/src/filed/verify.c +++ b/bacula/src/filed/verify.c @@ -7,7 +7,7 @@ * */ /* - 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 @@ -60,9 +60,6 @@ void do_verify(JCR *jcr) /* * 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 */ @@ -102,6 +99,9 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt) 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; @@ -133,8 +133,8 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt) } - 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)); diff --git a/bacula/src/findlib/create_file.c b/bacula/src/findlib/create_file.c index 42b6203336..33e75690d6 100644 --- a/bacula/src/findlib/create_file.c +++ b/bacula/src/findlib/create_file.c @@ -7,7 +7,7 @@ * */ /* - 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 @@ -123,31 +123,38 @@ int create_file(void *jcr, char *fname, char *ofile, char *lname, 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)) { @@ -174,20 +181,30 @@ int create_file(void *jcr, char *fname, char *ofile, char *lname, 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; diff --git a/bacula/src/findlib/find.c b/bacula/src/findlib/find.c index 06f85ae800..afc1097d25 100644 --- a/bacula/src/findlib/find.c +++ b/bacula/src/findlib/find.c @@ -5,7 +5,7 @@ * 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 @@ -133,8 +133,8 @@ void 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; } diff --git a/bacula/src/findlib/find.h b/bacula/src/findlib/find.h index 4c7ebd9658..1206761abc 100755 --- a/bacula/src/findlib/find.h +++ b/bacula/src/findlib/find.h @@ -4,7 +4,7 @@ * 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 @@ -72,6 +72,7 @@ #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 */ diff --git a/bacula/src/findlib/find_one.c b/bacula/src/findlib/find_one.c index b36f798cf6..b13a9da33f 100755 --- a/bacula/src/findlib/find_one.c +++ b/bacula/src/findlib/find_one.c @@ -310,8 +310,16 @@ find_one_file(FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), void *pkt 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); } diff --git a/bacula/src/version.h b/bacula/src/version.h index 393a34af24..ecd466b27b 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #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 -- 2.39.5