From 700cc68f57aa8a1d177d0dd56840be6d42a4d324 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Fri, 1 Nov 2002 13:19:01 +0000 Subject: [PATCH] bacula script + stack overrun -- see kes30Oct02 git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@181 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/kernstodo | 15 +++++----- bacula/src/baconfig.h | 8 ++++++ bacula/src/dird/dird_conf.c | 25 ++++++++--------- bacula/src/dird/restore.c | 2 +- bacula/src/dird/ua_run.c | 2 +- bacula/src/filed/restore.c | 2 +- bacula/src/findlib/create_file.c | 48 ++++++++++++++++++++++---------- bacula/src/findlib/find.h | 1 - bacula/src/findlib/protos.h | 2 +- bacula/src/stored/bextract.c | 2 +- bacula/src/stored/bscan.c | 7 +++-- bacula/src/stored/label.c | 2 ++ bacula/src/version.h | 4 +-- 13 files changed, 75 insertions(+), 45 deletions(-) diff --git a/bacula/kernstodo b/bacula/kernstodo index bd14c95fb6..5713158b83 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -1,5 +1,5 @@ Kern's ToDo List - 30 October 2002 + 1 November 2002 To do: - Document that two Verifys at same time on same client do not work. @@ -9,6 +9,7 @@ To do: - Document buffer size considerations with Sparse files -- - Document saving MySQL databases, where to find code for shutting down and saving other databases. +- Test restore options. Test bscan and MD5 in FileSet. For 1.27 release: - Continue improving the restore process (handling @@ -16,10 +17,10 @@ For 1.27 release: position the tape, ...) - Work more on how to to a Bacula restore beginning with just a Bacula tape and a boot floppy (bare metal recovery). +- Try bare metal Windows restore -- Finish implementation of restore "replace" options, and document. -- Write bcopy program. -- Recovery of a bad tape (bcopy) +- Write bcopy program -- recovery of bad tape. +- Fix read_record to handle multiple sessions. - Program files (i.e. execute a program to read/write files). Pass read date of last backup, size of file last time. @@ -34,11 +35,8 @@ For 1.27 release: - Add code to reject whole blocks if not wanted on restore. - Possibly add email to Watchdog if drive is unmounted too long and a job is waiting on the drive. -- What to do with btime and JobTDate? -- Add FileSet MD5 to bscan. - Strip trailing slashes from Include directory names in the FD. - Use read_record.c in SD code. -- Try bare metal Windows restore - Add EOM records ??????? - Why don't we get an error message from Win32 FD when bootstrap file cannot be created for restore command? @@ -555,4 +553,5 @@ Done: (see kernsdone for more) create_volume_list) -- also in restore command? - File system type from File daemon - Move block size code from block.c to init_dev(). - +- Add FileSet MD5 to bscan. +- Finish implementation of restore "replace" options, and document. diff --git a/bacula/src/baconfig.h b/bacula/src/baconfig.h index 627dc0fdbb..8a9f2f51f0 100644 --- a/bacula/src/baconfig.h +++ b/bacula/src/baconfig.h @@ -348,5 +348,13 @@ extern int thr_setconcurrency(int); #define S_ISWIN32 020000 #endif +/* Replace codes needed in both file routines and non-file routines */ +/* Job replace codes -- in "replace" */ +#define REPLACE_ALWAYS 'a' +#define REPLACE_IFNEWER 'w' +#define REPLACE_NEVER 'n' +#define REPLACE_IFOLDER 'o' + + #endif /* _BACONFIG_H */ diff --git a/bacula/src/dird/dird_conf.c b/bacula/src/dird/dird_conf.c index a5a4d12f1e..d7e873134b 100644 --- a/bacula/src/dird/dird_conf.c +++ b/bacula/src/dird/dird_conf.c @@ -174,7 +174,7 @@ static struct res_items job_items[] = { {"client", store_res, ITEM(res_job.client), R_CLIENT, 0, 0}, {"fileset", store_res, ITEM(res_job.fileset), R_FILESET, 0, 0}, {"where", store_dir, ITEM(res_job.RestoreWhere), 0, 0, 0}, - {"replace", store_replace, ITEM(res_job.replace), 'a', ITEM_DEFAULT, 0}, + {"replace", store_replace, ITEM(res_job.replace), REPLACE_ALWAYS, ITEM_DEFAULT, 0}, {"bootstrap",store_dir, ITEM(res_job.RestoreBootstrap), 0, 0, 0}, {"maxruntime", store_time, ITEM(res_job.MaxRunTime), 0, 0, 0}, {"maxstartdelay", store_time,ITEM(res_job.MaxStartDelay), 0, 0, 0}, @@ -333,9 +333,10 @@ static struct s_kw RestoreFields[] = { /* Options permitted in Restore replace= */ struct s_kw ReplaceOptions[] = { - {"always", 'a'}, /* always */ - {"ifnewer", 'w'}, - {"never", 'n'}, + {"always", REPLACE_ALWAYS}, + {"ifnewer", REPLACE_IFNEWER}, + {"ifolder", REPLACE_IFOLDER}, + {"never", REPLACE_NEVER}, {NULL, 0} }; @@ -1216,10 +1217,9 @@ static void store_restore(LEX *lc, struct res_items *item, int index, int pass) * Scan for Include options (keyword=option) is converted into one or * two characters. Verifyopts=xxxx is Vxxxx: */ -static char *scan_include_options(LEX *lc, int keyword) +static void scan_include_options(LEX *lc, int keyword, char *opts, int optlen) { int token, i; - static char opts[100]; char option[3]; option[0] = 0; /* default option = none */ @@ -1228,12 +1228,13 @@ static char *scan_include_options(LEX *lc, int keyword) token = lex_get_token(lc, T_NAME); /* expect at least one option */ if (keyword == INC_KW_VERIFY) { /* special case */ /* ***FIXME**** ensure these are in permitted set */ - strcpy(option, "V"); /* indicate Verify */ - strcat(option, lc->str); - strcat(option, ":"); /* terminate it */ + bstrncat(opts, "V", optlen); /* indicate Verify */ + bstrncat(opts, lc->str, optlen); + bstrncat(opts, ":", optlen); /* terminate it */ } else { for (i=0; FS_options[i].name; i++) { if (strcasecmp(lc->str, FS_options[i].name) == 0 && FS_options[i].keyword == keyword) { + /* NOTE! maximum 2 letters here or increase option[3] */ option[0] = FS_options[i].option[0]; option[1] = FS_options[i].option[1]; i = 0; @@ -1243,8 +1244,8 @@ static char *scan_include_options(LEX *lc, int keyword) if (i != 0) { scan_err1(lc, "Expected a FileSet option keyword, got: %s", lc->str); } + bstrncat(opts, option, optlen); } - strcat(opts, option); /* check if more options are specified */ if (lc->ch != ',') { @@ -1252,8 +1253,6 @@ static char *scan_include_options(LEX *lc, int keyword) } token = lex_get_token(lc, T_ALL); /* yes, eat comma */ } - - return opts; } @@ -1286,7 +1285,7 @@ static void store_inc(LEX *lc, struct res_items *item, int index, int pass) if ((token=lex_get_token(lc, T_ALL)) != T_EQUALS) { scan_err1(lc, "expected an = following keyword, got: %s", lc->str); } - strcat(inc_opts, scan_include_options(lc, keyword)); + scan_include_options(lc, keyword, inc_opts, sizeof(inc_opts)); if (token == T_BOB) { break; } diff --git a/bacula/src/dird/restore.c b/bacula/src/dird/restore.c index 9c686b7656..f702c620a6 100644 --- a/bacula/src/dird/restore.c +++ b/bacula/src/dird/restore.c @@ -233,7 +233,7 @@ int do_restore(JCR *jcr) if (jcr->job->replace != 0) { replace = jcr->job->replace; } else { - replace = 'a'; /* always replace */ + replace = REPLACE_ALWAYS; /* always replace */ } if (jcr->RestoreWhere) { where = jcr->RestoreWhere; /* override */ diff --git a/bacula/src/dird/ua_run.c b/bacula/src/dird/ua_run.c index be33e03479..84e5b8c283 100644 --- a/bacula/src/dird/ua_run.c +++ b/bacula/src/dird/ua_run.c @@ -281,7 +281,7 @@ int runcmd(UAContext *ua, char *cmd) } else if (job->replace) { jcr->replace = job->replace; } else { - jcr->replace = 'a'; + jcr->replace = REPLACE_ALWAYS; } replace = ReplaceOptions[0].name; for (i=0; ReplaceOptions[i].name; i++) { diff --git a/bacula/src/filed/restore.c b/bacula/src/filed/restore.c index 8953758e1b..322b24038e 100644 --- a/bacula/src/filed/restore.c +++ b/bacula/src/filed/restore.c @@ -248,7 +248,7 @@ void do_restore(JCR *jcr) print_ls_output(jcr, ofile, lname, type, &statp); extract = create_file(jcr, fname, ofile, lname, type, - stream, &statp, attribsEx, &ofd); + stream, &statp, attribsEx, &ofd, jcr->replace); Dmsg1(40, "Extract=%d\n", extract); if (extract) { jcr->JobFiles++; diff --git a/bacula/src/findlib/create_file.c b/bacula/src/findlib/create_file.c index 12e8ede309..b1d83cc07e 100644 --- a/bacula/src/findlib/create_file.c +++ b/bacula/src/findlib/create_file.c @@ -58,7 +58,7 @@ */ int create_file(void *jcr, char *fname, char *ofile, char *lname, int type, int stream, struct stat *statp, - char *attribsEx, int *ofd) + char *attribsEx, int *ofd, int replace) { int new_mode, parent_mode, mode; uid_t uid; @@ -68,9 +68,6 @@ int create_file(void *jcr, char *fname, char *ofile, char *lname, char *f, *p, savechr; *ofd = -1; -/* - * new_mode = S_IRWXUGO & ~umask(0); - */ new_mode = statp->st_mode; Dmsg2(300, "newmode=%x file=%s\n", new_mode, ofile); parent_mode = S_IWUSR | S_IXUSR | new_mode; @@ -81,12 +78,35 @@ int create_file(void *jcr, char *fname, char *ofile, char *lname, case FT_LNKSAVED: /* Hard linked, file already saved */ Dmsg2(130, "Hard link %s => %s\n", ofile, lname); if (link(lname, ofile) != 0) { - Jmsg3(jcr, M_ERROR, 0, "Could not hard link %s ==> %s: ERR=%s\n", + Jmsg3(jcr, M_ERROR, 0, _("Could not hard link %s ==> %s: ERR=%s\n"), ofile, lname, strerror(errno)); } break; case FT_REGE: /* empty file */ case FT_REG: /* regular file */ + /* If not always replacing, do a stat and decide */ + if (replace != REPLACE_ALWAYS) { + struct stat mstatp; + if (lstat(ofile, &mstatp) == 0) { + switch (replace) { + case REPLACE_IFNEWER: + if (statp->st_mtime < mstatp.st_mtime) { + Jmsg1(jcr, M_INFO, 0, _("File %s skipped. Not newer.\n"), ofile); + return 0; + } + break; + case REPLACE_IFOLDER: + if (statp->st_mtime > mstatp.st_mtime) { + Jmsg1(jcr, M_INFO, 0, _("File %s skipped. Not older.\n"), ofile); + return 0; + } + break; + case REPLACE_NEVER: + Jmsg1(jcr, M_INFO, 0, _("File %s skipped. Already exists.\n"), ofile); + return 0; + } + } + } /* Separate pathname and filename */ for (p=f=ofile; *p; p++) { if (*p == '/') { @@ -99,13 +119,13 @@ int create_file(void *jcr, char *fname, char *ofile, char *lname, fnl = p - f; if (fnl == 0) { - Jmsg1(jcr, M_ERROR, 0, "Zero length filename: %s\n", fname); + Jmsg1(jcr, M_ERROR, 0, _("Zero length filename: %s\n"), fname); return 0; } pnl = f - ofile - 1; if (pnl <= 0) { - Jmsg1(jcr, M_ERROR, 0, "Zero length path: %s\n", fname); + Jmsg1(jcr, M_ERROR, 0, _("Zero length path: %s\n"), fname); return 0; } savechr = ofile[pnl]; @@ -131,34 +151,34 @@ int create_file(void *jcr, char *fname, char *ofile, char *lname, } Dmsg1(50, "Create file: %s\n", ofile); if ((*ofd = open(ofile, mode, S_IRUSR | S_IWUSR)) < 0) { - Jmsg2(jcr, M_ERROR, 0, "Could not create %s: ERR=%s\n", ofile, strerror(errno)); + Jmsg2(jcr, M_ERROR, 0, _("Could not create %s: ERR=%s\n"), ofile, strerror(errno)); return 0; } return 1; case FT_LNK: Dmsg2(130, "FT_LNK should restore: %s -> %s\n", ofile, lname); if (symlink(lname, ofile) != 0 && errno != EEXIST) { - Jmsg3(jcr, M_ERROR, 0, "Could not symlink %s -> %s: ERR=%s\n", + Jmsg3(jcr, M_ERROR, 0, _("Could not symlink %s -> %s: ERR=%s\n"), ofile, lname, strerror(errno)); } return 0; case FT_DIR: Dmsg2(300, "Make dir mode=%o dir=%s\n", new_mode, ofile); if (make_path(jcr, ofile, new_mode, parent_mode, uid, gid, 0, NULL) != 0) { - Jmsg1(jcr, M_ERROR, 0, "Could not make directory: %s\n", ofile); + Jmsg1(jcr, M_ERROR, 0, _("Could not make directory: %s\n"), ofile); } return 0; case FT_SPEC: if (S_ISFIFO(statp->st_mode)) { Dmsg1(0, "Restore fifo: %s\n", ofile); if (mkfifo(ofile, statp->st_mode) != 0) { - Jmsg2(jcr, M_ERROR, 0, "Cannot make fifo %s: ERR=%s\n", ofile, strerror(errno)); + Jmsg2(jcr, M_ERROR, 0, _("Cannot make fifo %s: ERR=%s\n"), ofile, strerror(errno)); return 0; } } else { Dmsg1(0, "Restore node: %s\n", ofile); if (mknod(ofile, statp->st_mode, statp->st_rdev) != 0) { - Jmsg2(jcr, M_ERROR, 0, "Cannot make node %s: ERR=%s\n", ofile, strerror(errno)); + Jmsg2(jcr, M_ERROR, 0, _("Cannot make node %s: ERR=%s\n"), ofile, strerror(errno)); return 0; } } @@ -175,10 +195,10 @@ int create_file(void *jcr, char *fname, char *ofile, char *lname, case FT_NORECURSE: case FT_NOFSCHG: case FT_NOOPEN: - Jmsg2(jcr, M_ERROR, 0, "Original file %s not saved. Stat=%d\n", fname, type); + Jmsg2(jcr, M_ERROR, 0, _("Original file %s not saved. Stat=%d\n"), fname, type); return 0; default: - Jmsg2(jcr, M_ERROR, 0, "Unknown file type %d; not restored: %s\n", type, fname); + Jmsg2(jcr, M_ERROR, 0, _("Unknown file type %d; not restored: %s\n"), type, fname); return 0; } diff --git a/bacula/src/findlib/find.h b/bacula/src/findlib/find.h index d8a0e26d8b..ed362bbe05 100755 --- a/bacula/src/findlib/find.h +++ b/bacula/src/findlib/find.h @@ -45,7 +45,6 @@ #include "save-cwd.h" - /* * NOTE!!! These go on the tape, so don't change them. If * need be, add to them. diff --git a/bacula/src/findlib/protos.h b/bacula/src/findlib/protos.h index 69b5c2b677..5e2a61801e 100644 --- a/bacula/src/findlib/protos.h +++ b/bacula/src/findlib/protos.h @@ -34,7 +34,7 @@ int set_attributes(void *jcr, char *fname, char *ofile, char *lname, /* from create_file.c */ int create_file(void *jcr, char *fname, char *ofile, char *lname, int type, int stream, struct stat *statp, - char *attribsEx, int *ofd); + char *attribsEx, int *ofd, int replace); /* From find.c */ FF_PKT *init_find_files(); diff --git a/bacula/src/stored/bextract.c b/bacula/src/stored/bextract.c index c5a5554d76..4df73cd102 100644 --- a/bacula/src/stored/bextract.c +++ b/bacula/src/stored/bextract.c @@ -362,7 +362,7 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) /* Pmsg1(000, "Restoring: %s\n", ofile); */ extract = create_file(jcr, fname, ofile, lname, type, stream, - &statp, attribsEx, &ofd); + &statp, attribsEx, &ofd, REPLACE_ALWAYS); num_files++; if (extract) { diff --git a/bacula/src/stored/bscan.c b/bacula/src/stored/bscan.c index 9ab112e531..2034ca2fce 100644 --- a/bacula/src/stored/bscan.c +++ b/bacula/src/stored/bscan.c @@ -398,6 +398,7 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) /* Create FileSet record */ strcpy(fsr.FileSet, label.FileSetName); + strcpy(fsr.MD5, label.FileSetMD5); create_fileset_record(db, &fsr); jr.FileSetId = fsr.FileSetId; @@ -763,8 +764,10 @@ static int create_fileset_record(B_DB *db, FILESET_DBR *fsr) return 1; } fsr->FileSetId = 0; - fsr->MD5[0] = ' '; /* ***FIXME*** */ - fsr->MD5[1] = 0; + if (fsr->MD5[0] == 0) { + fsr->MD5[0] = ' '; /* Equivalent to nothing */ + fsr->MD5[1] = 0; + } if (db_get_fileset_record(db, fsr)) { if (verbose) { Pmsg1(000, _("Fileset \"%s\" already exists.\n"), fsr->FileSet); diff --git a/bacula/src/stored/label.c b/bacula/src/stored/label.c index 137ea73e24..82432efd37 100644 --- a/bacula/src/stored/label.c +++ b/bacula/src/stored/label.c @@ -662,6 +662,8 @@ int unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec) } if (label->VerNum >= 11) { unser_string(label->FileSetMD5); + } else { + label->FileSetMD5[0] = 0; } if (rec->FileIndex == EOS_LABEL) { unser_uint32(label->JobFiles); diff --git a/bacula/src/version.h b/bacula/src/version.h index b02e1cd68b..a4070d4e59 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #define VERSION "1.27" #define VSTRING "1" -#define DATE "30 October 2002" -#define LSMDATE "30Oct02" +#define DATE "01 November 2002" +#define LSMDATE "01Nov02" /* Debug flags */ #define DEBUG 1 -- 2.39.5