void iobuf_free(struct iobuf *iobuf) { if (iobuf != NULL) { NS_FREE(iobuf->buf); iobuf_init(iobuf, 0); } }
/* * sfs_init_read - used in sfs_do_mount to read disk block(blkno, 1) directly. * * @dev: the block device * @blkno: the NO. of disk block * @blk_buffer: the buffer used for read * * (1) init iobuf * (2) read dev into iobuf */ static int sfs_init_read(struct device *dev, uint32_t blkno, void *blk_buffer) { struct iobuf __iob, *iob = iobuf_init(&__iob, blk_buffer, SFS_BLKSIZE, blkno * SFS_BLKSIZE); return dop_io(dev, iob, 0); // 其实就是开始读取啦! }
static int cmd_tget(struct cli *cli, int argc, const char *args) { if (argc != 1 || !benc_isdct(args)) return IPC_COMMERR; size_t nkeys; const char *keys, *p; enum ipc_tval *opts; struct iobuf iob; if ((keys = benc_dget_lst(args, "keys")) == NULL) return IPC_COMMERR; nkeys = benc_nelems(keys); opts = btpd_calloc(nkeys, sizeof(*opts)); p = benc_first(keys); for (int i = 0; i < nkeys; i++) opts[i] = benc_int(p, &p); iob = iobuf_init(1 << 15); iobuf_swrite(&iob, "d4:codei0e6:resultl"); p = benc_dget_any(args, "from"); if (benc_isint(p)) { enum ipc_twc from = benc_int(p, NULL); struct htbl_iter it; struct tlib *tl; for (tl = tlib_iter_first(&it); tl != NULL; tl = tlib_iter_next(&it)) { if (!torrent_haunting(tl) && ( from == IPC_TWC_ALL || (!torrent_active(tl) && from == IPC_TWC_INACTIVE) || (torrent_active(tl) && from == IPC_TWC_ACTIVE))) { iobuf_swrite(&iob, "l"); for (int k = 0; k < nkeys; k++) write_ans(&iob, tl, opts[k]); iobuf_swrite(&iob, "e"); } } } else if (benc_islst(p)) { for (p = benc_first(p); p != NULL; p = benc_next(p)) { struct tlib *tl = NULL; if (benc_isint(p)) tl = tlib_by_num(benc_int(p, NULL)); else if (benc_isstr(p) && benc_strlen(p) == 20) tl = tlib_by_hash(benc_mem(p, NULL, NULL)); else { iobuf_free(&iob); free(opts); return IPC_COMMERR; } if (tl != NULL && !torrent_haunting(tl)) { iobuf_swrite(&iob, "l"); for (int i = 0; i < nkeys; i++) write_ans(&iob, tl, opts[i]); iobuf_swrite(&iob, "e"); } else iobuf_print(&iob, "i%de", IPC_ENOTENT); } } iobuf_swrite(&iob, "ee"); free(opts); return write_buffer(cli, &iob); }
int authorise_server(struct asfd *asfd, struct conf *conf, struct conf *cconf) { int ret=-1; char *cp=NULL; char *password=NULL; char whoareyou[256]=""; struct iobuf *rbuf=asfd->rbuf; if(asfd->read(asfd)) { logp("unable to read initial message\n"); goto end; } if(rbuf->cmd!=CMD_GEN || strncmp_w(rbuf->buf, "hello")) { iobuf_log_unexpected(rbuf, __func__); goto end; } // String may look like... // "hello" // "hello:(version)" // (version) is a version number if((cp=strchr(rbuf->buf, ':'))) { cp++; if(cp && !(cconf->peer_version=strdup_w(cp, __func__))) goto end; } iobuf_free_content(rbuf); snprintf(whoareyou, sizeof(whoareyou), "whoareyou"); if(cconf->peer_version) { long min_ver=0; long cli_ver=0; if((min_ver=version_to_long("1.3.2"))<0 || (cli_ver=version_to_long(cconf->peer_version))<0) return -1; // Stick the server version on the end of the whoareyou string. // if the client version is recent enough. if(min_ver<=cli_ver) snprintf(whoareyou, sizeof(whoareyou), "whoareyou:%s", VERSION); } asfd->write_str(asfd, CMD_GEN, whoareyou); if(asfd->read(asfd)) { logp("unable to get client name\n"); goto end; } cconf->cname=rbuf->buf; iobuf_init(rbuf); asfd->write_str(asfd, CMD_GEN, "okpassword"); if(asfd->read(asfd)) { logp("unable to get password for client %s\n", cconf->cname); goto end; } password=rbuf->buf; iobuf_init(rbuf); if(check_client_and_password(conf, password, cconf)) goto end; if(cconf->version_warn) version_warn(asfd, conf, cconf); logp("auth ok for: %s%s\n", cconf->cname, cconf->password_check?"":" (no password needed)"); asfd->write_str(asfd, CMD_GEN, "ok"); ret=0; end: iobuf_free_content(rbuf); free_w(&password); return ret; }
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; }
void iobuf_free_content(struct iobuf *iobuf) { if(!iobuf || !iobuf->buf) return; free(iobuf->buf); iobuf_init(iobuf); }
void main(int argc, char **argv) { int srvfd, pipefd[2], stdio; Xfsub **xs; char *mtpt; initfcalls(); stdio = 0; mtpt = nil; ARGBEGIN { case '9': noplan9 = 1; break; case 'c': nclust = atoi(EARGF(usage())); if (nclust <= 0) sysfatal("nclust %d non-positive", nclust); break; case 'f': deffile = EARGF(usage()); break; case 'r': norock = 1; break; case 's': stdio = 1; break; case 'v': chatty = 1; break; case 'J': nojoliet = 1; break; case 'm': mtpt = EARGF(usage()); break; default: usage(); } ARGEND switch(argc) { case 0: break; case 1: srvname = argv[0]; break; default: usage(); } iobuf_init(); for(xs=xsublist; *xs; xs++) (*(*xs)->reset)(); if(stdio) { pipefd[0] = 0; pipefd[1] = 1; } else { close(0); close(1); open("/dev/null", OREAD); open("/dev/null", OWRITE); if(pipe(pipefd) < 0) panic(1, "pipe"); if(post9pservice(pipefd[0], srvname, mtpt) < 0) sysfatal("post9pservice: %r"); close(pipefd[0]); } srvfd = pipefd[1]; switch(rfork(RFNOWAIT|RFNOTEG|RFFDG|RFPROC)){ case -1: panic(1, "fork"); default: _exits(0); case 0: break; } io(srvfd); exits(0); }
void main(int argc, char **argv) { int srvfd, pipefd[2], stdio; Xfsub **xs; stdio = 0; ARGBEGIN { case '9': noplan9 = 1; break; case 'c': nclust = atoi(EARGF(usage())); if (nclust <= 0) sysfatal("nclust %d non-positive", nclust); break; case 'f': deffile = EARGF(usage()); break; case 'r': norock = 1; break; case 's': stdio = 1; break; case 'v': chatty = 1; break; case 'J': nojoliet = 1; break; default: usage(); } ARGEND switch(argc) { case 0: break; case 1: srvname = argv[0]; break; default: usage(); } iobuf_init(); for(xs=xsublist; *xs; xs++) (*(*xs)->reset)(); if(stdio) { pipefd[0] = 0; pipefd[1] = 1; } else { close(0); close(1); open("/dev/null", OREAD); open("/dev/null", OWRITE); if(pipe(pipefd) < 0) panic(1, "pipe"); sprint(srvfile, "/srv/%s", srvname); srvfd = create(srvfile, OWRITE|ORCLOSE, 0600); if(srvfd < 0) panic(1, srvfile); fprint(srvfd, "%d", pipefd[0]); close(pipefd[0]); fprint(2, "%s %d: serving %s\n", argv0, getpid(), srvfile); } srvfd = pipefd[1]; switch(rfork(RFNOWAIT|RFNOTEG|RFFDG|RFPROC)){ case -1: panic(1, "fork"); default: _exits(0); case 0: break; } io(srvfd); exits(0); }
static void filter_dispatch(struct mproc *p, struct imsg *imsg) { struct filter_session *s; struct filter_connect q_connect; struct mailaddr maddr; struct msg m; const char *line, *name; uint32_t v, datalen; uint64_t id, qid; int status, type; int fds[2], fdin, fdout; log_trace(TRACE_FILTERS, "filter-api:%s imsg %s", filter_name, filterimsg_to_str(imsg->hdr.type)); switch (imsg->hdr.type) { case IMSG_FILTER_REGISTER: m_msg(&m, imsg); m_get_u32(&m, &v); m_get_string(&m, &name); filter_name = strdup(name); m_end(&m); if (v != FILTER_API_VERSION) { log_warnx("warn: filter-api:%s API mismatch", filter_name); fatalx("filter-api: exiting"); } m_create(p, IMSG_FILTER_REGISTER, 0, 0, -1); m_add_int(p, fi.hooks); m_add_int(p, fi.flags); m_close(p); break; case IMSG_FILTER_EVENT: m_msg(&m, imsg); m_get_id(&m, &id); m_get_int(&m, &type); m_end(&m); switch (type) { case EVENT_CONNECT: s = xcalloc(1, sizeof(*s), "filter_dispatch"); s->id = id; s->pipe.iev.sock = -1; s->pipe.oev.sock = -1; tree_xset(&sessions, id, s); break; case EVENT_DISCONNECT: filter_dispatch_disconnect(id); s = tree_xpop(&sessions, id); free(s); break; case EVENT_RESET: filter_dispatch_reset(id); break; case EVENT_COMMIT: filter_dispatch_commit(id); break; case EVENT_ROLLBACK: filter_dispatch_rollback(id); break; default: log_warnx("warn: filter-api:%s bad event %d", filter_name, type); fatalx("filter-api: exiting"); } break; case IMSG_FILTER_QUERY: m_msg(&m, imsg); m_get_id(&m, &id); m_get_id(&m, &qid); m_get_int(&m, &type); switch(type) { case QUERY_CONNECT: m_get_sockaddr(&m, (struct sockaddr*)&q_connect.local); m_get_sockaddr(&m, (struct sockaddr*)&q_connect.remote); m_get_string(&m, &q_connect.hostname); m_end(&m); filter_register_query(id, qid, type); filter_dispatch_connect(id, &q_connect); break; case QUERY_HELO: m_get_string(&m, &line); m_end(&m); filter_register_query(id, qid, type); filter_dispatch_helo(id, line); break; case QUERY_MAIL: m_get_mailaddr(&m, &maddr); m_end(&m); filter_register_query(id, qid, type); filter_dispatch_mail(id, &maddr); break; case QUERY_RCPT: m_get_mailaddr(&m, &maddr); m_end(&m); filter_register_query(id, qid, type); filter_dispatch_rcpt(id, &maddr); break; case QUERY_DATA: m_end(&m); filter_register_query(id, qid, type); filter_dispatch_data(id); break; case QUERY_EOM: m_get_u32(&m, &datalen); m_end(&m); filter_register_query(id, qid, type); filter_dispatch_eom(id, datalen); break; default: log_warnx("warn: filter-api:%s bad query %d", filter_name, type); fatalx("filter-api: exiting"); } break; case IMSG_FILTER_PIPE: m_msg(&m, imsg); m_get_id(&m, &id); m_end(&m); fdout = imsg->fd; fdin = -1; if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, fds) == -1) { log_warn("warn: filter-api:%s socketpair", filter_name); close(fdout); } else { s = tree_xget(&sessions, id); s->pipe.eom_called = 0; s->pipe.error = 0; s->pipe.idatalen = 0; s->pipe.odatalen = 0; iobuf_init(&s->pipe.obuf, 0, 0); io_init(&s->pipe.oev, fdout, s, filter_io_out, &s->pipe.obuf); io_set_write(&s->pipe.oev); iobuf_init(&s->pipe.ibuf, 0, 0); io_init(&s->pipe.iev, fds[0], s, filter_io_in, &s->pipe.ibuf); io_set_read(&s->pipe.iev); fdin = fds[1]; } log_trace(TRACE_FILTERS, "filter-api:%s %016"PRIx64" tx pipe %d -> %d", filter_name, id, fdin, fdout); m_create(&fi.p, IMSG_FILTER_PIPE, 0, 0, fdin); m_add_id(&fi.p, id); m_close(&fi.p); break; } }
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; }
int extra_comms(struct async *as, struct conf **confs, enum action *action, char **incexc) { int ret=-1; char *feat=NULL; struct asfd *asfd; struct iobuf *rbuf; const char *orig_client=get_string(confs[OPT_ORIG_CLIENT]); asfd=as->asfd; rbuf=asfd->rbuf; if(asfd->write_str(asfd, CMD_GEN, "extra_comms_begin")) { logp("Problem requesting extra_comms_begin\n"); goto end; } // Servers greater than 1.3.0 will list the extra_comms // features they support. if(asfd->read(asfd)) { logp("Problem reading response to extra_comms_begin\n"); goto end; } feat=rbuf->buf; if(rbuf->cmd!=CMD_GEN || strncmp_w(feat, "extra_comms_begin ok")) { iobuf_log_unexpected(rbuf, __func__); goto end; } logp("%s\n", feat); iobuf_init(rbuf); // Can add extra bits here. The first extra bit is the // autoupgrade stuff. if(server_supports_autoupgrade(feat) && get_string(confs[OPT_AUTOUPGRADE_DIR]) && get_string(confs[OPT_AUTOUPGRADE_OS]) && autoupgrade_client(as, confs)) goto end; // :srestore: means that the server wants to do a restore. if(server_supports(feat, ":srestore:")) { if(get_int(confs[OPT_SERVER_CAN_RESTORE])) { logp("Server is initiating a restore\n"); if(incexc_recv_client_restore(asfd, incexc, confs)) goto end; if(*incexc) { if(conf_parse_incexcs_buf(confs, *incexc)) goto end; *action=ACTION_RESTORE; log_restore_settings(confs, 1); } } else { logp("Server wants to initiate a restore\n"); logp("Client configuration says no\n"); if(asfd->write_str(asfd, CMD_GEN, "srestore not ok")) goto end; } } if(orig_client) { char str[512]=""; snprintf(str, sizeof(str), "orig_client=%s", orig_client); if(!server_supports(feat, ":orig_client:")) { logp("Server does not support switching client.\n"); goto end; } if(asfd->write_str(asfd, CMD_GEN, str) || asfd->read_expect(asfd, CMD_GEN, "orig_client ok")) { logp("Problem requesting %s\n", str); goto end; } logp("Switched to client %s\n", orig_client); } // :sincexc: is for the server giving the client the // incexc config. if(*action==ACTION_BACKUP || *action==ACTION_BACKUP_TIMED || *action==ACTION_TIMER_CHECK) { if(!*incexc && server_supports(feat, ":sincexc:")) { logp("Server is setting includes/excludes.\n"); if(incexc_recv_client(asfd, incexc, confs)) goto end; if(*incexc && conf_parse_incexcs_buf(confs, *incexc)) goto end; } } if(server_supports(feat, ":counters:")) { if(asfd->write_str(asfd, CMD_GEN, "countersok")) goto end; set_int(confs[OPT_SEND_CLIENT_CNTR], 1); } // :incexc: is for the client sending the server the // incexc conf so that it better knows what to do on // resume. if(server_supports(feat, ":incexc:") && incexc_send_client(asfd, confs)) goto end; if(server_supports(feat, ":uname:")) { const char *clientos=NULL; #ifdef HAVE_WIN32 #ifdef _WIN64 clientos="Windows 64bit"; #else clientos="Windows 32bit"; #endif #else struct utsname utsname; if(!uname(&utsname)) clientos=(const char *)utsname.sysname; #endif if(clientos) { char msg[128]=""; snprintf(msg, sizeof(msg), "uname=%s", clientos); if(asfd->write_str(asfd, CMD_GEN, msg)) goto end; } } if(server_supports(feat, ":csetproto:")) { char msg[128]=""; // Use protocol2 if no choice has been made on client side. if(get_e_protocol(confs[OPT_PROTOCOL])==PROTO_AUTO) { logp("Server has protocol=0 (auto)\n"); set_e_protocol(confs[OPT_PROTOCOL], PROTO_2); } // Send choice to server. snprintf(msg, sizeof(msg), "protocol=%d", get_e_protocol(confs[OPT_PROTOCOL])); if(asfd->write_str(asfd, CMD_GEN, msg)) goto end; logp("Using protocol=%d\n", get_e_protocol(confs[OPT_PROTOCOL])); } else if(server_supports(feat, ":forceproto=1:")) { logp("Server is forcing protocol 1\n"); if(get_e_protocol(confs[OPT_PROTOCOL])!=PROTO_AUTO && get_e_protocol(confs[OPT_PROTOCOL])!=PROTO_1) { logp("But client has set protocol=%d!\n", get_e_protocol(confs[OPT_PROTOCOL])); goto end; } set_e_protocol(confs[OPT_PROTOCOL], PROTO_1); } else if(server_supports(feat, ":forceproto=2:")) { logp("Server is forcing protocol 2\n"); if(get_e_protocol(confs[OPT_PROTOCOL])!=PROTO_AUTO && get_e_protocol(confs[OPT_PROTOCOL])!=PROTO_2) { logp("But client has set protocol=%d!\n", get_e_protocol(confs[OPT_PROTOCOL])); goto end; } set_e_protocol(confs[OPT_PROTOCOL], PROTO_2); } if(server_supports(feat, ":msg:")) { set_int(confs[OPT_MESSAGE], 1); if(asfd->write_str(asfd, CMD_GEN, "msg")) goto end; } #ifndef RS_DEFAULT_STRONG_LEN if(server_supports(feat, ":rshash=blake2:")) { set_e_rshash(confs[OPT_RSHASH], RSHASH_BLAKE2); // Send choice to server. if(asfd->write_str(asfd, CMD_GEN, "rshash=blake2")) goto end; } else #endif set_e_rshash(confs[OPT_RSHASH], RSHASH_MD4); if(asfd->write_str(asfd, CMD_GEN, "extra_comms_end") || asfd->read_expect(asfd, CMD_GEN, "extra_comms_end ok")) { logp("Problem requesting extra_comms_end\n"); goto end; } ret=0; end: return ret; }
int do_list_client(struct asfd *asfd, enum action act, struct conf **confs) { int ret=-1; char msg[512]=""; struct sbuf *sb=NULL; struct iobuf *rbuf=asfd->rbuf; const char *backup=get_string(confs[OPT_BACKUP]); const char *backup2=get_string(confs[OPT_BACKUP2]); const char *browsedir=get_string(confs[OPT_BROWSEDIR]); const char *regex=get_string(confs[OPT_REGEX]); //logp("in do_list\n"); switch(act) { case ACTION_LIST: case ACTION_LIST_LONG: if(browsedir && regex) { logp("You cannot specify both a directory and a regular expression when listing.\n"); goto end; } if(browsedir) snprintf(msg, sizeof(msg), "listb %s:%s", backup?backup:"", browsedir); else snprintf(msg, sizeof(msg), "list %s:%s", backup?backup:"", regex?regex:""); break; case ACTION_DIFF: case ACTION_DIFF_LONG: snprintf(msg, sizeof(msg), "diff %s:%s", backup?backup:"", backup2?backup2:""); break; default: logp("unknown action %d\n", act); goto end; } if(asfd->write_str(asfd, CMD_GEN, msg) || asfd_read_expect(asfd, CMD_GEN, "ok")) goto end; if(!(sb=sbuf_alloc(get_protocol(confs)))) goto end; iobuf_init(&sb->path); iobuf_init(&sb->link); iobuf_init(&sb->attr); // This should probably should use the sbuf stuff. while(1) { sbuf_free_content(sb); iobuf_free_content(rbuf); if(asfd->read(asfd)) break; if(rbuf->cmd==CMD_MESSAGE) { printf("%s\n", rbuf->buf); if(!strcmp(rbuf->buf, "no backups")) ret=0; goto end; } else if(rbuf->cmd==CMD_TIMESTAMP) { // A backup timestamp, just print it. printf("Backup: %s\n", rbuf->buf); if(browsedir) printf("Listing directory: %s\n", browsedir); if(regex) printf("With regex: %s\n", regex); continue; } else if(rbuf->cmd!=CMD_ATTRIBS) { iobuf_log_unexpected(rbuf, __func__); goto end; } iobuf_copy(&sb->attr, rbuf); iobuf_init(rbuf); attribs_decode(sb); if(asfd->read(asfd)) { logp("got stat without an object\n"); goto end; } iobuf_copy(&sb->path, rbuf); iobuf_init(rbuf); if(sb->path.cmd==CMD_DIRECTORY || sb->path.cmd==CMD_FILE || sb->path.cmd==CMD_ENC_FILE || sb->path.cmd==CMD_EFS_FILE || sb->path.cmd==CMD_SPECIAL) { list_item(act, sb); } else if(cmd_is_link(sb->path.cmd)) // symlink or hardlink { if(asfd->read(asfd) || rbuf->cmd!=sb->path.cmd) { logp("could not get link %s\n", iobuf_to_printable(&sb->path)); goto end; } iobuf_copy(&sb->link, rbuf); iobuf_init(rbuf); list_item(act, sb); } else { logp("unlistable %s\n", iobuf_to_printable(&sb->path)); } } ret=0; end: sbuf_free(&sb); if(!ret) logp("List finished ok\n"); return ret; }
void iobuf_xinit(struct iobuf *io, size_t size, size_t max, const char *where) { if (iobuf_init(io, size, max) == -1) errx(1, "%s: iobuf_init(%p, %zu, %zu)", where, io, size, max); }
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; }
void cmd_add(int argc, char **argv) { int ch, topdir = 0, start = 1, nfile, nloaded = 0; size_t dirlen = 0, labellen = 0; char *dir = NULL, *name = NULL, *glabel = NULL, *label; while ((ch = getopt_long(argc, argv, "NTd:l:n:", add_opts, NULL)) != -1) { switch (ch) { case 'N': start = 0; break; case 'T': topdir = 1; break; case 'd': dir = optarg; if ((dirlen = strlen(dir)) == 0) diemsg("bad option value for -d.\n"); break; case 'l': glabel = optarg; if ((labellen = strlen(dir)) == 0) diemsg("bad option value for -l.\n"); break; case 'n': name = optarg; break; default: usage_add(); } } argc -= optind; argv += optind; if (argc < 1) usage_add(); btpd_connect(); char *mi; size_t mi_size; enum ipc_err code; char dpath[PATH_MAX]; struct iobuf iob; for (nfile = 0; nfile < argc; nfile++) { if ((mi = mi_load(argv[nfile], &mi_size)) == NULL) { fprintf(stderr, "error loading '%s' (%s).\n", argv[nfile], strerror(errno)); continue; } if (dir == NULL) { dir = dirname(argv[nfile]); if ((dirlen = strlen(dir)) == 0) { fprintf(stderr, "error obtaining dirname for '%s'.\n", argv[nfile]); continue; } } iob = iobuf_init(PATH_MAX); iobuf_write(&iob, dir, dirlen); if (topdir && !mi_simple(mi)) { size_t tdlen; const char *td = benc_dget_mem(benc_dget_dct(mi, "info"), "name", &tdlen); iobuf_swrite(&iob, "/"); iobuf_write(&iob, td, tdlen); } iobuf_swrite(&iob, "\0"); if ((errno = make_abs_path(iob.buf, dpath)) != 0) { fprintf(stderr, "make_abs_path '%s' failed (%s).\n", dpath, strerror(errno)); iobuf_free(&iob); continue; } if(NULL == glabel) label = benc_dget_str(mi, "announce", NULL); else label = glabel; code = btpd_add(ipc, mi, mi_size, dpath, name, label); if ((code == IPC_OK) && start) { struct ipc_torrent tspec; tspec.by_hash = 1; mi_info_hash(mi, tspec.u.hash); code = btpd_start(ipc, &tspec); } if (code != IPC_OK) { fprintf(stderr, "command failed for '%s' (%s).\n", argv[nfile], ipc_strerror(code)); } else { nloaded++; } iobuf_free(&iob); } if (nloaded != nfile) { diemsg("error loaded %d of %d files.\n", nloaded, nfile); } }
int authorise_server(struct asfd *asfd, struct conf **globalcs, struct conf **cconfs) { int ret=-1; char *cp=NULL; char *password=NULL; char *cname=NULL; char whoareyou[256]=""; struct iobuf *rbuf=asfd->rbuf; const char *peer_version=NULL; if(asfd->read(asfd)) { logp("unable to read initial message\n"); goto end; } if(rbuf->cmd!=CMD_GEN || strncmp_w(rbuf->buf, "hello")) { iobuf_log_unexpected(rbuf, __func__); goto end; } // String may look like... // "hello" // "hello:(version)" // (version) is a version number if((cp=strchr(rbuf->buf, ':'))) { cp++; if(cp && set_string(cconfs[OPT_PEER_VERSION], cp)) goto end; } iobuf_free_content(rbuf); snprintf(whoareyou, sizeof(whoareyou), "whoareyou"); peer_version=get_string(cconfs[OPT_PEER_VERSION]); if(peer_version) { long min_ver=0; long cli_ver=0; if((min_ver=version_to_long("1.3.2"))<0 || (cli_ver=version_to_long(peer_version))<0) return -1; // Stick the server version on the end of the whoareyou string. // if the client version is recent enough. if(min_ver<=cli_ver) snprintf(whoareyou, sizeof(whoareyou), "whoareyou:%s", VERSION); } if(asfd->write_str(asfd, CMD_GEN, whoareyou) || asfd->read(asfd)) { logp("unable to get client name\n"); goto end; } if(!(cname=strdup_w(rbuf->buf, __func__))) goto end; if(!get_int(globalcs[OPT_CNAME_FQDN])) strip_fqdn(&cname); if(get_int(globalcs[OPT_CNAME_LOWERCASE])) strlwr(cname); if(set_string(cconfs[OPT_CNAME], cname)) goto end; iobuf_free_content(rbuf); if(asfd->write_str(asfd, CMD_GEN, "okpassword") || asfd->read(asfd)) { logp("unable to get password for client %s\n", get_string(cconfs[OPT_CNAME])); goto end; } password=rbuf->buf; iobuf_init(rbuf); if(check_client_and_password(globalcs, password, cconfs)) goto end; if(get_int(cconfs[OPT_VERSION_WARN])) version_warn(asfd, globalcs, cconfs); logp("auth ok for: %s%s\n", get_string(cconfs[OPT_CNAME]), get_int(cconfs[OPT_PASSWORD_CHECK])? "":" (no password needed)"); if(asfd->write_str(asfd, CMD_GEN, "ok")) goto end; ret=0; end: iobuf_free_content(rbuf); free_w(&password); free_w(&cname); return ret; }
static inline int ui_switch_names( Console* cons ) { /* Switch name */ Iobuf switchNameIobody; Iobuf* switchNameIo; Region switchNamebody; Region* switchName; uchar switchNameBuffer[ UI_SWITCH_NAME_SIZE * 2 ]; uchar* switchNamebuffers[ 2 ]; int status = 0; int i = 1; int switchId = 1; uchar curname[ UI_SWITCH_NAME_SIZE ] = UI_SWITCH_NAME; uint convSize = 0; switchNameIo = &switchNameIobody; switchName = &switchNamebody; switchNamebuffers[ 0 ] = switchNameBuffer; switchNamebuffers[ 1 ] = switchNameBuffer + UI_SWITCH_NAME_SIZE; while( 1 ){ status = iobuf_init( switchNameIo, cons ); ASSERT( status == ERR_NONE ); status = region_setup( switchName, switchFrame, ( ( ( i - 1 ) % UI_SWITCH_NAME_PER_LINE ) * UI_SWITCH_NAME_SIZE ), ( i - 1 ) / UI_SWITCH_NAME_PER_LINE + 2, UI_SWITCH_NAME_SIZE, 1, 0, 0, 0, switchNameIo, switchNamebuffers ); ASSERT( status == ERR_NONE ); status = region_init( switchName ); ASSERT( status == ERR_NONE ); if( i > 18 ){ switchId = 153 + i - 19; } else { switchId = i; } convSize = utos( switchId, (char*)(curname + UI_SWITCH_NAME_NUMBER_OFFSET) ); switch( convSize ){ case 1: curname[ UI_SWITCH_NAME_NUMBER_OFFSET + 2 ] = curname[ UI_SWITCH_NAME_NUMBER_OFFSET ]; curname[ UI_SWITCH_NAME_NUMBER_OFFSET ] = ' '; curname[ UI_SWITCH_NAME_NUMBER_OFFSET + 1 ] = ' '; break; case 2: curname[ UI_SWITCH_NAME_NUMBER_OFFSET + 2 ] = curname[ UI_SWITCH_NAME_NUMBER_OFFSET + 1 ]; curname[ UI_SWITCH_NAME_NUMBER_OFFSET + 1 ] = curname[ UI_SWITCH_NAME_NUMBER_OFFSET ]; curname[ UI_SWITCH_NAME_NUMBER_OFFSET ] = ' '; } curname[ UI_SWITCH_NAME_NUMBER_OFFSET + 3 ] = ' '; curname[ UI_SWITCH_NAME_SIZE - 1 ] = '\0'; status = region_write( switchName, (char*)curname ); ASSERT( status == ERR_NONE ); while( ! region_flushed( switchName ) ){ status = region_flush( switchName ); ASSERT( status == ERR_NONE ); } i += 1; if( i > SWITCHES_COUNT ){ break; } } return ERR_NONE; }