2 Bacula® - The Network Backup Solution
4 Copyright (C) 2001-2008 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 and included
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;
50 const char *verify_list;
65 run_ctx() { memset(this, 0, sizeof(run_ctx));
66 store = new USTORE; };
67 ~run_ctx() { delete store; };
70 /* Forward referenced subroutines */
71 static void select_job_level(UAContext *ua, JCR *jcr);
72 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job,
73 const char *verify_list, char *jid, const char *replace,
75 static void select_where_regexp(UAContext *ua, JCR *jcr);
76 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc);
77 static bool reset_restore_context(UAContext *ua, JCR *jcr, run_ctx &rc);
78 static int modify_job_parameters(UAContext *ua, JCR *jcr, run_ctx &rc);
80 /* Imported variables */
81 extern struct s_kw ReplaceOptions[];
84 * For Backup and Verify Jobs
85 * run [job=]<job-name> level=<level-name>
94 int run_cmd(UAContext *ua, const char *cmd)
100 if (!open_client_db(ua)) {
104 if (!scan_command_line_arguments(ua, rc)) {
108 if (find_arg(ua, NT_("fdcalled")) > 0) {
109 jcr->file_bsock = dup_bsock(ua->UA_sock);
114 * Create JCR to run job. NOTE!!! after this point, free_jcr()
118 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
119 set_jcr_defaults(jcr, rc.job);
120 jcr->unlink_bsr = ua->jcr->unlink_bsr; /* copy unlink flag from caller */
121 ua->jcr->unlink_bsr = false;
125 if (!reset_restore_context(ua, jcr, rc)) {
130 /* Run without prompting? */
131 if (ua->batch || find_arg(ua, NT_("yes")) > 0) {
136 * Prompt User to see if all run job parameters are correct, and
137 * allow him to modify them.
139 if (!display_job_parameters(ua, jcr, rc.job, rc.verify_list, rc.jid, rc.replace,
144 if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
148 if (strncasecmp(ua->cmd, ".mod ", 5) == 0 ||
149 (strncasecmp(ua->cmd, "mod ", 4) == 0 && strlen(ua->cmd) > 6)) {
152 if (!scan_command_line_arguments(ua, rc)) {
158 /* Allow the user to modify the settings */
159 status = modify_job_parameters(ua, jcr, rc);
170 if (ua->cmd[0] == 0 || strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
172 Dmsg1(800, "Calling run_job job=%x\n", jcr->job);
175 Dmsg3(100, "JobId=%u using pool %s priority=%d\n", (int)jcr->JobId,
176 jcr->pool->name(), jcr->JobPriority);
177 JobId = run_job(jcr);
178 Dmsg4(100, "JobId=%u NewJobId=%d using pool %s priority=%d\n", (int)jcr->JobId,
179 JobId, jcr->pool->name(), jcr->JobPriority);
180 free_jcr(jcr); /* release jcr */
182 ua->error_msg(_("Job failed.\n"));
185 ua->send_msg(_("Job queued. JobId=%s\n"), edit_int64(JobId, ed1));
191 ua->send_msg(_("Job not run.\n"));
193 return 0; /* do not run */
196 int modify_job_parameters(UAContext *ua, JCR *jcr, run_ctx &rc)
200 * At user request modify parameters of job to be run.
202 if (ua->cmd[0] != 0 && strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0) {
205 start_prompt(ua, _("Parameters to modify:\n"));
206 add_prompt(ua, _("Level")); /* 0 */
207 add_prompt(ua, _("Storage")); /* 1 */
208 add_prompt(ua, _("Job")); /* 2 */
209 add_prompt(ua, _("FileSet")); /* 3 */
210 if (jcr->JobType == JT_RESTORE) {
211 add_prompt(ua, _("Restore Client")); /* 4 */
213 add_prompt(ua, _("Client")); /* 4 */
215 add_prompt(ua, _("When")); /* 5 */
216 add_prompt(ua, _("Priority")); /* 6 */
217 if (jcr->JobType == JT_BACKUP ||
218 jcr->JobType == JT_COPY ||
219 jcr->JobType == JT_MIGRATE ||
220 jcr->JobType == JT_VERIFY) {
221 add_prompt(ua, _("Pool")); /* 7 */
222 if (jcr->JobType == JT_VERIFY) {
223 add_prompt(ua, _("Verify Job")); /* 8 */
225 } else if (jcr->JobType == JT_RESTORE) {
226 add_prompt(ua, _("Bootstrap")); /* 7 */
227 add_prompt(ua, _("Where")); /* 8 */
228 add_prompt(ua, _("File Relocation"));/* 9 */
229 add_prompt(ua, _("Replace")); /* 10 */
230 add_prompt(ua, _("JobId")); /* 11 */
232 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
235 select_job_level(ua, jcr);
239 rc.store->store = select_storage_resource(ua);
240 if (rc.store->store) {
241 pm_strcpy(rc.store->store_source, _("user selection"));
242 set_rwstorage(jcr, rc.store);
248 rc.job = select_job_resource(ua);
251 set_jcr_defaults(jcr, rc.job);
257 rc.fileset = select_fileset_resource(ua);
259 jcr->fileset = rc.fileset;
265 rc.client = select_client_resource(ua);
267 jcr->client = rc.client;
273 if (!get_cmd(ua, _("Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now): "))) {
276 if (ua->cmd[0] == 0) {
277 jcr->sched_time = time(NULL);
279 jcr->sched_time = str_to_utime(ua->cmd);
280 if (jcr->sched_time == 0) {
281 ua->send_msg(_("Invalid time, using current time.\n"));
282 jcr->sched_time = time(NULL);
288 if (!get_pint(ua, _("Enter new Priority: "))) {
291 if (ua->pint32_val == 0) {
292 ua->send_msg(_("Priority must be a positive integer.\n"));
294 jcr->JobPriority = ua->pint32_val;
298 /* Pool or Bootstrap depending on JobType */
299 if (jcr->JobType == JT_BACKUP ||
300 jcr->JobType == JT_COPY ||
301 jcr->JobType == JT_MIGRATE ||
302 jcr->JobType == JT_VERIFY) { /* Pool */
303 rc.pool = select_pool_resource(ua);
306 Dmsg1(100, "Set new pool=%s\n", jcr->pool->name());
313 if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
316 if (jcr->RestoreBootstrap) {
317 free(jcr->RestoreBootstrap);
318 jcr->RestoreBootstrap = NULL;
320 if (ua->cmd[0] != 0) {
321 jcr->RestoreBootstrap = bstrdup(ua->cmd);
322 fd = fopen(jcr->RestoreBootstrap, "rb");
325 ua->send_msg(_("Warning cannot open %s: ERR=%s\n"),
326 jcr->RestoreBootstrap, be.bstrerror());
327 free(jcr->RestoreBootstrap);
328 jcr->RestoreBootstrap = NULL;
336 if (jcr->JobType == JT_VERIFY) {
337 rc.verify_job = select_job_resource(ua);
339 jcr->verify_job = rc.verify_job;
344 if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) {
347 if (jcr->RegexWhere) { /* cannot use regexwhere and where */
348 free(jcr->RegexWhere);
349 jcr->RegexWhere = NULL;
355 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
358 jcr->where = bstrdup(ua->cmd);
361 /* File relocation */
362 select_where_regexp(ua, jcr);
366 start_prompt(ua, _("Replace:\n"));
367 for (i=0; ReplaceOptions[i].name; i++) {
368 add_prompt(ua, ReplaceOptions[i].name);
370 opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
372 rc.replace = ReplaceOptions[opt].name;
373 jcr->replace = ReplaceOptions[opt].token;
378 rc.jid = NULL; /* force reprompt */
379 jcr->RestoreJobId = 0;
380 if (jcr->RestoreBootstrap) {
381 ua->send_msg(_("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
384 case -1: /* error or cancel */
401 * Reset the restore context.
402 * This subroutine can be called multiple times, so it
403 * must keep any prior settings.
405 static bool reset_restore_context(UAContext *ua, JCR *jcr, run_ctx &rc)
409 jcr->verify_job = rc.verify_job;
410 jcr->previous_job = rc.previous_job;
412 if (jcr->pool != jcr->job->pool) {
413 pm_strcpy(jcr->pool_source, _("User input"));
415 set_rwstorage(jcr, rc.store);
416 jcr->client = rc.client;
417 pm_strcpy(jcr->client_name, rc.client->name());
418 jcr->fileset = rc.fileset;
419 jcr->ExpectedFiles = rc.files;
421 jcr->catalog = rc.catalog;
422 pm_strcpy(jcr->catalog_source, _("User input"));
428 jcr->where = bstrdup(rc.where);
434 if (jcr->RegexWhere) {
435 free(jcr->RegexWhere);
437 jcr->RegexWhere = bstrdup(rc.regexwhere);
438 rc.regexwhere = NULL;
442 jcr->sched_time = str_to_utime(rc.when);
443 if (jcr->sched_time == 0) {
444 ua->send_msg(_("Invalid time, using current time.\n"));
445 jcr->sched_time = time(NULL);
451 if (jcr->RestoreBootstrap) {
452 free(jcr->RestoreBootstrap);
454 jcr->RestoreBootstrap = bstrdup(rc.bootstrap);
458 if (rc.plugin_options) {
459 if (jcr->plugin_options) {
460 free(jcr->plugin_options);
462 jcr->plugin_options = bstrdup(rc.plugin_options);
463 rc.plugin_options = NULL;
469 for (i=0; ReplaceOptions[i].name; i++) {
470 if (strcasecmp(rc.replace, ReplaceOptions[i].name) == 0) {
471 jcr->replace = ReplaceOptions[i].token;
475 ua->send_msg(_("Invalid replace option: %s\n"), rc.replace);
478 } else if (rc.job->replace) {
479 jcr->replace = rc.job->replace;
481 jcr->replace = REPLACE_ALWAYS;
486 jcr->JobPriority = rc.Priority;
492 jcr->stime = get_pool_memory(PM_MESSAGE);
494 pm_strcpy(jcr->stime, rc.since);
499 jcr->cloned = rc.cloned;
504 /* If pool changed, update migration write storage */
505 if (jcr->JobType == JT_MIGRATE || jcr->JobType == JT_COPY) {
506 if (!set_migration_wstorage(jcr, rc.pool)) {
510 rc.replace = ReplaceOptions[0].name;
511 for (i=0; ReplaceOptions[i].name; i++) {
512 if (ReplaceOptions[i].token == jcr->replace) {
513 rc.replace = ReplaceOptions[i].name;
517 if (!get_level_from_name(jcr, rc.level_name)) {
518 ua->send_msg(_("Level %s not valid.\n"), rc.level_name);
521 rc.level_name = NULL;
524 /* Note, this is also MigrateJobId */
525 jcr->RestoreJobId = str_to_int64(rc.jid);
531 static void select_where_regexp(UAContext *ua, JCR *jcr)
534 char *strip_prefix, *add_prefix, *add_suffix, *rwhere;
535 strip_prefix = add_suffix = rwhere = add_prefix = NULL;
538 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s\n"),
539 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix));
541 start_prompt(ua, _("This will replace your current Where value\n"));
542 add_prompt(ua, _("Strip prefix")); /* 0 */
543 add_prompt(ua, _("Add prefix")); /* 1 */
544 add_prompt(ua, _("Add file suffix")); /* 2 */
545 add_prompt(ua, _("Enter a regexp")); /* 3 */
546 add_prompt(ua, _("Test filename manipulation")); /* 4 */
547 add_prompt(ua, _("Use this ?")); /* 5 */
549 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
552 if (get_cmd(ua, _("Please enter path prefix to strip: "))) {
553 if (strip_prefix) bfree(strip_prefix);
554 strip_prefix = bstrdup(ua->cmd);
560 if (get_cmd(ua, _("Please enter path prefix to add (/ for none): "))) {
561 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
565 if (add_prefix) bfree(add_prefix);
566 add_prefix = bstrdup(ua->cmd);
571 if (get_cmd(ua, _("Please enter file suffix to add: "))) {
572 if (add_suffix) bfree(add_suffix);
573 add_suffix = bstrdup(ua->cmd);
578 if (get_cmd(ua, _("Please enter a valid regexp (!from!to!): "))) {
579 if (rwhere) bfree(rwhere);
580 rwhere = bstrdup(ua->cmd);
589 if (rwhere && rwhere[0] != '\0') {
590 regs = get_bregexps(rwhere);
591 ua->send_msg(_("regexwhere=%s\n"), NPRT(rwhere));
593 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
594 regexp = (char *) bmalloc (len * sizeof(char));
595 bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix);
596 regs = get_bregexps(regexp);
597 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s result=%s\n"),
598 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix), NPRT(regexp));
604 ua->send_msg(_("Cannot use your regexp\n"));
608 while (get_cmd(ua, _("Please enter filename to test: "))) {
609 apply_bregexps(ua->cmd, regs, &result);
610 ua->send_msg(_("%s -> %s\n"), ua->cmd, result);
619 case -1: /* error or cancel */
625 /* replace the existing where */
631 /* replace the existing regexwhere */
632 if (jcr->RegexWhere) {
633 bfree(jcr->RegexWhere);
634 jcr->RegexWhere = NULL;
638 jcr->RegexWhere = bstrdup(rwhere);
639 } else if (strip_prefix || add_prefix || add_suffix) {
640 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
641 jcr->RegexWhere = (char *) bmalloc(len*sizeof(char));
642 bregexp_build_where(jcr->RegexWhere, len, strip_prefix, add_prefix, add_suffix);
645 regs = get_bregexps(jcr->RegexWhere);
650 if (jcr->RegexWhere) {
651 bfree(jcr->RegexWhere);
652 jcr->RegexWhere = NULL;
654 ua->send_msg(_("Cannot use your regexp.\n"));
658 if (strip_prefix) bfree(strip_prefix);
659 if (add_prefix) bfree(add_prefix);
660 if (add_suffix) bfree(add_suffix);
661 if (rwhere) bfree(rwhere);
664 static void select_job_level(UAContext *ua, JCR *jcr)
666 if (jcr->JobType == JT_BACKUP) {
667 start_prompt(ua, _("Levels:\n"));
668 add_prompt(ua, _("Base"));
669 add_prompt(ua, _("Full"));
670 add_prompt(ua, _("Incremental"));
671 add_prompt(ua, _("Differential"));
672 add_prompt(ua, _("Since"));
673 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
675 jcr->JobLevel = L_BASE;
678 jcr->JobLevel = L_FULL;
681 jcr->JobLevel = L_INCREMENTAL;
684 jcr->JobLevel = L_DIFFERENTIAL;
687 jcr->JobLevel = L_SINCE;
692 } else if (jcr->JobType == JT_VERIFY) {
693 start_prompt(ua, _("Levels:\n"));
694 add_prompt(ua, _("Initialize Catalog"));
695 add_prompt(ua, _("Verify Catalog"));
696 add_prompt(ua, _("Verify Volume to Catalog"));
697 add_prompt(ua, _("Verify Disk to Catalog"));
698 add_prompt(ua, _("Verify Volume Data (not yet implemented)"));
699 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
701 jcr->JobLevel = L_VERIFY_INIT;
704 jcr->JobLevel = L_VERIFY_CATALOG;
707 jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG;
710 jcr->JobLevel = L_VERIFY_DISK_TO_CATALOG;
713 jcr->JobLevel = L_VERIFY_DATA;
719 ua->warning_msg(_("Level not appropriate for this Job. Cannot be changed.\n"));
724 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char *verify_list,
725 char *jid, const char *replace, char *client_name)
727 Dmsg1(800, "JobType=%c\n", jcr->JobType);
728 switch (jcr->JobType) {
730 char dt[MAX_TIME_LENGTH];
732 if (ua->api) ua->signal(BNET_RUN_CMD);
733 ua->send_msg(_("Run %s job\n"
742 jcr->fileset->name(),
743 NPRT(jcr->client->name()),
744 jcr->wstore?jcr->wstore->name():"*None*",
745 bstrutime(dt, sizeof(dt), jcr->sched_time),
747 jcr->JobLevel = L_FULL;
751 if (jcr->JobType == JT_BACKUP) {
752 if (ua->api) ua->signal(BNET_RUN_CMD);
753 ua->send_msg(_("Run %s job\n"
758 "Pool: %s (From %s)\n"
759 "Storage: %s (From %s)\n"
764 level_to_str(jcr->JobLevel),
766 jcr->fileset->name(),
767 NPRT(jcr->pool->name()), jcr->pool_source,
768 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
769 bstrutime(dt, sizeof(dt), jcr->sched_time),
771 } else { /* JT_VERIFY */
773 if (jcr->verify_job) {
774 Name = jcr->verify_job->name();
779 verify_list = job->WriteVerifyList;
784 if (ua->api) ua->signal(BNET_RUN_CMD);
785 ua->send_msg(_("Run %s job\n"
790 "Pool: %s (From %s)\n"
791 "Storage: %s (From %s)\n"
798 level_to_str(jcr->JobLevel),
800 jcr->fileset->name(),
801 NPRT(jcr->pool->name()), jcr->pool_source,
802 jcr->rstore->name(), jcr->rstore_source,
805 bstrutime(dt, sizeof(dt), jcr->sched_time),
810 if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
812 jcr->RestoreJobId = str_to_int64(jid);
814 if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
817 jcr->RestoreJobId = ua->int64_val;
820 jcr->JobLevel = L_FULL; /* default level */
821 Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId);
822 if (jcr->RestoreJobId == 0) {
823 if (ua->api) ua->signal(BNET_RUN_CMD);
824 /* RegexWhere is take before RestoreWhere */
825 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
826 ua->send_msg(_("Run Restore job\n"
832 "Backup Client: %s\n"
833 "Restore Client: %s\n"
839 NPRT(jcr->RestoreBootstrap),
840 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
842 jcr->fileset->name(),
846 bstrutime(dt, sizeof(dt), jcr->sched_time),
847 jcr->catalog->name(),
851 ua->send_msg(_("Run Restore job\n"
857 "Backup Client: %s\n"
858 "Restore Client: %s\n"
864 NPRT(jcr->RestoreBootstrap),
865 jcr->where?jcr->where:NPRT(job->RestoreWhere),
867 jcr->fileset->name(),
871 bstrutime(dt, sizeof(dt), jcr->sched_time),
872 jcr->catalog->name(),
877 if (ua->api) ua->signal(BNET_RUN_CMD);
878 ua->send_msg(_("Run Restore job\n"
882 NPRT(jcr->RestoreBootstrap));
884 /* RegexWhere is take before RestoreWhere */
885 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
886 ua->send_msg(_("RegexWhere: %s\n"),
887 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere);
889 ua->send_msg(_("Where: %s\n"),
890 jcr->where?jcr->where:NPRT(job->RestoreWhere));
893 ua->send_msg(_("Replace: %s\n"
903 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
904 bstrutime(dt, sizeof(dt), jcr->sched_time),
905 jcr->catalog->name(),
912 if (jcr->JobType == JT_COPY) {
913 prt_type = _("Run Copy job\n");
915 prt_type = _("Run Migration job\n");
917 jcr->JobLevel = L_FULL; /* default level */
918 if (ua->api) ua->signal(BNET_RUN_CMD);
924 "Pool: %s (From %s)\n"
925 "Read Storage: %s (From %s)\n"
926 "Write Storage: %s (From %s)\n"
933 NPRT(jcr->RestoreBootstrap),
935 jcr->fileset->name(),
936 NPRT(jcr->pool->name()), jcr->pool_source,
937 jcr->rstore->name(), jcr->rstore_source,
938 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
939 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
940 bstrutime(dt, sizeof(dt), jcr->sched_time),
941 jcr->catalog->name(),
945 ua->error_msg(_("Unknown Job Type=%d\n"), jcr->JobType);
952 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc)
956 static const char *kw[] = { /* command line arguments */
957 "job", /* Used in a switch() */
965 "regexwhere", /* 8 where string as a bregexp */
967 "bootstrap", /* 10 */
971 "yes", /* 14 -- if you change this change YES_POS too */
972 "verifyjob", /* 15 */
973 "files", /* 16 number of files to restore */
974 "catalog", /* 17 override catalog */
975 "since", /* 18 since */
976 "cloned", /* 19 cloned */
977 "verifylist", /* 20 verify output list */
978 "migrationjob", /* 21 migration job name */
980 "backupclient", /* 23 */
981 "restoreclient", /* 24 */
986 rc.catalog_name = NULL;
989 rc.store_name = NULL;
990 rc.client_name = NULL;
991 rc.restore_client_name = NULL;
992 rc.fileset_name = NULL;
993 rc.verify_job_name = NULL;
994 rc.previous_job_name = NULL;
997 for (i=1; i<ua->argc; i++) {
998 Dmsg2(800, "Doing arg %d = %s\n", i, ua->argk[i]);
1000 /* Keep looking until we find a good keyword */
1001 for (j=0; !kw_ok && kw[j]; j++) {
1002 if (strcasecmp(ua->argk[i], kw[j]) == 0) {
1003 /* Note, yes and run have no value, so do not fail */
1004 if (!ua->argv[i] && j != YES_POS /*yes*/) {
1005 ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]);
1008 Dmsg1(800, "Got keyword=%s\n", NPRT(kw[j]));
1012 ua->send_msg(_("Job name specified twice.\n"));
1015 rc.job_name = ua->argv[i];
1019 if (rc.jid && !rc.mod) {
1020 ua->send_msg(_("JobId specified twice.\n"));
1023 rc.jid = ua->argv[i];
1026 case 2: /* client */
1028 if (rc.client_name) {
1029 ua->send_msg(_("Client specified twice.\n"));
1032 rc.client_name = ua->argv[i];
1035 case 4: /* fileset */
1036 if (rc.fileset_name) {
1037 ua->send_msg(_("FileSet specified twice.\n"));
1040 rc.fileset_name = ua->argv[i];
1044 if (rc.level_name) {
1045 ua->send_msg(_("Level specified twice.\n"));
1048 rc.level_name = ua->argv[i];
1051 case 6: /* storage */
1053 if (rc.store_name) {
1054 ua->send_msg(_("Storage specified twice.\n"));
1057 rc.store_name = ua->argv[i];
1060 case 8: /* regexwhere */
1061 if ((rc.regexwhere || rc.where) && !rc.mod) {
1062 ua->send_msg(_("RegexWhere or Where specified twice.\n"));
1065 rc.regexwhere = ua->argv[i];
1066 if (!acl_access_ok(ua, Where_ACL, rc.regexwhere)) {
1067 ua->send_msg(_("No authorization for \"regexwhere\" specification.\n"));
1073 if ((rc.where || rc.regexwhere) && !rc.mod) {
1074 ua->send_msg(_("Where or RegexWhere specified twice.\n"));
1077 rc.where = ua->argv[i];
1078 if (!acl_access_ok(ua, Where_ACL, rc.where)) {
1079 ua->send_msg(_("No authoriztion for \"where\" specification.\n"));
1084 case 10: /* bootstrap */
1085 if (rc.bootstrap && !rc.mod) {
1086 ua->send_msg(_("Bootstrap specified twice.\n"));
1089 rc.bootstrap = ua->argv[i];
1092 case 11: /* replace */
1093 if (rc.replace && !rc.mod) {
1094 ua->send_msg(_("Replace specified twice.\n"));
1097 rc.replace = ua->argv[i];
1101 if (rc.when && !rc.mod) {
1102 ua->send_msg(_("When specified twice.\n"));
1105 rc.when = ua->argv[i];
1108 case 13: /* Priority */
1109 if (rc.Priority && !rc.mod) {
1110 ua->send_msg(_("Priority specified twice.\n"));
1113 rc.Priority = atoi(ua->argv[i]);
1114 if (rc.Priority <= 0) {
1115 ua->send_msg(_("Priority must be positive nonzero setting it to 10.\n"));
1123 case 15: /* Verify Job */
1124 if (rc.verify_job_name) {
1125 ua->send_msg(_("Verify Job specified twice.\n"));
1128 rc.verify_job_name = ua->argv[i];
1131 case 16: /* files */
1132 rc.files = atoi(ua->argv[i]);
1136 case 17: /* catalog */
1137 rc.catalog_name = ua->argv[i];
1141 case 18: /* since */
1142 rc.since = ua->argv[i];
1146 case 19: /* cloned */
1151 case 20: /* write verify list output */
1152 rc.verify_list = ua->argv[i];
1155 case 21: /* Migration Job */
1156 if (rc.previous_job_name) {
1157 ua->send_msg(_("Migration Job specified twice.\n"));
1160 rc.previous_job_name = ua->argv[i];
1165 ua->send_msg(_("Pool specified twice.\n"));
1168 rc.pool_name = ua->argv[i];
1171 case 23: /* backupclient */
1172 if (rc.client_name) {
1173 ua->send_msg(_("Client specified twice.\n"));
1176 rc.client_name = ua->argv[i];
1179 case 24: /* restoreclient */
1180 if (rc.restore_client_name && !rc.mod) {
1181 ua->send_msg(_("Restore Client specified twice.\n"));
1184 rc.restore_client_name = ua->argv[i];
1190 } /* end strcase compare */
1191 } /* end keyword loop */
1193 * End of keyword for loop -- if not found, we got a bogus keyword
1196 Dmsg1(800, "%s not found\n", ua->argk[i]);
1198 * Special case for Job Name, it can be the first
1199 * keyword that has no value.
1201 if (!rc.job_name && !ua->argv[i]) {
1202 rc.job_name = ua->argk[i]; /* use keyword as job name */
1203 Dmsg1(800, "Set jobname=%s\n", rc.job_name);
1205 ua->send_msg(_("Invalid keyword: %s\n"), ua->argk[i]);
1209 } /* end argc loop */
1211 Dmsg0(800, "Done scan.\n");
1213 if (rc.catalog_name) {
1214 rc.catalog = GetCatalogResWithName(rc.catalog_name);
1215 if (rc.catalog == NULL) {
1216 ua->error_msg(_("Catalog \"%s\" not found\n"), rc.catalog_name);
1219 if (!acl_access_ok(ua, Catalog_ACL, rc.catalog->name())) {
1220 ua->error_msg(_("No authorization. Catalog \"%s\".\n"), rc.catalog->name());
1224 Dmsg1(800, "Using catalog=%s\n", NPRT(rc.catalog_name));
1228 rc.job = GetJobResWithName(rc.job_name);
1230 if (*rc.job_name != 0) {
1231 ua->send_msg(_("Job \"%s\" not found\n"), rc.job_name);
1233 rc.job = select_job_resource(ua);
1235 Dmsg1(800, "Found job=%s\n", rc.job_name);
1237 } else if (!rc.job) {
1238 ua->send_msg(_("A job name must be specified.\n"));
1239 rc.job = select_job_resource(ua);
1243 } else if (!acl_access_ok(ua, Job_ACL, rc.job->name())) {
1244 ua->error_msg( _("No authorization. Job \"%s\".\n"), rc.job->name());
1249 rc.pool = GetPoolResWithName(rc.pool_name);
1251 if (*rc.pool_name != 0) {
1252 ua->warning_msg(_("Pool \"%s\" not found.\n"), rc.pool_name);
1254 rc.pool = select_pool_resource(ua);
1256 } else if (!rc.pool) {
1257 rc.pool = rc.job->pool; /* use default */
1261 } else if (!acl_access_ok(ua, Pool_ACL, rc.pool->name())) {
1262 ua->error_msg(_("No authorization. Pool \"%s\".\n"), rc.pool->name());
1265 Dmsg1(100, "Using pool %s\n", rc.pool->name());
1267 if (rc.store_name) {
1268 rc.store->store = GetStoreResWithName(rc.store_name);
1269 pm_strcpy(rc.store->store_source, _("command line"));
1270 if (!rc.store->store) {
1271 if (*rc.store_name != 0) {
1272 ua->warning_msg(_("Storage \"%s\" not found.\n"), rc.store_name);
1274 rc.store->store = select_storage_resource(ua);
1275 pm_strcpy(rc.store->store_source, _("user selection"));
1277 } else if (!rc.store->store) {
1278 get_job_storage(rc.store, rc.job, NULL); /* use default */
1280 if (!rc.store->store) {
1281 ua->error_msg(_("No storage specified.\n"));
1283 } else if (!acl_access_ok(ua, Storage_ACL, rc.store->store->name())) {
1284 ua->error_msg(_("No authorization. Storage \"%s\".\n"),
1285 rc.store->store->name());
1288 Dmsg1(800, "Using storage=%s\n", rc.store->store->name());
1290 if (rc.client_name) {
1291 rc.client = GetClientResWithName(rc.client_name);
1293 if (*rc.client_name != 0) {
1294 ua->warning_msg(_("Client \"%s\" not found.\n"), rc.client_name);
1296 rc.client = select_client_resource(ua);
1298 } else if (!rc.client) {
1299 rc.client = rc.job->client; /* use default */
1303 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1304 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1308 Dmsg1(800, "Using client=%s\n", rc.client->name());
1310 if (rc.restore_client_name) {
1311 rc.client = GetClientResWithName(rc.restore_client_name);
1313 if (*rc.restore_client_name != 0) {
1314 ua->warning_msg(_("Restore Client \"%s\" not found.\n"), rc.restore_client_name);
1316 rc.client = select_client_resource(ua);
1318 } else if (!rc.client) {
1319 rc.client = rc.job->client; /* use default */
1323 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1324 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1328 Dmsg1(800, "Using restore client=%s\n", rc.client->name());
1331 if (rc.fileset_name) {
1332 rc.fileset = GetFileSetResWithName(rc.fileset_name);
1334 ua->send_msg(_("FileSet \"%s\" not found.\n"), rc.fileset_name);
1335 rc.fileset = select_fileset_resource(ua);
1337 } else if (!rc.fileset) {
1338 rc.fileset = rc.job->fileset; /* use default */
1342 } else if (!acl_access_ok(ua, FileSet_ACL, rc.fileset->name())) {
1343 ua->send_msg(_("No authorization. FileSet \"%s\".\n"),
1344 rc.fileset->name());
1348 if (rc.verify_job_name) {
1349 rc.verify_job = GetJobResWithName(rc.verify_job_name);
1350 if (!rc.verify_job) {
1351 ua->send_msg(_("Verify Job \"%s\" not found.\n"), rc.verify_job_name);
1352 rc.verify_job = select_job_resource(ua);
1354 } else if (!rc.verify_job) {
1355 rc.verify_job = rc.job->verify_job;
1358 if (rc.previous_job_name) {
1359 rc.previous_job = GetJobResWithName(rc.previous_job_name);
1360 if (!rc.previous_job) {
1361 ua->send_msg(_("Migration Job \"%s\" not found.\n"), rc.previous_job_name);
1362 rc.previous_job = select_job_resource(ua);
1365 rc.previous_job = rc.job->verify_job;