static int do_backup_phase2_client(struct config *conf, int resume, struct cntr *cntr) { int ret=0; int quit=0; char cmd; char *buf=NULL; size_t len=0; char attribs[MAXSTRING]; struct sbuf sb; init_sbuf(&sb); if(!resume) { // Only do this bit if the server did not tell us to resume. if(async_write_str(CMD_GEN, "backupphase2") || async_read_expect(CMD_GEN, "ok")) return -1; } while(!quit) { if(async_read(&cmd, &buf, &len)) { ret=-1; quit++; } else if(buf) { //logp("now: %c:%s\n", cmd, buf); if(cmd==CMD_DATAPTH) { sb.datapth=buf; buf=NULL; continue; } else if(cmd==CMD_STAT) { // Ignore the stat data - we will fill it // in again. Some time may have passed by now, // and it is best to make it as fresh as // possible. free(buf); buf=NULL; continue; } else if(cmd==CMD_FILE || cmd==CMD_ENC_FILE || cmd==CMD_METADATA || cmd==CMD_ENC_METADATA || cmd==CMD_EFS_FILE) { int forget=0; int64_t winattr=0; struct stat statbuf; char *extrameta=NULL; size_t elen=0; unsigned long long bytes=0; BFILE bfd; FILE *fp=NULL; sb.path=buf; buf=NULL; #ifdef HAVE_WIN32 if(win32_lstat(sb.path, &statbuf, &winattr)) #else if(lstat(sb.path, &statbuf)) #endif { logw(cntr, "Path has vanished: %s", sb.path); if(forget_file(&sb, cmd, cntr)) { ret=-1; quit++; } free_sbuf(&sb); continue; } if(conf->min_file_size && statbuf.st_size<(boffset_t)conf->min_file_size) { logw(cntr, "File size decreased below min_file_size after initial scan: %s", sb.path); forget++; } else if(conf->max_file_size && statbuf.st_size>(boffset_t)conf->max_file_size) { logw(cntr, "File size increased above max_file_size after initial scan: %s", sb.path); forget++; } if(!forget) { encode_stat(attribs, &statbuf, winattr); if(open_file_for_send(&bfd, &fp, sb.path, winattr, cntr)) forget++; } if(forget) { if(forget_file(&sb, cmd, cntr)) { ret=-1; quit++; } free_sbuf(&sb); continue; } if(cmd==CMD_METADATA || cmd==CMD_ENC_METADATA) { if(get_extrameta(sb.path, &statbuf, &extrameta, &elen, cntr)) { logw(cntr, "Meta data error for %s", sb.path); free_sbuf(&sb); close_file_for_send(&bfd, &fp); continue; } if(!extrameta) { logw(cntr, "No meta data after all: %s", sb.path); free_sbuf(&sb); close_file_for_send(&bfd, &fp); continue; } } if(cmd==CMD_FILE && sb.datapth) { unsigned long long sentbytes=0; // Need to do sig/delta stuff. if(async_write_str(CMD_DATAPTH, sb.datapth) || async_write_str(CMD_STAT, attribs) || async_write_str(CMD_FILE, sb.path) || load_signature_and_send_delta( &bfd, fp, &bytes, &sentbytes, cntr)) { logp("error in sig/delta for %s (%s)\n", sb.path, sb.datapth); ret=-1; quit++; } else { do_filecounter(cntr, CMD_FILE_CHANGED, 1); do_filecounter_bytes(cntr, bytes); do_filecounter_sentbytes(cntr, sentbytes); } } else { //logp("need to send whole file: %s\n", // sb.path); // send the whole file. if(async_write_str(CMD_STAT, attribs) || async_write_str(cmd, sb.path) || send_whole_file_w(cmd, sb.path, NULL, 0, &bytes, conf->encryption_password, cntr, conf->compression, &bfd, fp, extrameta, elen)) { ret=-1; quit++; } else { do_filecounter(cntr, cmd, 1); do_filecounter_bytes(cntr, bytes); do_filecounter_sentbytes(cntr, bytes); } } close_file_for_send(&bfd, &fp); free_sbuf(&sb); if(extrameta) free(extrameta); } else if(cmd==CMD_WARNING) { do_filecounter(cntr, cmd, 0); free(buf); buf=NULL; } else if(cmd==CMD_GEN && !strcmp(buf, "backupphase2end")) { if(async_write_str(CMD_GEN, "okbackupphase2end")) ret=-1; quit++; } else { logp("unexpected cmd from server: %c %s\n", cmd, buf); ret=-1; quit++; free(buf); buf=NULL; } } } return ret; }
static int do_backup_phase2_client(struct config *conf, int resume, struct cntr *p1cntr, struct cntr *cntr) { int ret=0; int quit=0; char cmd; char *buf=NULL; size_t len=0; char attribs[MAXSTRING]; // For efficiency, open Windows files for the VSS data, and do not // close them until another time around the loop, when the actual // data is read. BFILE bfd; // Windows VSS headers tell us how much file // data to expect. size_t datalen=0; #ifdef HAVE_WIN32 binit(&bfd, 0); #endif struct sbuf sb; init_sbuf(&sb); if(!resume) { // Only do this bit if the server did not tell us to resume. if(async_write_str(CMD_GEN, "backupphase2") || async_read_expect(CMD_GEN, "ok")) return -1; } else if(conf->send_client_counters) { // On resume, the server might update the client with the // counters. if(recv_counters(p1cntr, cntr)) return -1; } while(!quit) { if(async_read(&cmd, &buf, &len)) { ret=-1; quit++; } else if(buf) { //logp("now: %c:%s\n", cmd, buf); if(cmd==CMD_DATAPTH) { sb.datapth=buf; buf=NULL; continue; } else if(cmd==CMD_STAT) { // Ignore the stat data - we will fill it // in again. Some time may have passed by now, // and it is best to make it as fresh as // possible. free(buf); buf=NULL; continue; } else if(cmd==CMD_FILE || cmd==CMD_ENC_FILE || cmd==CMD_METADATA || cmd==CMD_ENC_METADATA || cmd==CMD_VSS || cmd==CMD_ENC_VSS || cmd==CMD_VSS_T || cmd==CMD_ENC_VSS_T || cmd==CMD_EFS_FILE) { int forget=0; int64_t winattr=0; struct stat statbuf; char *extrameta=NULL; size_t elen=0; unsigned long long bytes=0; FILE *fp=NULL; int compression=conf->compression; sb.path=buf; buf=NULL; #ifdef HAVE_WIN32 if(win32_lstat(sb.path, &statbuf, &winattr)) #else if(lstat(sb.path, &statbuf)) #endif { logw(cntr, "Path has vanished: %s", sb.path); if(forget_file(&sb, cmd, cntr)) { ret=-1; quit++; } free_sbuf(&sb); continue; } if(conf->min_file_size && statbuf.st_size< (boffset_t)conf->min_file_size && (cmd==CMD_FILE || cmd==CMD_ENC_FILE || cmd==CMD_EFS_FILE)) { logw(cntr, "File size decreased below min_file_size after initial scan: %c:%s", cmd, sb.path); forget++; } else if(conf->max_file_size && statbuf.st_size> (boffset_t)conf->max_file_size && (cmd==CMD_FILE || cmd==CMD_ENC_FILE || cmd==CMD_EFS_FILE)) { logw(cntr, "File size increased above max_file_size after initial scan: %c:%s", cmd, sb.path); forget++; } if(!forget) { compression=in_exclude_comp(conf->excom, conf->excmcount, sb.path, conf->compression); encode_stat(attribs, &statbuf, winattr, compression); if(open_file_for_send( #ifdef HAVE_WIN32 &bfd, NULL, #else NULL, &fp, #endif sb.path, winattr, &datalen, cntr)) forget++; } if(forget) { if(forget_file(&sb, cmd, cntr)) { ret=-1; quit++; } free_sbuf(&sb); continue; } if(cmd==CMD_METADATA || cmd==CMD_ENC_METADATA || cmd==CMD_VSS || cmd==CMD_ENC_VSS #ifdef HAVE_WIN32 || conf->strip_vss #endif ) { if(get_extrameta( #ifdef HAVE_WIN32 &bfd, #else NULL, #endif sb.path, &statbuf, &extrameta, &elen, winattr, cntr, &datalen)) { logw(cntr, "Meta data error for %s", sb.path); free_sbuf(&sb); close_file_for_send(&bfd, &fp); continue; } if(extrameta) { #ifdef HAVE_WIN32 if(conf->strip_vss) { free(extrameta); extrameta=NULL; elen=0; } #endif } else { logw(cntr, "No meta data after all: %s", sb.path); free_sbuf(&sb); close_file_for_send(&bfd, &fp); continue; } } if(cmd==CMD_FILE && sb.datapth) { unsigned long long sentbytes=0; // Need to do sig/delta stuff. if(async_write_str(CMD_DATAPTH, sb.datapth) || async_write_str(CMD_STAT, attribs) || async_write_str(CMD_FILE, sb.path) || load_signature_and_send_delta( &bfd, fp, &bytes, &sentbytes, cntr, datalen)) { logp("error in sig/delta for %s (%s)\n", sb.path, sb.datapth); ret=-1; quit++; } else { do_filecounter(cntr, CMD_FILE_CHANGED, 1); do_filecounter_bytes(cntr, bytes); do_filecounter_sentbytes(cntr, sentbytes); } } else { //logp("need to send whole file: %s\n", // sb.path); // send the whole file. if((async_write_str(CMD_STAT, attribs) || async_write_str(cmd, sb.path)) || send_whole_file_w(cmd, sb.path, NULL, 0, &bytes, conf->encryption_password, cntr, compression, &bfd, fp, extrameta, elen, datalen)) { ret=-1; quit++; } else { do_filecounter(cntr, cmd, 1); do_filecounter_bytes(cntr, bytes); do_filecounter_sentbytes(cntr, bytes); } } #ifdef HAVE_WIN32 // If using Windows do not close bfd - it needs // to stay open to read VSS/file data/VSS. // It will get closed either when given a // different file path, or when this function // exits. //if(cmd!=CMD_VSS // && cmd!=CMD_ENC_VSS) // close_file_for_send(&bfd, NULL); #else close_file_for_send(NULL, &fp); #endif free_sbuf(&sb); if(extrameta) free(extrameta); } else if(cmd==CMD_WARNING) { do_filecounter(cntr, cmd, 0); free(buf); buf=NULL; } else if(cmd==CMD_GEN && !strcmp(buf, "backupphase2end")) { if(async_write_str(CMD_GEN, "okbackupphase2end")) ret=-1; quit++; } else { logp("unexpected cmd from server: %c %s\n", cmd, buf); ret=-1; quit++; free(buf); buf=NULL; } } } #ifdef HAVE_WIN32 // It is possible for a bfd to still be open. close_file_for_send(&bfd, NULL); #endif return ret; }
static int deal_with_data(struct asfd *asfd, struct sbuf *sb, BFILE *bfd, size_t *datalen, struct conf *conf) { int ret=-1; int forget=0; FILE *fp=NULL; size_t elen=0; char *extrameta=NULL; unsigned long long bytes=0; sb->compression=conf->compression; iobuf_copy(&sb->path, asfd->rbuf); iobuf_init(asfd->rbuf); #ifdef HAVE_WIN32 if(win32_lstat(sb->path.buf, &sb->statp, &sb->winattr)) #else if(lstat(sb->path.buf, &sb->statp)) #endif { logw(asfd, conf, "Path has vanished: %s", sb->path.buf); if(forget_file(asfd, sb, conf)) goto error; goto end; } if(size_checks(asfd, sb, conf)) forget++; if(!forget) { sb->compression=in_exclude_comp(conf->excom, sb->path.buf, conf->compression); if(attribs_encode(sb)) goto error; else if(open_file_for_sendl(asfd, #ifdef HAVE_WIN32 bfd, NULL, #else NULL, &fp, #endif sb->path.buf, sb->winattr, datalen, conf->atime, conf)) forget++; } if(forget) { if(forget_file(asfd, sb, conf)) goto error; goto end; } if(sb->path.cmd==CMD_METADATA || sb->path.cmd==CMD_ENC_METADATA || sb->path.cmd==CMD_VSS || sb->path.cmd==CMD_ENC_VSS #ifdef HAVE_WIN32 || conf->strip_vss #endif ) { if(get_extrameta(asfd, #ifdef HAVE_WIN32 bfd, #endif sb->path.buf, &sb->statp, &extrameta, &elen, sb->winattr, conf, datalen)) { logw(asfd, conf, "Meta data error for %s", sb->path.buf); goto end; } if(extrameta) { #ifdef HAVE_WIN32 if(conf->strip_vss) { free(extrameta); extrameta=NULL; elen=0; } #endif } else { logw(asfd, conf, "No meta data after all: %s", sb->path.buf); goto end; } } if(sb->path.cmd==CMD_FILE && sb->burp1->datapth.buf) { unsigned long long sentbytes=0; // Need to do sig/delta stuff. if(asfd->write(asfd, &(sb->burp1->datapth)) || asfd->write(asfd, &sb->attr) || asfd->write(asfd, &sb->path) || load_signature_and_send_delta(asfd, bfd, fp, &bytes, &sentbytes, conf, *datalen)) { logp("error in sig/delta for %s (%s)\n", sb->path.buf, sb->burp1->datapth.buf); goto end; } else { cntr_add(conf->cntr, CMD_FILE_CHANGED, 1); cntr_add_bytes(conf->cntr, bytes); cntr_add_sentbytes(conf->cntr, sentbytes); } } else { //logp("need to send whole file: %s\n", sb.path); // send the whole file. if((asfd->write(asfd, &sb->attr) || asfd->write(asfd, &sb->path)) || send_whole_file_w(asfd, sb, NULL, 0, &bytes, conf->encryption_password, conf, sb->compression, bfd, fp, extrameta, elen, *datalen)) goto end; else { cntr_add(conf->cntr, sb->path.cmd, 1); cntr_add_bytes(conf->cntr, bytes); cntr_add_sentbytes(conf->cntr, bytes); } } end: ret=0; error: #ifdef HAVE_WIN32 // If using Windows do not close bfd - it needs // to stay open to read VSS/file data/VSS. // It will get closed either when given a // different file path, or when this function // exits. #else close_file_for_sendl(NULL, &fp, asfd); #endif sbuf_free_content(sb); if(extrameta) free(extrameta); return ret; }