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; };
72 ~run_ctx() { delete store; };
75 /* Forward referenced subroutines */
76 static void select_job_level(UAContext *ua, JCR *jcr);
77 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job,
78 const char *verify_list, char *jid, const char *replace,
80 static void select_where_regexp(UAContext *ua, JCR *jcr);
81 static bool scan_run_command_line_arguments(UAContext *ua, run_ctx &rc);
82 static bool set_run_context_in_jcr(UAContext *ua, JCR *jcr, run_ctx &rc);
83 static int modify_job_parameters(UAContext *ua, JCR *jcr, run_ctx &rc);
84 static JobId_t start_job(UAContext *ua, JCR *jcr, run_ctx &rc);
86 /* Imported variables */
87 extern struct s_kw ReplaceOptions[];
90 * For Backup and Verify Jobs
91 * run [job=]<job-name> level=<level-name>
100 int run_cmd(UAContext *ua, const char *cmd)
106 if (!open_client_db(ua)) {
110 if (!scan_run_command_line_arguments(ua, rc)) {
114 if (find_arg(ua, NT_("fdcalled")) > 0) {
115 jcr->file_bsock = dup_bsock(ua->UA_sock);
121 * Create JCR to run job. NOTE!!! after this point, free_jcr()
125 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
126 set_jcr_defaults(jcr, rc.job);
127 jcr->unlink_bsr = ua->jcr->unlink_bsr; /* copy unlink flag from caller */
128 ua->jcr->unlink_bsr = false;
130 /* Transfer JobIds to new restore Job */
131 if (ua->jcr->JobIds) {
132 jcr->JobIds = ua->jcr->JobIds;
133 ua->jcr->JobIds = NULL;
135 /* Transfer VSS component info */
136 if (ua->jcr->component_fname) {
137 jcr->component_fname = ua->jcr->component_fname;
138 ua->jcr->component_fname = NULL;
139 jcr->component_fd = ua->jcr->component_fd;
140 ua->jcr->component_fd = NULL;
143 if (!set_run_context_in_jcr(ua, jcr, rc)) {
144 break; /* error get out of while loop */
148 /* Run without prompting? */
149 if (ua->batch || find_arg(ua, NT_("yes")) > 0) {
150 return start_job(ua, jcr, rc);
154 * Prompt User to see if all run job parameters are correct, and
155 * allow him to modify them.
157 if (!display_job_parameters(ua, jcr, rc.job, rc.verify_list, rc.jid, rc.replace,
159 break; /* error get out of while loop */
162 if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
163 break; /* error get out of while loop */
166 if (strncasecmp(ua->cmd, ".mod ", 5) == 0 ||
167 (strncasecmp(ua->cmd, "mod ", 4) == 0 && strlen(ua->cmd) > 6)) {
170 if (!scan_run_command_line_arguments(ua, rc)) {
171 break; /* error get out of while loop */
173 continue; /* another round with while loop */
176 /* Allow the user to modify the settings */
177 status = modify_job_parameters(ua, jcr, rc);
179 continue; /* another round with while loop */
181 if (status == -1) { /* error */
182 break; /* error get out of while loop */
185 if (ua->cmd[0] == 0 || strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
186 return start_job(ua, jcr, rc);
188 if (strncasecmp(ua->cmd, _("no"), strlen(ua->cmd)) == 0) {
189 break; /* get out of while loop */
191 ua->send_msg(_("\nBad response: %s. You must answer yes, mod, or no.\n\n"), ua->cmd);
195 ua->send_msg(_("Job not run.\n"));
196 if (ua->jcr->component_fd) {
197 fclose(ua->jcr->component_fd);
198 ua->jcr->component_fd = NULL;
200 if (ua->jcr->component_fname) {
201 unlink(ua->jcr->component_fname);
202 free_and_null_pool_memory(ua->jcr->component_fname);
205 if (jcr->component_fd) {
206 fclose(jcr->component_fd);
207 jcr->component_fd = NULL;
209 if (jcr->component_fname) {
210 unlink(jcr->component_fname);
211 free_and_null_pool_memory(jcr->component_fname);
215 return 0; /* do not run */
218 static JobId_t start_job(UAContext *ua, JCR *jcr, run_ctx &rc)
222 if (rc.jr.JobStatus == JS_Incomplete) {
223 Dmsg1(100, "Ressuming JobId=%d\n", rc.jr.JobId);
224 JobId = resume_job(jcr, &rc.jr);
226 Dmsg1(100, "Starting JobId=%d\n", rc.jr.JobId);
227 JobId = run_job(jcr);
229 Dmsg4(100, "JobId=%u NewJobId=%d pool=%s priority=%d\n", (int)jcr->JobId,
230 JobId, jcr->pool->name(), jcr->JobPriority);
231 free_jcr(jcr); /* release jcr */
233 ua->error_msg(_("Job failed.\n"));
236 ua->send_msg(_("Job queued. JobId=%s\n"), edit_int64(JobId, ed1));
242 * If no job_name defined in the run context, ask
244 * Then put the job resource in the run context and
245 * check the access rights.
247 static bool get_job(UAContext *ua, run_ctx &rc)
251 rc.job = GetJobResWithName(rc.job_name);
253 if (*rc.job_name != 0) {
254 ua->send_msg(_("Job \"%s\" not found\n"), rc.job_name);
256 rc.job = select_job_resource(ua);
258 Dmsg1(100, "Found job=%s\n", rc.job_name);
260 } else if (!rc.job) {
261 ua->send_msg(_("A job name must be specified.\n"));
262 rc.job = select_job_resource(ua);
266 } else if (!acl_access_ok(ua, Job_ACL, rc.job->name())) {
267 ua->error_msg( _("No authorization. Job \"%s\".\n"), rc.job->name());
274 * If no pool_name defined in the run context, ask
276 * Then put the pool resource in the run context and
277 * check the access rights.
279 static bool get_pool(UAContext *ua, run_ctx &rc)
282 rc.pool = GetPoolResWithName(rc.pool_name);
284 if (*rc.pool_name != 0) {
285 ua->warning_msg(_("Pool \"%s\" not found.\n"), rc.pool_name);
287 rc.pool = select_pool_resource(ua);
289 } else if (!rc.pool) {
290 rc.pool = rc.job->pool; /* use default */
294 } else if (!acl_access_ok(ua, Pool_ACL, rc.pool->name())) {
295 ua->error_msg(_("No authorization. Pool \"%s\".\n"), rc.pool->name());
298 Dmsg1(100, "Using Pool=%s\n", rc.pool->name());
302 static bool get_next_pool(UAContext *ua, run_ctx &rc)
304 if (rc.next_pool_name) {
305 Dmsg1(100, "Have next pool=%s\n", rc.next_pool_name);
306 rc.next_pool = GetPoolResWithName(rc.next_pool_name);
308 if (*rc.next_pool_name != 0) {
309 ua->warning_msg(_("NextPool \"%s\" not found.\n"), rc.next_pool_name);
311 rc.next_pool = select_pool_resource(ua);
314 /* NextPool can come from Job resource NextPool or Pool resource NextPool */
316 if (rc.job->next_pool) {
317 rc.next_pool = rc.job->next_pool;
319 rc.next_pool = rc.pool->NextPool; /* use default */
322 if (rc.next_pool && !acl_access_ok(ua, Pool_ACL, rc.next_pool->name())) {
323 ua->error_msg(_("No authorization. NextPool \"%s\".\n"), rc.next_pool->name());
327 Dmsg1(100, "Using NextPool=%s\n", NPRT(rc.next_pool->name()));
334 * Fill in client data according to what is setup
335 * in the run context, and make sure the user
336 * has authorized access to it.
338 static bool get_client(UAContext *ua, run_ctx &rc)
340 if (rc.client_name) {
341 rc.client = GetClientResWithName(rc.client_name);
343 if (*rc.client_name != 0) {
344 ua->warning_msg(_("Client \"%s\" not found.\n"), rc.client_name);
346 rc.client = select_client_resource(ua);
348 } else if (!rc.client) {
349 rc.client = rc.job->client; /* use default */
353 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
354 ua->error_msg(_("No authorization. Client \"%s\".\n"),
358 Dmsg1(800, "Using client=%s\n", rc.client->name());
360 if (rc.restore_client_name) {
361 rc.client = GetClientResWithName(rc.restore_client_name);
363 if (*rc.restore_client_name != 0) {
364 ua->warning_msg(_("Restore Client \"%s\" not found.\n"), rc.restore_client_name);
366 rc.client = select_client_resource(ua);
368 } else if (!rc.client) {
369 rc.client = rc.job->client; /* use default */
373 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
374 ua->error_msg(_("No authorization. Client \"%s\".\n"),
378 Dmsg1(800, "Using restore client=%s\n", rc.client->name());
384 * Fill in fileset data according to what is setup
385 * in the run context, and make sure the user
386 * has authorized access to it.
388 static bool get_fileset(UAContext *ua, run_ctx &rc)
390 if (rc.fileset_name) {
391 rc.fileset = GetFileSetResWithName(rc.fileset_name);
393 ua->send_msg(_("FileSet \"%s\" not found.\n"), rc.fileset_name);
394 rc.fileset = select_fileset_resource(ua);
396 } else if (!rc.fileset) {
397 rc.fileset = rc.job->fileset; /* use default */
401 } else if (!acl_access_ok(ua, FileSet_ACL, rc.fileset->name())) {
402 ua->send_msg(_("No authorization. FileSet \"%s\".\n"),
410 * Fill in storage data according to what is setup
411 * in the run context, and make sure the user
412 * has authorized access to it.
414 static bool get_storage(UAContext *ua, run_ctx &rc)
417 rc.store->store = GetStoreResWithName(rc.store_name);
418 pm_strcpy(rc.store->store_source, _("command line"));
419 if (!rc.store->store) {
420 if (*rc.store_name != 0) {
421 ua->warning_msg(_("Storage \"%s\" not found.\n"), rc.store_name);
423 rc.store->store = select_storage_resource(ua);
424 pm_strcpy(rc.store->store_source, _("user selection"));
426 } else if (!rc.store->store) {
427 get_job_storage(rc.store, rc.job, NULL); /* use default */
429 if (!rc.store->store) {
430 ua->error_msg(_("No storage specified.\n"));
432 } else if (!acl_access_ok(ua, Storage_ACL, rc.store->store->name())) {
433 ua->error_msg(_("No authorization. Storage \"%s\".\n"),
434 rc.store->store->name());
437 Dmsg1(800, "Using storage=%s\n", rc.store->store->name());
442 * Get and pass back a list of Jobids in rc.jid
444 static bool get_jobid_list(UAContext *ua, sellist &sl, run_ctx &rc)
451 memset(&jr, 0, sizeof(jr));
453 /* See if any JobId is specified */
454 if ((i=find_arg(ua, "jobid")) >= 0) {
455 rc.jid = ua->argv[i];
457 ua->send_msg(_("No JobId specified.\n"));
460 if (!sl.set_string(ua->argv[i], true)) {
461 ua->send_msg("%s", sl.get_errmsg());
467 /* No JobId list give, so see if he specified a Job */
468 if ((i=find_arg(ua, "job")) >= 0) {
469 rc.job_name = ua->argv[i];
470 if (!get_job(ua, rc)) {
471 ua->send_msg(_("Invalid or no Job name specified.\n"));
475 jr.limit = 100; /* max 100 records */
477 bstrncpy(jr.Name, rc.job_name, sizeof(jr.Name));
481 jr.JobStatus = rc.jr.JobStatus;
482 Dmsg2(100, "JobStatus=%d JobName=%s\n", jr.JobStatus, jr.Name);
483 /* rc.JobIds is alist of all records found and printed */
484 rc.JobIds = db_list_job_records(ua->jcr, ua->db, &jr, prtit, ua, INCOMPLETE_JOBS);
485 if (!rc.JobIds || rc.JobIds->size()==0 ||
486 !get_selection_list(ua, sl, _("Enter the JobId list to select: "), false)) {
489 Dmsg1(100, "list=%s\n", sl.get_list());
491 * Make sure each item entered is in the JobIds list
493 while ( (JobId = sl.next()) > 0) {
494 foreach_alist(pJobId, rc.JobIds) {
495 if (JobId == str_to_int64(pJobId)) {
502 ua->error_msg(_("JobId=%d entered is not in the list.\n"), JobId);
506 sl.begin(); /* reset to walk list again */
511 static bool get_jobid_from_list(UAContext *ua, sellist &sl, run_ctx &rc)
518 if ((JobId = sl.next()) < 0) {
519 Dmsg1(100, "sl.next()=%d\n", JobId);
523 rc.jr.JobId = rc.JobId = JobId;
524 Dmsg1(100, "Next JobId=%d\n", rc.JobId);
525 if (!db_get_job_record(ua->jcr, ua->db, &rc.jr)) {
526 ua->error_msg(_("Could not get job record for selected JobId=%d. ERR=%s"),
527 rc.JobId, db_strerror(ua->db));
530 Dmsg3(100, "Job=%s JobId=%d JobStatus=%c\n", rc.jr.Name, rc.jr.JobId,
532 rc.job_name = rc.jr.Name;
533 if (!get_job(ua, rc)) {
536 if (!get_pool(ua, rc)) {
539 get_job_storage(rc.store, rc.job, NULL);
540 rc.client_name = rc.job->client->hdr.name;
541 if (!get_client(ua, rc)) {
544 if (!get_fileset(ua, rc)) {
547 if (!get_storage(ua, rc)) {
554 * Restart Canceled, Failed, or Incomplete Jobs
556 * Returns: 0 on error
560 int restart_cmd(UAContext *ua, const char *cmd)
568 const char *status_name;
572 {"Incomplete", JS_Incomplete},
573 {"Canceled", JS_Canceled},
574 {"Failed", JS_FatalError},
579 if (!open_client_db(ua)) {
584 for (i=1; i<ua->argc; i++) {
585 for (j=0; kw[j].status_name; j++) {
586 if (strcasecmp(ua->argk[i], kw[j].status_name) == 0) {
587 rc.jr.JobStatus = kw[j].job_status;
593 if (!got_kw) { /* Must prompt user */
594 start_prompt(ua, _("You have the following choices:\n"));
595 for (i=0; kw[i].status_name; i++) {
596 add_prompt(ua, kw[i].status_name);
598 i = do_prompt(ua, NULL, _("Select termination code: "), NULL, 0);
602 rc.jr.JobStatus = kw[i].job_status;
605 /* type now has what job termination code we want to look at */
606 Dmsg1(100, "Termination code=%c\n", rc.jr.JobStatus);
608 /* Get a list of JobIds to restore */
609 if (!get_jobid_list(ua, sl, rc)) {
611 rc.JobIds->destroy();
615 Dmsg1(100, "list=%s\n", sl.get_list());
617 while (get_jobid_from_list(ua, sl, rc)) {
619 * Create JCR to run job. NOTE!!! after this point, free_jcr()
623 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
624 set_jcr_defaults(jcr, rc.job);
625 jcr->unlink_bsr = ua->jcr->unlink_bsr; /* copy unlink flag from caller */
626 ua->jcr->unlink_bsr = false;
629 if (!set_run_context_in_jcr(ua, jcr, rc)) {
632 start_job(ua, jcr, rc);
640 rc.JobIds->destroy();
642 return 0; /* do not run */
645 int modify_job_parameters(UAContext *ua, JCR *jcr, run_ctx &rc)
650 * At user request modify parameters of job to be run.
652 if (ua->cmd[0] != 0 && strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0){
655 start_prompt(ua, _("Parameters to modify:\n"));
656 add_prompt(ua, _("Level")); /* 0 */
657 add_prompt(ua, _("Storage")); /* 1 */
658 add_prompt(ua, _("Job")); /* 2 */
659 add_prompt(ua, _("FileSet")); /* 3 */
660 if (jcr->getJobType() == JT_RESTORE) {
661 add_prompt(ua, _("Restore Client")); /* 4 */
663 add_prompt(ua, _("Client")); /* 4 */
665 add_prompt(ua, _("When")); /* 5 */
666 add_prompt(ua, _("Priority")); /* 6 */
667 if (jcr->getJobType() == JT_BACKUP ||
668 jcr->getJobType() == JT_COPY ||
669 jcr->getJobType() == JT_MIGRATE ||
670 jcr->getJobType() == JT_VERIFY) {
671 add_prompt(ua, _("Pool")); /* 7 */
672 if ((jcr->getJobType() == JT_BACKUP && /* Virtual full */
673 jcr->is_JobLevel(L_VIRTUAL_FULL)) ||
674 jcr->getJobType() == JT_COPY ||
675 jcr->getJobType() == JT_MIGRATE) {
676 add_prompt(ua, _("NextPool")); /* 8 */
677 } else if (jcr->getJobType() == JT_VERIFY) {
678 add_prompt(ua, _("Verify Job")); /* 8 */
680 } else if (jcr->getJobType() == JT_RESTORE) {
681 add_prompt(ua, _("Bootstrap")); /* 7 */
682 add_prompt(ua, _("Where")); /* 8 */
683 add_prompt(ua, _("File Relocation"));/* 9 */
684 add_prompt(ua, _("Replace")); /* 10 */
685 add_prompt(ua, _("JobId")); /* 11 */
687 if (jcr->getJobType() == JT_BACKUP || jcr->getJobType() == JT_RESTORE) {
688 add_prompt(ua, _("Plugin Options")); /* 12 */
690 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
693 select_job_level(ua, jcr);
697 rc.store->store = select_storage_resource(ua);
698 if (rc.store->store) {
699 pm_strcpy(rc.store->store_source, _("user selection"));
700 set_rwstorage(jcr, rc.store);
706 rc.job = select_job_resource(ua);
709 set_jcr_defaults(jcr, rc.job);
715 rc.fileset = select_fileset_resource(ua);
717 jcr->fileset = rc.fileset;
723 rc.client = select_client_resource(ua);
725 jcr->client = rc.client;
731 if (!get_cmd(ua, _("Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now): "))) {
734 if (ua->cmd[0] == 0) {
735 jcr->sched_time = time(NULL);
737 jcr->sched_time = str_to_utime(ua->cmd);
738 if (jcr->sched_time == 0) {
739 ua->send_msg(_("Invalid time, using current time.\n"));
740 jcr->sched_time = time(NULL);
746 if (!get_pint(ua, _("Enter new Priority: "))) {
749 if (ua->pint32_val == 0) {
750 ua->send_msg(_("Priority must be a positive integer.\n"));
752 jcr->JobPriority = ua->pint32_val;
756 /* Pool or Bootstrap depending on JobType */
757 if (jcr->getJobType() == JT_BACKUP ||
758 jcr->getJobType() == JT_COPY ||
759 jcr->getJobType() == JT_MIGRATE ||
760 jcr->getJobType() == JT_VERIFY) { /* Pool */
761 rc.pool = select_pool_resource(ua);
764 Dmsg1(100, "Set new pool=%s\n", jcr->pool->name());
771 if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
774 if (jcr->RestoreBootstrap) {
775 free(jcr->RestoreBootstrap);
776 jcr->RestoreBootstrap = NULL;
778 if (ua->cmd[0] != 0) {
779 jcr->RestoreBootstrap = bstrdup(ua->cmd);
780 fd = fopen(jcr->RestoreBootstrap, "rb");
783 ua->send_msg(_("Warning cannot open %s: ERR=%s\n"),
784 jcr->RestoreBootstrap, be.bstrerror());
785 free(jcr->RestoreBootstrap);
786 jcr->RestoreBootstrap = NULL;
793 /* Specify Next Pool */
794 if ((jcr->getJobType() == JT_BACKUP && /* Virtual full */
795 jcr->is_JobLevel(L_VIRTUAL_FULL)) ||
796 jcr->getJobType() == JT_COPY ||
797 jcr->getJobType() == JT_MIGRATE) {
798 rc.next_pool = select_pool_resource(ua);
800 jcr->next_pool = rc.next_pool;
805 if (jcr->getJobType() == JT_VERIFY) {
806 rc.verify_job = select_job_resource(ua);
808 jcr->verify_job = rc.verify_job;
813 if (!get_cmd(ua, _("Please enter the full path prefix for restore (/ for none): "))) {
816 if (jcr->RegexWhere) { /* cannot use regexwhere and where */
817 free(jcr->RegexWhere);
818 jcr->RegexWhere = NULL;
824 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
827 jcr->where = bstrdup(ua->cmd);
830 /* File relocation */
831 select_where_regexp(ua, jcr);
835 start_prompt(ua, _("Replace:\n"));
836 for (i=0; ReplaceOptions[i].name; i++) {
837 add_prompt(ua, ReplaceOptions[i].name);
839 opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
841 rc.replace = ReplaceOptions[opt].name;
842 jcr->replace = ReplaceOptions[opt].token;
847 rc.jid = NULL; /* force reprompt */
848 jcr->RestoreJobId = 0;
849 if (jcr->RestoreBootstrap) {
850 ua->send_msg(_("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
855 //generate_plugin_event(jcr, bEventJobConfig, &rc);
856 if (!get_cmd(ua, _("Please Plugin Options string: "))) {
859 if (jcr->plugin_options) {
860 free(jcr->plugin_options);
861 jcr->plugin_options = NULL;
863 jcr->plugin_options = bstrdup(ua->cmd);
865 case -1: /* error or cancel */
881 * Put the run context that we have at this point into the JCR.
882 * That allows us to re-ask for the run context.
883 * This subroutine can be called multiple times, so it
884 * must keep any prior settings.
886 static bool set_run_context_in_jcr(UAContext *ua, JCR *jcr, run_ctx &rc)
890 jcr->verify_job = rc.verify_job;
891 jcr->previous_job = rc.previous_job;
893 jcr->next_pool = rc.next_pool;
895 jcr->cmdline_next_pool_override = true;
898 pm_strcpy(jcr->pool_source, _("Command input"));
899 } else if (jcr->pool != jcr->job->pool) {
900 pm_strcpy(jcr->pool_source, _("User input"));
902 if (rc.next_pool_name) {
903 pm_strcpy(jcr->next_pool_source, _("Command input"));
904 } else if (jcr->next_pool == jcr->job->next_pool) {
905 pm_strcpy(jcr->next_pool_source, _("Job resource"));
906 } else if (jcr->next_pool != jcr->pool->NextPool) {
907 pm_strcpy(jcr->next_pool_source, _("User input"));
910 set_rwstorage(jcr, rc.store);
911 jcr->client = rc.client;
913 pm_strcpy(jcr->client_name, rc.client->name());
915 pm_strcpy(jcr->client_name, "**Dummy**");
918 if (!jcr->media_type) {
919 jcr->media_type = get_pool_memory(PM_NAME);
921 pm_strcpy(jcr->media_type, rc.media_type);
923 jcr->fileset = rc.fileset;
924 jcr->ExpectedFiles = rc.files;
926 jcr->catalog = rc.catalog;
927 pm_strcpy(jcr->catalog_source, _("User input"));
930 pm_strcpy(jcr->comment, rc.comment);
936 jcr->where = bstrdup(rc.where);
941 if (jcr->RegexWhere) {
942 free(jcr->RegexWhere);
944 jcr->RegexWhere = bstrdup(rc.regexwhere);
945 rc.regexwhere = NULL;
949 jcr->sched_time = str_to_utime(rc.when);
950 if (jcr->sched_time == 0) {
951 ua->send_msg(_("Invalid time, using current time.\n"));
952 jcr->sched_time = time(NULL);
958 if (jcr->RestoreBootstrap) {
959 free(jcr->RestoreBootstrap);
961 jcr->RestoreBootstrap = bstrdup(rc.bootstrap);
965 if (rc.plugin_options) {
966 if (jcr->plugin_options) {
967 free(jcr->plugin_options);
969 jcr->plugin_options = bstrdup(rc.plugin_options);
970 rc.plugin_options = NULL;
975 for (i=0; ReplaceOptions[i].name; i++) {
976 if (strcasecmp(rc.replace, ReplaceOptions[i].name) == 0) {
977 jcr->replace = ReplaceOptions[i].token;
981 ua->send_msg(_("Invalid replace option: %s\n"), rc.replace);
984 } else if (rc.job->replace) {
985 jcr->replace = rc.job->replace;
987 jcr->replace = REPLACE_ALWAYS;
991 /* Set Snapshot Retention (Job <- Client) */
993 jcr->snapshot_retention = jcr->client->SnapRetention;
995 if (jcr->job && jcr->job->SnapRetention > 0) {
996 jcr->snapshot_retention = jcr->job->SnapRetention;
1000 jcr->JobPriority = rc.Priority;
1006 jcr->stime = get_pool_memory(PM_MESSAGE);
1008 pm_strcpy(jcr->stime, rc.since);
1013 jcr->cloned = rc.cloned;
1017 /* If pool changed, update migration write storage */
1018 if (jcr->is_JobType(JT_MIGRATE) || jcr->is_JobType(JT_COPY) ||
1019 (jcr->is_JobType(JT_BACKUP) && jcr->is_JobLevel(L_VIRTUAL_FULL))) {
1020 if (!set_mac_wstorage(ua, jcr, rc.pool, rc.next_pool,
1021 jcr->next_pool_source)) {
1025 rc.replace = ReplaceOptions[0].name;
1026 for (i=0; ReplaceOptions[i].name; i++) {
1027 if ((int)ReplaceOptions[i].token == jcr->replace) {
1028 rc.replace = ReplaceOptions[i].name;
1031 if (rc.level_name) {
1032 if (!get_level_from_name(jcr, rc.level_name)) {
1033 ua->send_msg(_("Level \"%s\" not valid.\n"), rc.level_name);
1036 rc.level_name = NULL;
1039 /* Note, this is also MigrateJobId and a VerifyJobId */
1040 jcr->RestoreJobId = str_to_int64(rc.jid);
1042 /* Copy also this parameter for VirtualFull in jcr->JobIds */
1044 jcr->JobIds = get_pool_memory(PM_FNAME);
1046 pm_strcpy(jcr->JobIds, rc.jid);
1047 jcr->use_all_JobIds = rc.alljobid; /* if we found the "alljobid=" kw */
1048 rc.alljobid = false;
1052 /* Some options are not available through the menu
1053 * TODO: Add an advanced menu?
1055 if (rc.spool_data_set) {
1056 jcr->spool_data = rc.spool_data;
1059 if (rc.accurate_set) {
1060 jcr->accurate = rc.accurate;
1063 /* Used by migration jobs that can have the same name,
1064 * but can run at the same time
1066 if (rc.ignoreduplicatecheck_set) {
1067 jcr->IgnoreDuplicateJobChecking = rc.ignoreduplicatecheck;
1073 static void select_where_regexp(UAContext *ua, JCR *jcr)
1076 char *strip_prefix, *add_prefix, *add_suffix, *rwhere;
1077 strip_prefix = add_suffix = rwhere = add_prefix = NULL;
1080 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s\n"),
1081 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix));
1083 start_prompt(ua, _("This will replace your current Where value\n"));
1084 add_prompt(ua, _("Strip prefix")); /* 0 */
1085 add_prompt(ua, _("Add prefix")); /* 1 */
1086 add_prompt(ua, _("Add file suffix")); /* 2 */
1087 add_prompt(ua, _("Enter a regexp")); /* 3 */
1088 add_prompt(ua, _("Test filename manipulation")); /* 4 */
1089 add_prompt(ua, _("Use this ?")); /* 5 */
1091 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
1094 if (get_cmd(ua, _("Please enter the path prefix to strip: "))) {
1095 if (strip_prefix) bfree(strip_prefix);
1096 strip_prefix = bstrdup(ua->cmd);
1102 if (get_cmd(ua, _("Please enter the path prefix to add (/ for none): "))) {
1103 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
1107 if (add_prefix) bfree(add_prefix);
1108 add_prefix = bstrdup(ua->cmd);
1113 if (get_cmd(ua, _("Please enter the file suffix to add: "))) {
1114 if (add_suffix) bfree(add_suffix);
1115 add_suffix = bstrdup(ua->cmd);
1120 if (get_cmd(ua, _("Please enter a valid regexp (!from!to!): "))) {
1121 if (rwhere) bfree(rwhere);
1122 rwhere = bstrdup(ua->cmd);
1131 if (rwhere && rwhere[0] != '\0') {
1132 regs = get_bregexps(rwhere);
1133 ua->send_msg(_("regexwhere=%s\n"), NPRT(rwhere));
1135 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
1136 regexp = (char *) bmalloc (len * sizeof(char));
1137 bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix);
1138 regs = get_bregexps(regexp);
1139 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s result=%s\n"),
1140 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix), NPRT(regexp));
1146 ua->send_msg(_("Cannot use your regexp\n"));
1149 ua->send_msg(_("Enter a period (.) to stop this test\n"));
1150 while (get_cmd(ua, _("Please enter filename to test: "))) {
1151 apply_bregexps(ua->cmd, regs, &result);
1152 ua->send_msg(_("%s -> %s\n"), ua->cmd, result);
1154 free_bregexps(regs);
1161 case -1: /* error or cancel */
1167 /* replace the existing where */
1173 /* replace the existing regexwhere */
1174 if (jcr->RegexWhere) {
1175 bfree(jcr->RegexWhere);
1176 jcr->RegexWhere = NULL;
1180 jcr->RegexWhere = bstrdup(rwhere);
1181 } else if (strip_prefix || add_prefix || add_suffix) {
1182 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
1183 jcr->RegexWhere = (char *) bmalloc(len*sizeof(char));
1184 bregexp_build_where(jcr->RegexWhere, len, strip_prefix, add_prefix, add_suffix);
1187 regs = get_bregexps(jcr->RegexWhere);
1189 free_bregexps(regs);
1192 if (jcr->RegexWhere) {
1193 bfree(jcr->RegexWhere);
1194 jcr->RegexWhere = NULL;
1196 ua->send_msg(_("Cannot use your regexp.\n"));
1200 if (strip_prefix) bfree(strip_prefix);
1201 if (add_prefix) bfree(add_prefix);
1202 if (add_suffix) bfree(add_suffix);
1203 if (rwhere) bfree(rwhere);
1206 static void select_job_level(UAContext *ua, JCR *jcr)
1208 if (jcr->getJobType() == JT_BACKUP) {
1209 start_prompt(ua, _("Levels:\n"));
1210 // add_prompt(ua, _("Base"));
1211 add_prompt(ua, _("Full"));
1212 add_prompt(ua, _("Incremental"));
1213 add_prompt(ua, _("Differential"));
1214 add_prompt(ua, _("Since"));
1215 add_prompt(ua, _("VirtualFull"));
1216 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
1218 // jcr->JobLevel = L_BASE;
1221 jcr->setJobLevel(L_FULL);
1224 jcr->setJobLevel(L_INCREMENTAL);
1227 jcr->setJobLevel(L_DIFFERENTIAL);
1230 jcr->setJobLevel(L_SINCE);
1233 jcr->setJobLevel(L_VIRTUAL_FULL);
1238 } else if (jcr->getJobType() == JT_VERIFY) {
1239 start_prompt(ua, _("Levels:\n"));
1240 add_prompt(ua, _("Initialize Catalog"));
1241 add_prompt(ua, _("Verify Catalog"));
1242 add_prompt(ua, _("Verify Volume to Catalog"));
1243 add_prompt(ua, _("Verify Disk to Catalog"));
1244 add_prompt(ua, _("Verify Volume Data"));
1245 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
1247 jcr->setJobLevel(L_VERIFY_INIT);
1250 jcr->setJobLevel(L_VERIFY_CATALOG);
1253 jcr->setJobLevel(L_VERIFY_VOLUME_TO_CATALOG);
1256 jcr->setJobLevel(L_VERIFY_DISK_TO_CATALOG);
1259 jcr->setJobLevel(L_VERIFY_DATA);
1265 ua->warning_msg(_("Level not appropriate for this Job. Cannot be changed.\n"));
1270 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char *verify_list,
1271 char *jid, const char *replace, char *client_name)
1274 char dt[MAX_TIME_LENGTH];
1276 Dmsg1(800, "JobType=%c\n", jcr->getJobType());
1277 switch (jcr->getJobType()) {
1280 ua->signal(BNET_RUN_CMD);
1281 ua->send_msg("Type: Admin\n"
1282 "Title: Run Admin Job\n"
1290 jcr->fileset->name(),
1291 NPRT(jcr->client->name()),
1292 jcr->wstore?jcr->wstore->name():"*None*",
1293 bstrutime(dt, sizeof(dt), jcr->sched_time),
1296 ua->send_msg(_("Run Admin Job\n"
1304 jcr->fileset->name(),
1305 NPRT(jcr->client->name()),
1306 jcr->wstore?jcr->wstore->name():"*None*",
1307 bstrutime(dt, sizeof(dt), jcr->sched_time),
1310 jcr->setJobLevel(L_FULL);
1314 char next_pool[MAX_NAME_LENGTH + 50];
1316 if (jcr->getJobType() == JT_BACKUP) {
1318 ua->signal(BNET_RUN_CMD);
1319 if (jcr->is_JobLevel(L_VIRTUAL_FULL)) {
1320 bsnprintf(next_pool, sizeof(next_pool), "NextPool: %s\n",
1321 jcr->next_pool ? jcr->next_pool->name() : "*None*");
1323 ua->send_msg("Type: Backup\n"
1324 "Title: Run Backup Job\n"
1336 level_to_str(jcr->getJobLevel()),
1337 jcr->client->name(),
1338 jcr->fileset->name(),
1339 NPRT(jcr->pool->name()),
1341 jcr->wstore?jcr->wstore->name():"*None*",
1342 bstrutime(dt, sizeof(dt), jcr->sched_time),
1344 jcr->plugin_options?"Plugin Options: ":"",
1345 jcr->plugin_options?jcr->plugin_options:"",
1346 jcr->plugin_options?"\n":"");
1348 if (jcr->is_JobLevel(L_VIRTUAL_FULL)) {
1349 bsnprintf(next_pool, sizeof(next_pool),
1350 "NextPool: %s (From %s)\n",
1351 jcr->next_pool ? jcr->next_pool->name() : "*None*",
1352 jcr->next_pool_source);
1354 ua->send_msg(_("Run Backup job\n"
1359 "Pool: %s (From %s)\n"
1361 "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,
1371 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
1372 bstrutime(dt, sizeof(dt), jcr->sched_time),
1374 jcr->plugin_options?"Plugin Options: ":"",
1375 jcr->plugin_options?jcr->plugin_options:"",
1376 jcr->plugin_options?"\n":"");
1378 } else { /* JT_VERIFY */
1381 if (jcr->verify_job) {
1382 Name = jcr->verify_job->name();
1383 } else if (jcr->RestoreJobId) { /* Display job name if jobid requested */
1384 memset(&jr, 0, sizeof(jr));
1385 jr.JobId = jcr->RestoreJobId;
1386 if (!db_get_job_record(jcr, ua->db, &jr)) {
1387 ua->error_msg(_("Could not get job record for selected JobId. ERR=%s"),
1388 db_strerror(ua->db));
1396 verify_list = job->WriteVerifyList;
1402 ua->signal(BNET_RUN_CMD);
1403 ua->send_msg("Type: Verify\n"
1404 "Title: Run Verify Job\n"
1409 "Pool: %s (From %s)\n"
1410 "Storage: %s (From %s)\n"
1416 level_to_str(jcr->getJobLevel()),
1417 jcr->client->name(),
1418 jcr->fileset->name(),
1419 NPRT(jcr->pool->name()), jcr->pool_source,
1420 jcr->rstore->name(), jcr->rstore_source,
1423 bstrutime(dt, sizeof(dt), jcr->sched_time),
1426 ua->send_msg(_("Run Verify Job\n"
1431 "Pool: %s (From %s)\n"
1432 "Storage: %s (From %s)\n"
1438 level_to_str(jcr->getJobLevel()),
1439 jcr->client->name(),
1440 jcr->fileset->name(),
1441 NPRT(jcr->pool->name()), jcr->pool_source,
1442 jcr->rstore->name(), jcr->rstore_source,
1445 bstrutime(dt, sizeof(dt), jcr->sched_time),
1451 if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
1453 jcr->RestoreJobId = str_to_int64(jid);
1455 if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
1458 jcr->RestoreJobId = ua->int64_val;
1461 jcr->setJobLevel(L_FULL); /* default level */
1462 Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId);
1463 if (jcr->RestoreJobId == 0) {
1464 /* RegexWhere is take before RestoreWhere */
1465 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
1467 ua->signal(BNET_RUN_CMD);
1468 ua->send_msg("Type: Restore\n"
1469 "Title: Run Restore Job\n"
1475 "Backup Client: %s\n"
1476 "Restore Client: %s\n"
1481 "Plugin Options: %s\n",
1483 NPRT(jcr->RestoreBootstrap),
1484 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
1486 jcr->fileset->name(),
1488 jcr->client->name(),
1489 jcr->rstore->name(),
1490 bstrutime(dt, sizeof(dt), jcr->sched_time),
1491 jcr->catalog->name(),
1493 NPRTB(jcr->plugin_options));
1496 ua->send_msg(_("Run Restore job\n"
1502 "Backup Client: %s\n"
1503 "Restore Client: %s\n"
1508 "Plugin Options: %s\n"),
1510 NPRT(jcr->RestoreBootstrap),
1511 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
1513 jcr->fileset->name(),
1515 jcr->client->name(),
1516 jcr->rstore->name(),
1517 bstrutime(dt, sizeof(dt), jcr->sched_time),
1518 jcr->catalog->name(),
1520 NPRTB(jcr->plugin_options));
1524 ua->signal(BNET_RUN_CMD);
1525 ua->send_msg("Type: Restore\n"
1526 "Title: Run Restore job\n"
1532 "Backup Client: %s\n"
1533 "Restore Client: %s\n"
1538 "Plugin Options: %s\n",
1540 NPRT(jcr->RestoreBootstrap),
1541 jcr->where?jcr->where:NPRT(job->RestoreWhere),
1543 jcr->fileset->name(),
1545 jcr->client->name(),
1546 jcr->rstore->name(),
1547 bstrutime(dt, sizeof(dt), jcr->sched_time),
1548 jcr->catalog->name(),
1550 NPRTB(jcr->plugin_options));
1553 ua->send_msg(_("Run Restore job\n"
1559 "Backup Client: %s\n"
1560 "Restore Client: %s\n"
1565 "Plugin Options: %s\n"),
1567 NPRT(jcr->RestoreBootstrap),
1568 jcr->where?jcr->where:NPRT(job->RestoreWhere),
1570 jcr->fileset->name(),
1572 jcr->client->name(),
1573 jcr->rstore->name(),
1574 bstrutime(dt, sizeof(dt), jcr->sched_time),
1575 jcr->catalog->name(),
1577 NPRTB(jcr->plugin_options));
1582 /* ***FIXME*** This needs to be fixed for bat */
1583 if (ua->api) ua->signal(BNET_RUN_CMD);
1584 ua->send_msg(_("Run Restore job\n"
1588 NPRT(jcr->RestoreBootstrap));
1590 /* RegexWhere is take before RestoreWhere */
1591 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
1592 ua->send_msg(_("RegexWhere: %s\n"),
1593 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere);
1595 ua->send_msg(_("Where: %s\n"),
1596 jcr->where?jcr->where:NPRT(job->RestoreWhere));
1599 ua->send_msg(_("Replace: %s\n"
1606 "Plugin Options: %s\n"),
1608 jcr->client->name(),
1609 jcr->rstore->name(),
1610 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
1611 bstrutime(dt, sizeof(dt), jcr->sched_time),
1612 jcr->catalog->name(),
1614 NPRTB(jcr->plugin_options));
1620 jcr->setJobLevel(L_FULL); /* default level */
1622 ua->signal(BNET_RUN_CMD);
1623 if (jcr->getJobType() == JT_COPY) {
1624 prt_type = (char *)"Type: Copy\nTitle: Run Copy Job\n";
1626 prt_type = (char *)"Type: Migration\nTitle: Run Migration Job\n";
1635 "Read Storage: %s\n"
1636 "Write Storage: %s\n"
1643 NPRT(jcr->RestoreBootstrap),
1644 jcr->client->name(),
1645 jcr->fileset->name(),
1646 NPRT(jcr->pool->name()),
1647 jcr->next_pool?jcr->next_pool->name():"*None*",
1648 jcr->rstore->name(),
1649 jcr->wstore?jcr->wstore->name():"*None*",
1650 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
1651 bstrutime(dt, sizeof(dt), jcr->sched_time),
1652 jcr->catalog->name(),
1655 if (jcr->getJobType() == JT_COPY) {
1656 prt_type = _("Run Copy job\n");
1658 prt_type = _("Run Migration job\n");
1665 "Pool: %s (From %s)\n"
1666 "NextPool: %s (From %s)\n"
1667 "Read Storage: %s (From %s)\n"
1668 "Write Storage: %s (From %s)\n"
1675 NPRT(jcr->RestoreBootstrap),
1676 jcr->client->name(),
1677 jcr->fileset->name(),
1678 NPRT(jcr->pool->name()), jcr->pool_source,
1679 jcr->next_pool?jcr->next_pool->name():"*None*",
1680 NPRT(jcr->next_pool_source),
1681 jcr->rstore->name(), jcr->rstore_source,
1682 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
1683 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
1684 bstrutime(dt, sizeof(dt), jcr->sched_time),
1685 jcr->catalog->name(),
1690 ua->error_msg(_("Unknown Job Type=%d\n"), jcr->getJobType());
1697 static bool scan_run_command_line_arguments(UAContext *ua, run_ctx &rc)
1701 static const char *kw[] = { /* command line arguments */
1702 "alljobid", /* 0 Used in a switch() */
1710 "regexwhere", /* 8 where string as a bregexp */
1712 "bootstrap", /* 10 */
1715 "priority", /* 13 */
1716 "yes", /* 14 -- if you change this change YES_POS too */
1717 "verifyjob", /* 15 */
1718 "files", /* 16 number of files to restore */
1719 "catalog", /* 17 override catalog */
1720 "since", /* 18 since */
1721 "cloned", /* 19 cloned */
1722 "verifylist", /* 20 verify output list */
1723 "migrationjob", /* 21 migration job name */
1725 "backupclient", /* 23 */
1726 "restoreclient", /* 24 */
1727 "pluginoptions", /* 25 */
1728 "spooldata", /* 26 */
1730 "ignoreduplicatecheck", /* 28 */
1731 "accurate", /* 29 */
1733 "mediatype", /* 31 */
1734 "nextpool", /* 32 override next pool name */
1739 rc.catalog_name = NULL;
1741 rc.pool_name = NULL;
1742 rc.next_pool_name = NULL;
1743 rc.store_name = NULL;
1744 rc.client_name = NULL;
1745 rc.media_type = NULL;
1746 rc.restore_client_name = NULL;
1747 rc.fileset_name = NULL;
1748 rc.verify_job_name = NULL;
1749 rc.previous_job_name = NULL;
1750 rc.accurate_set = false;
1751 rc.spool_data_set = false;
1752 rc.ignoreduplicatecheck = false;
1754 rc.plugin_options = NULL;
1756 for (i=1; i<ua->argc; i++) {
1757 Dmsg2(800, "Doing arg %d = %s\n", i, ua->argk[i]);
1759 /* Keep looking until we find a good keyword */
1760 for (j=0; !kw_ok && kw[j]; j++) {
1761 if (strcasecmp(ua->argk[i], kw[j]) == 0) {
1762 /* Note, yes and run have no value, so do not fail */
1763 if (!ua->argv[i] && j != YES_POS /*yes*/) {
1764 ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]);
1767 Dmsg2(800, "Got j=%d keyword=%s\n", j, NPRT(kw[j]));
1769 case 0: /* alljobid */
1771 /* Fall through wanted */
1773 if (rc.jid && !rc.mod) {
1774 ua->send_msg(_("JobId specified twice.\n"));
1777 rc.jid = ua->argv[i];
1780 case 2: /* client */
1782 if (rc.client_name) {
1783 ua->send_msg(_("Client specified twice.\n"));
1786 rc.client_name = ua->argv[i];
1789 case 4: /* fileset */
1790 if (rc.fileset_name) {
1791 ua->send_msg(_("FileSet specified twice.\n"));
1794 rc.fileset_name = ua->argv[i];
1798 if (rc.level_name) {
1799 ua->send_msg(_("Level specified twice.\n"));
1802 rc.level_name = ua->argv[i];
1805 case 6: /* storage */
1807 if (rc.store_name) {
1808 ua->send_msg(_("Storage specified twice.\n"));
1811 rc.store_name = ua->argv[i];
1814 case 8: /* regexwhere */
1815 if ((rc.regexwhere || rc.where) && !rc.mod) {
1816 ua->send_msg(_("RegexWhere or Where specified twice.\n"));
1819 rc.regexwhere = ua->argv[i];
1820 if (!acl_access_ok(ua, Where_ACL, rc.regexwhere)) {
1821 ua->send_msg(_("No authorization for \"regexwhere\" specification.\n"));
1827 if ((rc.where || rc.regexwhere) && !rc.mod) {
1828 ua->send_msg(_("Where or RegexWhere specified twice.\n"));
1831 rc.where = ua->argv[i];
1832 if (!acl_access_ok(ua, Where_ACL, rc.where)) {
1833 ua->send_msg(_("No authoriztion for \"where\" specification.\n"));
1838 case 10: /* bootstrap */
1839 if (rc.bootstrap && !rc.mod) {
1840 ua->send_msg(_("Bootstrap specified twice.\n"));
1843 rc.bootstrap = ua->argv[i];
1846 case 11: /* replace */
1847 if (rc.replace && !rc.mod) {
1848 ua->send_msg(_("Replace specified twice.\n"));
1851 rc.replace = ua->argv[i];
1855 if (rc.when && !rc.mod) {
1856 ua->send_msg(_("When specified twice.\n"));
1859 rc.when = ua->argv[i];
1862 case 13: /* Priority */
1863 if (rc.Priority && !rc.mod) {
1864 ua->send_msg(_("Priority specified twice.\n"));
1867 rc.Priority = atoi(ua->argv[i]);
1868 if (rc.Priority <= 0) {
1869 ua->send_msg(_("Priority must be positive nonzero setting it to 10.\n"));
1877 case 15: /* Verify Job */
1878 if (rc.verify_job_name) {
1879 ua->send_msg(_("Verify Job specified twice.\n"));
1882 rc.verify_job_name = ua->argv[i];
1885 case 16: /* files */
1886 rc.files = atoi(ua->argv[i]);
1889 case 17: /* catalog */
1890 rc.catalog_name = ua->argv[i];
1893 case 18: /* since */
1894 rc.since = ua->argv[i];
1897 case 19: /* cloned */
1901 case 20: /* write verify list output */
1902 rc.verify_list = ua->argv[i];
1905 case 21: /* Migration Job */
1906 if (rc.previous_job_name) {
1907 ua->send_msg(_("Migration Job specified twice.\n"));
1910 rc.previous_job_name = ua->argv[i];
1915 ua->send_msg(_("Pool specified twice.\n"));
1918 rc.pool_name = ua->argv[i];
1921 case 23: /* backupclient */
1922 if (rc.client_name) {
1923 ua->send_msg(_("Client specified twice.\n"));
1926 rc.client_name = ua->argv[i];
1929 case 24: /* restoreclient */
1930 if (rc.restore_client_name && !rc.mod) {
1931 ua->send_msg(_("Restore Client specified twice.\n"));
1934 rc.restore_client_name = ua->argv[i];
1937 case 25: /* pluginoptions */
1938 ua->send_msg(_("Plugin Options not yet implemented.\n"));
1940 if (rc.plugin_options) {
1941 ua->send_msg(_("Plugin Options specified twice.\n"));
1944 rc.plugin_options = ua->argv[i];
1945 if (!acl_access_ok(ua, PluginOptions_ACL, rc.plugin_options)) {
1946 ua->send_msg(_("No authoriztion for \"PluginOptions\" specification.\n"));
1951 case 26: /* spooldata */
1952 if (rc.spool_data_set) {
1953 ua->send_msg(_("Spool flag specified twice.\n"));
1956 if (is_yesno(ua->argv[i], &rc.spool_data)) {
1957 rc.spool_data_set = true;
1960 ua->send_msg(_("Invalid spooldata flag.\n"));
1963 case 27: /* comment */
1964 rc.comment = ua->argv[i];
1967 case 28: /* ignoreduplicatecheck */
1968 if (rc.ignoreduplicatecheck_set) {
1969 ua->send_msg(_("IgnoreDuplicateCheck flag specified twice.\n"));
1972 if (is_yesno(ua->argv[i], &rc.ignoreduplicatecheck)) {
1973 rc.ignoreduplicatecheck_set = true;
1976 ua->send_msg(_("Invalid ignoreduplicatecheck flag.\n"));
1979 case 29: /* accurate */
1980 if (rc.accurate_set) {
1981 ua->send_msg(_("Accurate flag specified twice.\n"));
1984 if (is_yesno(ua->argv[i], &rc.accurate)) {
1985 rc.accurate_set = true;
1988 ua->send_msg(_("Invalid accurate flag.\n"));
1993 ua->send_msg(_("Job name specified twice.\n"));
1996 rc.job_name = ua->argv[i];
1999 case 31: /* mediatype */
2000 if (rc.media_type) {
2001 ua->send_msg(_("Media Type specified twice.\n"));
2004 rc.media_type = ua->argv[i];
2007 case 32: /* Next Pool */
2008 if (rc.next_pool_name) {
2009 ua->send_msg(_("NextPool specified twice.\n"));
2012 rc.next_pool_name = ua->argv[i];
2018 } /* end strcase compare */
2019 } /* end keyword loop */
2022 * End of keyword for loop -- if not found, we got a bogus keyword
2025 Dmsg1(800, "%s not found\n", ua->argk[i]);
2027 * Special case for Job Name, it can be the first
2028 * keyword that has no value.
2030 if (!rc.job_name && !ua->argv[i]) {
2031 rc.job_name = ua->argk[i]; /* use keyword as job name */
2032 Dmsg1(800, "Set jobname=%s\n", rc.job_name);
2034 ua->send_msg(_("Invalid keyword: %s\n"), ua->argk[i]);
2038 } /* end argc loop */
2040 Dmsg0(800, "Done scan.\n");
2042 if (!is_comment_legal(ua, rc.comment)) {
2046 if (rc.catalog_name) {
2047 rc.catalog = GetCatalogResWithName(rc.catalog_name);
2048 if (rc.catalog == NULL) {
2049 ua->error_msg(_("Catalog \"%s\" not found\n"), rc.catalog_name);
2052 if (!acl_access_ok(ua, Catalog_ACL, rc.catalog->name())) {
2053 ua->error_msg(_("No authorization. Catalog \"%s\".\n"), rc.catalog->name());
2057 Dmsg1(800, "Using catalog=%s\n", NPRT(rc.catalog_name));
2059 if (!get_job(ua, rc)) {
2063 if (!get_pool(ua, rc)) {
2067 if (!get_next_pool(ua, rc)) {
2071 if (!get_storage(ua, rc)) {
2076 if (!get_client(ua, rc)) {
2080 if (!get_fileset(ua, rc)) {
2084 if (rc.verify_job_name) {
2085 rc.verify_job = GetJobResWithName(rc.verify_job_name);
2086 if (!rc.verify_job) {
2087 ua->send_msg(_("Verify Job \"%s\" not found.\n"), rc.verify_job_name);
2088 rc.verify_job = select_job_resource(ua);
2090 } else if (!rc.verify_job) {
2091 rc.verify_job = rc.job->verify_job;
2094 if (rc.previous_job_name) {
2095 rc.previous_job = GetJobResWithName(rc.previous_job_name);
2096 if (!rc.previous_job) {
2097 ua->send_msg(_("Migration Job \"%s\" not found.\n"), rc.previous_job_name);
2098 rc.previous_job = select_job_resource(ua);
2101 rc.previous_job = rc.job->verify_job;