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 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 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
688 jcr->JobLevel = L_BASE;
691 jcr->JobLevel = L_FULL;
694 jcr->JobLevel = L_INCREMENTAL;
697 jcr->JobLevel = L_DIFFERENTIAL;
700 jcr->JobLevel = L_SINCE;
705 } else if (jcr->JobType == JT_VERIFY) {
706 start_prompt(ua, _("Levels:\n"));
707 add_prompt(ua, _("Initialize Catalog"));
708 add_prompt(ua, _("Verify Catalog"));
709 add_prompt(ua, _("Verify Volume to Catalog"));
710 add_prompt(ua, _("Verify Disk to Catalog"));
711 add_prompt(ua, _("Verify Volume Data (not yet implemented)"));
712 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
714 jcr->JobLevel = L_VERIFY_INIT;
717 jcr->JobLevel = L_VERIFY_CATALOG;
720 jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG;
723 jcr->JobLevel = L_VERIFY_DISK_TO_CATALOG;
726 jcr->JobLevel = L_VERIFY_DATA;
732 ua->warning_msg(_("Level not appropriate for this Job. Cannot be changed.\n"));
737 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char *verify_list,
738 char *jid, const char *replace, char *client_name)
740 Dmsg1(800, "JobType=%c\n", jcr->JobType);
741 switch (jcr->JobType) {
743 char dt[MAX_TIME_LENGTH];
745 if (ua->api) ua->signal(BNET_RUN_CMD);
746 ua->send_msg(_("Run %s job\n"
755 jcr->fileset->name(),
756 NPRT(jcr->client->name()),
757 jcr->wstore?jcr->wstore->name():"*None*",
758 bstrutime(dt, sizeof(dt), jcr->sched_time),
760 jcr->JobLevel = L_FULL;
764 if (jcr->JobType == JT_BACKUP) {
765 if (ua->api) ua->signal(BNET_RUN_CMD);
766 ua->send_msg(_("Run %s job\n"
771 "Pool: %s (From %s)\n"
772 "Storage: %s (From %s)\n"
778 level_to_str(jcr->JobLevel),
780 jcr->fileset->name(),
781 NPRT(jcr->pool->name()), jcr->pool_source,
782 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
783 bstrutime(dt, sizeof(dt), jcr->sched_time),
785 jcr->plugin_options?"Plugin Options: ":"",
786 jcr->plugin_options?jcr->plugin_options:"",
787 jcr->plugin_options?"\n":"");
788 } else { /* JT_VERIFY */
790 if (jcr->verify_job) {
791 Name = jcr->verify_job->name();
796 verify_list = job->WriteVerifyList;
801 if (ua->api) ua->signal(BNET_RUN_CMD);
802 ua->send_msg(_("Run %s job\n"
807 "Pool: %s (From %s)\n"
808 "Storage: %s (From %s)\n"
815 level_to_str(jcr->JobLevel),
817 jcr->fileset->name(),
818 NPRT(jcr->pool->name()), jcr->pool_source,
819 jcr->rstore->name(), jcr->rstore_source,
822 bstrutime(dt, sizeof(dt), jcr->sched_time),
827 if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
829 jcr->RestoreJobId = str_to_int64(jid);
831 if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
834 jcr->RestoreJobId = ua->int64_val;
837 jcr->JobLevel = L_FULL; /* default level */
838 Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId);
839 if (jcr->RestoreJobId == 0) {
840 if (ua->api) ua->signal(BNET_RUN_CMD);
841 /* RegexWhere is take before RestoreWhere */
842 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
843 ua->send_msg(_("Run Restore job\n"
849 "Backup Client: %s\n"
850 "Restore Client: %s\n"
855 "Plugin Options: %s\n"),
857 NPRT(jcr->RestoreBootstrap),
858 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
860 jcr->fileset->name(),
864 bstrutime(dt, sizeof(dt), jcr->sched_time),
865 jcr->catalog->name(),
867 NPRT(jcr->plugin_options));
870 ua->send_msg(_("Run Restore job\n"
876 "Backup Client: %s\n"
877 "Restore Client: %s\n"
882 "Plugin Options: %s\n"),
884 NPRT(jcr->RestoreBootstrap),
885 jcr->where?jcr->where:NPRT(job->RestoreWhere),
887 jcr->fileset->name(),
891 bstrutime(dt, sizeof(dt), jcr->sched_time),
892 jcr->catalog->name(),
894 NPRT(jcr->plugin_options));
898 if (ua->api) ua->signal(BNET_RUN_CMD);
899 ua->send_msg(_("Run Restore job\n"
903 NPRT(jcr->RestoreBootstrap));
905 /* RegexWhere is take before RestoreWhere */
906 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
907 ua->send_msg(_("RegexWhere: %s\n"),
908 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere);
910 ua->send_msg(_("Where: %s\n"),
911 jcr->where?jcr->where:NPRT(job->RestoreWhere));
914 ua->send_msg(_("Replace: %s\n"
921 "Plugin Options: %s\n"),
925 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
926 bstrutime(dt, sizeof(dt), jcr->sched_time),
927 jcr->catalog->name(),
929 NPRT(jcr->plugin_options));
935 if (jcr->JobType == JT_COPY) {
936 prt_type = _("Run Copy job\n");
938 prt_type = _("Run Migration job\n");
940 jcr->JobLevel = L_FULL; /* default level */
941 if (ua->api) ua->signal(BNET_RUN_CMD);
947 "Pool: %s (From %s)\n"
948 "Read Storage: %s (From %s)\n"
949 "Write Storage: %s (From %s)\n"
956 NPRT(jcr->RestoreBootstrap),
958 jcr->fileset->name(),
959 NPRT(jcr->pool->name()), jcr->pool_source,
960 jcr->rstore->name(), jcr->rstore_source,
961 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
962 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
963 bstrutime(dt, sizeof(dt), jcr->sched_time),
964 jcr->catalog->name(),
968 ua->error_msg(_("Unknown Job Type=%d\n"), jcr->JobType);
975 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc)
979 static const char *kw[] = { /* command line arguments */
980 "job", /* Used in a switch() */
988 "regexwhere", /* 8 where string as a bregexp */
990 "bootstrap", /* 10 */
994 "yes", /* 14 -- if you change this change YES_POS too */
995 "verifyjob", /* 15 */
996 "files", /* 16 number of files to restore */
997 "catalog", /* 17 override catalog */
998 "since", /* 18 since */
999 "cloned", /* 19 cloned */
1000 "verifylist", /* 20 verify output list */
1001 "migrationjob", /* 21 migration job name */
1003 "backupclient", /* 23 */
1004 "restoreclient", /* 24 */
1005 "pluginoptions", /* 25 */
1010 rc.catalog_name = NULL;
1012 rc.pool_name = NULL;
1013 rc.store_name = NULL;
1014 rc.client_name = NULL;
1015 rc.restore_client_name = NULL;
1016 rc.fileset_name = NULL;
1017 rc.verify_job_name = NULL;
1018 rc.previous_job_name = NULL;
1021 for (i=1; i<ua->argc; i++) {
1022 Dmsg2(800, "Doing arg %d = %s\n", i, ua->argk[i]);
1024 /* Keep looking until we find a good keyword */
1025 for (j=0; !kw_ok && kw[j]; j++) {
1026 if (strcasecmp(ua->argk[i], kw[j]) == 0) {
1027 /* Note, yes and run have no value, so do not fail */
1028 if (!ua->argv[i] && j != YES_POS /*yes*/) {
1029 ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]);
1032 Dmsg1(800, "Got keyword=%s\n", NPRT(kw[j]));
1036 ua->send_msg(_("Job name specified twice.\n"));
1039 rc.job_name = ua->argv[i];
1043 if (rc.jid && !rc.mod) {
1044 ua->send_msg(_("JobId specified twice.\n"));
1047 rc.jid = ua->argv[i];
1050 case 2: /* client */
1052 if (rc.client_name) {
1053 ua->send_msg(_("Client specified twice.\n"));
1056 rc.client_name = ua->argv[i];
1059 case 4: /* fileset */
1060 if (rc.fileset_name) {
1061 ua->send_msg(_("FileSet specified twice.\n"));
1064 rc.fileset_name = ua->argv[i];
1068 if (rc.level_name) {
1069 ua->send_msg(_("Level specified twice.\n"));
1072 rc.level_name = ua->argv[i];
1075 case 6: /* storage */
1077 if (rc.store_name) {
1078 ua->send_msg(_("Storage specified twice.\n"));
1081 rc.store_name = ua->argv[i];
1084 case 8: /* regexwhere */
1085 if ((rc.regexwhere || rc.where) && !rc.mod) {
1086 ua->send_msg(_("RegexWhere or Where specified twice.\n"));
1089 rc.regexwhere = ua->argv[i];
1090 if (!acl_access_ok(ua, Where_ACL, rc.regexwhere)) {
1091 ua->send_msg(_("No authorization for \"regexwhere\" specification.\n"));
1097 if ((rc.where || rc.regexwhere) && !rc.mod) {
1098 ua->send_msg(_("Where or RegexWhere specified twice.\n"));
1101 rc.where = ua->argv[i];
1102 if (!acl_access_ok(ua, Where_ACL, rc.where)) {
1103 ua->send_msg(_("No authoriztion for \"where\" specification.\n"));
1108 case 10: /* bootstrap */
1109 if (rc.bootstrap && !rc.mod) {
1110 ua->send_msg(_("Bootstrap specified twice.\n"));
1113 rc.bootstrap = ua->argv[i];
1116 case 11: /* replace */
1117 if (rc.replace && !rc.mod) {
1118 ua->send_msg(_("Replace specified twice.\n"));
1121 rc.replace = ua->argv[i];
1125 if (rc.when && !rc.mod) {
1126 ua->send_msg(_("When specified twice.\n"));
1129 rc.when = ua->argv[i];
1132 case 13: /* Priority */
1133 if (rc.Priority && !rc.mod) {
1134 ua->send_msg(_("Priority specified twice.\n"));
1137 rc.Priority = atoi(ua->argv[i]);
1138 if (rc.Priority <= 0) {
1139 ua->send_msg(_("Priority must be positive nonzero setting it to 10.\n"));
1147 case 15: /* Verify Job */
1148 if (rc.verify_job_name) {
1149 ua->send_msg(_("Verify Job specified twice.\n"));
1152 rc.verify_job_name = ua->argv[i];
1155 case 16: /* files */
1156 rc.files = atoi(ua->argv[i]);
1160 case 17: /* catalog */
1161 rc.catalog_name = ua->argv[i];
1165 case 18: /* since */
1166 rc.since = ua->argv[i];
1170 case 19: /* cloned */
1175 case 20: /* write verify list output */
1176 rc.verify_list = ua->argv[i];
1179 case 21: /* Migration Job */
1180 if (rc.previous_job_name) {
1181 ua->send_msg(_("Migration Job specified twice.\n"));
1184 rc.previous_job_name = ua->argv[i];
1189 ua->send_msg(_("Pool specified twice.\n"));
1192 rc.pool_name = ua->argv[i];
1195 case 23: /* backupclient */
1196 if (rc.client_name) {
1197 ua->send_msg(_("Client specified twice.\n"));
1200 rc.client_name = ua->argv[i];
1203 case 24: /* restoreclient */
1204 if (rc.restore_client_name && !rc.mod) {
1205 ua->send_msg(_("Restore Client specified twice.\n"));
1208 rc.restore_client_name = ua->argv[i];
1211 case 25: /* pluginoptions */
1212 if (rc.plugin_options) {
1213 ua->send_msg(_("Plugin Options specified twice.\n"));
1216 rc.plugin_options = ua->argv[i];
1217 if (!acl_access_ok(ua, PluginOptions_ACL, rc.plugin_options)) {
1218 ua->send_msg(_("No authoriztion for \"PluginOptions\" specification.\n"));
1226 } /* end strcase compare */
1227 } /* end keyword loop */
1229 * End of keyword for loop -- if not found, we got a bogus keyword
1232 Dmsg1(800, "%s not found\n", ua->argk[i]);
1234 * Special case for Job Name, it can be the first
1235 * keyword that has no value.
1237 if (!rc.job_name && !ua->argv[i]) {
1238 rc.job_name = ua->argk[i]; /* use keyword as job name */
1239 Dmsg1(800, "Set jobname=%s\n", rc.job_name);
1241 ua->send_msg(_("Invalid keyword: %s\n"), ua->argk[i]);
1245 } /* end argc loop */
1247 Dmsg0(800, "Done scan.\n");
1249 if (rc.catalog_name) {
1250 rc.catalog = GetCatalogResWithName(rc.catalog_name);
1251 if (rc.catalog == NULL) {
1252 ua->error_msg(_("Catalog \"%s\" not found\n"), rc.catalog_name);
1255 if (!acl_access_ok(ua, Catalog_ACL, rc.catalog->name())) {
1256 ua->error_msg(_("No authorization. Catalog \"%s\".\n"), rc.catalog->name());
1260 Dmsg1(800, "Using catalog=%s\n", NPRT(rc.catalog_name));
1264 rc.job = GetJobResWithName(rc.job_name);
1266 if (*rc.job_name != 0) {
1267 ua->send_msg(_("Job \"%s\" not found\n"), rc.job_name);
1269 rc.job = select_job_resource(ua);
1271 Dmsg1(800, "Found job=%s\n", rc.job_name);
1273 } else if (!rc.job) {
1274 ua->send_msg(_("A job name must be specified.\n"));
1275 rc.job = select_job_resource(ua);
1279 } else if (!acl_access_ok(ua, Job_ACL, rc.job->name())) {
1280 ua->error_msg( _("No authorization. Job \"%s\".\n"), rc.job->name());
1285 rc.pool = GetPoolResWithName(rc.pool_name);
1287 if (*rc.pool_name != 0) {
1288 ua->warning_msg(_("Pool \"%s\" not found.\n"), rc.pool_name);
1290 rc.pool = select_pool_resource(ua);
1292 } else if (!rc.pool) {
1293 rc.pool = rc.job->pool; /* use default */
1297 } else if (!acl_access_ok(ua, Pool_ACL, rc.pool->name())) {
1298 ua->error_msg(_("No authorization. Pool \"%s\".\n"), rc.pool->name());
1301 Dmsg1(100, "Using pool %s\n", rc.pool->name());
1303 if (rc.store_name) {
1304 rc.store->store = GetStoreResWithName(rc.store_name);
1305 pm_strcpy(rc.store->store_source, _("command line"));
1306 if (!rc.store->store) {
1307 if (*rc.store_name != 0) {
1308 ua->warning_msg(_("Storage \"%s\" not found.\n"), rc.store_name);
1310 rc.store->store = select_storage_resource(ua);
1311 pm_strcpy(rc.store->store_source, _("user selection"));
1313 } else if (!rc.store->store) {
1314 get_job_storage(rc.store, rc.job, NULL); /* use default */
1316 if (!rc.store->store) {
1317 ua->error_msg(_("No storage specified.\n"));
1319 } else if (!acl_access_ok(ua, Storage_ACL, rc.store->store->name())) {
1320 ua->error_msg(_("No authorization. Storage \"%s\".\n"),
1321 rc.store->store->name());
1324 Dmsg1(800, "Using storage=%s\n", rc.store->store->name());
1326 if (rc.client_name) {
1327 rc.client = GetClientResWithName(rc.client_name);
1329 if (*rc.client_name != 0) {
1330 ua->warning_msg(_("Client \"%s\" not found.\n"), rc.client_name);
1332 rc.client = select_client_resource(ua);
1334 } else if (!rc.client) {
1335 rc.client = rc.job->client; /* use default */
1339 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1340 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1344 Dmsg1(800, "Using client=%s\n", rc.client->name());
1346 if (rc.restore_client_name) {
1347 rc.client = GetClientResWithName(rc.restore_client_name);
1349 if (*rc.restore_client_name != 0) {
1350 ua->warning_msg(_("Restore Client \"%s\" not found.\n"), rc.restore_client_name);
1352 rc.client = select_client_resource(ua);
1354 } else if (!rc.client) {
1355 rc.client = rc.job->client; /* use default */
1359 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1360 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1364 Dmsg1(800, "Using restore client=%s\n", rc.client->name());
1367 if (rc.fileset_name) {
1368 rc.fileset = GetFileSetResWithName(rc.fileset_name);
1370 ua->send_msg(_("FileSet \"%s\" not found.\n"), rc.fileset_name);
1371 rc.fileset = select_fileset_resource(ua);
1373 } else if (!rc.fileset) {
1374 rc.fileset = rc.job->fileset; /* use default */
1378 } else if (!acl_access_ok(ua, FileSet_ACL, rc.fileset->name())) {
1379 ua->send_msg(_("No authorization. FileSet \"%s\".\n"),
1380 rc.fileset->name());
1384 if (rc.verify_job_name) {
1385 rc.verify_job = GetJobResWithName(rc.verify_job_name);
1386 if (!rc.verify_job) {
1387 ua->send_msg(_("Verify Job \"%s\" not found.\n"), rc.verify_job_name);
1388 rc.verify_job = select_job_resource(ua);
1390 } else if (!rc.verify_job) {
1391 rc.verify_job = rc.job->verify_job;
1394 if (rc.previous_job_name) {
1395 rc.previous_job = GetJobResWithName(rc.previous_job_name);
1396 if (!rc.previous_job) {
1397 ua->send_msg(_("Migration Job \"%s\" not found.\n"), rc.previous_job_name);
1398 rc.previous_job = select_job_resource(ua);
1401 rc.previous_job = rc.job->verify_job;