2 Bacula® - The Network Backup Solution
4 Copyright (C) 2001-2008 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
30 * Bacula Director -- Run Command
32 * Kern Sibbald, December MMI
42 char *job_name, *level_name, *jid, *store_name, *pool_name;
43 char *where, *fileset_name, *client_name, *bootstrap, *regexwhere;
44 char *restore_client_name;
46 char *when, *verify_job_name, *catalog_name;
47 char *previous_job_name;
49 const char *verify_list;
64 run_ctx() { memset(this, 0, sizeof(run_ctx));
65 store = new USTORE; };
66 ~run_ctx() { delete store; };
69 /* Forward referenced subroutines */
70 static void select_job_level(UAContext *ua, JCR *jcr);
71 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job,
72 const char *verify_list, char *jid, const char *replace,
74 static void select_where_regexp(UAContext *ua, JCR *jcr);
75 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc);
77 /* Imported variables */
78 extern struct s_kw ReplaceOptions[];
81 * For Backup and Verify Jobs
82 * run [job=]<job-name> level=<level-name>
91 int run_cmd(UAContext *ua, const char *cmd)
97 if (!open_client_db(ua)) {
101 if (!scan_command_line_arguments(ua, rc)) {
105 if (find_arg(ua, NT_("fdcalled")) > 0) {
106 jcr->file_bsock = dup_bsock(ua->UA_sock);
112 * Create JCR to run job. NOTE!!! after this point, free_jcr()
116 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
117 set_jcr_defaults(jcr, rc.job);
118 jcr->unlink_bsr = ua->jcr->unlink_bsr; /* copy unlink flag from caller */
119 ua->jcr->unlink_bsr = false;
122 jcr->verify_job = rc.verify_job;
123 jcr->previous_job = rc.previous_job;
125 if (jcr->pool != jcr->job->pool) {
126 pm_strcpy(jcr->pool_source, _("User input"));
128 set_rwstorage(jcr, rc.store);
129 jcr->client = rc.client;
130 pm_strcpy(jcr->client_name, rc.client->name());
131 jcr->fileset = rc.fileset;
132 jcr->ExpectedFiles = rc.files;
134 jcr->catalog = rc.catalog;
135 pm_strcpy(jcr->catalog_source, _("User input"));
141 jcr->where = bstrdup(rc.where);
146 if (jcr->RegexWhere) {
147 free(jcr->RegexWhere);
149 jcr->RegexWhere = bstrdup(rc.regexwhere);
150 rc.regexwhere = NULL;
154 jcr->sched_time = str_to_utime(rc.when);
155 if (jcr->sched_time == 0) {
156 ua->send_msg(_("Invalid time, using current time.\n"));
157 jcr->sched_time = time(NULL);
163 if (jcr->RestoreBootstrap) {
164 free(jcr->RestoreBootstrap);
166 jcr->RestoreBootstrap = bstrdup(rc.bootstrap);
172 for (i=0; ReplaceOptions[i].name; i++) {
173 if (strcasecmp(rc.replace, ReplaceOptions[i].name) == 0) {
174 jcr->replace = ReplaceOptions[i].token;
178 ua->send_msg(_("Invalid replace option: %s\n"), rc.replace);
181 } else if (rc.job->replace) {
182 jcr->replace = rc.job->replace;
184 jcr->replace = REPLACE_ALWAYS;
189 jcr->JobPriority = rc.Priority;
195 jcr->stime = get_pool_memory(PM_MESSAGE);
197 pm_strcpy(jcr->stime, rc.since);
202 jcr->cloned = rc.cloned;
207 /* If pool changed, update migration write storage */
208 if (jcr->JobType == JT_MIGRATE) {
209 if (!set_migration_wstorage(jcr, rc.pool)) {
213 rc.replace = ReplaceOptions[0].name;
214 for (i=0; ReplaceOptions[i].name; i++) {
215 if (ReplaceOptions[i].token == jcr->replace) {
216 rc.replace = ReplaceOptions[i].name;
220 if (!get_level_from_name(jcr, rc.level_name)) {
221 ua->send_msg(_("Level %s not valid.\n"), rc.level_name);
224 rc.level_name = NULL;
227 /* Note, this is also MigrateJobId */
228 jcr->RestoreJobId = str_to_int64(rc.jid);
232 /* Run without prompting? */
233 if (ua->batch || find_arg(ua, NT_("yes")) > 0) {
238 * Prompt User to see if all run job parameters are correct, and
239 * allow him to modify them.
241 if (!display_job_parameters(ua, jcr, rc.job, rc.verify_list, rc.jid, rc.replace,
246 if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
250 if (strncasecmp(ua->cmd, ".mod ", 5) == 0 ||
251 (strncasecmp(ua->cmd, "mod ", 4) == 0 && strlen(ua->cmd) > 6)) {
254 if (!scan_command_line_arguments(ua, rc)) {
261 * At user request modify parameters of job to be run.
263 if (ua->cmd[0] != 0 && strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0) {
266 start_prompt(ua, _("Parameters to modify:\n"));
267 add_prompt(ua, _("Level")); /* 0 */
268 add_prompt(ua, _("Storage")); /* 1 */
269 add_prompt(ua, _("Job")); /* 2 */
270 add_prompt(ua, _("FileSet")); /* 3 */
271 if (jcr->JobType == JT_RESTORE) {
272 add_prompt(ua, _("Restore Client")); /* 4 */
274 add_prompt(ua, _("Client")); /* 4 */
276 add_prompt(ua, _("When")); /* 5 */
277 add_prompt(ua, _("Priority")); /* 6 */
278 if (jcr->JobType == JT_BACKUP ||
279 jcr->JobType == JT_MIGRATE ||
280 jcr->JobType == JT_VERIFY) {
281 add_prompt(ua, _("Pool")); /* 7 */
282 if (jcr->JobType == JT_VERIFY) {
283 add_prompt(ua, _("Verify Job")); /* 8 */
285 } else if (jcr->JobType == JT_RESTORE) {
286 add_prompt(ua, _("Bootstrap")); /* 7 */
287 add_prompt(ua, _("Where")); /* 8 */
288 add_prompt(ua, _("File Relocation"));/* 9 */
289 add_prompt(ua, _("Replace")); /* 10 */
290 add_prompt(ua, _("JobId")); /* 11 */
292 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
295 select_job_level(ua, jcr);
299 rc.store->store = select_storage_resource(ua);
300 if (rc.store->store) {
301 pm_strcpy(rc.store->store_source, _("user selection"));
302 set_rwstorage(jcr, rc.store);
308 rc.job = select_job_resource(ua);
311 set_jcr_defaults(jcr, rc.job);
317 rc.fileset = select_fileset_resource(ua);
319 jcr->fileset = rc.fileset;
325 rc.client = select_client_resource(ua);
327 jcr->client = rc.client;
333 if (!get_cmd(ua, _("Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now): "))) {
336 if (ua->cmd[0] == 0) {
337 jcr->sched_time = time(NULL);
339 jcr->sched_time = str_to_utime(ua->cmd);
340 if (jcr->sched_time == 0) {
341 ua->send_msg(_("Invalid time, using current time.\n"));
342 jcr->sched_time = time(NULL);
348 if (!get_pint(ua, _("Enter new Priority: "))) {
351 if (ua->pint32_val == 0) {
352 ua->send_msg(_("Priority must be a positive integer.\n"));
354 jcr->JobPriority = ua->pint32_val;
358 /* Pool or Bootstrap depending on JobType */
359 if (jcr->JobType == JT_BACKUP ||
360 jcr->JobType == JT_MIGRATE ||
361 jcr->JobType == JT_VERIFY) { /* Pool */
362 rc.pool = select_pool_resource(ua);
365 Dmsg1(100, "Set new pool=%s\n", jcr->pool->name());
372 if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
375 if (jcr->RestoreBootstrap) {
376 free(jcr->RestoreBootstrap);
377 jcr->RestoreBootstrap = NULL;
379 if (ua->cmd[0] != 0) {
380 jcr->RestoreBootstrap = bstrdup(ua->cmd);
381 fd = fopen(jcr->RestoreBootstrap, "rb");
384 ua->send_msg(_("Warning cannot open %s: ERR=%s\n"),
385 jcr->RestoreBootstrap, be.bstrerror());
386 free(jcr->RestoreBootstrap);
387 jcr->RestoreBootstrap = NULL;
395 if (jcr->JobType == JT_VERIFY) {
396 rc.verify_job = select_job_resource(ua);
398 jcr->verify_job = rc.verify_job;
403 if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) {
406 if (jcr->RegexWhere) { /* cannot use regexwhere and where */
407 free(jcr->RegexWhere);
408 jcr->RegexWhere = NULL;
414 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
417 jcr->where = bstrdup(ua->cmd);
420 /* File relocation */
421 select_where_regexp(ua, jcr);
425 start_prompt(ua, _("Replace:\n"));
426 for (i=0; ReplaceOptions[i].name; i++) {
427 add_prompt(ua, ReplaceOptions[i].name);
429 opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
431 rc.replace = ReplaceOptions[opt].name;
432 jcr->replace = ReplaceOptions[opt].token;
437 rc.jid = NULL; /* force reprompt */
438 jcr->RestoreJobId = 0;
439 if (jcr->RestoreBootstrap) {
440 ua->send_msg(_("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
443 case -1: /* error or cancel */
451 if (ua->cmd[0] == 0 || strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
453 Dmsg1(800, "Calling run_job job=%x\n", jcr->job);
456 Dmsg3(100, "JobId=%u using pool %s priority=%d\n", (int)jcr->JobId,
457 jcr->pool->name(), jcr->JobPriority);
458 JobId = run_job(jcr);
459 Dmsg4(100, "JobId=%u NewJobId=%d using pool %s priority=%d\n", (int)jcr->JobId,
460 JobId, jcr->pool->name(), jcr->JobPriority);
461 free_jcr(jcr); /* release jcr */
463 ua->error_msg(_("Job failed.\n"));
466 ua->send_msg(_("Job queued. JobId=%s\n"), edit_int64(JobId, ed1));
472 ua->send_msg(_("Job not run.\n"));
474 return 0; /* do not run */
477 static void select_where_regexp(UAContext *ua, JCR *jcr)
480 char *strip_prefix, *add_prefix, *add_suffix, *rwhere;
481 strip_prefix = add_suffix = rwhere = add_prefix = NULL;
484 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s\n"),
485 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix));
487 start_prompt(ua, _("This will replace your current Where value\n"));
488 add_prompt(ua, _("Strip prefix")); /* 0 */
489 add_prompt(ua, _("Add prefix")); /* 1 */
490 add_prompt(ua, _("Add file suffix")); /* 2 */
491 add_prompt(ua, _("Enter a regexp")); /* 3 */
492 add_prompt(ua, _("Test filename manipulation")); /* 4 */
493 add_prompt(ua, _("Use this ?")); /* 5 */
495 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
498 if (get_cmd(ua, _("Please enter path prefix to strip: "))) {
499 if (strip_prefix) bfree(strip_prefix);
500 strip_prefix = bstrdup(ua->cmd);
506 if (get_cmd(ua, _("Please enter path prefix to add (/ for none): "))) {
507 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
511 if (add_prefix) bfree(add_prefix);
512 add_prefix = bstrdup(ua->cmd);
517 if (get_cmd(ua, _("Please enter file suffix to add: "))) {
518 if (add_suffix) bfree(add_suffix);
519 add_suffix = bstrdup(ua->cmd);
524 if (get_cmd(ua, _("Please enter a valid regexp (!from!to!): "))) {
525 if (rwhere) bfree(rwhere);
526 rwhere = bstrdup(ua->cmd);
535 if (rwhere && rwhere[0] != '\0') {
536 regs = get_bregexps(rwhere);
537 ua->send_msg(_("regexwhere=%s\n"), NPRT(rwhere));
539 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
540 regexp = (char *) bmalloc (len * sizeof(char));
541 bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix);
542 regs = get_bregexps(regexp);
543 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s result=%s\n"),
544 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix), NPRT(regexp));
550 ua->send_msg(_("Cannot use your regexp\n"));
554 while (get_cmd(ua, _("Please enter filename to test: "))) {
555 apply_bregexps(ua->cmd, regs, &result);
556 ua->send_msg(_("%s -> %s\n"), ua->cmd, result);
565 case -1: /* error or cancel */
571 /* replace the existing where */
577 /* replace the existing regexwhere */
578 if (jcr->RegexWhere) {
579 bfree(jcr->RegexWhere);
580 jcr->RegexWhere = NULL;
584 jcr->RegexWhere = bstrdup(rwhere);
585 } else if (strip_prefix || add_prefix || add_suffix) {
586 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
587 jcr->RegexWhere = (char *) bmalloc(len*sizeof(char));
588 bregexp_build_where(jcr->RegexWhere, len, strip_prefix, add_prefix, add_suffix);
591 regs = get_bregexps(jcr->RegexWhere);
596 if (jcr->RegexWhere) {
597 bfree(jcr->RegexWhere);
598 jcr->RegexWhere = NULL;
600 ua->send_msg(_("Cannot use your regexp.\n"));
604 if (strip_prefix) bfree(strip_prefix);
605 if (add_prefix) bfree(add_prefix);
606 if (add_suffix) bfree(add_suffix);
607 if (rwhere) bfree(rwhere);
610 static void select_job_level(UAContext *ua, JCR *jcr)
612 if (jcr->JobType == JT_BACKUP) {
613 start_prompt(ua, _("Levels:\n"));
614 add_prompt(ua, _("Base"));
615 add_prompt(ua, _("Full"));
616 add_prompt(ua, _("Incremental"));
617 add_prompt(ua, _("Differential"));
618 add_prompt(ua, _("Since"));
619 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
621 jcr->JobLevel = L_BASE;
624 jcr->JobLevel = L_FULL;
627 jcr->JobLevel = L_INCREMENTAL;
630 jcr->JobLevel = L_DIFFERENTIAL;
633 jcr->JobLevel = L_SINCE;
638 } else if (jcr->JobType == JT_VERIFY) {
639 start_prompt(ua, _("Levels:\n"));
640 add_prompt(ua, _("Initialize Catalog"));
641 add_prompt(ua, _("Verify Catalog"));
642 add_prompt(ua, _("Verify Volume to Catalog"));
643 add_prompt(ua, _("Verify Disk to Catalog"));
644 add_prompt(ua, _("Verify Volume Data (not yet implemented)"));
645 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
647 jcr->JobLevel = L_VERIFY_INIT;
650 jcr->JobLevel = L_VERIFY_CATALOG;
653 jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG;
656 jcr->JobLevel = L_VERIFY_DISK_TO_CATALOG;
659 jcr->JobLevel = L_VERIFY_DATA;
665 ua->warning_msg(_("Level not appropriate for this Job. Cannot be changed.\n"));
670 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char *verify_list,
671 char *jid, const char *replace, char *client_name)
673 Dmsg1(800, "JobType=%c\n", jcr->JobType);
674 switch (jcr->JobType) {
676 char dt[MAX_TIME_LENGTH];
678 if (ua->api) ua->signal(BNET_RUN_CMD);
679 ua->send_msg(_("Run %s job\n"
688 jcr->fileset->name(),
689 NPRT(jcr->client->name()),
690 jcr->wstore?jcr->wstore->name():"*None*",
691 bstrutime(dt, sizeof(dt), jcr->sched_time),
693 jcr->JobLevel = L_FULL;
697 if (jcr->JobType == JT_BACKUP) {
698 if (ua->api) ua->signal(BNET_RUN_CMD);
699 ua->send_msg(_("Run %s job\n"
704 "Pool: %s (From %s)\n"
705 "Storage: %s (From %s)\n"
710 level_to_str(jcr->JobLevel),
712 jcr->fileset->name(),
713 NPRT(jcr->pool->name()), jcr->pool_source,
714 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
715 bstrutime(dt, sizeof(dt), jcr->sched_time),
717 } else { /* JT_VERIFY */
719 if (jcr->verify_job) {
720 Name = jcr->verify_job->name();
725 verify_list = job->WriteVerifyList;
730 if (ua->api) ua->signal(BNET_RUN_CMD);
731 ua->send_msg(_("Run %s job\n"
736 "Pool: %s (From %s)\n"
737 "Storage: %s (From %s)\n"
744 level_to_str(jcr->JobLevel),
746 jcr->fileset->name(),
747 NPRT(jcr->pool->name()), jcr->pool_source,
748 jcr->rstore->name(), jcr->rstore_source,
751 bstrutime(dt, sizeof(dt), jcr->sched_time),
756 if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
758 jcr->RestoreJobId = str_to_int64(jid);
760 if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
763 jcr->RestoreJobId = ua->int64_val;
766 jcr->JobLevel = L_FULL; /* default level */
767 Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId);
768 if (jcr->RestoreJobId == 0) {
769 if (ua->api) ua->signal(BNET_RUN_CMD);
770 /* RegexWhere is take before RestoreWhere */
771 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
772 ua->send_msg(_("Run Restore job\n"
778 "Backup Client: %s\n"
779 "Restore Client: %s\n"
785 NPRT(jcr->RestoreBootstrap),
786 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
788 jcr->fileset->name(),
792 bstrutime(dt, sizeof(dt), jcr->sched_time),
793 jcr->catalog->name(),
797 ua->send_msg(_("Run Restore job\n"
803 "Backup Client: %s\n"
804 "Restore Client: %s\n"
810 NPRT(jcr->RestoreBootstrap),
811 jcr->where?jcr->where:NPRT(job->RestoreWhere),
813 jcr->fileset->name(),
817 bstrutime(dt, sizeof(dt), jcr->sched_time),
818 jcr->catalog->name(),
823 if (ua->api) ua->signal(BNET_RUN_CMD);
824 ua->send_msg(_("Run Restore job\n"
828 NPRT(jcr->RestoreBootstrap));
830 /* RegexWhere is take before RestoreWhere */
831 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
832 ua->send_msg(_("RegexWhere: %s\n"),
833 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere);
835 ua->send_msg(_("Where: %s\n"),
836 jcr->where?jcr->where:NPRT(job->RestoreWhere));
839 ua->send_msg(_("Replace: %s\n"
849 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
850 bstrutime(dt, sizeof(dt), jcr->sched_time),
851 jcr->catalog->name(),
856 jcr->JobLevel = L_FULL; /* default level */
857 if (ua->api) ua->signal(BNET_RUN_CMD);
858 ua->send_msg(_("Run Migration job\n"
863 "Pool: %s (From %s)\n"
864 "Read Storage: %s (From %s)\n"
865 "Write Storage: %s (From %s)\n"
871 NPRT(jcr->RestoreBootstrap),
873 jcr->fileset->name(),
874 NPRT(jcr->pool->name()), jcr->pool_source,
875 jcr->rstore->name(), jcr->rstore_source,
876 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
877 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
878 bstrutime(dt, sizeof(dt), jcr->sched_time),
879 jcr->catalog->name(),
883 ua->error_msg(_("Unknown Job Type=%d\n"), jcr->JobType);
890 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc)
894 static const char *kw[] = { /* command line arguments */
895 "job", /* Used in a switch() */
903 "regexwhere", /* 8 where string as a bregexp */
905 "bootstrap", /* 10 */
909 "yes", /* 14 -- if you change this change YES_POS too */
910 "verifyjob", /* 15 */
911 "files", /* 16 number of files to restore */
912 "catalog", /* 17 override catalog */
913 "since", /* 18 since */
914 "cloned", /* 19 cloned */
915 "verifylist", /* 20 verify output list */
916 "migrationjob", /* 21 migration job name */
918 "backupclient", /* 23 */
919 "restoreclient", /* 24 */
924 rc.catalog_name = NULL;
927 rc.store_name = NULL;
928 rc.client_name = NULL;
929 rc.restore_client_name = NULL;
930 rc.fileset_name = NULL;
931 rc.verify_job_name = NULL;
932 rc.previous_job_name = NULL;
935 for (i=1; i<ua->argc; i++) {
936 Dmsg2(800, "Doing arg %d = %s\n", i, ua->argk[i]);
938 /* Keep looking until we find a good keyword */
939 for (j=0; !kw_ok && kw[j]; j++) {
940 if (strcasecmp(ua->argk[i], kw[j]) == 0) {
941 /* Note, yes and run have no value, so do not fail */
942 if (!ua->argv[i] && j != YES_POS /*yes*/) {
943 ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]);
946 Dmsg1(800, "Got keyword=%s\n", NPRT(kw[j]));
950 ua->send_msg(_("Job name specified twice.\n"));
953 rc.job_name = ua->argv[i];
957 if (rc.jid && !rc.mod) {
958 ua->send_msg(_("JobId specified twice.\n"));
961 rc.jid = ua->argv[i];
966 if (rc.client_name) {
967 ua->send_msg(_("Client specified twice.\n"));
970 rc.client_name = ua->argv[i];
973 case 4: /* fileset */
974 if (rc.fileset_name) {
975 ua->send_msg(_("FileSet specified twice.\n"));
978 rc.fileset_name = ua->argv[i];
983 ua->send_msg(_("Level specified twice.\n"));
986 rc.level_name = ua->argv[i];
989 case 6: /* storage */
992 ua->send_msg(_("Storage specified twice.\n"));
995 rc.store_name = ua->argv[i];
998 case 8: /* regexwhere */
999 if ((rc.regexwhere || rc.where) && !rc.mod) {
1000 ua->send_msg(_("RegexWhere or Where specified twice.\n"));
1003 rc.regexwhere = ua->argv[i];
1004 if (!acl_access_ok(ua, Where_ACL, rc.regexwhere)) {
1005 ua->send_msg(_("No authorization for \"regexwhere\" specification.\n"));
1011 if ((rc.where || rc.regexwhere) && !rc.mod) {
1012 ua->send_msg(_("Where or RegexWhere specified twice.\n"));
1015 rc.where = ua->argv[i];
1016 if (!acl_access_ok(ua, Where_ACL, rc.where)) {
1017 ua->send_msg(_("No authoriztion for \"where\" specification.\n"));
1022 case 10: /* bootstrap */
1023 if (rc.bootstrap && !rc.mod) {
1024 ua->send_msg(_("Bootstrap specified twice.\n"));
1027 rc.bootstrap = ua->argv[i];
1030 case 11: /* replace */
1031 if (rc.replace && !rc.mod) {
1032 ua->send_msg(_("Replace specified twice.\n"));
1035 rc.replace = ua->argv[i];
1039 if (rc.when && !rc.mod) {
1040 ua->send_msg(_("When specified twice.\n"));
1043 rc.when = ua->argv[i];
1046 case 13: /* Priority */
1047 if (rc.Priority && !rc.mod) {
1048 ua->send_msg(_("Priority specified twice.\n"));
1051 rc.Priority = atoi(ua->argv[i]);
1052 if (rc.Priority <= 0) {
1053 ua->send_msg(_("Priority must be positive nonzero setting it to 10.\n"));
1061 case 15: /* Verify Job */
1062 if (rc.verify_job_name) {
1063 ua->send_msg(_("Verify Job specified twice.\n"));
1066 rc.verify_job_name = ua->argv[i];
1069 case 16: /* files */
1070 rc.files = atoi(ua->argv[i]);
1074 case 17: /* catalog */
1075 rc.catalog_name = ua->argv[i];
1079 case 18: /* since */
1080 rc.since = ua->argv[i];
1084 case 19: /* cloned */
1089 case 20: /* write verify list output */
1090 rc.verify_list = ua->argv[i];
1093 case 21: /* Migration Job */
1094 if (rc.previous_job_name) {
1095 ua->send_msg(_("Migration Job specified twice.\n"));
1098 rc.previous_job_name = ua->argv[i];
1103 ua->send_msg(_("Pool specified twice.\n"));
1106 rc.pool_name = ua->argv[i];
1109 case 23: /* backupclient */
1110 if (rc.client_name) {
1111 ua->send_msg(_("Client specified twice.\n"));
1114 rc.client_name = ua->argv[i];
1117 case 24: /* restoreclient */
1118 if (rc.restore_client_name && !rc.mod) {
1119 ua->send_msg(_("Restore Client specified twice.\n"));
1122 rc.restore_client_name = ua->argv[i];
1128 } /* end strcase compare */
1129 } /* end keyword loop */
1131 * End of keyword for loop -- if not found, we got a bogus keyword
1134 Dmsg1(800, "%s not found\n", ua->argk[i]);
1136 * Special case for Job Name, it can be the first
1137 * keyword that has no value.
1139 if (!rc.job_name && !ua->argv[i]) {
1140 rc.job_name = ua->argk[i]; /* use keyword as job name */
1141 Dmsg1(800, "Set jobname=%s\n", rc.job_name);
1143 ua->send_msg(_("Invalid keyword: %s\n"), ua->argk[i]);
1147 } /* end argc loop */
1149 Dmsg0(800, "Done scan.\n");
1151 if (rc.catalog_name) {
1152 rc.catalog = GetCatalogResWithName(rc.catalog_name);
1153 if (rc.catalog == NULL) {
1154 ua->error_msg(_("Catalog \"%s\" not found\n"), rc.catalog_name);
1157 if (!acl_access_ok(ua, Catalog_ACL, rc.catalog->name())) {
1158 ua->error_msg(_("No authorization. Catalog \"%s\".\n"), rc.catalog->name());
1162 Dmsg1(800, "Using catalog=%s\n", NPRT(rc.catalog_name));
1166 rc.job = GetJobResWithName(rc.job_name);
1168 if (*rc.job_name != 0) {
1169 ua->send_msg(_("Job \"%s\" not found\n"), rc.job_name);
1171 rc.job = select_job_resource(ua);
1173 Dmsg1(800, "Found job=%s\n", rc.job_name);
1175 } else if (!rc.job) {
1176 ua->send_msg(_("A job name must be specified.\n"));
1177 rc.job = select_job_resource(ua);
1181 } else if (!acl_access_ok(ua, Job_ACL, rc.job->name())) {
1182 ua->error_msg( _("No authorization. Job \"%s\".\n"), rc.job->name());
1187 rc.pool = GetPoolResWithName(rc.pool_name);
1189 if (*rc.pool_name != 0) {
1190 ua->warning_msg(_("Pool \"%s\" not found.\n"), rc.pool_name);
1192 rc.pool = select_pool_resource(ua);
1194 } else if (!rc.pool) {
1195 rc.pool = rc.job->pool; /* use default */
1199 } else if (!acl_access_ok(ua, Pool_ACL, rc.pool->name())) {
1200 ua->error_msg(_("No authorization. Pool \"%s\".\n"), rc.pool->name());
1203 Dmsg1(100, "Using pool %s\n", rc.pool->name());
1205 if (rc.store_name) {
1206 rc.store->store = GetStoreResWithName(rc.store_name);
1207 pm_strcpy(rc.store->store_source, _("command line"));
1208 if (!rc.store->store) {
1209 if (*rc.store_name != 0) {
1210 ua->warning_msg(_("Storage \"%s\" not found.\n"), rc.store_name);
1212 rc.store->store = select_storage_resource(ua);
1213 pm_strcpy(rc.store->store_source, _("user selection"));
1215 } else if (!rc.store->store) {
1216 get_job_storage(rc.store, rc.job, NULL); /* use default */
1218 if (!rc.store->store) {
1219 ua->error_msg(_("No storage specified.\n"));
1221 } else if (!acl_access_ok(ua, Storage_ACL, rc.store->store->name())) {
1222 ua->error_msg(_("No authorization. Storage \"%s\".\n"),
1223 rc.store->store->name());
1226 Dmsg1(800, "Using storage=%s\n", rc.store->store->name());
1228 if (rc.client_name) {
1229 rc.client = GetClientResWithName(rc.client_name);
1231 if (*rc.client_name != 0) {
1232 ua->warning_msg(_("Client \"%s\" not found.\n"), rc.client_name);
1234 rc.client = select_client_resource(ua);
1236 } else if (!rc.client) {
1237 rc.client = rc.job->client; /* use default */
1241 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1242 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1246 Dmsg1(800, "Using client=%s\n", rc.client->name());
1248 if (rc.restore_client_name) {
1249 rc.client = GetClientResWithName(rc.restore_client_name);
1251 if (*rc.restore_client_name != 0) {
1252 ua->warning_msg(_("Restore Client \"%s\" not found.\n"), rc.restore_client_name);
1254 rc.client = select_client_resource(ua);
1256 } else if (!rc.client) {
1257 rc.client = rc.job->client; /* use default */
1261 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1262 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1266 Dmsg1(800, "Using restore client=%s\n", rc.client->name());
1269 if (rc.fileset_name) {
1270 rc.fileset = GetFileSetResWithName(rc.fileset_name);
1272 ua->send_msg(_("FileSet \"%s\" not found.\n"), rc.fileset_name);
1273 rc.fileset = select_fileset_resource(ua);
1275 } else if (!rc.fileset) {
1276 rc.fileset = rc.job->fileset; /* use default */
1280 } else if (!acl_access_ok(ua, FileSet_ACL, rc.fileset->name())) {
1281 ua->send_msg(_("No authorization. FileSet \"%s\".\n"),
1282 rc.fileset->name());
1286 if (rc.verify_job_name) {
1287 rc.verify_job = GetJobResWithName(rc.verify_job_name);
1288 if (!rc.verify_job) {
1289 ua->send_msg(_("Verify Job \"%s\" not found.\n"), rc.verify_job_name);
1290 rc.verify_job = select_job_resource(ua);
1292 } else if (!rc.verify_job) {
1293 rc.verify_job = rc.job->verify_job;
1296 if (rc.previous_job_name) {
1297 rc.previous_job = GetJobResWithName(rc.previous_job_name);
1298 if (!rc.previous_job) {
1299 ua->send_msg(_("Migration Job \"%s\" not found.\n"), rc.previous_job_name);
1300 rc.previous_job = select_job_resource(ua);
1303 rc.previous_job = rc.job->verify_job;