LCOV - code coverage report
Current view: top level - src/server - restore.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 220 320 68.8 %
Date: 2017-10-31 Functions: 12 15 80.0 %

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

Generated by: LCOV version 1.10