LCOV - code coverage report
Current view: top level - src/server - restore.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 240 378 63.5 %
Date: 2020-07-31 05:59:47 Functions: 14 18 77.8 %

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

Generated by: LCOV version 1.13