]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_run.c
Display job information on jobid in Verify screen
[bacula/bacula] / bacula / src / dird / ua_run.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2001-2010 Free Software Foundation Europe e.V.
5
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 three of the GNU Affero General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
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.
17
18    You should have received a copy of the GNU Affero 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
21    02110-1301, USA.
22
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.
27 */
28 /*
29  *
30  *   Bacula Director -- Run Command
31  *
32  *     Kern Sibbald, December MMI
33  *
34  */
35
36 #include "bacula.h"
37 #include "dird.h"
38
39 class run_ctx {
40 public:
41    char *job_name, *level_name, *jid, *store_name, *pool_name;
42    char *where, *fileset_name, *client_name, *bootstrap, *regexwhere;
43    char *restore_client_name, *comment;
44    const char *replace;
45    char *when, *verify_job_name, *catalog_name;
46    char *previous_job_name;
47    char *since;
48    char *plugin_options;
49    const char *verify_list;
50    JOB *job;
51    JOB *verify_job;
52    JOB *previous_job;
53    USTORE *store;
54    CLIENT *client;
55    FILESET *fileset;
56    POOL *pool;
57    CAT *catalog;
58    int Priority;
59    int files;
60    bool cloned;
61    bool mod;
62    int spool_data;
63    bool spool_data_set;
64
65    /* Methods */
66    run_ctx() { memset(this, 0, sizeof(run_ctx)); 
67                store = new USTORE; };
68    ~run_ctx() { delete store; };
69 };
70
71 /* Forward referenced subroutines */
72 static void select_job_level(UAContext *ua, JCR *jcr);
73 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, 
74                 const char *verify_list, char *jid, const char *replace,
75                 char *client_name);
76 static void select_where_regexp(UAContext *ua, JCR *jcr);
77 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc);
78 static bool reset_restore_context(UAContext *ua, JCR *jcr, run_ctx &rc);
79 static int modify_job_parameters(UAContext *ua, JCR *jcr, run_ctx &rc);
80
81 /* Imported variables */
82 extern struct s_kw ReplaceOptions[];
83
84 /*
85  * For Backup and Verify Jobs
86  *     run [job=]<job-name> level=<level-name>
87  *
88  * For Restore Jobs
89  *     run <job-name> 
90  *
91  *  Returns: 0 on error
92  *           JobId if OK
93  *
94  */
95 int run_cmd(UAContext *ua, const char *cmd)
96 {
97    JCR *jcr = NULL;
98    run_ctx rc;
99    int status;
100
101    if (!open_client_db(ua)) {
102       return 1;
103    }
104
105    if (!scan_command_line_arguments(ua, rc)) {
106       return 0;
107    }
108
109    if (find_arg(ua, NT_("fdcalled")) > 0) {
110       jcr->file_bsock = dup_bsock(ua->UA_sock);
111       ua->quit = true;
112    }
113
114    /*
115     * Create JCR to run job.  NOTE!!! after this point, free_jcr()
116     *  before returning.
117     */
118    if (!jcr) {
119       jcr = new_jcr(sizeof(JCR), dird_free_jcr);
120       set_jcr_defaults(jcr, rc.job);
121       jcr->unlink_bsr = ua->jcr->unlink_bsr;    /* copy unlink flag from caller */
122       ua->jcr->unlink_bsr = false;
123    }
124    /* Transfer JobIds to new restore Job */
125    if (ua->jcr->JobIds) {
126       jcr->JobIds = ua->jcr->JobIds;
127       ua->jcr->JobIds = NULL;
128    }
129
130 try_again:
131    if (!reset_restore_context(ua, jcr, rc)) {
132       goto bail_out;
133    }
134
135
136    /* Run without prompting? */
137    if (ua->batch || find_arg(ua, NT_("yes")) > 0) {
138       goto start_job;
139    }
140
141    /*
142     * Prompt User to see if all run job parameters are correct, and
143     *   allow him to modify them.
144     */
145    if (!display_job_parameters(ua, jcr, rc.job, rc.verify_list, rc.jid, rc.replace,
146         rc.client_name)) {
147       goto bail_out;
148    }
149
150    if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
151       goto bail_out;
152    }
153
154    if (strncasecmp(ua->cmd, ".mod ", 5) == 0 || 
155        (strncasecmp(ua->cmd, "mod ", 4) == 0 && strlen(ua->cmd) > 6)) {
156       parse_ua_args(ua);
157       rc.mod = true;
158       if (!scan_command_line_arguments(ua, rc)) {
159          return 0;
160       }
161       goto try_again;
162    }
163
164    /* Allow the user to modify the settings */
165    status = modify_job_parameters(ua, jcr, rc);
166    switch (status) {
167    case 0:
168       goto try_again;
169    case 1:
170       break;
171    case -1:
172       goto bail_out;
173    }
174
175
176    if (ua->cmd[0] == 0 || strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
177       JobId_t JobId;
178       Dmsg1(800, "Calling run_job job=%x\n", jcr->job);
179
180 start_job:
181       Dmsg3(100, "JobId=%u using pool %s priority=%d\n", (int)jcr->JobId, 
182             jcr->pool->name(), jcr->JobPriority);
183       Dmsg1(900, "Running a job; its spool_data = %d\n", jcr->spool_data);
184       JobId = run_job(jcr);
185       Dmsg4(100, "JobId=%u NewJobId=%d using pool %s priority=%d\n", (int)jcr->JobId, 
186             JobId, jcr->pool->name(), jcr->JobPriority);
187       free_jcr(jcr);                  /* release jcr */
188       if (JobId == 0) {
189          ua->error_msg(_("Job failed.\n"));
190       } else {
191          char ed1[50];
192          ua->send_msg(_("Job queued. JobId=%s\n"), edit_int64(JobId, ed1));
193       }
194       return JobId;
195    }
196
197 bail_out:
198    ua->send_msg(_("Job not run.\n"));
199    free_jcr(jcr);
200    return 0;                       /* do not run */
201 }
202
203 int modify_job_parameters(UAContext *ua, JCR *jcr, run_ctx &rc)
204 {
205    int i, opt;
206    /*
207     * At user request modify parameters of job to be run.
208     */
209    if (ua->cmd[0] != 0 && strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0) {
210       FILE *fd;
211
212       start_prompt(ua, _("Parameters to modify:\n"));
213       add_prompt(ua, _("Level"));            /* 0 */
214       add_prompt(ua, _("Storage"));          /* 1 */
215       add_prompt(ua, _("Job"));              /* 2 */
216       add_prompt(ua, _("FileSet"));          /* 3 */
217       if (jcr->getJobType() == JT_RESTORE) {
218          add_prompt(ua, _("Restore Client"));   /* 4 */
219       } else {
220          add_prompt(ua, _("Client"));        /* 4 */
221       }
222       add_prompt(ua, _("When"));             /* 5 */
223       add_prompt(ua, _("Priority"));         /* 6 */
224       if (jcr->getJobType() == JT_BACKUP ||
225           jcr->getJobType() == JT_COPY ||
226           jcr->getJobType() == JT_MIGRATE ||
227           jcr->getJobType() == JT_VERIFY) {
228          add_prompt(ua, _("Pool"));          /* 7 */
229          if (jcr->getJobType() == JT_VERIFY) {
230             add_prompt(ua, _("Verify Job"));  /* 8 */
231          }
232       } else if (jcr->getJobType() == JT_RESTORE) {
233          add_prompt(ua, _("Bootstrap"));     /* 7 */
234          add_prompt(ua, _("Where"));         /* 8 */
235          add_prompt(ua, _("File Relocation"));/* 9 */    
236          add_prompt(ua, _("Replace"));       /* 10 */
237          add_prompt(ua, _("JobId"));         /* 11 */
238       }
239       if (jcr->getJobType() == JT_BACKUP || jcr->getJobType() == JT_RESTORE) {
240          add_prompt(ua, _("Plugin Options")); /* 12 */
241       }
242       switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
243       case 0:
244          /* Level */
245          select_job_level(ua, jcr);
246          goto try_again;
247       case 1:
248          /* Storage */
249          rc.store->store = select_storage_resource(ua);
250          if (rc.store->store) {
251             pm_strcpy(rc.store->store_source, _("user selection"));
252             set_rwstorage(jcr, rc.store);
253             goto try_again;
254          }
255          break;
256       case 2:
257          /* Job */
258          rc.job = select_job_resource(ua);
259          if (rc.job) {
260             jcr->job = rc.job;
261             set_jcr_defaults(jcr, rc.job);
262             goto try_again;
263          }
264          break;
265       case 3:
266          /* FileSet */
267          rc.fileset = select_fileset_resource(ua);
268          if (rc.fileset) {
269             jcr->fileset = rc.fileset;
270             goto try_again;
271          }
272          break;
273       case 4:
274          /* Client */
275          rc.client = select_client_resource(ua);
276          if (rc.client) {
277             jcr->client = rc.client;
278             goto try_again;
279          }
280          break;
281       case 5:
282          /* When */
283          if (!get_cmd(ua, _("Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now): "))) {
284             break;
285          }
286          if (ua->cmd[0] == 0) {
287             jcr->sched_time = time(NULL);
288          } else {
289             jcr->sched_time = str_to_utime(ua->cmd);
290             if (jcr->sched_time == 0) {
291                ua->send_msg(_("Invalid time, using current time.\n"));
292                jcr->sched_time = time(NULL);
293             }
294          }
295          goto try_again;
296       case 6:
297          /* Priority */
298          if (!get_pint(ua, _("Enter new Priority: "))) {
299             break;
300          }
301          if (ua->pint32_val == 0) {
302             ua->send_msg(_("Priority must be a positive integer.\n"));
303          } else {
304             jcr->JobPriority = ua->pint32_val;
305          }
306          goto try_again;
307       case 7: 
308          /* Pool or Bootstrap depending on JobType */
309          if (jcr->getJobType() == JT_BACKUP ||
310              jcr->getJobType() == JT_COPY ||
311              jcr->getJobType() == JT_MIGRATE ||
312              jcr->getJobType() == JT_VERIFY) {      /* Pool */
313             rc.pool = select_pool_resource(ua);
314             if (rc.pool) {
315                jcr->pool = rc.pool;
316                Dmsg1(100, "Set new pool=%s\n", jcr->pool->name());
317                goto try_again;
318             }
319             break;
320          }
321
322          /* Bootstrap */
323          if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
324             break;
325          }
326          if (jcr->RestoreBootstrap) {
327             free(jcr->RestoreBootstrap);
328             jcr->RestoreBootstrap = NULL;
329          }
330          if (ua->cmd[0] != 0) {
331             jcr->RestoreBootstrap = bstrdup(ua->cmd);
332             fd = fopen(jcr->RestoreBootstrap, "rb");
333             if (!fd) {
334                berrno be;
335                ua->send_msg(_("Warning cannot open %s: ERR=%s\n"),
336                   jcr->RestoreBootstrap, be.bstrerror());
337                free(jcr->RestoreBootstrap);
338                jcr->RestoreBootstrap = NULL;
339             } else {
340                fclose(fd);
341             }
342          }
343          goto try_again;
344       case 8:
345          /* Verify Job */
346          if (jcr->getJobType() == JT_VERIFY) {
347             rc.verify_job = select_job_resource(ua);
348             if (rc.verify_job) {
349               jcr->verify_job = rc.verify_job;
350             }
351             goto try_again;
352          }
353          /* Where */
354          if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) {
355             break;
356          }
357          if (jcr->RegexWhere) { /* cannot use regexwhere and where */
358             free(jcr->RegexWhere);
359             jcr->RegexWhere = NULL;
360          }
361          if (jcr->where) {
362             free(jcr->where);
363             jcr->where = NULL;
364          }
365          if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
366             ua->cmd[0] = 0;
367          }
368          jcr->where = bstrdup(ua->cmd);
369          goto try_again;
370       case 9: 
371          /* File relocation */
372          select_where_regexp(ua, jcr);
373          goto try_again;
374       case 10:
375          /* Replace */
376          start_prompt(ua, _("Replace:\n"));
377          for (i=0; ReplaceOptions[i].name; i++) {
378             add_prompt(ua, ReplaceOptions[i].name);
379          }
380          opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
381          if (opt >=  0) {
382             rc.replace = ReplaceOptions[opt].name;
383             jcr->replace = ReplaceOptions[opt].token;
384          }
385          goto try_again;
386       case 11:
387          /* JobId */
388          rc.jid = NULL;                  /* force reprompt */
389          jcr->RestoreJobId = 0;
390          if (jcr->RestoreBootstrap) {
391             ua->send_msg(_("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
392          }
393          goto try_again;
394       case 12:        
395          /* Plugin Options */
396          if (!get_cmd(ua, _("Please Plugin Options string: "))) {
397             break;
398          }
399          if (jcr->plugin_options) {
400             free(jcr->plugin_options);
401             jcr->plugin_options = NULL;
402          }
403          jcr->plugin_options = bstrdup(ua->cmd);
404          goto try_again;
405       case -1:                        /* error or cancel */
406          goto bail_out;
407       default:
408          goto try_again;
409       }
410       goto bail_out;
411    }
412    return 1;
413
414 bail_out:
415    return -1;
416
417 try_again:
418    return 0;
419 }
420
421 /*
422  * Reset the restore context. 
423  * This subroutine can be called multiple times, so it
424  *  must keep any prior settings.
425  */
426 static bool reset_restore_context(UAContext *ua, JCR *jcr, run_ctx &rc)
427 {
428    int i;
429
430    jcr->verify_job = rc.verify_job;
431    jcr->previous_job = rc.previous_job;
432    jcr->pool = rc.pool;
433    if (jcr->pool != jcr->job->pool) {
434       pm_strcpy(jcr->pool_source, _("User input"));
435    }
436    set_rwstorage(jcr, rc.store);
437    jcr->client = rc.client;
438    pm_strcpy(jcr->client_name, rc.client->name());
439    jcr->fileset = rc.fileset;
440    jcr->ExpectedFiles = rc.files;
441    if (rc.catalog) {
442       jcr->catalog = rc.catalog;
443       pm_strcpy(jcr->catalog_source, _("User input"));
444    }
445
446    pm_strcpy(jcr->comment, rc.comment);
447
448    if (rc.where) {
449       if (jcr->where) {
450          free(jcr->where);
451       }
452       jcr->where = bstrdup(rc.where);
453       rc.where = NULL;
454    }
455
456    if (rc.regexwhere) {
457       if (jcr->RegexWhere) {
458          free(jcr->RegexWhere);
459       }
460       jcr->RegexWhere = bstrdup(rc.regexwhere);       
461       rc.regexwhere = NULL;
462    }
463
464    if (rc.when) {
465       jcr->sched_time = str_to_utime(rc.when);
466       if (jcr->sched_time == 0) {
467          ua->send_msg(_("Invalid time, using current time.\n"));
468          jcr->sched_time = time(NULL);
469       }
470       rc.when = NULL;
471    }
472
473    if (rc.bootstrap) {
474       if (jcr->RestoreBootstrap) {
475          free(jcr->RestoreBootstrap);
476       }
477       jcr->RestoreBootstrap = bstrdup(rc.bootstrap);
478       rc.bootstrap = NULL;
479    }
480
481    if (rc.plugin_options) {
482       if (jcr->plugin_options) {
483          free(jcr->plugin_options);
484       }
485       jcr->plugin_options = bstrdup(rc.plugin_options);
486       rc.plugin_options = NULL;
487    }
488
489
490    if (rc.replace) {
491       jcr->replace = 0;
492       for (i=0; ReplaceOptions[i].name; i++) {
493          if (strcasecmp(rc.replace, ReplaceOptions[i].name) == 0) {
494             jcr->replace = ReplaceOptions[i].token;
495          }
496       }
497       if (!jcr->replace) {
498          ua->send_msg(_("Invalid replace option: %s\n"), rc.replace);
499          return false;
500       }
501    } else if (rc.job->replace) {
502       jcr->replace = rc.job->replace;
503    } else {
504       jcr->replace = REPLACE_ALWAYS;
505    }
506    rc.replace = NULL;
507
508    if (rc.Priority) {
509       jcr->JobPriority = rc.Priority;
510       rc.Priority = 0;
511    }
512
513    if (rc.since) {
514       if (!jcr->stime) {
515          jcr->stime = get_pool_memory(PM_MESSAGE);
516       }
517       pm_strcpy(jcr->stime, rc.since);
518       rc.since = NULL;
519    }
520
521    if (rc.cloned) {
522       jcr->cloned = rc.cloned;
523       rc.cloned = false;
524    }
525
526
527    /* If pool changed, update migration write storage */
528    if (jcr->getJobType() == JT_MIGRATE || jcr->getJobType() == JT_COPY ||
529       (jcr->getJobType() == JT_BACKUP && jcr->getJobLevel() == L_VIRTUAL_FULL)) {
530       if (!set_migration_wstorage(jcr, rc.pool)) {
531          return false;
532       }
533    }
534    rc.replace = ReplaceOptions[0].name;
535    for (i=0; ReplaceOptions[i].name; i++) {
536       if (ReplaceOptions[i].token == jcr->replace) {
537          rc.replace = ReplaceOptions[i].name;
538       }
539    }
540    if (rc.level_name) {
541       if (!get_level_from_name(jcr, rc.level_name)) {
542          ua->send_msg(_("Level \"%s\" not valid.\n"), rc.level_name);
543          return false;
544       }
545       rc.level_name = NULL;
546    }
547    if (rc.jid) {
548       /* Note, this is also MigrateJobId and a VerifyJobId */
549       jcr->RestoreJobId = str_to_int64(rc.jid);
550       rc.jid = 0;
551    }
552    return true;
553 }
554
555 static void select_where_regexp(UAContext *ua, JCR *jcr)
556 {
557    alist *regs;
558    char *strip_prefix, *add_prefix, *add_suffix, *rwhere;
559    strip_prefix = add_suffix = rwhere = add_prefix = NULL;
560
561 try_again_reg:
562    ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s\n"),
563                 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix));
564
565    start_prompt(ua, _("This will replace your current Where value\n"));
566    add_prompt(ua, _("Strip prefix"));                /* 0 */
567    add_prompt(ua, _("Add prefix"));                  /* 1 */
568    add_prompt(ua, _("Add file suffix"));             /* 2 */
569    add_prompt(ua, _("Enter a regexp"));              /* 3 */
570    add_prompt(ua, _("Test filename manipulation"));  /* 4 */
571    add_prompt(ua, _("Use this ?"));                  /* 5 */
572    
573    switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
574    case 0:
575       /* Strip prefix */
576       if (get_cmd(ua, _("Please enter path prefix to strip: "))) {
577          if (strip_prefix) bfree(strip_prefix);
578          strip_prefix = bstrdup(ua->cmd);
579       }
580       
581       goto try_again_reg;
582    case 1:
583       /* Add prefix */
584       if (get_cmd(ua, _("Please enter path prefix to add (/ for none): "))) {
585          if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
586             ua->cmd[0] = 0;
587          }
588
589          if (add_prefix) bfree(add_prefix);
590          add_prefix = bstrdup(ua->cmd);
591       }
592       goto try_again_reg;
593    case 2:
594       /* Add suffix */
595       if (get_cmd(ua, _("Please enter file suffix to add: "))) {
596          if (add_suffix) bfree(add_suffix);
597          add_suffix = bstrdup(ua->cmd);
598       }      
599       goto try_again_reg;
600    case 3:
601       /* Add rwhere */
602       if (get_cmd(ua, _("Please enter a valid regexp (!from!to!): "))) {
603          if (rwhere) bfree(rwhere);
604          rwhere = bstrdup(ua->cmd);
605       }
606       
607       goto try_again_reg;      
608    case 4:
609       /* Test regexp */ 
610       char *result;
611       char *regexp;
612       
613       if (rwhere && rwhere[0] != '\0') {
614          regs = get_bregexps(rwhere);
615          ua->send_msg(_("regexwhere=%s\n"), NPRT(rwhere));
616       } else {
617          int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
618          regexp = (char *) bmalloc (len * sizeof(char));
619          bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix);
620          regs = get_bregexps(regexp);
621          ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s result=%s\n"),
622                       NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix), NPRT(regexp));
623          
624          bfree(regexp);
625       }
626
627       if (!regs) {
628          ua->send_msg(_("Cannot use your regexp\n"));
629          goto try_again_reg;
630       }
631       ua->send_msg(_("Enter a period (.) to stop this test\n"));
632       while (get_cmd(ua, _("Please enter filename to test: "))) {
633          apply_bregexps(ua->cmd, regs, &result);
634          ua->send_msg(_("%s -> %s\n"), ua->cmd, result);
635       }
636       free_bregexps(regs);
637       delete regs;
638       goto try_again_reg;
639
640    case 5:
641       /* OK */
642       break;
643    case -1:                        /* error or cancel */
644       goto bail_out_reg;
645    default:
646       goto try_again_reg;
647    }
648
649    /* replace the existing where */
650    if (jcr->where) {
651       bfree(jcr->where);
652       jcr->where = NULL;
653    }
654
655    /* replace the existing regexwhere */
656    if (jcr->RegexWhere) {
657       bfree(jcr->RegexWhere);
658       jcr->RegexWhere = NULL;
659    }
660
661    if (rwhere) {
662       jcr->RegexWhere = bstrdup(rwhere);
663    } else if (strip_prefix || add_prefix || add_suffix) {
664       int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
665       jcr->RegexWhere = (char *) bmalloc(len*sizeof(char));
666       bregexp_build_where(jcr->RegexWhere, len, strip_prefix, add_prefix, add_suffix);
667    }
668
669    regs = get_bregexps(jcr->RegexWhere);
670    if (regs) {
671       free_bregexps(regs);
672       delete regs;
673    } else {
674       if (jcr->RegexWhere) {
675          bfree(jcr->RegexWhere);
676          jcr->RegexWhere = NULL;
677       }
678       ua->send_msg(_("Cannot use your regexp.\n"));
679    }
680
681 bail_out_reg:
682    if (strip_prefix) bfree(strip_prefix);
683    if (add_prefix)   bfree(add_prefix);
684    if (add_suffix)   bfree(add_suffix);
685    if (rwhere)       bfree(rwhere);
686 }
687
688 static void select_job_level(UAContext *ua, JCR *jcr)
689 {
690    if (jcr->getJobType() == JT_BACKUP) {
691       start_prompt(ua, _("Levels:\n"));
692 //    add_prompt(ua, _("Base"));
693       add_prompt(ua, _("Full"));
694       add_prompt(ua, _("Incremental"));
695       add_prompt(ua, _("Differential"));
696       add_prompt(ua, _("Since"));
697       add_prompt(ua, _("VirtualFull"));
698       switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
699 //    case 0:
700 //       jcr->JobLevel = L_BASE;
701 //       break;
702       case 0:
703          jcr->set_JobLevel(L_FULL);
704          break;
705       case 1:
706          jcr->set_JobLevel(L_INCREMENTAL);
707          break;
708       case 2:
709          jcr->set_JobLevel(L_DIFFERENTIAL);
710          break;
711       case 3:
712          jcr->set_JobLevel(L_SINCE);
713          break;
714       case 4:
715          jcr->set_JobLevel(L_VIRTUAL_FULL);
716          break;
717       default:
718          break;
719       }
720    } else if (jcr->getJobType() == JT_VERIFY) {
721       start_prompt(ua, _("Levels:\n"));
722       add_prompt(ua, _("Initialize Catalog"));
723       add_prompt(ua, _("Verify Catalog"));
724       add_prompt(ua, _("Verify Volume to Catalog"));
725       add_prompt(ua, _("Verify Disk to Catalog"));
726       add_prompt(ua, _("Verify Volume Data (not yet implemented)"));
727       switch (do_prompt(ua, "",  _("Select level"), NULL, 0)) {
728       case 0:
729          jcr->set_JobLevel(L_VERIFY_INIT);
730          break;
731       case 1:
732          jcr->set_JobLevel(L_VERIFY_CATALOG);
733          break;
734       case 2:
735          jcr->set_JobLevel(L_VERIFY_VOLUME_TO_CATALOG);
736          break;
737       case 3:
738          jcr->set_JobLevel(L_VERIFY_DISK_TO_CATALOG);
739          break;
740       case 4:
741          jcr->set_JobLevel(L_VERIFY_DATA);
742          break;
743       default:
744          break;
745       }
746    } else {
747       ua->warning_msg(_("Level not appropriate for this Job. Cannot be changed.\n"));
748    }
749    return;
750 }
751
752 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char *verify_list,
753    char *jid, const char *replace, char *client_name) 
754 {
755    char ec1[30];
756    char dt[MAX_TIME_LENGTH];
757
758    Dmsg1(800, "JobType=%c\n", jcr->getJobType());
759    switch (jcr->getJobType()) {
760    case JT_ADMIN:
761       if (ua->api) ua->signal(BNET_RUN_CMD);   
762       ua->send_msg(_("Run %s job\n"
763                      "JobName:  %s\n"
764                      "FileSet:  %s\n"
765                      "Client:   %s\n"
766                      "Storage:  %s\n"
767                      "When:     %s\n"
768                      "Priority: %d\n"),
769                  _("Admin"),
770                  job->name(),
771                  jcr->fileset->name(),
772                  NPRT(jcr->client->name()),
773                  jcr->wstore?jcr->wstore->name():"*None*",
774                  bstrutime(dt, sizeof(dt), jcr->sched_time),
775                  jcr->JobPriority);
776       jcr->set_JobLevel(L_FULL);
777       break;
778    case JT_BACKUP:
779    case JT_VERIFY:
780       if (jcr->getJobType() == JT_BACKUP) {
781          if (ua->api) ua->signal(BNET_RUN_CMD);   
782          ua->send_msg(_("Run %s job\n"
783                         "JobName:  %s\n"
784                         "Level:    %s\n"
785                         "Client:   %s\n"
786                         "FileSet:  %s\n"
787                         "Pool:     %s (From %s)\n"
788                         "Storage:  %s (From %s)\n"
789                         "When:     %s\n"
790                         "Priority: %d\n"
791                         "%s%s%s"),
792                  _("Backup"),
793                  job->name(),
794                  level_to_str(jcr->getJobLevel()),
795                  jcr->client->name(),
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),
800                  jcr->JobPriority,
801                  jcr->plugin_options?"Plugin Options: ":"",
802                  jcr->plugin_options?jcr->plugin_options:"",
803                  jcr->plugin_options?"\n":"");
804       } else {  /* JT_VERIFY */
805          JOB_DBR jr;
806          const char *Name;
807          if (jcr->verify_job) {
808             Name = jcr->verify_job->name();
809          } else if (jcr->RestoreJobId) { /* Display job name if jobid requested */
810             memset(&jr, 0, sizeof(jr));
811             jr.JobId = jcr->RestoreJobId;
812             if (!db_get_job_record(jcr, ua->db, &jr)) {
813                ua->error_msg(_("Could not get job record for selected JobId. ERR=%s"),
814                     db_strerror(ua->db));
815                return false;
816             }
817             Name = jr.Job;
818          } else {
819             Name = "";
820          }
821          if (!verify_list) {
822             verify_list = job->WriteVerifyList;
823          }
824          if (!verify_list) {
825             verify_list = "";
826          }
827          if (ua->api) ua->signal(BNET_RUN_CMD);   
828          ua->send_msg(_("Run %s job\n"
829                         "JobName:     %s\n"
830                         "Level:       %s\n"
831                         "Client:      %s\n"
832                         "FileSet:     %s\n"
833                         "Pool:        %s (From %s)\n"
834                         "Storage:     %s (From %s)\n"
835                         "Verify Job:  %s\n"
836                         "Verify List: %s\n"
837                         "When:        %s\n"
838                         "Priority:    %d\n"),
839               _("Verify"),
840               job->name(),
841               level_to_str(jcr->getJobLevel()),
842               jcr->client->name(),
843               jcr->fileset->name(),
844               NPRT(jcr->pool->name()), jcr->pool_source,
845               jcr->rstore->name(), jcr->rstore_source,
846               Name,
847               verify_list,
848               bstrutime(dt, sizeof(dt), jcr->sched_time),
849               jcr->JobPriority);
850       }
851       break;
852    case JT_RESTORE:
853       if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
854          if (jid) {
855             jcr->RestoreJobId = str_to_int64(jid);
856          } else {
857             if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
858                return false;
859             }
860             jcr->RestoreJobId = ua->int64_val;
861          }
862       }
863       jcr->set_JobLevel(L_FULL);      /* default level */
864       Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId);
865       if (jcr->RestoreJobId == 0) {
866          if (ua->api) ua->signal(BNET_RUN_CMD);   
867          /* RegexWhere is take before RestoreWhere */
868          if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
869             ua->send_msg(_("Run Restore job\n"
870                         "JobName:         %s\n"
871                         "Bootstrap:       %s\n"
872                         "RegexWhere:      %s\n"
873                         "Replace:         %s\n"
874                         "FileSet:         %s\n"
875                         "Backup Client:   %s\n"
876                         "Restore Client:  %s\n"
877                         "Storage:         %s\n"
878                         "When:            %s\n"
879                         "Catalog:         %s\n"
880                         "Priority:        %d\n"
881                         "Plugin Options:  %s\n"),
882                  job->name(),
883                  NPRT(jcr->RestoreBootstrap), 
884                  jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
885                  replace,
886                  jcr->fileset->name(),
887                  client_name,
888                  jcr->client->name(),
889                  jcr->rstore->name(),
890                  bstrutime(dt, sizeof(dt), jcr->sched_time),
891                  jcr->catalog->name(),
892                  jcr->JobPriority,
893                  NPRT(jcr->plugin_options));
894
895          } else {
896             ua->send_msg(_("Run Restore job\n"
897                         "JobName:         %s\n"
898                         "Bootstrap:       %s\n"
899                         "Where:           %s\n"
900                         "Replace:         %s\n"
901                         "FileSet:         %s\n"
902                         "Backup Client:   %s\n"
903                         "Restore Client:  %s\n"
904                         "Storage:         %s\n"
905                         "When:            %s\n"
906                         "Catalog:         %s\n"
907                         "Priority:        %d\n"
908                         "Plugin Options:  %s\n"),
909                  job->name(),
910                  NPRT(jcr->RestoreBootstrap), 
911                  jcr->where?jcr->where:NPRT(job->RestoreWhere), 
912                  replace,
913                  jcr->fileset->name(),
914                  client_name,
915                  jcr->client->name(),
916                  jcr->rstore->name(),
917                  bstrutime(dt, sizeof(dt), jcr->sched_time),
918                  jcr->catalog->name(),
919                  jcr->JobPriority,
920                  NPRT(jcr->plugin_options));
921          }
922
923       } else {
924          if (ua->api) ua->signal(BNET_RUN_CMD);   
925          ua->send_msg(_("Run Restore job\n"
926                         "JobName:    %s\n"
927                         "Bootstrap:  %s\n"),
928                       job->name(),
929                       NPRT(jcr->RestoreBootstrap));
930                       
931          /* RegexWhere is take before RestoreWhere */
932          if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
933             ua->send_msg(_("RegexWhere: %s\n"),
934                          jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere);
935          } else {
936             ua->send_msg(_("Where:      %s\n"),
937                          jcr->where?jcr->where:NPRT(job->RestoreWhere));
938          }
939
940          ua->send_msg(_("Replace:         %s\n"
941                         "Client:          %s\n"
942                         "Storage:         %s\n"
943                         "JobId:           %s\n"
944                         "When:            %s\n"
945                         "Catalog:         %s\n"
946                         "Priority:        %d\n"
947                         "Plugin Options:  %s\n"),
948               replace,
949               jcr->client->name(),
950               jcr->rstore->name(),
951               jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
952               bstrutime(dt, sizeof(dt), jcr->sched_time),
953               jcr->catalog->name(),
954               jcr->JobPriority,
955               NPRT(jcr->plugin_options));
956       }
957       break;
958    case JT_COPY:
959    case JT_MIGRATE:
960       char *prt_type;
961       if (jcr->getJobType() == JT_COPY) {
962          prt_type = _("Run Copy job\n");
963       } else {
964          prt_type = _("Run Migration job\n");
965       }
966       jcr->set_JobLevel(L_FULL);      /* default level */
967       if (ua->api) ua->signal(BNET_RUN_CMD);   
968       ua->send_msg("%s"
969                      "JobName:       %s\n"
970                      "Bootstrap:     %s\n"
971                      "Client:        %s\n"
972                      "FileSet:       %s\n"
973                      "Pool:          %s (From %s)\n"
974                      "Read Storage:  %s (From %s)\n"
975                      "Write Storage: %s (From %s)\n"
976                      "JobId:         %s\n"
977                      "When:          %s\n"
978                      "Catalog:       %s\n"
979                      "Priority:      %d\n",
980            prt_type,
981            job->name(),
982            NPRT(jcr->RestoreBootstrap),
983            jcr->client->name(),
984            jcr->fileset->name(),
985            NPRT(jcr->pool->name()), jcr->pool_source,
986            jcr->rstore->name(), jcr->rstore_source,
987            jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
988            jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
989            bstrutime(dt, sizeof(dt), jcr->sched_time),
990            jcr->catalog->name(),
991            jcr->JobPriority);
992       break;
993    default:
994       ua->error_msg(_("Unknown Job Type=%d\n"), jcr->getJobType());
995       return false;
996    }
997    return true;
998 }
999
1000
1001 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc)
1002 {
1003    bool kw_ok;
1004    int i, j;
1005    static const char *kw[] = {        /* command line arguments */
1006       "job",                          /*  Used in a switch() */
1007       "jobid",                        /* 1 */
1008       "client",                       /* 2 */
1009       "fd",
1010       "fileset",                      /* 4 */
1011       "level",                        /* 5 */
1012       "storage",                      /* 6 */
1013       "sd",                           /* 7 */
1014       "regexwhere",                   /* 8 where string as a bregexp */
1015       "where",                        /* 9 */
1016       "bootstrap",                    /* 10 */
1017       "replace",                      /* 11 */
1018       "when",                         /* 12 */
1019       "priority",                     /* 13 */
1020       "yes",          /* 14  -- if you change this change YES_POS too */
1021       "verifyjob",                    /* 15 */
1022       "files",                        /* 16 number of files to restore */
1023       "catalog",                      /* 17 override catalog */
1024       "since",                        /* 18 since */
1025       "cloned",                       /* 19 cloned */
1026       "verifylist",                   /* 20 verify output list */
1027       "migrationjob",                 /* 21 migration job name */
1028       "pool",                         /* 22 */
1029       "backupclient",                 /* 23 */
1030       "restoreclient",                /* 24 */
1031       "pluginoptions",                /* 25 */
1032       "spooldata",                    /* 26 */
1033       "comment",                      /* 27 */
1034       NULL};
1035
1036 #define YES_POS 14
1037
1038    rc.catalog_name = NULL;
1039    rc.job_name = NULL;
1040    rc.pool_name = NULL;
1041    rc.store_name = NULL;
1042    rc.client_name = NULL;
1043    rc.restore_client_name = NULL;
1044    rc.fileset_name = NULL;
1045    rc.verify_job_name = NULL;
1046    rc.previous_job_name = NULL;
1047    rc.spool_data_set = 0;
1048    rc.comment = NULL;
1049
1050    for (i=1; i<ua->argc; i++) {
1051       Dmsg2(800, "Doing arg %d = %s\n", i, ua->argk[i]);
1052       kw_ok = false;
1053       /* Keep looking until we find a good keyword */
1054       for (j=0; !kw_ok && kw[j]; j++) {
1055          if (strcasecmp(ua->argk[i], kw[j]) == 0) {
1056             /* Note, yes and run have no value, so do not fail */
1057             if (!ua->argv[i] && j != YES_POS /*yes*/) {
1058                ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]);
1059                return false;
1060             }
1061             Dmsg1(800, "Got keyword=%s\n", NPRT(kw[j]));
1062             switch (j) {
1063             case 0: /* job */
1064                if (rc.job_name) {
1065                   ua->send_msg(_("Job name specified twice.\n"));
1066                   return false;
1067                }
1068                rc.job_name = ua->argv[i];
1069                kw_ok = true;
1070                break;
1071             case 1: /* JobId */
1072                if (rc.jid && !rc.mod) {
1073                   ua->send_msg(_("JobId specified twice.\n"));
1074                   return false;
1075                }
1076                rc.jid = ua->argv[i];
1077                kw_ok = true;
1078                break;
1079             case 2: /* client */
1080             case 3: /* fd */
1081                if (rc.client_name) {
1082                   ua->send_msg(_("Client specified twice.\n"));
1083                   return false;
1084                }
1085                rc.client_name = ua->argv[i];
1086                kw_ok = true;
1087                break;
1088             case 4: /* fileset */
1089                if (rc.fileset_name) {
1090                   ua->send_msg(_("FileSet specified twice.\n"));
1091                   return false;
1092                }
1093                rc.fileset_name = ua->argv[i];
1094                kw_ok = true;
1095                break;
1096             case 5: /* level */
1097                if (rc.level_name) {
1098                   ua->send_msg(_("Level specified twice.\n"));
1099                   return false;
1100                }
1101                rc.level_name = ua->argv[i];
1102                kw_ok = true;
1103                break;
1104             case 6: /* storage */
1105             case 7: /* sd */
1106                if (rc.store_name) {
1107                   ua->send_msg(_("Storage specified twice.\n"));
1108                   return false;
1109                }
1110                rc.store_name = ua->argv[i];
1111                kw_ok = true;
1112                break;
1113             case 8: /* regexwhere */
1114                 if ((rc.regexwhere || rc.where) && !rc.mod) {
1115                   ua->send_msg(_("RegexWhere or Where specified twice.\n"));
1116                   return false;
1117                }
1118                rc.regexwhere = ua->argv[i];
1119                if (!acl_access_ok(ua, Where_ACL, rc.regexwhere)) {
1120                   ua->send_msg(_("No authorization for \"regexwhere\" specification.\n"));
1121                   return false;
1122                }
1123                kw_ok = true;
1124                break;
1125            case 9: /* where */
1126                if ((rc.where || rc.regexwhere) && !rc.mod) {
1127                   ua->send_msg(_("Where or RegexWhere specified twice.\n"));
1128                   return false;
1129                }
1130                rc.where = ua->argv[i];
1131                if (!acl_access_ok(ua, Where_ACL, rc.where)) {
1132                   ua->send_msg(_("No authoriztion for \"where\" specification.\n"));
1133                   return false;
1134                }
1135                kw_ok = true;
1136                break;
1137             case 10: /* bootstrap */
1138                if (rc.bootstrap && !rc.mod) {
1139                   ua->send_msg(_("Bootstrap specified twice.\n"));
1140                   return false;
1141                }
1142                rc.bootstrap = ua->argv[i];
1143                kw_ok = true;
1144                break;
1145             case 11: /* replace */
1146                if (rc.replace && !rc.mod) {
1147                   ua->send_msg(_("Replace specified twice.\n"));
1148                   return false;
1149                }
1150                rc.replace = ua->argv[i];
1151                kw_ok = true;
1152                break;
1153             case 12: /* When */
1154                if (rc.when && !rc.mod) {
1155                   ua->send_msg(_("When specified twice.\n"));
1156                   return false;
1157                }
1158                rc.when = ua->argv[i];
1159                kw_ok = true;
1160                break;
1161             case 13:  /* Priority */
1162                if (rc.Priority && !rc.mod) {
1163                   ua->send_msg(_("Priority specified twice.\n"));
1164                   return false;
1165                }
1166                rc.Priority = atoi(ua->argv[i]);
1167                if (rc.Priority <= 0) {
1168                   ua->send_msg(_("Priority must be positive nonzero setting it to 10.\n"));
1169                   rc.Priority = 10;
1170                }
1171                kw_ok = true;
1172                break;
1173             case 14: /* yes */
1174                kw_ok = true;
1175                break;
1176             case 15: /* Verify Job */
1177                if (rc.verify_job_name) {
1178                   ua->send_msg(_("Verify Job specified twice.\n"));
1179                   return false;
1180                }
1181                rc.verify_job_name = ua->argv[i];
1182                kw_ok = true;
1183                break;
1184             case 16: /* files */
1185                rc.files = atoi(ua->argv[i]);
1186                kw_ok = true;
1187                break;
1188
1189             case 17: /* catalog */
1190                rc.catalog_name = ua->argv[i];
1191                kw_ok = true;
1192                break;
1193
1194             case 18: /* since */
1195                rc.since = ua->argv[i];
1196                kw_ok = true; 
1197                break;
1198
1199             case 19: /* cloned */
1200                rc. cloned = true;
1201                kw_ok = true;
1202                break;
1203
1204             case 20: /* write verify list output */
1205                rc.verify_list = ua->argv[i];
1206                kw_ok = true;
1207                break;
1208             case 21: /* Migration Job */
1209                if (rc.previous_job_name) {
1210                   ua->send_msg(_("Migration Job specified twice.\n"));
1211                   return false;
1212                }
1213                rc.previous_job_name = ua->argv[i];
1214                kw_ok = true;
1215                break;
1216             case 22: /* pool */
1217                if (rc.pool_name) {
1218                   ua->send_msg(_("Pool specified twice.\n"));
1219                   return false;
1220                }
1221                rc.pool_name = ua->argv[i];
1222                kw_ok = true;
1223                break;
1224             case 23: /* backupclient */
1225                if (rc.client_name) {
1226                   ua->send_msg(_("Client specified twice.\n"));
1227                   return 0;
1228                }
1229                rc.client_name = ua->argv[i];
1230                kw_ok = true;
1231                break;
1232             case 24: /* restoreclient */
1233                if (rc.restore_client_name && !rc.mod) {
1234                   ua->send_msg(_("Restore Client specified twice.\n"));
1235                   return false;
1236                }
1237                rc.restore_client_name = ua->argv[i];
1238                kw_ok = true;
1239                break;
1240             case 25: /* pluginoptions */
1241                ua->send_msg(_("Plugin Options not yet implemented.\n"));
1242                return false;
1243                if (rc.plugin_options) {
1244                   ua->send_msg(_("Plugin Options specified twice.\n"));
1245                   return false;
1246                }
1247                rc.plugin_options = ua->argv[i];
1248                if (!acl_access_ok(ua, PluginOptions_ACL, rc.plugin_options)) {
1249                   ua->send_msg(_("No authoriztion for \"PluginOptions\" specification.\n"));
1250                   return false;
1251                }
1252                kw_ok = true;
1253                break;
1254             case 26: /* spooldata */
1255                if (rc.spool_data_set) {
1256                   ua->send_msg(_("Spool flag specified twice.\n"));
1257                   return false;
1258                }
1259                if (is_yesno(ua->argv[i], &rc.spool_data)) {
1260                   rc.spool_data_set = 1;
1261                   kw_ok = true;
1262                } else {
1263                   ua->send_msg(_("Invalid spooldata flag.\n"));
1264                }
1265                break;
1266             case 27: /* comment */
1267                rc.comment = ua->argv[i];
1268                kw_ok = true;
1269             default:
1270                break;
1271             }
1272          } /* end strcase compare */
1273       } /* end keyword loop */
1274       /*
1275        * End of keyword for loop -- if not found, we got a bogus keyword
1276        */
1277       if (!kw_ok) {
1278          Dmsg1(800, "%s not found\n", ua->argk[i]);
1279          /*
1280           * Special case for Job Name, it can be the first
1281           * keyword that has no value.
1282           */
1283          if (!rc.job_name && !ua->argv[i]) {
1284             rc.job_name = ua->argk[i];   /* use keyword as job name */
1285             Dmsg1(800, "Set jobname=%s\n", rc.job_name);
1286          } else {
1287             ua->send_msg(_("Invalid keyword: %s\n"), ua->argk[i]);
1288             return false;
1289          }
1290       }
1291    } /* end argc loop */
1292              
1293    Dmsg0(800, "Done scan.\n");
1294    if (rc.comment) {
1295       if (!is_comment_legal(ua, rc.comment)) {
1296          return false;
1297       }
1298    }
1299    if (rc.catalog_name) {
1300        rc.catalog = GetCatalogResWithName(rc.catalog_name);
1301        if (rc.catalog == NULL) {
1302             ua->error_msg(_("Catalog \"%s\" not found\n"), rc.catalog_name);
1303            return false;
1304        }
1305        if (!acl_access_ok(ua, Catalog_ACL, rc.catalog->name())) {
1306           ua->error_msg(_("No authorization. Catalog \"%s\".\n"), rc.catalog->name());
1307           return false;
1308        }
1309    }
1310    Dmsg1(800, "Using catalog=%s\n", NPRT(rc.catalog_name));
1311
1312    if (rc.job_name) {
1313       /* Find Job */
1314       rc.job = GetJobResWithName(rc.job_name);
1315       if (!rc.job) {
1316          if (*rc.job_name != 0) {
1317             ua->send_msg(_("Job \"%s\" not found\n"), rc.job_name);
1318          }
1319          rc.job = select_job_resource(ua);
1320       } else {
1321          Dmsg1(800, "Found job=%s\n", rc.job_name);
1322       }
1323    } else if (!rc.job) {
1324       ua->send_msg(_("A job name must be specified.\n"));
1325       rc.job = select_job_resource(ua);
1326    }
1327    if (!rc.job) {
1328       return false;
1329    } else if (!acl_access_ok(ua, Job_ACL, rc.job->name())) {
1330       ua->error_msg( _("No authorization. Job \"%s\".\n"), rc.job->name());
1331       return false;
1332    }
1333
1334    if (rc.pool_name) {
1335       rc.pool = GetPoolResWithName(rc.pool_name);
1336       if (!rc.pool) {
1337          if (*rc.pool_name != 0) {
1338             ua->warning_msg(_("Pool \"%s\" not found.\n"), rc.pool_name);
1339          }
1340          rc.pool = select_pool_resource(ua);
1341       }
1342    } else if (!rc.pool) {
1343       rc.pool = rc.job->pool;             /* use default */
1344    }
1345    if (!rc.pool) {
1346       return false;
1347    } else if (!acl_access_ok(ua, Pool_ACL, rc.pool->name())) {
1348       ua->error_msg(_("No authorization. Pool \"%s\".\n"), rc.pool->name());
1349       return false;
1350    }
1351    Dmsg1(100, "Using pool %s\n", rc.pool->name());
1352
1353    if (rc.spool_data_set) {
1354       rc.job->spool_data = rc.spool_data;
1355    }
1356    Dmsg1(900, "Spooling data: %s\n", (rc.job->spool_data ? "Yes" : "No"));
1357
1358    if (rc.store_name) {
1359       rc.store->store = GetStoreResWithName(rc.store_name);
1360       pm_strcpy(rc.store->store_source, _("command line"));
1361       if (!rc.store->store) {
1362          if (*rc.store_name != 0) {
1363             ua->warning_msg(_("Storage \"%s\" not found.\n"), rc.store_name);
1364          }
1365          rc.store->store = select_storage_resource(ua);
1366          pm_strcpy(rc.store->store_source, _("user selection"));
1367       }
1368    } else if (!rc.store->store) {
1369       get_job_storage(rc.store, rc.job, NULL);      /* use default */
1370    }
1371    if (!rc.store->store) {
1372       ua->error_msg(_("No storage specified.\n"));
1373       return false;
1374    } else if (!acl_access_ok(ua, Storage_ACL, rc.store->store->name())) {
1375       ua->error_msg(_("No authorization. Storage \"%s\".\n"),
1376                rc.store->store->name());
1377       return false;
1378    }
1379    Dmsg1(800, "Using storage=%s\n", rc.store->store->name());
1380
1381    if (rc.client_name) {
1382       rc.client = GetClientResWithName(rc.client_name);
1383       if (!rc.client) {
1384          if (*rc.client_name != 0) {
1385             ua->warning_msg(_("Client \"%s\" not found.\n"), rc.client_name);
1386          }
1387          rc.client = select_client_resource(ua);
1388       }
1389    } else if (!rc.client) {
1390       rc.client = rc.job->client;           /* use default */
1391    }
1392    if (!rc.client) {
1393       return false;
1394    } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1395       ua->error_msg(_("No authorization. Client \"%s\".\n"),
1396                rc.client->name());
1397       return false;
1398    }
1399    Dmsg1(800, "Using client=%s\n", rc.client->name());
1400
1401    if (rc.restore_client_name) {
1402       rc.client = GetClientResWithName(rc.restore_client_name);
1403       if (!rc.client) {
1404          if (*rc.restore_client_name != 0) {
1405             ua->warning_msg(_("Restore Client \"%s\" not found.\n"), rc.restore_client_name);
1406          }
1407          rc.client = select_client_resource(ua);
1408       }
1409    } else if (!rc.client) {
1410       rc.client = rc.job->client;           /* use default */
1411    }
1412    if (!rc.client) {
1413       return false;
1414    } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1415       ua->error_msg(_("No authorization. Client \"%s\".\n"),
1416                rc.client->name());
1417       return false;
1418    }
1419    Dmsg1(800, "Using restore client=%s\n", rc.client->name());
1420
1421
1422    if (rc.fileset_name) {
1423       rc.fileset = GetFileSetResWithName(rc.fileset_name);
1424       if (!rc.fileset) {
1425          ua->send_msg(_("FileSet \"%s\" not found.\n"), rc.fileset_name);
1426          rc.fileset = select_fileset_resource(ua);
1427       }
1428    } else if (!rc.fileset) {
1429       rc.fileset = rc.job->fileset;           /* use default */
1430    }
1431    if (!rc.fileset) {
1432       return false;
1433    } else if (!acl_access_ok(ua, FileSet_ACL, rc.fileset->name())) {
1434       ua->send_msg(_("No authorization. FileSet \"%s\".\n"),
1435                rc.fileset->name());
1436       return false;
1437    }
1438
1439    if (rc.verify_job_name) {
1440       rc.verify_job = GetJobResWithName(rc.verify_job_name);
1441       if (!rc.verify_job) {
1442          ua->send_msg(_("Verify Job \"%s\" not found.\n"), rc.verify_job_name);
1443          rc.verify_job = select_job_resource(ua);
1444       }
1445    } else if (!rc.verify_job) {
1446       rc.verify_job = rc.job->verify_job;
1447    }
1448
1449    if (rc.previous_job_name) {
1450       rc.previous_job = GetJobResWithName(rc.previous_job_name);
1451       if (!rc.previous_job) {
1452          ua->send_msg(_("Migration Job \"%s\" not found.\n"), rc.previous_job_name);
1453          rc.previous_job = select_job_resource(ua);
1454       }
1455    } else {
1456       rc.previous_job = rc.job->verify_job;
1457    }
1458    return true;
1459 }