2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2015 Kern Sibbald
5 Copyright (C) 2001-2014 Free Software Foundation Europe e.V.
7 The original author of Bacula is Kern Sibbald, with contributions
8 from many others, a complete list can be found in the file AUTHORS.
10 You may use this file and others of this release according to the
11 license defined in the LICENSE file, which includes the Affero General
12 Public License, v3.0 ("AGPLv3") and some additional permissions and
13 terms pursuant to its AGPLv3 Section 7.
15 This notice must be preserved when any source code is
16 conveyed and/or propagated.
18 Bacula(R) is a registered trademark of Kern Sibbald.
22 * Bacula Director -- Run Command
24 * Kern Sibbald, December MMI
31 const char *get_command(int index);
35 char *job_name, *level_name, *jid, *store_name, *pool_name;
36 char *where, *fileset_name, *client_name, *bootstrap, *regexwhere;
37 char *restore_client_name, *comment, *media_type, *next_pool_name;
39 char *when, *verify_job_name, *catalog_name;
40 char *previous_job_name;
43 const char *verify_list;
67 int ignoreduplicatecheck;
68 bool ignoreduplicatecheck_set;
70 run_ctx() { memset(this, 0, sizeof(run_ctx));
71 store = new USTORE; };
80 /* Forward referenced subroutines */
81 static void select_job_level(UAContext *ua, JCR *jcr);
82 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job,
83 const char *verify_list, char *jid, const char *replace,
85 static void select_where_regexp(UAContext *ua, JCR *jcr);
86 static bool scan_run_command_line_arguments(UAContext *ua, run_ctx &rc);
87 static bool set_run_context_in_jcr(UAContext *ua, JCR *jcr, run_ctx &rc);
88 static int modify_job_parameters(UAContext *ua, JCR *jcr, run_ctx &rc);
89 static JobId_t start_job(UAContext *ua, JCR *jcr, run_ctx &rc);
91 /* Imported variables */
92 extern struct s_kw ReplaceOptions[];
95 * For Backup and Verify Jobs
96 * run [job=]<job-name> level=<level-name>
101 * Returns: 0 on error
105 int run_cmd(UAContext *ua, const char *cmd)
111 if (!open_client_db(ua)) {
115 if (!scan_run_command_line_arguments(ua, rc)) {
119 if (find_arg(ua, NT_("fdcalled")) > 0) {
120 jcr->file_bsock = dup_bsock(ua->UA_sock);
126 * Create JCR to run job. NOTE!!! after this point, free_jcr()
130 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
131 set_jcr_defaults(jcr, rc.job);
132 jcr->unlink_bsr = ua->jcr->unlink_bsr; /* copy unlink flag from caller */
133 ua->jcr->unlink_bsr = false;
135 /* Transfer JobIds to new restore Job */
136 if (ua->jcr->JobIds) {
137 jcr->JobIds = ua->jcr->JobIds;
138 ua->jcr->JobIds = NULL;
140 /* Transfer VSS component info */
141 if (ua->jcr->component_fname) {
142 jcr->component_fname = ua->jcr->component_fname;
143 ua->jcr->component_fname = NULL;
144 jcr->component_fd = ua->jcr->component_fd;
145 ua->jcr->component_fd = NULL;
148 if (!set_run_context_in_jcr(ua, jcr, rc)) {
149 break; /* error get out of while loop */
153 /* Run without prompting? */
154 if (ua->batch || find_arg(ua, NT_("yes")) > 0) {
155 return start_job(ua, jcr, rc);
159 * Prompt User to see if all run job parameters are correct, and
160 * allow him to modify them.
162 if (!display_job_parameters(ua, jcr, rc.job, rc.verify_list, rc.jid, rc.replace,
164 break; /* error get out of while loop */
167 if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
168 break; /* error get out of while loop */
171 if (strncasecmp(ua->cmd, ".mod ", 5) == 0 ||
172 (strncasecmp(ua->cmd, "mod ", 4) == 0 && strlen(ua->cmd) > 6)) {
175 if (!scan_run_command_line_arguments(ua, rc)) {
176 break; /* error get out of while loop */
178 continue; /* another round with while loop */
181 /* Allow the user to modify the settings */
182 status = modify_job_parameters(ua, jcr, rc);
184 continue; /* another round with while loop */
186 if (status == -1) { /* error */
187 break; /* error get out of while loop */
190 if (ua->cmd[0] == 0 || strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
191 return start_job(ua, jcr, rc);
193 if (strncasecmp(ua->cmd, _("no"), strlen(ua->cmd)) == 0) {
194 break; /* get out of while loop */
196 ua->send_msg(_("\nBad response: %s. You must answer yes, mod, or no.\n\n"), ua->cmd);
200 ua->send_msg(_("Job not run.\n"));
201 if (ua->jcr->component_fd) {
202 fclose(ua->jcr->component_fd);
203 ua->jcr->component_fd = NULL;
205 if (ua->jcr->component_fname) {
206 unlink(ua->jcr->component_fname);
207 free_and_null_pool_memory(ua->jcr->component_fname);
210 if (jcr->component_fd) {
211 fclose(jcr->component_fd);
212 jcr->component_fd = NULL;
214 if (jcr->component_fname) {
215 unlink(jcr->component_fname);
216 free_and_null_pool_memory(jcr->component_fname);
220 return 0; /* do not run */
223 static JobId_t start_job(UAContext *ua, JCR *jcr, run_ctx &rc)
227 if (rc.jr.JobStatus == JS_Incomplete) {
228 Dmsg1(100, "Ressuming JobId=%d\n", rc.jr.JobId);
229 JobId = resume_job(jcr, &rc.jr);
231 Dmsg1(100, "Starting JobId=%d\n", rc.jr.JobId);
232 JobId = run_job(jcr);
234 Dmsg4(100, "JobId=%u NewJobId=%d pool=%s priority=%d\n", (int)jcr->JobId,
235 JobId, jcr->pool->name(), jcr->JobPriority);
236 free_jcr(jcr); /* release jcr */
238 ua->error_msg(_("Job failed.\n"));
241 ua->send_msg(_("Job queued. JobId=%s\n"), edit_int64(JobId, ed1));
247 * If no job_name defined in the run context, ask
249 * Then put the job resource in the run context and
250 * check the access rights.
252 static bool get_job(UAContext *ua, run_ctx &rc)
256 rc.job = GetJobResWithName(rc.job_name);
258 if (*rc.job_name != 0) {
259 ua->send_msg(_("Job \"%s\" not found\n"), rc.job_name);
261 rc.job = select_job_resource(ua);
263 Dmsg1(100, "Found job=%s\n", rc.job_name);
265 } else if (!rc.job) {
266 ua->send_msg(_("A job name must be specified.\n"));
267 rc.job = select_job_resource(ua);
271 } else if (!acl_access_ok(ua, Job_ACL, rc.job->name())) {
272 ua->error_msg( _("No authorization. Job \"%s\".\n"), rc.job->name());
279 * If no pool_name defined in the run context, ask
281 * Then put the pool resource in the run context and
282 * check the access rights.
284 static bool get_pool(UAContext *ua, run_ctx &rc)
287 rc.pool = GetPoolResWithName(rc.pool_name);
289 if (*rc.pool_name != 0) {
290 ua->warning_msg(_("Pool \"%s\" not found.\n"), rc.pool_name);
292 rc.pool = select_pool_resource(ua);
294 } else if (!rc.pool) {
295 rc.pool = rc.job->pool; /* use default */
299 } else if (!acl_access_ok(ua, Pool_ACL, rc.pool->name())) {
300 ua->error_msg(_("No authorization. Pool \"%s\".\n"), rc.pool->name());
303 Dmsg1(100, "Using Pool=%s\n", rc.pool->name());
307 static bool get_next_pool(UAContext *ua, run_ctx &rc)
309 if (rc.next_pool_name) {
310 Dmsg1(100, "Have next pool=%s\n", rc.next_pool_name);
311 rc.next_pool = GetPoolResWithName(rc.next_pool_name);
313 if (*rc.next_pool_name != 0) {
314 ua->warning_msg(_("NextPool \"%s\" not found.\n"), rc.next_pool_name);
316 rc.next_pool = select_pool_resource(ua);
319 /* NextPool can come from Job resource NextPool or Pool resource NextPool */
321 if (rc.job->next_pool) {
322 rc.next_pool = rc.job->next_pool;
324 rc.next_pool = rc.pool->NextPool; /* use default */
327 if (rc.next_pool && !acl_access_ok(ua, Pool_ACL, rc.next_pool->name())) {
328 ua->error_msg(_("No authorization. NextPool \"%s\".\n"), rc.next_pool->name());
332 Dmsg1(100, "Using NextPool=%s\n", NPRT(rc.next_pool->name()));
339 * Fill in client data according to what is setup
340 * in the run context, and make sure the user
341 * has authorized access to it.
343 static bool get_client(UAContext *ua, run_ctx &rc)
345 if (rc.client_name) {
346 rc.client = GetClientResWithName(rc.client_name);
348 if (*rc.client_name != 0) {
349 ua->warning_msg(_("Client \"%s\" not found.\n"), rc.client_name);
351 rc.client = select_client_resource(ua);
353 } else if (!rc.client) {
354 rc.client = rc.job->client; /* use default */
358 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
359 ua->error_msg(_("No authorization. Client \"%s\".\n"),
363 Dmsg1(800, "Using client=%s\n", rc.client->name());
365 if (rc.restore_client_name) {
366 rc.client = GetClientResWithName(rc.restore_client_name);
368 if (*rc.restore_client_name != 0) {
369 ua->warning_msg(_("Restore Client \"%s\" not found.\n"), rc.restore_client_name);
371 rc.client = select_client_resource(ua);
373 } else if (!rc.client) {
374 rc.client = rc.job->client; /* use default */
378 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
379 ua->error_msg(_("No authorization. Client \"%s\".\n"),
383 Dmsg1(800, "Using restore client=%s\n", rc.client->name());
389 * Fill in fileset data according to what is setup
390 * in the run context, and make sure the user
391 * has authorized access to it.
393 static bool get_fileset(UAContext *ua, run_ctx &rc)
395 if (rc.fileset_name) {
396 rc.fileset = GetFileSetResWithName(rc.fileset_name);
398 ua->send_msg(_("FileSet \"%s\" not found.\n"), rc.fileset_name);
399 rc.fileset = select_fileset_resource(ua);
401 } else if (!rc.fileset) {
402 rc.fileset = rc.job->fileset; /* use default */
406 } else if (!acl_access_ok(ua, FileSet_ACL, rc.fileset->name())) {
407 ua->send_msg(_("No authorization. FileSet \"%s\".\n"),
415 * Fill in storage data according to what is setup
416 * in the run context, and make sure the user
417 * has authorized access to it.
419 static bool get_storage(UAContext *ua, run_ctx &rc)
422 rc.store->store = GetStoreResWithName(rc.store_name);
423 pm_strcpy(rc.store->store_source, _("command line"));
424 if (!rc.store->store) {
425 if (*rc.store_name != 0) {
426 ua->warning_msg(_("Storage \"%s\" not found.\n"), rc.store_name);
428 rc.store->store = select_storage_resource(ua);
429 pm_strcpy(rc.store->store_source, _("user selection"));
431 } else if (!rc.store->store) {
432 get_job_storage(rc.store, rc.job, NULL); /* use default */
434 if (!rc.store->store) {
435 ua->error_msg(_("No storage specified.\n"));
437 } else if (!acl_access_ok(ua, Storage_ACL, rc.store->store->name())) {
438 ua->error_msg(_("No authorization. Storage \"%s\".\n"),
439 rc.store->store->name());
442 Dmsg1(800, "Using storage=%s\n", rc.store->store->name());
447 * Get and pass back a list of Jobids in rc.jid
449 static bool get_jobid_list(UAContext *ua, sellist &sl, run_ctx &rc)
456 memset(&jr, 0, sizeof(jr));
458 /* See if any JobId is specified */
459 if ((i=find_arg(ua, "jobid")) >= 0) {
460 rc.jid = ua->argv[i];
462 ua->send_msg(_("No JobId specified.\n"));
465 if (!sl.set_string(ua->argv[i], true)) {
466 ua->send_msg("%s", sl.get_errmsg());
472 /* No JobId list give, so see if he specified a Job */
473 if ((i=find_arg(ua, "job")) >= 0) {
474 rc.job_name = ua->argv[i];
475 if (!get_job(ua, rc)) {
476 ua->send_msg(_("Invalid or no Job name specified.\n"));
480 jr.limit = 100; /* max 100 records */
482 bstrncpy(jr.Name, rc.job_name, sizeof(jr.Name));
486 jr.JobStatus = rc.jr.JobStatus;
487 Dmsg2(100, "JobStatus=%d JobName=%s\n", jr.JobStatus, jr.Name);
488 /* rc.JobIds is alist of all records found and printed */
489 rc.JobIds = db_list_job_records(ua->jcr, ua->db, &jr, prtit, ua, INCOMPLETE_JOBS);
490 if (!rc.JobIds || rc.JobIds->size()==0 ||
491 !get_selection_list(ua, sl, _("Enter the JobId list to select: "), false)) {
494 Dmsg1(100, "list=%s\n", sl.get_list());
496 * Make sure each item entered is in the JobIds list
498 while ( (JobId = sl.next()) > 0) {
499 foreach_alist(pJobId, rc.JobIds) {
500 if (JobId == str_to_int64(pJobId)) {
507 ua->error_msg(_("JobId=%d entered is not in the list.\n"), JobId);
511 sl.begin(); /* reset to walk list again */
516 static bool get_jobid_from_list(UAContext *ua, sellist &sl, run_ctx &rc)
523 if ((JobId = sl.next()) < 0) {
524 Dmsg1(100, "sl.next()=%d\n", JobId);
528 rc.jr.JobId = rc.JobId = JobId;
529 Dmsg1(100, "Next JobId=%d\n", rc.JobId);
530 if (!db_get_job_record(ua->jcr, ua->db, &rc.jr)) {
531 ua->error_msg(_("Could not get job record for selected JobId=%d. ERR=%s"),
532 rc.JobId, db_strerror(ua->db));
535 Dmsg3(100, "Job=%s JobId=%d JobStatus=%c\n", rc.jr.Name, rc.jr.JobId,
537 rc.job_name = rc.jr.Name;
538 if (!get_job(ua, rc)) {
541 if (!get_pool(ua, rc)) {
544 get_job_storage(rc.store, rc.job, NULL);
545 rc.client_name = rc.job->client->hdr.name;
546 if (!get_client(ua, rc)) {
549 if (!get_fileset(ua, rc)) {
552 if (!get_storage(ua, rc)) {
559 * Restart Canceled, Failed, or Incomplete Jobs
561 * Returns: 0 on error
565 int restart_cmd(UAContext *ua, const char *cmd)
573 const char *status_name;
577 {"Incomplete", JS_Incomplete},
578 {"Canceled", JS_Canceled},
579 {"Failed", JS_FatalError},
584 if (!open_client_db(ua)) {
589 for (i=1; i<ua->argc; i++) {
590 for (j=0; kw[j].status_name; j++) {
591 if (strcasecmp(ua->argk[i], kw[j].status_name) == 0) {
592 rc.jr.JobStatus = kw[j].job_status;
598 if (!got_kw) { /* Must prompt user */
599 start_prompt(ua, _("You have the following choices:\n"));
600 for (i=0; kw[i].status_name; i++) {
601 add_prompt(ua, kw[i].status_name);
603 i = do_prompt(ua, NULL, _("Select termination code: "), NULL, 0);
607 rc.jr.JobStatus = kw[i].job_status;
610 /* type now has what job termination code we want to look at */
611 Dmsg1(100, "Termination code=%c\n", rc.jr.JobStatus);
613 /* Get a list of JobIds to restore */
614 if (!get_jobid_list(ua, sl, rc)) {
616 rc.JobIds->destroy();
620 Dmsg1(100, "list=%s\n", sl.get_list());
622 while (get_jobid_from_list(ua, sl, rc)) {
624 * Create JCR to run job. NOTE!!! after this point, free_jcr()
628 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
629 set_jcr_defaults(jcr, rc.job);
630 jcr->unlink_bsr = ua->jcr->unlink_bsr; /* copy unlink flag from caller */
631 ua->jcr->unlink_bsr = false;
634 if (!set_run_context_in_jcr(ua, jcr, rc)) {
637 start_job(ua, jcr, rc);
645 rc.JobIds->destroy();
647 return 0; /* do not run */
650 int modify_job_parameters(UAContext *ua, JCR *jcr, run_ctx &rc)
655 * At user request modify parameters of job to be run.
657 if (ua->cmd[0] != 0 && strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0){
660 start_prompt(ua, _("Parameters to modify:\n"));
661 add_prompt(ua, _("Level")); /* 0 */
662 add_prompt(ua, _("Storage")); /* 1 */
663 add_prompt(ua, _("Job")); /* 2 */
664 add_prompt(ua, _("FileSet")); /* 3 */
665 if (jcr->getJobType() == JT_RESTORE) {
666 add_prompt(ua, _("Restore Client")); /* 4 */
668 add_prompt(ua, _("Client")); /* 4 */
670 add_prompt(ua, _("When")); /* 5 */
671 add_prompt(ua, _("Priority")); /* 6 */
672 if (jcr->getJobType() == JT_BACKUP ||
673 jcr->getJobType() == JT_COPY ||
674 jcr->getJobType() == JT_MIGRATE ||
675 jcr->getJobType() == JT_VERIFY) {
676 add_prompt(ua, _("Pool")); /* 7 */
677 if ((jcr->getJobType() == JT_BACKUP && /* Virtual full */
678 jcr->is_JobLevel(L_VIRTUAL_FULL)) ||
679 jcr->getJobType() == JT_COPY ||
680 jcr->getJobType() == JT_MIGRATE) {
681 add_prompt(ua, _("NextPool")); /* 8 */
682 } else if (jcr->getJobType() == JT_VERIFY) {
683 add_prompt(ua, _("Verify Job")); /* 8 */
685 } else if (jcr->getJobType() == JT_RESTORE) {
686 add_prompt(ua, _("Bootstrap")); /* 7 */
687 add_prompt(ua, _("Where")); /* 8 */
688 add_prompt(ua, _("File Relocation"));/* 9 */
689 add_prompt(ua, _("Replace")); /* 10 */
690 add_prompt(ua, _("JobId")); /* 11 */
692 if (jcr->getJobType() == JT_BACKUP || jcr->getJobType() == JT_RESTORE) {
693 add_prompt(ua, _("Plugin Options")); /* 12 */
695 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
698 select_job_level(ua, jcr);
702 rc.store->store = select_storage_resource(ua);
703 if (rc.store->store) {
704 pm_strcpy(rc.store->store_source, _("user selection"));
705 set_rwstorage(jcr, rc.store);
711 rc.job = select_job_resource(ua);
714 set_jcr_defaults(jcr, rc.job);
720 rc.fileset = select_fileset_resource(ua);
722 jcr->fileset = rc.fileset;
728 rc.client = select_client_resource(ua);
730 jcr->client = rc.client;
736 if (!get_cmd(ua, _("Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now): "))) {
739 if (ua->cmd[0] == 0) {
740 jcr->sched_time = time(NULL);
742 jcr->sched_time = str_to_utime(ua->cmd);
743 if (jcr->sched_time == 0) {
744 ua->send_msg(_("Invalid time, using current time.\n"));
745 jcr->sched_time = time(NULL);
751 if (!get_pint(ua, _("Enter new Priority: "))) {
754 if (ua->pint32_val == 0) {
755 ua->send_msg(_("Priority must be a positive integer.\n"));
757 jcr->JobPriority = ua->pint32_val;
761 /* Pool or Bootstrap depending on JobType */
762 if (jcr->getJobType() == JT_BACKUP ||
763 jcr->getJobType() == JT_COPY ||
764 jcr->getJobType() == JT_MIGRATE ||
765 jcr->getJobType() == JT_VERIFY) { /* Pool */
766 rc.pool = select_pool_resource(ua);
769 Dmsg1(100, "Set new pool=%s\n", jcr->pool->name());
776 if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
779 if (jcr->RestoreBootstrap) {
780 free(jcr->RestoreBootstrap);
781 jcr->RestoreBootstrap = NULL;
783 if (ua->cmd[0] != 0) {
784 jcr->RestoreBootstrap = bstrdup(ua->cmd);
785 fd = fopen(jcr->RestoreBootstrap, "rb");
788 ua->send_msg(_("Warning cannot open %s: ERR=%s\n"),
789 jcr->RestoreBootstrap, be.bstrerror());
790 free(jcr->RestoreBootstrap);
791 jcr->RestoreBootstrap = NULL;
798 /* Specify Next Pool */
799 if ((jcr->getJobType() == JT_BACKUP && /* Virtual full */
800 jcr->is_JobLevel(L_VIRTUAL_FULL)) ||
801 jcr->getJobType() == JT_COPY ||
802 jcr->getJobType() == JT_MIGRATE) {
803 rc.next_pool = select_pool_resource(ua);
805 jcr->next_pool = rc.next_pool;
810 if (jcr->getJobType() == JT_VERIFY) {
811 rc.verify_job = select_job_resource(ua);
813 jcr->verify_job = rc.verify_job;
818 if (!get_cmd(ua, _("Please enter the full path prefix for restore (/ for none): "))) {
821 if (jcr->RegexWhere) { /* cannot use regexwhere and where */
822 free(jcr->RegexWhere);
823 jcr->RegexWhere = NULL;
829 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
832 jcr->where = bstrdup(ua->cmd);
835 /* File relocation */
836 select_where_regexp(ua, jcr);
840 start_prompt(ua, _("Replace:\n"));
841 for (i=0; ReplaceOptions[i].name; i++) {
842 add_prompt(ua, ReplaceOptions[i].name);
844 opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
846 rc.replace = ReplaceOptions[opt].name;
847 jcr->replace = ReplaceOptions[opt].token;
852 rc.jid = NULL; /* force reprompt */
853 jcr->RestoreJobId = 0;
854 if (jcr->RestoreBootstrap) {
855 ua->send_msg(_("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
860 //generate_plugin_event(jcr, bEventJobConfig, &rc);
861 if (!get_cmd(ua, _("Please Plugin Options string: "))) {
864 if (jcr->plugin_options) {
865 free(jcr->plugin_options);
866 jcr->plugin_options = NULL;
868 jcr->plugin_options = bstrdup(ua->cmd);
870 case -1: /* error or cancel */
886 * Put the run context that we have at this point into the JCR.
887 * That allows us to re-ask for the run context.
888 * This subroutine can be called multiple times, so it
889 * must keep any prior settings.
891 static bool set_run_context_in_jcr(UAContext *ua, JCR *jcr, run_ctx &rc)
895 jcr->verify_job = rc.verify_job;
896 jcr->previous_job = rc.previous_job;
898 jcr->next_pool = rc.next_pool;
900 jcr->cmdline_next_pool_override = true;
903 pm_strcpy(jcr->pool_source, _("Command input"));
904 } else if (jcr->pool != jcr->job->pool) {
905 pm_strcpy(jcr->pool_source, _("User input"));
907 if (rc.next_pool_name) {
908 pm_strcpy(jcr->next_pool_source, _("Command input"));
909 } else if (jcr->next_pool == jcr->job->next_pool) {
910 pm_strcpy(jcr->next_pool_source, _("Job resource"));
911 } else if (jcr->next_pool != jcr->pool->NextPool) {
912 pm_strcpy(jcr->next_pool_source, _("User input"));
915 set_rwstorage(jcr, rc.store);
916 jcr->client = rc.client;
918 pm_strcpy(jcr->client_name, rc.client->name());
920 pm_strcpy(jcr->client_name, "**Dummy**");
923 if (!jcr->media_type) {
924 jcr->media_type = get_pool_memory(PM_NAME);
926 pm_strcpy(jcr->media_type, rc.media_type);
928 jcr->fileset = rc.fileset;
929 jcr->ExpectedFiles = rc.files;
931 jcr->catalog = rc.catalog;
932 pm_strcpy(jcr->catalog_source, _("User input"));
935 pm_strcpy(jcr->comment, rc.comment);
941 jcr->where = bstrdup(rc.where);
946 if (jcr->RegexWhere) {
947 free(jcr->RegexWhere);
949 jcr->RegexWhere = bstrdup(rc.regexwhere);
950 rc.regexwhere = NULL;
954 jcr->sched_time = str_to_utime(rc.when);
955 if (jcr->sched_time == 0) {
956 ua->send_msg(_("Invalid time, using current time.\n"));
957 jcr->sched_time = time(NULL);
963 if (jcr->RestoreBootstrap) {
964 free(jcr->RestoreBootstrap);
966 jcr->RestoreBootstrap = bstrdup(rc.bootstrap);
970 if (rc.plugin_options) {
971 if (jcr->plugin_options) {
972 free(jcr->plugin_options);
974 jcr->plugin_options = bstrdup(rc.plugin_options);
975 rc.plugin_options = NULL;
980 for (i=0; ReplaceOptions[i].name; i++) {
981 if (strcasecmp(rc.replace, ReplaceOptions[i].name) == 0) {
982 jcr->replace = ReplaceOptions[i].token;
986 ua->send_msg(_("Invalid replace option: %s\n"), rc.replace);
989 } else if (rc.job->replace) {
990 jcr->replace = rc.job->replace;
992 jcr->replace = REPLACE_ALWAYS;
996 /* Set Snapshot Retention (Job <- Client) */
998 jcr->snapshot_retention = jcr->client->SnapRetention;
1000 if (jcr->job && jcr->job->SnapRetention > 0) {
1001 jcr->snapshot_retention = jcr->job->SnapRetention;
1005 jcr->JobPriority = rc.Priority;
1011 jcr->stime = get_pool_memory(PM_MESSAGE);
1013 pm_strcpy(jcr->stime, rc.since);
1018 jcr->cloned = rc.cloned;
1022 /* If pool changed, update migration write storage */
1023 if (jcr->is_JobType(JT_MIGRATE) || jcr->is_JobType(JT_COPY) ||
1024 (jcr->is_JobType(JT_BACKUP) && jcr->is_JobLevel(L_VIRTUAL_FULL))) {
1025 if (!set_mac_wstorage(ua, jcr, rc.pool, rc.next_pool,
1026 jcr->next_pool_source)) {
1030 rc.replace = ReplaceOptions[0].name;
1031 for (i=0; ReplaceOptions[i].name; i++) {
1032 if ((int)ReplaceOptions[i].token == jcr->replace) {
1033 rc.replace = ReplaceOptions[i].name;
1036 if (rc.level_name) {
1037 if (!get_level_from_name(jcr, rc.level_name)) {
1038 ua->send_msg(_("Level \"%s\" not valid.\n"), rc.level_name);
1041 rc.level_name = NULL;
1044 /* Note, this is also MigrateJobId and a VerifyJobId */
1045 jcr->RestoreJobId = str_to_int64(rc.jid);
1047 /* Copy also this parameter for VirtualFull in jcr->JobIds */
1049 jcr->JobIds = get_pool_memory(PM_FNAME);
1051 pm_strcpy(jcr->JobIds, rc.jid);
1052 jcr->use_all_JobIds = rc.alljobid; /* if we found the "alljobid=" kw */
1053 rc.alljobid = false;
1057 /* Some options are not available through the menu
1058 * TODO: Add an advanced menu?
1060 if (rc.spool_data_set) {
1061 jcr->spool_data = rc.spool_data;
1064 if (rc.accurate_set) {
1065 jcr->accurate = rc.accurate;
1068 /* Used by migration jobs that can have the same name,
1069 * but can run at the same time
1071 if (rc.ignoreduplicatecheck_set) {
1072 jcr->IgnoreDuplicateJobChecking = rc.ignoreduplicatecheck;
1078 static void select_where_regexp(UAContext *ua, JCR *jcr)
1081 char *strip_prefix, *add_prefix, *add_suffix, *rwhere;
1082 strip_prefix = add_suffix = rwhere = add_prefix = NULL;
1085 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s\n"),
1086 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix));
1088 start_prompt(ua, _("This will replace your current Where value\n"));
1089 add_prompt(ua, _("Strip prefix")); /* 0 */
1090 add_prompt(ua, _("Add prefix")); /* 1 */
1091 add_prompt(ua, _("Add file suffix")); /* 2 */
1092 add_prompt(ua, _("Enter a regexp")); /* 3 */
1093 add_prompt(ua, _("Test filename manipulation")); /* 4 */
1094 add_prompt(ua, _("Use this ?")); /* 5 */
1096 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
1099 if (get_cmd(ua, _("Please enter the path prefix to strip: "))) {
1100 if (strip_prefix) bfree(strip_prefix);
1101 strip_prefix = bstrdup(ua->cmd);
1107 if (get_cmd(ua, _("Please enter the path prefix to add (/ for none): "))) {
1108 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
1112 if (add_prefix) bfree(add_prefix);
1113 add_prefix = bstrdup(ua->cmd);
1118 if (get_cmd(ua, _("Please enter the file suffix to add: "))) {
1119 if (add_suffix) bfree(add_suffix);
1120 add_suffix = bstrdup(ua->cmd);
1125 if (get_cmd(ua, _("Please enter a valid regexp (!from!to!): "))) {
1126 if (rwhere) bfree(rwhere);
1127 rwhere = bstrdup(ua->cmd);
1136 if (rwhere && rwhere[0] != '\0') {
1137 regs = get_bregexps(rwhere);
1138 ua->send_msg(_("regexwhere=%s\n"), NPRT(rwhere));
1140 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
1141 regexp = (char *) bmalloc (len * sizeof(char));
1142 bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix);
1143 regs = get_bregexps(regexp);
1144 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s result=%s\n"),
1145 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix), NPRT(regexp));
1151 ua->send_msg(_("Cannot use your regexp\n"));
1154 ua->send_msg(_("Enter a period (.) to stop this test\n"));
1155 while (get_cmd(ua, _("Please enter filename to test: "))) {
1156 apply_bregexps(ua->cmd, regs, &result);
1157 ua->send_msg(_("%s -> %s\n"), ua->cmd, result);
1159 free_bregexps(regs);
1166 case -1: /* error or cancel */
1172 /* replace the existing where */
1178 /* replace the existing regexwhere */
1179 if (jcr->RegexWhere) {
1180 bfree(jcr->RegexWhere);
1181 jcr->RegexWhere = NULL;
1185 jcr->RegexWhere = bstrdup(rwhere);
1186 } else if (strip_prefix || add_prefix || add_suffix) {
1187 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
1188 jcr->RegexWhere = (char *) bmalloc(len*sizeof(char));
1189 bregexp_build_where(jcr->RegexWhere, len, strip_prefix, add_prefix, add_suffix);
1192 regs = get_bregexps(jcr->RegexWhere);
1194 free_bregexps(regs);
1197 if (jcr->RegexWhere) {
1198 bfree(jcr->RegexWhere);
1199 jcr->RegexWhere = NULL;
1201 ua->send_msg(_("Cannot use your regexp.\n"));
1205 if (strip_prefix) bfree(strip_prefix);
1206 if (add_prefix) bfree(add_prefix);
1207 if (add_suffix) bfree(add_suffix);
1208 if (rwhere) bfree(rwhere);
1211 static void select_job_level(UAContext *ua, JCR *jcr)
1213 if (jcr->getJobType() == JT_BACKUP) {
1214 start_prompt(ua, _("Levels:\n"));
1215 // add_prompt(ua, _("Base"));
1216 add_prompt(ua, _("Full"));
1217 add_prompt(ua, _("Incremental"));
1218 add_prompt(ua, _("Differential"));
1219 add_prompt(ua, _("Since"));
1220 add_prompt(ua, _("VirtualFull"));
1221 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
1223 // jcr->JobLevel = L_BASE;
1226 jcr->setJobLevel(L_FULL);
1229 jcr->setJobLevel(L_INCREMENTAL);
1232 jcr->setJobLevel(L_DIFFERENTIAL);
1235 jcr->setJobLevel(L_SINCE);
1238 jcr->setJobLevel(L_VIRTUAL_FULL);
1243 } else if (jcr->getJobType() == JT_VERIFY) {
1244 start_prompt(ua, _("Levels:\n"));
1245 add_prompt(ua, _("Initialize Catalog"));
1246 add_prompt(ua, _("Verify Catalog"));
1247 add_prompt(ua, _("Verify Volume to Catalog"));
1248 add_prompt(ua, _("Verify Disk to Catalog"));
1249 add_prompt(ua, _("Verify Volume Data"));
1250 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
1252 jcr->setJobLevel(L_VERIFY_INIT);
1255 jcr->setJobLevel(L_VERIFY_CATALOG);
1258 jcr->setJobLevel(L_VERIFY_VOLUME_TO_CATALOG);
1261 jcr->setJobLevel(L_VERIFY_DISK_TO_CATALOG);
1264 jcr->setJobLevel(L_VERIFY_DATA);
1270 ua->warning_msg(_("Level not appropriate for this Job. Cannot be changed.\n"));
1275 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char *verify_list,
1276 char *jid, const char *replace, char *client_name)
1279 char dt[MAX_TIME_LENGTH];
1281 Dmsg1(800, "JobType=%c\n", jcr->getJobType());
1282 switch (jcr->getJobType()) {
1285 ua->signal(BNET_RUN_CMD);
1286 ua->send_msg("Type: Admin\n"
1287 "Title: Run Admin Job\n"
1295 jcr->fileset->name(),
1296 NPRT(jcr->client->name()),
1297 jcr->wstore?jcr->wstore->name():"*None*",
1298 bstrutime(dt, sizeof(dt), jcr->sched_time),
1301 ua->send_msg(_("Run Admin Job\n"
1309 jcr->fileset->name(),
1310 NPRT(jcr->client->name()),
1311 jcr->wstore?jcr->wstore->name():"*None*",
1312 bstrutime(dt, sizeof(dt), jcr->sched_time),
1315 jcr->setJobLevel(L_FULL);
1319 char next_pool[MAX_NAME_LENGTH + 50];
1321 if (jcr->getJobType() == JT_BACKUP) {
1323 ua->signal(BNET_RUN_CMD);
1324 if (jcr->is_JobLevel(L_VIRTUAL_FULL)) {
1325 bsnprintf(next_pool, sizeof(next_pool), "NextPool: %s\n",
1326 jcr->next_pool ? jcr->next_pool->name() : "*None*");
1328 ua->send_msg("Type: Backup\n"
1329 "Title: Run Backup Job\n"
1341 level_to_str(jcr->getJobLevel()),
1342 jcr->client->name(),
1343 jcr->fileset->name(),
1344 NPRT(jcr->pool->name()),
1346 jcr->wstore?jcr->wstore->name():"*None*",
1347 bstrutime(dt, sizeof(dt), jcr->sched_time),
1349 jcr->plugin_options?"Plugin Options: ":"",
1350 jcr->plugin_options?jcr->plugin_options:"",
1351 jcr->plugin_options?"\n":"");
1353 if (jcr->is_JobLevel(L_VIRTUAL_FULL)) {
1354 bsnprintf(next_pool, sizeof(next_pool),
1355 "NextPool: %s (From %s)\n",
1356 jcr->next_pool ? jcr->next_pool->name() : "*None*",
1357 jcr->next_pool_source);
1359 ua->send_msg(_("Run Backup job\n"
1364 "Pool: %s (From %s)\n"
1366 "Storage: %s (From %s)\n"
1371 level_to_str(jcr->getJobLevel()),
1372 jcr->client->name(),
1373 jcr->fileset->name(),
1374 NPRT(jcr->pool->name()), jcr->pool_source,
1376 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
1377 bstrutime(dt, sizeof(dt), jcr->sched_time),
1379 jcr->plugin_options?"Plugin Options: ":"",
1380 jcr->plugin_options?jcr->plugin_options:"",
1381 jcr->plugin_options?"\n":"");
1383 } else { /* JT_VERIFY */
1386 if (jcr->verify_job) {
1387 Name = jcr->verify_job->name();
1388 } else if (jcr->RestoreJobId) { /* Display job name if jobid requested */
1389 memset(&jr, 0, sizeof(jr));
1390 jr.JobId = jcr->RestoreJobId;
1391 if (!db_get_job_record(jcr, ua->db, &jr)) {
1392 ua->error_msg(_("Could not get job record for selected JobId. ERR=%s"),
1393 db_strerror(ua->db));
1401 verify_list = job->WriteVerifyList;
1407 ua->signal(BNET_RUN_CMD);
1408 ua->send_msg("Type: Verify\n"
1409 "Title: Run Verify Job\n"
1414 "Pool: %s (From %s)\n"
1415 "Storage: %s (From %s)\n"
1421 level_to_str(jcr->getJobLevel()),
1422 jcr->client->name(),
1423 jcr->fileset->name(),
1424 NPRT(jcr->pool->name()), jcr->pool_source,
1425 jcr->rstore->name(), jcr->rstore_source,
1428 bstrutime(dt, sizeof(dt), jcr->sched_time),
1431 ua->send_msg(_("Run Verify Job\n"
1436 "Pool: %s (From %s)\n"
1437 "Storage: %s (From %s)\n"
1443 level_to_str(jcr->getJobLevel()),
1444 jcr->client->name(),
1445 jcr->fileset->name(),
1446 NPRT(jcr->pool->name()), jcr->pool_source,
1447 jcr->rstore->name(), jcr->rstore_source,
1450 bstrutime(dt, sizeof(dt), jcr->sched_time),
1456 if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
1458 jcr->RestoreJobId = str_to_int64(jid);
1460 if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
1463 jcr->RestoreJobId = ua->int64_val;
1466 jcr->setJobLevel(L_FULL); /* default level */
1467 Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId);
1468 if (jcr->RestoreJobId == 0) {
1469 /* RegexWhere is take before RestoreWhere */
1470 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
1472 ua->signal(BNET_RUN_CMD);
1473 ua->send_msg("Type: Restore\n"
1474 "Title: Run Restore Job\n"
1480 "Backup Client: %s\n"
1481 "Restore Client: %s\n"
1486 "Plugin Options: %s\n",
1488 NPRT(jcr->RestoreBootstrap),
1489 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
1491 jcr->fileset->name(),
1493 jcr->client->name(),
1494 jcr->rstore->name(),
1495 bstrutime(dt, sizeof(dt), jcr->sched_time),
1496 jcr->catalog->name(),
1498 NPRTB(jcr->plugin_options));
1501 ua->send_msg(_("Run Restore job\n"
1507 "Backup Client: %s\n"
1508 "Restore Client: %s\n"
1513 "Plugin Options: %s\n"),
1515 NPRT(jcr->RestoreBootstrap),
1516 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
1518 jcr->fileset->name(),
1520 jcr->client->name(),
1521 jcr->rstore->name(),
1522 bstrutime(dt, sizeof(dt), jcr->sched_time),
1523 jcr->catalog->name(),
1525 NPRTB(jcr->plugin_options));
1529 ua->signal(BNET_RUN_CMD);
1530 ua->send_msg("Type: Restore\n"
1531 "Title: Run Restore job\n"
1537 "Backup Client: %s\n"
1538 "Restore Client: %s\n"
1543 "Plugin Options: %s\n",
1545 NPRT(jcr->RestoreBootstrap),
1546 jcr->where?jcr->where:NPRT(job->RestoreWhere),
1548 jcr->fileset->name(),
1550 jcr->client->name(),
1551 jcr->rstore->name(),
1552 bstrutime(dt, sizeof(dt), jcr->sched_time),
1553 jcr->catalog->name(),
1555 NPRTB(jcr->plugin_options));
1558 ua->send_msg(_("Run Restore job\n"
1564 "Backup Client: %s\n"
1565 "Restore Client: %s\n"
1570 "Plugin Options: %s\n"),
1572 NPRT(jcr->RestoreBootstrap),
1573 jcr->where?jcr->where:NPRT(job->RestoreWhere),
1575 jcr->fileset->name(),
1577 jcr->client->name(),
1578 jcr->rstore->name(),
1579 bstrutime(dt, sizeof(dt), jcr->sched_time),
1580 jcr->catalog->name(),
1582 NPRTB(jcr->plugin_options));
1587 /* ***FIXME*** This needs to be fixed for bat */
1588 if (ua->api) ua->signal(BNET_RUN_CMD);
1589 ua->send_msg(_("Run Restore job\n"
1593 NPRT(jcr->RestoreBootstrap));
1595 /* RegexWhere is take before RestoreWhere */
1596 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
1597 ua->send_msg(_("RegexWhere: %s\n"),
1598 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere);
1600 ua->send_msg(_("Where: %s\n"),
1601 jcr->where?jcr->where:NPRT(job->RestoreWhere));
1604 ua->send_msg(_("Replace: %s\n"
1611 "Plugin Options: %s\n"),
1613 jcr->client->name(),
1614 jcr->rstore->name(),
1615 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
1616 bstrutime(dt, sizeof(dt), jcr->sched_time),
1617 jcr->catalog->name(),
1619 NPRTB(jcr->plugin_options));
1625 jcr->setJobLevel(L_FULL); /* default level */
1627 ua->signal(BNET_RUN_CMD);
1628 if (jcr->getJobType() == JT_COPY) {
1629 prt_type = (char *)"Type: Copy\nTitle: Run Copy Job\n";
1631 prt_type = (char *)"Type: Migration\nTitle: Run Migration Job\n";
1640 "Read Storage: %s\n"
1641 "Write Storage: %s\n"
1648 NPRT(jcr->RestoreBootstrap),
1649 jcr->client->name(),
1650 jcr->fileset->name(),
1651 NPRT(jcr->pool->name()),
1652 jcr->next_pool?jcr->next_pool->name():"*None*",
1653 jcr->rstore->name(),
1654 jcr->wstore?jcr->wstore->name():"*None*",
1655 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
1656 bstrutime(dt, sizeof(dt), jcr->sched_time),
1657 jcr->catalog->name(),
1660 if (jcr->getJobType() == JT_COPY) {
1661 prt_type = _("Run Copy job\n");
1663 prt_type = _("Run Migration job\n");
1670 "Pool: %s (From %s)\n"
1671 "NextPool: %s (From %s)\n"
1672 "Read Storage: %s (From %s)\n"
1673 "Write Storage: %s (From %s)\n"
1680 NPRT(jcr->RestoreBootstrap),
1681 jcr->client->name(),
1682 jcr->fileset->name(),
1683 NPRT(jcr->pool->name()), jcr->pool_source,
1684 jcr->next_pool?jcr->next_pool->name():"*None*",
1685 NPRT(jcr->next_pool_source),
1686 jcr->rstore->name(), jcr->rstore_source,
1687 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
1688 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
1689 bstrutime(dt, sizeof(dt), jcr->sched_time),
1690 jcr->catalog->name(),
1695 ua->error_msg(_("Unknown Job Type=%d\n"), jcr->getJobType());
1702 static bool scan_run_command_line_arguments(UAContext *ua, run_ctx &rc)
1706 static const char *kw[] = { /* command line arguments */
1707 "alljobid", /* 0 Used in a switch() */
1715 "regexwhere", /* 8 where string as a bregexp */
1717 "bootstrap", /* 10 */
1720 "priority", /* 13 */
1721 "yes", /* 14 -- if you change this change YES_POS too */
1722 "verifyjob", /* 15 */
1723 "files", /* 16 number of files to restore */
1724 "catalog", /* 17 override catalog */
1725 "since", /* 18 since */
1726 "cloned", /* 19 cloned */
1727 "verifylist", /* 20 verify output list */
1728 "migrationjob", /* 21 migration job name */
1730 "backupclient", /* 23 */
1731 "restoreclient", /* 24 */
1732 "pluginoptions", /* 25 */
1733 "spooldata", /* 26 */
1735 "ignoreduplicatecheck", /* 28 */
1736 "accurate", /* 29 */
1738 "mediatype", /* 31 */
1739 "nextpool", /* 32 override next pool name */
1744 rc.catalog_name = NULL;
1746 rc.pool_name = NULL;
1747 rc.next_pool_name = NULL;
1748 rc.store_name = NULL;
1749 rc.client_name = NULL;
1750 rc.media_type = NULL;
1751 rc.restore_client_name = NULL;
1752 rc.fileset_name = NULL;
1753 rc.verify_job_name = NULL;
1754 rc.previous_job_name = NULL;
1755 rc.accurate_set = false;
1756 rc.spool_data_set = false;
1757 rc.ignoreduplicatecheck = false;
1759 rc.plugin_options = NULL;
1761 for (i=1; i<ua->argc; i++) {
1762 Dmsg2(800, "Doing arg %d = %s\n", i, ua->argk[i]);
1764 /* Keep looking until we find a good keyword */
1765 for (j=0; !kw_ok && kw[j]; j++) {
1766 if (strcasecmp(ua->argk[i], kw[j]) == 0) {
1767 /* Note, yes and run have no value, so do not fail */
1768 if (!ua->argv[i] && j != YES_POS /*yes*/) {
1769 ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]);
1772 Dmsg2(800, "Got j=%d keyword=%s\n", j, NPRT(kw[j]));
1774 case 0: /* alljobid */
1776 /* Fall through wanted */
1778 if (rc.jid && !rc.mod) {
1779 ua->send_msg(_("JobId specified twice.\n"));
1782 rc.jid = ua->argv[i];
1785 case 2: /* client */
1787 if (rc.client_name) {
1788 ua->send_msg(_("Client specified twice.\n"));
1791 rc.client_name = ua->argv[i];
1794 case 4: /* fileset */
1795 if (rc.fileset_name) {
1796 ua->send_msg(_("FileSet specified twice.\n"));
1799 rc.fileset_name = ua->argv[i];
1803 if (rc.level_name) {
1804 ua->send_msg(_("Level specified twice.\n"));
1807 rc.level_name = ua->argv[i];
1810 case 6: /* storage */
1812 if (rc.store_name) {
1813 ua->send_msg(_("Storage specified twice.\n"));
1816 rc.store_name = ua->argv[i];
1819 case 8: /* regexwhere */
1820 if ((rc.regexwhere || rc.where) && !rc.mod) {
1821 ua->send_msg(_("RegexWhere or Where specified twice.\n"));
1824 rc.regexwhere = ua->argv[i];
1825 if (!acl_access_ok(ua, Where_ACL, rc.regexwhere)) {
1826 ua->send_msg(_("No authorization for \"regexwhere\" specification.\n"));
1832 if ((rc.where || rc.regexwhere) && !rc.mod) {
1833 ua->send_msg(_("Where or RegexWhere specified twice.\n"));
1836 rc.where = ua->argv[i];
1837 if (!acl_access_ok(ua, Where_ACL, rc.where)) {
1838 ua->send_msg(_("No authoriztion for \"where\" specification.\n"));
1843 case 10: /* bootstrap */
1844 if (rc.bootstrap && !rc.mod) {
1845 ua->send_msg(_("Bootstrap specified twice.\n"));
1848 rc.bootstrap = ua->argv[i];
1851 case 11: /* replace */
1852 if (rc.replace && !rc.mod) {
1853 ua->send_msg(_("Replace specified twice.\n"));
1856 rc.replace = ua->argv[i];
1860 if (rc.when && !rc.mod) {
1861 ua->send_msg(_("When specified twice.\n"));
1864 rc.when = ua->argv[i];
1867 case 13: /* Priority */
1868 if (rc.Priority && !rc.mod) {
1869 ua->send_msg(_("Priority specified twice.\n"));
1872 rc.Priority = atoi(ua->argv[i]);
1873 if (rc.Priority <= 0) {
1874 ua->send_msg(_("Priority must be positive nonzero setting it to 10.\n"));
1882 case 15: /* Verify Job */
1883 if (rc.verify_job_name) {
1884 ua->send_msg(_("Verify Job specified twice.\n"));
1887 rc.verify_job_name = ua->argv[i];
1890 case 16: /* files */
1891 rc.files = atoi(ua->argv[i]);
1894 case 17: /* catalog */
1895 rc.catalog_name = ua->argv[i];
1898 case 18: /* since */
1899 rc.since = ua->argv[i];
1902 case 19: /* cloned */
1906 case 20: /* write verify list output */
1907 rc.verify_list = ua->argv[i];
1910 case 21: /* Migration Job */
1911 if (rc.previous_job_name) {
1912 ua->send_msg(_("Migration Job specified twice.\n"));
1915 rc.previous_job_name = ua->argv[i];
1920 ua->send_msg(_("Pool specified twice.\n"));
1923 rc.pool_name = ua->argv[i];
1926 case 23: /* backupclient */
1927 if (rc.client_name) {
1928 ua->send_msg(_("Client specified twice.\n"));
1931 rc.client_name = ua->argv[i];
1934 case 24: /* restoreclient */
1935 if (rc.restore_client_name && !rc.mod) {
1936 ua->send_msg(_("Restore Client specified twice.\n"));
1939 rc.restore_client_name = ua->argv[i];
1942 case 25: /* pluginoptions */
1943 ua->send_msg(_("Plugin Options not yet implemented.\n"));
1945 if (rc.plugin_options) {
1946 ua->send_msg(_("Plugin Options specified twice.\n"));
1949 rc.plugin_options = ua->argv[i];
1950 if (!acl_access_ok(ua, PluginOptions_ACL, rc.plugin_options)) {
1951 ua->send_msg(_("No authoriztion for \"PluginOptions\" specification.\n"));
1956 case 26: /* spooldata */
1957 if (rc.spool_data_set) {
1958 ua->send_msg(_("Spool flag specified twice.\n"));
1961 if (is_yesno(ua->argv[i], &rc.spool_data)) {
1962 rc.spool_data_set = true;
1965 ua->send_msg(_("Invalid spooldata flag.\n"));
1968 case 27: /* comment */
1969 rc.comment = ua->argv[i];
1972 case 28: /* ignoreduplicatecheck */
1973 if (rc.ignoreduplicatecheck_set) {
1974 ua->send_msg(_("IgnoreDuplicateCheck flag specified twice.\n"));
1977 if (is_yesno(ua->argv[i], &rc.ignoreduplicatecheck)) {
1978 rc.ignoreduplicatecheck_set = true;
1981 ua->send_msg(_("Invalid ignoreduplicatecheck flag.\n"));
1984 case 29: /* accurate */
1985 if (rc.accurate_set) {
1986 ua->send_msg(_("Accurate flag specified twice.\n"));
1989 if (is_yesno(ua->argv[i], &rc.accurate)) {
1990 rc.accurate_set = true;
1993 ua->send_msg(_("Invalid accurate flag.\n"));
1998 ua->send_msg(_("Job name specified twice.\n"));
2001 rc.job_name = ua->argv[i];
2004 case 31: /* mediatype */
2005 if (rc.media_type) {
2006 ua->send_msg(_("Media Type specified twice.\n"));
2009 rc.media_type = ua->argv[i];
2012 case 32: /* Next Pool */
2013 if (rc.next_pool_name) {
2014 ua->send_msg(_("NextPool specified twice.\n"));
2017 rc.next_pool_name = ua->argv[i];
2023 } /* end strcase compare */
2024 } /* end keyword loop */
2027 * End of keyword for loop -- if not found, we got a bogus keyword
2030 Dmsg1(800, "%s not found\n", ua->argk[i]);
2032 * Special case for Job Name, it can be the first
2033 * keyword that has no value.
2035 if (!rc.job_name && !ua->argv[i]) {
2036 rc.job_name = ua->argk[i]; /* use keyword as job name */
2037 Dmsg1(800, "Set jobname=%s\n", rc.job_name);
2039 ua->send_msg(_("Invalid keyword: %s\n"), ua->argk[i]);
2043 } /* end argc loop */
2045 Dmsg0(800, "Done scan.\n");
2047 if (!is_comment_legal(ua, rc.comment)) {
2051 if (rc.catalog_name) {
2052 rc.catalog = GetCatalogResWithName(rc.catalog_name);
2053 if (rc.catalog == NULL) {
2054 ua->error_msg(_("Catalog \"%s\" not found\n"), rc.catalog_name);
2057 if (!acl_access_ok(ua, Catalog_ACL, rc.catalog->name())) {
2058 ua->error_msg(_("No authorization. Catalog \"%s\".\n"), rc.catalog->name());
2062 Dmsg1(800, "Using catalog=%s\n", NPRT(rc.catalog_name));
2064 if (!get_job(ua, rc)) {
2068 if (!get_pool(ua, rc)) {
2072 if (!get_next_pool(ua, rc)) {
2076 if (!get_storage(ua, rc)) {
2081 if (!get_client(ua, rc)) {
2085 if (!get_fileset(ua, rc)) {
2089 if (rc.verify_job_name) {
2090 rc.verify_job = GetJobResWithName(rc.verify_job_name);
2091 if (!rc.verify_job) {
2092 ua->send_msg(_("Verify Job \"%s\" not found.\n"), rc.verify_job_name);
2093 rc.verify_job = select_job_resource(ua);
2095 } else if (!rc.verify_job) {
2096 rc.verify_job = rc.job->verify_job;
2099 if (rc.previous_job_name) {
2100 rc.previous_job = GetJobResWithName(rc.previous_job_name);
2101 if (!rc.previous_job) {
2102 ua->send_msg(_("Migration Job \"%s\" not found.\n"), rc.previous_job_name);
2103 rc.previous_job = select_job_resource(ua);
2106 rc.previous_job = rc.job->verify_job;