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

Generated by: LCOV version 1.10