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, *comment;
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->getJobType() == 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->getJobType() == JT_BACKUP ||
221 jcr->getJobType() == JT_COPY ||
222 jcr->getJobType() == JT_MIGRATE ||
223 jcr->getJobType() == JT_VERIFY) {
224 add_prompt(ua, _("Pool")); /* 7 */
225 if (jcr->getJobType() == JT_VERIFY) {
226 add_prompt(ua, _("Verify Job")); /* 8 */
228 } else if (jcr->getJobType() == 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->getJobType() == JT_BACKUP || jcr->getJobType() == 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->getJobType() == JT_BACKUP ||
306 jcr->getJobType() == JT_COPY ||
307 jcr->getJobType() == JT_MIGRATE ||
308 jcr->getJobType() == 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->getJobType() == 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"));
442 pm_strcpy(jcr->comment, rc.comment);
448 jcr->where = bstrdup(rc.where);
453 if (jcr->RegexWhere) {
454 free(jcr->RegexWhere);
456 jcr->RegexWhere = bstrdup(rc.regexwhere);
457 rc.regexwhere = NULL;
461 jcr->sched_time = str_to_utime(rc.when);
462 if (jcr->sched_time == 0) {
463 ua->send_msg(_("Invalid time, using current time.\n"));
464 jcr->sched_time = time(NULL);
470 if (jcr->RestoreBootstrap) {
471 free(jcr->RestoreBootstrap);
473 jcr->RestoreBootstrap = bstrdup(rc.bootstrap);
477 if (rc.plugin_options) {
478 if (jcr->plugin_options) {
479 free(jcr->plugin_options);
481 jcr->plugin_options = bstrdup(rc.plugin_options);
482 rc.plugin_options = NULL;
488 for (i=0; ReplaceOptions[i].name; i++) {
489 if (strcasecmp(rc.replace, ReplaceOptions[i].name) == 0) {
490 jcr->replace = ReplaceOptions[i].token;
494 ua->send_msg(_("Invalid replace option: %s\n"), rc.replace);
497 } else if (rc.job->replace) {
498 jcr->replace = rc.job->replace;
500 jcr->replace = REPLACE_ALWAYS;
505 jcr->JobPriority = rc.Priority;
511 jcr->stime = get_pool_memory(PM_MESSAGE);
513 pm_strcpy(jcr->stime, rc.since);
518 jcr->cloned = rc.cloned;
523 /* If pool changed, update migration write storage */
524 if (jcr->getJobType() == JT_MIGRATE || jcr->getJobType() == JT_COPY ||
525 (jcr->getJobType() == JT_BACKUP && jcr->getJobLevel() == L_VIRTUAL_FULL)) {
526 if (!set_migration_wstorage(jcr, rc.pool)) {
530 rc.replace = ReplaceOptions[0].name;
531 for (i=0; ReplaceOptions[i].name; i++) {
532 if (ReplaceOptions[i].token == jcr->replace) {
533 rc.replace = ReplaceOptions[i].name;
537 if (!get_level_from_name(jcr, rc.level_name)) {
538 ua->send_msg(_("Level \"%s\" not valid.\n"), rc.level_name);
541 rc.level_name = NULL;
544 /* Note, this is also MigrateJobId */
545 jcr->RestoreJobId = str_to_int64(rc.jid);
551 static void select_where_regexp(UAContext *ua, JCR *jcr)
554 char *strip_prefix, *add_prefix, *add_suffix, *rwhere;
555 strip_prefix = add_suffix = rwhere = add_prefix = NULL;
558 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s\n"),
559 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix));
561 start_prompt(ua, _("This will replace your current Where value\n"));
562 add_prompt(ua, _("Strip prefix")); /* 0 */
563 add_prompt(ua, _("Add prefix")); /* 1 */
564 add_prompt(ua, _("Add file suffix")); /* 2 */
565 add_prompt(ua, _("Enter a regexp")); /* 3 */
566 add_prompt(ua, _("Test filename manipulation")); /* 4 */
567 add_prompt(ua, _("Use this ?")); /* 5 */
569 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
572 if (get_cmd(ua, _("Please enter path prefix to strip: "))) {
573 if (strip_prefix) bfree(strip_prefix);
574 strip_prefix = bstrdup(ua->cmd);
580 if (get_cmd(ua, _("Please enter path prefix to add (/ for none): "))) {
581 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
585 if (add_prefix) bfree(add_prefix);
586 add_prefix = bstrdup(ua->cmd);
591 if (get_cmd(ua, _("Please enter file suffix to add: "))) {
592 if (add_suffix) bfree(add_suffix);
593 add_suffix = bstrdup(ua->cmd);
598 if (get_cmd(ua, _("Please enter a valid regexp (!from!to!): "))) {
599 if (rwhere) bfree(rwhere);
600 rwhere = bstrdup(ua->cmd);
609 if (rwhere && rwhere[0] != '\0') {
610 regs = get_bregexps(rwhere);
611 ua->send_msg(_("regexwhere=%s\n"), NPRT(rwhere));
613 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
614 regexp = (char *) bmalloc (len * sizeof(char));
615 bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix);
616 regs = get_bregexps(regexp);
617 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s result=%s\n"),
618 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix), NPRT(regexp));
624 ua->send_msg(_("Cannot use your regexp\n"));
627 ua->send_msg(_("Enter a period (.) to stop this test\n"));
628 while (get_cmd(ua, _("Please enter filename to test: "))) {
629 apply_bregexps(ua->cmd, regs, &result);
630 ua->send_msg(_("%s -> %s\n"), ua->cmd, result);
639 case -1: /* error or cancel */
645 /* replace the existing where */
651 /* replace the existing regexwhere */
652 if (jcr->RegexWhere) {
653 bfree(jcr->RegexWhere);
654 jcr->RegexWhere = NULL;
658 jcr->RegexWhere = bstrdup(rwhere);
659 } else if (strip_prefix || add_prefix || add_suffix) {
660 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
661 jcr->RegexWhere = (char *) bmalloc(len*sizeof(char));
662 bregexp_build_where(jcr->RegexWhere, len, strip_prefix, add_prefix, add_suffix);
665 regs = get_bregexps(jcr->RegexWhere);
670 if (jcr->RegexWhere) {
671 bfree(jcr->RegexWhere);
672 jcr->RegexWhere = NULL;
674 ua->send_msg(_("Cannot use your regexp.\n"));
678 if (strip_prefix) bfree(strip_prefix);
679 if (add_prefix) bfree(add_prefix);
680 if (add_suffix) bfree(add_suffix);
681 if (rwhere) bfree(rwhere);
684 static void select_job_level(UAContext *ua, JCR *jcr)
686 if (jcr->getJobType() == JT_BACKUP) {
687 start_prompt(ua, _("Levels:\n"));
688 // add_prompt(ua, _("Base"));
689 add_prompt(ua, _("Full"));
690 add_prompt(ua, _("Incremental"));
691 add_prompt(ua, _("Differential"));
692 add_prompt(ua, _("Since"));
693 add_prompt(ua, _("VirtualFull"));
694 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
696 // jcr->JobLevel = L_BASE;
699 jcr->set_JobLevel(L_FULL);
702 jcr->set_JobLevel(L_INCREMENTAL);
705 jcr->set_JobLevel(L_DIFFERENTIAL);
708 jcr->set_JobLevel(L_SINCE);
711 jcr->set_JobLevel(L_VIRTUAL_FULL);
716 } else if (jcr->getJobType() == JT_VERIFY) {
717 start_prompt(ua, _("Levels:\n"));
718 add_prompt(ua, _("Initialize Catalog"));
719 add_prompt(ua, _("Verify Catalog"));
720 add_prompt(ua, _("Verify Volume to Catalog"));
721 add_prompt(ua, _("Verify Disk to Catalog"));
722 add_prompt(ua, _("Verify Volume Data (not yet implemented)"));
723 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
725 jcr->set_JobLevel(L_VERIFY_INIT);
728 jcr->set_JobLevel(L_VERIFY_CATALOG);
731 jcr->set_JobLevel(L_VERIFY_VOLUME_TO_CATALOG);
734 jcr->set_JobLevel(L_VERIFY_DISK_TO_CATALOG);
737 jcr->set_JobLevel(L_VERIFY_DATA);
743 ua->warning_msg(_("Level not appropriate for this Job. Cannot be changed.\n"));
748 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char *verify_list,
749 char *jid, const char *replace, char *client_name)
751 Dmsg1(800, "JobType=%c\n", jcr->getJobType());
752 switch (jcr->getJobType()) {
754 char dt[MAX_TIME_LENGTH];
756 if (ua->api) ua->signal(BNET_RUN_CMD);
757 ua->send_msg(_("Run %s job\n"
766 jcr->fileset->name(),
767 NPRT(jcr->client->name()),
768 jcr->wstore?jcr->wstore->name():"*None*",
769 bstrutime(dt, sizeof(dt), jcr->sched_time),
771 jcr->set_JobLevel(L_FULL);
775 if (jcr->getJobType() == JT_BACKUP) {
776 if (ua->api) ua->signal(BNET_RUN_CMD);
777 ua->send_msg(_("Run %s job\n"
782 "Pool: %s (From %s)\n"
783 "Storage: %s (From %s)\n"
789 level_to_str(jcr->getJobLevel()),
791 jcr->fileset->name(),
792 NPRT(jcr->pool->name()), jcr->pool_source,
793 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
794 bstrutime(dt, sizeof(dt), jcr->sched_time),
796 jcr->plugin_options?"Plugin Options: ":"",
797 jcr->plugin_options?jcr->plugin_options:"",
798 jcr->plugin_options?"\n":"");
799 } else { /* JT_VERIFY */
801 if (jcr->verify_job) {
802 Name = jcr->verify_job->name();
807 verify_list = job->WriteVerifyList;
812 if (ua->api) ua->signal(BNET_RUN_CMD);
813 ua->send_msg(_("Run %s job\n"
818 "Pool: %s (From %s)\n"
819 "Storage: %s (From %s)\n"
826 level_to_str(jcr->getJobLevel()),
828 jcr->fileset->name(),
829 NPRT(jcr->pool->name()), jcr->pool_source,
830 jcr->rstore->name(), jcr->rstore_source,
833 bstrutime(dt, sizeof(dt), jcr->sched_time),
838 if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
840 jcr->RestoreJobId = str_to_int64(jid);
842 if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
845 jcr->RestoreJobId = ua->int64_val;
848 jcr->set_JobLevel(L_FULL); /* default level */
849 Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId);
850 if (jcr->RestoreJobId == 0) {
851 if (ua->api) ua->signal(BNET_RUN_CMD);
852 /* RegexWhere is take before RestoreWhere */
853 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
854 ua->send_msg(_("Run Restore job\n"
860 "Backup Client: %s\n"
861 "Restore Client: %s\n"
866 "Plugin Options: %s\n"),
868 NPRT(jcr->RestoreBootstrap),
869 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
871 jcr->fileset->name(),
875 bstrutime(dt, sizeof(dt), jcr->sched_time),
876 jcr->catalog->name(),
878 NPRT(jcr->plugin_options));
881 ua->send_msg(_("Run Restore job\n"
887 "Backup Client: %s\n"
888 "Restore Client: %s\n"
893 "Plugin Options: %s\n"),
895 NPRT(jcr->RestoreBootstrap),
896 jcr->where?jcr->where:NPRT(job->RestoreWhere),
898 jcr->fileset->name(),
902 bstrutime(dt, sizeof(dt), jcr->sched_time),
903 jcr->catalog->name(),
905 NPRT(jcr->plugin_options));
909 if (ua->api) ua->signal(BNET_RUN_CMD);
910 ua->send_msg(_("Run Restore job\n"
914 NPRT(jcr->RestoreBootstrap));
916 /* RegexWhere is take before RestoreWhere */
917 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
918 ua->send_msg(_("RegexWhere: %s\n"),
919 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere);
921 ua->send_msg(_("Where: %s\n"),
922 jcr->where?jcr->where:NPRT(job->RestoreWhere));
925 ua->send_msg(_("Replace: %s\n"
932 "Plugin Options: %s\n"),
936 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
937 bstrutime(dt, sizeof(dt), jcr->sched_time),
938 jcr->catalog->name(),
940 NPRT(jcr->plugin_options));
946 if (jcr->getJobType() == JT_COPY) {
947 prt_type = _("Run Copy job\n");
949 prt_type = _("Run Migration job\n");
951 jcr->set_JobLevel(L_FULL); /* default level */
952 if (ua->api) ua->signal(BNET_RUN_CMD);
958 "Pool: %s (From %s)\n"
959 "Read Storage: %s (From %s)\n"
960 "Write Storage: %s (From %s)\n"
967 NPRT(jcr->RestoreBootstrap),
969 jcr->fileset->name(),
970 NPRT(jcr->pool->name()), jcr->pool_source,
971 jcr->rstore->name(), jcr->rstore_source,
972 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
973 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
974 bstrutime(dt, sizeof(dt), jcr->sched_time),
975 jcr->catalog->name(),
979 ua->error_msg(_("Unknown Job Type=%d\n"), jcr->getJobType());
986 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc)
990 static const char *kw[] = { /* command line arguments */
991 "job", /* Used in a switch() */
999 "regexwhere", /* 8 where string as a bregexp */
1001 "bootstrap", /* 10 */
1004 "priority", /* 13 */
1005 "yes", /* 14 -- if you change this change YES_POS too */
1006 "verifyjob", /* 15 */
1007 "files", /* 16 number of files to restore */
1008 "catalog", /* 17 override catalog */
1009 "since", /* 18 since */
1010 "cloned", /* 19 cloned */
1011 "verifylist", /* 20 verify output list */
1012 "migrationjob", /* 21 migration job name */
1014 "backupclient", /* 23 */
1015 "restoreclient", /* 24 */
1016 "pluginoptions", /* 25 */
1017 "spooldata", /* 26 */
1023 rc.catalog_name = NULL;
1025 rc.pool_name = NULL;
1026 rc.store_name = NULL;
1027 rc.client_name = NULL;
1028 rc.restore_client_name = NULL;
1029 rc.fileset_name = NULL;
1030 rc.verify_job_name = NULL;
1031 rc.previous_job_name = NULL;
1032 rc.spool_data_set = 0;
1035 for (i=1; i<ua->argc; i++) {
1036 Dmsg2(800, "Doing arg %d = %s\n", i, ua->argk[i]);
1038 /* Keep looking until we find a good keyword */
1039 for (j=0; !kw_ok && kw[j]; j++) {
1040 if (strcasecmp(ua->argk[i], kw[j]) == 0) {
1041 /* Note, yes and run have no value, so do not fail */
1042 if (!ua->argv[i] && j != YES_POS /*yes*/) {
1043 ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]);
1046 Dmsg1(800, "Got keyword=%s\n", NPRT(kw[j]));
1050 ua->send_msg(_("Job name specified twice.\n"));
1053 rc.job_name = ua->argv[i];
1057 if (rc.jid && !rc.mod) {
1058 ua->send_msg(_("JobId specified twice.\n"));
1061 rc.jid = ua->argv[i];
1064 case 2: /* client */
1066 if (rc.client_name) {
1067 ua->send_msg(_("Client specified twice.\n"));
1070 rc.client_name = ua->argv[i];
1073 case 4: /* fileset */
1074 if (rc.fileset_name) {
1075 ua->send_msg(_("FileSet specified twice.\n"));
1078 rc.fileset_name = ua->argv[i];
1082 if (rc.level_name) {
1083 ua->send_msg(_("Level specified twice.\n"));
1086 rc.level_name = ua->argv[i];
1089 case 6: /* storage */
1091 if (rc.store_name) {
1092 ua->send_msg(_("Storage specified twice.\n"));
1095 rc.store_name = ua->argv[i];
1098 case 8: /* regexwhere */
1099 if ((rc.regexwhere || rc.where) && !rc.mod) {
1100 ua->send_msg(_("RegexWhere or Where specified twice.\n"));
1103 rc.regexwhere = ua->argv[i];
1104 if (!acl_access_ok(ua, Where_ACL, rc.regexwhere)) {
1105 ua->send_msg(_("No authorization for \"regexwhere\" specification.\n"));
1111 if ((rc.where || rc.regexwhere) && !rc.mod) {
1112 ua->send_msg(_("Where or RegexWhere specified twice.\n"));
1115 rc.where = ua->argv[i];
1116 if (!acl_access_ok(ua, Where_ACL, rc.where)) {
1117 ua->send_msg(_("No authoriztion for \"where\" specification.\n"));
1122 case 10: /* bootstrap */
1123 if (rc.bootstrap && !rc.mod) {
1124 ua->send_msg(_("Bootstrap specified twice.\n"));
1127 rc.bootstrap = ua->argv[i];
1130 case 11: /* replace */
1131 if (rc.replace && !rc.mod) {
1132 ua->send_msg(_("Replace specified twice.\n"));
1135 rc.replace = ua->argv[i];
1139 if (rc.when && !rc.mod) {
1140 ua->send_msg(_("When specified twice.\n"));
1143 rc.when = ua->argv[i];
1146 case 13: /* Priority */
1147 if (rc.Priority && !rc.mod) {
1148 ua->send_msg(_("Priority specified twice.\n"));
1151 rc.Priority = atoi(ua->argv[i]);
1152 if (rc.Priority <= 0) {
1153 ua->send_msg(_("Priority must be positive nonzero setting it to 10.\n"));
1161 case 15: /* Verify Job */
1162 if (rc.verify_job_name) {
1163 ua->send_msg(_("Verify Job specified twice.\n"));
1166 rc.verify_job_name = ua->argv[i];
1169 case 16: /* files */
1170 rc.files = atoi(ua->argv[i]);
1174 case 17: /* catalog */
1175 rc.catalog_name = ua->argv[i];
1179 case 18: /* since */
1180 rc.since = ua->argv[i];
1184 case 19: /* cloned */
1189 case 20: /* write verify list output */
1190 rc.verify_list = ua->argv[i];
1193 case 21: /* Migration Job */
1194 if (rc.previous_job_name) {
1195 ua->send_msg(_("Migration Job specified twice.\n"));
1198 rc.previous_job_name = ua->argv[i];
1203 ua->send_msg(_("Pool specified twice.\n"));
1206 rc.pool_name = ua->argv[i];
1209 case 23: /* backupclient */
1210 if (rc.client_name) {
1211 ua->send_msg(_("Client specified twice.\n"));
1214 rc.client_name = ua->argv[i];
1217 case 24: /* restoreclient */
1218 if (rc.restore_client_name && !rc.mod) {
1219 ua->send_msg(_("Restore Client specified twice.\n"));
1222 rc.restore_client_name = ua->argv[i];
1225 case 25: /* pluginoptions */
1226 ua->send_msg(_("Plugin Options not yet implemented.\n"));
1228 if (rc.plugin_options) {
1229 ua->send_msg(_("Plugin Options specified twice.\n"));
1232 rc.plugin_options = ua->argv[i];
1233 if (!acl_access_ok(ua, PluginOptions_ACL, rc.plugin_options)) {
1234 ua->send_msg(_("No authoriztion for \"PluginOptions\" specification.\n"));
1239 case 26: /* spooldata */
1240 if (rc.spool_data_set) {
1241 ua->send_msg(_("Spool flag specified twice.\n"));
1244 if (is_yesno(ua->argv[i], &rc.spool_data)) {
1245 rc.spool_data_set = 1;
1248 ua->send_msg(_("Invalid spooldata flag.\n"));
1251 case 27: /* comment */
1252 rc.comment = ua->argv[i];
1257 } /* end strcase compare */
1258 } /* end keyword loop */
1260 * End of keyword for loop -- if not found, we got a bogus keyword
1263 Dmsg1(800, "%s not found\n", ua->argk[i]);
1265 * Special case for Job Name, it can be the first
1266 * keyword that has no value.
1268 if (!rc.job_name && !ua->argv[i]) {
1269 rc.job_name = ua->argk[i]; /* use keyword as job name */
1270 Dmsg1(800, "Set jobname=%s\n", rc.job_name);
1272 ua->send_msg(_("Invalid keyword: %s\n"), ua->argk[i]);
1276 } /* end argc loop */
1278 Dmsg0(800, "Done scan.\n");
1280 if (!is_comment_legal(ua, rc.comment)) {
1284 if (rc.catalog_name) {
1285 rc.catalog = GetCatalogResWithName(rc.catalog_name);
1286 if (rc.catalog == NULL) {
1287 ua->error_msg(_("Catalog \"%s\" not found\n"), rc.catalog_name);
1290 if (!acl_access_ok(ua, Catalog_ACL, rc.catalog->name())) {
1291 ua->error_msg(_("No authorization. Catalog \"%s\".\n"), rc.catalog->name());
1295 Dmsg1(800, "Using catalog=%s\n", NPRT(rc.catalog_name));
1299 rc.job = GetJobResWithName(rc.job_name);
1301 if (*rc.job_name != 0) {
1302 ua->send_msg(_("Job \"%s\" not found\n"), rc.job_name);
1304 rc.job = select_job_resource(ua);
1306 Dmsg1(800, "Found job=%s\n", rc.job_name);
1308 } else if (!rc.job) {
1309 ua->send_msg(_("A job name must be specified.\n"));
1310 rc.job = select_job_resource(ua);
1314 } else if (!acl_access_ok(ua, Job_ACL, rc.job->name())) {
1315 ua->error_msg( _("No authorization. Job \"%s\".\n"), rc.job->name());
1320 rc.pool = GetPoolResWithName(rc.pool_name);
1322 if (*rc.pool_name != 0) {
1323 ua->warning_msg(_("Pool \"%s\" not found.\n"), rc.pool_name);
1325 rc.pool = select_pool_resource(ua);
1327 } else if (!rc.pool) {
1328 rc.pool = rc.job->pool; /* use default */
1332 } else if (!acl_access_ok(ua, Pool_ACL, rc.pool->name())) {
1333 ua->error_msg(_("No authorization. Pool \"%s\".\n"), rc.pool->name());
1336 Dmsg1(100, "Using pool %s\n", rc.pool->name());
1338 if (rc.spool_data_set) {
1339 rc.job->spool_data = rc.spool_data;
1341 Dmsg1(900, "Spooling data: %s\n", (rc.job->spool_data ? "Yes" : "No"));
1343 if (rc.store_name) {
1344 rc.store->store = GetStoreResWithName(rc.store_name);
1345 pm_strcpy(rc.store->store_source, _("command line"));
1346 if (!rc.store->store) {
1347 if (*rc.store_name != 0) {
1348 ua->warning_msg(_("Storage \"%s\" not found.\n"), rc.store_name);
1350 rc.store->store = select_storage_resource(ua);
1351 pm_strcpy(rc.store->store_source, _("user selection"));
1353 } else if (!rc.store->store) {
1354 get_job_storage(rc.store, rc.job, NULL); /* use default */
1356 if (!rc.store->store) {
1357 ua->error_msg(_("No storage specified.\n"));
1359 } else if (!acl_access_ok(ua, Storage_ACL, rc.store->store->name())) {
1360 ua->error_msg(_("No authorization. Storage \"%s\".\n"),
1361 rc.store->store->name());
1364 Dmsg1(800, "Using storage=%s\n", rc.store->store->name());
1366 if (rc.client_name) {
1367 rc.client = GetClientResWithName(rc.client_name);
1369 if (*rc.client_name != 0) {
1370 ua->warning_msg(_("Client \"%s\" not found.\n"), rc.client_name);
1372 rc.client = select_client_resource(ua);
1374 } else if (!rc.client) {
1375 rc.client = rc.job->client; /* use default */
1379 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1380 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1384 Dmsg1(800, "Using client=%s\n", rc.client->name());
1386 if (rc.restore_client_name) {
1387 rc.client = GetClientResWithName(rc.restore_client_name);
1389 if (*rc.restore_client_name != 0) {
1390 ua->warning_msg(_("Restore Client \"%s\" not found.\n"), rc.restore_client_name);
1392 rc.client = select_client_resource(ua);
1394 } else if (!rc.client) {
1395 rc.client = rc.job->client; /* use default */
1399 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1400 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1404 Dmsg1(800, "Using restore client=%s\n", rc.client->name());
1407 if (rc.fileset_name) {
1408 rc.fileset = GetFileSetResWithName(rc.fileset_name);
1410 ua->send_msg(_("FileSet \"%s\" not found.\n"), rc.fileset_name);
1411 rc.fileset = select_fileset_resource(ua);
1413 } else if (!rc.fileset) {
1414 rc.fileset = rc.job->fileset; /* use default */
1418 } else if (!acl_access_ok(ua, FileSet_ACL, rc.fileset->name())) {
1419 ua->send_msg(_("No authorization. FileSet \"%s\".\n"),
1420 rc.fileset->name());
1424 if (rc.verify_job_name) {
1425 rc.verify_job = GetJobResWithName(rc.verify_job_name);
1426 if (!rc.verify_job) {
1427 ua->send_msg(_("Verify Job \"%s\" not found.\n"), rc.verify_job_name);
1428 rc.verify_job = select_job_resource(ua);
1430 } else if (!rc.verify_job) {
1431 rc.verify_job = rc.job->verify_job;
1434 if (rc.previous_job_name) {
1435 rc.previous_job = GetJobResWithName(rc.previous_job_name);
1436 if (!rc.previous_job) {
1437 ua->send_msg(_("Migration Job \"%s\" not found.\n"), rc.previous_job_name);
1438 rc.previous_job = select_job_resource(ua);
1441 rc.previous_job = rc.job->verify_job;