LCOV - code coverage report
Current view: top level - src/server/protocol1 - restore.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 0 182 0.0 %
Date: 2015-10-31 Functions: 0 7 0.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 "../../hexmap.h"
      10             : #include "../../log.h"
      11             : #include "../../prepend.h"
      12             : #include "../../protocol1/handy.h"
      13             : #include "../../server/protocol1/backup_phase4.h"
      14             : #include "../../server/protocol1/link.h"
      15             : #include "../../server/protocol1/zlibio.h"
      16             : #include "../../server/protocol2/restore.h"
      17             : #include "../../sbuf.h"
      18             : #include "../../slist.h"
      19             : #include "../sdirs.h"
      20             : #include "dpth.h"
      21             : 
      22             : #include <librsync.h>
      23             : 
      24           0 : static int create_zero_length_file(const char *path)
      25             : {
      26           0 :         int ret=0;
      27             :         struct fzp *dest;
      28           0 :         if(!(dest=fzp_open(path, "wb")))
      29           0 :                 ret=-1;
      30           0 :         ret|=fzp_close(&dest);
      31           0 :         return ret;
      32             : }
      33             : 
      34           0 : static int inflate_or_link_oldfile(struct asfd *asfd, const char *oldpath,
      35             :         const char *infpath, struct conf **cconfs, int compression)
      36             : {
      37           0 :         int ret=0;
      38             :         struct stat statp;
      39             : 
      40           0 :         if(lstat(oldpath, &statp))
      41             :         {
      42           0 :                 logp("could not lstat %s\n", oldpath);
      43           0 :                 return -1;
      44             :         }
      45             : 
      46           0 :         if(dpth_protocol1_is_compressed(compression, oldpath))
      47             :         {
      48             :                 //logp("inflating...\n");
      49             : 
      50           0 :                 if(!statp.st_size)
      51             :                 {
      52             :                         // Empty file - cannot inflate.
      53             :                         logp("asked to inflate zero length file: %s\n",
      54           0 :                                 oldpath);
      55           0 :                         return create_zero_length_file(infpath);
      56             :                 }
      57             : 
      58           0 :                 if((ret=zlib_inflate(asfd, oldpath, infpath, get_cntr(cconfs))))
      59           0 :                         logp("zlib_inflate returned: %d\n", ret);
      60             :         }
      61             :         else
      62             :         {
      63             :                 // Not compressed - just hard link it.
      64           0 :                 if(do_link(oldpath, infpath, &statp, cconfs,
      65           0 :                         1 /* allow overwrite of infpath */))
      66           0 :                                 return -1;
      67             :         }
      68           0 :         return ret;
      69             : }
      70             : 
      71           0 : static int send_file(struct asfd *asfd, struct sbuf *sb,
      72             :         int patches, const char *best,
      73             :         uint64_t *bytes, struct cntr *cntr)
      74             : {
      75           0 :         int ret=0;
      76             :         static BFILE *bfd=NULL;
      77             : 
      78           0 :         if(!bfd && !(bfd=bfile_alloc())) return -1;
      79             : 
      80           0 :         bfile_init(bfd, 0, cntr);
      81           0 :         if(bfd->open_for_send(bfd, asfd, best, sb->winattr,
      82           0 :                 1 /* no O_NOATIME */, cntr, PROTO_1)) return -1;
      83             :         //logp("sending: %s\n", best);
      84           0 :         if(asfd->write(asfd, &sb->path))
      85           0 :                 ret=-1;
      86           0 :         else if(patches)
      87             :         {
      88             :                 // If we did some patches, the resulting file
      89             :                 // is not gzipped. Gzip it during the send. 
      90             :                 ret=send_whole_file_gzl(asfd, best, sb->protocol1->datapth.buf,
      91           0 :                         1, bytes, NULL, cntr, 9, bfd, NULL, 0);
      92             :         }
      93             :         else
      94             :         {
      95             :                 // If it was encrypted, it may or may not have been compressed
      96             :                 // before encryption. Send it as it as, and let the client
      97             :                 // sort it out.
      98           0 :                 if(sbuf_is_encrypted(sb))
      99             :                 {
     100             :                         ret=send_whole_filel(asfd, sb->path.cmd, best,
     101             :                                 sb->protocol1->datapth.buf, 1, bytes,
     102           0 :                                 cntr, bfd, NULL, 0);
     103             :                 }
     104             :                 // It might have been stored uncompressed. Gzip it during
     105             :                 // the send. If the client knew what kind of file it would be
     106             :                 // receiving, this step could disappear.
     107           0 :                 else if(!dpth_protocol1_is_compressed(sb->compression,
     108           0 :                         sb->protocol1->datapth.buf))
     109             :                 {
     110             :                         ret=send_whole_file_gzl(asfd,
     111             :                                 best, sb->protocol1->datapth.buf, 1, bytes,
     112           0 :                                 NULL, cntr, 9, bfd, NULL, 0);
     113             :                 }
     114             :                 else
     115             :                 {
     116             :                         // If we did not do some patches, the resulting
     117             :                         // file might already be gzipped. Send it as it is.
     118             :                         ret=send_whole_filel(asfd, sb->path.cmd, best,
     119             :                                 sb->protocol1->datapth.buf, 1, bytes,
     120           0 :                                 cntr, bfd, NULL, 0);
     121             :                 }
     122             :         }
     123           0 :         bfd->close(bfd, asfd);
     124           0 :         return ret;
     125             : }
     126             : 
     127           0 : static int verify_file(struct asfd *asfd, struct sbuf *sb,
     128             :         int patches, const char *best,
     129             :         uint64_t *bytes, struct cntr *cntr)
     130             : {
     131             :         MD5_CTX md5;
     132           0 :         size_t b=0;
     133           0 :         const char *cp=NULL;
     134           0 :         const char *newsum=NULL;
     135             :         uint8_t in[ZCHUNK];
     136             :         uint8_t checksum[MD5_DIGEST_LENGTH];
     137           0 :         uint64_t cbytes=0;
     138           0 :         struct fzp *fzp=NULL;
     139             : 
     140           0 :         if(!(cp=strrchr(sb->endfile.buf, ':')))
     141             :         {
     142             :                 logw(asfd, cntr,
     143           0 :                         "%s has no md5sum!\n", sb->protocol1->datapth.buf);
     144           0 :                 return 0;
     145             :         }
     146           0 :         cp++;
     147           0 :         if(!MD5_Init(&md5))
     148             :         {
     149           0 :                 logp("MD5_Init() failed\n");
     150           0 :                 return -1;
     151             :         }
     152           0 :         if(patches
     153           0 :           || sb->path.cmd==CMD_ENC_FILE
     154           0 :           || sb->path.cmd==CMD_ENC_METADATA
     155           0 :           || sb->path.cmd==CMD_EFS_FILE
     156           0 :           || sb->path.cmd==CMD_ENC_VSS
     157           0 :           || (!patches && !dpth_protocol1_is_compressed(sb->compression, best)))
     158           0 :                 fzp=fzp_open(best, "rb");
     159             :         else
     160           0 :                 fzp=fzp_gzopen(best, "rb");
     161             : 
     162           0 :         if(!fzp)
     163             :         {
     164           0 :                 logw(asfd, cntr, "could not open %s\n", best);
     165           0 :                 return 0;
     166             :         }
     167           0 :         while((b=fzp_read(fzp, in, ZCHUNK))>0)
     168             :         {
     169           0 :                 cbytes+=b;
     170           0 :                 if(!MD5_Update(&md5, in, b))
     171             :                 {
     172           0 :                         logp("MD5_Update() failed\n");
     173           0 :                         fzp_close(&fzp);
     174           0 :                         return -1;
     175             :                 }
     176             :         }
     177           0 :         if(!fzp_eof(fzp))
     178             :         {
     179           0 :                 logw(asfd, cntr, "error while reading %s\n", best);
     180           0 :                 fzp_close(&fzp);
     181           0 :                 return 0;
     182             :         }
     183           0 :         fzp_close(&fzp);
     184           0 :         if(!MD5_Final(checksum, &md5))
     185             :         {
     186           0 :                 logp("MD5_Final() failed\n");
     187           0 :                 return -1;
     188             :         }
     189           0 :         newsum=bytes_to_md5str(checksum);
     190             : 
     191           0 :         if(strcmp(newsum, cp))
     192             :         {
     193           0 :                 logp("%s %s\n", newsum, cp);
     194             :                 logw(asfd, cntr, "md5sum for '%s (%s)' did not match!\n",
     195           0 :                         sb->path.buf, sb->protocol1->datapth.buf);
     196             :                 logp("md5sum for '%s (%s)' did not match!\n",
     197           0 :                         sb->path.buf, sb->protocol1->datapth.buf);
     198           0 :                 return 0;
     199             :         }
     200           0 :         *bytes+=cbytes;
     201             : 
     202             :         // Just send the file name to the client, so that it can show cntr.
     203           0 :         if(asfd->write(asfd, &sb->path)) return -1;
     204           0 :         return 0;
     205             : }
     206             : 
     207           0 : static int process_data_dir_file(struct asfd *asfd,
     208             :         struct bu *bu, struct bu *b, const char *path,
     209             :         struct sbuf *sb, enum action act, struct sdirs *sdirs,
     210             :         struct conf **cconfs)
     211             : {
     212           0 :         int ret=-1;
     213           0 :         int patches=0;
     214           0 :         char *dpath=NULL;
     215             :         struct stat dstatp;
     216           0 :         const char *tmp=NULL;
     217           0 :         const char *best=NULL;
     218           0 :         uint64_t bytes=0;
     219             :         static char *tmppath1=NULL;
     220             :         static char *tmppath2=NULL;
     221           0 :         struct cntr *cntr=NULL;
     222           0 :         if(cconfs) cntr=get_cntr(cconfs);
     223             : 
     224           0 :         if((!tmppath1 && !(tmppath1=prepend_s(sdirs->client, "tmp1")))
     225           0 :           || (!tmppath2 && !(tmppath2=prepend_s(sdirs->client, "tmp2"))))
     226           0 :                 goto end;
     227             : 
     228           0 :         best=path;
     229           0 :         tmp=tmppath1;
     230             :         // Now go down the list, applying any deltas.
     231           0 :         for(b=b->prev; b && b->next!=bu; b=b->prev)
     232             :         {
     233           0 :                 free_w(&dpath);
     234           0 :                 if(!(dpath=prepend_s(b->delta, sb->protocol1->datapth.buf)))
     235           0 :                         goto end;
     236             : 
     237           0 :                 if(lstat(dpath, &dstatp) || !S_ISREG(dstatp.st_mode))
     238           0 :                         continue;
     239             : 
     240           0 :                 if(!patches)
     241             :                 {
     242             :                         // Need to gunzip the first one.
     243           0 :                         if(inflate_or_link_oldfile(asfd, best, tmp,
     244           0 :                                 cconfs, sb->compression))
     245             :                         {
     246           0 :                                 char msg[256]="";
     247             :                                 snprintf(msg, sizeof(msg),
     248           0 :                                   "error when inflating %s\n", best);
     249           0 :                                 log_and_send(asfd, msg);
     250           0 :                                 goto end;
     251             :                         }
     252           0 :                         best=tmp;
     253           0 :                         if(tmp==tmppath1) tmp=tmppath2;
     254           0 :                         else tmp=tmppath1;
     255             :                 }
     256             : 
     257           0 :                 if(do_patch(asfd, best, dpath, tmp,
     258             :                         0 /* do not gzip the result */,
     259           0 :                         sb->compression /* from the manifest */, cconfs))
     260             :                 {
     261           0 :                         char msg[256]="";
     262             :                         snprintf(msg, sizeof(msg), "error when patching %s\n",
     263           0 :                                 path);
     264           0 :                         log_and_send(asfd, msg);
     265           0 :                         goto end;
     266             :                 }
     267             : 
     268           0 :                 best=tmp;
     269           0 :                 if(tmp==tmppath1) tmp=tmppath2;
     270           0 :                 else tmp=tmppath1;
     271           0 :                 unlink(tmp);
     272           0 :                 patches++;
     273             :         }
     274             : 
     275           0 :         switch(act)
     276             :         {
     277             :                 case ACTION_RESTORE:
     278           0 :                         if(send_file(asfd, sb, patches, best, &bytes, cntr))
     279           0 :                                 goto end;
     280           0 :                         break;
     281             :                 case ACTION_VERIFY:
     282           0 :                         if(verify_file(asfd, sb, patches, best, &bytes, cntr))
     283           0 :                                 goto end;
     284           0 :                         break;
     285             :                 default:
     286           0 :                         logp("Unknown action: %d\n", act);
     287           0 :                         goto end;
     288             :         }
     289           0 :         cntr_add(cntr, sb->path.cmd, 0);
     290           0 :         cntr_add_bytes(cntr, strtoull(sb->endfile.buf, NULL, 10));
     291           0 :         cntr_add_sentbytes(cntr, bytes);
     292             : 
     293           0 :         ret=0;
     294             : end:
     295           0 :         free_w(&dpath);
     296           0 :         return ret;
     297             : }
     298             : 
     299             : // a = length of struct bu array
     300             : // i = position to restore from
     301           0 : static int restore_file(struct asfd *asfd, struct bu *bu,
     302             :         struct sbuf *sb, enum action act,
     303             :         struct sdirs *sdirs, struct conf **cconfs)
     304             : {
     305           0 :         int ret=-1;
     306           0 :         char *path=NULL;
     307             :         struct bu *b;
     308           0 :         struct bu *hlwarn=NULL;
     309             :         struct stat statp;
     310           0 :         struct cntr *cntr=NULL;
     311           0 :         if(cconfs) cntr=get_cntr(cconfs);
     312             : 
     313             :         // Go up the array until we find the file in the data directory.
     314           0 :         for(b=bu; b; b=b->next)
     315             :         {
     316           0 :                 free_w(&path);
     317           0 :                 if(!(path=prepend_s(b->data, sb->protocol1->datapth.buf)))
     318           0 :                         goto end;
     319             : 
     320           0 :                 if(lstat(path, &statp) || !S_ISREG(statp.st_mode))
     321           0 :                         continue;
     322             : 
     323           0 :                 if(b!=bu && (bu->flags & BU_HARDLINKED)) hlwarn=b;
     324             : 
     325           0 :                 if(process_data_dir_file(asfd, bu, b,
     326           0 :                         path, sb, act, sdirs, cconfs)) goto end;
     327             : 
     328             :                 // This warning must be done after everything else,
     329             :                 // Because the client does not expect another cmd after
     330             :                 // the warning.
     331           0 :                 if(hlwarn) logw(asfd, cntr, "restore found %s in %s\n",
     332           0 :                         sb->path.buf, hlwarn->basename);
     333           0 :                 ret=0; // All OK.
     334           0 :                 break;
     335             :         }
     336             : 
     337           0 :         if(!b) logw(asfd, cntr, "restore could not find %s (%s)\n",
     338           0 :                 sb->path.buf, sb->protocol1->datapth.buf);
     339             : end:
     340           0 :         free_w(&path);
     341           0 :         return ret;
     342             : }
     343             : 
     344           0 : int restore_sbuf_protocol1(struct asfd *asfd, struct sbuf *sb, struct bu *bu,
     345             :         enum action act, struct sdirs *sdirs,
     346             :         enum cntr_status cntr_status, struct conf **cconfs)
     347             : {
     348           0 :         if((sb->protocol1->datapth.buf
     349           0 :                 && asfd->write(asfd, &(sb->protocol1->datapth)))
     350           0 :           || asfd->write(asfd, &sb->attr))
     351           0 :                 return -1;
     352           0 :         else if(sbuf_is_filedata(sb)
     353           0 :           || sbuf_is_vssdata(sb))
     354             :         {
     355           0 :                 if(!sb->protocol1->datapth.buf)
     356             :                 {
     357             :                         logw(asfd, get_cntr(cconfs),
     358             :                                 "Got filedata entry with no datapth: %c:%s\n",
     359           0 :                                         sb->path.cmd, sb->path.buf);
     360           0 :                         return 0;
     361             :                 }
     362           0 :                 return restore_file(asfd, bu, sb, act, sdirs, cconfs);
     363             :         }
     364             :         else
     365             :         {
     366           0 :                 if(asfd->write(asfd, &sb->path))
     367           0 :                         return -1;
     368             :                 // If it is a link, send what
     369             :                 // it points to.
     370           0 :                 else if(sbuf_is_link(sb)
     371           0 :                   && asfd->write(asfd, &sb->link)) return -1;
     372           0 :                 cntr_add(get_cntr(cconfs), sb->path.cmd, 0);
     373             :         }
     374           0 :         return 0;
     375             : }

Generated by: LCOV version 1.10