]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/restore.c
Apply patch from Wandlei Huttel to add Run Time and suffix to Restored bytes
[bacula/bacula] / bacula / src / dird / restore.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2015 Kern Sibbald
5
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /**
20  *   Bacula Director -- restore.c -- responsible for restoring files
21  *
22  *     Written by Kern Sibbald, November MM
23  *
24  *    This routine is run as a separate thread.
25  *
26  * Current implementation is Catalog verification only (i.e. no
27  *  verification versus tape).
28  *
29  *  Basic tasks done here:
30  *     Open DB
31  *     Open Message Channel with Storage daemon to tell him a job will be starting.
32  *     Open connection with File daemon and pass him commands
33  *       to do the restore.
34  *     Update the DB according to what files where restored????
35  *
36  */
37
38
39 #include "bacula.h"
40 #include "dird.h"
41 #include "lib/ini.h"
42
43 /* Commands sent to File daemon */
44 static char restorecmd[]  = "restore %sreplace=%c prelinks=%d where=%s\n";
45 static char restorecmdR[] = "restore %sreplace=%c prelinks=%d regexwhere=%s\n";
46 static char storaddr[]    = "storage address=%s port=%d ssl=%d Authorization=%s\n";
47
48 /* Responses received from File daemon */
49 static char OKrestore[]   = "2000 OK restore\n";
50 static char OKstore[]     = "2000 OK storage\n";
51 static char OKstoreend[]  = "2000 OK storage end\n";
52
53 /* Responses received from the Storage daemon */
54 static char OKbootstrap[] = "3000 OK bootstrap\n";
55
56 static void build_restore_command(JCR *jcr, POOL_MEM &ret)
57 {
58    char replace, *where, *cmd;
59    char empty = '\0';
60    char files[100];
61
62    /* Build the restore command */
63
64    if (jcr->replace != 0) {
65       replace = jcr->replace;
66    } else if (jcr->job->replace != 0) {
67       replace = jcr->job->replace;
68    } else {
69       replace = REPLACE_ALWAYS;       /* always replace */
70    }
71
72    if (jcr->RegexWhere) {
73       where = jcr->RegexWhere;             /* override */
74       cmd = restorecmdR;
75    } else if (jcr->job->RegexWhere) {
76       where = jcr->job->RegexWhere;   /* no override take from job */
77       cmd = restorecmdR;
78
79    } else if (jcr->where) {
80       where = jcr->where;             /* override */
81       cmd = restorecmd;
82    } else if (jcr->job->RestoreWhere) {
83       where = jcr->job->RestoreWhere; /* no override take from job */
84       cmd = restorecmd;
85
86    } else {                           /* nothing was specified */
87       where = ∅                 /* use default */
88       cmd   = restorecmd;
89    }
90
91    jcr->prefix_links = jcr->job->PrefixLinks;
92
93    bash_spaces(where);
94    if (jcr->FDVersion < 7) {
95       Mmsg(ret, cmd, "", replace, jcr->prefix_links, where);
96    } else {
97       snprintf(files, sizeof(files), "files=%d ", jcr->ExpectedFiles);
98       Mmsg(ret, cmd, files, replace, jcr->prefix_links, where);
99    }
100    unbash_spaces(where);
101 }
102
103 struct bootstrap_info
104 {
105    FILE *bs;
106    UAContext *ua;
107    char storage[MAX_NAME_LENGTH+1];
108 };
109
110 #define UA_CMD_SIZE 1000
111
112 /**
113  * Open the bootstrap file and find the first Storage=
114  * Returns ok if able to open
115  * It fills the storage name (should be the first line)
116  * and the file descriptor to the bootstrap file,
117  * it should be used for next operations, and need to be closed
118  * at the end.
119  */
120 static bool open_bootstrap_file(JCR *jcr, bootstrap_info &info)
121 {
122    FILE *bs;
123    UAContext *ua;
124    info.bs = NULL;
125    info.ua = NULL;
126
127    if (!jcr->RestoreBootstrap) {
128       return false;
129    }
130    strncpy(info.storage, jcr->rstore->name(), MAX_NAME_LENGTH);
131
132    bs = bfopen(jcr->RestoreBootstrap, "rb");
133    if (!bs) {
134       berrno be;
135       Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"),
136          jcr->RestoreBootstrap, be.bstrerror());
137       jcr->setJobStatus(JS_ErrorTerminated);
138       return false;
139    }
140
141    ua = new_ua_context(jcr);
142    ua->cmd = check_pool_memory_size(ua->cmd, UA_CMD_SIZE+1);
143    while (!fgets(ua->cmd, UA_CMD_SIZE, bs)) {
144       parse_ua_args(ua);
145       if (ua->argc != 1) {
146          continue;
147       }
148       if (!strcasecmp(ua->argk[0], "Storage")) {
149          strncpy(info.storage, ua->argv[0], MAX_NAME_LENGTH);
150          break;
151       }
152    }
153    info.bs = bs;
154    info.ua = ua;
155    fseek(bs, 0, SEEK_SET);      /* return to the top of the file */
156    return true;
157 }
158
159 /**
160  * This function compare the given storage name with the
161  * the current one. We compare the name and the address:port.
162  * Returns true if we use the same storage.
163  */
164 static bool is_on_same_storage(JCR *jcr, char *new_one)
165 {
166    STORE *new_store;
167
168    /* with old FD, we send the whole bootstrap to the storage */
169    if (jcr->FDVersion < 2) {
170       return true;
171    }
172    /* we are in init loop ? shoudn't fail here */
173    if (!*new_one) {
174       return true;
175    }
176    /* same name */
177    if (!strcmp(new_one, jcr->rstore->name())) {
178       return true;
179    }
180    new_store = (STORE *)GetResWithName(R_STORAGE, new_one);
181    if (!new_store) {
182       Jmsg(jcr, M_WARNING, 0,
183            _("Could not get storage resource '%s'.\n"), new_one);
184       /* If not storage found, use last one */
185       return true;
186    }
187    /* if Port and Hostname/IP are same, we are talking to the same
188     * Storage Daemon
189     */
190    if (jcr->rstore->SDport != new_store->SDport ||
191        strcmp(jcr->rstore->address, new_store->address))
192    {
193       return false;
194    }
195    return true;
196 }
197
198 /**
199  * Check if the current line contains Storage="xxx", and compare the
200  * result to the current storage. We use UAContext to analyse the bsr
201  * string.
202  *
203  * Returns true if we need to change the storage, and it set the new
204  * Storage resource name in "storage" arg.
205  */
206 static bool check_for_new_storage(JCR *jcr, bootstrap_info &info)
207 {
208    UAContext *ua = info.ua;
209    parse_ua_args(ua);
210    if (ua->argc != 1) {
211       return false;
212    }
213    if (!strcasecmp(ua->argk[0], "Storage")) {
214       /* Continue if this is a volume from the same storage. */
215       if (is_on_same_storage(jcr, ua->argv[0])) {
216          return false;
217       }
218       /* note the next storage name */
219       strncpy(info.storage, ua->argv[0], MAX_NAME_LENGTH);
220       Dmsg1(5, "Change storage to %s\n", info.storage);
221       return true;
222    }
223    return false;
224 }
225
226 /**
227  * Send bootstrap file to Storage daemon section by section.
228  */
229 static bool send_bootstrap_file(JCR *jcr, BSOCK *sock,
230                                 bootstrap_info &info)
231 {
232    boffset_t pos;
233    const char *bootstrap = "bootstrap\n";
234    UAContext *ua = info.ua;
235    FILE *bs = info.bs;
236
237    Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap);
238    if (!jcr->RestoreBootstrap) {
239       return false;
240    }
241    sock->fsend(bootstrap);
242    pos = ftello(bs);
243    while(fgets(ua->cmd, UA_CMD_SIZE, bs)) {
244       if (check_for_new_storage(jcr, info)) {
245          /* Otherwise, we need to contact another storage daemon.
246           * Reset bs to the beginning of the current segment.
247           */
248          fseeko(bs, pos, SEEK_SET);
249          break;
250       }
251       sock->fsend("%s", ua->cmd);
252       pos = ftello(bs);
253    }
254    sock->signal(BNET_EOD);
255    return true;
256 }
257
258 #define MAX_TRIES 6 * 360   /* 6 hours */
259
260 /**
261  * Change the read storage resource for the current job.
262  */
263 static bool select_rstore(JCR *jcr, bootstrap_info &info)
264 {
265    USTORE ustore;
266    int i;
267
268
269    if (!strcmp(jcr->rstore->name(), info.storage)) {
270       return true;                 /* same SD nothing to change */
271    }
272
273    if (!(ustore.store = (STORE *)GetResWithName(R_STORAGE,info.storage))) {
274       Jmsg(jcr, M_FATAL, 0,
275            _("Could not get storage resource '%s'.\n"), info.storage);
276       jcr->setJobStatus(JS_ErrorTerminated);
277       return false;
278    }
279
280    /*
281     * This releases the store_bsock between calls to the SD.
282     *  I think.
283     */
284    free_bsock(jcr->store_bsock);
285
286    /*
287     * release current read storage and get a new one
288     */
289    dec_read_store(jcr);
290    free_rstorage(jcr);
291    set_rstorage(jcr, &ustore);
292    jcr->setJobStatus(JS_WaitSD);
293    /*
294     * Wait for up to 6 hours to increment read stoage counter
295     */
296    for (i=0; i < MAX_TRIES; i++) {
297       /* try to get read storage counter incremented */
298       if (inc_read_store(jcr)) {
299          jcr->setJobStatus(JS_Running);
300          return true;
301       }
302       bmicrosleep(10, 0);       /* sleep 10 secs */
303       if (job_canceled(jcr)) {
304          free_rstorage(jcr);
305          return false;
306       }
307    }
308    /* Failed to inc_read_store() */
309    free_rstorage(jcr);
310    Jmsg(jcr, M_FATAL, 0,
311       _("Could not acquire read storage lock for \"%s\""), info.storage);
312    return false;
313 }
314
315 /*
316  * Clean the bootstrap_info struct
317  */
318 static void close_bootstrap_file(bootstrap_info &info)
319 {
320    if (info.bs) {
321       fclose(info.bs);
322    }
323    if (info.ua) {
324       free_ua_context(info.ua);
325    }
326 }
327
328 /**
329  * The bootstrap is stored in a file, so open the file, and loop
330  *   through it processing each storage device in turn. If the
331  *   storage is different from the prior one, we open a new connection
332  *   to the new storage and do a restore for that part.
333  * This permits handling multiple storage daemons for a single
334  *   restore.  E.g. your Full is stored on tape, and Incrementals
335  *   on disk.
336  */
337 bool restore_bootstrap(JCR *jcr)
338 {
339    int tls_need = BNET_TLS_NONE;
340    BSOCK *fd = NULL;
341    BSOCK *sd;
342    char *store_address;
343    uint32_t store_port;
344    bool first_time = true;
345    bootstrap_info info;
346    POOL_MEM restore_cmd(PM_MESSAGE);
347    bool ret = false;
348
349
350    /* Open the bootstrap file */
351    if (!open_bootstrap_file(jcr, info)) {
352       goto bail_out;
353    }
354    /* Read the bootstrap file */
355    while (!feof(info.bs)) {
356
357       if (!select_rstore(jcr, info)) {
358          goto bail_out;
359       }
360
361       /**
362        * Open a message channel connection with the Storage
363        * daemon. This is to let him know that our client
364        * will be contacting him for a backup  session.
365        *
366        */
367       Dmsg0(10, "Open connection with storage daemon\n");
368       jcr->setJobStatus(JS_WaitSD);
369       /*
370        * Start conversation with Storage daemon
371        */
372       if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
373          goto bail_out;
374       }
375       sd = jcr->store_bsock;
376       /*
377        * Now start a job with the Storage daemon
378        */
379       if (!start_storage_daemon_job(jcr, jcr->rstorage, NULL)) {
380          goto bail_out;
381       }
382
383       if (first_time) {
384          /*
385           * Start conversation with File daemon
386           */
387          jcr->setJobStatus(JS_WaitFD);
388          jcr->keep_sd_auth_key = true; /* don't clear the sd_auth_key now */
389          if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
390             goto bail_out;
391          }
392          fd = jcr->file_bsock;
393          build_restore_command(jcr, restore_cmd);
394       }
395
396       jcr->setJobStatus(JS_Running);
397
398       /*
399        * Send the bootstrap file -- what Volumes/files to restore
400        */
401       if (!send_bootstrap_file(jcr, sd, info) ||
402           !response(jcr, sd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
403          goto bail_out;
404       }
405
406       if (jcr->sd_calls_client) {
407          /*
408           * SD must call "client" i.e. FD
409           */
410          if (jcr->FDVersion < 10) {
411             Jmsg(jcr, M_FATAL, 0, _("The File daemon does not support SDCallsClient.\n"));
412             goto bail_out;
413          }
414          if (!send_client_addr_to_sd(jcr)) {
415             goto bail_out;
416          }
417          if (!run_storage_and_start_message_thread(jcr, sd)) {
418             goto bail_out;
419          }
420
421          store_address = jcr->rstore->address;  /* dummy */
422          store_port = 0;                        /* flag that SD calls FD */
423
424       } else {
425          /*
426           * Default case where FD must call the SD
427           */
428          if (!run_storage_and_start_message_thread(jcr, sd)) {
429             goto bail_out;
430          }
431
432          /*
433           * send Storage daemon address to the File daemon,
434           *   then wait for File daemon to make connection
435           *   with Storage daemon.
436           */
437          if (jcr->rstore->SDDport == 0) {
438             jcr->rstore->SDDport = jcr->rstore->SDport;
439          }
440
441          store_address = get_storage_address(jcr->client, jcr->rstore);
442          store_port = jcr->rstore->SDDport;
443       }
444
445       /* TLS Requirement */
446       if (jcr->rstore->tls_enable) {
447          if (jcr->rstore->tls_require) {
448             tls_need = BNET_TLS_REQUIRED;
449          } else {
450             tls_need = BNET_TLS_OK;
451          }
452       }
453
454       /*
455        * Send storage address to FD
456        *  if port==0 FD must wait for SD to call it.
457        */
458       fd->fsend(storaddr, store_address, store_port, tls_need, jcr->sd_auth_key);
459       memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
460       Dmsg1(6, "dird>filed: %s\n", fd->msg);
461       if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
462          goto bail_out;
463       }
464
465       /* Declare the job started to start the MaxRunTime check */
466       jcr->setJobStarted();
467
468       /* Only pass "global" commands to the FD once */
469       if (first_time) {
470          first_time = false;
471          if (!send_runscripts_commands(jcr)) {
472             goto bail_out;
473          }
474          if (!send_component_info(jcr)) {
475             Pmsg0(000, "FAIL: Send component info\n");
476             goto bail_out;
477          }
478          if (!send_restore_objects(jcr)) {
479             Pmsg0(000, "FAIL: Send restore objects\n");
480             goto bail_out;
481          }
482       }
483
484       fd->fsend("%s", restore_cmd.c_str());
485       if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
486          goto bail_out;
487       }
488
489       if (jcr->FDVersion < 2) { /* Old FD */
490          break;                 /* we do only one loop */
491       } else {
492          if (!response(jcr, fd, OKstoreend, "Store end", DISPLAY_ERROR)) {
493             goto bail_out;
494          }
495          wait_for_storage_daemon_termination(jcr);
496       }
497    } /* the whole boostrap has been send */
498
499    if (fd && jcr->FDVersion >= 2) {
500       fd->fsend("endrestore");
501    }
502
503    ret = true;
504
505 bail_out:
506    close_bootstrap_file(info);
507    return ret;
508 }
509
510 /**
511  * Do a restore of the specified files
512  *
513  *  Returns:  0 on failure
514  *            1 on success
515  */
516 bool do_restore(JCR *jcr)
517 {
518    JOB_DBR rjr;                       /* restore job record */
519    int stat;
520
521    free_wstorage(jcr);                /* we don't write */
522
523    if (!allow_duplicate_job(jcr)) {
524       goto bail_out;
525    }
526
527    memset(&rjr, 0, sizeof(rjr));
528    jcr->jr.JobLevel = L_FULL;         /* Full restore */
529    if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
530       Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
531       goto bail_out;
532    }
533    Dmsg0(20, "Updated job start record\n");
534
535    Dmsg1(20, "RestoreJobId=%d\n", jcr->job->RestoreJobId);
536
537    if (!jcr->RestoreBootstrap) {
538       Jmsg(jcr, M_FATAL, 0, _("Cannot restore without a bootstrap file.\n"
539           "You probably ran a restore job directly. All restore jobs must\n"
540           "be run using the restore command.\n"));
541       goto bail_out;
542    }
543
544
545    /* Print Job Start message */
546    Jmsg(jcr, M_INFO, 0, _("Start Restore Job %s\n"), jcr->Job);
547
548    if (jcr->client) {
549       jcr->sd_calls_client = jcr->client->sd_calls_client;
550    }
551
552    /* Read the bootstrap file and do the restore */
553    if (!restore_bootstrap(jcr)) {
554       goto bail_out;
555    }
556
557    /* Wait for Job Termination */
558    stat = wait_for_job_termination(jcr);
559    restore_cleanup(jcr, stat);
560    return true;
561
562 bail_out:
563    restore_cleanup(jcr, JS_ErrorTerminated);
564    return false;
565 }
566
567 /* Create a Plugin Config RestoreObject, will be sent
568  * at restore time to the Plugin
569  */
570 static void plugin_create_restoreobject(JCR *jcr, plugin_config_item *elt)
571 {
572    ROBJECT_DBR ro;
573    memset(&ro, 0, sizeof(ro));
574    ro.FileIndex = 1;
575    ro.JobId = jcr->JobId;
576    ro.FileType = FT_PLUGIN_CONFIG_FILLED;
577    ro.object_index = 1;
578    ro.object_full_len = ro.object_len = strlen(elt->content);
579    ro.object_compression = 0;
580    ro.plugin_name = elt->plugin_name;
581    ro.object_name = (char*)INI_RESTORE_OBJECT_NAME;
582    ro.object = elt->content;
583    db_create_restore_object_record(jcr, jcr->db, &ro);
584    Dmsg1(50, "Creating restore object for %s\n", elt->plugin_name);
585 }
586
587 bool do_restore_init(JCR *jcr)
588 {
589    /* Will add RestoreObject used for the Plugin configuration */
590    if (jcr->plugin_config) {
591
592       plugin_config_item *elt;
593       foreach_alist(elt, jcr->plugin_config) {
594          plugin_create_restoreobject(jcr, elt);
595          free_plugin_config_item(elt);
596       }
597
598       delete jcr->plugin_config;
599       jcr->plugin_config = NULL;
600    }
601    free_wstorage(jcr);
602    return true;
603 }
604
605 /**
606  * Release resources allocated during restore.
607  *
608  */
609 void restore_cleanup(JCR *jcr, int TermCode)
610 {
611    char sdt[MAX_TIME_LENGTH], edt[MAX_TIME_LENGTH];
612    char ec1[30], ec2[30], ec3[30], ec4[30], elapsed[50];
613    char term_code[100], fd_term_msg[100], sd_term_msg[100];
614    const char *term_msg;
615    int msg_type = M_INFO;
616    double kbps;
617    utime_t RunTime;
618
619    Dmsg0(20, "In restore_cleanup\n");
620    update_job_end(jcr, TermCode);
621
622    if (jcr->component_fd) {
623       fclose(jcr->component_fd);
624       jcr->component_fd = NULL;
625    }
626    if (jcr->component_fname && *jcr->component_fname) {
627       unlink(jcr->component_fname);
628    }
629    free_and_null_pool_memory(jcr->component_fname);
630
631    if (jcr->unlink_bsr && jcr->RestoreBootstrap) {
632       unlink(jcr->RestoreBootstrap);
633       jcr->unlink_bsr = false;
634    }
635
636    if (job_canceled(jcr)) {
637       cancel_storage_daemon_job(jcr);
638    }
639
640    switch (TermCode) {
641    case JS_Terminated:
642       if (jcr->ExpectedFiles > jcr->jr.JobFiles) {
643          term_msg = _("Restore OK -- warning file count mismatch");
644
645       } else if (jcr->JobErrors > 0 || jcr->SDErrors > 0) {
646          term_msg = _("Restore OK -- with errors");
647
648       } else {
649          term_msg = _("Restore OK");
650       }
651       break;
652    case JS_Warnings:
653          term_msg = _("Restore OK -- with warnings");
654          break;
655    case JS_FatalError:
656    case JS_ErrorTerminated:
657       term_msg = _("*** Restore Error ***");
658       msg_type = M_ERROR;          /* Generate error message */
659       if (jcr->store_bsock) {
660          jcr->store_bsock->signal(BNET_TERMINATE);
661          if (jcr->SD_msg_chan_started) {
662             pthread_cancel(jcr->SD_msg_chan);
663          }
664       }
665       break;
666    case JS_Canceled:
667       term_msg = _("Restore Canceled");
668       if (jcr->store_bsock) {
669          jcr->store_bsock->signal(BNET_TERMINATE);
670          if (jcr->SD_msg_chan_started) {
671             pthread_cancel(jcr->SD_msg_chan);
672          }
673       }
674       break;
675    default:
676       term_msg = term_code;
677       sprintf(term_code, _("Inappropriate term code: %c\n"), TermCode);
678       break;
679    }
680    bstrftimes(sdt, sizeof(sdt), jcr->jr.StartTime);
681    bstrftimes(edt, sizeof(edt), jcr->jr.EndTime);
682
683    RunTime = jcr->jr.EndTime - jcr->jr.StartTime;
684    if (RunTime <= 0) {
685       RunTime = 1;
686    }
687    kbps = (double)jcr->jr.JobBytes / (1000.0 * (double)RunTime);
688    if (kbps < 0.05) {
689       kbps = 0;
690    }
691
692    jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
693    jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
694
695    Jmsg(jcr, msg_type, 0, _("%s %s %s (%s):\n"
696 "  Build OS:               %s %s %s\n"
697 "  JobId:                  %d\n"
698 "  Job:                    %s\n"
699 "  Restore Client:         %s\n"
700 "  Start time:             %s\n"
701 "  End time:               %s\n"
702 "  Elapsed time:           %s\n"
703 "  Files Expected:         %s\n"
704 "  Files Restored:         %s\n"
705 "  Bytes Restored:         %s (%sB)\n"
706 "  Rate:                   %.1f KB/s\n"
707 "  FD Errors:              %d\n"
708 "  FD termination status:  %s\n"
709 "  SD termination status:  %s\n"
710 "  Termination:            %s\n\n"),
711         BACULA, my_name, VERSION, LSMDATE,
712         HOST_OS, DISTNAME, DISTVER,
713         jcr->jr.JobId,
714         jcr->jr.Job,
715         jcr->client->name(),
716         sdt,
717         edt,
718         edit_utime(RunTime, elapsed, sizeof(elapsed)),
719         edit_uint64_with_commas((uint64_t)jcr->ExpectedFiles, ec1),
720         edit_uint64_with_commas((uint64_t)jcr->jr.JobFiles, ec2),
721         edit_uint64_with_commas(jcr->jr.JobBytes, ec3), edit_uint64_with_suffix(jcr->jr.JobBytes, ec4),
722         (float)kbps,
723         jcr->JobErrors,
724         fd_term_msg,
725         sd_term_msg,
726         term_msg);
727
728    Dmsg0(20, "Leaving restore_cleanup\n");
729 }