]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_run.c
tweak copyright
[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    Dmsg1(800, "JobType=%c\n", jcr->getJobType());
756    switch (jcr->getJobType()) {
757       char ec1[30];
758       char dt[MAX_TIME_LENGTH];
759    case JT_ADMIN:
760       if (ua->api) ua->signal(BNET_RUN_CMD);   
761       ua->send_msg(_("Run %s job\n"
762                      "JobName:  %s\n"
763                      "FileSet:  %s\n"
764                      "Client:   %s\n"
765                      "Storage:  %s\n"
766                      "When:     %s\n"
767                      "Priority: %d\n"),
768                  _("Admin"),
769                  job->name(),
770                  jcr->fileset->name(),
771                  NPRT(jcr->client->name()),
772                  jcr->wstore?jcr->wstore->name():"*None*",
773                  bstrutime(dt, sizeof(dt), jcr->sched_time),
774                  jcr->JobPriority);
775       jcr->set_JobLevel(L_FULL);
776       break;
777    case JT_BACKUP:
778    case JT_VERIFY:
779       if (jcr->getJobType() == JT_BACKUP) {
780          if (ua->api) ua->signal(BNET_RUN_CMD);   
781          ua->send_msg(_("Run %s job\n"
782                         "JobName:  %s\n"
783                         "Level:    %s\n"
784                         "Client:   %s\n"
785                         "FileSet:  %s\n"
786                         "Pool:     %s (From %s)\n"
787                         "Storage:  %s (From %s)\n"
788                         "When:     %s\n"
789                         "Priority: %d\n"
790                         "%s%s%s"),
791                  _("Backup"),
792                  job->name(),
793                  level_to_str(jcr->getJobLevel()),
794                  jcr->client->name(),
795                  jcr->fileset->name(),
796                  NPRT(jcr->pool->name()), jcr->pool_source,
797                  jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
798                  bstrutime(dt, sizeof(dt), jcr->sched_time),
799                  jcr->JobPriority,
800                  jcr->plugin_options?"Plugin Options: ":"",
801                  jcr->plugin_options?jcr->plugin_options:"",
802                  jcr->plugin_options?"\n":"");
803       } else {  /* JT_VERIFY */
804          const char *Name;
805          if (jcr->verify_job) {
806             Name = jcr->verify_job->name();
807          } else {
808             Name = "";
809          }
810          if (!verify_list) {
811             verify_list = job->WriteVerifyList;
812          }
813          if (!verify_list) {
814             verify_list = "";
815          }
816          if (ua->api) ua->signal(BNET_RUN_CMD);   
817          ua->send_msg(_("Run %s job\n"
818                         "JobName:     %s\n"
819                         "Level:       %s\n"
820                         "Client:      %s\n"
821                         "FileSet:     %s\n"
822                         "Pool:        %s (From %s)\n"
823                         "Storage:     %s (From %s)\n"
824                         "Verify Job:  %s\n"
825                         "Verify List: %s\n"
826                         "When:        %s\n"
827                         "Priority:    %d\n"),
828               _("Verify"),
829               job->name(),
830               level_to_str(jcr->getJobLevel()),
831               jcr->client->name(),
832               jcr->fileset->name(),
833               NPRT(jcr->pool->name()), jcr->pool_source,
834               jcr->rstore->name(), jcr->rstore_source,
835               Name,
836               verify_list,
837               bstrutime(dt, sizeof(dt), jcr->sched_time),
838               jcr->JobPriority);
839       }
840       break;
841    case JT_RESTORE:
842       if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
843          if (jid) {
844             jcr->RestoreJobId = str_to_int64(jid);
845          } else {
846             if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
847                return false;
848             }
849             jcr->RestoreJobId = ua->int64_val;
850          }
851       }
852       jcr->set_JobLevel(L_FULL);      /* default level */
853       Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId);
854       if (jcr->RestoreJobId == 0) {
855          if (ua->api) ua->signal(BNET_RUN_CMD);   
856          /* RegexWhere is take before RestoreWhere */
857          if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
858             ua->send_msg(_("Run Restore job\n"
859                         "JobName:         %s\n"
860                         "Bootstrap:       %s\n"
861                         "RegexWhere:      %s\n"
862                         "Replace:         %s\n"
863                         "FileSet:         %s\n"
864                         "Backup Client:   %s\n"
865                         "Restore Client:  %s\n"
866                         "Storage:         %s\n"
867                         "When:            %s\n"
868                         "Catalog:         %s\n"
869                         "Priority:        %d\n"
870                         "Plugin Options:  %s\n"),
871                  job->name(),
872                  NPRT(jcr->RestoreBootstrap), 
873                  jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
874                  replace,
875                  jcr->fileset->name(),
876                  client_name,
877                  jcr->client->name(),
878                  jcr->rstore->name(),
879                  bstrutime(dt, sizeof(dt), jcr->sched_time),
880                  jcr->catalog->name(),
881                  jcr->JobPriority,
882                  NPRT(jcr->plugin_options));
883
884          } else {
885             ua->send_msg(_("Run Restore job\n"
886                         "JobName:         %s\n"
887                         "Bootstrap:       %s\n"
888                         "Where:           %s\n"
889                         "Replace:         %s\n"
890                         "FileSet:         %s\n"
891                         "Backup Client:   %s\n"
892                         "Restore Client:  %s\n"
893                         "Storage:         %s\n"
894                         "When:            %s\n"
895                         "Catalog:         %s\n"
896                         "Priority:        %d\n"
897                         "Plugin Options:  %s\n"),
898                  job->name(),
899                  NPRT(jcr->RestoreBootstrap), 
900                  jcr->where?jcr->where:NPRT(job->RestoreWhere), 
901                  replace,
902                  jcr->fileset->name(),
903                  client_name,
904                  jcr->client->name(),
905                  jcr->rstore->name(),
906                  bstrutime(dt, sizeof(dt), jcr->sched_time),
907                  jcr->catalog->name(),
908                  jcr->JobPriority,
909                  NPRT(jcr->plugin_options));
910          }
911
912       } else {
913          if (ua->api) ua->signal(BNET_RUN_CMD);   
914          ua->send_msg(_("Run Restore job\n"
915                         "JobName:    %s\n"
916                         "Bootstrap:  %s\n"),
917                       job->name(),
918                       NPRT(jcr->RestoreBootstrap));
919                       
920          /* RegexWhere is take before RestoreWhere */
921          if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
922             ua->send_msg(_("RegexWhere: %s\n"),
923                          jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere);
924          } else {
925             ua->send_msg(_("Where:      %s\n"),
926                          jcr->where?jcr->where:NPRT(job->RestoreWhere));
927          }
928
929          ua->send_msg(_("Replace:         %s\n"
930                         "Client:          %s\n"
931                         "Storage:         %s\n"
932                         "JobId:           %s\n"
933                         "When:            %s\n"
934                         "Catalog:         %s\n"
935                         "Priority:        %d\n"
936                         "Plugin Options:  %s\n"),
937               replace,
938               jcr->client->name(),
939               jcr->rstore->name(),
940               jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
941               bstrutime(dt, sizeof(dt), jcr->sched_time),
942               jcr->catalog->name(),
943               jcr->JobPriority,
944               NPRT(jcr->plugin_options));
945       }
946       break;
947    case JT_COPY:
948    case JT_MIGRATE:
949       char *prt_type;
950       if (jcr->getJobType() == JT_COPY) {
951          prt_type = _("Run Copy job\n");
952       } else {
953          prt_type = _("Run Migration job\n");
954       }
955       jcr->set_JobLevel(L_FULL);      /* default level */
956       if (ua->api) ua->signal(BNET_RUN_CMD);   
957       ua->send_msg("%s"
958                      "JobName:       %s\n"
959                      "Bootstrap:     %s\n"
960                      "Client:        %s\n"
961                      "FileSet:       %s\n"
962                      "Pool:          %s (From %s)\n"
963                      "Read Storage:  %s (From %s)\n"
964                      "Write Storage: %s (From %s)\n"
965                      "JobId:         %s\n"
966                      "When:          %s\n"
967                      "Catalog:       %s\n"
968                      "Priority:      %d\n",
969            prt_type,
970            job->name(),
971            NPRT(jcr->RestoreBootstrap),
972            jcr->client->name(),
973            jcr->fileset->name(),
974            NPRT(jcr->pool->name()), jcr->pool_source,
975            jcr->rstore->name(), jcr->rstore_source,
976            jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
977            jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
978            bstrutime(dt, sizeof(dt), jcr->sched_time),
979            jcr->catalog->name(),
980            jcr->JobPriority);
981       break;
982    default:
983       ua->error_msg(_("Unknown Job Type=%d\n"), jcr->getJobType());
984       return false;
985    }
986    return true;
987 }
988
989
990 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc)
991 {
992    bool kw_ok;
993    int i, j;
994    static const char *kw[] = {        /* command line arguments */
995       "job",                          /*  Used in a switch() */
996       "jobid",                        /* 1 */
997       "client",                       /* 2 */
998       "fd",
999       "fileset",                      /* 4 */
1000       "level",                        /* 5 */
1001       "storage",                      /* 6 */
1002       "sd",                           /* 7 */
1003       "regexwhere",                   /* 8 where string as a bregexp */
1004       "where",                        /* 9 */
1005       "bootstrap",                    /* 10 */
1006       "replace",                      /* 11 */
1007       "when",                         /* 12 */
1008       "priority",                     /* 13 */
1009       "yes",          /* 14  -- if you change this change YES_POS too */
1010       "verifyjob",                    /* 15 */
1011       "files",                        /* 16 number of files to restore */
1012       "catalog",                      /* 17 override catalog */
1013       "since",                        /* 18 since */
1014       "cloned",                       /* 19 cloned */
1015       "verifylist",                   /* 20 verify output list */
1016       "migrationjob",                 /* 21 migration job name */
1017       "pool",                         /* 22 */
1018       "backupclient",                 /* 23 */
1019       "restoreclient",                /* 24 */
1020       "pluginoptions",                /* 25 */
1021       "spooldata",                    /* 26 */
1022       "comment",                      /* 27 */
1023       NULL};
1024
1025 #define YES_POS 14
1026
1027    rc.catalog_name = NULL;
1028    rc.job_name = NULL;
1029    rc.pool_name = NULL;
1030    rc.store_name = NULL;
1031    rc.client_name = NULL;
1032    rc.restore_client_name = NULL;
1033    rc.fileset_name = NULL;
1034    rc.verify_job_name = NULL;
1035    rc.previous_job_name = NULL;
1036    rc.spool_data_set = 0;
1037    rc.comment = NULL;
1038
1039    for (i=1; i<ua->argc; i++) {
1040       Dmsg2(800, "Doing arg %d = %s\n", i, ua->argk[i]);
1041       kw_ok = false;
1042       /* Keep looking until we find a good keyword */
1043       for (j=0; !kw_ok && kw[j]; j++) {
1044          if (strcasecmp(ua->argk[i], kw[j]) == 0) {
1045             /* Note, yes and run have no value, so do not fail */
1046             if (!ua->argv[i] && j != YES_POS /*yes*/) {
1047                ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]);
1048                return false;
1049             }
1050             Dmsg1(800, "Got keyword=%s\n", NPRT(kw[j]));
1051             switch (j) {
1052             case 0: /* job */
1053                if (rc.job_name) {
1054                   ua->send_msg(_("Job name specified twice.\n"));
1055                   return false;
1056                }
1057                rc.job_name = ua->argv[i];
1058                kw_ok = true;
1059                break;
1060             case 1: /* JobId */
1061                if (rc.jid && !rc.mod) {
1062                   ua->send_msg(_("JobId specified twice.\n"));
1063                   return false;
1064                }
1065                rc.jid = ua->argv[i];
1066                kw_ok = true;
1067                break;
1068             case 2: /* client */
1069             case 3: /* fd */
1070                if (rc.client_name) {
1071                   ua->send_msg(_("Client specified twice.\n"));
1072                   return false;
1073                }
1074                rc.client_name = ua->argv[i];
1075                kw_ok = true;
1076                break;
1077             case 4: /* fileset */
1078                if (rc.fileset_name) {
1079                   ua->send_msg(_("FileSet specified twice.\n"));
1080                   return false;
1081                }
1082                rc.fileset_name = ua->argv[i];
1083                kw_ok = true;
1084                break;
1085             case 5: /* level */
1086                if (rc.level_name) {
1087                   ua->send_msg(_("Level specified twice.\n"));
1088                   return false;
1089                }
1090                rc.level_name = ua->argv[i];
1091                kw_ok = true;
1092                break;
1093             case 6: /* storage */
1094             case 7: /* sd */
1095                if (rc.store_name) {
1096                   ua->send_msg(_("Storage specified twice.\n"));
1097                   return false;
1098                }
1099                rc.store_name = ua->argv[i];
1100                kw_ok = true;
1101                break;
1102             case 8: /* regexwhere */
1103                 if ((rc.regexwhere || rc.where) && !rc.mod) {
1104                   ua->send_msg(_("RegexWhere or Where specified twice.\n"));
1105                   return false;
1106                }
1107                rc.regexwhere = ua->argv[i];
1108                if (!acl_access_ok(ua, Where_ACL, rc.regexwhere)) {
1109                   ua->send_msg(_("No authorization for \"regexwhere\" specification.\n"));
1110                   return false;
1111                }
1112                kw_ok = true;
1113                break;
1114            case 9: /* where */
1115                if ((rc.where || rc.regexwhere) && !rc.mod) {
1116                   ua->send_msg(_("Where or RegexWhere specified twice.\n"));
1117                   return false;
1118                }
1119                rc.where = ua->argv[i];
1120                if (!acl_access_ok(ua, Where_ACL, rc.where)) {
1121                   ua->send_msg(_("No authoriztion for \"where\" specification.\n"));
1122                   return false;
1123                }
1124                kw_ok = true;
1125                break;
1126             case 10: /* bootstrap */
1127                if (rc.bootstrap && !rc.mod) {
1128                   ua->send_msg(_("Bootstrap specified twice.\n"));
1129                   return false;
1130                }
1131                rc.bootstrap = ua->argv[i];
1132                kw_ok = true;
1133                break;
1134             case 11: /* replace */
1135                if (rc.replace && !rc.mod) {
1136                   ua->send_msg(_("Replace specified twice.\n"));
1137                   return false;
1138                }
1139                rc.replace = ua->argv[i];
1140                kw_ok = true;
1141                break;
1142             case 12: /* When */
1143                if (rc.when && !rc.mod) {
1144                   ua->send_msg(_("When specified twice.\n"));
1145                   return false;
1146                }
1147                rc.when = ua->argv[i];
1148                kw_ok = true;
1149                break;
1150             case 13:  /* Priority */
1151                if (rc.Priority && !rc.mod) {
1152                   ua->send_msg(_("Priority specified twice.\n"));
1153                   return false;
1154                }
1155                rc.Priority = atoi(ua->argv[i]);
1156                if (rc.Priority <= 0) {
1157                   ua->send_msg(_("Priority must be positive nonzero setting it to 10.\n"));
1158                   rc.Priority = 10;
1159                }
1160                kw_ok = true;
1161                break;
1162             case 14: /* yes */
1163                kw_ok = true;
1164                break;
1165             case 15: /* Verify Job */
1166                if (rc.verify_job_name) {
1167                   ua->send_msg(_("Verify Job specified twice.\n"));
1168                   return false;
1169                }
1170                rc.verify_job_name = ua->argv[i];
1171                kw_ok = true;
1172                break;
1173             case 16: /* files */
1174                rc.files = atoi(ua->argv[i]);
1175                kw_ok = true;
1176                break;
1177
1178             case 17: /* catalog */
1179                rc.catalog_name = ua->argv[i];
1180                kw_ok = true;
1181                break;
1182
1183             case 18: /* since */
1184                rc.since = ua->argv[i];
1185                kw_ok = true; 
1186                break;
1187
1188             case 19: /* cloned */
1189                rc. cloned = true;
1190                kw_ok = true;
1191                break;
1192
1193             case 20: /* write verify list output */
1194                rc.verify_list = ua->argv[i];
1195                kw_ok = true;
1196                break;
1197             case 21: /* Migration Job */
1198                if (rc.previous_job_name) {
1199                   ua->send_msg(_("Migration Job specified twice.\n"));
1200                   return false;
1201                }
1202                rc.previous_job_name = ua->argv[i];
1203                kw_ok = true;
1204                break;
1205             case 22: /* pool */
1206                if (rc.pool_name) {
1207                   ua->send_msg(_("Pool specified twice.\n"));
1208                   return false;
1209                }
1210                rc.pool_name = ua->argv[i];
1211                kw_ok = true;
1212                break;
1213             case 23: /* backupclient */
1214                if (rc.client_name) {
1215                   ua->send_msg(_("Client specified twice.\n"));
1216                   return 0;
1217                }
1218                rc.client_name = ua->argv[i];
1219                kw_ok = true;
1220                break;
1221             case 24: /* restoreclient */
1222                if (rc.restore_client_name && !rc.mod) {
1223                   ua->send_msg(_("Restore Client specified twice.\n"));
1224                   return false;
1225                }
1226                rc.restore_client_name = ua->argv[i];
1227                kw_ok = true;
1228                break;
1229             case 25: /* pluginoptions */
1230                ua->send_msg(_("Plugin Options not yet implemented.\n"));
1231                return false;
1232                if (rc.plugin_options) {
1233                   ua->send_msg(_("Plugin Options specified twice.\n"));
1234                   return false;
1235                }
1236                rc.plugin_options = ua->argv[i];
1237                if (!acl_access_ok(ua, PluginOptions_ACL, rc.plugin_options)) {
1238                   ua->send_msg(_("No authoriztion for \"PluginOptions\" specification.\n"));
1239                   return false;
1240                }
1241                kw_ok = true;
1242                break;
1243             case 26: /* spooldata */
1244                if (rc.spool_data_set) {
1245                   ua->send_msg(_("Spool flag specified twice.\n"));
1246                   return false;
1247                }
1248                if (is_yesno(ua->argv[i], &rc.spool_data)) {
1249                   rc.spool_data_set = 1;
1250                   kw_ok = true;
1251                } else {
1252                   ua->send_msg(_("Invalid spooldata flag.\n"));
1253                }
1254                break;
1255             case 27: /* comment */
1256                rc.comment = ua->argv[i];
1257                kw_ok = true;
1258             default:
1259                break;
1260             }
1261          } /* end strcase compare */
1262       } /* end keyword loop */
1263       /*
1264        * End of keyword for loop -- if not found, we got a bogus keyword
1265        */
1266       if (!kw_ok) {
1267          Dmsg1(800, "%s not found\n", ua->argk[i]);
1268          /*
1269           * Special case for Job Name, it can be the first
1270           * keyword that has no value.
1271           */
1272          if (!rc.job_name && !ua->argv[i]) {
1273             rc.job_name = ua->argk[i];   /* use keyword as job name */
1274             Dmsg1(800, "Set jobname=%s\n", rc.job_name);
1275          } else {
1276             ua->send_msg(_("Invalid keyword: %s\n"), ua->argk[i]);
1277             return false;
1278          }
1279       }
1280    } /* end argc loop */
1281              
1282    Dmsg0(800, "Done scan.\n");
1283    if (rc.comment) {
1284       if (!is_comment_legal(ua, rc.comment)) {
1285          return false;
1286       }
1287    }
1288    if (rc.catalog_name) {
1289        rc.catalog = GetCatalogResWithName(rc.catalog_name);
1290        if (rc.catalog == NULL) {
1291             ua->error_msg(_("Catalog \"%s\" not found\n"), rc.catalog_name);
1292            return false;
1293        }
1294        if (!acl_access_ok(ua, Catalog_ACL, rc.catalog->name())) {
1295           ua->error_msg(_("No authorization. Catalog \"%s\".\n"), rc.catalog->name());
1296           return false;
1297        }
1298    }
1299    Dmsg1(800, "Using catalog=%s\n", NPRT(rc.catalog_name));
1300
1301    if (rc.job_name) {
1302       /* Find Job */
1303       rc.job = GetJobResWithName(rc.job_name);
1304       if (!rc.job) {
1305          if (*rc.job_name != 0) {
1306             ua->send_msg(_("Job \"%s\" not found\n"), rc.job_name);
1307          }
1308          rc.job = select_job_resource(ua);
1309       } else {
1310          Dmsg1(800, "Found job=%s\n", rc.job_name);
1311       }
1312    } else if (!rc.job) {
1313       ua->send_msg(_("A job name must be specified.\n"));
1314       rc.job = select_job_resource(ua);
1315    }
1316    if (!rc.job) {
1317       return false;
1318    } else if (!acl_access_ok(ua, Job_ACL, rc.job->name())) {
1319       ua->error_msg( _("No authorization. Job \"%s\".\n"), rc.job->name());
1320       return false;
1321    }
1322
1323    if (rc.pool_name) {
1324       rc.pool = GetPoolResWithName(rc.pool_name);
1325       if (!rc.pool) {
1326          if (*rc.pool_name != 0) {
1327             ua->warning_msg(_("Pool \"%s\" not found.\n"), rc.pool_name);
1328          }
1329          rc.pool = select_pool_resource(ua);
1330       }
1331    } else if (!rc.pool) {
1332       rc.pool = rc.job->pool;             /* use default */
1333    }
1334    if (!rc.pool) {
1335       return false;
1336    } else if (!acl_access_ok(ua, Pool_ACL, rc.pool->name())) {
1337       ua->error_msg(_("No authorization. Pool \"%s\".\n"), rc.pool->name());
1338       return false;
1339    }
1340    Dmsg1(100, "Using pool %s\n", rc.pool->name());
1341
1342    if (rc.spool_data_set) {
1343       rc.job->spool_data = rc.spool_data;
1344    }
1345    Dmsg1(900, "Spooling data: %s\n", (rc.job->spool_data ? "Yes" : "No"));
1346
1347    if (rc.store_name) {
1348       rc.store->store = GetStoreResWithName(rc.store_name);
1349       pm_strcpy(rc.store->store_source, _("command line"));
1350       if (!rc.store->store) {
1351          if (*rc.store_name != 0) {
1352             ua->warning_msg(_("Storage \"%s\" not found.\n"), rc.store_name);
1353          }
1354          rc.store->store = select_storage_resource(ua);
1355          pm_strcpy(rc.store->store_source, _("user selection"));
1356       }
1357    } else if (!rc.store->store) {
1358       get_job_storage(rc.store, rc.job, NULL);      /* use default */
1359    }
1360    if (!rc.store->store) {
1361       ua->error_msg(_("No storage specified.\n"));
1362       return false;
1363    } else if (!acl_access_ok(ua, Storage_ACL, rc.store->store->name())) {
1364       ua->error_msg(_("No authorization. Storage \"%s\".\n"),
1365                rc.store->store->name());
1366       return false;
1367    }
1368    Dmsg1(800, "Using storage=%s\n", rc.store->store->name());
1369
1370    if (rc.client_name) {
1371       rc.client = GetClientResWithName(rc.client_name);
1372       if (!rc.client) {
1373          if (*rc.client_name != 0) {
1374             ua->warning_msg(_("Client \"%s\" not found.\n"), rc.client_name);
1375          }
1376          rc.client = select_client_resource(ua);
1377       }
1378    } else if (!rc.client) {
1379       rc.client = rc.job->client;           /* use default */
1380    }
1381    if (!rc.client) {
1382       return false;
1383    } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1384       ua->error_msg(_("No authorization. Client \"%s\".\n"),
1385                rc.client->name());
1386       return false;
1387    }
1388    Dmsg1(800, "Using client=%s\n", rc.client->name());
1389
1390    if (rc.restore_client_name) {
1391       rc.client = GetClientResWithName(rc.restore_client_name);
1392       if (!rc.client) {
1393          if (*rc.restore_client_name != 0) {
1394             ua->warning_msg(_("Restore Client \"%s\" not found.\n"), rc.restore_client_name);
1395          }
1396          rc.client = select_client_resource(ua);
1397       }
1398    } else if (!rc.client) {
1399       rc.client = rc.job->client;           /* use default */
1400    }
1401    if (!rc.client) {
1402       return false;
1403    } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1404       ua->error_msg(_("No authorization. Client \"%s\".\n"),
1405                rc.client->name());
1406       return false;
1407    }
1408    Dmsg1(800, "Using restore client=%s\n", rc.client->name());
1409
1410
1411    if (rc.fileset_name) {
1412       rc.fileset = GetFileSetResWithName(rc.fileset_name);
1413       if (!rc.fileset) {
1414          ua->send_msg(_("FileSet \"%s\" not found.\n"), rc.fileset_name);
1415          rc.fileset = select_fileset_resource(ua);
1416       }
1417    } else if (!rc.fileset) {
1418       rc.fileset = rc.job->fileset;           /* use default */
1419    }
1420    if (!rc.fileset) {
1421       return false;
1422    } else if (!acl_access_ok(ua, FileSet_ACL, rc.fileset->name())) {
1423       ua->send_msg(_("No authorization. FileSet \"%s\".\n"),
1424                rc.fileset->name());
1425       return false;
1426    }
1427
1428    if (rc.verify_job_name) {
1429       rc.verify_job = GetJobResWithName(rc.verify_job_name);
1430       if (!rc.verify_job) {
1431          ua->send_msg(_("Verify Job \"%s\" not found.\n"), rc.verify_job_name);
1432          rc.verify_job = select_job_resource(ua);
1433       }
1434    } else if (!rc.verify_job) {
1435       rc.verify_job = rc.job->verify_job;
1436    }
1437
1438    if (rc.previous_job_name) {
1439       rc.previous_job = GetJobResWithName(rc.previous_job_name);
1440       if (!rc.previous_job) {
1441          ua->send_msg(_("Migration Job \"%s\" not found.\n"), rc.previous_job_name);
1442          rc.previous_job = select_job_resource(ua);
1443       }
1444    } else {
1445       rc.previous_job = rc.job->verify_job;
1446    }
1447    return true;
1448 }