LCOV - code coverage report
Current view: top level - src/server - restore.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 160 272 58.8 %
Date: 2022-08-30 22:36:43 Functions: 13 16 81.2 %

          Line data    Source code
       1             : #include "../burp.h"
       2             : #include "../alloc.h"
       3             : #include "../asfd.h"
       4             : #include "../async.h"
       5             : #include "../bu.h"
       6             : #include "../cmd.h"
       7             : #include "../cntr.h"
       8             : #include "../cstat.h"
       9             : #include "../handy.h"
      10             : #include "../hexmap.h"
      11             : #include "../linkhash.h"
      12             : #include "../lock.h"
      13             : #include "../log.h"
      14             : #include "../pathcmp.h"
      15             : #include "../prepend.h"
      16             : #include "../regexp.h"
      17             : #include "../slist.h"
      18             : #include "../strlist.h"
      19             : #include "bu_get.h"
      20             : #include "child.h"
      21             : #include "compress.h"
      22             : #include "manio.h"
      23             : #include "restore_sbuf.h"
      24             : #include "rubble.h"
      25             : #include "sdirs.h"
      26             : 
      27           1 : static enum asl_ret restore_end_func(struct asfd *asfd,
      28             :         __attribute__ ((unused)) struct conf **confs,
      29             :         __attribute__ ((unused)) void *param)
      30             : {
      31           1 :         if(!strcmp(asfd->rbuf->buf, "restoreend ok"))
      32             :                 return ASL_END_OK;
      33             :         // Old v2 clients send something slightly different.
      34           0 :         if(!strcmp(asfd->rbuf->buf, "restoreend_ok"))
      35             :                 return ASL_END_OK;
      36           0 :         iobuf_log_unexpected(asfd->rbuf, __func__);
      37           0 :         return ASL_END_ERROR;
      38             : }
      39             : 
      40           1 : static int restore_end(struct asfd *asfd, struct conf **confs)
      41             : {
      42           1 :         if(asfd->write_str(asfd, CMD_GEN, "restoreend")) return -1;
      43           1 :         return asfd->simple_loop(asfd, confs, NULL, __func__, restore_end_func);
      44             : }
      45             : 
      46             : static int srestore_matches(struct strlist *s, const char *path)
      47             : {
      48           0 :         int r=0;
      49           0 :         if(!s->flag) return 0; // Do not know how to do excludes yet.
      50           0 :         if((r=strncmp_w(path, s->path))) return 0; // no match
      51             :         if(!r) return 1; // exact match
      52             :         if(*(path+strlen(s->path)+1)=='/')
      53             :                 return 1; // matched directory contents
      54             :         return 0; // no match
      55             : }
      56             : 
      57             : // Used when restore is initiated from the server.
      58           0 : static int srestore_check(struct conf **confs, const char *path)
      59             : {
      60           0 :         struct strlist *l=get_strlist(confs[OPT_INCEXCDIR]);
      61             : 
      62             :         // If no includes specified, restore everything.
      63           0 :         if(!l) return 1;
      64             : 
      65           0 :         for(; l; l=l->next)
      66           0 :                 if(srestore_matches(l, path))
      67             :                         return 1;
      68             :         return 0;
      69             : }
      70             : 
      71           0 : static int restore_list_check(
      72             :         struct asfd *asfd,
      73             :         struct cntr *cntr,
      74             :         struct fzp *rl_fzp,
      75             :         struct iobuf *rl_iobuf,
      76             :         const char *path
      77             : )
      78             : {
      79           0 :         char *last=NULL;
      80             : 
      81             :         do {
      82           0 :                 if(!rl_iobuf->buf)
      83             :                 {
      84           0 :                         switch(iobuf_fill_from_fzp(rl_iobuf, rl_fzp))
      85             :                         {
      86             :                                 case 0: break; // OK, read something.
      87             :                                 case 1: return 0; // Finished, no match.
      88           0 :                                 default: return -1; // Error.
      89             :                         }
      90             :                 }
      91             : 
      92           0 :                 if(last && pathcmp(rl_iobuf->buf, last)!=1)
      93             :                 {
      94           0 :                         logw(asfd, cntr,
      95             :                                 "Input file ordering problem: '%s' '%s'",
      96             :                                         last, rl_iobuf->buf);
      97             :                 }
      98             : 
      99           0 :                 switch(pathcmp(rl_iobuf->buf, path))
     100             :                 {
     101             :                         case 0: return 1; // Successful match.
     102           0 :                         case 1: return 0; // Ahead in input, no match.
     103             :                         default:
     104             :                                 // Behind, need to read more from input.
     105           0 :                                 free_w(&last);
     106           0 :                                 last=rl_iobuf->buf;
     107           0 :                                 rl_iobuf->buf=NULL;
     108             :                 }
     109             :         } while (1);
     110             : 
     111             :         return 0;
     112             : }
     113             : 
     114          10 : static int want_to_restore(
     115             :         struct asfd *asfd,
     116             :         int srestore,
     117             :         struct fzp *input_fzp,
     118             :         struct iobuf *input_iobuf,
     119             :         struct sbuf *sb,
     120             :         regex_t *regex,
     121             :         enum action act,
     122             :         struct conf **cconfs
     123             : ) {
     124          10 :         if(act==ACTION_RESTORE)
     125             :         {
     126             :                 // Do not send VSS data to non-windows, or to windows client
     127             :                 // that asked us not to send it.
     128          10 :                 if(!get_int(cconfs[OPT_CLIENT_IS_WINDOWS])
     129           0 :                   || get_int(cconfs[OPT_VSS_RESTORE])!=VSS_RESTORE_ON)
     130             :                 {
     131          10 :                         if(sbuf_is_vssdata(sb))
     132             :                                 return 0;
     133             :                         // Do not send VSS directory data to non-windows.
     134          10 :                         if(S_ISDIR(sb->statp.st_mode)
     135           0 :                           && sbuf_is_filedata(sb)
     136           0 :                           && !sbuf_is_metadata(sb))
     137             :                                 return 0;
     138             :                 }
     139             :         }
     140             :         return
     141             :           (!input_fzp
     142           0 :                 || restore_list_check(asfd, get_cntr(cconfs),
     143           0 :                         input_fzp, input_iobuf, sb->path.buf))
     144          10 :           && (!srestore
     145           0 :                 || srestore_check(cconfs, sb->path.buf))
     146          20 :           && (!regex
     147           0 :                 || regex_check(regex, sb->path.buf));
     148             : }
     149             : 
     150           1 : static int maybe_open_restore_list(
     151             :         struct conf **cconfs,
     152             :         struct fzp **rl_fzp,
     153             :         struct iobuf **rl_iobuf,
     154             :         struct sdirs *sdirs
     155             : ) {
     156           1 :         if(!get_string(cconfs[OPT_RESTORE_LIST]))
     157             :                 return 0;
     158             : 
     159           0 :         if(!(*rl_fzp=fzp_open(sdirs->restore_list, "rb"))
     160           0 :           || !(*rl_iobuf=iobuf_alloc()))
     161             :                 return -1;
     162             : 
     163             :         return 0;
     164             : }
     165             : 
     166           1 : static int setup_cntr(struct asfd *asfd, const char *manifest,
     167             :         regex_t *regex, int srestore, struct conf **cconfs, enum action act,
     168             :         struct bu *bu, struct sdirs *sdirs)
     169             : {
     170           1 :         int ars=0;
     171           1 :         int ret=-1;
     172           1 :         struct fzp *fzp=NULL;
     173           1 :         struct sbuf *sb=NULL;
     174           1 :         struct cntr *cntr=NULL;
     175           1 :         struct fzp *rl_fzp=NULL;
     176           1 :         struct iobuf *rl_iobuf=NULL;
     177             : 
     178           1 :         cntr=get_cntr(cconfs);
     179           1 :         if(!cntr) return 0;
     180           0 :         cntr->bno=(int)bu->bno;
     181             : 
     182           0 :         if(maybe_open_restore_list(cconfs, &rl_fzp, &rl_iobuf, sdirs))
     183             :                 goto end;
     184             : 
     185           0 :         if(!(sb=sbuf_alloc())) goto end;
     186           0 :         if(!(fzp=fzp_gzopen(manifest, "rb")))
     187             :         {
     188           0 :                 log_and_send(asfd, "could not open manifest");
     189             :                 goto end;
     190             :         }
     191             :         while(1)
     192             :         {
     193           0 :                 if((ars=sbuf_fill_from_file(sb, fzp)))
     194             :                 {
     195           0 :                         if(ars<0) goto end;
     196             :                         // ars==1 means end ok
     197             :                         break;
     198             :                 }
     199             :                 else
     200             :                 {
     201           0 :                         if(want_to_restore(asfd, srestore,
     202             :                                 rl_fzp, rl_iobuf,
     203             :                                 sb, regex, act, cconfs))
     204             :                         {
     205           0 :                                 cntr_add_phase1(cntr, sb->path.cmd, 0);
     206           0 :                                 if(sb->endfile.buf)
     207           0 :                                   cntr_add_val(cntr,
     208             :                                         CMD_BYTES_ESTIMATED,
     209           0 :                                         strtoull(sb->endfile.buf,
     210             :                                                 NULL, 10));
     211             :                         }
     212             :                 }
     213           0 :                 sbuf_free_content(sb);
     214             :         }
     215           0 :         ret=0;
     216             : end:
     217           0 :         iobuf_free(&rl_iobuf);
     218           0 :         fzp_close(&rl_fzp);
     219           0 :         sbuf_free(&sb);
     220           0 :         fzp_close(&fzp);
     221             :         return ret;
     222             : }
     223             : 
     224             : static int restore_sbuf(struct asfd *asfd, struct sbuf *sb, struct bu *bu,
     225             :         enum action act, struct sdirs *sdirs, enum cntr_status cntr_status,
     226             :         struct conf **cconfs, const char *manifest,
     227             :         struct slist *slist);
     228             : 
     229             : // Used when restoring a hard link that we have not restored the destination
     230             : // for. Read through the manifest from the beginning and substitute the path
     231             : // and data to the new location.
     232           0 : static int hard_link_substitution(struct asfd *asfd,
     233             :         struct sbuf *sb, struct f_link *lp,
     234             :         struct bu *bu, enum action act, struct sdirs *sdirs,
     235             :         enum cntr_status cntr_status, struct conf **cconfs,
     236             :         const char *manifest, struct slist *slist)
     237             : {
     238           0 :         int ret=-1;
     239           0 :         struct sbuf *hb=NULL;
     240           0 :         struct manio *manio=NULL;
     241             :         int pcmp;
     242             : 
     243           0 :         if(!(manio=manio_open(manifest, "rb"))
     244           0 :           || !(hb=sbuf_alloc()))
     245             :                 goto end;
     246             : 
     247             :         while(1)
     248             :         {
     249           0 :                 switch(manio_read(manio, hb))
     250             :                 {
     251             :                         case 0: break; // Keep going.
     252           0 :                         case 1: ret=0; goto end; // Finished OK.
     253             :                         default: goto end; // Error;
     254             :                 }
     255             : 
     256           0 :                 pcmp=pathcmp(lp->name, hb->path.buf);
     257             : 
     258           0 :                 if(!pcmp && (sbuf_is_filedata(hb) || sbuf_is_vssdata(hb)))
     259             :                 {
     260             :                         // Copy the path from sb to hb.
     261           0 :                         free_w(&hb->path.buf);
     262           0 :                         if(!(hb->path.buf=strdup_w(sb->path.buf, __func__)))
     263             :                                 goto end;
     264           0 :                         hb->path.len = sb->path.len;
     265             :                         // Should now be able to restore the original data
     266             :                         // to the new location.
     267           0 :                         ret=restore_sbuf(asfd, hb, bu, act, sdirs,
     268             :                           cntr_status, cconfs, manifest, slist);
     269             :                         break;
     270             :                 }
     271             : 
     272           0 :                 sbuf_free_content(hb);
     273             :                 // Break out once we have gone past the entry that we are
     274             :                 // interested in.
     275           0 :                 if(pcmp<0) break;
     276             :         }
     277             : end:
     278           0 :         sbuf_free(&hb);
     279           0 :         manio_close(&manio);
     280           0 :         return ret;
     281             : }
     282             : 
     283          10 : static int restore_sbuf(struct asfd *asfd, struct sbuf *sb, struct bu *bu,
     284             :         enum action act, struct sdirs *sdirs, enum cntr_status cntr_status,
     285             :         struct conf **cconfs, const char *manifest,
     286             :         struct slist *slist)
     287             : {
     288             :         //printf("%s: %s\n", act==ACTION_RESTORE?"restore":"verify",
     289             :         //  iobuf_to_printable(&sb->path));
     290          10 :         if(timed_operation_status_only(cntr_status, sb->path.buf, cconfs))
     291             :                 return -1;
     292             : 
     293          10 :         if(sb->path.cmd==CMD_HARD_LINK)
     294             :         {
     295           1 :                 struct f_link *lp=NULL;
     296           1 :                 struct f_link **bucket=NULL;
     297           1 :                 if((lp=linkhash_search(&sb->statp, &bucket)))
     298             :                 {
     299             :                         // It is in the list of stuff that is in the manifest,
     300             :                         // but was skipped on this restore.
     301             :                         // Need to go through the manifest from the beginning,
     302             :                         // and substitute in the data to restore to this
     303             :                         // location.
     304           0 :                         return hard_link_substitution(asfd, sb, lp,
     305             :                                 bu, act, sdirs,
     306             :                                 cntr_status, cconfs, manifest, slist);
     307             :                         // FIX THIS: Would be nice to remember the new link
     308             :                         // location so that further hard links would link to
     309             :                         // it instead of doing the hard_link_substitution
     310             :                         // business over again.
     311             :                 }
     312             :         }
     313             : 
     314          10 :         return restore_sbuf_all(asfd, sb, bu, act, sdirs, cconfs);
     315             : }
     316             : 
     317          10 : static int restore_ent(struct asfd *asfd,
     318             :         struct sbuf **sb,
     319             :         struct slist *slist,
     320             :         struct bu *bu,
     321             :         enum action act,
     322             :         struct sdirs *sdirs,
     323             :         enum cntr_status cntr_status,
     324             :         struct conf **cconfs,
     325             :         int *last_ent_was_dir,
     326             :         const char *manifest)
     327             : {
     328          10 :         int ret=-1;
     329             :         struct sbuf *xb;
     330             : 
     331          10 :         if(!(*sb)->path.buf)
     332             :         {
     333           0 :                 logp("Got NULL path!\n");
     334           0 :                 return -1;
     335             :         }
     336             : 
     337             :         // Check if we have any directories waiting to be restored.
     338          10 :         while((xb=slist->head))
     339             :         {
     340           0 :                 if(is_subdir(xb->path.buf, (*sb)->path.buf))
     341             :                 {
     342             :                         // We are still in a subdir.
     343             :                         break;
     344             :                 }
     345             :                 else
     346             :                 {
     347             :                         // Can now restore xb because nothing else is fiddling
     348             :                         // in a subdirectory.
     349           0 :                         if(restore_sbuf(asfd, xb, bu,
     350             :                           act, sdirs, cntr_status, cconfs, manifest,
     351             :                           slist))
     352             :                                 goto end;
     353           0 :                         slist->head=xb->next;
     354           0 :                         sbuf_free(&xb);
     355             :                 }
     356             :         }
     357             : 
     358             :         /* If it is a directory, need to remember it and restore it later, so
     359             :            that the permissions come out right. */
     360             :         /* Meta data of directories will also have the stat stuff set to be a
     361             :            directory, so will also come out at the end. */
     362             :         /* FIX THIS: for Windows, need to read and remember the blocks that
     363             :            go with the directories. Probably have to do the same for metadata
     364             :            that goes with directories. */
     365          10 :         if(S_ISDIR((*sb)->statp.st_mode)
     366             :           // Hack for metadata for now - just do it straight away.
     367           0 :           && !sbuf_is_metadata(*sb))
     368             :         {
     369             :                 // Add to the head of the list instead of the tail.
     370           0 :                 (*sb)->next=slist->head;
     371           0 :                 slist->head=*sb;
     372             : 
     373           0 :                 *last_ent_was_dir=1;
     374             : 
     375             :                 // Allocate a new sb.
     376           0 :                 if(!(*sb=sbuf_alloc())) goto end;
     377             :         }
     378             :         else
     379             :         {
     380          10 :                 *last_ent_was_dir=0;
     381          10 :                 if(restore_sbuf(asfd, *sb, bu,
     382             :                   act, sdirs, cntr_status, cconfs, manifest,
     383             :                   slist))
     384             :                         goto end;
     385             :         }
     386             :         ret=0;
     387             : end:
     388             :         return ret;
     389             : }
     390             : 
     391             : static int restore_remaining_dirs(struct asfd *asfd, struct bu *bu,
     392             :         struct slist *slist, enum action act, struct sdirs *sdirs,
     393             :         struct conf **cconfs)
     394             : {
     395           1 :         int ret=-1;
     396             :         struct sbuf *sb;
     397             :         // Restore any directories that are left in the list.
     398           1 :         for(sb=slist->head; sb; sb=sb->next)
     399             :         {
     400           0 :                 if(restore_sbuf_all(asfd, sb, bu, act, sdirs, cconfs))
     401             :                                 goto end;
     402             :         }
     403             :         ret=0;
     404             : end:
     405             :         return ret;
     406             : }
     407             : 
     408           1 : static int restore_stream(struct asfd *asfd, struct sdirs *sdirs,
     409             :         struct slist *slist, struct bu *bu, const char *manifest,
     410             :         regex_t *regex, int srestore, struct conf **cconfs, enum action act,
     411             :         enum cntr_status cntr_status)
     412             : {
     413           1 :         int ret=-1;
     414           1 :         int last_ent_was_dir=0;
     415           1 :         struct sbuf *sb=NULL;
     416           1 :         struct iobuf *rbuf=asfd->rbuf;
     417           1 :         struct manio *manio=NULL;
     418           1 :         struct cntr *cntr=get_cntr(cconfs);
     419             :         struct iobuf interrupt;
     420           1 :         struct fzp *rl_fzp=NULL;
     421           1 :         struct iobuf *rl_iobuf=NULL;
     422             : 
     423           1 :         iobuf_init(&interrupt);
     424             : 
     425           1 :         if(maybe_open_restore_list(cconfs, &rl_fzp, &rl_iobuf, sdirs))
     426             :                 goto end;
     427             : 
     428           1 :         if(!(manio=manio_open(manifest, "rb"))
     429           1 :           || !(sb=sbuf_alloc()))
     430             :                 goto end;
     431             : 
     432             :         while(1)
     433             :         {
     434          11 :                 iobuf_free_content(rbuf);
     435          11 :                 if(asfd->as->read_quick(asfd->as))
     436             :                 {
     437           0 :                         logp("read quick error\n");
     438           0 :                         goto end;
     439             :                 }
     440          11 :                 if(rbuf->buf) switch(rbuf->cmd)
     441             :                 {
     442             :                         case CMD_MESSAGE:
     443             :                         case CMD_WARNING:
     444             :                         {
     445           0 :                                 log_recvd(rbuf, cntr, 0);
     446           0 :                                 continue;
     447             :                         }
     448             :                         case CMD_INTERRUPT:
     449             :                                 // Client wanted to interrupt the
     450             :                                 // sending of a file. But if we are
     451             :                                 // here, we have already moved on.
     452             :                                 // Ignore.
     453           0 :                                 continue;
     454             :                         default:
     455           0 :                                 iobuf_log_unexpected(rbuf, __func__);
     456           0 :                                 goto end;
     457             :                 }
     458             : 
     459          11 :                 switch(manio_read(manio, sb))
     460             :                 {
     461             :                         case 0: break; // Keep going.
     462           1 :                         case 1: ret=0; goto end; // Finished OK.
     463             :                         default: goto end; // Error;
     464             :                 }
     465             : 
     466          10 :                 if(want_to_restore(asfd, srestore, rl_fzp, rl_iobuf,
     467             :                         sb, regex, act, cconfs))
     468             :                 {
     469          10 :                         if(restore_ent(asfd, &sb, slist,
     470             :                                 bu, act, sdirs, cntr_status, cconfs,
     471             :                                 &last_ent_was_dir, manifest))
     472             :                                         goto end;
     473             :                 }
     474             :                 else
     475             :                 {
     476           0 :                         if(sbuf_is_filedata(sb) || sbuf_is_vssdata(sb))
     477             :                         {
     478             :                                 // Add it to the list of filedata that was not
     479             :                                 // restored.
     480           0 :                                 struct f_link **bucket=NULL;
     481           0 :                                 if(!linkhash_search(&sb->statp, &bucket)
     482           0 :                                   && linkhash_add(sb->path.buf, &sb->statp, bucket))
     483             :                                         goto end;
     484             :                         }
     485             :                 }
     486             : 
     487          10 :                 sbuf_free_content(sb);
     488             :         }
     489             : end:
     490           1 :         iobuf_free(&rl_iobuf);
     491           1 :         fzp_close(&rl_fzp);
     492           1 :         sbuf_free(&sb);
     493           1 :         iobuf_free_content(rbuf);
     494           1 :         iobuf_free_content(&interrupt);
     495           1 :         manio_close(&manio);
     496           1 :         return ret;
     497             : }
     498             : 
     499           1 : static int actual_restore(struct asfd *asfd, struct bu *bu,
     500             :         const char *manifest, regex_t *regex, int srestore, enum action act,
     501             :         struct sdirs *sdirs, enum cntr_status cntr_status, struct conf **cconfs)
     502             : {
     503           1 :         int ret=-1;
     504             :         // For out-of-sequence directory restoring so that the
     505             :         // timestamps come out right:
     506           1 :         struct slist *slist=NULL;
     507           1 :         struct cntr *cntr=NULL;
     508             : 
     509           1 :         if(linkhash_init()
     510           1 :           || !(slist=slist_alloc()))
     511             :                 goto end;
     512             : 
     513           1 :         if(restore_stream(asfd, sdirs, slist,
     514             :                 bu, manifest, regex,
     515             :                 srestore, cconfs, act, cntr_status))
     516             :                         goto end;
     517             : 
     518           2 :         if(restore_remaining_dirs(asfd, bu, slist,
     519             :                 act, sdirs, cconfs)) goto end;
     520             : 
     521           1 :         if(cconfs) cntr=get_cntr(cconfs);
     522           1 :         cntr_set_bytes(cntr, asfd);
     523           1 :         cntr_print(cntr, act);
     524           1 :         if(cntr_stats_to_file(cntr, bu->path, act))
     525             :                 goto end;
     526           1 :         ret=0;
     527             : end:
     528           1 :         slist_free(&slist);
     529           1 :         linkhash_free();
     530           1 :         return ret;
     531             : }
     532             : 
     533           1 : static int get_logpaths(struct bu *bu, const char *file,
     534             :         char **logpath, char **logpathz)
     535             : {
     536           1 :         if(!(*logpath=prepend_s(bu->path, file))
     537           1 :           || !(*logpathz=prepend(*logpath, ".gz")))
     538             :                 return -1;
     539             :         return 0;
     540             : }
     541             : 
     542           1 : static void parallelism_warnings(struct asfd *asfd, struct conf **cconfs,
     543             :         struct sdirs *sdirs, struct bu *bu)
     544             : {
     545             :         struct bu *b;
     546             : 
     547           1 :         if(lock_test(sdirs->lock_storage_for_write->path))
     548             :         {
     549           0 :                 logm(asfd, cconfs, "Another process is currently backing up or deleting for this client.\n");
     550           0 :                 return;
     551             :         }
     552             : 
     553           1 :         if(!check_for_rubble(sdirs))
     554             :                 return;
     555             : 
     556           0 :         for(b=bu; b && b->next; b=b->next)
     557             :         {
     558           0 :                 if(b->flags & BU_CURRENT)
     559             :                         break; // Warning.
     560           0 :                 if(b->flags & BU_HARDLINKED)
     561             :                         return; // No warning.
     562             :         }
     563             : 
     564           0 :         logw(asfd, get_cntr(cconfs),
     565             :                 "The latest backup needs recovery, but continuing anyway.\n");
     566             : }
     567             : 
     568           1 : static int restore_manifest(struct asfd *asfd, struct bu *bu,
     569             :         regex_t *regex, int srestore, enum action act, struct sdirs *sdirs,
     570             :         char **dir_for_notify, struct conf **cconfs)
     571             : {
     572           1 :         int ret=-1;
     573           1 :         char *manifest=NULL;
     574           1 :         char *logpath=NULL;
     575           1 :         char *logpathz=NULL;
     576             :         enum cntr_status cntr_status;
     577           1 :         struct lock *lock=NULL;
     578           1 :         char *lockfile=NULL;
     579             :         static int manifest_count=0;
     580             : 
     581           1 :         if(!(lockfile=prepend_s(bu->path, "lockfile.read"))
     582           1 :           || !(lock=lock_alloc_and_init(lockfile)))
     583             :                 goto end;
     584           1 :         lock_get(lock);
     585           1 :         if(lock->status!=GET_LOCK_GOT)
     586             :         {
     587           0 :                 char msg[256]="";
     588           0 :                 snprintf(msg, sizeof(msg), "Another process is restoring or verifying backup %s.\n", bu->timestamp);
     589           0 :                 log_and_send(asfd, msg);
     590             :                 goto end;
     591             :         }
     592             : 
     593             :         // For sending status information up to the server.
     594           1 :         cntr_status=CNTR_STATUS_RESTORING;
     595             : 
     596           1 :         if(act==ACTION_RESTORE) cntr_status=CNTR_STATUS_RESTORING;
     597           0 :         else if(act==ACTION_VERIFY) cntr_status=CNTR_STATUS_VERIFYING;
     598             : 
     599           1 :         if((act==ACTION_RESTORE && get_logpaths(bu, "restorelog",
     600             :                 &logpath, &logpathz))
     601           1 :           || (act==ACTION_VERIFY && get_logpaths(bu, "verifylog",
     602             :                 &logpath, &logpathz))
     603           1 :           || !(manifest=prepend_s(bu->path, "manifest.gz")))
     604             :         {
     605           0 :                 log_and_send_oom(asfd);
     606           0 :                 goto end;
     607             :         }
     608             : 
     609           1 :         if(log_fzp_set(logpath, cconfs))
     610             :         {
     611           0 :                 char msg[256]="";
     612           0 :                 snprintf(msg, sizeof(msg),
     613             :                                 "could not open log file: %s", logpath);
     614           0 :                 log_and_send(asfd, msg);
     615             :                 goto end;
     616             :         }
     617             : 
     618           1 :         *dir_for_notify=strdup_w(bu->path, __func__);
     619             : 
     620           1 :         log_restore_settings(cconfs, srestore);
     621             : 
     622             :         // First, do a pass through the manifest to set up cntr.
     623             :         // This is the equivalent of a phase1 scan during backup.
     624             : 
     625           1 :         if(setup_cntr(asfd, manifest,
     626             :                 regex, srestore, cconfs, act, bu, sdirs))
     627             :                         goto end;
     628             : 
     629           1 :         if(!manifest_count)
     630             :         {
     631             :                 // FIX THIS: Only send the counters once, otherwise the
     632             :                 // client will break on '-b a' because it does not expect
     633             :                 // multiple sets of counters to turn up.
     634             :                 // This means that the client side 'expected' counter will be
     635             :                 // confusing in that case. Live with it for now.
     636             :                 // However, the server side log will be OK.
     637           1 :                 if(cntr_send_bu(asfd, bu, cconfs, cntr_status))
     638             :                         goto end;
     639             :         }
     640             : 
     641           1 :         parallelism_warnings(asfd, cconfs, sdirs, bu);
     642             : 
     643             :         // Now, do the actual restore.
     644           1 :         ret=actual_restore(asfd, bu, manifest,
     645             :                   regex, srestore, act, sdirs, cntr_status, cconfs);
     646             : end:
     647           1 :         log_fzp_set(NULL, cconfs);
     648           1 :         if(logpath && logpathz)
     649           1 :                 compress_file(logpath, logpathz,
     650             :                         get_int(cconfs[OPT_COMPRESSION]));
     651           1 :         free_w(&manifest);
     652           1 :         free_w(&logpath);
     653           1 :         free_w(&logpathz);
     654           1 :         free_w(&lockfile);
     655           1 :         lock_release(lock);
     656           1 :         lock_free(&lock);
     657           1 :         manifest_count++;
     658           1 :         return ret;
     659             : }
     660             : 
     661           4 : int do_restore_server(struct asfd *asfd, struct sdirs *sdirs,
     662             :         enum action act, int srestore,
     663             :         char **dir_for_notify, struct conf **confs)
     664             : {
     665           4 :         int ret=-1;
     666           4 :         uint8_t found=0;
     667           4 :         struct bu *bu=NULL;
     668           4 :         struct bu *bu_list=NULL;
     669           4 :         unsigned long bno=0;
     670           4 :         regex_t *regex=NULL;
     671           4 :         const char *regexstr=get_string(confs[OPT_REGEX]);
     672           4 :         const char *backup=get_string(confs[OPT_BACKUP]);
     673           4 :         int regex_case_insensitive=get_int(confs[OPT_REGEX_CASE_INSENSITIVE]);
     674             : 
     675           4 :         logp("in do_restore\n");
     676             : 
     677           4 :         if(regexstr
     678           1 :           && *regexstr
     679           1 :           && !(regex=regex_compile_restore(regexstr, regex_case_insensitive)))
     680             :         {
     681           1 :                 char msg[256]="";
     682           1 :                 snprintf(msg, sizeof(msg), "unable to compile regex: %s\n",
     683             :                         regexstr);
     684           1 :                 log_and_send(asfd, msg);
     685             :                 goto end;
     686             :         }
     687             : 
     688           3 :         if(bu_get_list(sdirs, &bu_list))
     689             :                 goto end;
     690             : 
     691           3 :         if(bu_list &&
     692             :            (!backup
     693           1 :          || !*backup
     694           1 :          || (!(bno=strtoul(backup, NULL, 10)) && *backup!='a')))
     695             :         {
     696           0 :                 found=1;
     697             :                 // No backup specified, do the most recent.
     698           0 :                 for(bu=bu_list; bu && bu->next; bu=bu->next) { }
     699           0 :                 ret=restore_manifest(asfd, bu, regex, srestore,
     700             :                                 act, sdirs, dir_for_notify, confs);
     701             :         }
     702             : 
     703           3 :         if(!found) for(bu=bu_list; bu; bu=bu->next)
     704             :         {
     705           1 :                 if(!strcmp(bu->timestamp, backup)
     706           1 :                   || bu->bno==bno || (backup && *backup=='a'))
     707             :                 {
     708           1 :                         found=1;
     709             :                         //logp("got: %s\n", bu->path);
     710           1 :                         ret|=restore_manifest(asfd, bu, regex, srestore,
     711             :                                 act, sdirs, dir_for_notify, confs);
     712           1 :                         if(backup && *backup=='a')
     713           0 :                                 continue;
     714             :                         break;
     715             :                 }
     716             :         }
     717             : 
     718           3 :         bu_list_free(&bu_list);
     719             : 
     720             : 
     721           3 :         if(found)
     722             :         {
     723             :                 // Restore has nearly completed OK.
     724           1 :                 ret=restore_end(asfd, confs);
     725             :         }
     726             :         else
     727             :         {
     728           2 :                 logp("backup not found\n");
     729           2 :                 asfd->write_str(asfd, CMD_ERROR, "backup not found");
     730           2 :                 ret=-1;
     731             :         }
     732             : end:
     733           4 :         regex_free(&regex);
     734           4 :         return ret;
     735             : }

Generated by: LCOV version 1.13