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