/* * Get current directory, as a pathname. * Use vop_namefile to get the pathname. */ int vfs_getcwd(struct iobuf *iob) { int ret; struct inode *node; if ((ret = vfs_get_curdir(&node)) != 0) { return ret; } /* The current dir must be a directory, and thus it is not a device. */ assert(node->in_fs != NULL); const char *devname = vfs_get_devname(node->in_fs); if ((ret = iobuf_move(iob, (char *)devname, strlen(devname), 1, NULL)) != 0) { goto out; } char colon = ':'; if ((ret = iobuf_move(iob, &colon, sizeof(colon), 1, NULL)) != 0) { goto out; } ret = vop_namefile(node, iob); out: vop_ref_dec(node); return ret; }
/* * sfs_getdirentry - according to the iob->io_offset, calculate the dir entry's slot in disk block, get dir entry content from the disk */ static int sfs_getdirentry(struct inode *node, struct iobuf *iob) { struct sfs_disk_entry *entry; if ((entry = kmalloc(sizeof(struct sfs_disk_entry))) == NULL) { return -E_NO_MEM; } struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); struct sfs_inode *sin = vop_info(node, sfs_inode); int ret, slot; off_t offset = iob->io_offset; if (offset < 0 || offset % sfs_dentry_size != 0) { kfree(entry); return -E_INVAL; } if ((slot = offset / sfs_dentry_size) > sin->din->blocks) { kfree(entry); return -E_NOENT; } lock_sin(sin); if ((ret = sfs_getdirentry_sub_nolock(sfs, sin, slot, entry)) != 0) { unlock_sin(sin); goto out; } unlock_sin(sin); ret = iobuf_move(iob, entry->name, sfs_dentry_size, 1, NULL); out: kfree(entry); return ret; }
static int set_up_for_sig_info(struct slist *slist, struct iobuf *attr, uint64_t index) { struct sbuf *sb; for(sb=slist->add_sigs_here; sb; sb=sb->next) { if(!sb->protocol2->index) continue; if(index==sb->protocol2->index) break; } if(!sb) { logp("Could not find %" PRIu64 " in request list\n", index); return -1; } // Replace the attribs with the more recent values. iobuf_free_content(&sb->attr); iobuf_move(&sb->attr, attr); // Mark the end of the previous file. slist->add_sigs_here->protocol2->bend=slist->blist->tail; slist->add_sigs_here=sb; // Incoming sigs now need to get added to 'add_sigs_here' return 0; }
static int deal_with_filedata(struct asfd *asfd, struct sdirs *sdirs, struct sbuf *rb, struct iobuf *rbuf, struct dpth *dpth, struct conf **cconfs) { iobuf_move(&rb->path, rbuf); if(rb->protocol1->datapth.buf) { // Receiving a delta. if(start_to_receive_delta(sdirs, cconfs, rb)) { logp("error in start_to_receive_delta\n"); return -1; } return 0; } // Receiving a whole new file. if(start_to_receive_new_file(asfd, sdirs, cconfs, rb, dpth)) { logp("error in start_to_receive_new_file\n"); return -1; } return 0; }
static int disk0_io(struct device *dev, struct iobuf *iob, bool write) { off_t offset = iob->io_offset; size_t resid = iob->io_resid; uint32_t blkno = offset / DISK0_BLKSIZE; uint32_t nblks = resid / DISK0_BLKSIZE; /* don't allow I/O that isn't block-aligned */ if ((offset % DISK0_BLKSIZE) != 0 || (resid % DISK0_BLKSIZE) != 0) { return -E_INVAL; } /* don't allow I/O past the end of disk0 */ if (blkno + nblks > dev->d_blocks) { return -E_INVAL; } /* read/write nothing ? */ if (nblks == 0) { return 0; } lock_disk0(); while (resid != 0) { size_t copied, alen = DISK0_BUFSIZE; if (write) { iobuf_move(iob, disk0_buffer, alen, 0, &copied); assert(copied != 0 && copied <= resid && copied % DISK0_BLKSIZE == 0); nblks = copied / DISK0_BLKSIZE; disk0_write_blks_nolock(blkno, nblks); } else { if (alen > resid) { alen = resid; } nblks = alen / DISK0_BLKSIZE; disk0_read_blks_nolock(blkno, nblks); iobuf_move(iob, disk0_buffer, alen, 1, &copied); assert(copied == alen && copied % DISK0_BLKSIZE == 0); } resid -= copied, blkno += nblks; } unlock_disk0(); return 0; }
static int process_unchanged_file(struct sbuf *p1b, struct sbuf *cb, struct fzp *ucfp, struct conf **cconfs) { // Need to re-encode the p1b attribs to include compression and // other bits and pieces that are recorded on cb. iobuf_move(&p1b->protocol1->datapth, &cb->protocol1->datapth); iobuf_move(&p1b->protocol1->endfile, &cb->protocol1->endfile); p1b->compression=cb->compression; if(attribs_encode(p1b)) return -1; if(sbufl_to_manifest(p1b, ucfp)) return -1; cntr_add_same(get_cntr(cconfs[OPT_CNTR]), p1b->path.cmd); if(p1b->protocol1->endfile.buf) cntr_add_bytes( get_cntr(cconfs[OPT_CNTR]), strtoull(p1b->protocol1->endfile.buf, NULL, 10)); sbuf_free_content(cb); return 1; }
static int add_to_file_requests(struct slist *slist, struct iobuf *rbuf) { static uint64_t file_no=1; struct sbuf *sb; if(!(sb=sbuf_alloc(PROTO_2))) return -1; iobuf_move(&sb->path, rbuf); // Give it a number to simplify tracking. sb->protocol2->index=file_no++; slist_add_sbuf(slist, sb); return 0; }
void build_manifest_phase1_from_slist(const char *path, struct slist *slist, enum protocol protocol) { struct sbuf *sb; struct manio *manio=NULL; struct iobuf datapth; struct iobuf endfile; iobuf_init(&datapth); iobuf_init(&endfile); for(sb=slist->head; sb; sb=sb->next) set_sbuf(slist, sb, 0 /* with_data_files */); fail_unless((manio=manio_open_phase1(path, "wb", protocol))!=NULL); for(sb=slist->head; sb; sb=sb->next) { // Might be given an slist that has datapth or endfile set, // which should not go into a phase1 scan. Deal with it. if(sb->protocol1 && sb->protocol1->datapth.buf) iobuf_move(&datapth, &sb->protocol1->datapth); if(sb->endfile.buf) iobuf_move(&endfile, &sb->endfile); fail_unless(!manio_write_sbuf(manio, sb)); if(datapth.buf) iobuf_move(&sb->protocol1->datapth, &datapth); if(endfile.buf) iobuf_move(&sb->endfile, &endfile); } fail_unless(!send_msg_fzp(manio->fzp, CMD_GEN, "phase1end", strlen("phase1end"))); fail_unless(!manio_close(&manio)); }
static int deal_with_receive_end_file(struct asfd *asfd, struct sdirs *sdirs, struct sbuf *rb, struct fzp *chfp, struct conf **cconfs, char **last_requested) { static char *cp=NULL; static struct iobuf *rbuf; rbuf=asfd->rbuf; // Finished the file. // Write it to the phase2 file, and free the buffers. if(fzp_close(&(rb->protocol1->fzp))) { logp("error closing delta for %s in receive\n", rb->path); goto error; } iobuf_move(&rb->protocol1->endfile, rbuf); if(rb->flags & SBUFL_RECV_DELTA && finish_delta(sdirs, rb)) goto error; if(sbufl_to_manifest(rb, chfp)) goto error; if(rb->flags & SBUFL_RECV_DELTA) cntr_add_changed(get_cntr(cconfs[OPT_CNTR]), rb->path.cmd); else cntr_add(get_cntr(cconfs[OPT_CNTR]), rb->path.cmd, 0); if(*last_requested && !strcmp(rb->path.buf, *last_requested)) { free(*last_requested); *last_requested=NULL; } cp=strchr(rb->protocol1->endfile.buf, ':'); if(rb->protocol1->endfile.buf) cntr_add_bytes(get_cntr(cconfs[OPT_CNTR]), strtoull(rb->protocol1->endfile.buf, NULL, 10)); if(cp) { // checksum stuff goes here } sbuf_free_content(rb); return 0; error: sbuf_free_content(rb); return -1; }
static int deal_with_receive_end_file(struct asfd *asfd, struct sdirs *sdirs, struct sbuf *rb, struct manio *chmanio, struct conf **cconfs, char **last_requested) { int ret=-1; static char *cp=NULL; static struct iobuf *rbuf; struct cntr *cntr=get_cntr(cconfs); rbuf=asfd->rbuf; // Finished the file. // Write it to the phase2 file, and free the buffers. if(fzp_close(&(rb->protocol1->fzp))) { logp("error closing delta for %s in receive\n", rb->path.buf); goto end; } iobuf_move(&rb->endfile, rbuf); if(rb->flags & SBUF_RECV_DELTA && finish_delta(sdirs, rb)) goto end; if(manio_write_sbuf(chmanio, rb)) goto end; if(rb->flags & SBUF_RECV_DELTA) cntr_add_changed(cntr, rb->path.cmd); else cntr_add(cntr, rb->path.cmd, 0); if(*last_requested && !strcmp(rb->path.buf, *last_requested)) free_w(last_requested); cp=strchr(rb->endfile.buf, ':'); if(rb->endfile.buf) cntr_add_bytes(cntr, strtoull(rb->endfile.buf, NULL, 10)); if(cp) { // checksum stuff goes here } ret=0; end: sbuf_free_content(rb); return ret; }
static int load_rblk(struct rblk *rblks, int ind, const char *datpath) { int r; int ret=-1; int done=0; struct fzp *fzp=NULL; struct iobuf rbuf; iobuf_init(&rbuf); free_w(&rblks[ind].datpath); if(!(rblks[ind].datpath=strdup_w(datpath, __func__))) goto end; logp("swap %d to: %s\n", ind, datpath); if(!(fzp=fzp_open(datpath, "rb"))) goto end; for(r=0; r<DATA_FILE_SIG_MAX; r++) { switch(iobuf_fill_from_fzp_data(&rbuf, fzp)) { case 0: if(rbuf.cmd!=CMD_DATA) { logp("unknown cmd in %s: %c\n", __func__, rbuf.cmd); goto end; } iobuf_free_content(&rblks[ind].readbuf[r]); iobuf_move(&rblks[ind].readbuf[r], &rbuf); continue; case 1: done++; break; default: goto end; } if(done) break; } rblks[ind].readbuflen=r; ret=0; end: fzp_close(&fzp); return ret; }
static int sfs_getdirentry(struct inode *node, struct iobuf *iob) { struct sfs_disk_entry *entry; if ((entry = kmalloc(sizeof(struct sfs_disk_entry))) == NULL) { return -E_NO_MEM; } struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); struct sfs_inode *sin = vop_info(node, sfs_inode); off_t offset = iob->io_offset; if (offset < 0 || offset % sfs_dentry_size != 0) { kfree(entry); return -E_INVAL; } int ret, slot = offset / sfs_dentry_size; if (slot >= sin->din->dirinfo.slots + 2) { kfree(entry); return -E_NOENT; } switch (slot) { case 0: strcpy(entry->name, "."); break; case 1: strcpy(entry->name, ".."); break; default: if ((ret = trylock_sin(sin)) != 0) { goto out; } ret = sfs_getdirentry_sub_nolock(sfs, sin, slot - 2, entry); unlock_sin(sin); if (ret != 0) { goto out; } } ret = iobuf_move(iob, entry->name, sfs_dentry_size, 1, NULL); out: kfree(entry); return ret; }
static int mock_asfd_read(struct asfd *asfd) { struct ioevent *r; struct ioevent_list *reads=(struct ioevent_list *)asfd->data1; //printf("r %s %d %d\n", asfd->desc, reads->cursor, reads->size); fail_unless(reads->cursor<reads->size); r=&reads->ioevent[reads->cursor]; if(r->no_op) { r->no_op--; if(!r->no_op) reads->cursor++; return r->ret; } //printf("r %s - %c:%s\n", asfd->desc, r->iobuf.cmd, r->iobuf.buf); iobuf_move(asfd->rbuf, &r->iobuf); reads->cursor++; return r->ret; }
static int sfs_getdirentry(struct inode *node, struct iobuf *iob) { struct sfs_disk_entry *entry; if ((entry = kmalloc(sizeof(struct sfs_disk_entry))) == NULL) { // kprintf("%s %s %d -E_NO_MEM\n", __FILE__, __func__, __LINE__); return -E_NO_MEM; } struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); struct sfs_inode *sin = vop_info(node, sfs_inode); int ret, slot; off_t offset = iob->io_offset; if (offset < 0 || offset % sfs_dentry_size != 0) { // kprintf("%s %s %d -E_INVAL\n", __FILE__, __func__, __LINE__); kfree(entry); return -E_INVAL; } if ((slot = offset / sfs_dentry_size) > sin->din->blocks) { // kprintf("%s %s %d -E_NOENT\n", __FILE__, __func__, __LINE__); kfree(entry); return -E_NOENT; } lock_sin(sin); if ((ret = sfs_getdirentry_sub_nolock(sfs, sin, slot, entry)) != 0) { unlock_sin(sin); // kprintf("%s %s %d can not find!!! slot is %d\n", __FILE__, __func__, __LINE__, slot); goto out; } unlock_sin(sin); // kprintf("sfs_getdirentry\n"); ret = iobuf_move(iob, entry->name, sfs_dentry_size, 1, NULL); out: kfree(entry); return ret; }
static int deal_with_read(struct iobuf *rbuf, struct slist *slist, struct cntr *cntr, uint8_t *end_flags, struct dpth *dpth) { int ret=0; switch(rbuf->cmd) { /* Incoming block data. */ case CMD_DATA: if(add_data_to_store(cntr, slist, rbuf, dpth)) goto error; goto end; /* Incoming block signatures. */ case CMD_ATTRIBS_SIGS: static struct iobuf attr; static uint64_t index; iobuf_init(&attr); iobuf_move(&attr, rbuf); index=decode_file_no(&attr); // Need to go through slist to find the matching // entry. if(set_up_for_sig_info(slist, &attr, index)) goto error; return 0; case CMD_SIG: if(add_to_sig_list(slist, rbuf)) goto error; goto end; /* Incoming control/message stuff. */ case CMD_MESSAGE: case CMD_WARNING: { struct cntr *cntr=NULL; log_recvd(rbuf, cntr, 0); goto end; } case CMD_GEN: if(!strcmp(rbuf->buf, "sigs_end")) { (*end_flags)|=END_SIGS; goto end; } else if(!strcmp(rbuf->buf, "backup_end")) { (*end_flags)|=END_BACKUP; goto end; } break; case CMD_INTERRUPT: { uint64_t file_no; file_no=base64_to_uint64(rbuf->buf); if(slist_del_sbuf_by_index(slist, file_no)) goto error; goto end; } default: break; } iobuf_log_unexpected(rbuf, __func__); error: ret=-1; end: iobuf_free_content(rbuf); return ret; }
static enum parse_ret parse_cmd(struct sbuf *sb, struct asfd *asfd, struct iobuf *rbuf, struct blk *blk, struct cntr *cntr) { switch(rbuf->cmd) { case CMD_ATTRIBS: if(sb->protocol2) sbuf_free_content(sb); else { if(sb->protocol1->datapth.buf) // protocol 1 phase 2+ file data // starts with datapth. iobuf_free_content(&sb->attr); else // protocol 1 phase 1 or non file data // starts with attribs sbuf_free_content(sb); } iobuf_move(&sb->attr, rbuf); attribs_decode(sb); return PARSE_RET_NEED_MORE; case CMD_FILE: case CMD_DIRECTORY: case CMD_SOFT_LINK: case CMD_HARD_LINK: case CMD_SPECIAL: // Stuff not currently supported in burp-2, but OK // to find in burp-1. case CMD_ENC_FILE: case CMD_METADATA: case CMD_ENC_METADATA: case CMD_EFS_FILE: case CMD_VSS: case CMD_ENC_VSS: case CMD_VSS_T: case CMD_ENC_VSS_T: if(!sb->attr.buf) { log_and_send(asfd, "read cmd with no attribs"); return PARSE_RET_ERROR; } if(sb->flags & SBUF_NEED_LINK) { if(cmd_is_link(rbuf->cmd)) { iobuf_free_content(&sb->link); iobuf_move(&sb->link, rbuf); sb->flags &= ~SBUF_NEED_LINK; return PARSE_RET_COMPLETE; } else { log_and_send(asfd, "got non-link after link in manifest"); return PARSE_RET_NEED_MORE; } } else { iobuf_free_content(&sb->path); iobuf_move(&sb->path, rbuf); if(cmd_is_link(rbuf->cmd)) { sb->flags |= SBUF_NEED_LINK; return PARSE_RET_NEED_MORE; } else if(sb->protocol1 && sb->protocol1->datapth.buf) { // Protocol1 client restore reads // CMD_APPEND and CMD_END_FILE in the // calling function, so pretend it is // complete if we have the hack flag. if(sb->flags & SBUF_CLIENT_RESTORE_HACK) return PARSE_RET_COMPLETE; return PARSE_RET_NEED_MORE; } return PARSE_RET_COMPLETE; } #ifndef HAVE_WIN32 case CMD_SIG: // Fill in the sig/block, if the caller provided // a pointer for one. Server only. if(!blk) return PARSE_RET_NEED_MORE; // Just fill in the sig details. if(blk_set_from_iobuf_sig_and_savepath(blk, rbuf)) return PARSE_RET_ERROR; blk->got_save_path=1; iobuf_free_content(rbuf); return PARSE_RET_COMPLETE; #endif case CMD_DATA: // Need to write the block to disk. // Client only. if(!blk) return PARSE_RET_NEED_MORE; blk->data=rbuf->buf; blk->length=rbuf->len; rbuf->buf=NULL; return PARSE_RET_COMPLETE; case CMD_MESSAGE: case CMD_WARNING: log_recvd(rbuf, cntr, 1); return PARSE_RET_NEED_MORE; case CMD_GEN: if(!strcmp(rbuf->buf, "restoreend") || !strcmp(rbuf->buf, "phase1end") || !strcmp(rbuf->buf, "backupphase2") // Think these are protocol1 things. || !strcmp(rbuf->buf, "backupend") || !strcmp(rbuf->buf, "estimateend")) return PARSE_RET_FINISHED; iobuf_log_unexpected(rbuf, __func__); return PARSE_RET_ERROR; case CMD_FINGERPRINT: if(blk && blk_set_from_iobuf_fingerprint(blk, rbuf)) return PARSE_RET_ERROR; // Fall through. case CMD_MANIFEST: iobuf_free_content(&sb->path); iobuf_move(&sb->path, rbuf); return PARSE_RET_COMPLETE; case CMD_ERROR: logp("got error: %s\n", rbuf->buf); return PARSE_RET_ERROR; case CMD_DATAPTH: if(!sb->protocol1) { iobuf_log_unexpected(rbuf, __func__); return PARSE_RET_ERROR; } if(sb->flags & SBUF_CLIENT_RESTORE_HACK) { sbuf_free_content(sb); sb->flags |= SBUF_CLIENT_RESTORE_HACK; } else sbuf_free_content(sb); iobuf_move(&sb->protocol1->datapth, rbuf); return PARSE_RET_NEED_MORE; case CMD_END_FILE: iobuf_free_content(&sb->endfile); iobuf_move(&sb->endfile, rbuf); if(sb->protocol1) { if(!sb->attr.buf || !sb->protocol1->datapth.buf || (!sbuf_is_filedata(sb) && !sbuf_is_vssdata(sb))) { logp("got unexpected cmd_endfile"); return PARSE_RET_ERROR; } } return PARSE_RET_COMPLETE; default: iobuf_log_unexpected(rbuf, __func__); return PARSE_RET_ERROR; } logp("Fell out of switch unexpectedly in %s()\n", __func__); return PARSE_RET_ERROR; }
static int deal_with_read(struct iobuf *rbuf, struct slist *slist, struct cntr *cntr, uint8_t *end_flags, struct dpth *dpth) { int ret=0; static struct sbuf *inew=NULL; if(!inew && !(inew=sbuf_alloc(PROTO_2))) goto error; switch(rbuf->cmd) { /* Incoming block data. */ case CMD_DATA: if(add_data_to_store(cntr, slist, rbuf, dpth)) goto error; goto end; /* Incoming block signatures. */ case CMD_ATTRIBS_SIGS: // New set of stuff incoming. Clean up. iobuf_free_content(&inew->attr); iobuf_move(&inew->attr, rbuf); inew->protocol2->index=decode_file_no(&inew->attr); // Need to go through slist to find the matching // entry. if(set_up_for_sig_info(slist, inew)) goto error; return 0; case CMD_SIG: if(add_to_sig_list(slist, rbuf)) goto error; goto end; /* Incoming control/message stuff. */ case CMD_MESSAGE: case CMD_WARNING: { struct cntr *cntr=NULL; log_recvd(rbuf, cntr, 0); goto end; } case CMD_GEN: if(!strcmp(rbuf->buf, "sigs_end")) { (*end_flags)|=END_SIGS; goto end; } else if(!strcmp(rbuf->buf, "backup_end")) { (*end_flags)|=END_BACKUP; goto end; } break; default: break; } iobuf_log_unexpected(rbuf, __func__); error: ret=-1; sbuf_free(&inew); end: iobuf_free_content(rbuf); return ret; }
static int process_changed_file(struct asfd *asfd, struct sdirs *sdirs, struct conf **cconfs, struct sbuf *cb, struct sbuf *p1b, const char *adir) { size_t blocklen=0; char *curpath=NULL; //logp("need to process changed file: %s (%s)\n", // cb->path, cb->datapth); // Move datapth onto p1b. iobuf_move(&p1b->protocol1->datapth, &cb->protocol1->datapth); if(!(curpath=prepend_s(adir, p1b->protocol1->datapth.buf))) { log_out_of_memory(__func__); return -1; } if(dpth_protocol1_is_compressed(cb->compression, curpath)) p1b->protocol1->sigfzp=fzp_gzopen(curpath, "rb"); else p1b->protocol1->sigfzp=fzp_open(curpath, "rb"); if(!p1b->protocol1->sigfzp) { logp("could not open %s: %s\n", curpath, strerror(errno)); free(curpath); return -1; } free(curpath); blocklen=get_librsync_block_len(cb->protocol1->endfile.buf); if(!(p1b->protocol1->sigjob= #ifdef RS_DEFAULT_STRONG_LEN rs_sig_begin(blocklen, RS_DEFAULT_STRONG_LEN) #else // This is for librsync-1.0.0. RS_DEFAULT_STRONG_LEN was 8 in // librsync-0.9.7. rs_sig_begin(blocklen, 8, rshash_to_magic_number(get_e_rshash(cconfs[OPT_RSHASH]))) #endif )) { logp("could not start signature job.\n"); return -1; } //logp("sig begin: %s\n", p1b->protocol1->datapth.buf); if(!(p1b->protocol1->infb=rs_filebuf_new(asfd, NULL, p1b->protocol1->sigfzp, -1, blocklen, -1, get_cntr(cconfs[OPT_CNTR])))) { logp("could not rs_filebuf_new for infb.\n"); return -1; } if(!(p1b->protocol1->outfb=rs_filebuf_new(asfd, NULL, NULL, asfd->fd, ASYNC_BUF_LEN, -1, get_cntr(cconfs[OPT_CNTR])))) { logp("could not rs_filebuf_new for in_outfb.\n"); return -1; } // Flag the things that need to be sent (to the client) p1b->flags |= SBUFL_SEND_DATAPTH; p1b->flags |= SBUFL_SEND_STAT; p1b->flags |= SBUFL_SEND_PATH; //logp("sending sig for %s\n", p1b->path); //logp("(%s)\n", p1b->datapth); return 0; }
static #endif int get_last_good_entry(struct manio *manio, struct iobuf *result, struct cntr *cntr, struct dpth *dpth, enum protocol protocol, man_off_t **pos) { int ars=0; int got_vss_start=0; struct sbuf *sb=NULL; struct iobuf lastpath; if(!(sb=sbuf_alloc(protocol))) goto error; iobuf_init(&lastpath); man_off_t_free(pos); if(!(*pos=manio_tell(manio))) { logp("Could not manio_tell first pos in %s(): %s\n", __func__, strerror(errno)); goto error; } while(1) { if(sb->path.buf && !got_vss_start) { iobuf_free_content(&lastpath); iobuf_move(&lastpath, &sb->path); if(!sbuf_is_filedata(sb) && !sbuf_is_vssdata(sb)) { iobuf_free_content(result); iobuf_move(result, &lastpath); man_off_t_free(pos); if(!(*pos=manio_tell(manio))) { logp("Could not manio_tell pos in %s(): %s\n", __func__, strerror(errno)); goto error; } } } if(sb->endfile.buf && !got_vss_start) { iobuf_free_content(result); iobuf_move(result, &lastpath); man_off_t_free(pos); if(!(*pos=manio_tell(manio))) { logp("Could not manio_tell pos in %s(): %s\n", __func__, strerror(errno)); goto error; } } sbuf_free_content(sb); ars=manio_read(manio, sb); if(dpth && set_higher_datapth(sb, dpth)) goto error; switch(ars) { case 0: break; case 1: iobuf_free_content(&lastpath); sbuf_free(&sb); return 0; default: if(result->buf) logp("Error after %s in %s()\n", result->buf, __func__); // Treat error in changed manio as // OK - could have been a short write. iobuf_free_content(&lastpath); sbuf_free(&sb); return 0; } // Some hacks for split_vss. switch(sb->path.cmd) { case CMD_VSS: case CMD_ENC_VSS: got_vss_start=1; break; case CMD_VSS_T: case CMD_ENC_VSS_T: got_vss_start=0; break; case CMD_FILE: case CMD_ENC_FILE: if(S_ISDIR(sb->statp.st_mode)) got_vss_start=0; break; default: break; } if(cntr) { // FIX THIS: cannot distinguish between new and // changed files. cntr_add_changed(cntr, sb->path.cmd); if(sb->endfile.buf) { uint64_t e=strtoull(sb->endfile.buf, NULL, 10); cntr_add_bytes(cntr, e); } } } error: iobuf_free_content(&lastpath); sbuf_free(&sb); man_off_t_free(pos); return -1; }
// returns 1 for finished ok. static int do_stuff_to_receive(struct asfd *asfd, struct sdirs *sdirs, struct conf **cconfs, struct sbuf *rb, struct fzp *chfp, struct dpth *dpth, char **last_requested) { struct iobuf *rbuf=asfd->rbuf; iobuf_free_content(rbuf); // This also attempts to write anything in the write buffer. if(asfd->as->read_write(asfd->as)) { logp("error in %s\n", __func__); return -1; } if(!rbuf->buf) return 0; if(rbuf->cmd==CMD_MESSAGE || rbuf->cmd==CMD_WARNING) { log_recvd(rbuf, cconfs, 0); return 0; } if(rb->protocol1->fzp) { // Currently writing a file (or meta data) switch(rbuf->cmd) { case CMD_APPEND: if(deal_with_receive_append(asfd, rb, cconfs)) goto error; return 0; case CMD_END_FILE: if(deal_with_receive_end_file(asfd, sdirs, rb, chfp, cconfs, last_requested)) goto error; return 0; default: iobuf_log_unexpected(rbuf, __func__); goto error; } } // Otherwise, expecting to be told of a file to save. switch(rbuf->cmd) { case CMD_DATAPTH: iobuf_move(&rb->protocol1->datapth, rbuf); return 0; case CMD_ATTRIBS: iobuf_move(&rb->attr, rbuf); return 0; case CMD_GEN: if(!strcmp(rbuf->buf, "okbackupphase2end")) goto end_phase2; iobuf_log_unexpected(rbuf, __func__); goto error; case CMD_INTERRUPT: // Interrupt - forget about the last requested // file if it matches. Otherwise, we can get // stuck on the select in the async stuff, // waiting for something that will never arrive. if(*last_requested && !strcmp(rbuf->buf, *last_requested)) free_w(last_requested); return 0; default: break; } if(cmd_is_filedata(rbuf->cmd)) { if(deal_with_filedata(asfd, sdirs, rb, rbuf, dpth, cconfs)) goto error; return 0; } iobuf_log_unexpected(rbuf, __func__); error: return -1; end_phase2: return 1; }