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);
315 rc.next_pool = rc.pool->NextPool; /* use default */
317 if (rc.next_pool && !acl_access_ok(ua, Pool_ACL, rc.next_pool->name())) {
318 ua->error_msg(_("No authorization. NextPool \"%s\".\n"), rc.next_pool->name());
322 Dmsg1(100, "Using NextPool=%s\n", NPRT(rc.next_pool->name()));
329 * Fill in client data according to what is setup
330 * in the run context, and make sure the user
331 * has authorized access to it.
333 static bool get_client(UAContext *ua, run_ctx &rc)
335 if (rc.client_name) {
336 rc.client = GetClientResWithName(rc.client_name);
338 if (*rc.client_name != 0) {
339 ua->warning_msg(_("Client \"%s\" not found.\n"), rc.client_name);
341 rc.client = select_client_resource(ua);
343 } else if (!rc.client) {
344 rc.client = rc.job->client; /* use default */
348 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
349 ua->error_msg(_("No authorization. Client \"%s\".\n"),
353 Dmsg1(800, "Using client=%s\n", rc.client->name());
355 if (rc.restore_client_name) {
356 rc.client = GetClientResWithName(rc.restore_client_name);
358 if (*rc.restore_client_name != 0) {
359 ua->warning_msg(_("Restore Client \"%s\" not found.\n"), rc.restore_client_name);
361 rc.client = select_client_resource(ua);
363 } else if (!rc.client) {
364 rc.client = rc.job->client; /* use default */
368 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
369 ua->error_msg(_("No authorization. Client \"%s\".\n"),
373 Dmsg1(800, "Using restore client=%s\n", rc.client->name());
379 * Fill in fileset data according to what is setup
380 * in the run context, and make sure the user
381 * has authorized access to it.
383 static bool get_fileset(UAContext *ua, run_ctx &rc)
385 if (rc.fileset_name) {
386 rc.fileset = GetFileSetResWithName(rc.fileset_name);
388 ua->send_msg(_("FileSet \"%s\" not found.\n"), rc.fileset_name);
389 rc.fileset = select_fileset_resource(ua);
391 } else if (!rc.fileset) {
392 rc.fileset = rc.job->fileset; /* use default */
396 } else if (!acl_access_ok(ua, FileSet_ACL, rc.fileset->name())) {
397 ua->send_msg(_("No authorization. FileSet \"%s\".\n"),
405 * Fill in storage data according to what is setup
406 * in the run context, and make sure the user
407 * has authorized access to it.
409 static bool get_storage(UAContext *ua, run_ctx &rc)
412 rc.store->store = GetStoreResWithName(rc.store_name);
413 pm_strcpy(rc.store->store_source, _("command line"));
414 if (!rc.store->store) {
415 if (*rc.store_name != 0) {
416 ua->warning_msg(_("Storage \"%s\" not found.\n"), rc.store_name);
418 rc.store->store = select_storage_resource(ua);
419 pm_strcpy(rc.store->store_source, _("user selection"));
421 } else if (!rc.store->store) {
422 get_job_storage(rc.store, rc.job, NULL); /* use default */
424 if (!rc.store->store) {
425 ua->error_msg(_("No storage specified.\n"));
427 } else if (!acl_access_ok(ua, Storage_ACL, rc.store->store->name())) {
428 ua->error_msg(_("No authorization. Storage \"%s\".\n"),
429 rc.store->store->name());
432 Dmsg1(800, "Using storage=%s\n", rc.store->store->name());
437 * Get and pass back a list of Jobids in rc.jid
439 static bool get_jobid_list(UAContext *ua, sellist &sl, run_ctx &rc)
446 memset(&jr, 0, sizeof(jr));
448 /* See if any JobId is specified */
449 if ((i=find_arg(ua, "jobid")) >= 0) {
450 rc.jid = ua->argv[i];
452 ua->send_msg(_("No JobId specified.\n"));
455 if (!sl.set_string(ua->argv[i], true)) {
456 ua->send_msg("%s", sl.get_errmsg());
462 /* No JobId list give, so see if he specified a Job */
463 if ((i=find_arg(ua, "job")) >= 0) {
464 rc.job_name = ua->argv[i];
465 if (!get_job(ua, rc)) {
466 ua->send_msg(_("Invalid or no Job name specified.\n"));
470 jr.limit = 100; /* max 100 records */
472 bstrncpy(jr.Name, rc.job_name, sizeof(jr.Name));
476 jr.JobStatus = rc.jr.JobStatus;
477 Dmsg2(100, "JobStatus=%d JobName=%s\n", jr.JobStatus, jr.Name);
478 /* rc.JobIds is alist of all records found and printed */
479 rc.JobIds = db_list_job_records(ua->jcr, ua->db, &jr, prtit, ua, INCOMPLETE_JOBS);
480 if (!rc.JobIds || rc.JobIds->size()==0 ||
481 !get_selection_list(ua, sl, _("Enter the JobId list to select: "), false)) {
484 Dmsg1(100, "list=%s\n", sl.get_list());
486 * Make sure each item entered is in the JobIds list
488 while ( (JobId = sl.next()) > 0) {
489 foreach_alist(pJobId, rc.JobIds) {
490 if (JobId == str_to_int64(pJobId)) {
497 ua->error_msg(_("JobId=%d entered is not in the list.\n"), JobId);
501 sl.begin(); /* reset to walk list again */
506 static bool get_jobid_from_list(UAContext *ua, sellist &sl, run_ctx &rc)
513 if ((JobId = sl.next()) < 0) {
514 Dmsg1(100, "sl.next()=%d\n", JobId);
518 rc.jr.JobId = rc.JobId = JobId;
519 Dmsg1(100, "Next JobId=%d\n", rc.JobId);
520 if (!db_get_job_record(ua->jcr, ua->db, &rc.jr)) {
521 ua->error_msg(_("Could not get job record for selected JobId=%d. ERR=%s"),
522 rc.JobId, db_strerror(ua->db));
525 Dmsg3(100, "Job=%s JobId=%d JobStatus=%c\n", rc.jr.Name, rc.jr.JobId,
527 rc.job_name = rc.jr.Name;
528 if (!get_job(ua, rc)) {
531 if (!get_pool(ua, rc)) {
534 get_job_storage(rc.store, rc.job, NULL);
535 rc.client_name = rc.job->client->hdr.name;
536 if (!get_client(ua, rc)) {
539 if (!get_fileset(ua, rc)) {
542 if (!get_storage(ua, rc)) {
549 * Restart Canceled, Failed, or Incomplete Jobs
551 * Returns: 0 on error
555 int restart_cmd(UAContext *ua, const char *cmd)
563 const char *status_name;
567 {"Incomplete", JS_Incomplete},
568 {"Canceled", JS_Canceled},
569 {"Failed", JS_FatalError},
574 if (!open_client_db(ua)) {
579 for (i=1; i<ua->argc; i++) {
580 for (j=0; kw[j].status_name; j++) {
581 if (strcasecmp(ua->argk[i], kw[j].status_name) == 0) {
582 rc.jr.JobStatus = kw[j].job_status;
588 if (!got_kw) { /* Must prompt user */
589 start_prompt(ua, _("You have the following choices:\n"));
590 for (i=0; kw[i].status_name; i++) {
591 add_prompt(ua, kw[i].status_name);
593 i = do_prompt(ua, NULL, _("Select termination code: "), NULL, 0);
597 rc.jr.JobStatus = kw[i].job_status;
600 /* type now has what job termination code we want to look at */
601 Dmsg1(100, "Termination code=%c\n", rc.jr.JobStatus);
603 /* Get a list of JobIds to restore */
604 if (!get_jobid_list(ua, sl, rc)) {
606 rc.JobIds->destroy();
610 Dmsg1(100, "list=%s\n", sl.get_list());
612 while (get_jobid_from_list(ua, sl, rc)) {
614 * Create JCR to run job. NOTE!!! after this point, free_jcr()
618 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
619 set_jcr_defaults(jcr, rc.job);
620 jcr->unlink_bsr = ua->jcr->unlink_bsr; /* copy unlink flag from caller */
621 ua->jcr->unlink_bsr = false;
624 if (!set_run_context_in_jcr(ua, jcr, rc)) {
627 start_job(ua, jcr, rc);
635 rc.JobIds->destroy();
637 return 0; /* do not run */
640 int modify_job_parameters(UAContext *ua, JCR *jcr, run_ctx &rc)
645 * At user request modify parameters of job to be run.
647 if (ua->cmd[0] != 0 && strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0){
650 start_prompt(ua, _("Parameters to modify:\n"));
651 add_prompt(ua, _("Level")); /* 0 */
652 add_prompt(ua, _("Storage")); /* 1 */
653 add_prompt(ua, _("Job")); /* 2 */
654 add_prompt(ua, _("FileSet")); /* 3 */
655 if (jcr->getJobType() == JT_RESTORE) {
656 add_prompt(ua, _("Restore Client")); /* 4 */
658 add_prompt(ua, _("Client")); /* 4 */
660 add_prompt(ua, _("When")); /* 5 */
661 add_prompt(ua, _("Priority")); /* 6 */
662 if (jcr->getJobType() == JT_BACKUP ||
663 jcr->getJobType() == JT_COPY ||
664 jcr->getJobType() == JT_MIGRATE ||
665 jcr->getJobType() == JT_VERIFY) {
666 add_prompt(ua, _("Pool")); /* 7 */
667 if ((jcr->getJobType() == JT_BACKUP && /* Virtual full */
668 jcr->is_JobLevel(L_VIRTUAL_FULL)) ||
669 jcr->getJobType() == JT_COPY ||
670 jcr->getJobType() == JT_MIGRATE) {
671 add_prompt(ua, _("NextPool")); /* 8 */
672 } else if (jcr->getJobType() == JT_VERIFY) {
673 add_prompt(ua, _("Verify Job")); /* 8 */
675 } else if (jcr->getJobType() == JT_RESTORE) {
676 add_prompt(ua, _("Bootstrap")); /* 7 */
677 add_prompt(ua, _("Where")); /* 8 */
678 add_prompt(ua, _("File Relocation"));/* 9 */
679 add_prompt(ua, _("Replace")); /* 10 */
680 add_prompt(ua, _("JobId")); /* 11 */
682 if (jcr->getJobType() == JT_BACKUP || jcr->getJobType() == JT_RESTORE) {
683 add_prompt(ua, _("Plugin Options")); /* 12 */
685 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
688 select_job_level(ua, jcr);
692 rc.store->store = select_storage_resource(ua);
693 if (rc.store->store) {
694 pm_strcpy(rc.store->store_source, _("user selection"));
695 set_rwstorage(jcr, rc.store);
701 rc.job = select_job_resource(ua);
704 set_jcr_defaults(jcr, rc.job);
710 rc.fileset = select_fileset_resource(ua);
712 jcr->fileset = rc.fileset;
718 rc.client = select_client_resource(ua);
720 jcr->client = rc.client;
726 if (!get_cmd(ua, _("Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now): "))) {
729 if (ua->cmd[0] == 0) {
730 jcr->sched_time = time(NULL);
732 jcr->sched_time = str_to_utime(ua->cmd);
733 if (jcr->sched_time == 0) {
734 ua->send_msg(_("Invalid time, using current time.\n"));
735 jcr->sched_time = time(NULL);
741 if (!get_pint(ua, _("Enter new Priority: "))) {
744 if (ua->pint32_val == 0) {
745 ua->send_msg(_("Priority must be a positive integer.\n"));
747 jcr->JobPriority = ua->pint32_val;
751 /* Pool or Bootstrap depending on JobType */
752 if (jcr->getJobType() == JT_BACKUP ||
753 jcr->getJobType() == JT_COPY ||
754 jcr->getJobType() == JT_MIGRATE ||
755 jcr->getJobType() == JT_VERIFY) { /* Pool */
756 rc.pool = select_pool_resource(ua);
759 Dmsg1(100, "Set new pool=%s\n", jcr->pool->name());
766 if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
769 if (jcr->RestoreBootstrap) {
770 free(jcr->RestoreBootstrap);
771 jcr->RestoreBootstrap = NULL;
773 if (ua->cmd[0] != 0) {
774 jcr->RestoreBootstrap = bstrdup(ua->cmd);
775 fd = fopen(jcr->RestoreBootstrap, "rb");
778 ua->send_msg(_("Warning cannot open %s: ERR=%s\n"),
779 jcr->RestoreBootstrap, be.bstrerror());
780 free(jcr->RestoreBootstrap);
781 jcr->RestoreBootstrap = NULL;
788 /* Specify Next Pool */
789 if ((jcr->getJobType() == JT_BACKUP && /* Virtual full */
790 jcr->is_JobLevel(L_VIRTUAL_FULL)) ||
791 jcr->getJobType() == JT_COPY ||
792 jcr->getJobType() == JT_MIGRATE) {
793 rc.next_pool = select_pool_resource(ua);
795 jcr->next_pool = rc.next_pool;
800 if (jcr->getJobType() == JT_VERIFY) {
801 rc.verify_job = select_job_resource(ua);
803 jcr->verify_job = rc.verify_job;
808 if (!get_cmd(ua, _("Please enter the full path prefix for restore (/ for none): "))) {
811 if (jcr->RegexWhere) { /* cannot use regexwhere and where */
812 free(jcr->RegexWhere);
813 jcr->RegexWhere = NULL;
819 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
822 jcr->where = bstrdup(ua->cmd);
825 /* File relocation */
826 select_where_regexp(ua, jcr);
830 start_prompt(ua, _("Replace:\n"));
831 for (i=0; ReplaceOptions[i].name; i++) {
832 add_prompt(ua, ReplaceOptions[i].name);
834 opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
836 rc.replace = ReplaceOptions[opt].name;
837 jcr->replace = ReplaceOptions[opt].token;
842 rc.jid = NULL; /* force reprompt */
843 jcr->RestoreJobId = 0;
844 if (jcr->RestoreBootstrap) {
845 ua->send_msg(_("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
850 //generate_plugin_event(jcr, bEventJobConfig, &rc);
851 if (!get_cmd(ua, _("Please Plugin Options string: "))) {
854 if (jcr->plugin_options) {
855 free(jcr->plugin_options);
856 jcr->plugin_options = NULL;
858 jcr->plugin_options = bstrdup(ua->cmd);
860 case -1: /* error or cancel */
876 * Put the run context that we have at this point into the JCR.
877 * That allows us to re-ask for the run context.
878 * This subroutine can be called multiple times, so it
879 * must keep any prior settings.
881 static bool set_run_context_in_jcr(UAContext *ua, JCR *jcr, run_ctx &rc)
885 jcr->verify_job = rc.verify_job;
886 jcr->previous_job = rc.previous_job;
888 jcr->next_pool = rc.next_pool;
890 jcr->cmdline_next_pool_override = true;
893 pm_strcpy(jcr->pool_source, _("Command input"));
894 } else if (jcr->pool != jcr->job->pool) {
895 pm_strcpy(jcr->pool_source, _("User input"));
897 if (rc.next_pool_name) {
898 pm_strcpy(jcr->next_pool_source, _("Command input"));
899 } else if (jcr->next_pool != jcr->pool->NextPool) {
900 pm_strcpy(jcr->next_pool_source, _("User input"));
903 set_rwstorage(jcr, rc.store);
904 jcr->client = rc.client;
906 pm_strcpy(jcr->client_name, rc.client->name());
908 pm_strcpy(jcr->client_name, "**Dummy**");
911 if (!jcr->media_type) {
912 jcr->media_type = get_pool_memory(PM_NAME);
914 pm_strcpy(jcr->media_type, rc.media_type);
916 jcr->fileset = rc.fileset;
917 jcr->ExpectedFiles = rc.files;
919 jcr->catalog = rc.catalog;
920 pm_strcpy(jcr->catalog_source, _("User input"));
923 pm_strcpy(jcr->comment, rc.comment);
929 jcr->where = bstrdup(rc.where);
934 if (jcr->RegexWhere) {
935 free(jcr->RegexWhere);
937 jcr->RegexWhere = bstrdup(rc.regexwhere);
938 rc.regexwhere = NULL;
942 jcr->sched_time = str_to_utime(rc.when);
943 if (jcr->sched_time == 0) {
944 ua->send_msg(_("Invalid time, using current time.\n"));
945 jcr->sched_time = time(NULL);
951 if (jcr->RestoreBootstrap) {
952 free(jcr->RestoreBootstrap);
954 jcr->RestoreBootstrap = bstrdup(rc.bootstrap);
958 if (rc.plugin_options) {
959 if (jcr->plugin_options) {
960 free(jcr->plugin_options);
962 jcr->plugin_options = bstrdup(rc.plugin_options);
963 rc.plugin_options = NULL;
968 for (i=0; ReplaceOptions[i].name; i++) {
969 if (strcasecmp(rc.replace, ReplaceOptions[i].name) == 0) {
970 jcr->replace = ReplaceOptions[i].token;
974 ua->send_msg(_("Invalid replace option: %s\n"), rc.replace);
977 } else if (rc.job->replace) {
978 jcr->replace = rc.job->replace;
980 jcr->replace = REPLACE_ALWAYS;
984 /* Set Snapshot Retention (Job <- Client) */
986 jcr->snapshot_retention = jcr->client->SnapRetention;
988 if (jcr->job && jcr->job->SnapRetention > 0) {
989 jcr->snapshot_retention = jcr->job->SnapRetention;
993 jcr->JobPriority = rc.Priority;
999 jcr->stime = get_pool_memory(PM_MESSAGE);
1001 pm_strcpy(jcr->stime, rc.since);
1006 jcr->cloned = rc.cloned;
1010 /* If pool changed, update migration write storage */
1011 if (jcr->is_JobType(JT_MIGRATE) || jcr->is_JobType(JT_COPY) ||
1012 (jcr->is_JobType(JT_BACKUP) && jcr->is_JobLevel(L_VIRTUAL_FULL))) {
1013 if (!set_mac_wstorage(ua, jcr, rc.pool, rc.next_pool,
1014 jcr->next_pool_source)) {
1018 rc.replace = ReplaceOptions[0].name;
1019 for (i=0; ReplaceOptions[i].name; i++) {
1020 if (ReplaceOptions[i].token == jcr->replace) {
1021 rc.replace = ReplaceOptions[i].name;
1024 if (rc.level_name) {
1025 if (!get_level_from_name(jcr, rc.level_name)) {
1026 ua->send_msg(_("Level \"%s\" not valid.\n"), rc.level_name);
1029 rc.level_name = NULL;
1032 /* Note, this is also MigrateJobId and a VerifyJobId */
1033 jcr->RestoreJobId = str_to_int64(rc.jid);
1035 /* Copy also this parameter for VirtualFull in jcr->JobIds */
1037 jcr->JobIds = get_pool_memory(PM_FNAME);
1039 pm_strcpy(jcr->JobIds, rc.jid);
1040 jcr->use_all_JobIds = rc.alljobid; /* if we found the "alljobid=" kw */
1041 rc.alljobid = false;
1045 /* Some options are not available through the menu
1046 * TODO: Add an advanced menu?
1048 if (rc.spool_data_set) {
1049 jcr->spool_data = rc.spool_data;
1052 if (rc.accurate_set) {
1053 jcr->accurate = rc.accurate;
1056 /* Used by migration jobs that can have the same name,
1057 * but can run at the same time
1059 if (rc.ignoreduplicatecheck_set) {
1060 jcr->IgnoreDuplicateJobChecking = rc.ignoreduplicatecheck;
1066 static void select_where_regexp(UAContext *ua, JCR *jcr)
1069 char *strip_prefix, *add_prefix, *add_suffix, *rwhere;
1070 strip_prefix = add_suffix = rwhere = add_prefix = NULL;
1073 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s\n"),
1074 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix));
1076 start_prompt(ua, _("This will replace your current Where value\n"));
1077 add_prompt(ua, _("Strip prefix")); /* 0 */
1078 add_prompt(ua, _("Add prefix")); /* 1 */
1079 add_prompt(ua, _("Add file suffix")); /* 2 */
1080 add_prompt(ua, _("Enter a regexp")); /* 3 */
1081 add_prompt(ua, _("Test filename manipulation")); /* 4 */
1082 add_prompt(ua, _("Use this ?")); /* 5 */
1084 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
1087 if (get_cmd(ua, _("Please enter the path prefix to strip: "))) {
1088 if (strip_prefix) bfree(strip_prefix);
1089 strip_prefix = bstrdup(ua->cmd);
1095 if (get_cmd(ua, _("Please enter the path prefix to add (/ for none): "))) {
1096 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
1100 if (add_prefix) bfree(add_prefix);
1101 add_prefix = bstrdup(ua->cmd);
1106 if (get_cmd(ua, _("Please enter the file suffix to add: "))) {
1107 if (add_suffix) bfree(add_suffix);
1108 add_suffix = bstrdup(ua->cmd);
1113 if (get_cmd(ua, _("Please enter a valid regexp (!from!to!): "))) {
1114 if (rwhere) bfree(rwhere);
1115 rwhere = bstrdup(ua->cmd);
1124 if (rwhere && rwhere[0] != '\0') {
1125 regs = get_bregexps(rwhere);
1126 ua->send_msg(_("regexwhere=%s\n"), NPRT(rwhere));
1128 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
1129 regexp = (char *) bmalloc (len * sizeof(char));
1130 bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix);
1131 regs = get_bregexps(regexp);
1132 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s result=%s\n"),
1133 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix), NPRT(regexp));
1139 ua->send_msg(_("Cannot use your regexp\n"));
1142 ua->send_msg(_("Enter a period (.) to stop this test\n"));
1143 while (get_cmd(ua, _("Please enter filename to test: "))) {
1144 apply_bregexps(ua->cmd, regs, &result);
1145 ua->send_msg(_("%s -> %s\n"), ua->cmd, result);
1147 free_bregexps(regs);
1154 case -1: /* error or cancel */
1160 /* replace the existing where */
1166 /* replace the existing regexwhere */
1167 if (jcr->RegexWhere) {
1168 bfree(jcr->RegexWhere);
1169 jcr->RegexWhere = NULL;
1173 jcr->RegexWhere = bstrdup(rwhere);
1174 } else if (strip_prefix || add_prefix || add_suffix) {
1175 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
1176 jcr->RegexWhere = (char *) bmalloc(len*sizeof(char));
1177 bregexp_build_where(jcr->RegexWhere, len, strip_prefix, add_prefix, add_suffix);
1180 regs = get_bregexps(jcr->RegexWhere);
1182 free_bregexps(regs);
1185 if (jcr->RegexWhere) {
1186 bfree(jcr->RegexWhere);
1187 jcr->RegexWhere = NULL;
1189 ua->send_msg(_("Cannot use your regexp.\n"));
1193 if (strip_prefix) bfree(strip_prefix);
1194 if (add_prefix) bfree(add_prefix);
1195 if (add_suffix) bfree(add_suffix);
1196 if (rwhere) bfree(rwhere);
1199 static void select_job_level(UAContext *ua, JCR *jcr)
1201 if (jcr->getJobType() == JT_BACKUP) {
1202 start_prompt(ua, _("Levels:\n"));
1203 // add_prompt(ua, _("Base"));
1204 add_prompt(ua, _("Full"));
1205 add_prompt(ua, _("Incremental"));
1206 add_prompt(ua, _("Differential"));
1207 add_prompt(ua, _("Since"));
1208 add_prompt(ua, _("VirtualFull"));
1209 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
1211 // jcr->JobLevel = L_BASE;
1214 jcr->setJobLevel(L_FULL);
1217 jcr->setJobLevel(L_INCREMENTAL);
1220 jcr->setJobLevel(L_DIFFERENTIAL);
1223 jcr->setJobLevel(L_SINCE);
1226 jcr->setJobLevel(L_VIRTUAL_FULL);
1231 } else if (jcr->getJobType() == JT_VERIFY) {
1232 start_prompt(ua, _("Levels:\n"));
1233 add_prompt(ua, _("Initialize Catalog"));
1234 add_prompt(ua, _("Verify Catalog"));
1235 add_prompt(ua, _("Verify Volume to Catalog"));
1236 add_prompt(ua, _("Verify Disk to Catalog"));
1237 add_prompt(ua, _("Verify Volume Data (not yet implemented)"));
1238 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
1240 jcr->setJobLevel(L_VERIFY_INIT);
1243 jcr->setJobLevel(L_VERIFY_CATALOG);
1246 jcr->setJobLevel(L_VERIFY_VOLUME_TO_CATALOG);
1249 jcr->setJobLevel(L_VERIFY_DISK_TO_CATALOG);
1252 jcr->setJobLevel(L_VERIFY_DATA);
1258 ua->warning_msg(_("Level not appropriate for this Job. Cannot be changed.\n"));
1263 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char *verify_list,
1264 char *jid, const char *replace, char *client_name)
1267 char dt[MAX_TIME_LENGTH];
1269 Dmsg1(800, "JobType=%c\n", jcr->getJobType());
1270 switch (jcr->getJobType()) {
1273 ua->signal(BNET_RUN_CMD);
1274 ua->send_msg("Type: Admin\n"
1275 "Title: Run Admin Job\n"
1283 jcr->fileset->name(),
1284 NPRT(jcr->client->name()),
1285 jcr->wstore?jcr->wstore->name():"*None*",
1286 bstrutime(dt, sizeof(dt), jcr->sched_time),
1289 ua->send_msg(_("Run Admin Job\n"
1297 jcr->fileset->name(),
1298 NPRT(jcr->client->name()),
1299 jcr->wstore?jcr->wstore->name():"*None*",
1300 bstrutime(dt, sizeof(dt), jcr->sched_time),
1303 jcr->setJobLevel(L_FULL);
1307 char next_pool[MAX_NAME_LENGTH + 50];
1309 if (jcr->getJobType() == JT_BACKUP) {
1311 ua->signal(BNET_RUN_CMD);
1312 if (jcr->is_JobLevel(L_VIRTUAL_FULL)) {
1313 bsnprintf(next_pool, sizeof(next_pool), "NextPool: %s\n",
1314 jcr->next_pool ? jcr->next_pool->name() : "*None*");
1316 ua->send_msg("Type: Backup\n"
1317 "Title: Run Backup Job\n"
1329 level_to_str(jcr->getJobLevel()),
1330 jcr->client->name(),
1331 jcr->fileset->name(),
1332 NPRT(jcr->pool->name()),
1334 jcr->wstore?jcr->wstore->name():"*None*",
1335 bstrutime(dt, sizeof(dt), jcr->sched_time),
1337 jcr->plugin_options?"Plugin Options: ":"",
1338 jcr->plugin_options?jcr->plugin_options:"",
1339 jcr->plugin_options?"\n":"");
1341 if (jcr->is_JobLevel(L_VIRTUAL_FULL)) {
1342 bsnprintf(next_pool, sizeof(next_pool),
1343 "NextPool: %s (From %s)\n",
1344 jcr->next_pool ? jcr->next_pool->name() : "*None*",
1345 jcr->next_pool_source);
1347 ua->send_msg(_("Run Backup job\n"
1352 "Pool: %s (From %s)\n"
1354 "Storage: %s (From %s)\n"
1359 level_to_str(jcr->getJobLevel()),
1360 jcr->client->name(),
1361 jcr->fileset->name(),
1362 NPRT(jcr->pool->name()), jcr->pool_source,
1364 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
1365 bstrutime(dt, sizeof(dt), jcr->sched_time),
1367 jcr->plugin_options?"Plugin Options: ":"",
1368 jcr->plugin_options?jcr->plugin_options:"",
1369 jcr->plugin_options?"\n":"");
1371 } else { /* JT_VERIFY */
1374 if (jcr->verify_job) {
1375 Name = jcr->verify_job->name();
1376 } else if (jcr->RestoreJobId) { /* Display job name if jobid requested */
1377 memset(&jr, 0, sizeof(jr));
1378 jr.JobId = jcr->RestoreJobId;
1379 if (!db_get_job_record(jcr, ua->db, &jr)) {
1380 ua->error_msg(_("Could not get job record for selected JobId. ERR=%s"),
1381 db_strerror(ua->db));
1389 verify_list = job->WriteVerifyList;
1395 ua->signal(BNET_RUN_CMD);
1396 ua->send_msg("Type: Verify\n"
1397 "Title: Run Verify Job\n"
1402 "Pool: %s (From %s)\n"
1403 "Storage: %s (From %s)\n"
1409 level_to_str(jcr->getJobLevel()),
1410 jcr->client->name(),
1411 jcr->fileset->name(),
1412 NPRT(jcr->pool->name()), jcr->pool_source,
1413 jcr->rstore->name(), jcr->rstore_source,
1416 bstrutime(dt, sizeof(dt), jcr->sched_time),
1419 ua->send_msg(_("Run Verify Job\n"
1424 "Pool: %s (From %s)\n"
1425 "Storage: %s (From %s)\n"
1431 level_to_str(jcr->getJobLevel()),
1432 jcr->client->name(),
1433 jcr->fileset->name(),
1434 NPRT(jcr->pool->name()), jcr->pool_source,
1435 jcr->rstore->name(), jcr->rstore_source,
1438 bstrutime(dt, sizeof(dt), jcr->sched_time),
1444 if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
1446 jcr->RestoreJobId = str_to_int64(jid);
1448 if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
1451 jcr->RestoreJobId = ua->int64_val;
1454 jcr->setJobLevel(L_FULL); /* default level */
1455 Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId);
1456 if (jcr->RestoreJobId == 0) {
1457 /* RegexWhere is take before RestoreWhere */
1458 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
1460 ua->signal(BNET_RUN_CMD);
1461 ua->send_msg("Type: Restore\n"
1462 "Title: Run Restore Job\n"
1468 "Backup Client: %s\n"
1469 "Restore Client: %s\n"
1474 "Plugin Options: %s\n",
1476 NPRT(jcr->RestoreBootstrap),
1477 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
1479 jcr->fileset->name(),
1481 jcr->client->name(),
1482 jcr->rstore->name(),
1483 bstrutime(dt, sizeof(dt), jcr->sched_time),
1484 jcr->catalog->name(),
1486 NPRTB(jcr->plugin_options));
1489 ua->send_msg(_("Run Restore job\n"
1495 "Backup Client: %s\n"
1496 "Restore Client: %s\n"
1501 "Plugin Options: %s\n"),
1503 NPRT(jcr->RestoreBootstrap),
1504 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
1506 jcr->fileset->name(),
1508 jcr->client->name(),
1509 jcr->rstore->name(),
1510 bstrutime(dt, sizeof(dt), jcr->sched_time),
1511 jcr->catalog->name(),
1513 NPRTB(jcr->plugin_options));
1517 ua->signal(BNET_RUN_CMD);
1518 ua->send_msg("Type: Restore\n"
1519 "Title: Run Restore job\n"
1525 "Backup Client: %s\n"
1526 "Restore Client: %s\n"
1531 "Plugin Options: %s\n",
1533 NPRT(jcr->RestoreBootstrap),
1534 jcr->where?jcr->where:NPRT(job->RestoreWhere),
1536 jcr->fileset->name(),
1538 jcr->client->name(),
1539 jcr->rstore->name(),
1540 bstrutime(dt, sizeof(dt), jcr->sched_time),
1541 jcr->catalog->name(),
1543 NPRTB(jcr->plugin_options));
1546 ua->send_msg(_("Run Restore job\n"
1552 "Backup Client: %s\n"
1553 "Restore Client: %s\n"
1558 "Plugin Options: %s\n"),
1560 NPRT(jcr->RestoreBootstrap),
1561 jcr->where?jcr->where:NPRT(job->RestoreWhere),
1563 jcr->fileset->name(),
1565 jcr->client->name(),
1566 jcr->rstore->name(),
1567 bstrutime(dt, sizeof(dt), jcr->sched_time),
1568 jcr->catalog->name(),
1570 NPRTB(jcr->plugin_options));
1575 /* ***FIXME*** This needs to be fixed for bat */
1576 if (ua->api) ua->signal(BNET_RUN_CMD);
1577 ua->send_msg(_("Run Restore job\n"
1581 NPRT(jcr->RestoreBootstrap));
1583 /* RegexWhere is take before RestoreWhere */
1584 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
1585 ua->send_msg(_("RegexWhere: %s\n"),
1586 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere);
1588 ua->send_msg(_("Where: %s\n"),
1589 jcr->where?jcr->where:NPRT(job->RestoreWhere));
1592 ua->send_msg(_("Replace: %s\n"
1599 "Plugin Options: %s\n"),
1601 jcr->client->name(),
1602 jcr->rstore->name(),
1603 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
1604 bstrutime(dt, sizeof(dt), jcr->sched_time),
1605 jcr->catalog->name(),
1607 NPRTB(jcr->plugin_options));
1613 jcr->setJobLevel(L_FULL); /* default level */
1615 ua->signal(BNET_RUN_CMD);
1616 if (jcr->getJobType() == JT_COPY) {
1617 prt_type = (char *)"Type: Copy\nTitle: Run Copy Job\n";
1619 prt_type = (char *)"Type: Migration\nTitle: Run Migration Job\n";
1628 "Read Storage: %s\n"
1629 "Write Storage: %s\n"
1636 NPRT(jcr->RestoreBootstrap),
1637 jcr->client->name(),
1638 jcr->fileset->name(),
1639 NPRT(jcr->pool->name()),
1640 jcr->next_pool?jcr->next_pool->name():"*None*",
1641 jcr->rstore->name(),
1642 jcr->wstore?jcr->wstore->name():"*None*",
1643 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
1644 bstrutime(dt, sizeof(dt), jcr->sched_time),
1645 jcr->catalog->name(),
1648 if (jcr->getJobType() == JT_COPY) {
1649 prt_type = _("Run Copy job\n");
1651 prt_type = _("Run Migration job\n");
1658 "Pool: %s (From %s)\n"
1659 "NextPool: %s (From %s)\n"
1660 "Read Storage: %s (From %s)\n"
1661 "Write Storage: %s (From %s)\n"
1668 NPRT(jcr->RestoreBootstrap),
1669 jcr->client->name(),
1670 jcr->fileset->name(),
1671 NPRT(jcr->pool->name()), jcr->pool_source,
1672 jcr->next_pool?jcr->next_pool->name():"*None*",
1673 NPRT(jcr->next_pool_source),
1674 jcr->rstore->name(), jcr->rstore_source,
1675 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
1676 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
1677 bstrutime(dt, sizeof(dt), jcr->sched_time),
1678 jcr->catalog->name(),
1683 ua->error_msg(_("Unknown Job Type=%d\n"), jcr->getJobType());
1690 static bool scan_run_command_line_arguments(UAContext *ua, run_ctx &rc)
1694 static const char *kw[] = { /* command line arguments */
1695 "alljobid", /* 0 Used in a switch() */
1703 "regexwhere", /* 8 where string as a bregexp */
1705 "bootstrap", /* 10 */
1708 "priority", /* 13 */
1709 "yes", /* 14 -- if you change this change YES_POS too */
1710 "verifyjob", /* 15 */
1711 "files", /* 16 number of files to restore */
1712 "catalog", /* 17 override catalog */
1713 "since", /* 18 since */
1714 "cloned", /* 19 cloned */
1715 "verifylist", /* 20 verify output list */
1716 "migrationjob", /* 21 migration job name */
1718 "backupclient", /* 23 */
1719 "restoreclient", /* 24 */
1720 "pluginoptions", /* 25 */
1721 "spooldata", /* 26 */
1723 "ignoreduplicatecheck", /* 28 */
1724 "accurate", /* 29 */
1726 "mediatype", /* 31 */
1727 "nextpool", /* 32 override next pool name */
1732 rc.catalog_name = NULL;
1734 rc.pool_name = NULL;
1735 rc.next_pool_name = NULL;
1736 rc.store_name = NULL;
1737 rc.client_name = NULL;
1738 rc.media_type = NULL;
1739 rc.restore_client_name = NULL;
1740 rc.fileset_name = NULL;
1741 rc.verify_job_name = NULL;
1742 rc.previous_job_name = NULL;
1743 rc.accurate_set = false;
1744 rc.spool_data_set = false;
1745 rc.ignoreduplicatecheck = false;
1747 rc.plugin_options = NULL;
1749 for (i=1; i<ua->argc; i++) {
1750 Dmsg2(800, "Doing arg %d = %s\n", i, ua->argk[i]);
1752 /* Keep looking until we find a good keyword */
1753 for (j=0; !kw_ok && kw[j]; j++) {
1754 if (strcasecmp(ua->argk[i], kw[j]) == 0) {
1755 /* Note, yes and run have no value, so do not fail */
1756 if (!ua->argv[i] && j != YES_POS /*yes*/) {
1757 ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]);
1760 Dmsg2(800, "Got j=%d keyword=%s\n", j, NPRT(kw[j]));
1762 case 0: /* alljobid */
1764 /* Fall through wanted */
1766 if (rc.jid && !rc.mod) {
1767 ua->send_msg(_("JobId specified twice.\n"));
1770 rc.jid = ua->argv[i];
1773 case 2: /* client */
1775 if (rc.client_name) {
1776 ua->send_msg(_("Client specified twice.\n"));
1779 rc.client_name = ua->argv[i];
1782 case 4: /* fileset */
1783 if (rc.fileset_name) {
1784 ua->send_msg(_("FileSet specified twice.\n"));
1787 rc.fileset_name = ua->argv[i];
1791 if (rc.level_name) {
1792 ua->send_msg(_("Level specified twice.\n"));
1795 rc.level_name = ua->argv[i];
1798 case 6: /* storage */
1800 if (rc.store_name) {
1801 ua->send_msg(_("Storage specified twice.\n"));
1804 rc.store_name = ua->argv[i];
1807 case 8: /* regexwhere */
1808 if ((rc.regexwhere || rc.where) && !rc.mod) {
1809 ua->send_msg(_("RegexWhere or Where specified twice.\n"));
1812 rc.regexwhere = ua->argv[i];
1813 if (!acl_access_ok(ua, Where_ACL, rc.regexwhere)) {
1814 ua->send_msg(_("No authorization for \"regexwhere\" specification.\n"));
1820 if ((rc.where || rc.regexwhere) && !rc.mod) {
1821 ua->send_msg(_("Where or RegexWhere specified twice.\n"));
1824 rc.where = ua->argv[i];
1825 if (!acl_access_ok(ua, Where_ACL, rc.where)) {
1826 ua->send_msg(_("No authoriztion for \"where\" specification.\n"));
1831 case 10: /* bootstrap */
1832 if (rc.bootstrap && !rc.mod) {
1833 ua->send_msg(_("Bootstrap specified twice.\n"));
1836 rc.bootstrap = ua->argv[i];
1839 case 11: /* replace */
1840 if (rc.replace && !rc.mod) {
1841 ua->send_msg(_("Replace specified twice.\n"));
1844 rc.replace = ua->argv[i];
1848 if (rc.when && !rc.mod) {
1849 ua->send_msg(_("When specified twice.\n"));
1852 rc.when = ua->argv[i];
1855 case 13: /* Priority */
1856 if (rc.Priority && !rc.mod) {
1857 ua->send_msg(_("Priority specified twice.\n"));
1860 rc.Priority = atoi(ua->argv[i]);
1861 if (rc.Priority <= 0) {
1862 ua->send_msg(_("Priority must be positive nonzero setting it to 10.\n"));
1870 case 15: /* Verify Job */
1871 if (rc.verify_job_name) {
1872 ua->send_msg(_("Verify Job specified twice.\n"));
1875 rc.verify_job_name = ua->argv[i];
1878 case 16: /* files */
1879 rc.files = atoi(ua->argv[i]);
1882 case 17: /* catalog */
1883 rc.catalog_name = ua->argv[i];
1886 case 18: /* since */
1887 rc.since = ua->argv[i];
1890 case 19: /* cloned */
1894 case 20: /* write verify list output */
1895 rc.verify_list = ua->argv[i];
1898 case 21: /* Migration Job */
1899 if (rc.previous_job_name) {
1900 ua->send_msg(_("Migration Job specified twice.\n"));
1903 rc.previous_job_name = ua->argv[i];
1908 ua->send_msg(_("Pool specified twice.\n"));
1911 rc.pool_name = ua->argv[i];
1914 case 23: /* backupclient */
1915 if (rc.client_name) {
1916 ua->send_msg(_("Client specified twice.\n"));
1919 rc.client_name = ua->argv[i];
1922 case 24: /* restoreclient */
1923 if (rc.restore_client_name && !rc.mod) {
1924 ua->send_msg(_("Restore Client specified twice.\n"));
1927 rc.restore_client_name = ua->argv[i];
1930 case 25: /* pluginoptions */
1931 ua->send_msg(_("Plugin Options not yet implemented.\n"));
1933 if (rc.plugin_options) {
1934 ua->send_msg(_("Plugin Options specified twice.\n"));
1937 rc.plugin_options = ua->argv[i];
1938 if (!acl_access_ok(ua, PluginOptions_ACL, rc.plugin_options)) {
1939 ua->send_msg(_("No authoriztion for \"PluginOptions\" specification.\n"));
1944 case 26: /* spooldata */
1945 if (rc.spool_data_set) {
1946 ua->send_msg(_("Spool flag specified twice.\n"));
1949 if (is_yesno(ua->argv[i], &rc.spool_data)) {
1950 rc.spool_data_set = true;
1953 ua->send_msg(_("Invalid spooldata flag.\n"));
1956 case 27: /* comment */
1957 rc.comment = ua->argv[i];
1960 case 28: /* ignoreduplicatecheck */
1961 if (rc.ignoreduplicatecheck_set) {
1962 ua->send_msg(_("IgnoreDuplicateCheck flag specified twice.\n"));
1965 if (is_yesno(ua->argv[i], &rc.ignoreduplicatecheck)) {
1966 rc.ignoreduplicatecheck_set = true;
1969 ua->send_msg(_("Invalid ignoreduplicatecheck flag.\n"));
1972 case 29: /* accurate */
1973 if (rc.accurate_set) {
1974 ua->send_msg(_("Accurate flag specified twice.\n"));
1977 if (is_yesno(ua->argv[i], &rc.accurate)) {
1978 rc.accurate_set = true;
1981 ua->send_msg(_("Invalid accurate flag.\n"));
1986 ua->send_msg(_("Job name specified twice.\n"));
1989 rc.job_name = ua->argv[i];
1992 case 31: /* mediatype */
1993 if (rc.media_type) {
1994 ua->send_msg(_("Media Type specified twice.\n"));
1997 rc.media_type = ua->argv[i];
2000 case 32: /* Next Pool */
2001 if (rc.next_pool_name) {
2002 ua->send_msg(_("NextPool specified twice.\n"));
2005 rc.next_pool_name = ua->argv[i];
2011 } /* end strcase compare */
2012 } /* end keyword loop */
2015 * End of keyword for loop -- if not found, we got a bogus keyword
2018 Dmsg1(800, "%s not found\n", ua->argk[i]);
2020 * Special case for Job Name, it can be the first
2021 * keyword that has no value.
2023 if (!rc.job_name && !ua->argv[i]) {
2024 rc.job_name = ua->argk[i]; /* use keyword as job name */
2025 Dmsg1(800, "Set jobname=%s\n", rc.job_name);
2027 ua->send_msg(_("Invalid keyword: %s\n"), ua->argk[i]);
2031 } /* end argc loop */
2033 Dmsg0(800, "Done scan.\n");
2035 if (!is_comment_legal(ua, rc.comment)) {
2039 if (rc.catalog_name) {
2040 rc.catalog = GetCatalogResWithName(rc.catalog_name);
2041 if (rc.catalog == NULL) {
2042 ua->error_msg(_("Catalog \"%s\" not found\n"), rc.catalog_name);
2045 if (!acl_access_ok(ua, Catalog_ACL, rc.catalog->name())) {
2046 ua->error_msg(_("No authorization. Catalog \"%s\".\n"), rc.catalog->name());
2050 Dmsg1(800, "Using catalog=%s\n", NPRT(rc.catalog_name));
2052 if (!get_job(ua, rc)) {
2056 if (!get_pool(ua, rc)) {
2060 if (!get_next_pool(ua, rc)) {
2064 if (!get_storage(ua, rc)) {
2069 if (!get_client(ua, rc)) {
2073 if (!get_fileset(ua, rc)) {
2077 if (rc.verify_job_name) {
2078 rc.verify_job = GetJobResWithName(rc.verify_job_name);
2079 if (!rc.verify_job) {
2080 ua->send_msg(_("Verify Job \"%s\" not found.\n"), rc.verify_job_name);
2081 rc.verify_job = select_job_resource(ua);
2083 } else if (!rc.verify_job) {
2084 rc.verify_job = rc.job->verify_job;
2087 if (rc.previous_job_name) {
2088 rc.previous_job = GetJobResWithName(rc.previous_job_name);
2089 if (!rc.previous_job) {
2090 ua->send_msg(_("Migration Job \"%s\" not found.\n"), rc.previous_job_name);
2091 rc.previous_job = select_job_resource(ua);
2094 rc.previous_job = rc.job->verify_job;