"Fossies" - the Fresh Open Source Software Archive

Member "burp-2.3.6/src/client/protocol1/backup_phase2.c" (28 Apr 2019, 11021 Bytes) of package /linux/privat/burp-2.3.6.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "backup_phase2.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.3.0_vs_2.3.6.

    1 #include "../../burp.h"
    2 #include "../../action.h"
    3 #include "../../alloc.h"
    4 #include "../../asfd.h"
    5 #include "../../async.h"
    6 #include "../../attribs.h"
    7 #include "../../cmd.h"
    8 #include "../../cntr.h"
    9 #include "../../conf.h"
   10 #include "../../log.h"
   11 #include "../../protocol1/handy.h"
   12 #include "../../protocol1/msg.h"
   13 #include "../extrameta.h"
   14 #include "../find.h"
   15 #include "backup_phase2.h"
   16 
   17 static int rs_loadsig_network_run(struct asfd *asfd,
   18     rs_job_t *job, struct cntr *cntr)
   19 {
   20     int ret=-1;
   21     rs_buffers_t buf;
   22     rs_result result;
   23     rs_filebuf_t *in_fb=NULL;
   24     memset(&buf, 0, sizeof(buf));
   25 
   26     if(!(in_fb=rs_filebuf_new(NULL,
   27         NULL, asfd, ASYNC_BUF_LEN, -1)))
   28         goto end;
   29 
   30     while(1)
   31     {
   32         iobuf_free_content(asfd->rbuf);
   33         if(asfd->read(asfd)) goto end;
   34         if(asfd->rbuf->cmd==CMD_MESSAGE
   35           || asfd->rbuf->cmd==CMD_WARNING)
   36         {
   37             log_recvd(asfd->rbuf, cntr, 0);
   38             continue;
   39         }
   40         switch((result=rs_async(job, &buf, in_fb, NULL)))
   41         {
   42             case RS_BLOCKED:
   43             case RS_RUNNING:
   44                 continue;
   45             case RS_DONE:
   46                 ret=0;
   47                 goto end;
   48             default:
   49                 logp("error in rs_async for sig: %d\n",
   50                     result);
   51                 goto end;
   52         }
   53     }
   54 
   55 end:
   56     iobuf_free_content(asfd->rbuf);
   57     rs_filebuf_free(&in_fb);
   58     return ret;
   59 }
   60 
   61 static int load_signature(struct asfd *asfd,
   62     rs_signature_t **sumset, struct cntr *cntr)
   63 {
   64     rs_job_t *job;
   65 
   66     if(!(job=rs_loadsig_begin(sumset)))
   67     {
   68         logp("could not start sig job.\n");
   69         return -1;
   70     }
   71     if(rs_loadsig_network_run(asfd, job, cntr))
   72         return -1;
   73     if(rs_build_hash_table(*sumset))
   74         return -1;
   75     rs_job_free(job);
   76     return 0;
   77 }
   78 
   79 static int load_signature_and_send_delta(struct asfd *asfd,
   80     struct BFILE *bfd, uint64_t *bytes, uint64_t *sentbytes,
   81     struct cntr *cntr)
   82 {
   83     int ret=-1;
   84     rs_job_t *job=NULL;
   85     rs_signature_t *sumset=NULL;
   86     uint8_t checksum[MD5_DIGEST_LENGTH];
   87     rs_filebuf_t *infb=NULL;
   88     rs_filebuf_t *outfb=NULL;
   89     rs_buffers_t rsbuf;
   90     memset(&rsbuf, 0, sizeof(rsbuf));
   91 
   92     if(load_signature(asfd, &sumset, cntr))
   93         goto end;
   94 
   95     if(!(job=rs_delta_begin(sumset)))
   96     {
   97         logp("could not start delta job.\n");
   98         goto end;
   99     }
  100 
  101     if(!(infb=rs_filebuf_new(bfd,
  102         NULL, NULL, ASYNC_BUF_LEN, bfd->datalen))
  103       || !(outfb=rs_filebuf_new(NULL,
  104         NULL, asfd, ASYNC_BUF_LEN, -1)))
  105     {
  106         logp("could not rs_filebuf_new for delta\n");
  107         goto end;
  108     }
  109 
  110     while(1)
  111     {
  112         rs_result result;
  113         switch((result=rs_async(job, &rsbuf, infb, outfb)))
  114         {
  115             case RS_DONE:
  116                 *bytes=infb->bytes;
  117                 *sentbytes=outfb->bytes;
  118                 if(!MD5_Final(checksum, &(infb->md5)))
  119                 {
  120                     logp("MD5_Final() failed\n");
  121                     goto end;
  122                 }
  123                 if(write_endfile(asfd, *bytes, checksum))
  124                     goto end;
  125                 ret=0;
  126                 goto end;
  127             case RS_BLOCKED:
  128             case RS_RUNNING:
  129                 // FIX ME: get it to read stuff here too.
  130                 // (errors, for example)
  131                 if(asfd->as->write(asfd->as))
  132                     goto end;
  133                 continue;
  134             default:
  135                 logp("error in rs_async for delta: %d\n",
  136                     result);
  137                 goto end;
  138         }
  139     }
  140 end:
  141     rs_filebuf_free(&infb);
  142     rs_filebuf_free(&outfb);
  143     if(job) rs_job_free(job);
  144     if(sumset) rs_free_sumset(sumset);
  145     return ret;
  146 }
  147 
  148 static enum send_e send_whole_file_w(struct asfd *asfd,
  149     struct sbuf *sb, const char *datapth,
  150     int quick_read, uint64_t *bytes, const char *encpassword,
  151     struct cntr *cntr, int compression, struct BFILE *bfd,
  152     const char *extrameta, size_t elen)
  153 {
  154     if((compression || encpassword) && sb->path.cmd!=CMD_EFS_FILE)
  155     {
  156         int key_deriv=sb->encryption==ENCRYPTION_KEY_DERIVED;
  157 
  158         return send_whole_file_gzl(asfd, datapth, quick_read, bytes,
  159           encpassword, cntr, compression, bfd, extrameta, elen,
  160           key_deriv, sb->protocol1->salt);
  161     }
  162     else
  163         return send_whole_filel(asfd,
  164 #ifdef HAVE_WIN32
  165           sb->path.cmd,
  166 #endif
  167           datapth, quick_read, bytes,
  168           cntr, bfd, extrameta, elen);
  169 }
  170 
  171 static int forget_file(struct asfd *asfd, struct sbuf *sb, struct conf **confs)
  172 {
  173     // Tell the server to forget about this
  174     // file, otherwise it might get stuck
  175     // on a select waiting for it to arrive.
  176     if(asfd->write_str(asfd, CMD_INTERRUPT, sb->path.buf))
  177         return 0;
  178 
  179     if(sb->path.cmd==CMD_FILE && sb->protocol1->datapth.buf)
  180     {
  181         rs_signature_t *sumset=NULL;
  182         // The server will be sending us a signature.
  183         // Munch it up then carry on.
  184         if(load_signature(asfd, &sumset, get_cntr(confs))) return -1;
  185         else rs_free_sumset(sumset);
  186     }
  187     return 0;
  188 }
  189 
  190 static int size_checks(struct asfd *asfd, struct sbuf *sb, struct conf **confs)
  191 {
  192     if(sb->path.cmd!=CMD_FILE
  193       && sb->path.cmd!=CMD_ENC_FILE
  194       && sb->path.cmd!=CMD_EFS_FILE)
  195         return 0;
  196     if(get_uint64_t(confs[OPT_MIN_FILE_SIZE])
  197       && (uint64_t)sb->statp.st_size<get_uint64_t(confs[OPT_MIN_FILE_SIZE]))
  198     {
  199         logw(asfd, get_cntr(confs), "File size decreased below min_file_size after initial scan: %s\n", iobuf_to_printable(&sb->path));
  200         return -1;
  201     }
  202     if(get_uint64_t(confs[OPT_MAX_FILE_SIZE])
  203       && (uint64_t)sb->statp.st_size>get_uint64_t(confs[OPT_MAX_FILE_SIZE]))
  204     {
  205         logw(asfd, get_cntr(confs), "File size increased above max_file_size after initial scan: %s\n", iobuf_to_printable(&sb->path));
  206         return -1;
  207     }
  208     return 0;
  209 }
  210 
  211 static int deal_with_data(struct asfd *asfd, struct sbuf *sb,
  212     struct BFILE *bfd, struct conf **confs)
  213 {
  214     int ret=-1;
  215     int forget=0;
  216     size_t elen=0;
  217     char *extrameta=NULL;
  218     uint64_t bytes=0;
  219     int conf_compression=get_int(confs[OPT_COMPRESSION]);
  220     struct cntr *cntr=get_cntr(confs);
  221     const char *enc_password=get_string(confs[OPT_ENCRYPTION_PASSWORD]);
  222 
  223     sb->compression=conf_compression;
  224     if(enc_password)
  225     {
  226         sb->encryption=ENCRYPTION_KEY_DERIVED;
  227         if(!RAND_bytes((uint8_t *)&sb->protocol1->salt, 8))
  228         {
  229             logp("RAND_bytes() failed\n");
  230             return -1;
  231         }
  232     }
  233 
  234     iobuf_copy(&sb->path, asfd->rbuf);
  235     iobuf_init(asfd->rbuf);
  236 
  237 #ifdef HAVE_WIN32
  238     if(win32_lstat(sb->path.buf, &sb->statp, &sb->winattr))
  239 #else
  240     if(lstat(sb->path.buf, &sb->statp))
  241 #endif
  242     {
  243         logw(asfd, cntr, "Path has vanished: %s\n",
  244             iobuf_to_printable(&sb->path));
  245         forget++;
  246         goto end;
  247     }
  248 
  249     if(size_checks(asfd, sb, confs))
  250     {
  251         forget++;
  252         goto end;
  253     }
  254 
  255     sb->compression=in_exclude_comp(get_strlist(confs[OPT_EXCOM]),
  256         sb->path.buf, conf_compression);
  257     if(attribs_encode(sb)) goto error;
  258 
  259     if(sb->path.cmd!=CMD_METADATA
  260       && sb->path.cmd!=CMD_ENC_METADATA)
  261     {
  262         if(bfd->open_for_send(bfd, asfd,
  263             sb->path.buf, sb->winattr,
  264             get_int(confs[OPT_ATIME]), cntr, PROTO_1))
  265         {
  266             forget++;
  267             goto end;
  268         }
  269     }
  270 
  271     if(sb->path.cmd==CMD_METADATA
  272       || sb->path.cmd==CMD_ENC_METADATA
  273       || sb->path.cmd==CMD_VSS
  274       || sb->path.cmd==CMD_ENC_VSS
  275 #ifdef HAVE_WIN32
  276       || get_int(confs[OPT_STRIP_VSS])
  277 #endif
  278       )
  279     {
  280         if(get_extrameta(asfd,
  281 #ifdef HAVE_WIN32
  282             bfd,
  283 #endif
  284             sb->path.buf,
  285             S_ISDIR(sb->statp.st_mode),
  286             &extrameta, &elen, cntr))
  287         {
  288             logw(asfd, cntr,
  289                 "Meta data error for %s\n",
  290                 iobuf_to_printable(&sb->path));
  291             forget++;
  292             goto end;
  293         }
  294         if(extrameta)
  295         {
  296 #ifdef HAVE_WIN32
  297             if(get_int(confs[OPT_STRIP_VSS]))
  298             {
  299                 free_w(&extrameta);
  300                 elen=0;
  301             }
  302 #endif
  303         }
  304         else
  305         {
  306             logw(asfd, cntr,
  307                 "No meta data after all: %s\n",
  308                 iobuf_to_printable(&sb->path));
  309             forget++;
  310             goto end;
  311         }
  312     }
  313 
  314     if(sb->path.cmd==CMD_FILE
  315       && sb->protocol1->datapth.buf)
  316     {
  317         uint64_t sentbytes=0;
  318         // Need to do sig/delta stuff.
  319         if(asfd->write(asfd, &(sb->protocol1->datapth))
  320           || asfd->write(asfd, &sb->attr)
  321           || asfd->write(asfd, &sb->path)
  322           || load_signature_and_send_delta(asfd, bfd,
  323             &bytes, &sentbytes, cntr))
  324         {
  325             logp("error in sig/delta for %s (%s)\n",
  326                 iobuf_to_printable(&sb->path),
  327                 iobuf_to_printable(&sb->protocol1->datapth));
  328             forget++;
  329             goto end;
  330         }
  331         cntr_add(cntr, CMD_FILE_CHANGED, 1);
  332     }
  333     else
  334     {
  335         //logp("need to send whole file: %s\n", sb.path);
  336         // send the whole file.
  337 
  338         if(asfd->write(asfd, &sb->attr)
  339           || asfd->write(asfd, &sb->path))
  340             goto end;
  341 
  342         switch(send_whole_file_w(asfd, sb, NULL, 0, &bytes,
  343             enc_password,
  344             cntr, sb->compression,
  345             bfd, extrameta, elen))
  346         {
  347             case SEND_OK:
  348                 break;
  349             case SEND_ERROR:
  350                 forget++;
  351                 break;
  352             case SEND_FATAL:
  353             default:
  354                 goto error;
  355         }
  356         cntr_add(cntr, sb->path.cmd, 1);
  357     }
  358     cntr_add_bytes(cntr, bytes);
  359 
  360 end:
  361     ret=0;
  362     if(forget && forget_file(asfd, sb, confs))
  363         ret=-1;
  364 error:
  365 #ifdef HAVE_WIN32
  366     // If using Windows do not close bfd - it needs
  367     // to stay open to read VSS/file data/VSS.
  368     // It will get closed either when given a
  369     // different file path, or when this function
  370     // exits.
  371 #else
  372     bfd->close(bfd, asfd);
  373 #endif
  374     sbuf_free_content(sb);
  375     free_w(&extrameta);
  376     return ret;
  377 }
  378 
  379 static int parse_rbuf(struct asfd *asfd, struct sbuf *sb,
  380     struct BFILE *bfd, struct conf **confs)
  381 {
  382     static struct iobuf *rbuf;
  383     rbuf=asfd->rbuf;
  384     if(rbuf->cmd==CMD_DATAPTH)
  385     {
  386         iobuf_move(&(sb->protocol1->datapth), rbuf);
  387     }
  388     else if(rbuf->cmd==CMD_ATTRIBS)
  389     {
  390         // Ignore the stat data - we will fill it
  391         // in again. Some time may have passed by now,
  392         // and it is best to make it as fresh as
  393         // possible.
  394     }
  395     else if(iobuf_is_filedata(rbuf)
  396       || iobuf_is_vssdata(rbuf))
  397     {
  398         if(deal_with_data(asfd, sb, bfd, confs))
  399             return -1;
  400     }
  401     else if(rbuf->cmd==CMD_MESSAGE
  402       || rbuf->cmd==CMD_WARNING)
  403     {
  404         struct cntr *cntr=NULL;
  405         if(confs) cntr=get_cntr(confs);
  406         log_recvd(rbuf, cntr, 0);
  407     }
  408     else
  409     {
  410         iobuf_log_unexpected(rbuf, __func__);
  411         return -1;
  412     }
  413     return 0;
  414 }
  415 
  416 static int do_backup_phase2_client(struct asfd *asfd,
  417     struct conf **confs, int resume)
  418 {
  419     int ret=-1;
  420     // For efficiency, open Windows files for the VSS data, and do not
  421     // close them until another time around the loop, when the actual
  422     // data is read.
  423     struct BFILE *bfd=NULL;
  424     struct sbuf *sb=NULL;
  425     struct iobuf *rbuf=NULL;
  426     struct cntr *cntr=NULL;
  427     if(confs) cntr=get_cntr(confs);
  428 
  429     if(!asfd)
  430     {
  431         logp("%s() called without asfd!\n", __func__);
  432         goto end;
  433     }
  434     rbuf=asfd->rbuf;
  435 
  436     if(!(bfd=bfile_alloc())
  437       || !(sb=sbuf_alloc(PROTO_1)))
  438         goto end;
  439     bfile_init(bfd, 0, cntr);
  440 
  441     if(!resume)
  442     {
  443         // Only do this bit if the server did not tell us to resume.
  444         if(asfd->write_str(asfd, CMD_GEN, "backupphase2")
  445           || asfd_read_expect(asfd, CMD_GEN, "ok"))
  446             goto end;
  447     }
  448     else
  449     {
  450         // On resume, the server might update the client with cntr.
  451         if(cntr_recv(asfd, confs))
  452             goto end;
  453     }
  454 
  455     while(1)
  456     {
  457         iobuf_free_content(rbuf);
  458         if(asfd->read(asfd)) goto end;
  459         else if(!rbuf->buf) continue;
  460 
  461         if(rbuf->cmd==CMD_GEN && !strcmp(rbuf->buf, "backupphase2end"))
  462         {
  463             if(asfd->write_str(asfd, CMD_GEN, "okbackupphase2end"))
  464                 goto end;
  465             ret=0;
  466             break;
  467         }
  468 
  469         if(parse_rbuf(asfd, sb, bfd, confs))
  470             goto end;
  471     }
  472 
  473 end:
  474     // It is possible for a bfd to still be open.
  475     if(bfd) bfd->close(bfd, asfd);
  476     bfile_free(&bfd);
  477     iobuf_free_content(rbuf);
  478     sbuf_free(&sb);
  479     return ret;
  480 }
  481 
  482 int backup_phase2_client_protocol1(struct asfd *asfd,
  483     struct conf **confs, int resume)
  484 {
  485     int ret=0;
  486     struct cntr *cntr=NULL;
  487     if(confs) cntr=get_cntr(confs);
  488 
  489     logp("Phase 2 begin (send backup data)\n");
  490     logfmt("\n");
  491 
  492     ret=do_backup_phase2_client(asfd, confs, resume);
  493 
  494     cntr_print_end(cntr);
  495     cntr_set_bytes(cntr, asfd);
  496     cntr_print(cntr, ACTION_BACKUP);
  497 
  498     if(ret) logp("Error in phase 2\n");
  499     logp("Phase 2 end (send file data)\n");
  500 
  501     return ret;
  502 }