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 */
152 /* Run without prompting? */
153 if (ua->batch || find_arg(ua, NT_("yes")) > 0) {
154 return start_job(ua, jcr, rc);
158 * Prompt User to see if all run job parameters are correct, and
159 * allow him to modify them.
161 if (!display_job_parameters(ua, jcr, rc.job, rc.verify_list, rc.jid, rc.replace,
163 break; /* error get out of while loop */
166 if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
167 break; /* error get out of while loop */
170 if (strncasecmp(ua->cmd, ".mod ", 5) == 0 ||
171 (strncasecmp(ua->cmd, "mod ", 4) == 0 && strlen(ua->cmd) > 6)) {
174 if (!scan_run_command_line_arguments(ua, rc)) {
175 break; /* error get out of while loop */
177 continue; /* another round with while loop */
180 /* Allow the user to modify the settings */
181 status = modify_job_parameters(ua, jcr, rc);
183 continue; /* another round with while loop */
185 if (status == -1) { /* error */
186 break; /* error get out of while loop */
189 if (ua->cmd[0] == 0 || strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
190 return start_job(ua, jcr, rc);
192 if (strncasecmp(ua->cmd, _("no"), strlen(ua->cmd)) == 0) {
193 break; /* get out of while loop */
195 ua->send_msg(_("\nBad response: %s. You must answer yes, mod, or no.\n\n"), ua->cmd);
199 ua->send_msg(_("Job not run.\n"));
200 if (ua->jcr->component_fd) {
201 fclose(ua->jcr->component_fd);
202 ua->jcr->component_fd = NULL;
204 if (ua->jcr->component_fname) {
205 unlink(ua->jcr->component_fname);
206 free_and_null_pool_memory(ua->jcr->component_fname);
209 if (jcr->component_fd) {
210 fclose(jcr->component_fd);
211 jcr->component_fd = NULL;
213 if (jcr->component_fname) {
214 unlink(jcr->component_fname);
215 free_and_null_pool_memory(jcr->component_fname);
219 return 0; /* do not run */
222 static JobId_t start_job(UAContext *ua, JCR *jcr, run_ctx &rc)
226 if (rc.jr.JobStatus == JS_Incomplete) {
227 Dmsg1(100, "Ressuming JobId=%d\n", rc.jr.JobId);
228 JobId = resume_job(jcr, &rc.jr);
230 Dmsg1(100, "Starting JobId=%d\n", rc.jr.JobId);
231 JobId = run_job(jcr);
233 Dmsg4(100, "JobId=%u NewJobId=%d pool=%s priority=%d\n", (int)jcr->JobId,
234 JobId, jcr->pool->name(), jcr->JobPriority);
235 free_jcr(jcr); /* release jcr */
237 ua->error_msg(_("Job failed.\n"));
240 ua->send_msg(_("Job queued. JobId=%s\n"), edit_int64(JobId, ed1));
246 * If no job_name defined in the run context, ask
248 * Then put the job resource in the run context and
249 * check the access rights.
251 static bool get_job(UAContext *ua, run_ctx &rc)
255 rc.job = GetJobResWithName(rc.job_name);
257 if (*rc.job_name != 0) {
258 ua->send_msg(_("Job \"%s\" not found\n"), rc.job_name);
260 rc.job = select_job_resource(ua);
262 Dmsg1(100, "Found job=%s\n", rc.job_name);
264 } else if (!rc.job) {
265 ua->send_msg(_("A job name must be specified.\n"));
266 rc.job = select_job_resource(ua);
270 } else if (!acl_access_ok(ua, Job_ACL, rc.job->name())) {
271 ua->error_msg( _("No authorization. Job \"%s\".\n"), rc.job->name());
278 * If no pool_name defined in the run context, ask
280 * Then put the pool resource in the run context and
281 * check the access rights.
283 static bool get_pool(UAContext *ua, run_ctx &rc)
286 rc.pool = GetPoolResWithName(rc.pool_name);
288 if (*rc.pool_name != 0) {
289 ua->warning_msg(_("Pool \"%s\" not found.\n"), rc.pool_name);
291 rc.pool = select_pool_resource(ua);
293 } else if (!rc.pool) {
294 rc.pool = rc.job->pool; /* use default */
298 } else if (!acl_access_ok(ua, Pool_ACL, rc.pool->name())) {
299 ua->error_msg(_("No authorization. Pool \"%s\".\n"), rc.pool->name());
302 Dmsg1(100, "Using Pool=%s\n", rc.pool->name());
306 static bool get_next_pool(UAContext *ua, run_ctx &rc)
308 if (rc.next_pool_name) {
309 Dmsg1(100, "Have next pool=%s\n", rc.next_pool_name);
310 rc.next_pool = GetPoolResWithName(rc.next_pool_name);
312 if (*rc.next_pool_name != 0) {
313 ua->warning_msg(_("NextPool \"%s\" not found.\n"), rc.next_pool_name);
315 rc.next_pool = select_pool_resource(ua);
318 /* NextPool can come from Job resource NextPool or Pool resource NextPool */
320 if (rc.job->next_pool) {
321 rc.next_pool = rc.job->next_pool;
323 rc.next_pool = rc.pool->NextPool; /* use default */
326 if (rc.next_pool && !acl_access_ok(ua, Pool_ACL, rc.next_pool->name())) {
327 ua->error_msg(_("No authorization. NextPool \"%s\".\n"), rc.next_pool->name());
331 Dmsg1(100, "Using NextPool=%s\n", NPRT(rc.next_pool->name()));
338 * Fill in client data according to what is setup
339 * in the run context, and make sure the user
340 * has authorized access to it.
342 static bool get_client(UAContext *ua, run_ctx &rc)
344 if (rc.client_name) {
345 rc.client = GetClientResWithName(rc.client_name);
347 if (*rc.client_name != 0) {
348 ua->warning_msg(_("Client \"%s\" not found.\n"), rc.client_name);
350 rc.client = select_client_resource(ua);
352 } else if (!rc.client) {
353 rc.client = rc.job->client; /* use default */
357 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
358 ua->error_msg(_("No authorization. Client \"%s\".\n"),
362 Dmsg1(800, "Using client=%s\n", rc.client->name());
364 if (rc.restore_client_name) {
365 rc.client = GetClientResWithName(rc.restore_client_name);
367 if (*rc.restore_client_name != 0) {
368 ua->warning_msg(_("Restore Client \"%s\" not found.\n"), rc.restore_client_name);
370 rc.client = select_client_resource(ua);
372 } else if (!rc.client) {
373 rc.client = rc.job->client; /* use default */
377 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
378 ua->error_msg(_("No authorization. Client \"%s\".\n"),
382 Dmsg1(800, "Using restore client=%s\n", rc.client->name());
388 * Fill in fileset data according to what is setup
389 * in the run context, and make sure the user
390 * has authorized access to it.
392 static bool get_fileset(UAContext *ua, run_ctx &rc)
394 if (rc.fileset_name) {
395 rc.fileset = GetFileSetResWithName(rc.fileset_name);
397 ua->send_msg(_("FileSet \"%s\" not found.\n"), rc.fileset_name);
398 rc.fileset = select_fileset_resource(ua);
400 } else if (!rc.fileset) {
401 rc.fileset = rc.job->fileset; /* use default */
405 } else if (!acl_access_ok(ua, FileSet_ACL, rc.fileset->name())) {
406 ua->send_msg(_("No authorization. FileSet \"%s\".\n"),
414 * Fill in storage data according to what is setup
415 * in the run context, and make sure the user
416 * has authorized access to it.
418 static bool get_storage(UAContext *ua, run_ctx &rc)
421 rc.store->store = GetStoreResWithName(rc.store_name);
422 pm_strcpy(rc.store->store_source, _("command line"));
423 if (!rc.store->store) {
424 if (*rc.store_name != 0) {
425 ua->warning_msg(_("Storage \"%s\" not found.\n"), rc.store_name);
427 rc.store->store = select_storage_resource(ua);
428 pm_strcpy(rc.store->store_source, _("user selection"));
430 } else if (!rc.store->store) {
431 get_job_storage(rc.store, rc.job, NULL); /* use default */
433 if (!rc.store->store) {
434 ua->error_msg(_("No storage specified.\n"));
436 } else if (!acl_access_ok(ua, Storage_ACL, rc.store->store->name())) {
437 ua->error_msg(_("No authorization. Storage \"%s\".\n"),
438 rc.store->store->name());
441 Dmsg1(800, "Using storage=%s\n", rc.store->store->name());
446 * Get and pass back a list of Jobids in rc.jid
448 static bool get_jobid_list(UAContext *ua, sellist &sl, run_ctx &rc)
455 memset(&jr, 0, sizeof(jr));
457 /* See if any JobId is specified */
458 if ((i=find_arg(ua, "jobid")) >= 0) {
459 rc.jid = ua->argv[i];
461 ua->send_msg(_("No JobId specified.\n"));
464 if (!sl.set_string(ua->argv[i], true)) {
465 ua->send_msg("%s", sl.get_errmsg());
471 /* No JobId list give, so see if he specified a Job */
472 if ((i=find_arg(ua, "job")) >= 0) {
473 rc.job_name = ua->argv[i];
474 if (!get_job(ua, rc)) {
475 ua->send_msg(_("Invalid or no Job name specified.\n"));
479 jr.limit = 100; /* max 100 records */
481 bstrncpy(jr.Name, rc.job_name, sizeof(jr.Name));
485 jr.JobStatus = rc.jr.JobStatus;
486 Dmsg2(100, "JobStatus=%d JobName=%s\n", jr.JobStatus, jr.Name);
487 /* rc.JobIds is alist of all records found and printed */
488 rc.JobIds = db_list_job_records(ua->jcr, ua->db, &jr, prtit, ua, INCOMPLETE_JOBS);
489 if (!rc.JobIds || rc.JobIds->size()==0 ||
490 !get_selection_list(ua, sl, _("Enter the JobId list to select: "), false)) {
493 Dmsg1(100, "list=%s\n", sl.get_list());
495 * Make sure each item entered is in the JobIds list
497 while ( (JobId = sl.next()) > 0) {
498 foreach_alist(pJobId, rc.JobIds) {
499 if (JobId == str_to_int64(pJobId)) {
506 ua->error_msg(_("JobId=%d entered is not in the list.\n"), JobId);
510 sl.begin(); /* reset to walk list again */
515 static bool get_jobid_from_list(UAContext *ua, sellist &sl, run_ctx &rc)
522 if ((JobId = sl.next()) < 0) {
523 Dmsg1(100, "sl.next()=%d\n", JobId);
527 rc.jr.JobId = rc.JobId = JobId;
528 Dmsg1(100, "Next JobId=%d\n", rc.JobId);
529 if (!db_get_job_record(ua->jcr, ua->db, &rc.jr)) {
530 ua->error_msg(_("Could not get job record for selected JobId=%d. ERR=%s"),
531 rc.JobId, db_strerror(ua->db));
534 Dmsg3(100, "Job=%s JobId=%d JobStatus=%c\n", rc.jr.Name, rc.jr.JobId,
536 rc.job_name = rc.jr.Name;
537 if (!get_job(ua, rc)) {
540 if (!get_pool(ua, rc)) {
543 get_job_storage(rc.store, rc.job, NULL);
544 rc.client_name = rc.job->client->hdr.name;
545 if (!get_client(ua, rc)) {
548 if (!get_fileset(ua, rc)) {
551 if (!get_storage(ua, rc)) {
558 * Restart Canceled, Failed, or Incomplete Jobs
560 * Returns: 0 on error
564 int restart_cmd(UAContext *ua, const char *cmd)
572 const char *status_name;
576 {"Incomplete", JS_Incomplete},
577 {"Canceled", JS_Canceled},
578 {"Failed", JS_FatalError},
583 if (!open_client_db(ua)) {
588 for (i=1; i<ua->argc; i++) {
589 for (j=0; kw[j].status_name; j++) {
590 if (strcasecmp(ua->argk[i], kw[j].status_name) == 0) {
591 rc.jr.JobStatus = kw[j].job_status;
597 if (!got_kw) { /* Must prompt user */
598 start_prompt(ua, _("You have the following choices:\n"));
599 for (i=0; kw[i].status_name; i++) {
600 add_prompt(ua, kw[i].status_name);
602 i = do_prompt(ua, NULL, _("Select termination code: "), NULL, 0);
606 rc.jr.JobStatus = kw[i].job_status;
609 /* type now has what job termination code we want to look at */
610 Dmsg1(100, "Termination code=%c\n", rc.jr.JobStatus);
612 /* Get a list of JobIds to restore */
613 if (!get_jobid_list(ua, sl, rc)) {
615 rc.JobIds->destroy();
619 Dmsg1(100, "list=%s\n", sl.get_list());
621 while (get_jobid_from_list(ua, sl, rc)) {
623 * Create JCR to run job. NOTE!!! after this point, free_jcr()
627 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
628 set_jcr_defaults(jcr, rc.job);
629 jcr->unlink_bsr = ua->jcr->unlink_bsr; /* copy unlink flag from caller */
630 ua->jcr->unlink_bsr = false;
633 if (!set_run_context_in_jcr(ua, jcr, rc)) {
636 start_job(ua, jcr, rc);
644 rc.JobIds->destroy();
646 return 0; /* do not run */
649 int modify_job_parameters(UAContext *ua, JCR *jcr, run_ctx &rc)
654 * At user request modify parameters of job to be run.
656 if (ua->cmd[0] != 0 && strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0){
659 start_prompt(ua, _("Parameters to modify:\n"));
660 add_prompt(ua, _("Level")); /* 0 */
661 add_prompt(ua, _("Storage")); /* 1 */
662 add_prompt(ua, _("Job")); /* 2 */
663 add_prompt(ua, _("FileSet")); /* 3 */
664 if (jcr->getJobType() == JT_RESTORE) {
665 add_prompt(ua, _("Restore Client")); /* 4 */
667 add_prompt(ua, _("Client")); /* 4 */
669 add_prompt(ua, _("When")); /* 5 */
670 add_prompt(ua, _("Priority")); /* 6 */
671 if (jcr->getJobType() == JT_BACKUP ||
672 jcr->getJobType() == JT_COPY ||
673 jcr->getJobType() == JT_MIGRATE ||
674 jcr->getJobType() == JT_VERIFY) {
675 add_prompt(ua, _("Pool")); /* 7 */
676 if ((jcr->getJobType() == JT_BACKUP && /* Virtual full */
677 jcr->is_JobLevel(L_VIRTUAL_FULL)) ||
678 jcr->getJobType() == JT_COPY ||
679 jcr->getJobType() == JT_MIGRATE) {
680 add_prompt(ua, _("NextPool")); /* 8 */
681 } else if (jcr->getJobType() == JT_VERIFY) {
682 add_prompt(ua, _("Verify Job")); /* 8 */
684 } else if (jcr->getJobType() == JT_RESTORE) {
685 add_prompt(ua, _("Bootstrap")); /* 7 */
686 add_prompt(ua, _("Where")); /* 8 */
687 add_prompt(ua, _("File Relocation"));/* 9 */
688 add_prompt(ua, _("Replace")); /* 10 */
689 add_prompt(ua, _("JobId")); /* 11 */
691 if (jcr->getJobType() == JT_BACKUP || jcr->getJobType() == JT_RESTORE) {
692 add_prompt(ua, _("Plugin Options")); /* 12 */
694 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
697 select_job_level(ua, jcr);
701 rc.store->store = select_storage_resource(ua);
702 if (rc.store->store) {
703 pm_strcpy(rc.store->store_source, _("user selection"));
704 set_rwstorage(jcr, rc.store);
710 rc.job = select_job_resource(ua);
713 set_jcr_defaults(jcr, rc.job);
719 rc.fileset = select_fileset_resource(ua);
721 jcr->fileset = rc.fileset;
727 rc.client = select_client_resource(ua);
729 jcr->client = rc.client;
735 if (!get_cmd(ua, _("Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now): "))) {
738 if (ua->cmd[0] == 0) {
739 jcr->sched_time = time(NULL);
741 jcr->sched_time = str_to_utime(ua->cmd);
742 if (jcr->sched_time == 0) {
743 ua->send_msg(_("Invalid time, using current time.\n"));
744 jcr->sched_time = time(NULL);
750 if (!get_pint(ua, _("Enter new Priority: "))) {
753 if (ua->pint32_val == 0) {
754 ua->send_msg(_("Priority must be a positive integer.\n"));
756 jcr->JobPriority = ua->pint32_val;
760 /* Pool or Bootstrap depending on JobType */
761 if (jcr->getJobType() == JT_BACKUP ||
762 jcr->getJobType() == JT_COPY ||
763 jcr->getJobType() == JT_MIGRATE ||
764 jcr->getJobType() == JT_VERIFY) { /* Pool */
765 rc.pool = select_pool_resource(ua);
768 Dmsg1(100, "Set new pool=%s\n", jcr->pool->name());
775 if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
778 if (jcr->RestoreBootstrap) {
779 free(jcr->RestoreBootstrap);
780 jcr->RestoreBootstrap = NULL;
782 if (ua->cmd[0] != 0) {
783 jcr->RestoreBootstrap = bstrdup(ua->cmd);
784 fd = fopen(jcr->RestoreBootstrap, "rb");
787 ua->send_msg(_("Warning cannot open %s: ERR=%s\n"),
788 jcr->RestoreBootstrap, be.bstrerror());
789 free(jcr->RestoreBootstrap);
790 jcr->RestoreBootstrap = NULL;
797 /* Specify Next Pool */
798 if ((jcr->getJobType() == JT_BACKUP && /* Virtual full */
799 jcr->is_JobLevel(L_VIRTUAL_FULL)) ||
800 jcr->getJobType() == JT_COPY ||
801 jcr->getJobType() == JT_MIGRATE) {
802 rc.next_pool = select_pool_resource(ua);
804 jcr->next_pool = rc.next_pool;
809 if (jcr->getJobType() == JT_VERIFY) {
810 rc.verify_job = select_job_resource(ua);
812 jcr->verify_job = rc.verify_job;
817 if (!get_cmd(ua, _("Please enter the full path prefix for restore (/ for none): "))) {
820 if (jcr->RegexWhere) { /* cannot use regexwhere and where */
821 free(jcr->RegexWhere);
822 jcr->RegexWhere = NULL;
828 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
831 jcr->where = bstrdup(ua->cmd);
834 /* File relocation */
835 select_where_regexp(ua, jcr);
839 start_prompt(ua, _("Replace:\n"));
840 for (i=0; ReplaceOptions[i].name; i++) {
841 add_prompt(ua, ReplaceOptions[i].name);
843 opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
845 rc.replace = ReplaceOptions[opt].name;
846 jcr->replace = ReplaceOptions[opt].token;
851 rc.jid = NULL; /* force reprompt */
852 jcr->RestoreJobId = 0;
853 if (jcr->RestoreBootstrap) {
854 ua->send_msg(_("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
859 //generate_plugin_event(jcr, bEventJobConfig, &rc);
860 if (!get_cmd(ua, _("Please Plugin Options string: "))) {
863 if (jcr->plugin_options) {
864 free(jcr->plugin_options);
865 jcr->plugin_options = NULL;
867 jcr->plugin_options = bstrdup(ua->cmd);
869 case -1: /* error or cancel */
885 * Put the run context that we have at this point into the JCR.
886 * That allows us to re-ask for the run context.
887 * This subroutine can be called multiple times, so it
888 * must keep any prior settings.
890 static bool set_run_context_in_jcr(UAContext *ua, JCR *jcr, run_ctx &rc)
894 jcr->verify_job = rc.verify_job;
895 jcr->previous_job = rc.previous_job;
897 jcr->next_pool = rc.next_pool;
899 jcr->cmdline_next_pool_override = true;
902 pm_strcpy(jcr->pool_source, _("Command input"));
903 } else if (jcr->pool != jcr->job->pool) {
904 pm_strcpy(jcr->pool_source, _("User input"));
906 if (rc.next_pool_name) {
907 pm_strcpy(jcr->next_pool_source, _("Command input"));
908 } else if (jcr->next_pool == jcr->job->next_pool) {
909 pm_strcpy(jcr->next_pool_source, _("Job resource"));
910 } else if (jcr->next_pool != jcr->pool->NextPool) {
911 pm_strcpy(jcr->next_pool_source, _("User input"));
914 set_rwstorage(jcr, rc.store);
915 jcr->client = rc.client;
917 pm_strcpy(jcr->client_name, rc.client->name());
919 pm_strcpy(jcr->client_name, "**Dummy**");
922 if (!jcr->media_type) {
923 jcr->media_type = get_pool_memory(PM_NAME);
925 pm_strcpy(jcr->media_type, rc.media_type);
927 jcr->fileset = rc.fileset;
928 jcr->ExpectedFiles = rc.files;
930 jcr->catalog = rc.catalog;
931 pm_strcpy(jcr->catalog_source, _("User input"));
934 pm_strcpy(jcr->comment, rc.comment);
940 jcr->where = bstrdup(rc.where);
945 if (jcr->RegexWhere) {
946 free(jcr->RegexWhere);
948 jcr->RegexWhere = bstrdup(rc.regexwhere);
949 rc.regexwhere = NULL;
953 jcr->sched_time = str_to_utime(rc.when);
954 if (jcr->sched_time == 0) {
955 ua->send_msg(_("Invalid time, using current time.\n"));
956 jcr->sched_time = time(NULL);
962 if (jcr->RestoreBootstrap) {
963 free(jcr->RestoreBootstrap);
965 jcr->RestoreBootstrap = bstrdup(rc.bootstrap);
969 if (rc.plugin_options) {
970 if (jcr->plugin_options) {
971 free(jcr->plugin_options);
973 jcr->plugin_options = bstrdup(rc.plugin_options);
974 rc.plugin_options = NULL;
979 for (i=0; ReplaceOptions[i].name; i++) {
980 if (strcasecmp(rc.replace, ReplaceOptions[i].name) == 0) {
981 jcr->replace = ReplaceOptions[i].token;
985 ua->send_msg(_("Invalid replace option: %s\n"), rc.replace);
988 } else if (rc.job->replace) {
989 jcr->replace = rc.job->replace;
991 jcr->replace = REPLACE_ALWAYS;
995 /* Set Snapshot Retention (Job <- Client) */
997 jcr->snapshot_retention = jcr->client->SnapRetention;
999 if (jcr->job && jcr->job->SnapRetention > 0) {
1000 jcr->snapshot_retention = jcr->job->SnapRetention;
1004 jcr->JobPriority = rc.Priority;
1010 jcr->stime = get_pool_memory(PM_MESSAGE);
1012 pm_strcpy(jcr->stime, rc.since);
1017 jcr->cloned = rc.cloned;
1021 /* If pool changed, update migration write storage */
1022 if (jcr->is_JobType(JT_MIGRATE) || jcr->is_JobType(JT_COPY) ||
1023 (jcr->is_JobType(JT_BACKUP) && jcr->is_JobLevel(L_VIRTUAL_FULL))) {
1024 if (!set_mac_wstorage(ua, jcr, rc.pool, rc.next_pool,
1025 jcr->next_pool_source)) {
1029 rc.replace = ReplaceOptions[0].name;
1030 for (i=0; ReplaceOptions[i].name; i++) {
1031 if ((int)ReplaceOptions[i].token == jcr->replace) {
1032 rc.replace = ReplaceOptions[i].name;
1035 if (rc.level_name) {
1036 if (!get_level_from_name(jcr, rc.level_name)) {
1037 ua->send_msg(_("Level \"%s\" not valid.\n"), rc.level_name);
1040 rc.level_name = NULL;
1043 /* Note, this is also MigrateJobId and a VerifyJobId */
1044 jcr->RestoreJobId = str_to_int64(rc.jid);
1046 /* Copy also this parameter for VirtualFull in jcr->JobIds */
1048 jcr->JobIds = get_pool_memory(PM_FNAME);
1050 pm_strcpy(jcr->JobIds, rc.jid);
1051 jcr->use_all_JobIds = rc.alljobid; /* if we found the "alljobid=" kw */
1052 rc.alljobid = false;
1056 /* Some options are not available through the menu
1057 * TODO: Add an advanced menu?
1059 if (rc.spool_data_set) {
1060 jcr->spool_data = rc.spool_data;
1063 if (rc.accurate_set) {
1064 jcr->accurate = rc.accurate;
1067 /* Used by migration jobs that can have the same name,
1068 * but can run at the same time
1070 if (rc.ignoreduplicatecheck_set) {
1071 jcr->IgnoreDuplicateJobChecking = rc.ignoreduplicatecheck;
1077 static void select_where_regexp(UAContext *ua, JCR *jcr)
1080 char *strip_prefix, *add_prefix, *add_suffix, *rwhere;
1081 strip_prefix = add_suffix = rwhere = add_prefix = NULL;
1084 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s\n"),
1085 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix));
1087 start_prompt(ua, _("This will replace your current Where value\n"));
1088 add_prompt(ua, _("Strip prefix")); /* 0 */
1089 add_prompt(ua, _("Add prefix")); /* 1 */
1090 add_prompt(ua, _("Add file suffix")); /* 2 */
1091 add_prompt(ua, _("Enter a regexp")); /* 3 */
1092 add_prompt(ua, _("Test filename manipulation")); /* 4 */
1093 add_prompt(ua, _("Use this ?")); /* 5 */
1095 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
1098 if (get_cmd(ua, _("Please enter the path prefix to strip: "))) {
1099 if (strip_prefix) bfree(strip_prefix);
1100 strip_prefix = bstrdup(ua->cmd);
1106 if (get_cmd(ua, _("Please enter the path prefix to add (/ for none): "))) {
1107 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
1111 if (add_prefix) bfree(add_prefix);
1112 add_prefix = bstrdup(ua->cmd);
1117 if (get_cmd(ua, _("Please enter the file suffix to add: "))) {
1118 if (add_suffix) bfree(add_suffix);
1119 add_suffix = bstrdup(ua->cmd);
1124 if (get_cmd(ua, _("Please enter a valid regexp (!from!to!): "))) {
1125 if (rwhere) bfree(rwhere);
1126 rwhere = bstrdup(ua->cmd);
1135 if (rwhere && rwhere[0] != '\0') {
1136 regs = get_bregexps(rwhere);
1137 ua->send_msg(_("regexwhere=%s\n"), NPRT(rwhere));
1139 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
1140 regexp = (char *) bmalloc (len * sizeof(char));
1141 bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix);
1142 regs = get_bregexps(regexp);
1143 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s result=%s\n"),
1144 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix), NPRT(regexp));
1150 ua->send_msg(_("Cannot use your regexp\n"));
1153 ua->send_msg(_("Enter a period (.) to stop this test\n"));
1154 while (get_cmd(ua, _("Please enter filename to test: "))) {
1155 apply_bregexps(ua->cmd, regs, &result);
1156 ua->send_msg(_("%s -> %s\n"), ua->cmd, result);
1158 free_bregexps(regs);
1165 case -1: /* error or cancel */
1171 /* replace the existing where */
1177 /* replace the existing regexwhere */
1178 if (jcr->RegexWhere) {
1179 bfree(jcr->RegexWhere);
1180 jcr->RegexWhere = NULL;
1184 jcr->RegexWhere = bstrdup(rwhere);
1185 } else if (strip_prefix || add_prefix || add_suffix) {
1186 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
1187 jcr->RegexWhere = (char *) bmalloc(len*sizeof(char));
1188 bregexp_build_where(jcr->RegexWhere, len, strip_prefix, add_prefix, add_suffix);
1191 regs = get_bregexps(jcr->RegexWhere);
1193 free_bregexps(regs);
1196 if (jcr->RegexWhere) {
1197 bfree(jcr->RegexWhere);
1198 jcr->RegexWhere = NULL;
1200 ua->send_msg(_("Cannot use your regexp.\n"));
1204 if (strip_prefix) bfree(strip_prefix);
1205 if (add_prefix) bfree(add_prefix);
1206 if (add_suffix) bfree(add_suffix);
1207 if (rwhere) bfree(rwhere);
1210 static void select_job_level(UAContext *ua, JCR *jcr)
1212 if (jcr->getJobType() == JT_BACKUP) {
1213 start_prompt(ua, _("Levels:\n"));
1214 // add_prompt(ua, _("Base"));
1215 add_prompt(ua, _("Full"));
1216 add_prompt(ua, _("Incremental"));
1217 add_prompt(ua, _("Differential"));
1218 add_prompt(ua, _("Since"));
1219 add_prompt(ua, _("VirtualFull"));
1220 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
1222 // jcr->JobLevel = L_BASE;
1225 jcr->setJobLevel(L_FULL);
1228 jcr->setJobLevel(L_INCREMENTAL);
1231 jcr->setJobLevel(L_DIFFERENTIAL);
1234 jcr->setJobLevel(L_SINCE);
1237 jcr->setJobLevel(L_VIRTUAL_FULL);
1242 } else if (jcr->getJobType() == JT_VERIFY) {
1243 start_prompt(ua, _("Levels:\n"));
1244 add_prompt(ua, _("Initialize Catalog"));
1245 add_prompt(ua, _("Verify Catalog"));
1246 add_prompt(ua, _("Verify Volume to Catalog"));
1247 add_prompt(ua, _("Verify Disk to Catalog"));
1248 add_prompt(ua, _("Verify Volume Data"));
1249 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
1251 jcr->setJobLevel(L_VERIFY_INIT);
1254 jcr->setJobLevel(L_VERIFY_CATALOG);
1257 jcr->setJobLevel(L_VERIFY_VOLUME_TO_CATALOG);
1260 jcr->setJobLevel(L_VERIFY_DISK_TO_CATALOG);
1263 jcr->setJobLevel(L_VERIFY_DATA);
1269 ua->warning_msg(_("Level not appropriate for this Job. Cannot be changed.\n"));
1274 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char *verify_list,
1275 char *jid, const char *replace, char *client_name)
1278 char dt[MAX_TIME_LENGTH];
1280 Dmsg1(800, "JobType=%c\n", jcr->getJobType());
1281 switch (jcr->getJobType()) {
1284 ua->signal(BNET_RUN_CMD);
1285 ua->send_msg("Type: Admin\n"
1286 "Title: Run Admin Job\n"
1294 jcr->fileset->name(),
1295 NPRT(jcr->client->name()),
1296 jcr->wstore?jcr->wstore->name():"*None*",
1297 bstrutime(dt, sizeof(dt), jcr->sched_time),
1300 ua->send_msg(_("Run Admin Job\n"
1308 jcr->fileset->name(),
1309 NPRT(jcr->client->name()),
1310 jcr->wstore?jcr->wstore->name():"*None*",
1311 bstrutime(dt, sizeof(dt), jcr->sched_time),
1314 jcr->setJobLevel(L_FULL);
1318 char next_pool[MAX_NAME_LENGTH + 50];
1320 if (jcr->getJobType() == JT_BACKUP) {
1322 ua->signal(BNET_RUN_CMD);
1323 if (jcr->is_JobLevel(L_VIRTUAL_FULL)) {
1324 bsnprintf(next_pool, sizeof(next_pool), "NextPool: %s\n",
1325 jcr->next_pool ? jcr->next_pool->name() : "*None*");
1327 ua->send_msg("Type: Backup\n"
1328 "Title: Run Backup Job\n"
1340 level_to_str(jcr->getJobLevel()),
1341 jcr->client->name(),
1342 jcr->fileset->name(),
1343 NPRT(jcr->pool->name()),
1345 jcr->wstore?jcr->wstore->name():"*None*",
1346 bstrutime(dt, sizeof(dt), jcr->sched_time),
1348 jcr->plugin_options?"Plugin Options: ":"",
1349 jcr->plugin_options?jcr->plugin_options:"",
1350 jcr->plugin_options?"\n":"");
1352 if (jcr->is_JobLevel(L_VIRTUAL_FULL)) {
1353 bsnprintf(next_pool, sizeof(next_pool),
1354 "NextPool: %s (From %s)\n",
1355 jcr->next_pool ? jcr->next_pool->name() : "*None*",
1356 jcr->next_pool_source);
1358 ua->send_msg(_("Run Backup job\n"
1363 "Pool: %s (From %s)\n"
1365 "Storage: %s (From %s)\n"
1370 level_to_str(jcr->getJobLevel()),
1371 jcr->client->name(),
1372 jcr->fileset->name(),
1373 NPRT(jcr->pool->name()), jcr->pool_source,
1375 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
1376 bstrutime(dt, sizeof(dt), jcr->sched_time),
1378 jcr->plugin_options?"Plugin Options: ":"",
1379 jcr->plugin_options?jcr->plugin_options:"",
1380 jcr->plugin_options?"\n":"");
1382 } else { /* JT_VERIFY */
1385 if (jcr->verify_job) {
1386 Name = jcr->verify_job->name();
1387 } else if (jcr->RestoreJobId) { /* Display job name if jobid requested */
1388 memset(&jr, 0, sizeof(jr));
1389 jr.JobId = jcr->RestoreJobId;
1390 if (!db_get_job_record(jcr, ua->db, &jr)) {
1391 ua->error_msg(_("Could not get job record for selected JobId. ERR=%s"),
1392 db_strerror(ua->db));
1400 verify_list = job->WriteVerifyList;
1406 ua->signal(BNET_RUN_CMD);
1407 ua->send_msg("Type: Verify\n"
1408 "Title: Run Verify Job\n"
1413 "Pool: %s (From %s)\n"
1414 "Storage: %s (From %s)\n"
1420 level_to_str(jcr->getJobLevel()),
1421 jcr->client->name(),
1422 jcr->fileset->name(),
1423 NPRT(jcr->pool->name()), jcr->pool_source,
1424 jcr->rstore->name(), jcr->rstore_source,
1427 bstrutime(dt, sizeof(dt), jcr->sched_time),
1430 ua->send_msg(_("Run Verify Job\n"
1435 "Pool: %s (From %s)\n"
1436 "Storage: %s (From %s)\n"
1442 level_to_str(jcr->getJobLevel()),
1443 jcr->client->name(),
1444 jcr->fileset->name(),
1445 NPRT(jcr->pool->name()), jcr->pool_source,
1446 jcr->rstore->name(), jcr->rstore_source,
1449 bstrutime(dt, sizeof(dt), jcr->sched_time),
1455 if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
1457 jcr->RestoreJobId = str_to_int64(jid);
1459 if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
1462 jcr->RestoreJobId = ua->int64_val;
1465 jcr->setJobLevel(L_FULL); /* default level */
1466 Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId);
1467 if (jcr->RestoreJobId == 0) {
1468 /* RegexWhere is take before RestoreWhere */
1469 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
1471 ua->signal(BNET_RUN_CMD);
1472 ua->send_msg("Type: Restore\n"
1473 "Title: Run Restore Job\n"
1479 "Backup Client: %s\n"
1480 "Restore Client: %s\n"
1485 "Plugin Options: %s\n",
1487 NPRT(jcr->RestoreBootstrap),
1488 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
1490 jcr->fileset->name(),
1492 jcr->client->name(),
1493 jcr->rstore->name(),
1494 bstrutime(dt, sizeof(dt), jcr->sched_time),
1495 jcr->catalog->name(),
1497 NPRTB(jcr->plugin_options));
1500 ua->send_msg(_("Run Restore job\n"
1506 "Backup Client: %s\n"
1507 "Restore Client: %s\n"
1512 "Plugin Options: %s\n"),
1514 NPRT(jcr->RestoreBootstrap),
1515 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
1517 jcr->fileset->name(),
1519 jcr->client->name(),
1520 jcr->rstore->name(),
1521 bstrutime(dt, sizeof(dt), jcr->sched_time),
1522 jcr->catalog->name(),
1524 NPRTB(jcr->plugin_options));
1528 ua->signal(BNET_RUN_CMD);
1529 ua->send_msg("Type: Restore\n"
1530 "Title: Run Restore job\n"
1536 "Backup Client: %s\n"
1537 "Restore Client: %s\n"
1542 "Plugin Options: %s\n",
1544 NPRT(jcr->RestoreBootstrap),
1545 jcr->where?jcr->where:NPRT(job->RestoreWhere),
1547 jcr->fileset->name(),
1549 jcr->client->name(),
1550 jcr->rstore->name(),
1551 bstrutime(dt, sizeof(dt), jcr->sched_time),
1552 jcr->catalog->name(),
1554 NPRTB(jcr->plugin_options));
1557 ua->send_msg(_("Run Restore job\n"
1563 "Backup Client: %s\n"
1564 "Restore Client: %s\n"
1569 "Plugin Options: %s\n"),
1571 NPRT(jcr->RestoreBootstrap),
1572 jcr->where?jcr->where:NPRT(job->RestoreWhere),
1574 jcr->fileset->name(),
1576 jcr->client->name(),
1577 jcr->rstore->name(),
1578 bstrutime(dt, sizeof(dt), jcr->sched_time),
1579 jcr->catalog->name(),
1581 NPRTB(jcr->plugin_options));
1586 /* ***FIXME*** This needs to be fixed for bat */
1587 if (ua->api) ua->signal(BNET_RUN_CMD);
1588 ua->send_msg(_("Run Restore job\n"
1592 NPRT(jcr->RestoreBootstrap));
1594 /* RegexWhere is take before RestoreWhere */
1595 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
1596 ua->send_msg(_("RegexWhere: %s\n"),
1597 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere);
1599 ua->send_msg(_("Where: %s\n"),
1600 jcr->where?jcr->where:NPRT(job->RestoreWhere));
1603 ua->send_msg(_("Replace: %s\n"
1610 "Plugin Options: %s\n"),
1612 jcr->client->name(),
1613 jcr->rstore->name(),
1614 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
1615 bstrutime(dt, sizeof(dt), jcr->sched_time),
1616 jcr->catalog->name(),
1618 NPRTB(jcr->plugin_options));
1624 jcr->setJobLevel(L_FULL); /* default level */
1626 ua->signal(BNET_RUN_CMD);
1627 if (jcr->getJobType() == JT_COPY) {
1628 prt_type = (char *)"Type: Copy\nTitle: Run Copy Job\n";
1630 prt_type = (char *)"Type: Migration\nTitle: Run Migration Job\n";
1639 "Read Storage: %s\n"
1640 "Write Storage: %s\n"
1647 NPRT(jcr->RestoreBootstrap),
1648 jcr->client->name(),
1649 jcr->fileset->name(),
1650 NPRT(jcr->pool->name()),
1651 jcr->next_pool?jcr->next_pool->name():"*None*",
1652 jcr->rstore->name(),
1653 jcr->wstore?jcr->wstore->name():"*None*",
1654 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
1655 bstrutime(dt, sizeof(dt), jcr->sched_time),
1656 jcr->catalog->name(),
1659 if (jcr->getJobType() == JT_COPY) {
1660 prt_type = _("Run Copy job\n");
1662 prt_type = _("Run Migration job\n");
1669 "Pool: %s (From %s)\n"
1670 "NextPool: %s (From %s)\n"
1671 "Read Storage: %s (From %s)\n"
1672 "Write Storage: %s (From %s)\n"
1679 NPRT(jcr->RestoreBootstrap),
1680 jcr->client->name(),
1681 jcr->fileset->name(),
1682 NPRT(jcr->pool->name()), jcr->pool_source,
1683 jcr->next_pool?jcr->next_pool->name():"*None*",
1684 NPRT(jcr->next_pool_source),
1685 jcr->rstore->name(), jcr->rstore_source,
1686 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
1687 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
1688 bstrutime(dt, sizeof(dt), jcr->sched_time),
1689 jcr->catalog->name(),
1694 ua->error_msg(_("Unknown Job Type=%d\n"), jcr->getJobType());
1701 static bool scan_run_command_line_arguments(UAContext *ua, run_ctx &rc)
1705 static const char *kw[] = { /* command line arguments */
1706 "alljobid", /* 0 Used in a switch() */
1714 "regexwhere", /* 8 where string as a bregexp */
1716 "bootstrap", /* 10 */
1719 "priority", /* 13 */
1720 "yes", /* 14 -- if you change this change YES_POS too */
1721 "verifyjob", /* 15 */
1722 "files", /* 16 number of files to restore */
1723 "catalog", /* 17 override catalog */
1724 "since", /* 18 since */
1725 "cloned", /* 19 cloned */
1726 "verifylist", /* 20 verify output list */
1727 "migrationjob", /* 21 migration job name */
1729 "backupclient", /* 23 */
1730 "restoreclient", /* 24 */
1731 "pluginoptions", /* 25 */
1732 "spooldata", /* 26 */
1734 "ignoreduplicatecheck", /* 28 */
1735 "accurate", /* 29 */
1737 "mediatype", /* 31 */
1738 "nextpool", /* 32 override next pool name */
1743 rc.catalog_name = NULL;
1745 rc.pool_name = NULL;
1746 rc.next_pool_name = NULL;
1747 rc.store_name = NULL;
1748 rc.client_name = NULL;
1749 rc.media_type = NULL;
1750 rc.restore_client_name = NULL;
1751 rc.fileset_name = NULL;
1752 rc.verify_job_name = NULL;
1753 rc.previous_job_name = NULL;
1754 rc.accurate_set = false;
1755 rc.spool_data_set = false;
1756 rc.ignoreduplicatecheck = false;
1758 rc.plugin_options = NULL;
1760 for (i=1; i<ua->argc; i++) {
1761 Dmsg2(800, "Doing arg %d = %s\n", i, ua->argk[i]);
1763 /* Keep looking until we find a good keyword */
1764 for (j=0; !kw_ok && kw[j]; j++) {
1765 if (strcasecmp(ua->argk[i], kw[j]) == 0) {
1766 /* Note, yes and run have no value, so do not fail */
1767 if (!ua->argv[i] && j != YES_POS /*yes*/) {
1768 ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]);
1771 Dmsg2(800, "Got j=%d keyword=%s\n", j, NPRT(kw[j]));
1773 case 0: /* alljobid */
1775 /* Fall through wanted */
1777 if (rc.jid && !rc.mod) {
1778 ua->send_msg(_("JobId specified twice.\n"));
1781 rc.jid = ua->argv[i];
1784 case 2: /* client */
1786 if (rc.client_name) {
1787 ua->send_msg(_("Client specified twice.\n"));
1790 rc.client_name = ua->argv[i];
1793 case 4: /* fileset */
1794 if (rc.fileset_name) {
1795 ua->send_msg(_("FileSet specified twice.\n"));
1798 rc.fileset_name = ua->argv[i];
1802 if (rc.level_name) {
1803 ua->send_msg(_("Level specified twice.\n"));
1806 rc.level_name = ua->argv[i];
1809 case 6: /* storage */
1811 if (rc.store_name) {
1812 ua->send_msg(_("Storage specified twice.\n"));
1815 rc.store_name = ua->argv[i];
1818 case 8: /* regexwhere */
1819 if ((rc.regexwhere || rc.where) && !rc.mod) {
1820 ua->send_msg(_("RegexWhere or Where specified twice.\n"));
1823 rc.regexwhere = ua->argv[i];
1824 if (!acl_access_ok(ua, Where_ACL, rc.regexwhere)) {
1825 ua->send_msg(_("No authorization for \"regexwhere\" specification.\n"));
1831 if ((rc.where || rc.regexwhere) && !rc.mod) {
1832 ua->send_msg(_("Where or RegexWhere specified twice.\n"));
1835 rc.where = ua->argv[i];
1836 if (!acl_access_ok(ua, Where_ACL, rc.where)) {
1837 ua->send_msg(_("No authoriztion for \"where\" specification.\n"));
1842 case 10: /* bootstrap */
1843 if (rc.bootstrap && !rc.mod) {
1844 ua->send_msg(_("Bootstrap specified twice.\n"));
1847 rc.bootstrap = ua->argv[i];
1850 case 11: /* replace */
1851 if (rc.replace && !rc.mod) {
1852 ua->send_msg(_("Replace specified twice.\n"));
1855 rc.replace = ua->argv[i];
1859 if (rc.when && !rc.mod) {
1860 ua->send_msg(_("When specified twice.\n"));
1863 rc.when = ua->argv[i];
1866 case 13: /* Priority */
1867 if (rc.Priority && !rc.mod) {
1868 ua->send_msg(_("Priority specified twice.\n"));
1871 rc.Priority = atoi(ua->argv[i]);
1872 if (rc.Priority <= 0) {
1873 ua->send_msg(_("Priority must be positive nonzero setting it to 10.\n"));
1881 case 15: /* Verify Job */
1882 if (rc.verify_job_name) {
1883 ua->send_msg(_("Verify Job specified twice.\n"));
1886 rc.verify_job_name = ua->argv[i];
1889 case 16: /* files */
1890 rc.files = atoi(ua->argv[i]);
1893 case 17: /* catalog */
1894 rc.catalog_name = ua->argv[i];
1897 case 18: /* since */
1898 rc.since = ua->argv[i];
1901 case 19: /* cloned */
1905 case 20: /* write verify list output */
1906 rc.verify_list = ua->argv[i];
1909 case 21: /* Migration Job */
1910 if (rc.previous_job_name) {
1911 ua->send_msg(_("Migration Job specified twice.\n"));
1914 rc.previous_job_name = ua->argv[i];
1919 ua->send_msg(_("Pool specified twice.\n"));
1922 rc.pool_name = ua->argv[i];
1925 case 23: /* backupclient */
1926 if (rc.client_name) {
1927 ua->send_msg(_("Client specified twice.\n"));
1930 rc.client_name = ua->argv[i];
1933 case 24: /* restoreclient */
1934 if (rc.restore_client_name && !rc.mod) {
1935 ua->send_msg(_("Restore Client specified twice.\n"));
1938 rc.restore_client_name = ua->argv[i];
1941 case 25: /* pluginoptions */
1942 ua->send_msg(_("Plugin Options not yet implemented.\n"));
1944 if (rc.plugin_options) {
1945 ua->send_msg(_("Plugin Options specified twice.\n"));
1948 rc.plugin_options = ua->argv[i];
1949 if (!acl_access_ok(ua, PluginOptions_ACL, rc.plugin_options)) {
1950 ua->send_msg(_("No authoriztion for \"PluginOptions\" specification.\n"));
1955 case 26: /* spooldata */
1956 if (rc.spool_data_set) {
1957 ua->send_msg(_("Spool flag specified twice.\n"));
1960 if (is_yesno(ua->argv[i], &rc.spool_data)) {
1961 rc.spool_data_set = true;
1964 ua->send_msg(_("Invalid spooldata flag.\n"));
1967 case 27: /* comment */
1968 rc.comment = ua->argv[i];
1971 case 28: /* ignoreduplicatecheck */
1972 if (rc.ignoreduplicatecheck_set) {
1973 ua->send_msg(_("IgnoreDuplicateCheck flag specified twice.\n"));
1976 if (is_yesno(ua->argv[i], &rc.ignoreduplicatecheck)) {
1977 rc.ignoreduplicatecheck_set = true;
1980 ua->send_msg(_("Invalid ignoreduplicatecheck flag.\n"));
1983 case 29: /* accurate */
1984 if (rc.accurate_set) {
1985 ua->send_msg(_("Accurate flag specified twice.\n"));
1988 if (is_yesno(ua->argv[i], &rc.accurate)) {
1989 rc.accurate_set = true;
1992 ua->send_msg(_("Invalid accurate flag.\n"));
1997 ua->send_msg(_("Job name specified twice.\n"));
2000 rc.job_name = ua->argv[i];
2003 case 31: /* mediatype */
2004 if (rc.media_type) {
2005 ua->send_msg(_("Media Type specified twice.\n"));
2008 rc.media_type = ua->argv[i];
2011 case 32: /* Next Pool */
2012 if (rc.next_pool_name) {
2013 ua->send_msg(_("NextPool specified twice.\n"));
2016 rc.next_pool_name = ua->argv[i];
2022 } /* end strcase compare */
2023 } /* end keyword loop */
2026 * End of keyword for loop -- if not found, we got a bogus keyword
2029 Dmsg1(800, "%s not found\n", ua->argk[i]);
2031 * Special case for Job Name, it can be the first
2032 * keyword that has no value.
2034 if (!rc.job_name && !ua->argv[i]) {
2035 rc.job_name = ua->argk[i]; /* use keyword as job name */
2036 Dmsg1(800, "Set jobname=%s\n", rc.job_name);
2038 ua->send_msg(_("Invalid keyword: %s\n"), ua->argk[i]);
2042 } /* end argc loop */
2044 Dmsg0(800, "Done scan.\n");
2046 if (!is_comment_legal(ua, rc.comment)) {
2050 if (rc.catalog_name) {
2051 rc.catalog = GetCatalogResWithName(rc.catalog_name);
2052 if (rc.catalog == NULL) {
2053 ua->error_msg(_("Catalog \"%s\" not found\n"), rc.catalog_name);
2056 if (!acl_access_ok(ua, Catalog_ACL, rc.catalog->name())) {
2057 ua->error_msg(_("No authorization. Catalog \"%s\".\n"), rc.catalog->name());
2061 Dmsg1(800, "Using catalog=%s\n", NPRT(rc.catalog_name));
2063 if (!get_job(ua, rc)) {
2067 if (!get_pool(ua, rc)) {
2071 if (!get_next_pool(ua, rc)) {
2075 if (!get_storage(ua, rc)) {
2080 if (!get_client(ua, rc)) {
2084 if (!get_fileset(ua, rc)) {
2088 if (rc.verify_job_name) {
2089 rc.verify_job = GetJobResWithName(rc.verify_job_name);
2090 if (!rc.verify_job) {
2091 ua->send_msg(_("Verify Job \"%s\" not found.\n"), rc.verify_job_name);
2092 rc.verify_job = select_job_resource(ua);
2094 } else if (!rc.verify_job) {
2095 rc.verify_job = rc.job->verify_job;
2098 if (rc.previous_job_name) {
2099 rc.previous_job = GetJobResWithName(rc.previous_job_name);
2100 if (!rc.previous_job) {
2101 ua->send_msg(_("Migration Job \"%s\" not found.\n"), rc.previous_job_name);
2102 rc.previous_job = select_job_resource(ua);
2105 rc.previous_job = rc.job->verify_job;