2 Bacula® - The Network Backup Solution
4 Copyright (C) 2001-2007 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation plus additions
11 that are listed in the file LICENSE.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
30 * Bacula Director -- Run Command
32 * Kern Sibbald, December MMI
42 char *job_name, *level_name, *jid, *store_name, *pool_name;
43 char *where, *fileset_name, *client_name, *bootstrap, *regexwhere;
44 char *restore_client_name;
46 char *when, *verify_job_name, *catalog_name;
47 char *previous_job_name;
64 run_ctx() { memset(this, 0, sizeof(run_ctx));
65 store = new USTORE; };
66 ~run_ctx() { delete store; };
69 /* Forward referenced subroutines */
70 static void select_job_level(UAContext *ua, JCR *jcr);
71 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job,
72 char *verify_list, char *jid, const char *replace,
74 static void select_where_regexp(UAContext *ua, JCR *jcr);
75 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc);
77 /* Imported variables */
78 extern struct s_kw ReplaceOptions[];
81 * For Backup and Verify Jobs
82 * run [job=]<job-name> level=<level-name>
91 int run_cmd(UAContext *ua, const char *cmd)
97 if (!open_client_db(ua)) {
101 if (!scan_command_line_arguments(ua, rc)) {
106 * Create JCR to run job. NOTE!!! after this point, free_jcr()
109 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
110 set_jcr_defaults(jcr, rc.job);
111 jcr->unlink_bsr = ua->jcr->unlink_bsr; /* copy unlink flag from caller */
112 ua->jcr->unlink_bsr = false;
114 jcr->verify_job = rc.verify_job;
115 jcr->previous_job = rc.previous_job;
117 set_rwstorage(jcr, rc.store);
118 jcr->client = rc.client;
119 pm_strcpy(jcr->client_name, rc.client->name());
120 jcr->fileset = rc.fileset;
121 jcr->ExpectedFiles = rc.files;
122 if (rc.catalog != NULL) {
123 jcr->catalog = rc.catalog;
129 jcr->where = bstrdup(rc.where);
133 if (jcr->RegexWhere) {
134 free(jcr->RegexWhere);
136 jcr->RegexWhere = bstrdup(rc.regexwhere);
140 jcr->sched_time = str_to_utime(rc.when);
141 if (jcr->sched_time == 0) {
142 ua->send_msg(_("Invalid time, using current time.\n"));
143 jcr->sched_time = time(NULL);
148 if (jcr->RestoreBootstrap) {
149 free(jcr->RestoreBootstrap);
151 jcr->RestoreBootstrap = bstrdup(rc.bootstrap);
156 for (i=0; ReplaceOptions[i].name; i++) {
157 if (strcasecmp(rc.replace, ReplaceOptions[i].name) == 0) {
158 jcr->replace = ReplaceOptions[i].token;
162 ua->send_msg(_("Invalid replace option: %s\n"), rc.replace);
165 } else if (rc.job->replace) {
166 jcr->replace = rc.job->replace;
168 jcr->replace = REPLACE_ALWAYS;
172 jcr->JobPriority = rc.Priority;
177 jcr->stime = get_pool_memory(PM_MESSAGE);
179 pm_strcpy(jcr->stime, rc.since);
182 jcr->cloned = rc.cloned;
184 if (find_arg(ua, NT_("fdcalled")) > 0) {
185 jcr->file_bsock = dup_bsock(ua->UA_sock);
190 /* If pool changed, update migration write storage */
191 if (jcr->JobType == JT_MIGRATE) {
192 if (!set_migration_wstorage(jcr, rc.pool)) {
196 rc.replace = ReplaceOptions[0].name;
197 for (i=0; ReplaceOptions[i].name; i++) {
198 if (ReplaceOptions[i].token == jcr->replace) {
199 rc.replace = ReplaceOptions[i].name;
203 if (!get_level_from_name(jcr, rc.level_name)) {
204 ua->send_msg(_("Level %s not valid.\n"), rc.level_name);
209 /* Note, this is also MigrateJobId */
210 jcr->RestoreJobId = str_to_int64(rc.jid);
213 /* Run without prompting? */
214 if (ua->batch || find_arg(ua, NT_("yes")) > 0) {
219 * Prompt User to see if all run job parameters are correct, and
220 * allow him to modify them.
222 if (!display_job_parameters(ua, jcr, rc.job, rc.verify_list, rc.jid, rc.replace,
227 if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
231 if (ua->cmd[0] == '.' && strncasecmp(ua->cmd, ".mod ", 5) == 0) {
232 Dmsg1(000, "got: %s\n", ua->cmd);
235 if (!scan_command_line_arguments(ua, rc)) {
242 * At user request modify parameters of job to be run.
244 if (ua->cmd[0] != 0 && strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0) {
247 start_prompt(ua, _("Parameters to modify:\n"));
248 add_prompt(ua, _("Level")); /* 0 */
249 add_prompt(ua, _("Storage")); /* 1 */
250 add_prompt(ua, _("Job")); /* 2 */
251 add_prompt(ua, _("FileSet")); /* 3 */
252 if (jcr->JobType == JT_RESTORE) {
253 add_prompt(ua, _("Restore Client")); /* 4 */
255 add_prompt(ua, _("Client")); /* 4 */
257 add_prompt(ua, _("When")); /* 5 */
258 add_prompt(ua, _("Priority")); /* 6 */
259 if (jcr->JobType == JT_BACKUP ||
260 jcr->JobType == JT_MIGRATE ||
261 jcr->JobType == JT_VERIFY) {
262 add_prompt(ua, _("Pool")); /* 7 */
263 if (jcr->JobType == JT_VERIFY) {
264 add_prompt(ua, _("Verify Job")); /* 8 */
266 } else if (jcr->JobType == JT_RESTORE) {
267 add_prompt(ua, _("Bootstrap")); /* 7 */
268 add_prompt(ua, _("Where")); /* 8 */
269 add_prompt(ua, _("File Relocation"));/* 9 */
270 add_prompt(ua, _("Replace")); /* 10 */
271 add_prompt(ua, _("JobId")); /* 11 */
273 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
276 select_job_level(ua, jcr);
280 rc.store->store = select_storage_resource(ua);
281 if (rc.store->store) {
282 pm_strcpy(rc.store->store_source, _("user selection"));
283 set_rwstorage(jcr, rc.store);
289 rc.job = select_job_resource(ua);
292 set_jcr_defaults(jcr, rc.job);
298 rc.fileset = select_fileset_resource(ua);
300 jcr->fileset = rc.fileset;
306 rc.client = select_client_resource(ua);
308 jcr->client = rc.client;
314 if (!get_cmd(ua, _("Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now): "))) {
317 if (ua->cmd[0] == 0) {
318 jcr->sched_time = time(NULL);
320 jcr->sched_time = str_to_utime(ua->cmd);
321 if (jcr->sched_time == 0) {
322 ua->send_msg(_("Invalid time, using current time.\n"));
323 jcr->sched_time = time(NULL);
329 if (!get_pint(ua, _("Enter new Priority: "))) {
332 if (ua->pint32_val == 0) {
333 ua->send_msg(_("Priority must be a positive integer.\n"));
335 jcr->JobPriority = ua->pint32_val;
339 /* Pool or Bootstrap depending on JobType */
340 if (jcr->JobType == JT_BACKUP ||
341 jcr->JobType == JT_MIGRATE ||
342 jcr->JobType == JT_VERIFY) { /* Pool */
343 rc.pool = select_pool_resource(ua);
346 Dmsg1(100, "Set new pool=%s\n", jcr->pool->name());
353 if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
356 if (jcr->RestoreBootstrap) {
357 free(jcr->RestoreBootstrap);
358 jcr->RestoreBootstrap = NULL;
360 if (ua->cmd[0] != 0) {
361 jcr->RestoreBootstrap = bstrdup(ua->cmd);
362 fd = fopen(jcr->RestoreBootstrap, "rb");
364 ua->send_msg(_("Warning cannot open %s: ERR=%s\n"),
365 jcr->RestoreBootstrap, strerror(errno));
366 free(jcr->RestoreBootstrap);
367 jcr->RestoreBootstrap = NULL;
375 if (jcr->JobType == JT_VERIFY) {
376 rc.verify_job = select_job_resource(ua);
378 jcr->verify_job = rc.verify_job;
383 if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) {
386 if (jcr->RegexWhere) { /* cannot use regexwhere and where */
387 free(jcr->RegexWhere);
388 jcr->RegexWhere = NULL;
394 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
397 jcr->where = bstrdup(ua->cmd);
400 /* File relocation */
401 select_where_regexp(ua, jcr);
405 start_prompt(ua, _("Replace:\n"));
406 for (i=0; ReplaceOptions[i].name; i++) {
407 add_prompt(ua, ReplaceOptions[i].name);
409 opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
411 jcr->replace = ReplaceOptions[opt].token;
416 rc.jid = NULL; /* force reprompt */
417 jcr->RestoreJobId = 0;
418 if (jcr->RestoreBootstrap) {
419 ua->send_msg(_("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
422 case -1: /* error or cancel */
430 if (ua->cmd[0] == 0 || strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
432 Dmsg1(800, "Calling run_job job=%x\n", jcr->job);
435 Dmsg1(100, "Using pool %s\n", jcr->pool->name());
436 JobId = run_job(jcr);
437 free_jcr(jcr); /* release jcr */
439 ua->error_msg(_("Job failed.\n"));
442 ua->send_msg(_("Job queued. JobId=%s\n"), edit_int64(JobId, ed1));
448 ua->send_msg(_("Job not run.\n"));
450 return 0; /* do not run */
453 static void select_where_regexp(UAContext *ua, JCR *jcr)
456 char *strip_prefix, *add_prefix, *add_suffix, *rwhere;
457 strip_prefix = add_suffix = rwhere = add_prefix = NULL;
460 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s\n"),
461 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix));
463 start_prompt(ua, _("This will replace your current Where value\n"));
464 add_prompt(ua, _("Strip prefix")); /* 0 */
465 add_prompt(ua, _("Add prefix")); /* 1 */
466 add_prompt(ua, _("Add file suffix")); /* 2 */
467 add_prompt(ua, _("Enter a regexp")); /* 3 */
468 add_prompt(ua, _("Test filename manipulation")); /* 4 */
469 add_prompt(ua, _("Use this ?")); /* 5 */
471 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
474 if (get_cmd(ua, _("Please enter path prefix to strip: "))) {
475 if (strip_prefix) bfree(strip_prefix);
476 strip_prefix = bstrdup(ua->cmd);
482 if (get_cmd(ua, _("Please enter path prefix to add (/ for none): "))) {
483 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
487 if (add_prefix) bfree(add_prefix);
488 add_prefix = bstrdup(ua->cmd);
493 if (get_cmd(ua, _("Please enter file suffix to add: "))) {
494 if (add_suffix) bfree(add_suffix);
495 add_suffix = bstrdup(ua->cmd);
500 if (get_cmd(ua, _("Please enter a valid regexp (!from!to!): "))) {
501 if (rwhere) bfree(rwhere);
502 rwhere = bstrdup(ua->cmd);
511 if (rwhere && rwhere[0] != '\0') {
512 regs = get_bregexps(rwhere);
513 ua->send_msg(_("regexwhere=%s\n"), NPRT(rwhere));
515 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
516 regexp = (char *) bmalloc (len * sizeof(char));
517 bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix);
518 regs = get_bregexps(regexp);
519 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s result=%s\n"),
520 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix), NPRT(regexp));
526 ua->send_msg(_("Cannot use your regexp\n"));
530 while (get_cmd(ua, _("Please enter filename to test: "))) {
531 apply_bregexps(ua->cmd, regs, &result);
532 ua->send_msg(_("%s -> %s\n"), ua->cmd, result);
541 case -1: /* error or cancel */
547 /* replace the existing where */
553 /* replace the existing regexwhere */
554 if (jcr->RegexWhere) {
555 bfree(jcr->RegexWhere);
556 jcr->RegexWhere = NULL;
560 jcr->RegexWhere = bstrdup(rwhere);
561 } else if (strip_prefix || add_prefix || add_suffix) {
562 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
563 jcr->RegexWhere = (char *) bmalloc(len*sizeof(char));
564 bregexp_build_where(jcr->RegexWhere, len, strip_prefix, add_prefix, add_suffix);
567 regs = get_bregexps(jcr->RegexWhere);
572 if (jcr->RegexWhere) {
573 bfree(jcr->RegexWhere);
574 jcr->RegexWhere = NULL;
576 ua->send_msg(_("Cannot use your regexp.\n"));
580 if (strip_prefix) bfree(strip_prefix);
581 if (add_prefix) bfree(add_prefix);
582 if (add_suffix) bfree(add_suffix);
583 if (rwhere) bfree(rwhere);
586 static void select_job_level(UAContext *ua, JCR *jcr)
588 if (jcr->JobType == JT_BACKUP) {
589 start_prompt(ua, _("Levels:\n"));
590 add_prompt(ua, _("Base"));
591 add_prompt(ua, _("Full"));
592 add_prompt(ua, _("Incremental"));
593 add_prompt(ua, _("Differential"));
594 add_prompt(ua, _("Since"));
595 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
597 jcr->JobLevel = L_BASE;
600 jcr->JobLevel = L_FULL;
603 jcr->JobLevel = L_INCREMENTAL;
606 jcr->JobLevel = L_DIFFERENTIAL;
609 jcr->JobLevel = L_SINCE;
614 } else if (jcr->JobType == JT_VERIFY) {
615 start_prompt(ua, _("Levels:\n"));
616 add_prompt(ua, _("Initialize Catalog"));
617 add_prompt(ua, _("Verify Catalog"));
618 add_prompt(ua, _("Verify Volume to Catalog"));
619 add_prompt(ua, _("Verify Disk to Catalog"));
620 add_prompt(ua, _("Verify Volume Data (not yet implemented)"));
621 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
623 jcr->JobLevel = L_VERIFY_INIT;
626 jcr->JobLevel = L_VERIFY_CATALOG;
629 jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG;
632 jcr->JobLevel = L_VERIFY_DISK_TO_CATALOG;
635 jcr->JobLevel = L_VERIFY_DATA;
641 ua->warning_msg(_("Level not appropriate for this Job. Cannot be changed.\n"));
646 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, char *verify_list,
647 char *jid, const char *replace, char *client_name)
649 Dmsg1(800, "JobType=%c\n", jcr->JobType);
650 switch (jcr->JobType) {
652 char dt[MAX_TIME_LENGTH];
654 if (ua->api) ua->signal(BNET_RUN_CMD);
655 ua->send_msg(_("Run %s job\n"
664 jcr->fileset->name(),
665 NPRT(jcr->client->name()),
666 jcr->wstore?jcr->wstore->name():"*None*",
667 bstrutime(dt, sizeof(dt), jcr->sched_time),
669 jcr->JobLevel = L_FULL;
673 if (jcr->JobType == JT_BACKUP) {
674 if (ua->api) ua->signal(BNET_RUN_CMD);
675 ua->send_msg(_("Run %s job\n"
680 "Pool: %s (From %s)\n"
681 "Storage: %s (From %s)\n"
686 level_to_str(jcr->JobLevel),
688 jcr->fileset->name(),
689 NPRT(jcr->pool->name()), jcr->pool_source,
690 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
691 bstrutime(dt, sizeof(dt), jcr->sched_time),
693 } else { /* JT_VERIFY */
695 if (jcr->verify_job) {
696 Name = jcr->verify_job->name();
701 verify_list = job->WriteVerifyList;
706 if (ua->api) ua->signal(BNET_RUN_CMD);
707 ua->send_msg(_("Run %s job\n"
712 "Pool: %s (From %s)\n"
713 "Storage: %s (From %s)\n"
720 level_to_str(jcr->JobLevel),
722 jcr->fileset->name(),
723 NPRT(jcr->pool->name()), jcr->pool_source,
724 jcr->rstore->name(), jcr->rstore_source,
727 bstrutime(dt, sizeof(dt), jcr->sched_time),
732 if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
734 jcr->RestoreJobId = str_to_int64(jid);
736 if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
739 jcr->RestoreJobId = ua->int64_val;
742 jcr->JobLevel = L_FULL; /* default level */
743 Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId);
744 if (jcr->RestoreJobId == 0) {
745 if (ua->api) ua->signal(BNET_RUN_CMD);
746 /* RegexWhere is take before RestoreWhere */
747 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
748 ua->send_msg(_("Run Restore job\n"
754 "Backup Client: %s\n"
755 "Restore Client: %s\n"
761 NPRT(jcr->RestoreBootstrap),
762 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
764 jcr->fileset->name(),
768 bstrutime(dt, sizeof(dt), jcr->sched_time),
769 jcr->catalog->name(),
773 ua->send_msg(_("Run Restore job\n"
779 "Backup Client: %s\n"
780 "Restore Client: %s\n"
786 NPRT(jcr->RestoreBootstrap),
787 jcr->where?jcr->where:NPRT(job->RestoreWhere),
789 jcr->fileset->name(),
793 bstrutime(dt, sizeof(dt), jcr->sched_time),
794 jcr->catalog->name(),
799 if (ua->api) ua->signal(BNET_RUN_CMD);
800 ua->send_msg(_("Run Restore job\n"
804 NPRT(jcr->RestoreBootstrap));
806 /* RegexWhere is take before RestoreWhere */
807 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
808 ua->send_msg(_("RegexWhere: %s\n"),
809 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere);
811 ua->send_msg(_("Where: %s\n"),
812 jcr->where?jcr->where:NPRT(job->RestoreWhere));
815 ua->send_msg(_("Replace: %s\n"
825 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
826 bstrutime(dt, sizeof(dt), jcr->sched_time),
827 jcr->catalog->name(),
832 jcr->JobLevel = L_FULL; /* default level */
833 if (ua->api) ua->signal(BNET_RUN_CMD);
834 ua->send_msg(_("Run Migration job\n"
839 "Pool: %s (From %s)\n"
840 "Read Storage: %s (From %s)\n"
841 "Write Storage: %s (From %s)\n"
847 NPRT(jcr->RestoreBootstrap),
849 jcr->fileset->name(),
850 NPRT(jcr->pool->name()), jcr->pool_source,
851 jcr->rstore->name(), jcr->rstore_source,
852 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
853 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
854 bstrutime(dt, sizeof(dt), jcr->sched_time),
855 jcr->catalog->name(),
859 ua->error_msg(_("Unknown Job Type=%d\n"), jcr->JobType);
866 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc)
870 static const char *kw[] = { /* command line arguments */
871 "job", /* Used in a switch() */
879 "regexwhere", /* 8 where string as a bregexp */
881 "bootstrap", /* 10 */
885 "yes", /* 14 -- if you change this change YES_POS too */
886 "verifyjob", /* 15 */
887 "files", /* 16 number of files to restore */
888 "catalog", /* 17 override catalog */
889 "since", /* 18 since */
890 "cloned", /* 19 cloned */
891 "verifylist", /* 20 verify output list */
892 "migrationjob", /* 21 migration job name */
894 "backupclient", /* 23 */
895 "restoreclient", /* 24 */
900 for (i=1; i<ua->argc; i++) {
901 Dmsg2(800, "Doing arg %d = %s\n", i, ua->argk[i]);
903 /* Keep looking until we find a good keyword */
904 for (j=0; !kw_ok && kw[j]; j++) {
905 if (strcasecmp(ua->argk[i], kw[j]) == 0) {
906 /* Note, yes and run have no value, so do not fail */
907 if (!ua->argv[i] && j != YES_POS /*yes*/) {
908 ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]);
911 Dmsg1(800, "Got keyword=%s\n", NPRT(kw[j]));
914 if (rc.job_name && !rc.mod) {
915 ua->send_msg(_("Job name specified twice.\n"));
918 rc.job_name = ua->argv[i];
922 if (rc.jid && !rc.mod) {
923 ua->send_msg(_("JobId specified twice.\n"));
926 rc.jid = ua->argv[i];
931 if (rc.client_name && !rc.mod) {
932 ua->send_msg(_("Client specified twice.\n"));
935 rc.client_name = ua->argv[i];
938 case 4: /* fileset */
939 if (rc.fileset_name && !rc.mod) {
940 ua->send_msg(_("FileSet specified twice.\n"));
943 rc.fileset_name = ua->argv[i];
947 if (rc.level_name && !rc.mod) {
948 ua->send_msg(_("Level specified twice.\n"));
951 rc.level_name = ua->argv[i];
954 case 6: /* storage */
956 if (rc.store_name && !rc.mod) {
957 ua->send_msg(_("Storage specified twice.\n"));
960 rc.store_name = ua->argv[i];
963 case 8: /* regexwhere */
964 if ((rc.regexwhere || rc.where) && !rc.mod) {
965 ua->send_msg(_("RegexWhere or Where specified twice.\n"));
968 rc.regexwhere = ua->argv[i];
969 if (!acl_access_ok(ua, Where_ACL, rc.regexwhere)) {
970 ua->send_msg(_("No authorization for \"regexwhere\" specification.\n"));
976 if ((rc.where || rc.regexwhere) && !rc.mod) {
977 ua->send_msg(_("Where or RegexWhere specified twice.\n"));
980 rc.where = ua->argv[i];
981 if (!acl_access_ok(ua, Where_ACL, rc.where)) {
982 ua->send_msg(_("No authoriztion for \"where\" specification.\n"));
987 case 10: /* bootstrap */
988 if (rc.bootstrap && !rc.mod) {
989 ua->send_msg(_("Bootstrap specified twice.\n"));
992 rc.bootstrap = ua->argv[i];
995 case 11: /* replace */
996 if (rc.replace && !rc.mod) {
997 ua->send_msg(_("Replace specified twice.\n"));
1000 rc.replace = ua->argv[i];
1004 if (rc.when && !rc.mod) {
1005 ua->send_msg(_("When specified twice.\n"));
1008 rc.when = ua->argv[i];
1011 case 13: /* Priority */
1012 if (rc.Priority && !rc.mod) {
1013 ua->send_msg(_("Priority specified twice.\n"));
1016 rc.Priority = atoi(ua->argv[i]);
1017 if (rc.Priority <= 0) {
1018 ua->send_msg(_("Priority must be positive nonzero setting it to 10.\n"));
1026 case 15: /* Verify Job */
1027 if (rc.verify_job_name && !rc.mod) {
1028 ua->send_msg(_("Verify Job specified twice.\n"));
1031 rc.verify_job_name = ua->argv[i];
1034 case 16: /* files */
1035 rc.files = atoi(ua->argv[i]);
1039 case 17: /* catalog */
1040 rc.catalog_name = ua->argv[i];
1044 case 18: /* since */
1045 rc.since = ua->argv[i];
1049 case 19: /* cloned */
1054 case 20: /* write verify list output */
1055 rc.verify_list = ua->argv[i];
1058 case 21: /* Migration Job */
1059 if (rc.previous_job_name && !rc.mod) {
1060 ua->send_msg(_("Migration Job specified twice.\n"));
1063 rc.previous_job_name = ua->argv[i];
1067 if (rc.pool_name && !rc.mod) {
1068 ua->send_msg(_("Pool specified twice.\n"));
1071 rc.pool_name = ua->argv[i];
1074 case 23: /* backupclient */
1075 if (rc.client_name && !rc.mod) {
1076 ua->send_msg(_("Client specified twice.\n"));
1079 rc.client_name = ua->argv[i];
1082 case 24: /* restoreclient */
1083 if (rc.restore_client_name && !rc.mod) {
1084 ua->send_msg(_("Restore Client specified twice.\n"));
1087 rc.restore_client_name = ua->argv[i];
1093 } /* end strcase compare */
1094 } /* end keyword loop */
1096 * End of keyword for loop -- if not found, we got a bogus keyword
1099 Dmsg1(800, "%s not found\n", ua->argk[i]);
1101 * Special case for Job Name, it can be the first
1102 * keyword that has no value.
1104 if (!rc.job_name && !ua->argv[i]) {
1105 rc.job_name = ua->argk[i]; /* use keyword as job name */
1106 Dmsg1(800, "Set jobname=%s\n", rc.job_name);
1108 ua->send_msg(_("Invalid keyword: %s\n"), ua->argk[i]);
1112 } /* end argc loop */
1114 Dmsg0(800, "Done scan.\n");
1116 if (rc.catalog_name != NULL) {
1117 rc.catalog = GetCatalogResWithName(rc.catalog_name);
1118 if (rc.catalog == NULL) {
1119 ua->error_msg(_("Catalog \"%s\" not found\n"), rc.catalog_name);
1122 if (!acl_access_ok(ua, Catalog_ACL, rc.catalog->name())) {
1123 ua->error_msg(_("No authorization. Catalog \"%s\".\n"), rc.catalog->name());
1127 Dmsg1(800, "Using catalog=%s\n", NPRT(rc.catalog_name));
1131 rc.job = GetJobResWithName(rc.job_name);
1133 if (*rc.job_name != 0) {
1134 ua->send_msg(_("Job \"%s\" not found\n"), rc.job_name);
1136 rc.job = select_job_resource(ua);
1138 Dmsg1(800, "Found job=%s\n", rc.job_name);
1141 ua->send_msg(_("A job name must be specified.\n"));
1142 rc.job = select_job_resource(ua);
1146 } else if (!acl_access_ok(ua, Job_ACL, rc.job->name())) {
1147 ua->error_msg( _("No authorization. Job \"%s\".\n"), rc.job->name());
1152 rc.pool = GetPoolResWithName(rc.pool_name);
1154 if (*rc.pool_name != 0) {
1155 ua->warning_msg(_("Pool \"%s\" not found.\n"), rc.pool_name);
1157 rc.pool = select_pool_resource(ua);
1160 rc.pool = rc.job->pool; /* use default */
1164 } else if (!acl_access_ok(ua, Pool_ACL, rc.pool->name())) {
1165 ua->error_msg(_("No authorization. Pool \"%s\".\n"), rc.pool->name());
1168 Dmsg1(100, "Using pool %s\n", rc.pool->name());
1170 if (rc.store_name) {
1171 rc.store->store = GetStoreResWithName(rc.store_name);
1172 pm_strcpy(rc.store->store_source, _("command line"));
1173 if (!rc.store->store) {
1174 if (*rc.store_name != 0) {
1175 ua->warning_msg(_("Storage \"%s\" not found.\n"), rc.store_name);
1177 rc.store->store = select_storage_resource(ua);
1178 pm_strcpy(rc.store->store_source, _("user selection"));
1181 get_job_storage(rc.store, rc.job, NULL); /* use default */
1183 if (!rc.store->store) {
1184 ua->error_msg(_("No storage specified.\n"));
1186 } else if (!acl_access_ok(ua, Storage_ACL, rc.store->store->name())) {
1187 ua->error_msg(_("No authorization. Storage \"%s\".\n"),
1188 rc.store->store->name());
1191 Dmsg1(800, "Using storage=%s\n", rc.store->store->name());
1193 if (rc.client_name) {
1194 rc.client = GetClientResWithName(rc.client_name);
1196 if (*rc.client_name != 0) {
1197 ua->warning_msg(_("Client \"%s\" not found.\n"), rc.client_name);
1199 rc.client = select_client_resource(ua);
1202 rc.client = rc.job->client; /* use default */
1206 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1207 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1211 Dmsg1(800, "Using client=%s\n", rc.client->name());
1213 if (rc.restore_client_name) {
1214 rc.client = GetClientResWithName(rc.restore_client_name);
1216 if (*rc.restore_client_name != 0) {
1217 ua->warning_msg(_("Restore Client \"%s\" not found.\n"), rc.restore_client_name);
1219 rc.client = select_client_resource(ua);
1222 rc.client = rc.job->client; /* use default */
1226 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1227 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1231 Dmsg1(800, "Using restore client=%s\n", rc.client->name());
1234 if (rc.fileset_name) {
1235 rc.fileset = GetFileSetResWithName(rc.fileset_name);
1237 ua->send_msg(_("FileSet \"%s\" not found.\n"), rc.fileset_name);
1238 rc.fileset = select_fileset_resource(ua);
1241 rc.fileset = rc.job->fileset; /* use default */
1245 } else if (!acl_access_ok(ua, FileSet_ACL, rc.fileset->name())) {
1246 ua->send_msg(_("No authorization. FileSet \"%s\".\n"),
1247 rc.fileset->name());
1251 if (rc.verify_job_name) {
1252 rc.verify_job = GetJobResWithName(rc.verify_job_name);
1253 if (!rc.verify_job) {
1254 ua->send_msg(_("Verify Job \"%s\" not found.\n"), rc.verify_job_name);
1255 rc.verify_job = select_job_resource(ua);
1258 rc.verify_job = rc.job->verify_job;
1261 if (rc.previous_job_name) {
1262 rc.previous_job = GetJobResWithName(rc.previous_job_name);
1263 if (!rc.previous_job) {
1264 ua->send_msg(_("Migration Job \"%s\" not found.\n"), rc.previous_job_name);
1265 rc.previous_job = select_job_resource(ua);
1268 rc.previous_job = rc.job->verify_job;