From: Kern Sibbald Date: Sat, 11 Oct 2003 16:37:02 +0000 (+0000) Subject: Implement select by file before date + more restore X-Git-Tag: Release-7.0.0~9959 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=a83d4155ca138d917b0b2dc33e90dcee325527e7;p=bacula%2Fbacula Implement select by file before date + more restore command line options git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@746 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/kernstodo b/bacula/kernstodo index 28065c6ac5..582aa56831 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -36,6 +36,7 @@ For 1.33 Testing/Documentation: SuSE. For 1.33 +- Report CVS problems to SourceForge. - Implement .consolerc for Console - I want to restore by file to some date. - Is it really important to make Job name the same to find the @@ -1043,4 +1044,3 @@ Done: (see kernsdone for more) - Test connect timeouts. - Fix FreeBSD build with tcp_wrapper -- should not have -lnsl - Implement fast block rejection. - diff --git a/bacula/src/dird/sql_cmds.c b/bacula/src/dird/sql_cmds.c index b7f2836264..2ad029bb35 100644 --- a/bacula/src/dird/sql_cmds.c +++ b/bacula/src/dird/sql_cmds.c @@ -213,7 +213,7 @@ char *uar_inc_dec = "Job.Level,Job.JobFiles,Job.StartTime,Media.VolumeName,JobMedia.StartFile," "Job.VolSessionId,Job.VolSessionTime " "FROM Job,JobMedia,Media " - "WHERE Job.JobTDate>%s AND Job.StartTime < '%s' " + "WHERE Job.JobTDate>%s AND Job.StartTime<'%s' " "AND Job.ClientId=%u " "AND JobMedia.JobId=Job.JobId " "AND JobMedia.MediaId=Media.MediaId " @@ -241,10 +241,11 @@ char *uar_mediatype = "SELECT MediaType FROM JobMedia,Media WHERE JobMedia.JobId=%u " "AND JobMedia.MediaId=Media.MediaId"; -/* Find JobId, FileIndex for a given path/file */ +/* Find JobId, FileIndex for a given path/file and date */ char *uar_jobid_fileindex = "SELECT Job.JobId, File.FileIndex FROM Job,File,Path,Filename,Client " "WHERE Job.JobId=File.JobId " + "AND Job.StartTime<'%s' " "AND Path.Path='%s' " "AND Filename.Name='%s' " "AND Client.Name='%s' " diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index 2aa5729bb7..c455d086b4 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -50,7 +50,7 @@ extern int messagescmd(UAContext *ua, char *cmd); extern int autodisplaycmd(UAContext *ua, char *cmd); extern int sqlquerycmd(UAContext *ua, char *cmd); extern int querycmd(UAContext *ua, char *cmd); -extern int runcmd(UAContext *ua, char *cmd); +extern int run_cmd(UAContext *ua, char *cmd); extern int retentioncmd(UAContext *ua, char *cmd); extern int prunecmd(UAContext *ua, char *cmd); extern int purgecmd(UAContext *ua, char *cmd); @@ -106,7 +106,7 @@ static struct cmdstruct commands[] = { { N_("relabel"), relabel_cmd, _("relabel a tape")}, { N_("release"), release_cmd, _("release ")}, { N_("restore"), restore_cmd, _("restore files")}, - { N_("run"), runcmd, _("run ")}, + { N_("run"), run_cmd, _("run ")}, { N_("setdebug"), setdebug_cmd, _("sets debug level")}, { N_("show"), show_cmd, _("show (resource records) [jobs | pools | ... | all]")}, { N_("sqlquery"), sqlquerycmd, _("use SQL to query catalog")}, diff --git a/bacula/src/dird/ua_restore.c b/bacula/src/dird/ua_restore.c index 0ca2ab0da9..91d78a18c7 100644 --- a/bacula/src/dird/ua_restore.c +++ b/bacula/src/dird/ua_restore.c @@ -38,7 +38,7 @@ /* Imported functions */ -extern int runcmd(UAContext *ua, char *cmd); +extern int run_cmd(UAContext *ua, char *cmd); extern void print_bsr(UAContext *ua, RBSR *bsr); /* Imported variables */ @@ -101,9 +101,11 @@ static void build_directory_tree(UAContext *ua, RESTORE_CTX *rx); static void free_rx(RESTORE_CTX *rx); static void split_path_and_filename(RESTORE_CTX *rx, char *fname); static int jobid_fileindex_handler(void *ctx, int num_fields, char **row); -static int insert_file_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *file); -static void insert_one_file(UAContext *ua, RESTORE_CTX *rx); +static int insert_file_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *file, + char *date); +static void insert_one_file(UAContext *ua, RESTORE_CTX *rx, char *date); static int get_client_name(UAContext *ua, RESTORE_CTX *rx); +static int get_date(UAContext *ua, char *date, int date_len); /* * Restore files @@ -165,7 +167,7 @@ int restore_cmd(UAContext *ua, char *cmd) case 1: /* select by jobid */ build_directory_tree(ua, &rx); break; - case 2: + case 2: /* select by filename, no tree needed */ break; } @@ -210,10 +212,12 @@ int restore_cmd(UAContext *ua, char *cmd) job->hdr.name, rx.ClientName, rx.store?rx.store->hdr.name:"", working_directory); } - + if (find_arg(ua, _("run")) >= 0) { + pm_strcat(&ua->cmd, " run"); /* pass it on to the run command */ + } Dmsg1(400, "Submitting: %s\n", ua->cmd); parse_ua_args(ua); - runcmd(ua, ua->cmd); + run_cmd(ua, ua->cmd); bsendmsg(ua, _("Restore command done.\n")); free_rx(&rx); @@ -273,6 +277,7 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) { char *p; char date[MAX_TIME_LENGTH]; + bool have_date = false; JobId_t JobId; JOB_DBR jr; bool done = false; @@ -285,6 +290,7 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) "Select the most recent backup for a client", "Select backup for a client before a specified time", "Enter a list of files to restore", + "Enter a list of files to restore before a specified time", "Cancel", NULL }; @@ -293,24 +299,26 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) "current", /* 1 */ "before", /* 2 */ "file", /* 3 */ + "select", /* 4 */ NULL }; + *rx->JobIds = 0; switch (find_arg_keyword(ua, kw)) { case 0: /* jobid */ - i = find_arg_with_value(ua, _("jobid")); - if (i < 0) { - return 0; + for ( ;; ) { + i = find_arg_with_value(ua, _("jobid")); + if (i < 0) { + break; + } + pm_strcpy(&rx->JobIds, ua->argv[i]); + ua->argk[i][0] = 0; /* "consume" jobid= */ } - pm_strcpy(&rx->JobIds, ua->argv[i]); done = true; break; case 1: /* current */ bstrutime(date, sizeof(date), time(NULL)); - if (!select_backups_before_date(ua, rx, date)) { - return 0; - } - done = true; + have_date = true; break; case 2: /* before */ i = find_arg_with_value(ua, _("before")); @@ -322,12 +330,12 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) return 0; } bstrncpy(date, ua->argv[i], sizeof(date)); - if (!select_backups_before_date(ua, rx, date)) { - return 0; - } - done = true; + have_date = true; break; case 3: /* file */ + if (!have_date) { + bstrutime(date, sizeof(date), time(NULL)); + } if (!get_client_name(ua, rx)) { return 0; } @@ -337,12 +345,21 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) break; } pm_strcpy(&ua->cmd, ua->argv[i]); - insert_one_file(ua, rx); - ua->argk[i][0] = 0; + insert_one_file(ua, rx, date); + ua->argk[i][0] = 0; /* "consume" the file= */ } /* Check MediaType and select storage that corresponds */ get_storage_from_mediatype(ua, &rx->name_list, rx); return 2; + case 4: /* select */ + if (!have_date) { + bstrutime(date, sizeof(date), time(NULL)); + } + if (!select_backups_before_date(ua, rx, date)) { + return 0; + } + done = true; + break; default: break; } @@ -403,23 +420,38 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) } break; case 5: /* select backup at specified time */ - bsendmsg(ua, _("The restored files will the most current backup\n" - "BEFORE the date you specify below.\n\n")); + if (!get_date(ua, date, sizeof(date))) { + return 0; + } + if (!select_backups_before_date(ua, rx, date)) { + return 0; + } + break; + case 6: /* Enter files */ + bstrutime(date, sizeof(date), time(NULL)); + if (!get_client_name(ua, rx)) { + return 0; + } + bsendmsg(ua, _("Enter file names, or < to enter a filename\n" + "containg a list of file names, and terminate\n" + "them with a blank line.\n")); for ( ;; ) { - if (!get_cmd(ua, _("Enter date as YYYY-MM-DD HH:MM:SS :"))) { + if (!get_cmd(ua, _("Enter filename: "))) { return 0; } - if (str_to_utime(ua->cmd) != 0) { + len = strlen(ua->cmd); + if (len == 0) { break; } - bsendmsg(ua, _("Improper date format.\n")); - } - bstrncpy(date, ua->cmd, sizeof(date)); - if (!select_backups_before_date(ua, rx, date)) { + insert_one_file(ua, rx, date); + } + /* Check MediaType and select storage that corresponds */ + get_storage_from_mediatype(ua, &rx->name_list, rx); + return 2; + case 7: /* enter files backed up before specified time */ + if (!get_date(ua, date, sizeof(date))) { return 0; } - break; - case 6: /* Enter files */ if (!get_client_name(ua, rx)) { return 0; } @@ -434,13 +466,14 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) if (len == 0) { break; } - insert_one_file(ua, rx); + insert_one_file(ua, rx, date); } /* Check MediaType and select storage that corresponds */ get_storage_from_mediatype(ua, &rx->name_list, rx); return 2; + - case 7: /* Cancel or quit */ + case 8: /* Cancel or quit */ return 0; } } @@ -477,7 +510,24 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) return 1; } -static void insert_one_file(UAContext *ua, RESTORE_CTX *rx) +static int get_date(UAContext *ua, char *date, int date_len) +{ + bsendmsg(ua, _("The restored files will the most current backup\n" + "BEFORE the date you specify below.\n\n")); + for ( ;; ) { + if (!get_cmd(ua, _("Enter date as YYYY-MM-DD HH:MM:SS :"))) { + return 0; + } + if (str_to_utime(ua->cmd) != 0) { + break; + } + bsendmsg(ua, _("Improper date format.\n")); + } + bstrncpy(date, ua->cmd, date_len); + return 1; +} + +static void insert_one_file(UAContext *ua, RESTORE_CTX *rx, char *date) { FILE *ffd; char file[5000]; @@ -494,14 +544,14 @@ static void insert_one_file(UAContext *ua, RESTORE_CTX *rx) } while (fgets(file, sizeof(file), ffd)) { line++; - if (!insert_file_into_findex_list(ua, rx, file)) { + if (!insert_file_into_findex_list(ua, rx, file, date)) { bsendmsg(ua, _("Error occurred on line %d of %s\n"), line, p); } } fclose(ffd); break; default: - insert_file_into_findex_list(ua, rx, ua->cmd); + insert_file_into_findex_list(ua, rx, ua->cmd, date); break; } } @@ -511,11 +561,12 @@ static void insert_one_file(UAContext *ua, RESTORE_CTX *rx) * lookup the most recent backup in the catalog to get the JobId * and FileIndex, then insert them into the findex list. */ -static int insert_file_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *file) +static int insert_file_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *file, + char *date) { strip_trailing_junk(file); split_path_and_filename(rx, file); - Mmsg(&rx->query, uar_jobid_fileindex, rx->path, rx->fname, rx->ClientName); + Mmsg(&rx->query, uar_jobid_fileindex, date, rx->path, rx->fname, rx->ClientName); rx->found = false; /* Find and insert jobid and File Index */ if (!db_sql_query(ua->db, rx->query, jobid_fileindex_handler, (void *)rx)) { diff --git a/bacula/src/dird/ua_run.c b/bacula/src/dird/ua_run.c index 9a4a559dce..829e1e9a92 100644 --- a/bacula/src/dird/ua_run.c +++ b/bacula/src/dird/ua_run.c @@ -44,7 +44,7 @@ extern struct s_kw ReplaceOptions[]; * run jobid=nn * */ -int runcmd(UAContext *ua, char *cmd) +int run_cmd(UAContext *ua, char *cmd) { JCR *jcr; char *job_name, *level_name, *jid, *store_name, *pool_name; @@ -71,9 +71,11 @@ int runcmd(UAContext *ua, char *cmd) N_("when"), N_("priority"), N_("yes"), /* 12 -- if you change this change YES_POS too */ + N_("run"), /* 13 -- if you change this change RUN_POS too */ NULL}; #define YES_POS 12 +#define RUN_POS 13 if (!open_db(ua)) { return 1; @@ -96,8 +98,8 @@ int runcmd(UAContext *ua, char *cmd) Dmsg2(200, "Doing arg %d = %s\n", i, ua->argk[i]); for (j=0; !found && kw[j]; j++) { if (strcasecmp(ua->argk[i], _(kw[j])) == 0) { - /* Note, yes has no value, so do not err */ - if (!ua->argv[i] && j != YES_POS /*yes*/) { + /* Note, yes and run have no value, so do not err */ + if (!ua->argv[i] && (j != YES_POS /*yes*/ && j != RUN_POS)) { bsendmsg(ua, _("Value missing for keyword %s\n"), ua->argk[i]); return 1; } @@ -203,6 +205,7 @@ int runcmd(UAContext *ua, char *cmd) } break; case 12: /* yes */ + case 13: /* run */ found = True; break; default: diff --git a/bacula/src/dird/ua_select.c b/bacula/src/dird/ua_select.c index 4a32478317..3bef0d2bcf 100644 --- a/bacula/src/dird/ua_select.c +++ b/bacula/src/dird/ua_select.c @@ -84,6 +84,12 @@ int find_arg_keyword(UAContext *ua, char **list) return -1; } +/* + * Given one keyword, find the first one that + * is in the argument list. + * Returns: argk index (always gt 0) + * -1 if not found + */ int find_arg(UAContext *ua, char *keyword) { for (int i=1; iargc; i++) {