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 Kern Sibbald.
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 if (jcr->JobType == JT_BACKUP || jcr->JobType == JT_RESTORE) {
233 add_prompt(ua, _("Plugin Options")); /* 12 */
235 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
238 select_job_level(ua, jcr);
242 rc.store->store = select_storage_resource(ua);
243 if (rc.store->store) {
244 pm_strcpy(rc.store->store_source, _("user selection"));
245 set_rwstorage(jcr, rc.store);
251 rc.job = select_job_resource(ua);
254 set_jcr_defaults(jcr, rc.job);
260 rc.fileset = select_fileset_resource(ua);
262 jcr->fileset = rc.fileset;
268 rc.client = select_client_resource(ua);
270 jcr->client = rc.client;
276 if (!get_cmd(ua, _("Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now): "))) {
279 if (ua->cmd[0] == 0) {
280 jcr->sched_time = time(NULL);
282 jcr->sched_time = str_to_utime(ua->cmd);
283 if (jcr->sched_time == 0) {
284 ua->send_msg(_("Invalid time, using current time.\n"));
285 jcr->sched_time = time(NULL);
291 if (!get_pint(ua, _("Enter new Priority: "))) {
294 if (ua->pint32_val == 0) {
295 ua->send_msg(_("Priority must be a positive integer.\n"));
297 jcr->JobPriority = ua->pint32_val;
301 /* Pool or Bootstrap depending on JobType */
302 if (jcr->JobType == JT_BACKUP ||
303 jcr->JobType == JT_COPY ||
304 jcr->JobType == JT_MIGRATE ||
305 jcr->JobType == JT_VERIFY) { /* Pool */
306 rc.pool = select_pool_resource(ua);
309 Dmsg1(100, "Set new pool=%s\n", jcr->pool->name());
316 if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
319 if (jcr->RestoreBootstrap) {
320 free(jcr->RestoreBootstrap);
321 jcr->RestoreBootstrap = NULL;
323 if (ua->cmd[0] != 0) {
324 jcr->RestoreBootstrap = bstrdup(ua->cmd);
325 fd = fopen(jcr->RestoreBootstrap, "rb");
328 ua->send_msg(_("Warning cannot open %s: ERR=%s\n"),
329 jcr->RestoreBootstrap, be.bstrerror());
330 free(jcr->RestoreBootstrap);
331 jcr->RestoreBootstrap = NULL;
339 if (jcr->JobType == JT_VERIFY) {
340 rc.verify_job = select_job_resource(ua);
342 jcr->verify_job = rc.verify_job;
347 if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) {
350 if (jcr->RegexWhere) { /* cannot use regexwhere and where */
351 free(jcr->RegexWhere);
352 jcr->RegexWhere = NULL;
358 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
361 jcr->where = bstrdup(ua->cmd);
364 /* File relocation */
365 select_where_regexp(ua, jcr);
369 start_prompt(ua, _("Replace:\n"));
370 for (i=0; ReplaceOptions[i].name; i++) {
371 add_prompt(ua, ReplaceOptions[i].name);
373 opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
375 rc.replace = ReplaceOptions[opt].name;
376 jcr->replace = ReplaceOptions[opt].token;
381 rc.jid = NULL; /* force reprompt */
382 jcr->RestoreJobId = 0;
383 if (jcr->RestoreBootstrap) {
384 ua->send_msg(_("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
389 if (!get_cmd(ua, _("Please Plugin Options string: "))) {
392 if (jcr->plugin_options) {
393 free(jcr->plugin_options);
394 jcr->plugin_options = NULL;
396 jcr->plugin_options = bstrdup(ua->cmd);
398 case -1: /* error or cancel */
415 * Reset the restore context.
416 * This subroutine can be called multiple times, so it
417 * must keep any prior settings.
419 static bool reset_restore_context(UAContext *ua, JCR *jcr, run_ctx &rc)
423 jcr->verify_job = rc.verify_job;
424 jcr->previous_job = rc.previous_job;
426 if (jcr->pool != jcr->job->pool) {
427 pm_strcpy(jcr->pool_source, _("User input"));
429 set_rwstorage(jcr, rc.store);
430 jcr->client = rc.client;
431 pm_strcpy(jcr->client_name, rc.client->name());
432 jcr->fileset = rc.fileset;
433 jcr->ExpectedFiles = rc.files;
435 jcr->catalog = rc.catalog;
436 pm_strcpy(jcr->catalog_source, _("User input"));
442 jcr->where = bstrdup(rc.where);
447 if (jcr->RegexWhere) {
448 free(jcr->RegexWhere);
450 jcr->RegexWhere = bstrdup(rc.regexwhere);
451 rc.regexwhere = NULL;
455 jcr->sched_time = str_to_utime(rc.when);
456 if (jcr->sched_time == 0) {
457 ua->send_msg(_("Invalid time, using current time.\n"));
458 jcr->sched_time = time(NULL);
464 if (jcr->RestoreBootstrap) {
465 free(jcr->RestoreBootstrap);
467 jcr->RestoreBootstrap = bstrdup(rc.bootstrap);
471 if (rc.plugin_options) {
472 if (jcr->plugin_options) {
473 free(jcr->plugin_options);
475 jcr->plugin_options = bstrdup(rc.plugin_options);
476 rc.plugin_options = NULL;
482 for (i=0; ReplaceOptions[i].name; i++) {
483 if (strcasecmp(rc.replace, ReplaceOptions[i].name) == 0) {
484 jcr->replace = ReplaceOptions[i].token;
488 ua->send_msg(_("Invalid replace option: %s\n"), rc.replace);
491 } else if (rc.job->replace) {
492 jcr->replace = rc.job->replace;
494 jcr->replace = REPLACE_ALWAYS;
499 jcr->JobPriority = rc.Priority;
505 jcr->stime = get_pool_memory(PM_MESSAGE);
507 pm_strcpy(jcr->stime, rc.since);
512 jcr->cloned = rc.cloned;
517 /* If pool changed, update migration write storage */
518 if (jcr->JobType == JT_MIGRATE || jcr->JobType == JT_COPY) {
519 if (!set_migration_wstorage(jcr, rc.pool)) {
523 rc.replace = ReplaceOptions[0].name;
524 for (i=0; ReplaceOptions[i].name; i++) {
525 if (ReplaceOptions[i].token == jcr->replace) {
526 rc.replace = ReplaceOptions[i].name;
530 if (!get_level_from_name(jcr, rc.level_name)) {
531 ua->send_msg(_("Level \"%s\" not valid.\n"), rc.level_name);
534 rc.level_name = NULL;
537 /* Note, this is also MigrateJobId */
538 jcr->RestoreJobId = str_to_int64(rc.jid);
544 static void select_where_regexp(UAContext *ua, JCR *jcr)
547 char *strip_prefix, *add_prefix, *add_suffix, *rwhere;
548 strip_prefix = add_suffix = rwhere = add_prefix = NULL;
551 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s\n"),
552 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix));
554 start_prompt(ua, _("This will replace your current Where value\n"));
555 add_prompt(ua, _("Strip prefix")); /* 0 */
556 add_prompt(ua, _("Add prefix")); /* 1 */
557 add_prompt(ua, _("Add file suffix")); /* 2 */
558 add_prompt(ua, _("Enter a regexp")); /* 3 */
559 add_prompt(ua, _("Test filename manipulation")); /* 4 */
560 add_prompt(ua, _("Use this ?")); /* 5 */
562 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
565 if (get_cmd(ua, _("Please enter path prefix to strip: "))) {
566 if (strip_prefix) bfree(strip_prefix);
567 strip_prefix = bstrdup(ua->cmd);
573 if (get_cmd(ua, _("Please enter path prefix to add (/ for none): "))) {
574 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
578 if (add_prefix) bfree(add_prefix);
579 add_prefix = bstrdup(ua->cmd);
584 if (get_cmd(ua, _("Please enter file suffix to add: "))) {
585 if (add_suffix) bfree(add_suffix);
586 add_suffix = bstrdup(ua->cmd);
591 if (get_cmd(ua, _("Please enter a valid regexp (!from!to!): "))) {
592 if (rwhere) bfree(rwhere);
593 rwhere = bstrdup(ua->cmd);
602 if (rwhere && rwhere[0] != '\0') {
603 regs = get_bregexps(rwhere);
604 ua->send_msg(_("regexwhere=%s\n"), NPRT(rwhere));
606 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
607 regexp = (char *) bmalloc (len * sizeof(char));
608 bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix);
609 regs = get_bregexps(regexp);
610 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s result=%s\n"),
611 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix), NPRT(regexp));
617 ua->send_msg(_("Cannot use your regexp\n"));
621 while (get_cmd(ua, _("Please enter filename to test: "))) {
622 apply_bregexps(ua->cmd, regs, &result);
623 ua->send_msg(_("%s -> %s\n"), ua->cmd, result);
632 case -1: /* error or cancel */
638 /* replace the existing where */
644 /* replace the existing regexwhere */
645 if (jcr->RegexWhere) {
646 bfree(jcr->RegexWhere);
647 jcr->RegexWhere = NULL;
651 jcr->RegexWhere = bstrdup(rwhere);
652 } else if (strip_prefix || add_prefix || add_suffix) {
653 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
654 jcr->RegexWhere = (char *) bmalloc(len*sizeof(char));
655 bregexp_build_where(jcr->RegexWhere, len, strip_prefix, add_prefix, add_suffix);
658 regs = get_bregexps(jcr->RegexWhere);
663 if (jcr->RegexWhere) {
664 bfree(jcr->RegexWhere);
665 jcr->RegexWhere = NULL;
667 ua->send_msg(_("Cannot use your regexp.\n"));
671 if (strip_prefix) bfree(strip_prefix);
672 if (add_prefix) bfree(add_prefix);
673 if (add_suffix) bfree(add_suffix);
674 if (rwhere) bfree(rwhere);
677 static void select_job_level(UAContext *ua, JCR *jcr)
679 if (jcr->JobType == JT_BACKUP) {
680 start_prompt(ua, _("Levels:\n"));
681 // add_prompt(ua, _("Base"));
682 add_prompt(ua, _("Full"));
683 add_prompt(ua, _("Incremental"));
684 add_prompt(ua, _("Differential"));
685 add_prompt(ua, _("Since"));
686 add_prompt(ua, _("VirtualFull"));
687 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
689 // jcr->JobLevel = L_BASE;
692 jcr->JobLevel = L_FULL;
695 jcr->JobLevel = L_INCREMENTAL;
698 jcr->JobLevel = L_DIFFERENTIAL;
701 jcr->JobLevel = L_SINCE;
704 jcr->JobLevel = L_VIRTUAL_FULL;
709 } else if (jcr->JobType == JT_VERIFY) {
710 start_prompt(ua, _("Levels:\n"));
711 add_prompt(ua, _("Initialize Catalog"));
712 add_prompt(ua, _("Verify Catalog"));
713 add_prompt(ua, _("Verify Volume to Catalog"));
714 add_prompt(ua, _("Verify Disk to Catalog"));
715 add_prompt(ua, _("Verify Volume Data (not yet implemented)"));
716 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
718 jcr->JobLevel = L_VERIFY_INIT;
721 jcr->JobLevel = L_VERIFY_CATALOG;
724 jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG;
727 jcr->JobLevel = L_VERIFY_DISK_TO_CATALOG;
730 jcr->JobLevel = L_VERIFY_DATA;
736 ua->warning_msg(_("Level not appropriate for this Job. Cannot be changed.\n"));
741 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char *verify_list,
742 char *jid, const char *replace, char *client_name)
744 Dmsg1(800, "JobType=%c\n", jcr->JobType);
745 switch (jcr->JobType) {
747 char dt[MAX_TIME_LENGTH];
749 if (ua->api) ua->signal(BNET_RUN_CMD);
750 ua->send_msg(_("Run %s job\n"
759 jcr->fileset->name(),
760 NPRT(jcr->client->name()),
761 jcr->wstore?jcr->wstore->name():"*None*",
762 bstrutime(dt, sizeof(dt), jcr->sched_time),
764 jcr->JobLevel = L_FULL;
768 if (jcr->JobType == JT_BACKUP) {
769 if (ua->api) ua->signal(BNET_RUN_CMD);
770 ua->send_msg(_("Run %s job\n"
775 "Pool: %s (From %s)\n"
776 "Storage: %s (From %s)\n"
782 level_to_str(jcr->JobLevel),
784 jcr->fileset->name(),
785 NPRT(jcr->pool->name()), jcr->pool_source,
786 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
787 bstrutime(dt, sizeof(dt), jcr->sched_time),
789 jcr->plugin_options?"Plugin Options: ":"",
790 jcr->plugin_options?jcr->plugin_options:"",
791 jcr->plugin_options?"\n":"");
792 } else { /* JT_VERIFY */
794 if (jcr->verify_job) {
795 Name = jcr->verify_job->name();
800 verify_list = job->WriteVerifyList;
805 if (ua->api) ua->signal(BNET_RUN_CMD);
806 ua->send_msg(_("Run %s job\n"
811 "Pool: %s (From %s)\n"
812 "Storage: %s (From %s)\n"
819 level_to_str(jcr->JobLevel),
821 jcr->fileset->name(),
822 NPRT(jcr->pool->name()), jcr->pool_source,
823 jcr->rstore->name(), jcr->rstore_source,
826 bstrutime(dt, sizeof(dt), jcr->sched_time),
831 if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
833 jcr->RestoreJobId = str_to_int64(jid);
835 if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
838 jcr->RestoreJobId = ua->int64_val;
841 jcr->JobLevel = L_FULL; /* default level */
842 Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId);
843 if (jcr->RestoreJobId == 0) {
844 if (ua->api) ua->signal(BNET_RUN_CMD);
845 /* RegexWhere is take before RestoreWhere */
846 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
847 ua->send_msg(_("Run Restore job\n"
853 "Backup Client: %s\n"
854 "Restore Client: %s\n"
859 "Plugin Options: %s\n"),
861 NPRT(jcr->RestoreBootstrap),
862 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
864 jcr->fileset->name(),
868 bstrutime(dt, sizeof(dt), jcr->sched_time),
869 jcr->catalog->name(),
871 NPRT(jcr->plugin_options));
874 ua->send_msg(_("Run Restore job\n"
880 "Backup Client: %s\n"
881 "Restore Client: %s\n"
886 "Plugin Options: %s\n"),
888 NPRT(jcr->RestoreBootstrap),
889 jcr->where?jcr->where:NPRT(job->RestoreWhere),
891 jcr->fileset->name(),
895 bstrutime(dt, sizeof(dt), jcr->sched_time),
896 jcr->catalog->name(),
898 NPRT(jcr->plugin_options));
902 if (ua->api) ua->signal(BNET_RUN_CMD);
903 ua->send_msg(_("Run Restore job\n"
907 NPRT(jcr->RestoreBootstrap));
909 /* RegexWhere is take before RestoreWhere */
910 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
911 ua->send_msg(_("RegexWhere: %s\n"),
912 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere);
914 ua->send_msg(_("Where: %s\n"),
915 jcr->where?jcr->where:NPRT(job->RestoreWhere));
918 ua->send_msg(_("Replace: %s\n"
925 "Plugin Options: %s\n"),
929 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
930 bstrutime(dt, sizeof(dt), jcr->sched_time),
931 jcr->catalog->name(),
933 NPRT(jcr->plugin_options));
939 if (jcr->JobType == JT_COPY) {
940 prt_type = _("Run Copy job\n");
942 prt_type = _("Run Migration job\n");
944 jcr->JobLevel = L_FULL; /* default level */
945 if (ua->api) ua->signal(BNET_RUN_CMD);
951 "Pool: %s (From %s)\n"
952 "Read Storage: %s (From %s)\n"
953 "Write Storage: %s (From %s)\n"
960 NPRT(jcr->RestoreBootstrap),
962 jcr->fileset->name(),
963 NPRT(jcr->pool->name()), jcr->pool_source,
964 jcr->rstore->name(), jcr->rstore_source,
965 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
966 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
967 bstrutime(dt, sizeof(dt), jcr->sched_time),
968 jcr->catalog->name(),
972 ua->error_msg(_("Unknown Job Type=%d\n"), jcr->JobType);
979 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc)
983 static const char *kw[] = { /* command line arguments */
984 "job", /* Used in a switch() */
992 "regexwhere", /* 8 where string as a bregexp */
994 "bootstrap", /* 10 */
998 "yes", /* 14 -- if you change this change YES_POS too */
999 "verifyjob", /* 15 */
1000 "files", /* 16 number of files to restore */
1001 "catalog", /* 17 override catalog */
1002 "since", /* 18 since */
1003 "cloned", /* 19 cloned */
1004 "verifylist", /* 20 verify output list */
1005 "migrationjob", /* 21 migration job name */
1007 "backupclient", /* 23 */
1008 "restoreclient", /* 24 */
1009 "pluginoptions", /* 25 */
1014 rc.catalog_name = NULL;
1016 rc.pool_name = NULL;
1017 rc.store_name = NULL;
1018 rc.client_name = NULL;
1019 rc.restore_client_name = NULL;
1020 rc.fileset_name = NULL;
1021 rc.verify_job_name = NULL;
1022 rc.previous_job_name = NULL;
1025 for (i=1; i<ua->argc; i++) {
1026 Dmsg2(800, "Doing arg %d = %s\n", i, ua->argk[i]);
1028 /* Keep looking until we find a good keyword */
1029 for (j=0; !kw_ok && kw[j]; j++) {
1030 if (strcasecmp(ua->argk[i], kw[j]) == 0) {
1031 /* Note, yes and run have no value, so do not fail */
1032 if (!ua->argv[i] && j != YES_POS /*yes*/) {
1033 ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]);
1036 Dmsg1(800, "Got keyword=%s\n", NPRT(kw[j]));
1040 ua->send_msg(_("Job name specified twice.\n"));
1043 rc.job_name = ua->argv[i];
1047 if (rc.jid && !rc.mod) {
1048 ua->send_msg(_("JobId specified twice.\n"));
1051 rc.jid = ua->argv[i];
1054 case 2: /* client */
1056 if (rc.client_name) {
1057 ua->send_msg(_("Client specified twice.\n"));
1060 rc.client_name = ua->argv[i];
1063 case 4: /* fileset */
1064 if (rc.fileset_name) {
1065 ua->send_msg(_("FileSet specified twice.\n"));
1068 rc.fileset_name = ua->argv[i];
1072 if (rc.level_name) {
1073 ua->send_msg(_("Level specified twice.\n"));
1076 rc.level_name = ua->argv[i];
1079 case 6: /* storage */
1081 if (rc.store_name) {
1082 ua->send_msg(_("Storage specified twice.\n"));
1085 rc.store_name = ua->argv[i];
1088 case 8: /* regexwhere */
1089 if ((rc.regexwhere || rc.where) && !rc.mod) {
1090 ua->send_msg(_("RegexWhere or Where specified twice.\n"));
1093 rc.regexwhere = ua->argv[i];
1094 if (!acl_access_ok(ua, Where_ACL, rc.regexwhere)) {
1095 ua->send_msg(_("No authorization for \"regexwhere\" specification.\n"));
1101 if ((rc.where || rc.regexwhere) && !rc.mod) {
1102 ua->send_msg(_("Where or RegexWhere specified twice.\n"));
1105 rc.where = ua->argv[i];
1106 if (!acl_access_ok(ua, Where_ACL, rc.where)) {
1107 ua->send_msg(_("No authoriztion for \"where\" specification.\n"));
1112 case 10: /* bootstrap */
1113 if (rc.bootstrap && !rc.mod) {
1114 ua->send_msg(_("Bootstrap specified twice.\n"));
1117 rc.bootstrap = ua->argv[i];
1120 case 11: /* replace */
1121 if (rc.replace && !rc.mod) {
1122 ua->send_msg(_("Replace specified twice.\n"));
1125 rc.replace = ua->argv[i];
1129 if (rc.when && !rc.mod) {
1130 ua->send_msg(_("When specified twice.\n"));
1133 rc.when = ua->argv[i];
1136 case 13: /* Priority */
1137 if (rc.Priority && !rc.mod) {
1138 ua->send_msg(_("Priority specified twice.\n"));
1141 rc.Priority = atoi(ua->argv[i]);
1142 if (rc.Priority <= 0) {
1143 ua->send_msg(_("Priority must be positive nonzero setting it to 10.\n"));
1151 case 15: /* Verify Job */
1152 if (rc.verify_job_name) {
1153 ua->send_msg(_("Verify Job specified twice.\n"));
1156 rc.verify_job_name = ua->argv[i];
1159 case 16: /* files */
1160 rc.files = atoi(ua->argv[i]);
1164 case 17: /* catalog */
1165 rc.catalog_name = ua->argv[i];
1169 case 18: /* since */
1170 rc.since = ua->argv[i];
1174 case 19: /* cloned */
1179 case 20: /* write verify list output */
1180 rc.verify_list = ua->argv[i];
1183 case 21: /* Migration Job */
1184 if (rc.previous_job_name) {
1185 ua->send_msg(_("Migration Job specified twice.\n"));
1188 rc.previous_job_name = ua->argv[i];
1193 ua->send_msg(_("Pool specified twice.\n"));
1196 rc.pool_name = ua->argv[i];
1199 case 23: /* backupclient */
1200 if (rc.client_name) {
1201 ua->send_msg(_("Client specified twice.\n"));
1204 rc.client_name = ua->argv[i];
1207 case 24: /* restoreclient */
1208 if (rc.restore_client_name && !rc.mod) {
1209 ua->send_msg(_("Restore Client specified twice.\n"));
1212 rc.restore_client_name = ua->argv[i];
1215 case 25: /* pluginoptions */
1216 if (rc.plugin_options) {
1217 ua->send_msg(_("Plugin Options specified twice.\n"));
1220 rc.plugin_options = ua->argv[i];
1221 if (!acl_access_ok(ua, PluginOptions_ACL, rc.plugin_options)) {
1222 ua->send_msg(_("No authoriztion for \"PluginOptions\" specification.\n"));
1230 } /* end strcase compare */
1231 } /* end keyword loop */
1233 * End of keyword for loop -- if not found, we got a bogus keyword
1236 Dmsg1(800, "%s not found\n", ua->argk[i]);
1238 * Special case for Job Name, it can be the first
1239 * keyword that has no value.
1241 if (!rc.job_name && !ua->argv[i]) {
1242 rc.job_name = ua->argk[i]; /* use keyword as job name */
1243 Dmsg1(800, "Set jobname=%s\n", rc.job_name);
1245 ua->send_msg(_("Invalid keyword: %s\n"), ua->argk[i]);
1249 } /* end argc loop */
1251 Dmsg0(800, "Done scan.\n");
1253 if (rc.catalog_name) {
1254 rc.catalog = GetCatalogResWithName(rc.catalog_name);
1255 if (rc.catalog == NULL) {
1256 ua->error_msg(_("Catalog \"%s\" not found\n"), rc.catalog_name);
1259 if (!acl_access_ok(ua, Catalog_ACL, rc.catalog->name())) {
1260 ua->error_msg(_("No authorization. Catalog \"%s\".\n"), rc.catalog->name());
1264 Dmsg1(800, "Using catalog=%s\n", NPRT(rc.catalog_name));
1268 rc.job = GetJobResWithName(rc.job_name);
1270 if (*rc.job_name != 0) {
1271 ua->send_msg(_("Job \"%s\" not found\n"), rc.job_name);
1273 rc.job = select_job_resource(ua);
1275 Dmsg1(800, "Found job=%s\n", rc.job_name);
1277 } else if (!rc.job) {
1278 ua->send_msg(_("A job name must be specified.\n"));
1279 rc.job = select_job_resource(ua);
1283 } else if (!acl_access_ok(ua, Job_ACL, rc.job->name())) {
1284 ua->error_msg( _("No authorization. Job \"%s\".\n"), rc.job->name());
1289 rc.pool = GetPoolResWithName(rc.pool_name);
1291 if (*rc.pool_name != 0) {
1292 ua->warning_msg(_("Pool \"%s\" not found.\n"), rc.pool_name);
1294 rc.pool = select_pool_resource(ua);
1296 } else if (!rc.pool) {
1297 rc.pool = rc.job->pool; /* use default */
1301 } else if (!acl_access_ok(ua, Pool_ACL, rc.pool->name())) {
1302 ua->error_msg(_("No authorization. Pool \"%s\".\n"), rc.pool->name());
1305 Dmsg1(100, "Using pool %s\n", rc.pool->name());
1307 if (rc.store_name) {
1308 rc.store->store = GetStoreResWithName(rc.store_name);
1309 pm_strcpy(rc.store->store_source, _("command line"));
1310 if (!rc.store->store) {
1311 if (*rc.store_name != 0) {
1312 ua->warning_msg(_("Storage \"%s\" not found.\n"), rc.store_name);
1314 rc.store->store = select_storage_resource(ua);
1315 pm_strcpy(rc.store->store_source, _("user selection"));
1317 } else if (!rc.store->store) {
1318 get_job_storage(rc.store, rc.job, NULL); /* use default */
1320 if (!rc.store->store) {
1321 ua->error_msg(_("No storage specified.\n"));
1323 } else if (!acl_access_ok(ua, Storage_ACL, rc.store->store->name())) {
1324 ua->error_msg(_("No authorization. Storage \"%s\".\n"),
1325 rc.store->store->name());
1328 Dmsg1(800, "Using storage=%s\n", rc.store->store->name());
1330 if (rc.client_name) {
1331 rc.client = GetClientResWithName(rc.client_name);
1333 if (*rc.client_name != 0) {
1334 ua->warning_msg(_("Client \"%s\" not found.\n"), rc.client_name);
1336 rc.client = select_client_resource(ua);
1338 } else if (!rc.client) {
1339 rc.client = rc.job->client; /* use default */
1343 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1344 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1348 Dmsg1(800, "Using client=%s\n", rc.client->name());
1350 if (rc.restore_client_name) {
1351 rc.client = GetClientResWithName(rc.restore_client_name);
1353 if (*rc.restore_client_name != 0) {
1354 ua->warning_msg(_("Restore Client \"%s\" not found.\n"), rc.restore_client_name);
1356 rc.client = select_client_resource(ua);
1358 } else if (!rc.client) {
1359 rc.client = rc.job->client; /* use default */
1363 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1364 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1368 Dmsg1(800, "Using restore client=%s\n", rc.client->name());
1371 if (rc.fileset_name) {
1372 rc.fileset = GetFileSetResWithName(rc.fileset_name);
1374 ua->send_msg(_("FileSet \"%s\" not found.\n"), rc.fileset_name);
1375 rc.fileset = select_fileset_resource(ua);
1377 } else if (!rc.fileset) {
1378 rc.fileset = rc.job->fileset; /* use default */
1382 } else if (!acl_access_ok(ua, FileSet_ACL, rc.fileset->name())) {
1383 ua->send_msg(_("No authorization. FileSet \"%s\".\n"),
1384 rc.fileset->name());
1388 if (rc.verify_job_name) {
1389 rc.verify_job = GetJobResWithName(rc.verify_job_name);
1390 if (!rc.verify_job) {
1391 ua->send_msg(_("Verify Job \"%s\" not found.\n"), rc.verify_job_name);
1392 rc.verify_job = select_job_resource(ua);
1394 } else if (!rc.verify_job) {
1395 rc.verify_job = rc.job->verify_job;
1398 if (rc.previous_job_name) {
1399 rc.previous_job = GetJobResWithName(rc.previous_job_name);
1400 if (!rc.previous_job) {
1401 ua->send_msg(_("Migration Job \"%s\" not found.\n"), rc.previous_job_name);
1402 rc.previous_job = select_job_resource(ua);
1405 rc.previous_job = rc.job->verify_job;