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;
67 run_ctx() { memset(this, 0, sizeof(run_ctx));
68 store = new USTORE; };
69 ~run_ctx() { delete store; };
72 /* Forward referenced subroutines */
73 static void select_job_level(UAContext *ua, JCR *jcr);
74 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job,
75 const char *verify_list, char *jid, const char *replace,
77 static void select_where_regexp(UAContext *ua, JCR *jcr);
78 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc);
79 static bool reset_restore_context(UAContext *ua, JCR *jcr, run_ctx &rc);
80 static int modify_job_parameters(UAContext *ua, JCR *jcr, run_ctx &rc);
82 /* Imported variables */
83 extern struct s_kw ReplaceOptions[];
86 * For Backup and Verify Jobs
87 * run [job=]<job-name> level=<level-name>
96 int run_cmd(UAContext *ua, const char *cmd)
102 if (!open_client_db(ua)) {
106 if (!scan_command_line_arguments(ua, rc)) {
110 if (find_arg(ua, NT_("fdcalled")) > 0) {
111 jcr->file_bsock = dup_bsock(ua->UA_sock);
116 * Create JCR to run job. NOTE!!! after this point, free_jcr()
120 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
121 set_jcr_defaults(jcr, rc.job);
122 jcr->unlink_bsr = ua->jcr->unlink_bsr; /* copy unlink flag from caller */
123 ua->jcr->unlink_bsr = false;
127 if (!reset_restore_context(ua, jcr, rc)) {
132 /* Run without prompting? */
133 if (ua->batch || find_arg(ua, NT_("yes")) > 0) {
138 * Prompt User to see if all run job parameters are correct, and
139 * allow him to modify them.
141 if (!display_job_parameters(ua, jcr, rc.job, rc.verify_list, rc.jid, rc.replace,
146 if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
150 if (strncasecmp(ua->cmd, ".mod ", 5) == 0 ||
151 (strncasecmp(ua->cmd, "mod ", 4) == 0 && strlen(ua->cmd) > 6)) {
154 if (!scan_command_line_arguments(ua, rc)) {
160 /* Allow the user to modify the settings */
161 status = modify_job_parameters(ua, jcr, rc);
172 if (ua->cmd[0] == 0 || strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
174 Dmsg1(800, "Calling run_job job=%x\n", jcr->job);
177 Dmsg3(100, "JobId=%u using pool %s priority=%d\n", (int)jcr->JobId,
178 jcr->pool->name(), jcr->JobPriority);
179 Dmsg1(900, "Running a job; its spool_data = %d\n", jcr->spool_data);
180 JobId = run_job(jcr);
181 Dmsg4(100, "JobId=%u NewJobId=%d using pool %s priority=%d\n", (int)jcr->JobId,
182 JobId, jcr->pool->name(), jcr->JobPriority);
183 free_jcr(jcr); /* release jcr */
185 ua->error_msg(_("Job failed.\n"));
188 ua->send_msg(_("Job queued. JobId=%s\n"), edit_int64(JobId, ed1));
194 ua->send_msg(_("Job not run.\n"));
196 return 0; /* do not run */
199 int modify_job_parameters(UAContext *ua, JCR *jcr, run_ctx &rc)
203 * At user request modify parameters of job to be run.
205 if (ua->cmd[0] != 0 && strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0) {
208 start_prompt(ua, _("Parameters to modify:\n"));
209 add_prompt(ua, _("Level")); /* 0 */
210 add_prompt(ua, _("Storage")); /* 1 */
211 add_prompt(ua, _("Job")); /* 2 */
212 add_prompt(ua, _("FileSet")); /* 3 */
213 if (jcr->get_JobType() == JT_RESTORE) {
214 add_prompt(ua, _("Restore Client")); /* 4 */
216 add_prompt(ua, _("Client")); /* 4 */
218 add_prompt(ua, _("When")); /* 5 */
219 add_prompt(ua, _("Priority")); /* 6 */
220 if (jcr->get_JobType() == JT_BACKUP ||
221 jcr->get_JobType() == JT_COPY ||
222 jcr->get_JobType() == JT_MIGRATE ||
223 jcr->get_JobType() == JT_VERIFY) {
224 add_prompt(ua, _("Pool")); /* 7 */
225 if (jcr->get_JobType() == JT_VERIFY) {
226 add_prompt(ua, _("Verify Job")); /* 8 */
228 } else if (jcr->get_JobType() == JT_RESTORE) {
229 add_prompt(ua, _("Bootstrap")); /* 7 */
230 add_prompt(ua, _("Where")); /* 8 */
231 add_prompt(ua, _("File Relocation"));/* 9 */
232 add_prompt(ua, _("Replace")); /* 10 */
233 add_prompt(ua, _("JobId")); /* 11 */
235 if (jcr->get_JobType() == JT_BACKUP || jcr->get_JobType() == JT_RESTORE) {
236 add_prompt(ua, _("Plugin Options")); /* 12 */
238 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
241 select_job_level(ua, jcr);
245 rc.store->store = select_storage_resource(ua);
246 if (rc.store->store) {
247 pm_strcpy(rc.store->store_source, _("user selection"));
248 set_rwstorage(jcr, rc.store);
254 rc.job = select_job_resource(ua);
257 set_jcr_defaults(jcr, rc.job);
263 rc.fileset = select_fileset_resource(ua);
265 jcr->fileset = rc.fileset;
271 rc.client = select_client_resource(ua);
273 jcr->client = rc.client;
279 if (!get_cmd(ua, _("Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now): "))) {
282 if (ua->cmd[0] == 0) {
283 jcr->sched_time = time(NULL);
285 jcr->sched_time = str_to_utime(ua->cmd);
286 if (jcr->sched_time == 0) {
287 ua->send_msg(_("Invalid time, using current time.\n"));
288 jcr->sched_time = time(NULL);
294 if (!get_pint(ua, _("Enter new Priority: "))) {
297 if (ua->pint32_val == 0) {
298 ua->send_msg(_("Priority must be a positive integer.\n"));
300 jcr->JobPriority = ua->pint32_val;
304 /* Pool or Bootstrap depending on JobType */
305 if (jcr->get_JobType() == JT_BACKUP ||
306 jcr->get_JobType() == JT_COPY ||
307 jcr->get_JobType() == JT_MIGRATE ||
308 jcr->get_JobType() == JT_VERIFY) { /* Pool */
309 rc.pool = select_pool_resource(ua);
312 Dmsg1(100, "Set new pool=%s\n", jcr->pool->name());
319 if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
322 if (jcr->RestoreBootstrap) {
323 free(jcr->RestoreBootstrap);
324 jcr->RestoreBootstrap = NULL;
326 if (ua->cmd[0] != 0) {
327 jcr->RestoreBootstrap = bstrdup(ua->cmd);
328 fd = fopen(jcr->RestoreBootstrap, "rb");
331 ua->send_msg(_("Warning cannot open %s: ERR=%s\n"),
332 jcr->RestoreBootstrap, be.bstrerror());
333 free(jcr->RestoreBootstrap);
334 jcr->RestoreBootstrap = NULL;
342 if (jcr->get_JobType() == JT_VERIFY) {
343 rc.verify_job = select_job_resource(ua);
345 jcr->verify_job = rc.verify_job;
350 if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) {
353 if (jcr->RegexWhere) { /* cannot use regexwhere and where */
354 free(jcr->RegexWhere);
355 jcr->RegexWhere = NULL;
361 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
364 jcr->where = bstrdup(ua->cmd);
367 /* File relocation */
368 select_where_regexp(ua, jcr);
372 start_prompt(ua, _("Replace:\n"));
373 for (i=0; ReplaceOptions[i].name; i++) {
374 add_prompt(ua, ReplaceOptions[i].name);
376 opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
378 rc.replace = ReplaceOptions[opt].name;
379 jcr->replace = ReplaceOptions[opt].token;
384 rc.jid = NULL; /* force reprompt */
385 jcr->RestoreJobId = 0;
386 if (jcr->RestoreBootstrap) {
387 ua->send_msg(_("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
392 if (!get_cmd(ua, _("Please Plugin Options string: "))) {
395 if (jcr->plugin_options) {
396 free(jcr->plugin_options);
397 jcr->plugin_options = NULL;
399 jcr->plugin_options = bstrdup(ua->cmd);
401 case -1: /* error or cancel */
418 * Reset the restore context.
419 * This subroutine can be called multiple times, so it
420 * must keep any prior settings.
422 static bool reset_restore_context(UAContext *ua, JCR *jcr, run_ctx &rc)
426 jcr->verify_job = rc.verify_job;
427 jcr->previous_job = rc.previous_job;
429 if (jcr->pool != jcr->job->pool) {
430 pm_strcpy(jcr->pool_source, _("User input"));
432 set_rwstorage(jcr, rc.store);
433 jcr->client = rc.client;
434 pm_strcpy(jcr->client_name, rc.client->name());
435 jcr->fileset = rc.fileset;
436 jcr->ExpectedFiles = rc.files;
438 jcr->catalog = rc.catalog;
439 pm_strcpy(jcr->catalog_source, _("User input"));
445 jcr->where = bstrdup(rc.where);
450 if (jcr->RegexWhere) {
451 free(jcr->RegexWhere);
453 jcr->RegexWhere = bstrdup(rc.regexwhere);
454 rc.regexwhere = NULL;
458 jcr->sched_time = str_to_utime(rc.when);
459 if (jcr->sched_time == 0) {
460 ua->send_msg(_("Invalid time, using current time.\n"));
461 jcr->sched_time = time(NULL);
467 if (jcr->RestoreBootstrap) {
468 free(jcr->RestoreBootstrap);
470 jcr->RestoreBootstrap = bstrdup(rc.bootstrap);
474 if (rc.plugin_options) {
475 if (jcr->plugin_options) {
476 free(jcr->plugin_options);
478 jcr->plugin_options = bstrdup(rc.plugin_options);
479 rc.plugin_options = NULL;
485 for (i=0; ReplaceOptions[i].name; i++) {
486 if (strcasecmp(rc.replace, ReplaceOptions[i].name) == 0) {
487 jcr->replace = ReplaceOptions[i].token;
491 ua->send_msg(_("Invalid replace option: %s\n"), rc.replace);
494 } else if (rc.job->replace) {
495 jcr->replace = rc.job->replace;
497 jcr->replace = REPLACE_ALWAYS;
502 jcr->JobPriority = rc.Priority;
508 jcr->stime = get_pool_memory(PM_MESSAGE);
510 pm_strcpy(jcr->stime, rc.since);
515 jcr->cloned = rc.cloned;
520 /* If pool changed, update migration write storage */
521 if (jcr->get_JobType() == JT_MIGRATE || jcr->get_JobType() == JT_COPY ||
522 (jcr->get_JobType() == JT_BACKUP && jcr->get_JobLevel() == L_VIRTUAL_FULL)) {
523 if (!set_migration_wstorage(jcr, rc.pool)) {
527 rc.replace = ReplaceOptions[0].name;
528 for (i=0; ReplaceOptions[i].name; i++) {
529 if (ReplaceOptions[i].token == jcr->replace) {
530 rc.replace = ReplaceOptions[i].name;
534 if (!get_level_from_name(jcr, rc.level_name)) {
535 ua->send_msg(_("Level \"%s\" not valid.\n"), rc.level_name);
538 rc.level_name = NULL;
541 /* Note, this is also MigrateJobId */
542 jcr->RestoreJobId = str_to_int64(rc.jid);
548 static void select_where_regexp(UAContext *ua, JCR *jcr)
551 char *strip_prefix, *add_prefix, *add_suffix, *rwhere;
552 strip_prefix = add_suffix = rwhere = add_prefix = NULL;
555 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s\n"),
556 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix));
558 start_prompt(ua, _("This will replace your current Where value\n"));
559 add_prompt(ua, _("Strip prefix")); /* 0 */
560 add_prompt(ua, _("Add prefix")); /* 1 */
561 add_prompt(ua, _("Add file suffix")); /* 2 */
562 add_prompt(ua, _("Enter a regexp")); /* 3 */
563 add_prompt(ua, _("Test filename manipulation")); /* 4 */
564 add_prompt(ua, _("Use this ?")); /* 5 */
566 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
569 if (get_cmd(ua, _("Please enter path prefix to strip: "))) {
570 if (strip_prefix) bfree(strip_prefix);
571 strip_prefix = bstrdup(ua->cmd);
577 if (get_cmd(ua, _("Please enter path prefix to add (/ for none): "))) {
578 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
582 if (add_prefix) bfree(add_prefix);
583 add_prefix = bstrdup(ua->cmd);
588 if (get_cmd(ua, _("Please enter file suffix to add: "))) {
589 if (add_suffix) bfree(add_suffix);
590 add_suffix = bstrdup(ua->cmd);
595 if (get_cmd(ua, _("Please enter a valid regexp (!from!to!): "))) {
596 if (rwhere) bfree(rwhere);
597 rwhere = bstrdup(ua->cmd);
606 if (rwhere && rwhere[0] != '\0') {
607 regs = get_bregexps(rwhere);
608 ua->send_msg(_("regexwhere=%s\n"), NPRT(rwhere));
610 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
611 regexp = (char *) bmalloc (len * sizeof(char));
612 bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix);
613 regs = get_bregexps(regexp);
614 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s result=%s\n"),
615 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix), NPRT(regexp));
621 ua->send_msg(_("Cannot use your regexp\n"));
625 while (get_cmd(ua, _("Please enter filename to test: "))) {
626 apply_bregexps(ua->cmd, regs, &result);
627 ua->send_msg(_("%s -> %s\n"), ua->cmd, result);
636 case -1: /* error or cancel */
642 /* replace the existing where */
648 /* replace the existing regexwhere */
649 if (jcr->RegexWhere) {
650 bfree(jcr->RegexWhere);
651 jcr->RegexWhere = NULL;
655 jcr->RegexWhere = bstrdup(rwhere);
656 } else if (strip_prefix || add_prefix || add_suffix) {
657 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
658 jcr->RegexWhere = (char *) bmalloc(len*sizeof(char));
659 bregexp_build_where(jcr->RegexWhere, len, strip_prefix, add_prefix, add_suffix);
662 regs = get_bregexps(jcr->RegexWhere);
667 if (jcr->RegexWhere) {
668 bfree(jcr->RegexWhere);
669 jcr->RegexWhere = NULL;
671 ua->send_msg(_("Cannot use your regexp.\n"));
675 if (strip_prefix) bfree(strip_prefix);
676 if (add_prefix) bfree(add_prefix);
677 if (add_suffix) bfree(add_suffix);
678 if (rwhere) bfree(rwhere);
681 static void select_job_level(UAContext *ua, JCR *jcr)
683 if (jcr->get_JobType() == JT_BACKUP) {
684 start_prompt(ua, _("Levels:\n"));
685 // add_prompt(ua, _("Base"));
686 add_prompt(ua, _("Full"));
687 add_prompt(ua, _("Incremental"));
688 add_prompt(ua, _("Differential"));
689 add_prompt(ua, _("Since"));
690 add_prompt(ua, _("VirtualFull"));
691 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
693 // jcr->JobLevel = L_BASE;
696 jcr->set_JobLevel(L_FULL);
699 jcr->set_JobLevel(L_INCREMENTAL);
702 jcr->set_JobLevel(L_DIFFERENTIAL);
705 jcr->set_JobLevel(L_SINCE);
708 jcr->set_JobLevel(L_VIRTUAL_FULL);
713 } else if (jcr->get_JobType() == JT_VERIFY) {
714 start_prompt(ua, _("Levels:\n"));
715 add_prompt(ua, _("Initialize Catalog"));
716 add_prompt(ua, _("Verify Catalog"));
717 add_prompt(ua, _("Verify Volume to Catalog"));
718 add_prompt(ua, _("Verify Disk to Catalog"));
719 add_prompt(ua, _("Verify Volume Data (not yet implemented)"));
720 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
722 jcr->set_JobLevel(L_VERIFY_INIT);
725 jcr->set_JobLevel(L_VERIFY_CATALOG);
728 jcr->set_JobLevel(L_VERIFY_VOLUME_TO_CATALOG);
731 jcr->set_JobLevel(L_VERIFY_DISK_TO_CATALOG);
734 jcr->set_JobLevel(L_VERIFY_DATA);
740 ua->warning_msg(_("Level not appropriate for this Job. Cannot be changed.\n"));
745 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char *verify_list,
746 char *jid, const char *replace, char *client_name)
748 Dmsg1(800, "JobType=%c\n", jcr->get_JobType());
749 switch (jcr->get_JobType()) {
751 char dt[MAX_TIME_LENGTH];
753 if (ua->api) ua->signal(BNET_RUN_CMD);
754 ua->send_msg(_("Run %s job\n"
763 jcr->fileset->name(),
764 NPRT(jcr->client->name()),
765 jcr->wstore?jcr->wstore->name():"*None*",
766 bstrutime(dt, sizeof(dt), jcr->sched_time),
768 jcr->set_JobLevel(L_FULL);
772 if (jcr->get_JobType() == JT_BACKUP) {
773 if (ua->api) ua->signal(BNET_RUN_CMD);
774 ua->send_msg(_("Run %s job\n"
779 "Pool: %s (From %s)\n"
780 "Storage: %s (From %s)\n"
786 level_to_str(jcr->get_JobLevel()),
788 jcr->fileset->name(),
789 NPRT(jcr->pool->name()), jcr->pool_source,
790 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
791 bstrutime(dt, sizeof(dt), jcr->sched_time),
793 jcr->plugin_options?"Plugin Options: ":"",
794 jcr->plugin_options?jcr->plugin_options:"",
795 jcr->plugin_options?"\n":"");
796 } else { /* JT_VERIFY */
798 if (jcr->verify_job) {
799 Name = jcr->verify_job->name();
804 verify_list = job->WriteVerifyList;
809 if (ua->api) ua->signal(BNET_RUN_CMD);
810 ua->send_msg(_("Run %s job\n"
815 "Pool: %s (From %s)\n"
816 "Storage: %s (From %s)\n"
823 level_to_str(jcr->get_JobLevel()),
825 jcr->fileset->name(),
826 NPRT(jcr->pool->name()), jcr->pool_source,
827 jcr->rstore->name(), jcr->rstore_source,
830 bstrutime(dt, sizeof(dt), jcr->sched_time),
835 if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
837 jcr->RestoreJobId = str_to_int64(jid);
839 if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
842 jcr->RestoreJobId = ua->int64_val;
845 jcr->set_JobLevel(L_FULL); /* default level */
846 Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId);
847 if (jcr->RestoreJobId == 0) {
848 if (ua->api) ua->signal(BNET_RUN_CMD);
849 /* RegexWhere is take before RestoreWhere */
850 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
851 ua->send_msg(_("Run Restore job\n"
857 "Backup Client: %s\n"
858 "Restore Client: %s\n"
863 "Plugin Options: %s\n"),
865 NPRT(jcr->RestoreBootstrap),
866 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
868 jcr->fileset->name(),
872 bstrutime(dt, sizeof(dt), jcr->sched_time),
873 jcr->catalog->name(),
875 NPRT(jcr->plugin_options));
878 ua->send_msg(_("Run Restore job\n"
884 "Backup Client: %s\n"
885 "Restore Client: %s\n"
890 "Plugin Options: %s\n"),
892 NPRT(jcr->RestoreBootstrap),
893 jcr->where?jcr->where:NPRT(job->RestoreWhere),
895 jcr->fileset->name(),
899 bstrutime(dt, sizeof(dt), jcr->sched_time),
900 jcr->catalog->name(),
902 NPRT(jcr->plugin_options));
906 if (ua->api) ua->signal(BNET_RUN_CMD);
907 ua->send_msg(_("Run Restore job\n"
911 NPRT(jcr->RestoreBootstrap));
913 /* RegexWhere is take before RestoreWhere */
914 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
915 ua->send_msg(_("RegexWhere: %s\n"),
916 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere);
918 ua->send_msg(_("Where: %s\n"),
919 jcr->where?jcr->where:NPRT(job->RestoreWhere));
922 ua->send_msg(_("Replace: %s\n"
929 "Plugin Options: %s\n"),
933 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
934 bstrutime(dt, sizeof(dt), jcr->sched_time),
935 jcr->catalog->name(),
937 NPRT(jcr->plugin_options));
943 if (jcr->get_JobType() == JT_COPY) {
944 prt_type = _("Run Copy job\n");
946 prt_type = _("Run Migration job\n");
948 jcr->set_JobLevel(L_FULL); /* default level */
949 if (ua->api) ua->signal(BNET_RUN_CMD);
955 "Pool: %s (From %s)\n"
956 "Read Storage: %s (From %s)\n"
957 "Write Storage: %s (From %s)\n"
964 NPRT(jcr->RestoreBootstrap),
966 jcr->fileset->name(),
967 NPRT(jcr->pool->name()), jcr->pool_source,
968 jcr->rstore->name(), jcr->rstore_source,
969 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
970 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
971 bstrutime(dt, sizeof(dt), jcr->sched_time),
972 jcr->catalog->name(),
976 ua->error_msg(_("Unknown Job Type=%d\n"), jcr->get_JobType());
983 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc)
987 static const char *kw[] = { /* command line arguments */
988 "job", /* Used in a switch() */
996 "regexwhere", /* 8 where string as a bregexp */
998 "bootstrap", /* 10 */
1001 "priority", /* 13 */
1002 "yes", /* 14 -- if you change this change YES_POS too */
1003 "verifyjob", /* 15 */
1004 "files", /* 16 number of files to restore */
1005 "catalog", /* 17 override catalog */
1006 "since", /* 18 since */
1007 "cloned", /* 19 cloned */
1008 "verifylist", /* 20 verify output list */
1009 "migrationjob", /* 21 migration job name */
1011 "backupclient", /* 23 */
1012 "restoreclient", /* 24 */
1013 "pluginoptions", /* 25 */
1014 "spooldata", /* 26 */
1019 rc.catalog_name = NULL;
1021 rc.pool_name = NULL;
1022 rc.store_name = NULL;
1023 rc.client_name = NULL;
1024 rc.restore_client_name = NULL;
1025 rc.fileset_name = NULL;
1026 rc.verify_job_name = NULL;
1027 rc.previous_job_name = NULL;
1028 rc.spool_data_set = 0;
1031 for (i=1; i<ua->argc; i++) {
1032 Dmsg2(800, "Doing arg %d = %s\n", i, ua->argk[i]);
1034 /* Keep looking until we find a good keyword */
1035 for (j=0; !kw_ok && kw[j]; j++) {
1036 if (strcasecmp(ua->argk[i], kw[j]) == 0) {
1037 /* Note, yes and run have no value, so do not fail */
1038 if (!ua->argv[i] && j != YES_POS /*yes*/) {
1039 ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]);
1042 Dmsg1(800, "Got keyword=%s\n", NPRT(kw[j]));
1046 ua->send_msg(_("Job name specified twice.\n"));
1049 rc.job_name = ua->argv[i];
1053 if (rc.jid && !rc.mod) {
1054 ua->send_msg(_("JobId specified twice.\n"));
1057 rc.jid = ua->argv[i];
1060 case 2: /* client */
1062 if (rc.client_name) {
1063 ua->send_msg(_("Client specified twice.\n"));
1066 rc.client_name = ua->argv[i];
1069 case 4: /* fileset */
1070 if (rc.fileset_name) {
1071 ua->send_msg(_("FileSet specified twice.\n"));
1074 rc.fileset_name = ua->argv[i];
1078 if (rc.level_name) {
1079 ua->send_msg(_("Level specified twice.\n"));
1082 rc.level_name = ua->argv[i];
1085 case 6: /* storage */
1087 if (rc.store_name) {
1088 ua->send_msg(_("Storage specified twice.\n"));
1091 rc.store_name = ua->argv[i];
1094 case 8: /* regexwhere */
1095 if ((rc.regexwhere || rc.where) && !rc.mod) {
1096 ua->send_msg(_("RegexWhere or Where specified twice.\n"));
1099 rc.regexwhere = ua->argv[i];
1100 if (!acl_access_ok(ua, Where_ACL, rc.regexwhere)) {
1101 ua->send_msg(_("No authorization for \"regexwhere\" specification.\n"));
1107 if ((rc.where || rc.regexwhere) && !rc.mod) {
1108 ua->send_msg(_("Where or RegexWhere specified twice.\n"));
1111 rc.where = ua->argv[i];
1112 if (!acl_access_ok(ua, Where_ACL, rc.where)) {
1113 ua->send_msg(_("No authoriztion for \"where\" specification.\n"));
1118 case 10: /* bootstrap */
1119 if (rc.bootstrap && !rc.mod) {
1120 ua->send_msg(_("Bootstrap specified twice.\n"));
1123 rc.bootstrap = ua->argv[i];
1126 case 11: /* replace */
1127 if (rc.replace && !rc.mod) {
1128 ua->send_msg(_("Replace specified twice.\n"));
1131 rc.replace = ua->argv[i];
1135 if (rc.when && !rc.mod) {
1136 ua->send_msg(_("When specified twice.\n"));
1139 rc.when = ua->argv[i];
1142 case 13: /* Priority */
1143 if (rc.Priority && !rc.mod) {
1144 ua->send_msg(_("Priority specified twice.\n"));
1147 rc.Priority = atoi(ua->argv[i]);
1148 if (rc.Priority <= 0) {
1149 ua->send_msg(_("Priority must be positive nonzero setting it to 10.\n"));
1157 case 15: /* Verify Job */
1158 if (rc.verify_job_name) {
1159 ua->send_msg(_("Verify Job specified twice.\n"));
1162 rc.verify_job_name = ua->argv[i];
1165 case 16: /* files */
1166 rc.files = atoi(ua->argv[i]);
1170 case 17: /* catalog */
1171 rc.catalog_name = ua->argv[i];
1175 case 18: /* since */
1176 rc.since = ua->argv[i];
1180 case 19: /* cloned */
1185 case 20: /* write verify list output */
1186 rc.verify_list = ua->argv[i];
1189 case 21: /* Migration Job */
1190 if (rc.previous_job_name) {
1191 ua->send_msg(_("Migration Job specified twice.\n"));
1194 rc.previous_job_name = ua->argv[i];
1199 ua->send_msg(_("Pool specified twice.\n"));
1202 rc.pool_name = ua->argv[i];
1205 case 23: /* backupclient */
1206 if (rc.client_name) {
1207 ua->send_msg(_("Client specified twice.\n"));
1210 rc.client_name = ua->argv[i];
1213 case 24: /* restoreclient */
1214 if (rc.restore_client_name && !rc.mod) {
1215 ua->send_msg(_("Restore Client specified twice.\n"));
1218 rc.restore_client_name = ua->argv[i];
1221 case 25: /* pluginoptions */
1222 ua->send_msg(_("Plugin Options not yet implemented.\n"));
1224 if (rc.plugin_options) {
1225 ua->send_msg(_("Plugin Options specified twice.\n"));
1228 rc.plugin_options = ua->argv[i];
1229 if (!acl_access_ok(ua, PluginOptions_ACL, rc.plugin_options)) {
1230 ua->send_msg(_("No authoriztion for \"PluginOptions\" specification.\n"));
1235 case 26: /* spooldata */
1236 if (rc.spool_data_set) {
1237 ua->send_msg(_("Spool flag specified twice.\n"));
1240 if (is_yesno(ua->argv[i], &rc.spool_data)) {
1241 rc.spool_data_set = 1;
1244 ua->send_msg(_("Invalid spooldata flag.\n"));
1250 } /* end strcase compare */
1251 } /* end keyword loop */
1253 * End of keyword for loop -- if not found, we got a bogus keyword
1256 Dmsg1(800, "%s not found\n", ua->argk[i]);
1258 * Special case for Job Name, it can be the first
1259 * keyword that has no value.
1261 if (!rc.job_name && !ua->argv[i]) {
1262 rc.job_name = ua->argk[i]; /* use keyword as job name */
1263 Dmsg1(800, "Set jobname=%s\n", rc.job_name);
1265 ua->send_msg(_("Invalid keyword: %s\n"), ua->argk[i]);
1269 } /* end argc loop */
1271 Dmsg0(800, "Done scan.\n");
1273 if (rc.catalog_name) {
1274 rc.catalog = GetCatalogResWithName(rc.catalog_name);
1275 if (rc.catalog == NULL) {
1276 ua->error_msg(_("Catalog \"%s\" not found\n"), rc.catalog_name);
1279 if (!acl_access_ok(ua, Catalog_ACL, rc.catalog->name())) {
1280 ua->error_msg(_("No authorization. Catalog \"%s\".\n"), rc.catalog->name());
1284 Dmsg1(800, "Using catalog=%s\n", NPRT(rc.catalog_name));
1288 rc.job = GetJobResWithName(rc.job_name);
1290 if (*rc.job_name != 0) {
1291 ua->send_msg(_("Job \"%s\" not found\n"), rc.job_name);
1293 rc.job = select_job_resource(ua);
1295 Dmsg1(800, "Found job=%s\n", rc.job_name);
1297 } else if (!rc.job) {
1298 ua->send_msg(_("A job name must be specified.\n"));
1299 rc.job = select_job_resource(ua);
1303 } else if (!acl_access_ok(ua, Job_ACL, rc.job->name())) {
1304 ua->error_msg( _("No authorization. Job \"%s\".\n"), rc.job->name());
1309 rc.pool = GetPoolResWithName(rc.pool_name);
1311 if (*rc.pool_name != 0) {
1312 ua->warning_msg(_("Pool \"%s\" not found.\n"), rc.pool_name);
1314 rc.pool = select_pool_resource(ua);
1316 } else if (!rc.pool) {
1317 rc.pool = rc.job->pool; /* use default */
1321 } else if (!acl_access_ok(ua, Pool_ACL, rc.pool->name())) {
1322 ua->error_msg(_("No authorization. Pool \"%s\".\n"), rc.pool->name());
1325 Dmsg1(100, "Using pool %s\n", rc.pool->name());
1327 if (rc.spool_data_set) {
1328 rc.job->spool_data = rc.spool_data;
1330 Dmsg1(900, "Spooling data: %s\n", (rc.job->spool_data ? "Yes" : "No"));
1332 if (rc.store_name) {
1333 rc.store->store = GetStoreResWithName(rc.store_name);
1334 pm_strcpy(rc.store->store_source, _("command line"));
1335 if (!rc.store->store) {
1336 if (*rc.store_name != 0) {
1337 ua->warning_msg(_("Storage \"%s\" not found.\n"), rc.store_name);
1339 rc.store->store = select_storage_resource(ua);
1340 pm_strcpy(rc.store->store_source, _("user selection"));
1342 } else if (!rc.store->store) {
1343 get_job_storage(rc.store, rc.job, NULL); /* use default */
1345 if (!rc.store->store) {
1346 ua->error_msg(_("No storage specified.\n"));
1348 } else if (!acl_access_ok(ua, Storage_ACL, rc.store->store->name())) {
1349 ua->error_msg(_("No authorization. Storage \"%s\".\n"),
1350 rc.store->store->name());
1353 Dmsg1(800, "Using storage=%s\n", rc.store->store->name());
1355 if (rc.client_name) {
1356 rc.client = GetClientResWithName(rc.client_name);
1358 if (*rc.client_name != 0) {
1359 ua->warning_msg(_("Client \"%s\" not found.\n"), rc.client_name);
1361 rc.client = select_client_resource(ua);
1363 } else if (!rc.client) {
1364 rc.client = rc.job->client; /* use default */
1368 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1369 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1373 Dmsg1(800, "Using client=%s\n", rc.client->name());
1375 if (rc.restore_client_name) {
1376 rc.client = GetClientResWithName(rc.restore_client_name);
1378 if (*rc.restore_client_name != 0) {
1379 ua->warning_msg(_("Restore Client \"%s\" not found.\n"), rc.restore_client_name);
1381 rc.client = select_client_resource(ua);
1383 } else if (!rc.client) {
1384 rc.client = rc.job->client; /* use default */
1388 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1389 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1393 Dmsg1(800, "Using restore client=%s\n", rc.client->name());
1396 if (rc.fileset_name) {
1397 rc.fileset = GetFileSetResWithName(rc.fileset_name);
1399 ua->send_msg(_("FileSet \"%s\" not found.\n"), rc.fileset_name);
1400 rc.fileset = select_fileset_resource(ua);
1402 } else if (!rc.fileset) {
1403 rc.fileset = rc.job->fileset; /* use default */
1407 } else if (!acl_access_ok(ua, FileSet_ACL, rc.fileset->name())) {
1408 ua->send_msg(_("No authorization. FileSet \"%s\".\n"),
1409 rc.fileset->name());
1413 if (rc.verify_job_name) {
1414 rc.verify_job = GetJobResWithName(rc.verify_job_name);
1415 if (!rc.verify_job) {
1416 ua->send_msg(_("Verify Job \"%s\" not found.\n"), rc.verify_job_name);
1417 rc.verify_job = select_job_resource(ua);
1419 } else if (!rc.verify_job) {
1420 rc.verify_job = rc.job->verify_job;
1423 if (rc.previous_job_name) {
1424 rc.previous_job = GetJobResWithName(rc.previous_job_name);
1425 if (!rc.previous_job) {
1426 ua->send_msg(_("Migration Job \"%s\" not found.\n"), rc.previous_job_name);
1427 rc.previous_job = select_job_resource(ua);
1430 rc.previous_job = rc.job->verify_job;