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;
125 /* Transfer JobIds to new restore Job */
126 if (ua->jcr->JobIds) {
127 jcr->JobIds = ua->jcr->JobIds;
128 ua->jcr->JobIds = NULL;
132 if (!reset_restore_context(ua, jcr, rc)) {
137 /* Run without prompting? */
138 if (ua->batch || find_arg(ua, NT_("yes")) > 0) {
143 * Prompt User to see if all run job parameters are correct, and
144 * allow him to modify them.
146 if (!display_job_parameters(ua, jcr, rc.job, rc.verify_list, rc.jid, rc.replace,
151 if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
155 if (strncasecmp(ua->cmd, ".mod ", 5) == 0 ||
156 (strncasecmp(ua->cmd, "mod ", 4) == 0 && strlen(ua->cmd) > 6)) {
159 if (!scan_command_line_arguments(ua, rc)) {
165 /* Allow the user to modify the settings */
166 status = modify_job_parameters(ua, jcr, rc);
177 if (ua->cmd[0] == 0 || strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
179 Dmsg1(800, "Calling run_job job=%x\n", jcr->job);
182 Dmsg3(100, "JobId=%u using pool %s priority=%d\n", (int)jcr->JobId,
183 jcr->pool->name(), jcr->JobPriority);
184 Dmsg1(900, "Running a job; its spool_data = %d\n", jcr->spool_data);
185 JobId = run_job(jcr);
186 Dmsg4(100, "JobId=%u NewJobId=%d using pool %s priority=%d\n", (int)jcr->JobId,
187 JobId, jcr->pool->name(), jcr->JobPriority);
188 free_jcr(jcr); /* release jcr */
190 ua->error_msg(_("Job failed.\n"));
193 ua->send_msg(_("Job queued. JobId=%s\n"), edit_int64(JobId, ed1));
199 ua->send_msg(_("Job not run.\n"));
201 return 0; /* do not run */
204 int modify_job_parameters(UAContext *ua, JCR *jcr, run_ctx &rc)
208 * At user request modify parameters of job to be run.
210 if (ua->cmd[0] != 0 && strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0) {
213 start_prompt(ua, _("Parameters to modify:\n"));
214 add_prompt(ua, _("Level")); /* 0 */
215 add_prompt(ua, _("Storage")); /* 1 */
216 add_prompt(ua, _("Job")); /* 2 */
217 add_prompt(ua, _("FileSet")); /* 3 */
218 if (jcr->getJobType() == JT_RESTORE) {
219 add_prompt(ua, _("Restore Client")); /* 4 */
221 add_prompt(ua, _("Client")); /* 4 */
223 add_prompt(ua, _("When")); /* 5 */
224 add_prompt(ua, _("Priority")); /* 6 */
225 if (jcr->getJobType() == JT_BACKUP ||
226 jcr->getJobType() == JT_COPY ||
227 jcr->getJobType() == JT_MIGRATE ||
228 jcr->getJobType() == JT_VERIFY) {
229 add_prompt(ua, _("Pool")); /* 7 */
230 if (jcr->getJobType() == JT_VERIFY) {
231 add_prompt(ua, _("Verify Job")); /* 8 */
233 } else if (jcr->getJobType() == JT_RESTORE) {
234 add_prompt(ua, _("Bootstrap")); /* 7 */
235 add_prompt(ua, _("Where")); /* 8 */
236 add_prompt(ua, _("File Relocation"));/* 9 */
237 add_prompt(ua, _("Replace")); /* 10 */
238 add_prompt(ua, _("JobId")); /* 11 */
240 if (jcr->getJobType() == JT_BACKUP || jcr->getJobType() == JT_RESTORE) {
241 add_prompt(ua, _("Plugin Options")); /* 12 */
243 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
246 select_job_level(ua, jcr);
250 rc.store->store = select_storage_resource(ua);
251 if (rc.store->store) {
252 pm_strcpy(rc.store->store_source, _("user selection"));
253 set_rwstorage(jcr, rc.store);
259 rc.job = select_job_resource(ua);
262 set_jcr_defaults(jcr, rc.job);
268 rc.fileset = select_fileset_resource(ua);
270 jcr->fileset = rc.fileset;
276 rc.client = select_client_resource(ua);
278 jcr->client = rc.client;
284 if (!get_cmd(ua, _("Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now): "))) {
287 if (ua->cmd[0] == 0) {
288 jcr->sched_time = time(NULL);
290 jcr->sched_time = str_to_utime(ua->cmd);
291 if (jcr->sched_time == 0) {
292 ua->send_msg(_("Invalid time, using current time.\n"));
293 jcr->sched_time = time(NULL);
299 if (!get_pint(ua, _("Enter new Priority: "))) {
302 if (ua->pint32_val == 0) {
303 ua->send_msg(_("Priority must be a positive integer.\n"));
305 jcr->JobPriority = ua->pint32_val;
309 /* Pool or Bootstrap depending on JobType */
310 if (jcr->getJobType() == JT_BACKUP ||
311 jcr->getJobType() == JT_COPY ||
312 jcr->getJobType() == JT_MIGRATE ||
313 jcr->getJobType() == JT_VERIFY) { /* Pool */
314 rc.pool = select_pool_resource(ua);
317 Dmsg1(100, "Set new pool=%s\n", jcr->pool->name());
324 if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
327 if (jcr->RestoreBootstrap) {
328 free(jcr->RestoreBootstrap);
329 jcr->RestoreBootstrap = NULL;
331 if (ua->cmd[0] != 0) {
332 jcr->RestoreBootstrap = bstrdup(ua->cmd);
333 fd = fopen(jcr->RestoreBootstrap, "rb");
336 ua->send_msg(_("Warning cannot open %s: ERR=%s\n"),
337 jcr->RestoreBootstrap, be.bstrerror());
338 free(jcr->RestoreBootstrap);
339 jcr->RestoreBootstrap = NULL;
347 if (jcr->getJobType() == JT_VERIFY) {
348 rc.verify_job = select_job_resource(ua);
350 jcr->verify_job = rc.verify_job;
355 if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) {
358 if (jcr->RegexWhere) { /* cannot use regexwhere and where */
359 free(jcr->RegexWhere);
360 jcr->RegexWhere = NULL;
366 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
369 jcr->where = bstrdup(ua->cmd);
372 /* File relocation */
373 select_where_regexp(ua, jcr);
377 start_prompt(ua, _("Replace:\n"));
378 for (i=0; ReplaceOptions[i].name; i++) {
379 add_prompt(ua, ReplaceOptions[i].name);
381 opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
383 rc.replace = ReplaceOptions[opt].name;
384 jcr->replace = ReplaceOptions[opt].token;
389 rc.jid = NULL; /* force reprompt */
390 jcr->RestoreJobId = 0;
391 if (jcr->RestoreBootstrap) {
392 ua->send_msg(_("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
397 if (!get_cmd(ua, _("Please Plugin Options string: "))) {
400 if (jcr->plugin_options) {
401 free(jcr->plugin_options);
402 jcr->plugin_options = NULL;
404 jcr->plugin_options = bstrdup(ua->cmd);
406 case -1: /* error or cancel */
423 * Reset the restore context.
424 * This subroutine can be called multiple times, so it
425 * must keep any prior settings.
427 static bool reset_restore_context(UAContext *ua, JCR *jcr, run_ctx &rc)
431 jcr->verify_job = rc.verify_job;
432 jcr->previous_job = rc.previous_job;
434 if (jcr->pool != jcr->job->pool) {
435 pm_strcpy(jcr->pool_source, _("User input"));
437 set_rwstorage(jcr, rc.store);
438 jcr->client = rc.client;
439 pm_strcpy(jcr->client_name, rc.client->name());
440 jcr->fileset = rc.fileset;
441 jcr->ExpectedFiles = rc.files;
443 jcr->catalog = rc.catalog;
444 pm_strcpy(jcr->catalog_source, _("User input"));
447 pm_strcpy(jcr->comment, rc.comment);
453 jcr->where = bstrdup(rc.where);
458 if (jcr->RegexWhere) {
459 free(jcr->RegexWhere);
461 jcr->RegexWhere = bstrdup(rc.regexwhere);
462 rc.regexwhere = NULL;
466 jcr->sched_time = str_to_utime(rc.when);
467 if (jcr->sched_time == 0) {
468 ua->send_msg(_("Invalid time, using current time.\n"));
469 jcr->sched_time = time(NULL);
475 if (jcr->RestoreBootstrap) {
476 free(jcr->RestoreBootstrap);
478 jcr->RestoreBootstrap = bstrdup(rc.bootstrap);
482 if (rc.plugin_options) {
483 if (jcr->plugin_options) {
484 free(jcr->plugin_options);
486 jcr->plugin_options = bstrdup(rc.plugin_options);
487 rc.plugin_options = NULL;
493 for (i=0; ReplaceOptions[i].name; i++) {
494 if (strcasecmp(rc.replace, ReplaceOptions[i].name) == 0) {
495 jcr->replace = ReplaceOptions[i].token;
499 ua->send_msg(_("Invalid replace option: %s\n"), rc.replace);
502 } else if (rc.job->replace) {
503 jcr->replace = rc.job->replace;
505 jcr->replace = REPLACE_ALWAYS;
510 jcr->JobPriority = rc.Priority;
516 jcr->stime = get_pool_memory(PM_MESSAGE);
518 pm_strcpy(jcr->stime, rc.since);
523 jcr->cloned = rc.cloned;
528 /* If pool changed, update migration write storage */
529 if (jcr->getJobType() == JT_MIGRATE || jcr->getJobType() == JT_COPY ||
530 (jcr->getJobType() == JT_BACKUP && jcr->getJobLevel() == L_VIRTUAL_FULL)) {
531 if (!set_migration_wstorage(jcr, rc.pool)) {
535 rc.replace = ReplaceOptions[0].name;
536 for (i=0; ReplaceOptions[i].name; i++) {
537 if (ReplaceOptions[i].token == jcr->replace) {
538 rc.replace = ReplaceOptions[i].name;
542 if (!get_level_from_name(jcr, rc.level_name)) {
543 ua->send_msg(_("Level \"%s\" not valid.\n"), rc.level_name);
546 rc.level_name = NULL;
549 /* Note, this is also MigrateJobId */
550 jcr->RestoreJobId = str_to_int64(rc.jid);
556 static void select_where_regexp(UAContext *ua, JCR *jcr)
559 char *strip_prefix, *add_prefix, *add_suffix, *rwhere;
560 strip_prefix = add_suffix = rwhere = add_prefix = NULL;
563 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s\n"),
564 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix));
566 start_prompt(ua, _("This will replace your current Where value\n"));
567 add_prompt(ua, _("Strip prefix")); /* 0 */
568 add_prompt(ua, _("Add prefix")); /* 1 */
569 add_prompt(ua, _("Add file suffix")); /* 2 */
570 add_prompt(ua, _("Enter a regexp")); /* 3 */
571 add_prompt(ua, _("Test filename manipulation")); /* 4 */
572 add_prompt(ua, _("Use this ?")); /* 5 */
574 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
577 if (get_cmd(ua, _("Please enter path prefix to strip: "))) {
578 if (strip_prefix) bfree(strip_prefix);
579 strip_prefix = bstrdup(ua->cmd);
585 if (get_cmd(ua, _("Please enter path prefix to add (/ for none): "))) {
586 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
590 if (add_prefix) bfree(add_prefix);
591 add_prefix = bstrdup(ua->cmd);
596 if (get_cmd(ua, _("Please enter file suffix to add: "))) {
597 if (add_suffix) bfree(add_suffix);
598 add_suffix = bstrdup(ua->cmd);
603 if (get_cmd(ua, _("Please enter a valid regexp (!from!to!): "))) {
604 if (rwhere) bfree(rwhere);
605 rwhere = bstrdup(ua->cmd);
614 if (rwhere && rwhere[0] != '\0') {
615 regs = get_bregexps(rwhere);
616 ua->send_msg(_("regexwhere=%s\n"), NPRT(rwhere));
618 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
619 regexp = (char *) bmalloc (len * sizeof(char));
620 bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix);
621 regs = get_bregexps(regexp);
622 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s result=%s\n"),
623 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix), NPRT(regexp));
629 ua->send_msg(_("Cannot use your regexp\n"));
632 ua->send_msg(_("Enter a period (.) to stop this test\n"));
633 while (get_cmd(ua, _("Please enter filename to test: "))) {
634 apply_bregexps(ua->cmd, regs, &result);
635 ua->send_msg(_("%s -> %s\n"), ua->cmd, result);
644 case -1: /* error or cancel */
650 /* replace the existing where */
656 /* replace the existing regexwhere */
657 if (jcr->RegexWhere) {
658 bfree(jcr->RegexWhere);
659 jcr->RegexWhere = NULL;
663 jcr->RegexWhere = bstrdup(rwhere);
664 } else if (strip_prefix || add_prefix || add_suffix) {
665 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
666 jcr->RegexWhere = (char *) bmalloc(len*sizeof(char));
667 bregexp_build_where(jcr->RegexWhere, len, strip_prefix, add_prefix, add_suffix);
670 regs = get_bregexps(jcr->RegexWhere);
675 if (jcr->RegexWhere) {
676 bfree(jcr->RegexWhere);
677 jcr->RegexWhere = NULL;
679 ua->send_msg(_("Cannot use your regexp.\n"));
683 if (strip_prefix) bfree(strip_prefix);
684 if (add_prefix) bfree(add_prefix);
685 if (add_suffix) bfree(add_suffix);
686 if (rwhere) bfree(rwhere);
689 static void select_job_level(UAContext *ua, JCR *jcr)
691 if (jcr->getJobType() == JT_BACKUP) {
692 start_prompt(ua, _("Levels:\n"));
693 // add_prompt(ua, _("Base"));
694 add_prompt(ua, _("Full"));
695 add_prompt(ua, _("Incremental"));
696 add_prompt(ua, _("Differential"));
697 add_prompt(ua, _("Since"));
698 add_prompt(ua, _("VirtualFull"));
699 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
701 // jcr->JobLevel = L_BASE;
704 jcr->set_JobLevel(L_FULL);
707 jcr->set_JobLevel(L_INCREMENTAL);
710 jcr->set_JobLevel(L_DIFFERENTIAL);
713 jcr->set_JobLevel(L_SINCE);
716 jcr->set_JobLevel(L_VIRTUAL_FULL);
721 } else if (jcr->getJobType() == JT_VERIFY) {
722 start_prompt(ua, _("Levels:\n"));
723 add_prompt(ua, _("Initialize Catalog"));
724 add_prompt(ua, _("Verify Catalog"));
725 add_prompt(ua, _("Verify Volume to Catalog"));
726 add_prompt(ua, _("Verify Disk to Catalog"));
727 add_prompt(ua, _("Verify Volume Data (not yet implemented)"));
728 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
730 jcr->set_JobLevel(L_VERIFY_INIT);
733 jcr->set_JobLevel(L_VERIFY_CATALOG);
736 jcr->set_JobLevel(L_VERIFY_VOLUME_TO_CATALOG);
739 jcr->set_JobLevel(L_VERIFY_DISK_TO_CATALOG);
742 jcr->set_JobLevel(L_VERIFY_DATA);
748 ua->warning_msg(_("Level not appropriate for this Job. Cannot be changed.\n"));
753 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char *verify_list,
754 char *jid, const char *replace, char *client_name)
756 Dmsg1(800, "JobType=%c\n", jcr->getJobType());
757 switch (jcr->getJobType()) {
759 char dt[MAX_TIME_LENGTH];
761 if (ua->api) ua->signal(BNET_RUN_CMD);
762 ua->send_msg(_("Run %s job\n"
771 jcr->fileset->name(),
772 NPRT(jcr->client->name()),
773 jcr->wstore?jcr->wstore->name():"*None*",
774 bstrutime(dt, sizeof(dt), jcr->sched_time),
776 jcr->set_JobLevel(L_FULL);
780 if (jcr->getJobType() == JT_BACKUP) {
781 if (ua->api) ua->signal(BNET_RUN_CMD);
782 ua->send_msg(_("Run %s job\n"
787 "Pool: %s (From %s)\n"
788 "Storage: %s (From %s)\n"
794 level_to_str(jcr->getJobLevel()),
796 jcr->fileset->name(),
797 NPRT(jcr->pool->name()), jcr->pool_source,
798 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
799 bstrutime(dt, sizeof(dt), jcr->sched_time),
801 jcr->plugin_options?"Plugin Options: ":"",
802 jcr->plugin_options?jcr->plugin_options:"",
803 jcr->plugin_options?"\n":"");
804 } else { /* JT_VERIFY */
806 if (jcr->verify_job) {
807 Name = jcr->verify_job->name();
812 verify_list = job->WriteVerifyList;
817 if (ua->api) ua->signal(BNET_RUN_CMD);
818 ua->send_msg(_("Run %s job\n"
823 "Pool: %s (From %s)\n"
824 "Storage: %s (From %s)\n"
831 level_to_str(jcr->getJobLevel()),
833 jcr->fileset->name(),
834 NPRT(jcr->pool->name()), jcr->pool_source,
835 jcr->rstore->name(), jcr->rstore_source,
838 bstrutime(dt, sizeof(dt), jcr->sched_time),
843 if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
845 jcr->RestoreJobId = str_to_int64(jid);
847 if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
850 jcr->RestoreJobId = ua->int64_val;
853 jcr->set_JobLevel(L_FULL); /* default level */
854 Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId);
855 if (jcr->RestoreJobId == 0) {
856 if (ua->api) ua->signal(BNET_RUN_CMD);
857 /* RegexWhere is take before RestoreWhere */
858 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
859 ua->send_msg(_("Run Restore job\n"
865 "Backup Client: %s\n"
866 "Restore Client: %s\n"
871 "Plugin Options: %s\n"),
873 NPRT(jcr->RestoreBootstrap),
874 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
876 jcr->fileset->name(),
880 bstrutime(dt, sizeof(dt), jcr->sched_time),
881 jcr->catalog->name(),
883 NPRT(jcr->plugin_options));
886 ua->send_msg(_("Run Restore job\n"
892 "Backup Client: %s\n"
893 "Restore Client: %s\n"
898 "Plugin Options: %s\n"),
900 NPRT(jcr->RestoreBootstrap),
901 jcr->where?jcr->where:NPRT(job->RestoreWhere),
903 jcr->fileset->name(),
907 bstrutime(dt, sizeof(dt), jcr->sched_time),
908 jcr->catalog->name(),
910 NPRT(jcr->plugin_options));
914 if (ua->api) ua->signal(BNET_RUN_CMD);
915 ua->send_msg(_("Run Restore job\n"
919 NPRT(jcr->RestoreBootstrap));
921 /* RegexWhere is take before RestoreWhere */
922 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
923 ua->send_msg(_("RegexWhere: %s\n"),
924 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere);
926 ua->send_msg(_("Where: %s\n"),
927 jcr->where?jcr->where:NPRT(job->RestoreWhere));
930 ua->send_msg(_("Replace: %s\n"
937 "Plugin Options: %s\n"),
941 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
942 bstrutime(dt, sizeof(dt), jcr->sched_time),
943 jcr->catalog->name(),
945 NPRT(jcr->plugin_options));
951 if (jcr->getJobType() == JT_COPY) {
952 prt_type = _("Run Copy job\n");
954 prt_type = _("Run Migration job\n");
956 jcr->set_JobLevel(L_FULL); /* default level */
957 if (ua->api) ua->signal(BNET_RUN_CMD);
963 "Pool: %s (From %s)\n"
964 "Read Storage: %s (From %s)\n"
965 "Write Storage: %s (From %s)\n"
972 NPRT(jcr->RestoreBootstrap),
974 jcr->fileset->name(),
975 NPRT(jcr->pool->name()), jcr->pool_source,
976 jcr->rstore->name(), jcr->rstore_source,
977 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
978 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
979 bstrutime(dt, sizeof(dt), jcr->sched_time),
980 jcr->catalog->name(),
984 ua->error_msg(_("Unknown Job Type=%d\n"), jcr->getJobType());
991 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc)
995 static const char *kw[] = { /* command line arguments */
996 "job", /* Used in a switch() */
1004 "regexwhere", /* 8 where string as a bregexp */
1006 "bootstrap", /* 10 */
1009 "priority", /* 13 */
1010 "yes", /* 14 -- if you change this change YES_POS too */
1011 "verifyjob", /* 15 */
1012 "files", /* 16 number of files to restore */
1013 "catalog", /* 17 override catalog */
1014 "since", /* 18 since */
1015 "cloned", /* 19 cloned */
1016 "verifylist", /* 20 verify output list */
1017 "migrationjob", /* 21 migration job name */
1019 "backupclient", /* 23 */
1020 "restoreclient", /* 24 */
1021 "pluginoptions", /* 25 */
1022 "spooldata", /* 26 */
1028 rc.catalog_name = NULL;
1030 rc.pool_name = NULL;
1031 rc.store_name = NULL;
1032 rc.client_name = NULL;
1033 rc.restore_client_name = NULL;
1034 rc.fileset_name = NULL;
1035 rc.verify_job_name = NULL;
1036 rc.previous_job_name = NULL;
1037 rc.spool_data_set = 0;
1040 for (i=1; i<ua->argc; i++) {
1041 Dmsg2(800, "Doing arg %d = %s\n", i, ua->argk[i]);
1043 /* Keep looking until we find a good keyword */
1044 for (j=0; !kw_ok && kw[j]; j++) {
1045 if (strcasecmp(ua->argk[i], kw[j]) == 0) {
1046 /* Note, yes and run have no value, so do not fail */
1047 if (!ua->argv[i] && j != YES_POS /*yes*/) {
1048 ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]);
1051 Dmsg1(800, "Got keyword=%s\n", NPRT(kw[j]));
1055 ua->send_msg(_("Job name specified twice.\n"));
1058 rc.job_name = ua->argv[i];
1062 if (rc.jid && !rc.mod) {
1063 ua->send_msg(_("JobId specified twice.\n"));
1066 rc.jid = ua->argv[i];
1069 case 2: /* client */
1071 if (rc.client_name) {
1072 ua->send_msg(_("Client specified twice.\n"));
1075 rc.client_name = ua->argv[i];
1078 case 4: /* fileset */
1079 if (rc.fileset_name) {
1080 ua->send_msg(_("FileSet specified twice.\n"));
1083 rc.fileset_name = ua->argv[i];
1087 if (rc.level_name) {
1088 ua->send_msg(_("Level specified twice.\n"));
1091 rc.level_name = ua->argv[i];
1094 case 6: /* storage */
1096 if (rc.store_name) {
1097 ua->send_msg(_("Storage specified twice.\n"));
1100 rc.store_name = ua->argv[i];
1103 case 8: /* regexwhere */
1104 if ((rc.regexwhere || rc.where) && !rc.mod) {
1105 ua->send_msg(_("RegexWhere or Where specified twice.\n"));
1108 rc.regexwhere = ua->argv[i];
1109 if (!acl_access_ok(ua, Where_ACL, rc.regexwhere)) {
1110 ua->send_msg(_("No authorization for \"regexwhere\" specification.\n"));
1116 if ((rc.where || rc.regexwhere) && !rc.mod) {
1117 ua->send_msg(_("Where or RegexWhere specified twice.\n"));
1120 rc.where = ua->argv[i];
1121 if (!acl_access_ok(ua, Where_ACL, rc.where)) {
1122 ua->send_msg(_("No authoriztion for \"where\" specification.\n"));
1127 case 10: /* bootstrap */
1128 if (rc.bootstrap && !rc.mod) {
1129 ua->send_msg(_("Bootstrap specified twice.\n"));
1132 rc.bootstrap = ua->argv[i];
1135 case 11: /* replace */
1136 if (rc.replace && !rc.mod) {
1137 ua->send_msg(_("Replace specified twice.\n"));
1140 rc.replace = ua->argv[i];
1144 if (rc.when && !rc.mod) {
1145 ua->send_msg(_("When specified twice.\n"));
1148 rc.when = ua->argv[i];
1151 case 13: /* Priority */
1152 if (rc.Priority && !rc.mod) {
1153 ua->send_msg(_("Priority specified twice.\n"));
1156 rc.Priority = atoi(ua->argv[i]);
1157 if (rc.Priority <= 0) {
1158 ua->send_msg(_("Priority must be positive nonzero setting it to 10.\n"));
1166 case 15: /* Verify Job */
1167 if (rc.verify_job_name) {
1168 ua->send_msg(_("Verify Job specified twice.\n"));
1171 rc.verify_job_name = ua->argv[i];
1174 case 16: /* files */
1175 rc.files = atoi(ua->argv[i]);
1179 case 17: /* catalog */
1180 rc.catalog_name = ua->argv[i];
1184 case 18: /* since */
1185 rc.since = ua->argv[i];
1189 case 19: /* cloned */
1194 case 20: /* write verify list output */
1195 rc.verify_list = ua->argv[i];
1198 case 21: /* Migration Job */
1199 if (rc.previous_job_name) {
1200 ua->send_msg(_("Migration Job specified twice.\n"));
1203 rc.previous_job_name = ua->argv[i];
1208 ua->send_msg(_("Pool specified twice.\n"));
1211 rc.pool_name = ua->argv[i];
1214 case 23: /* backupclient */
1215 if (rc.client_name) {
1216 ua->send_msg(_("Client specified twice.\n"));
1219 rc.client_name = ua->argv[i];
1222 case 24: /* restoreclient */
1223 if (rc.restore_client_name && !rc.mod) {
1224 ua->send_msg(_("Restore Client specified twice.\n"));
1227 rc.restore_client_name = ua->argv[i];
1230 case 25: /* pluginoptions */
1231 ua->send_msg(_("Plugin Options not yet implemented.\n"));
1233 if (rc.plugin_options) {
1234 ua->send_msg(_("Plugin Options specified twice.\n"));
1237 rc.plugin_options = ua->argv[i];
1238 if (!acl_access_ok(ua, PluginOptions_ACL, rc.plugin_options)) {
1239 ua->send_msg(_("No authoriztion for \"PluginOptions\" specification.\n"));
1244 case 26: /* spooldata */
1245 if (rc.spool_data_set) {
1246 ua->send_msg(_("Spool flag specified twice.\n"));
1249 if (is_yesno(ua->argv[i], &rc.spool_data)) {
1250 rc.spool_data_set = 1;
1253 ua->send_msg(_("Invalid spooldata flag.\n"));
1256 case 27: /* comment */
1257 rc.comment = ua->argv[i];
1262 } /* end strcase compare */
1263 } /* end keyword loop */
1265 * End of keyword for loop -- if not found, we got a bogus keyword
1268 Dmsg1(800, "%s not found\n", ua->argk[i]);
1270 * Special case for Job Name, it can be the first
1271 * keyword that has no value.
1273 if (!rc.job_name && !ua->argv[i]) {
1274 rc.job_name = ua->argk[i]; /* use keyword as job name */
1275 Dmsg1(800, "Set jobname=%s\n", rc.job_name);
1277 ua->send_msg(_("Invalid keyword: %s\n"), ua->argk[i]);
1281 } /* end argc loop */
1283 Dmsg0(800, "Done scan.\n");
1285 if (!is_comment_legal(ua, rc.comment)) {
1289 if (rc.catalog_name) {
1290 rc.catalog = GetCatalogResWithName(rc.catalog_name);
1291 if (rc.catalog == NULL) {
1292 ua->error_msg(_("Catalog \"%s\" not found\n"), rc.catalog_name);
1295 if (!acl_access_ok(ua, Catalog_ACL, rc.catalog->name())) {
1296 ua->error_msg(_("No authorization. Catalog \"%s\".\n"), rc.catalog->name());
1300 Dmsg1(800, "Using catalog=%s\n", NPRT(rc.catalog_name));
1304 rc.job = GetJobResWithName(rc.job_name);
1306 if (*rc.job_name != 0) {
1307 ua->send_msg(_("Job \"%s\" not found\n"), rc.job_name);
1309 rc.job = select_job_resource(ua);
1311 Dmsg1(800, "Found job=%s\n", rc.job_name);
1313 } else if (!rc.job) {
1314 ua->send_msg(_("A job name must be specified.\n"));
1315 rc.job = select_job_resource(ua);
1319 } else if (!acl_access_ok(ua, Job_ACL, rc.job->name())) {
1320 ua->error_msg( _("No authorization. Job \"%s\".\n"), rc.job->name());
1325 rc.pool = GetPoolResWithName(rc.pool_name);
1327 if (*rc.pool_name != 0) {
1328 ua->warning_msg(_("Pool \"%s\" not found.\n"), rc.pool_name);
1330 rc.pool = select_pool_resource(ua);
1332 } else if (!rc.pool) {
1333 rc.pool = rc.job->pool; /* use default */
1337 } else if (!acl_access_ok(ua, Pool_ACL, rc.pool->name())) {
1338 ua->error_msg(_("No authorization. Pool \"%s\".\n"), rc.pool->name());
1341 Dmsg1(100, "Using pool %s\n", rc.pool->name());
1343 if (rc.spool_data_set) {
1344 rc.job->spool_data = rc.spool_data;
1346 Dmsg1(900, "Spooling data: %s\n", (rc.job->spool_data ? "Yes" : "No"));
1348 if (rc.store_name) {
1349 rc.store->store = GetStoreResWithName(rc.store_name);
1350 pm_strcpy(rc.store->store_source, _("command line"));
1351 if (!rc.store->store) {
1352 if (*rc.store_name != 0) {
1353 ua->warning_msg(_("Storage \"%s\" not found.\n"), rc.store_name);
1355 rc.store->store = select_storage_resource(ua);
1356 pm_strcpy(rc.store->store_source, _("user selection"));
1358 } else if (!rc.store->store) {
1359 get_job_storage(rc.store, rc.job, NULL); /* use default */
1361 if (!rc.store->store) {
1362 ua->error_msg(_("No storage specified.\n"));
1364 } else if (!acl_access_ok(ua, Storage_ACL, rc.store->store->name())) {
1365 ua->error_msg(_("No authorization. Storage \"%s\".\n"),
1366 rc.store->store->name());
1369 Dmsg1(800, "Using storage=%s\n", rc.store->store->name());
1371 if (rc.client_name) {
1372 rc.client = GetClientResWithName(rc.client_name);
1374 if (*rc.client_name != 0) {
1375 ua->warning_msg(_("Client \"%s\" not found.\n"), rc.client_name);
1377 rc.client = select_client_resource(ua);
1379 } else if (!rc.client) {
1380 rc.client = rc.job->client; /* use default */
1384 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1385 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1389 Dmsg1(800, "Using client=%s\n", rc.client->name());
1391 if (rc.restore_client_name) {
1392 rc.client = GetClientResWithName(rc.restore_client_name);
1394 if (*rc.restore_client_name != 0) {
1395 ua->warning_msg(_("Restore Client \"%s\" not found.\n"), rc.restore_client_name);
1397 rc.client = select_client_resource(ua);
1399 } else if (!rc.client) {
1400 rc.client = rc.job->client; /* use default */
1404 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1405 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1409 Dmsg1(800, "Using restore client=%s\n", rc.client->name());
1412 if (rc.fileset_name) {
1413 rc.fileset = GetFileSetResWithName(rc.fileset_name);
1415 ua->send_msg(_("FileSet \"%s\" not found.\n"), rc.fileset_name);
1416 rc.fileset = select_fileset_resource(ua);
1418 } else if (!rc.fileset) {
1419 rc.fileset = rc.job->fileset; /* use default */
1423 } else if (!acl_access_ok(ua, FileSet_ACL, rc.fileset->name())) {
1424 ua->send_msg(_("No authorization. FileSet \"%s\".\n"),
1425 rc.fileset->name());
1429 if (rc.verify_job_name) {
1430 rc.verify_job = GetJobResWithName(rc.verify_job_name);
1431 if (!rc.verify_job) {
1432 ua->send_msg(_("Verify Job \"%s\" not found.\n"), rc.verify_job_name);
1433 rc.verify_job = select_job_resource(ua);
1435 } else if (!rc.verify_job) {
1436 rc.verify_job = rc.job->verify_job;
1439 if (rc.previous_job_name) {
1440 rc.previous_job = GetJobResWithName(rc.previous_job_name);
1441 if (!rc.previous_job) {
1442 ua->send_msg(_("Migration Job \"%s\" not found.\n"), rc.previous_job_name);
1443 rc.previous_job = select_job_resource(ua);
1446 rc.previous_job = rc.job->verify_job;