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

Generated by: LCOV version 1.13