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"));
443 jcr->comment = get_pool_memory(PM_MESSAGE);
445 pm_strcpy(jcr->comment, rc.comment);
451 jcr->where = bstrdup(rc.where);
456 if (jcr->RegexWhere) {
457 free(jcr->RegexWhere);
459 jcr->RegexWhere = bstrdup(rc.regexwhere);
460 rc.regexwhere = NULL;
464 jcr->sched_time = str_to_utime(rc.when);
465 if (jcr->sched_time == 0) {
466 ua->send_msg(_("Invalid time, using current time.\n"));
467 jcr->sched_time = time(NULL);
473 if (jcr->RestoreBootstrap) {
474 free(jcr->RestoreBootstrap);
476 jcr->RestoreBootstrap = bstrdup(rc.bootstrap);
480 if (rc.plugin_options) {
481 if (jcr->plugin_options) {
482 free(jcr->plugin_options);
484 jcr->plugin_options = bstrdup(rc.plugin_options);
485 rc.plugin_options = NULL;
491 for (i=0; ReplaceOptions[i].name; i++) {
492 if (strcasecmp(rc.replace, ReplaceOptions[i].name) == 0) {
493 jcr->replace = ReplaceOptions[i].token;
497 ua->send_msg(_("Invalid replace option: %s\n"), rc.replace);
500 } else if (rc.job->replace) {
501 jcr->replace = rc.job->replace;
503 jcr->replace = REPLACE_ALWAYS;
508 jcr->JobPriority = rc.Priority;
514 jcr->stime = get_pool_memory(PM_MESSAGE);
516 pm_strcpy(jcr->stime, rc.since);
521 jcr->cloned = rc.cloned;
526 /* If pool changed, update migration write storage */
527 if (jcr->getJobType() == JT_MIGRATE || jcr->getJobType() == JT_COPY ||
528 (jcr->getJobType() == JT_BACKUP && jcr->getJobLevel() == L_VIRTUAL_FULL)) {
529 if (!set_migration_wstorage(jcr, rc.pool)) {
533 rc.replace = ReplaceOptions[0].name;
534 for (i=0; ReplaceOptions[i].name; i++) {
535 if (ReplaceOptions[i].token == jcr->replace) {
536 rc.replace = ReplaceOptions[i].name;
540 if (!get_level_from_name(jcr, rc.level_name)) {
541 ua->send_msg(_("Level \"%s\" not valid.\n"), rc.level_name);
544 rc.level_name = NULL;
547 /* Note, this is also MigrateJobId */
548 jcr->RestoreJobId = str_to_int64(rc.jid);
554 static void select_where_regexp(UAContext *ua, JCR *jcr)
557 char *strip_prefix, *add_prefix, *add_suffix, *rwhere;
558 strip_prefix = add_suffix = rwhere = add_prefix = NULL;
561 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s\n"),
562 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix));
564 start_prompt(ua, _("This will replace your current Where value\n"));
565 add_prompt(ua, _("Strip prefix")); /* 0 */
566 add_prompt(ua, _("Add prefix")); /* 1 */
567 add_prompt(ua, _("Add file suffix")); /* 2 */
568 add_prompt(ua, _("Enter a regexp")); /* 3 */
569 add_prompt(ua, _("Test filename manipulation")); /* 4 */
570 add_prompt(ua, _("Use this ?")); /* 5 */
572 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
575 if (get_cmd(ua, _("Please enter path prefix to strip: "))) {
576 if (strip_prefix) bfree(strip_prefix);
577 strip_prefix = bstrdup(ua->cmd);
583 if (get_cmd(ua, _("Please enter path prefix to add (/ for none): "))) {
584 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
588 if (add_prefix) bfree(add_prefix);
589 add_prefix = bstrdup(ua->cmd);
594 if (get_cmd(ua, _("Please enter file suffix to add: "))) {
595 if (add_suffix) bfree(add_suffix);
596 add_suffix = bstrdup(ua->cmd);
601 if (get_cmd(ua, _("Please enter a valid regexp (!from!to!): "))) {
602 if (rwhere) bfree(rwhere);
603 rwhere = bstrdup(ua->cmd);
612 if (rwhere && rwhere[0] != '\0') {
613 regs = get_bregexps(rwhere);
614 ua->send_msg(_("regexwhere=%s\n"), NPRT(rwhere));
616 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
617 regexp = (char *) bmalloc (len * sizeof(char));
618 bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix);
619 regs = get_bregexps(regexp);
620 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s result=%s\n"),
621 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix), NPRT(regexp));
627 ua->send_msg(_("Cannot use your regexp\n"));
630 ua->send_msg(_("Enter a period (.) to stop this test\n"));
631 while (get_cmd(ua, _("Please enter filename to test: "))) {
632 apply_bregexps(ua->cmd, regs, &result);
633 ua->send_msg(_("%s -> %s\n"), ua->cmd, result);
642 case -1: /* error or cancel */
648 /* replace the existing where */
654 /* replace the existing regexwhere */
655 if (jcr->RegexWhere) {
656 bfree(jcr->RegexWhere);
657 jcr->RegexWhere = NULL;
661 jcr->RegexWhere = bstrdup(rwhere);
662 } else if (strip_prefix || add_prefix || add_suffix) {
663 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
664 jcr->RegexWhere = (char *) bmalloc(len*sizeof(char));
665 bregexp_build_where(jcr->RegexWhere, len, strip_prefix, add_prefix, add_suffix);
668 regs = get_bregexps(jcr->RegexWhere);
673 if (jcr->RegexWhere) {
674 bfree(jcr->RegexWhere);
675 jcr->RegexWhere = NULL;
677 ua->send_msg(_("Cannot use your regexp.\n"));
681 if (strip_prefix) bfree(strip_prefix);
682 if (add_prefix) bfree(add_prefix);
683 if (add_suffix) bfree(add_suffix);
684 if (rwhere) bfree(rwhere);
687 static void select_job_level(UAContext *ua, JCR *jcr)
689 if (jcr->getJobType() == JT_BACKUP) {
690 start_prompt(ua, _("Levels:\n"));
691 // add_prompt(ua, _("Base"));
692 add_prompt(ua, _("Full"));
693 add_prompt(ua, _("Incremental"));
694 add_prompt(ua, _("Differential"));
695 add_prompt(ua, _("Since"));
696 add_prompt(ua, _("VirtualFull"));
697 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
699 // jcr->JobLevel = L_BASE;
702 jcr->set_JobLevel(L_FULL);
705 jcr->set_JobLevel(L_INCREMENTAL);
708 jcr->set_JobLevel(L_DIFFERENTIAL);
711 jcr->set_JobLevel(L_SINCE);
714 jcr->set_JobLevel(L_VIRTUAL_FULL);
719 } else if (jcr->getJobType() == JT_VERIFY) {
720 start_prompt(ua, _("Levels:\n"));
721 add_prompt(ua, _("Initialize Catalog"));
722 add_prompt(ua, _("Verify Catalog"));
723 add_prompt(ua, _("Verify Volume to Catalog"));
724 add_prompt(ua, _("Verify Disk to Catalog"));
725 add_prompt(ua, _("Verify Volume Data (not yet implemented)"));
726 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
728 jcr->set_JobLevel(L_VERIFY_INIT);
731 jcr->set_JobLevel(L_VERIFY_CATALOG);
734 jcr->set_JobLevel(L_VERIFY_VOLUME_TO_CATALOG);
737 jcr->set_JobLevel(L_VERIFY_DISK_TO_CATALOG);
740 jcr->set_JobLevel(L_VERIFY_DATA);
746 ua->warning_msg(_("Level not appropriate for this Job. Cannot be changed.\n"));
751 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char *verify_list,
752 char *jid, const char *replace, char *client_name)
754 Dmsg1(800, "JobType=%c\n", jcr->getJobType());
755 switch (jcr->getJobType()) {
757 char dt[MAX_TIME_LENGTH];
759 if (ua->api) ua->signal(BNET_RUN_CMD);
760 ua->send_msg(_("Run %s job\n"
769 jcr->fileset->name(),
770 NPRT(jcr->client->name()),
771 jcr->wstore?jcr->wstore->name():"*None*",
772 bstrutime(dt, sizeof(dt), jcr->sched_time),
774 jcr->set_JobLevel(L_FULL);
778 if (jcr->getJobType() == JT_BACKUP) {
779 if (ua->api) ua->signal(BNET_RUN_CMD);
780 ua->send_msg(_("Run %s job\n"
785 "Pool: %s (From %s)\n"
786 "Storage: %s (From %s)\n"
792 level_to_str(jcr->getJobLevel()),
794 jcr->fileset->name(),
795 NPRT(jcr->pool->name()), jcr->pool_source,
796 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
797 bstrutime(dt, sizeof(dt), jcr->sched_time),
799 jcr->plugin_options?"Plugin Options: ":"",
800 jcr->plugin_options?jcr->plugin_options:"",
801 jcr->plugin_options?"\n":"");
802 } else { /* JT_VERIFY */
804 if (jcr->verify_job) {
805 Name = jcr->verify_job->name();
810 verify_list = job->WriteVerifyList;
815 if (ua->api) ua->signal(BNET_RUN_CMD);
816 ua->send_msg(_("Run %s job\n"
821 "Pool: %s (From %s)\n"
822 "Storage: %s (From %s)\n"
829 level_to_str(jcr->getJobLevel()),
831 jcr->fileset->name(),
832 NPRT(jcr->pool->name()), jcr->pool_source,
833 jcr->rstore->name(), jcr->rstore_source,
836 bstrutime(dt, sizeof(dt), jcr->sched_time),
841 if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
843 jcr->RestoreJobId = str_to_int64(jid);
845 if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
848 jcr->RestoreJobId = ua->int64_val;
851 jcr->set_JobLevel(L_FULL); /* default level */
852 Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId);
853 if (jcr->RestoreJobId == 0) {
854 if (ua->api) ua->signal(BNET_RUN_CMD);
855 /* RegexWhere is take before RestoreWhere */
856 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
857 ua->send_msg(_("Run Restore job\n"
863 "Backup Client: %s\n"
864 "Restore Client: %s\n"
869 "Plugin Options: %s\n"),
871 NPRT(jcr->RestoreBootstrap),
872 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
874 jcr->fileset->name(),
878 bstrutime(dt, sizeof(dt), jcr->sched_time),
879 jcr->catalog->name(),
881 NPRT(jcr->plugin_options));
884 ua->send_msg(_("Run Restore job\n"
890 "Backup Client: %s\n"
891 "Restore Client: %s\n"
896 "Plugin Options: %s\n"),
898 NPRT(jcr->RestoreBootstrap),
899 jcr->where?jcr->where:NPRT(job->RestoreWhere),
901 jcr->fileset->name(),
905 bstrutime(dt, sizeof(dt), jcr->sched_time),
906 jcr->catalog->name(),
908 NPRT(jcr->plugin_options));
912 if (ua->api) ua->signal(BNET_RUN_CMD);
913 ua->send_msg(_("Run Restore job\n"
917 NPRT(jcr->RestoreBootstrap));
919 /* RegexWhere is take before RestoreWhere */
920 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
921 ua->send_msg(_("RegexWhere: %s\n"),
922 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere);
924 ua->send_msg(_("Where: %s\n"),
925 jcr->where?jcr->where:NPRT(job->RestoreWhere));
928 ua->send_msg(_("Replace: %s\n"
935 "Plugin Options: %s\n"),
939 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
940 bstrutime(dt, sizeof(dt), jcr->sched_time),
941 jcr->catalog->name(),
943 NPRT(jcr->plugin_options));
949 if (jcr->getJobType() == JT_COPY) {
950 prt_type = _("Run Copy job\n");
952 prt_type = _("Run Migration job\n");
954 jcr->set_JobLevel(L_FULL); /* default level */
955 if (ua->api) ua->signal(BNET_RUN_CMD);
961 "Pool: %s (From %s)\n"
962 "Read Storage: %s (From %s)\n"
963 "Write Storage: %s (From %s)\n"
970 NPRT(jcr->RestoreBootstrap),
972 jcr->fileset->name(),
973 NPRT(jcr->pool->name()), jcr->pool_source,
974 jcr->rstore->name(), jcr->rstore_source,
975 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
976 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
977 bstrutime(dt, sizeof(dt), jcr->sched_time),
978 jcr->catalog->name(),
982 ua->error_msg(_("Unknown Job Type=%d\n"), jcr->getJobType());
989 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc)
993 static const char *kw[] = { /* command line arguments */
994 "job", /* Used in a switch() */
1002 "regexwhere", /* 8 where string as a bregexp */
1004 "bootstrap", /* 10 */
1007 "priority", /* 13 */
1008 "yes", /* 14 -- if you change this change YES_POS too */
1009 "verifyjob", /* 15 */
1010 "files", /* 16 number of files to restore */
1011 "catalog", /* 17 override catalog */
1012 "since", /* 18 since */
1013 "cloned", /* 19 cloned */
1014 "verifylist", /* 20 verify output list */
1015 "migrationjob", /* 21 migration job name */
1017 "backupclient", /* 23 */
1018 "restoreclient", /* 24 */
1019 "pluginoptions", /* 25 */
1020 "spooldata", /* 26 */
1026 rc.catalog_name = NULL;
1028 rc.pool_name = NULL;
1029 rc.store_name = NULL;
1030 rc.client_name = NULL;
1031 rc.restore_client_name = NULL;
1032 rc.fileset_name = NULL;
1033 rc.verify_job_name = NULL;
1034 rc.previous_job_name = NULL;
1035 rc.spool_data_set = 0;
1038 for (i=1; i<ua->argc; i++) {
1039 Dmsg2(800, "Doing arg %d = %s\n", i, ua->argk[i]);
1041 /* Keep looking until we find a good keyword */
1042 for (j=0; !kw_ok && kw[j]; j++) {
1043 if (strcasecmp(ua->argk[i], kw[j]) == 0) {
1044 /* Note, yes and run have no value, so do not fail */
1045 if (!ua->argv[i] && j != YES_POS /*yes*/) {
1046 ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]);
1049 Dmsg1(800, "Got keyword=%s\n", NPRT(kw[j]));
1053 ua->send_msg(_("Job name specified twice.\n"));
1056 rc.job_name = ua->argv[i];
1060 if (rc.jid && !rc.mod) {
1061 ua->send_msg(_("JobId specified twice.\n"));
1064 rc.jid = ua->argv[i];
1067 case 2: /* client */
1069 if (rc.client_name) {
1070 ua->send_msg(_("Client specified twice.\n"));
1073 rc.client_name = ua->argv[i];
1076 case 4: /* fileset */
1077 if (rc.fileset_name) {
1078 ua->send_msg(_("FileSet specified twice.\n"));
1081 rc.fileset_name = ua->argv[i];
1085 if (rc.level_name) {
1086 ua->send_msg(_("Level specified twice.\n"));
1089 rc.level_name = ua->argv[i];
1092 case 6: /* storage */
1094 if (rc.store_name) {
1095 ua->send_msg(_("Storage specified twice.\n"));
1098 rc.store_name = ua->argv[i];
1101 case 8: /* regexwhere */
1102 if ((rc.regexwhere || rc.where) && !rc.mod) {
1103 ua->send_msg(_("RegexWhere or Where specified twice.\n"));
1106 rc.regexwhere = ua->argv[i];
1107 if (!acl_access_ok(ua, Where_ACL, rc.regexwhere)) {
1108 ua->send_msg(_("No authorization for \"regexwhere\" specification.\n"));
1114 if ((rc.where || rc.regexwhere) && !rc.mod) {
1115 ua->send_msg(_("Where or RegexWhere specified twice.\n"));
1118 rc.where = ua->argv[i];
1119 if (!acl_access_ok(ua, Where_ACL, rc.where)) {
1120 ua->send_msg(_("No authoriztion for \"where\" specification.\n"));
1125 case 10: /* bootstrap */
1126 if (rc.bootstrap && !rc.mod) {
1127 ua->send_msg(_("Bootstrap specified twice.\n"));
1130 rc.bootstrap = ua->argv[i];
1133 case 11: /* replace */
1134 if (rc.replace && !rc.mod) {
1135 ua->send_msg(_("Replace specified twice.\n"));
1138 rc.replace = ua->argv[i];
1142 if (rc.when && !rc.mod) {
1143 ua->send_msg(_("When specified twice.\n"));
1146 rc.when = ua->argv[i];
1149 case 13: /* Priority */
1150 if (rc.Priority && !rc.mod) {
1151 ua->send_msg(_("Priority specified twice.\n"));
1154 rc.Priority = atoi(ua->argv[i]);
1155 if (rc.Priority <= 0) {
1156 ua->send_msg(_("Priority must be positive nonzero setting it to 10.\n"));
1164 case 15: /* Verify Job */
1165 if (rc.verify_job_name) {
1166 ua->send_msg(_("Verify Job specified twice.\n"));
1169 rc.verify_job_name = ua->argv[i];
1172 case 16: /* files */
1173 rc.files = atoi(ua->argv[i]);
1177 case 17: /* catalog */
1178 rc.catalog_name = ua->argv[i];
1182 case 18: /* since */
1183 rc.since = ua->argv[i];
1187 case 19: /* cloned */
1192 case 20: /* write verify list output */
1193 rc.verify_list = ua->argv[i];
1196 case 21: /* Migration Job */
1197 if (rc.previous_job_name) {
1198 ua->send_msg(_("Migration Job specified twice.\n"));
1201 rc.previous_job_name = ua->argv[i];
1206 ua->send_msg(_("Pool specified twice.\n"));
1209 rc.pool_name = ua->argv[i];
1212 case 23: /* backupclient */
1213 if (rc.client_name) {
1214 ua->send_msg(_("Client specified twice.\n"));
1217 rc.client_name = ua->argv[i];
1220 case 24: /* restoreclient */
1221 if (rc.restore_client_name && !rc.mod) {
1222 ua->send_msg(_("Restore Client specified twice.\n"));
1225 rc.restore_client_name = ua->argv[i];
1228 case 25: /* pluginoptions */
1229 ua->send_msg(_("Plugin Options not yet implemented.\n"));
1231 if (rc.plugin_options) {
1232 ua->send_msg(_("Plugin Options specified twice.\n"));
1235 rc.plugin_options = ua->argv[i];
1236 if (!acl_access_ok(ua, PluginOptions_ACL, rc.plugin_options)) {
1237 ua->send_msg(_("No authoriztion for \"PluginOptions\" specification.\n"));
1242 case 26: /* spooldata */
1243 if (rc.spool_data_set) {
1244 ua->send_msg(_("Spool flag specified twice.\n"));
1247 if (is_yesno(ua->argv[i], &rc.spool_data)) {
1248 rc.spool_data_set = 1;
1251 ua->send_msg(_("Invalid spooldata flag.\n"));
1254 case 27: /* comment */
1255 rc.comment = ua->argv[i];
1260 } /* end strcase compare */
1261 } /* end keyword loop */
1263 * End of keyword for loop -- if not found, we got a bogus keyword
1266 Dmsg1(800, "%s not found\n", ua->argk[i]);
1268 * Special case for Job Name, it can be the first
1269 * keyword that has no value.
1271 if (!rc.job_name && !ua->argv[i]) {
1272 rc.job_name = ua->argk[i]; /* use keyword as job name */
1273 Dmsg1(800, "Set jobname=%s\n", rc.job_name);
1275 ua->send_msg(_("Invalid keyword: %s\n"), ua->argk[i]);
1279 } /* end argc loop */
1281 Dmsg0(800, "Done scan.\n");
1283 if (!is_comment_legal(ua, rc.comment)) {
1287 if (rc.catalog_name) {
1288 rc.catalog = GetCatalogResWithName(rc.catalog_name);
1289 if (rc.catalog == NULL) {
1290 ua->error_msg(_("Catalog \"%s\" not found\n"), rc.catalog_name);
1293 if (!acl_access_ok(ua, Catalog_ACL, rc.catalog->name())) {
1294 ua->error_msg(_("No authorization. Catalog \"%s\".\n"), rc.catalog->name());
1298 Dmsg1(800, "Using catalog=%s\n", NPRT(rc.catalog_name));
1302 rc.job = GetJobResWithName(rc.job_name);
1304 if (*rc.job_name != 0) {
1305 ua->send_msg(_("Job \"%s\" not found\n"), rc.job_name);
1307 rc.job = select_job_resource(ua);
1309 Dmsg1(800, "Found job=%s\n", rc.job_name);
1311 } else if (!rc.job) {
1312 ua->send_msg(_("A job name must be specified.\n"));
1313 rc.job = select_job_resource(ua);
1317 } else if (!acl_access_ok(ua, Job_ACL, rc.job->name())) {
1318 ua->error_msg( _("No authorization. Job \"%s\".\n"), rc.job->name());
1323 rc.pool = GetPoolResWithName(rc.pool_name);
1325 if (*rc.pool_name != 0) {
1326 ua->warning_msg(_("Pool \"%s\" not found.\n"), rc.pool_name);
1328 rc.pool = select_pool_resource(ua);
1330 } else if (!rc.pool) {
1331 rc.pool = rc.job->pool; /* use default */
1335 } else if (!acl_access_ok(ua, Pool_ACL, rc.pool->name())) {
1336 ua->error_msg(_("No authorization. Pool \"%s\".\n"), rc.pool->name());
1339 Dmsg1(100, "Using pool %s\n", rc.pool->name());
1341 if (rc.spool_data_set) {
1342 rc.job->spool_data = rc.spool_data;
1344 Dmsg1(900, "Spooling data: %s\n", (rc.job->spool_data ? "Yes" : "No"));
1346 if (rc.store_name) {
1347 rc.store->store = GetStoreResWithName(rc.store_name);
1348 pm_strcpy(rc.store->store_source, _("command line"));
1349 if (!rc.store->store) {
1350 if (*rc.store_name != 0) {
1351 ua->warning_msg(_("Storage \"%s\" not found.\n"), rc.store_name);
1353 rc.store->store = select_storage_resource(ua);
1354 pm_strcpy(rc.store->store_source, _("user selection"));
1356 } else if (!rc.store->store) {
1357 get_job_storage(rc.store, rc.job, NULL); /* use default */
1359 if (!rc.store->store) {
1360 ua->error_msg(_("No storage specified.\n"));
1362 } else if (!acl_access_ok(ua, Storage_ACL, rc.store->store->name())) {
1363 ua->error_msg(_("No authorization. Storage \"%s\".\n"),
1364 rc.store->store->name());
1367 Dmsg1(800, "Using storage=%s\n", rc.store->store->name());
1369 if (rc.client_name) {
1370 rc.client = GetClientResWithName(rc.client_name);
1372 if (*rc.client_name != 0) {
1373 ua->warning_msg(_("Client \"%s\" not found.\n"), rc.client_name);
1375 rc.client = select_client_resource(ua);
1377 } else if (!rc.client) {
1378 rc.client = rc.job->client; /* use default */
1382 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1383 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1387 Dmsg1(800, "Using client=%s\n", rc.client->name());
1389 if (rc.restore_client_name) {
1390 rc.client = GetClientResWithName(rc.restore_client_name);
1392 if (*rc.restore_client_name != 0) {
1393 ua->warning_msg(_("Restore Client \"%s\" not found.\n"), rc.restore_client_name);
1395 rc.client = select_client_resource(ua);
1397 } else if (!rc.client) {
1398 rc.client = rc.job->client; /* use default */
1402 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1403 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1407 Dmsg1(800, "Using restore client=%s\n", rc.client->name());
1410 if (rc.fileset_name) {
1411 rc.fileset = GetFileSetResWithName(rc.fileset_name);
1413 ua->send_msg(_("FileSet \"%s\" not found.\n"), rc.fileset_name);
1414 rc.fileset = select_fileset_resource(ua);
1416 } else if (!rc.fileset) {
1417 rc.fileset = rc.job->fileset; /* use default */
1421 } else if (!acl_access_ok(ua, FileSet_ACL, rc.fileset->name())) {
1422 ua->send_msg(_("No authorization. FileSet \"%s\".\n"),
1423 rc.fileset->name());
1427 if (rc.verify_job_name) {
1428 rc.verify_job = GetJobResWithName(rc.verify_job_name);
1429 if (!rc.verify_job) {
1430 ua->send_msg(_("Verify Job \"%s\" not found.\n"), rc.verify_job_name);
1431 rc.verify_job = select_job_resource(ua);
1433 } else if (!rc.verify_job) {
1434 rc.verify_job = rc.job->verify_job;
1437 if (rc.previous_job_name) {
1438 rc.previous_job = GetJobResWithName(rc.previous_job_name);
1439 if (!rc.previous_job) {
1440 ua->send_msg(_("Migration Job \"%s\" not found.\n"), rc.previous_job_name);
1441 rc.previous_job = select_job_resource(ua);
1444 rc.previous_job = rc.job->verify_job;