2 Bacula® - The Network Backup Solution
4 Copyright (C) 2001-2014 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from many
7 others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 Bacula® is a registered trademark of Kern Sibbald.
18 * Bacula Director -- Run Command
20 * Kern Sibbald, December MMI
27 const char *get_command(int index);
31 char *job_name, *level_name, *jid, *store_name, *pool_name;
32 char *where, *fileset_name, *client_name, *bootstrap, *regexwhere;
33 char *restore_client_name, *comment, *media_type, *next_pool_name;
35 char *when, *verify_job_name, *catalog_name;
36 char *previous_job_name;
39 const char *verify_list;
63 int ignoreduplicatecheck;
64 bool ignoreduplicatecheck_set;
66 run_ctx() { memset(this, 0, sizeof(run_ctx));
67 store = new USTORE; };
68 ~run_ctx() { delete store; };
71 /* Forward referenced subroutines */
72 static void select_job_level(UAContext *ua, JCR *jcr);
73 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job,
74 const char *verify_list, char *jid, const char *replace,
76 static void select_where_regexp(UAContext *ua, JCR *jcr);
77 static bool scan_run_command_line_arguments(UAContext *ua, run_ctx &rc);
78 static bool set_run_context_in_jcr(UAContext *ua, JCR *jcr, run_ctx &rc);
79 static int modify_job_parameters(UAContext *ua, JCR *jcr, run_ctx &rc);
80 static JobId_t start_job(UAContext *ua, JCR *jcr, run_ctx &rc);
82 /* Imported variables */
83 extern struct s_kw ReplaceOptions[];
86 * For Backup and Verify Jobs
87 * run [job=]<job-name> level=<level-name>
96 int run_cmd(UAContext *ua, const char *cmd)
102 if (!open_client_db(ua)) {
106 if (!scan_run_command_line_arguments(ua, rc)) {
110 if (find_arg(ua, NT_("fdcalled")) > 0) {
111 jcr->file_bsock = dup_bsock(ua->UA_sock);
117 * Create JCR to run job. NOTE!!! after this point, free_jcr()
121 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
122 set_jcr_defaults(jcr, rc.job);
123 jcr->unlink_bsr = ua->jcr->unlink_bsr; /* copy unlink flag from caller */
124 ua->jcr->unlink_bsr = false;
126 /* Transfer JobIds to new restore Job */
127 if (ua->jcr->JobIds) {
128 jcr->JobIds = ua->jcr->JobIds;
129 ua->jcr->JobIds = NULL;
131 if (!set_run_context_in_jcr(ua, jcr, rc)) {
132 break; /* error get out of while loop */
136 /* Run without prompting? */
137 if (ua->batch || find_arg(ua, NT_("yes")) > 0) {
138 return start_job(ua, jcr, rc);
142 * Prompt User to see if all run job parameters are correct, and
143 * allow him to modify them.
145 if (!display_job_parameters(ua, jcr, rc.job, rc.verify_list, rc.jid, rc.replace,
147 break; /* error get out of while loop */
150 if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
151 break; /* error get out of while loop */
154 if (strncasecmp(ua->cmd, ".mod ", 5) == 0 ||
155 (strncasecmp(ua->cmd, "mod ", 4) == 0 && strlen(ua->cmd) > 6)) {
158 if (!scan_run_command_line_arguments(ua, rc)) {
159 break; /* error get out of while loop */
161 continue; /* another round with while loop */
164 /* Allow the user to modify the settings */
165 status = modify_job_parameters(ua, jcr, rc);
167 continue; /* another round with while loop */
169 if (status == -1) { /* error */
170 break; /* error get out of while loop */
173 if (ua->cmd[0] == 0 || strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
174 return start_job(ua, jcr, rc);
176 if (strncasecmp(ua->cmd, _("no"), strlen(ua->cmd)) == 0) {
177 break; /* get out of while loop */
179 ua->send_msg(_("\nBad response: %s. You must answer yes, mod, or no.\n\n"), ua->cmd);
183 ua->send_msg(_("Job not run.\n"));
187 return 0; /* do not run */
190 static JobId_t start_job(UAContext *ua, JCR *jcr, run_ctx &rc)
194 Dmsg1(100, "Starting JobId=%d\n", rc.jr.JobId);
195 JobId = run_job(jcr);
196 Dmsg4(100, "JobId=%u NewJobId=%d pool=%s priority=%d\n", (int)jcr->JobId,
197 JobId, jcr->pool->name(), jcr->JobPriority);
198 free_jcr(jcr); /* release jcr */
200 ua->error_msg(_("Job failed.\n"));
203 ua->send_msg(_("Job queued. JobId=%s\n"), edit_int64(JobId, ed1));
209 * If no job_name defined in the run context, ask
211 * Then put the job resource in the run context and
212 * check the access rights.
214 static bool get_job(UAContext *ua, run_ctx &rc)
218 rc.job = GetJobResWithName(rc.job_name);
220 if (*rc.job_name != 0) {
221 ua->send_msg(_("Job \"%s\" not found\n"), rc.job_name);
223 rc.job = select_job_resource(ua);
225 Dmsg1(100, "Found job=%s\n", rc.job_name);
227 } else if (!rc.job) {
228 ua->send_msg(_("A job name must be specified.\n"));
229 rc.job = select_job_resource(ua);
233 } else if (!acl_access_ok(ua, Job_ACL, rc.job->name())) {
234 ua->error_msg( _("No authorization. Job \"%s\".\n"), rc.job->name());
241 * If no pool_name defined in the run context, ask
243 * Then put the pool resource in the run context and
244 * check the access rights.
246 static bool get_pool(UAContext *ua, run_ctx &rc)
249 rc.pool = GetPoolResWithName(rc.pool_name);
251 if (*rc.pool_name != 0) {
252 ua->warning_msg(_("Pool \"%s\" not found.\n"), rc.pool_name);
254 rc.pool = select_pool_resource(ua);
256 } else if (!rc.pool) {
257 rc.pool = rc.job->pool; /* use default */
261 } else if (!acl_access_ok(ua, Pool_ACL, rc.pool->name())) {
262 ua->error_msg(_("No authorization. Pool \"%s\".\n"), rc.pool->name());
265 Dmsg1(100, "Using Pool=%s\n", rc.pool->name());
269 static bool get_next_pool(UAContext *ua, run_ctx &rc)
271 if (rc.next_pool_name) {
272 Dmsg1(100, "Have next pool=%s\n", rc.next_pool_name);
273 rc.next_pool = GetPoolResWithName(rc.next_pool_name);
275 if (*rc.next_pool_name != 0) {
276 ua->warning_msg(_("NextPool \"%s\" not found.\n"), rc.next_pool_name);
278 rc.next_pool = select_pool_resource(ua);
282 rc.next_pool = rc.pool->NextPool; /* use default */
284 if (rc.next_pool && !acl_access_ok(ua, Pool_ACL, rc.next_pool->name())) {
285 ua->error_msg(_("No authorization. NextPool \"%s\".\n"), rc.next_pool->name());
289 Dmsg1(100, "Using NextPool=%s\n", NPRT(rc.next_pool->name()));
296 * Fill in client data according to what is setup
297 * in the run context, and make sure the user
298 * has authorized access to it.
300 static bool get_client(UAContext *ua, run_ctx &rc)
302 if (rc.client_name) {
303 rc.client = GetClientResWithName(rc.client_name);
305 if (*rc.client_name != 0) {
306 ua->warning_msg(_("Client \"%s\" not found.\n"), rc.client_name);
308 rc.client = select_client_resource(ua);
310 } else if (!rc.client) {
311 rc.client = rc.job->client; /* use default */
315 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
316 ua->error_msg(_("No authorization. Client \"%s\".\n"),
320 Dmsg1(800, "Using client=%s\n", rc.client->name());
322 if (rc.restore_client_name) {
323 rc.client = GetClientResWithName(rc.restore_client_name);
325 if (*rc.restore_client_name != 0) {
326 ua->warning_msg(_("Restore Client \"%s\" not found.\n"), rc.restore_client_name);
328 rc.client = select_client_resource(ua);
330 } else if (!rc.client) {
331 rc.client = rc.job->client; /* use default */
335 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
336 ua->error_msg(_("No authorization. Client \"%s\".\n"),
340 Dmsg1(800, "Using restore client=%s\n", rc.client->name());
346 * Fill in fileset data according to what is setup
347 * in the run context, and make sure the user
348 * has authorized access to it.
350 static bool get_fileset(UAContext *ua, run_ctx &rc)
352 if (rc.fileset_name) {
353 rc.fileset = GetFileSetResWithName(rc.fileset_name);
355 ua->send_msg(_("FileSet \"%s\" not found.\n"), rc.fileset_name);
356 rc.fileset = select_fileset_resource(ua);
358 } else if (!rc.fileset) {
359 rc.fileset = rc.job->fileset; /* use default */
363 } else if (!acl_access_ok(ua, FileSet_ACL, rc.fileset->name())) {
364 ua->send_msg(_("No authorization. FileSet \"%s\".\n"),
372 * Fill in storage data according to what is setup
373 * in the run context, and make sure the user
374 * has authorized access to it.
376 static bool get_storage(UAContext *ua, run_ctx &rc)
379 rc.store->store = GetStoreResWithName(rc.store_name);
380 pm_strcpy(rc.store->store_source, _("command line"));
381 if (!rc.store->store) {
382 if (*rc.store_name != 0) {
383 ua->warning_msg(_("Storage \"%s\" not found.\n"), rc.store_name);
385 rc.store->store = select_storage_resource(ua);
386 pm_strcpy(rc.store->store_source, _("user selection"));
388 } else if (!rc.store->store) {
389 get_job_storage(rc.store, rc.job, NULL); /* use default */
391 if (!rc.store->store) {
392 ua->error_msg(_("No storage specified.\n"));
394 } else if (!acl_access_ok(ua, Storage_ACL, rc.store->store->name())) {
395 ua->error_msg(_("No authorization. Storage \"%s\".\n"),
396 rc.store->store->name());
399 Dmsg1(800, "Using storage=%s\n", rc.store->store->name());
404 * Get and pass back a list of Jobids in rc.jid
406 static bool get_jobid_list(UAContext *ua, sellist &sl, run_ctx &rc)
413 memset(&jr, 0, sizeof(jr));
415 /* See if any JobId is specified */
416 if ((i=find_arg(ua, "jobid")) >= 0) {
417 rc.jid = ua->argv[i];
419 ua->send_msg(_("No JobId specified.\n"));
422 if (!sl.set_string(ua->argv[i], true)) {
423 ua->send_msg("%s", sl.get_errmsg());
429 /* No JobId list give, so see if he specified a Job */
430 if ((i=find_arg(ua, "job")) >= 0) {
431 rc.job_name = ua->argv[i];
432 if (!get_job(ua, rc)) {
433 ua->send_msg(_("Invalid or no Job name specified.\n"));
437 jr.limit = 100; /* max 100 records */
439 bstrncpy(jr.Name, rc.job_name, sizeof(jr.Name));
443 jr.JobStatus = rc.jr.JobStatus;
444 Dmsg2(100, "JobStatus=%d JobName=%s\n", jr.JobStatus, jr.Name);
445 /* rc.JobIds is alist of all records found and printed */
446 rc.JobIds = db_list_job_records(ua->jcr, ua->db, &jr, prtit, ua, INCOMPLETE_JOBS);
447 if (!rc.JobIds || rc.JobIds->size()==0 ||
448 !get_selection_list(ua, sl, _("Enter the JobId list to select: "), false)) {
451 Dmsg1(100, "list=%s\n", sl.get_list());
453 * Make sure each item entered is in the JobIds list
455 while ( (JobId = sl.next()) > 0) {
456 foreach_alist(pJobId, rc.JobIds) {
457 if (JobId == str_to_int64(pJobId)) {
464 ua->error_msg(_("JobId=%d entered is not in the list.\n"), JobId);
468 sl.begin(); /* reset to walk list again */
473 static bool get_jobid_from_list(UAContext *ua, sellist &sl, run_ctx &rc)
480 if ((JobId = sl.next()) < 0) {
481 Dmsg1(100, "sl.next()=%d\n", JobId);
485 rc.jr.JobId = rc.JobId = JobId;
486 Dmsg1(100, "Next JobId=%d\n", rc.JobId);
487 if (!db_get_job_record(ua->jcr, ua->db, &rc.jr)) {
488 ua->error_msg(_("Could not get job record for selected JobId=%d. ERR=%s"),
489 rc.JobId, db_strerror(ua->db));
492 Dmsg3(100, "Job=%s JobId=%d JobStatus=%c\n", rc.jr.Name, rc.jr.JobId,
494 rc.job_name = rc.jr.Name;
495 if (!get_job(ua, rc)) {
498 if (!get_pool(ua, rc)) {
501 get_job_storage(rc.store, rc.job, NULL);
502 rc.client_name = rc.job->client->hdr.name;
503 if (!get_client(ua, rc)) {
506 if (!get_fileset(ua, rc)) {
509 if (!get_storage(ua, rc)) {
516 * Restart Canceled or Failed
518 * Returns: 0 on error
522 int restart_cmd(UAContext *ua, const char *cmd)
530 const char *status_name;
534 {"Canceled", JS_Canceled},
535 {"Failed", JS_FatalError},
540 if (!open_client_db(ua)) {
545 for (i=1; i<ua->argc; i++) {
546 for (j=0; kw[j].status_name; j++) {
547 if (strcasecmp(ua->argk[i], kw[j].status_name) == 0) {
548 rc.jr.JobStatus = kw[j].job_status;
554 if (!got_kw) { /* Must prompt user */
555 start_prompt(ua, _("You have the following choices:\n"));
556 for (i=0; kw[i].status_name; i++) {
557 add_prompt(ua, kw[i].status_name);
559 i = do_prompt(ua, NULL, _("Select termination code: "), NULL, 0);
563 rc.jr.JobStatus = kw[i].job_status;
566 /* type now has what job termination code we want to look at */
567 Dmsg1(100, "Termination code=%c\n", rc.jr.JobStatus);
569 /* Get a list of JobIds to restore */
570 if (!get_jobid_list(ua, sl, rc)) {
572 rc.JobIds->destroy();
576 Dmsg1(100, "list=%s\n", sl.get_list());
578 while (get_jobid_from_list(ua, sl, rc)) {
580 * Create JCR to run job. NOTE!!! after this point, free_jcr()
584 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
585 set_jcr_defaults(jcr, rc.job);
586 jcr->unlink_bsr = ua->jcr->unlink_bsr; /* copy unlink flag from caller */
587 ua->jcr->unlink_bsr = false;
590 if (!set_run_context_in_jcr(ua, jcr, rc)) {
593 start_job(ua, jcr, rc);
601 rc.JobIds->destroy();
603 return 0; /* do not run */
607 int modify_job_parameters(UAContext *ua, JCR *jcr, run_ctx &rc)
612 * At user request modify parameters of job to be run.
614 if (ua->cmd[0] != 0 && strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0){
617 start_prompt(ua, _("Parameters to modify:\n"));
618 add_prompt(ua, _("Level")); /* 0 */
619 add_prompt(ua, _("Storage")); /* 1 */
620 add_prompt(ua, _("Job")); /* 2 */
621 add_prompt(ua, _("FileSet")); /* 3 */
622 if (jcr->getJobType() == JT_RESTORE) {
623 add_prompt(ua, _("Restore Client")); /* 4 */
625 add_prompt(ua, _("Client")); /* 4 */
627 add_prompt(ua, _("When")); /* 5 */
628 add_prompt(ua, _("Priority")); /* 6 */
629 if (jcr->getJobType() == JT_BACKUP ||
630 jcr->getJobType() == JT_COPY ||
631 jcr->getJobType() == JT_MIGRATE ||
632 jcr->getJobType() == JT_VERIFY) {
633 add_prompt(ua, _("Pool")); /* 7 */
634 if ((jcr->getJobType() == JT_BACKUP && /* Virtual full */
635 jcr->is_JobLevel(L_VIRTUAL_FULL)) ||
636 jcr->getJobType() == JT_COPY ||
637 jcr->getJobType() == JT_MIGRATE) {
638 add_prompt(ua, _("NextPool")); /* 8 */
639 } else if (jcr->getJobType() == JT_VERIFY) {
640 add_prompt(ua, _("Verify Job")); /* 8 */
642 } else if (jcr->getJobType() == JT_RESTORE) {
643 add_prompt(ua, _("Bootstrap")); /* 7 */
644 add_prompt(ua, _("Where")); /* 8 */
645 add_prompt(ua, _("File Relocation"));/* 9 */
646 add_prompt(ua, _("Replace")); /* 10 */
647 add_prompt(ua, _("JobId")); /* 11 */
649 if (jcr->getJobType() == JT_BACKUP || jcr->getJobType() == JT_RESTORE) {
650 add_prompt(ua, _("Plugin Options")); /* 12 */
652 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
655 select_job_level(ua, jcr);
659 rc.store->store = select_storage_resource(ua);
660 if (rc.store->store) {
661 pm_strcpy(rc.store->store_source, _("user selection"));
662 set_rwstorage(jcr, rc.store);
668 rc.job = select_job_resource(ua);
671 set_jcr_defaults(jcr, rc.job);
677 rc.fileset = select_fileset_resource(ua);
679 jcr->fileset = rc.fileset;
685 rc.client = select_client_resource(ua);
687 jcr->client = rc.client;
693 if (!get_cmd(ua, _("Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now): "))) {
696 if (ua->cmd[0] == 0) {
697 jcr->sched_time = time(NULL);
699 jcr->sched_time = str_to_utime(ua->cmd);
700 if (jcr->sched_time == 0) {
701 ua->send_msg(_("Invalid time, using current time.\n"));
702 jcr->sched_time = time(NULL);
708 if (!get_pint(ua, _("Enter new Priority: "))) {
711 if (ua->pint32_val == 0) {
712 ua->send_msg(_("Priority must be a positive integer.\n"));
714 jcr->JobPriority = ua->pint32_val;
718 /* Pool or Bootstrap depending on JobType */
719 if (jcr->getJobType() == JT_BACKUP ||
720 jcr->getJobType() == JT_COPY ||
721 jcr->getJobType() == JT_MIGRATE ||
722 jcr->getJobType() == JT_VERIFY) { /* Pool */
723 rc.pool = select_pool_resource(ua);
726 Dmsg1(100, "Set new pool=%s\n", jcr->pool->name());
733 if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
736 if (jcr->RestoreBootstrap) {
737 free(jcr->RestoreBootstrap);
738 jcr->RestoreBootstrap = NULL;
740 if (ua->cmd[0] != 0) {
741 jcr->RestoreBootstrap = bstrdup(ua->cmd);
742 fd = fopen(jcr->RestoreBootstrap, "rb");
745 ua->send_msg(_("Warning cannot open %s: ERR=%s\n"),
746 jcr->RestoreBootstrap, be.bstrerror());
747 free(jcr->RestoreBootstrap);
748 jcr->RestoreBootstrap = NULL;
755 /* Specify Next Pool */
756 if ((jcr->getJobType() == JT_BACKUP && /* Virtual full */
757 jcr->is_JobLevel(L_VIRTUAL_FULL)) ||
758 jcr->getJobType() == JT_COPY ||
759 jcr->getJobType() == JT_MIGRATE) {
760 rc.next_pool = select_pool_resource(ua);
762 jcr->next_pool = rc.next_pool;
763 pm_strcpy(jcr->next_pool_source, _("Command input"));
768 if (jcr->getJobType() == JT_VERIFY) {
769 rc.verify_job = select_job_resource(ua);
771 jcr->verify_job = rc.verify_job;
776 if (!get_cmd(ua, _("Please enter the full path prefix for restore (/ for none): "))) {
779 if (jcr->RegexWhere) { /* cannot use regexwhere and where */
780 free(jcr->RegexWhere);
781 jcr->RegexWhere = NULL;
787 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
790 jcr->where = bstrdup(ua->cmd);
793 /* File relocation */
794 select_where_regexp(ua, jcr);
798 start_prompt(ua, _("Replace:\n"));
799 for (i=0; ReplaceOptions[i].name; i++) {
800 add_prompt(ua, ReplaceOptions[i].name);
802 opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
804 rc.replace = ReplaceOptions[opt].name;
805 jcr->replace = ReplaceOptions[opt].token;
810 rc.jid = NULL; /* force reprompt */
811 jcr->RestoreJobId = 0;
812 if (jcr->RestoreBootstrap) {
813 ua->send_msg(_("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
818 case -1: /* error or cancel */
834 * Put the run context that we have at this point into the JCR.
835 * That allows us to re-ask for the run context.
836 * This subroutine can be called multiple times, so it
837 * must keep any prior settings.
839 static bool set_run_context_in_jcr(UAContext *ua, JCR *jcr, run_ctx &rc)
843 jcr->verify_job = rc.verify_job;
844 jcr->previous_job = rc.previous_job;
846 jcr->next_pool = rc.next_pool;
848 pm_strcpy(jcr->pool_source, _("Command input"));
849 } else if (jcr->pool != jcr->job->pool) {
850 pm_strcpy(jcr->pool_source, _("User input"));
852 if (rc.next_pool_name) {
853 pm_strcpy(jcr->next_pool_source, _("Command input"));
854 } else if (jcr->next_pool != jcr->pool->NextPool) {
855 pm_strcpy(jcr->next_pool_source, _("User input"));
858 set_rwstorage(jcr, rc.store);
859 jcr->client = rc.client;
860 pm_strcpy(jcr->client_name, rc.client->name());
862 if (!jcr->media_type) {
863 jcr->media_type = get_pool_memory(PM_NAME);
865 pm_strcpy(jcr->media_type, rc.media_type);
867 jcr->fileset = rc.fileset;
868 jcr->ExpectedFiles = rc.files;
870 jcr->catalog = rc.catalog;
871 pm_strcpy(jcr->catalog_source, _("User input"));
874 pm_strcpy(jcr->comment, rc.comment);
880 jcr->where = bstrdup(rc.where);
885 if (jcr->RegexWhere) {
886 free(jcr->RegexWhere);
888 jcr->RegexWhere = bstrdup(rc.regexwhere);
889 rc.regexwhere = NULL;
893 jcr->sched_time = str_to_utime(rc.when);
894 if (jcr->sched_time == 0) {
895 ua->send_msg(_("Invalid time, using current time.\n"));
896 jcr->sched_time = time(NULL);
902 if (jcr->RestoreBootstrap) {
903 free(jcr->RestoreBootstrap);
905 jcr->RestoreBootstrap = bstrdup(rc.bootstrap);
909 if (rc.plugin_options) {
910 if (jcr->plugin_options) {
911 free(jcr->plugin_options);
913 jcr->plugin_options = bstrdup(rc.plugin_options);
914 rc.plugin_options = NULL;
919 for (i=0; ReplaceOptions[i].name; i++) {
920 if (strcasecmp(rc.replace, ReplaceOptions[i].name) == 0) {
921 jcr->replace = ReplaceOptions[i].token;
925 ua->send_msg(_("Invalid replace option: %s\n"), rc.replace);
928 } else if (rc.job->replace) {
929 jcr->replace = rc.job->replace;
931 jcr->replace = REPLACE_ALWAYS;
936 jcr->JobPriority = rc.Priority;
942 jcr->stime = get_pool_memory(PM_MESSAGE);
944 pm_strcpy(jcr->stime, rc.since);
949 jcr->cloned = rc.cloned;
953 /* If pool changed, update migration write storage */
954 if (jcr->is_JobType(JT_MIGRATE) || jcr->is_JobType(JT_COPY) ||
955 (jcr->is_JobType(JT_BACKUP) && jcr->is_JobLevel(L_VIRTUAL_FULL))) {
956 if (!set_mac_wstorage(ua, jcr, rc.pool, rc.next_pool,
957 jcr->next_pool_source)) {
961 rc.replace = ReplaceOptions[0].name;
962 for (i=0; ReplaceOptions[i].name; i++) {
963 if (ReplaceOptions[i].token == (int)jcr->replace) {
964 rc.replace = ReplaceOptions[i].name;
968 if (!get_level_from_name(jcr, rc.level_name)) {
969 ua->send_msg(_("Level \"%s\" not valid.\n"), rc.level_name);
972 rc.level_name = NULL;
975 /* Note, this is also MigrateJobId and a VerifyJobId */
976 jcr->RestoreJobId = str_to_int64(rc.jid);
978 /* Copy also this parameter for VirtualFull in jcr->JobIds */
980 jcr->JobIds = get_pool_memory(PM_FNAME);
982 pm_strcpy(jcr->JobIds, rc.jid);
983 jcr->use_all_JobIds = rc.alljobid; /* if we found the "alljobid=" kw */
988 /* Some options are not available through the menu
989 * TODO: Add an advanced menu?
991 if (rc.spool_data_set) {
992 jcr->spool_data = rc.spool_data;
995 if (rc.accurate_set) {
996 jcr->accurate = rc.accurate;
999 /* Used by migration jobs that can have the same name,
1000 * but can run at the same time
1002 if (rc.ignoreduplicatecheck_set) {
1003 jcr->IgnoreDuplicateJobChecking = rc.ignoreduplicatecheck;
1009 static void select_where_regexp(UAContext *ua, JCR *jcr)
1012 char *strip_prefix, *add_prefix, *add_suffix, *rwhere;
1013 strip_prefix = add_suffix = rwhere = add_prefix = NULL;
1016 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s\n"),
1017 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix));
1019 start_prompt(ua, _("This will replace your current Where value\n"));
1020 add_prompt(ua, _("Strip prefix")); /* 0 */
1021 add_prompt(ua, _("Add prefix")); /* 1 */
1022 add_prompt(ua, _("Add file suffix")); /* 2 */
1023 add_prompt(ua, _("Enter a regexp")); /* 3 */
1024 add_prompt(ua, _("Test filename manipulation")); /* 4 */
1025 add_prompt(ua, _("Use this ?")); /* 5 */
1027 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
1030 if (get_cmd(ua, _("Please enter the path prefix to strip: "))) {
1031 if (strip_prefix) bfree(strip_prefix);
1032 strip_prefix = bstrdup(ua->cmd);
1038 if (get_cmd(ua, _("Please enter the path prefix to add (/ for none): "))) {
1039 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
1043 if (add_prefix) bfree(add_prefix);
1044 add_prefix = bstrdup(ua->cmd);
1049 if (get_cmd(ua, _("Please enter the file suffix to add: "))) {
1050 if (add_suffix) bfree(add_suffix);
1051 add_suffix = bstrdup(ua->cmd);
1056 if (get_cmd(ua, _("Please enter a valid regexp (!from!to!): "))) {
1057 if (rwhere) bfree(rwhere);
1058 rwhere = bstrdup(ua->cmd);
1067 if (rwhere && rwhere[0] != '\0') {
1068 regs = get_bregexps(rwhere);
1069 ua->send_msg(_("regexwhere=%s\n"), NPRT(rwhere));
1071 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
1072 regexp = (char *) bmalloc (len * sizeof(char));
1073 bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix);
1074 regs = get_bregexps(regexp);
1075 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s result=%s\n"),
1076 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix), NPRT(regexp));
1082 ua->send_msg(_("Cannot use your regexp\n"));
1085 ua->send_msg(_("Enter a period (.) to stop this test\n"));
1086 while (get_cmd(ua, _("Please enter filename to test: "))) {
1087 apply_bregexps(ua->cmd, regs, &result);
1088 ua->send_msg(_("%s -> %s\n"), ua->cmd, result);
1090 free_bregexps(regs);
1097 case -1: /* error or cancel */
1103 /* replace the existing where */
1109 /* replace the existing regexwhere */
1110 if (jcr->RegexWhere) {
1111 bfree(jcr->RegexWhere);
1112 jcr->RegexWhere = NULL;
1116 jcr->RegexWhere = bstrdup(rwhere);
1117 } else if (strip_prefix || add_prefix || add_suffix) {
1118 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
1119 jcr->RegexWhere = (char *) bmalloc(len*sizeof(char));
1120 bregexp_build_where(jcr->RegexWhere, len, strip_prefix, add_prefix, add_suffix);
1123 regs = get_bregexps(jcr->RegexWhere);
1125 free_bregexps(regs);
1128 if (jcr->RegexWhere) {
1129 bfree(jcr->RegexWhere);
1130 jcr->RegexWhere = NULL;
1132 ua->send_msg(_("Cannot use your regexp.\n"));
1136 if (strip_prefix) bfree(strip_prefix);
1137 if (add_prefix) bfree(add_prefix);
1138 if (add_suffix) bfree(add_suffix);
1139 if (rwhere) bfree(rwhere);
1142 static void select_job_level(UAContext *ua, JCR *jcr)
1144 if (jcr->getJobType() == JT_BACKUP) {
1145 start_prompt(ua, _("Levels:\n"));
1146 // add_prompt(ua, _("Base"));
1147 add_prompt(ua, _("Full"));
1148 add_prompt(ua, _("Incremental"));
1149 add_prompt(ua, _("Differential"));
1150 add_prompt(ua, _("Since"));
1151 add_prompt(ua, _("VirtualFull"));
1152 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
1154 // jcr->JobLevel = L_BASE;
1157 jcr->setJobLevel(L_FULL);
1160 jcr->setJobLevel(L_INCREMENTAL);
1163 jcr->setJobLevel(L_DIFFERENTIAL);
1166 jcr->setJobLevel(L_SINCE);
1169 jcr->setJobLevel(L_VIRTUAL_FULL);
1174 } else if (jcr->getJobType() == JT_VERIFY) {
1175 start_prompt(ua, _("Levels:\n"));
1176 add_prompt(ua, _("Initialize Catalog"));
1177 add_prompt(ua, _("Verify Catalog"));
1178 add_prompt(ua, _("Verify Volume to Catalog"));
1179 add_prompt(ua, _("Verify Disk to Catalog"));
1180 add_prompt(ua, _("Verify Volume Data (not yet implemented)"));
1181 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
1183 jcr->setJobLevel(L_VERIFY_INIT);
1186 jcr->setJobLevel(L_VERIFY_CATALOG);
1189 jcr->setJobLevel(L_VERIFY_VOLUME_TO_CATALOG);
1192 jcr->setJobLevel(L_VERIFY_DISK_TO_CATALOG);
1195 jcr->setJobLevel(L_VERIFY_DATA);
1201 ua->warning_msg(_("Level not appropriate for this Job. Cannot be changed.\n"));
1206 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char *verify_list,
1207 char *jid, const char *replace, char *client_name)
1210 char dt[MAX_TIME_LENGTH];
1212 Dmsg1(800, "JobType=%c\n", jcr->getJobType());
1213 switch (jcr->getJobType()) {
1216 ua->signal(BNET_RUN_CMD);
1217 ua->send_msg("Type: Admin\n"
1218 "Title: Run Admin Job\n"
1226 jcr->fileset->name(),
1227 NPRT(jcr->client->name()),
1228 jcr->wstore?jcr->wstore->name():"*None*",
1229 bstrutime(dt, sizeof(dt), jcr->sched_time),
1232 ua->send_msg(_("Run Admin Job\n"
1240 jcr->fileset->name(),
1241 NPRT(jcr->client->name()),
1242 jcr->wstore?jcr->wstore->name():"*None*",
1243 bstrutime(dt, sizeof(dt), jcr->sched_time),
1246 jcr->setJobLevel(L_FULL);
1250 char next_pool[MAX_NAME_LENGTH + 50];
1252 if (jcr->getJobType() == JT_BACKUP) {
1254 ua->signal(BNET_RUN_CMD);
1255 if (jcr->is_JobLevel(L_VIRTUAL_FULL)) {
1256 bsnprintf(next_pool, sizeof(next_pool), "NextPool: %s\n",
1257 jcr->next_pool ? jcr->next_pool->name() : "*None*");
1259 ua->send_msg("Type: Backup\n"
1260 "Title: Run Backup Job\n"
1271 level_to_str(jcr->getJobLevel()),
1272 jcr->client->name(),
1273 jcr->fileset->name(),
1274 NPRT(jcr->pool->name()),
1276 jcr->wstore?jcr->wstore->name():"*None*",
1277 bstrutime(dt, sizeof(dt), jcr->sched_time),
1280 if (jcr->is_JobLevel(L_VIRTUAL_FULL)) {
1281 bsnprintf(next_pool, sizeof(next_pool),
1282 "NextPool: %s (From %s)\n",
1283 jcr->next_pool ? jcr->next_pool->name() : "*None*",
1284 jcr->next_pool_source);
1286 ua->send_msg(_("Run Backup job\n"
1291 "Pool: %s (From %s)\n"
1293 "Storage: %s (From %s)\n"
1297 level_to_str(jcr->getJobLevel()),
1298 jcr->client->name(),
1299 jcr->fileset->name(),
1300 NPRT(jcr->pool->name()), jcr->pool_source,
1302 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
1303 bstrutime(dt, sizeof(dt), jcr->sched_time),
1306 } else { /* JT_VERIFY */
1309 if (jcr->verify_job) {
1310 Name = jcr->verify_job->name();
1311 } else if (jcr->RestoreJobId) { /* Display job name if jobid requested */
1312 memset(&jr, 0, sizeof(jr));
1313 jr.JobId = jcr->RestoreJobId;
1314 if (!db_get_job_record(jcr, ua->db, &jr)) {
1315 ua->error_msg(_("Could not get job record for selected JobId. ERR=%s"),
1316 db_strerror(ua->db));
1324 verify_list = job->WriteVerifyList;
1330 ua->signal(BNET_RUN_CMD);
1331 ua->send_msg("Type: Verify\n"
1332 "Title: Run Verify Job\n"
1337 "Pool: %s (From %s)\n"
1338 "Storage: %s (From %s)\n"
1344 level_to_str(jcr->getJobLevel()),
1345 jcr->client->name(),
1346 jcr->fileset->name(),
1347 NPRT(jcr->pool->name()), jcr->pool_source,
1348 jcr->rstore->name(), jcr->rstore_source,
1351 bstrutime(dt, sizeof(dt), jcr->sched_time),
1354 ua->send_msg(_("Run Verify Job\n"
1359 "Pool: %s (From %s)\n"
1360 "Storage: %s (From %s)\n"
1366 level_to_str(jcr->getJobLevel()),
1367 jcr->client->name(),
1368 jcr->fileset->name(),
1369 NPRT(jcr->pool->name()), jcr->pool_source,
1370 jcr->rstore->name(), jcr->rstore_source,
1373 bstrutime(dt, sizeof(dt), jcr->sched_time),
1379 if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
1381 jcr->RestoreJobId = str_to_int64(jid);
1383 if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
1386 jcr->RestoreJobId = ua->int64_val;
1389 jcr->setJobLevel(L_FULL); /* default level */
1390 Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId);
1391 if (jcr->RestoreJobId == 0) {
1392 /* RegexWhere is take before RestoreWhere */
1393 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
1395 ua->signal(BNET_RUN_CMD);
1396 ua->send_msg("Type: Restore\n"
1397 "Title: Run Restore Job\n"
1403 "Backup Client: %s\n"
1404 "Restore Client: %s\n"
1410 NPRT(jcr->RestoreBootstrap),
1411 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
1413 jcr->fileset->name(),
1415 jcr->client->name(),
1416 jcr->rstore->name(),
1417 bstrutime(dt, sizeof(dt), jcr->sched_time),
1418 jcr->catalog->name(),
1421 ua->send_msg(_("Run Restore job\n"
1427 "Backup Client: %s\n"
1428 "Restore Client: %s\n"
1434 NPRT(jcr->RestoreBootstrap),
1435 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
1437 jcr->fileset->name(),
1439 jcr->client->name(),
1440 jcr->rstore->name(),
1441 bstrutime(dt, sizeof(dt), jcr->sched_time),
1442 jcr->catalog->name(),
1447 ua->signal(BNET_RUN_CMD);
1448 ua->send_msg("Type: Restore\n"
1449 "Title: Run Restore job\n"
1455 "Backup Client: %s\n"
1456 "Restore Client: %s\n"
1462 NPRT(jcr->RestoreBootstrap),
1463 jcr->where?jcr->where:NPRT(job->RestoreWhere),
1465 jcr->fileset->name(),
1467 jcr->client->name(),
1468 jcr->rstore->name(),
1469 bstrutime(dt, sizeof(dt), jcr->sched_time),
1470 jcr->catalog->name(),
1473 ua->send_msg(_("Run Restore job\n"
1479 "Backup Client: %s\n"
1480 "Restore Client: %s\n"
1486 NPRT(jcr->RestoreBootstrap),
1487 jcr->where?jcr->where:NPRT(job->RestoreWhere),
1489 jcr->fileset->name(),
1491 jcr->client->name(),
1492 jcr->rstore->name(),
1493 bstrutime(dt, sizeof(dt), jcr->sched_time),
1494 jcr->catalog->name(),
1500 /* ***FIXME*** This needs to be fixed for bat */
1501 if (ua->api) ua->signal(BNET_RUN_CMD);
1502 ua->send_msg(_("Run Restore job\n"
1506 NPRT(jcr->RestoreBootstrap));
1508 /* RegexWhere is take before RestoreWhere */
1509 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
1510 ua->send_msg(_("RegexWhere: %s\n"),
1511 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere);
1513 ua->send_msg(_("Where: %s\n"),
1514 jcr->where?jcr->where:NPRT(job->RestoreWhere));
1517 ua->send_msg(_("Replace: %s\n"
1525 jcr->client->name(),
1526 jcr->rstore->name(),
1527 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
1528 bstrutime(dt, sizeof(dt), jcr->sched_time),
1529 jcr->catalog->name(),
1536 jcr->setJobLevel(L_FULL); /* default level */
1538 ua->signal(BNET_RUN_CMD);
1539 if (jcr->getJobType() == JT_COPY) {
1540 prt_type = (char *)"Type: Copy\nTitle: Run Copy Job\n";
1542 prt_type = (char *)"Type: Migration\nTitle: Run Migration Job\n";
1551 "Read Storage: %s\n"
1552 "Write Storage: %s\n"
1559 NPRT(jcr->RestoreBootstrap),
1560 jcr->client->name(),
1561 jcr->fileset->name(),
1562 NPRT(jcr->pool->name()),
1563 jcr->next_pool?jcr->next_pool->name():"*None*",
1564 jcr->rstore->name(),
1565 jcr->wstore?jcr->wstore->name():"*None*",
1566 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
1567 bstrutime(dt, sizeof(dt), jcr->sched_time),
1568 jcr->catalog->name(),
1571 if (jcr->getJobType() == JT_COPY) {
1572 prt_type = _("Run Copy job\n");
1574 prt_type = _("Run Migration job\n");
1581 "Pool: %s (From %s)\n"
1582 "NextPool: %s (From %s)\n"
1583 "Read Storage: %s (From %s)\n"
1584 "Write Storage: %s (From %s)\n"
1591 NPRT(jcr->RestoreBootstrap),
1592 jcr->client->name(),
1593 jcr->fileset->name(),
1594 NPRT(jcr->pool->name()), jcr->pool_source,
1595 jcr->next_pool?jcr->next_pool->name():"*None*",
1596 NPRT(jcr->next_pool_source),
1597 jcr->rstore->name(), jcr->rstore_source,
1598 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
1599 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
1600 bstrutime(dt, sizeof(dt), jcr->sched_time),
1601 jcr->catalog->name(),
1606 ua->error_msg(_("Unknown Job Type=%d\n"), jcr->getJobType());
1613 static bool scan_run_command_line_arguments(UAContext *ua, run_ctx &rc)
1617 static const char *kw[] = { /* command line arguments */
1618 "alljobid", /* 0 Used in a switch() */
1626 "regexwhere", /* 8 where string as a bregexp */
1628 "bootstrap", /* 10 */
1631 "priority", /* 13 */
1632 "yes", /* 14 -- if you change this change YES_POS too */
1633 "verifyjob", /* 15 */
1634 "files", /* 16 number of files to restore */
1635 "catalog", /* 17 override catalog */
1636 "since", /* 18 since */
1637 "cloned", /* 19 cloned */
1638 "verifylist", /* 20 verify output list */
1639 "migrationjob", /* 21 migration job name */
1641 "backupclient", /* 23 */
1642 "restoreclient", /* 24 */
1643 "pluginoptions", /* 25 */
1644 "spooldata", /* 26 */
1646 "ignoreduplicatecheck", /* 28 */
1647 "accurate", /* 29 */
1649 "mediatype", /* 31 */
1650 "nextpool", /* 32 override next pool name */
1656 rc.catalog_name = NULL;
1658 rc.pool_name = NULL;
1659 rc.next_pool_name = NULL;
1660 rc.store_name = NULL;
1661 rc.client_name = NULL;
1662 rc.media_type = NULL;
1663 rc.restore_client_name = NULL;
1664 rc.fileset_name = NULL;
1665 rc.verify_job_name = NULL;
1666 rc.previous_job_name = NULL;
1667 rc.accurate_set = false;
1668 rc.spool_data_set = false;
1669 rc.ignoreduplicatecheck = false;
1672 for (i=1; i<ua->argc; i++) {
1673 Dmsg2(800, "Doing arg %d = %s\n", i, ua->argk[i]);
1675 /* Keep looking until we find a good keyword */
1676 for (j=0; !kw_ok && kw[j]; j++) {
1677 if (strcasecmp(ua->argk[i], kw[j]) == 0) {
1678 /* Note, yes and run have no value, so do not fail */
1679 if (!ua->argv[i] && j != YES_POS /*yes*/) {
1680 ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]);
1683 Dmsg2(800, "Got j=%d keyword=%s\n", j, NPRT(kw[j]));
1685 case 0: /* alljobid */
1687 /* Fall through wanted */
1689 if (rc.jid && !rc.mod) {
1690 ua->send_msg(_("JobId specified twice.\n"));
1693 rc.jid = ua->argv[i];
1696 case 2: /* client */
1698 if (rc.client_name) {
1699 ua->send_msg(_("Client specified twice.\n"));
1702 rc.client_name = ua->argv[i];
1705 case 4: /* fileset */
1706 if (rc.fileset_name) {
1707 ua->send_msg(_("FileSet specified twice.\n"));
1710 rc.fileset_name = ua->argv[i];
1714 if (rc.level_name) {
1715 ua->send_msg(_("Level specified twice.\n"));
1718 rc.level_name = ua->argv[i];
1721 case 6: /* storage */
1723 if (rc.store_name) {
1724 ua->send_msg(_("Storage specified twice.\n"));
1727 rc.store_name = ua->argv[i];
1730 case 8: /* regexwhere */
1731 if ((rc.regexwhere || rc.where) && !rc.mod) {
1732 ua->send_msg(_("RegexWhere or Where specified twice.\n"));
1735 rc.regexwhere = ua->argv[i];
1736 if (!acl_access_ok(ua, Where_ACL, rc.regexwhere)) {
1737 ua->send_msg(_("No authorization for \"regexwhere\" specification.\n"));
1743 if ((rc.where || rc.regexwhere) && !rc.mod) {
1744 ua->send_msg(_("Where or RegexWhere specified twice.\n"));
1747 rc.where = ua->argv[i];
1748 if (!acl_access_ok(ua, Where_ACL, rc.where)) {
1749 ua->send_msg(_("No authoriztion for \"where\" specification.\n"));
1754 case 10: /* bootstrap */
1755 if (rc.bootstrap && !rc.mod) {
1756 ua->send_msg(_("Bootstrap specified twice.\n"));
1759 rc.bootstrap = ua->argv[i];
1762 case 11: /* replace */
1763 if (rc.replace && !rc.mod) {
1764 ua->send_msg(_("Replace specified twice.\n"));
1767 rc.replace = ua->argv[i];
1771 if (rc.when && !rc.mod) {
1772 ua->send_msg(_("When specified twice.\n"));
1775 rc.when = ua->argv[i];
1778 case 13: /* Priority */
1779 if (rc.Priority && !rc.mod) {
1780 ua->send_msg(_("Priority specified twice.\n"));
1783 rc.Priority = atoi(ua->argv[i]);
1784 if (rc.Priority <= 0) {
1785 ua->send_msg(_("Priority must be positive nonzero setting it to 10.\n"));
1793 case 15: /* Verify Job */
1794 if (rc.verify_job_name) {
1795 ua->send_msg(_("Verify Job specified twice.\n"));
1798 rc.verify_job_name = ua->argv[i];
1801 case 16: /* files */
1802 rc.files = atoi(ua->argv[i]);
1805 case 17: /* catalog */
1806 rc.catalog_name = ua->argv[i];
1809 case 18: /* since */
1810 rc.since = ua->argv[i];
1813 case 19: /* cloned */
1817 case 20: /* write verify list output */
1818 rc.verify_list = ua->argv[i];
1821 case 21: /* Migration Job */
1822 if (rc.previous_job_name) {
1823 ua->send_msg(_("Migration Job specified twice.\n"));
1826 rc.previous_job_name = ua->argv[i];
1831 ua->send_msg(_("Pool specified twice.\n"));
1834 rc.pool_name = ua->argv[i];
1837 case 23: /* backupclient */
1838 if (rc.client_name) {
1839 ua->send_msg(_("Client specified twice.\n"));
1842 rc.client_name = ua->argv[i];
1845 case 24: /* restoreclient */
1846 if (rc.restore_client_name && !rc.mod) {
1847 ua->send_msg(_("Restore Client specified twice.\n"));
1850 rc.restore_client_name = ua->argv[i];
1853 case 25: /* pluginoptions */
1854 ua->send_msg(_("Plugin Options not yet implemented.\n"));
1856 if (rc.plugin_options) {
1857 ua->send_msg(_("Plugin Options specified twice.\n"));
1860 rc.plugin_options = ua->argv[i];
1861 if (!acl_access_ok(ua, PluginOptions_ACL, rc.plugin_options)) {
1862 ua->send_msg(_("No authoriztion for \"PluginOptions\" specification.\n"));
1867 case 26: /* spooldata */
1868 if (rc.spool_data_set) {
1869 ua->send_msg(_("Spool flag specified twice.\n"));
1872 if (is_yesno(ua->argv[i], &rc.spool_data)) {
1873 rc.spool_data_set = true;
1876 ua->send_msg(_("Invalid spooldata flag.\n"));
1879 case 27: /* comment */
1880 rc.comment = ua->argv[i];
1883 case 28: /* ignoreduplicatecheck */
1884 if (rc.ignoreduplicatecheck_set) {
1885 ua->send_msg(_("IgnoreDuplicateCheck flag specified twice.\n"));
1888 if (is_yesno(ua->argv[i], &rc.ignoreduplicatecheck)) {
1889 rc.ignoreduplicatecheck_set = true;
1892 ua->send_msg(_("Invalid ignoreduplicatecheck flag.\n"));
1895 case 29: /* accurate */
1896 if (rc.accurate_set) {
1897 ua->send_msg(_("Accurate flag specified twice.\n"));
1900 if (is_yesno(ua->argv[i], &rc.accurate)) {
1901 rc.accurate_set = true;
1904 ua->send_msg(_("Invalid accurate flag.\n"));
1909 ua->send_msg(_("Job name specified twice.\n"));
1912 rc.job_name = ua->argv[i];
1915 case 31: /* mediatype */
1916 if (rc.media_type) {
1917 ua->send_msg(_("Media Type specified twice.\n"));
1920 rc.media_type = ua->argv[i];
1923 case 32: /* Next Pool */
1924 if (rc.next_pool_name) {
1925 ua->send_msg(_("NextPool specified twice.\n"));
1928 rc.next_pool_name = ua->argv[i];
1934 } /* end strcase compare */
1935 } /* end keyword loop */
1938 * End of keyword for loop -- if not found, we got a bogus keyword
1941 Dmsg1(800, "%s not found\n", ua->argk[i]);
1943 * Special case for Job Name, it can be the first
1944 * keyword that has no value.
1946 if (!rc.job_name && !ua->argv[i]) {
1947 rc.job_name = ua->argk[i]; /* use keyword as job name */
1948 Dmsg1(800, "Set jobname=%s\n", rc.job_name);
1950 ua->send_msg(_("Invalid keyword: %s\n"), ua->argk[i]);
1954 } /* end argc loop */
1956 Dmsg0(800, "Done scan.\n");
1958 if (!is_comment_legal(ua, rc.comment)) {
1962 if (rc.catalog_name) {
1963 rc.catalog = GetCatalogResWithName(rc.catalog_name);
1964 if (rc.catalog == NULL) {
1965 ua->error_msg(_("Catalog \"%s\" not found\n"), rc.catalog_name);
1968 if (!acl_access_ok(ua, Catalog_ACL, rc.catalog->name())) {
1969 ua->error_msg(_("No authorization. Catalog \"%s\".\n"), rc.catalog->name());
1973 Dmsg1(800, "Using catalog=%s\n", NPRT(rc.catalog_name));
1975 if (!get_job(ua, rc)) {
1979 if (!get_pool(ua, rc)) {
1983 if (!get_next_pool(ua, rc)) {
1987 if (!get_storage(ua, rc)) {
1992 if (!get_client(ua, rc)) {
1996 if (!get_fileset(ua, rc)) {
2000 if (rc.verify_job_name) {
2001 rc.verify_job = GetJobResWithName(rc.verify_job_name);
2002 if (!rc.verify_job) {
2003 ua->send_msg(_("Verify Job \"%s\" not found.\n"), rc.verify_job_name);
2004 rc.verify_job = select_job_resource(ua);
2006 } else if (!rc.verify_job) {
2007 rc.verify_job = rc.job->verify_job;
2010 if (rc.previous_job_name) {
2011 rc.previous_job = GetJobResWithName(rc.previous_job_name);
2012 if (!rc.previous_job) {
2013 ua->send_msg(_("Migration Job \"%s\" not found.\n"), rc.previous_job_name);
2014 rc.previous_job = select_job_resource(ua);
2017 rc.previous_job = rc.job->verify_job;