int cpeer_kill(struct cpeer *p) { if(!p) return 0; if(__sync_bool_compare_and_swap(&p->status,CPEER_CONNECTED,CPEER_DISCONNECTED)) { printf("ref:%d,close peer id:%lu,peer:%p,nc:%p\n",p->refcount,p->id,p,p->nc); close(p->sd); fdev_del(&p->ioev); //push one msg to notify disconnect struct msg_t *msg = (struct msg_t *)mmalloc(p->nc->allocator, sizeof(struct msg_t)); msg->buf = NULL; msg->len = 0; msg->peer_id = p->id; msg->type = MSG_DISCONNECT; queue_push(p->nc->recv_queue,msg); } if(__sync_bool_compare_and_swap(&p->refcount,0,1)) { printf("free peer id:%lu\n",p->id); iobuf_free(p->allocator,&p->recvbuf); iobuf_free(p->allocator,&p->sendbuf); //free send queue struct msg_t *msg = NULL,*next = NULL; thread_mutex_lock(p->sq_mutex); msg = BTPDQ_FIRST(&p->send_queue); while(msg){ next = BTPDQ_NEXT(msg,msg_entry); BTPDQ_REMOVE(&p->send_queue,msg,msg_entry); mfree(p->allocator,msg->buf); mfree(p->allocator,msg); msg = next; } thread_mutex_unlock(p->sq_mutex); thread_mutex_destroy(p->mpool_mutex); thread_mutex_destroy(p->sq_mutex); allocator_destroy(p->allocator); thread_mutex_lock(p->nc->peer_mutex); mfree(p->nc->allocator,p); p->nc->peer = NULL; thread_mutex_unlock(p->nc->peer_mutex); } return 0; }
static void ns_destroy_conn(struct ns_connection *conn) { closesocket(conn->sock); iobuf_free(&conn->recv_iobuf); iobuf_free(&conn->send_iobuf); #ifdef NS_ENABLE_SSL if (conn->ssl != NULL) { SSL_free(conn->ssl); } if (conn->ssl_ctx != NULL) { SSL_CTX_free(conn->ssl_ctx); } #endif NS_FREE(conn); }
static const char *test_iobuf(void) { struct iobuf io; iobuf_init(&io, 0); ASSERT(io.buf == NULL && io.len == 0 && io.size == 0); iobuf_free(&io); ASSERT(io.buf == NULL && io.len == 0 && io.size == 0); iobuf_init(&io, 10); ASSERT(io.buf != NULL && io.len == 0 && io.size == 10); iobuf_free(&io); ASSERT(io.buf == NULL && io.len == 0 && io.size == 0); return NULL; }
static void test_empty() { struct iobuf *buf = iobuf_new(); TEST_ASSERT(iobuf_rstart(buf) == NULL); TEST_ASSERT(iobuf_rsize(buf) == 0); TEST_ASSERT(iobuf_wstart(buf) == NULL); TEST_ASSERT(iobuf_wsize(buf) == 0); iobuf_drain(buf, 0); TEST_ASSERT(iobuf_rstart(buf) == NULL); TEST_ASSERT(iobuf_rsize(buf) == 0); TEST_ASSERT(iobuf_wstart(buf) == NULL); TEST_ASSERT(iobuf_wsize(buf) == 0); iobuf_reserve(buf, 0); TEST_ASSERT(iobuf_rstart(buf) == NULL); TEST_ASSERT(iobuf_rsize(buf) == 0); TEST_ASSERT(iobuf_wstart(buf) == NULL); TEST_ASSERT(iobuf_wsize(buf) == 0); iobuf_fill(buf, 0); TEST_ASSERT(iobuf_rstart(buf) == NULL); TEST_ASSERT(iobuf_rsize(buf) == 0); TEST_ASSERT(iobuf_wstart(buf) == NULL); TEST_ASSERT(iobuf_wsize(buf) == 0); iobuf_free(buf); }
static void test_preallocated() { struct iobuf *buf = iobuf_new1(4096); TEST_ASSERT(iobuf_rstart(buf) != NULL); TEST_ASSERT(iobuf_rsize(buf) == 0); TEST_ASSERT(iobuf_wstart(buf) != NULL); TEST_ASSERT(iobuf_wsize(buf) == 4096); size_t size = iobuf_wsize(buf); memset(iobuf_wstart(buf), 42, size); iobuf_fill(buf, size); TEST_ASSERT(iobuf_rstart(buf) != NULL); TEST_ASSERT(iobuf_rsize(buf) == 4096); TEST_ASSERT(iobuf_wstart(buf) != NULL); TEST_ASSERT(iobuf_wsize(buf) == 0); char *rbuf = ((char *)iobuf_rstart(buf)); for (size_t i = 0; i < 4096; ++i) { TEST_ASSERT(rbuf[i] == 42); TEST_ASSERT(iobuf_rsize(buf) >= 1); iobuf_drain(buf, 1); } TEST_ASSERT(iobuf_rsize(buf) == 0); TEST_ASSERT(iobuf_wsize(buf) == 4096); iobuf_free(buf); }
static void test_one_byte() { struct iobuf *buf = iobuf_new(); iobuf_reserve(buf, 1); TEST_ASSERT(iobuf_rstart(buf) != NULL); TEST_ASSERT(iobuf_rsize(buf) == 0); TEST_ASSERT(iobuf_wstart(buf) != NULL); TEST_ASSERT(iobuf_wsize(buf) == 1); *((char *)iobuf_wstart(buf)) = 42; iobuf_fill(buf, 1); TEST_ASSERT(iobuf_rstart(buf) != NULL); TEST_ASSERT(iobuf_rsize(buf) == 1); TEST_ASSERT(iobuf_wstart(buf) != NULL); TEST_ASSERT(iobuf_wsize(buf) == 0); TEST_ASSERT(*((char *)iobuf_rstart(buf)) == 42); iobuf_drain(buf, 1); TEST_ASSERT(iobuf_rstart(buf) != NULL); TEST_ASSERT(iobuf_rsize(buf) == 0); TEST_ASSERT(iobuf_wstart(buf) != NULL); TEST_ASSERT(iobuf_wsize(buf) == 1); iobuf_free(buf); }
void uv_custom_poll_free(struct uv_custom_poll_t *data) { if(data->is_ssl == 1) { mbedtls_ssl_free(&data->ssl.ctx); } if(data->host != NULL) { FREE(data->host); } if(data->send_iobuf.size > 0) { iobuf_free(&data->send_iobuf); } if(data->recv_iobuf.size > 0) { iobuf_free(&data->recv_iobuf); } FREE(data); }
static void test_random_access() { struct fake_fd fd; fake_fd_init(&fd); char out[sizeof(fd.in)]; memset(out, 0, sizeof(out)); size_t read = 0; struct iobuf *buf = iobuf_new(); for (;;) { iobuf_reserve(buf, 1024); TEST_ASSERT(iobuf_wsize(buf) >= 1024); ssize_t ret = fake_read(&fd, iobuf_wstart(buf), 1024); if (ret == 0) { break; } TEST_ASSERT(ret); read += ret; } TEST_ASSERT_EQUAL(sizeof(fd.in), read); iobuf_free(buf); }
static void test_reserved() { struct iobuf *buf = iobuf_new(); iobuf_reserve(buf, 4096); TEST_ASSERT(iobuf_wstart(buf) != NULL); TEST_ASSERT(iobuf_wsize(buf) == 4096); iobuf_free(buf); }
static void httptr_free(struct httptr_req *treq) { if (treq->sd != -1) { btpd_ev_del(&treq->ioev); close(treq->sd); } btpd_timer_del(&treq->timer); iobuf_free(&treq->buf); free(treq); }
static int write_buffer(struct cli *cli, struct iobuf *iob) { int err = 0; if (!iob->error) { uint32_t len = iob->off; write_fully(cli->sd, &len, sizeof(len)); err = write_fully(cli->sd, iob->buf, iob->off); } else btpd_err("Out of memory.\n"); iobuf_free(iob); return err; }
static const char *test_hexdump_file(void) { const char *path = "test_hexdump"; const char *want = "0xbeef :0 -> :0 3\n" "0000 66 6f 6f " " foo\n\n"; char *data, *got; size_t size; struct ns_connection *nc = (struct ns_connection *) calloc(1, sizeof(*nc)); /* "In the GNU system, non-null pointers are printed as unsigned integers, * as if a `%#x' conversion were used. Null pointers print as `(nil)'. * (Pointers might print differently in other systems.)" * indeed it prints 0x0 on apple. */ nc->user_data = (void *)0xbeef; truncate(path, 0); iobuf_append(&nc->send_iobuf, "foo", 3); iobuf_append(&nc->recv_iobuf, "bar", 3); ns_hexdump_connection(nc, path, 3, NS_SEND); iobuf_free(&nc->send_iobuf); iobuf_free(&nc->recv_iobuf); free(nc); ASSERT((data = read_file(path, &size)) != NULL); unlink(path); got = data; while(got-data < (int)size && *got++ != ' '); size -= got-data; ASSERT(strncmp(got, want, size) == 0); free(data); return NULL; }
int write_status(enum cntr_status cntr_status, const char *path, struct cntr *cntr) { time_t now=0; time_t diff=0; static time_t lasttime=0; static size_t l=0; static struct iobuf *wbuf=NULL; if(!wasfd) return 0; if(!cntr || !cntr->bno) return 0; // Only update every 2 seconds. now=time(NULL); diff=now-lasttime; if(diff<2) { // Might as well do this in case they fiddled their // clock back in time. if(diff<0) lasttime=now; return 0; } lasttime=now; // Only get a new string if we did not manage to write the previous // one. if(!l) { cntr->cntr_status=cntr_status; if(!(l=cntr_to_str(cntr, path))) goto error; if(!wbuf && !(wbuf=iobuf_alloc())) goto error; iobuf_set(wbuf, CMD_APPEND, cntr->str, l); } switch(wasfd->append_all_to_write_buffer(wasfd, wbuf)) { case APPEND_OK: l=0; // Fall through. case APPEND_BLOCKED: return 0; default: break; } error: iobuf_free(&wbuf); return -1; }
static void test_grow() { struct iobuf *buf = iobuf_new(); for (size_t i = 0; i < 4096; ++i) { iobuf_reserve(buf, i); TEST_ASSERT(iobuf_wsize(buf) == i); } for (size_t i = 4096; i != 0; --i) { iobuf_reserve(buf, i); TEST_ASSERT(iobuf_wsize(buf) == 4096); } iobuf_free(buf); }
static void test_reclaim_full() { struct iobuf *buf = iobuf_new(); iobuf_reserve(buf, 4096); TEST_ASSERT(iobuf_wsize(buf) == 4096); memset(iobuf_wstart(buf), 1, 4096); iobuf_fill(buf, 4096); TEST_ASSERT(iobuf_wsize(buf) == 0); TEST_ASSERT(iobuf_rsize(buf) == 4096); TEST_ASSERT(memneq(iobuf_rstart(buf), 1, iobuf_rsize(buf))); iobuf_drain(buf, 2048); TEST_ASSERT(iobuf_wsize(buf) == 0); TEST_ASSERT(iobuf_rsize(buf) == 2048); iobuf_reserve(buf, 2048); TEST_ASSERT(iobuf_wsize(buf) == 2048); TEST_ASSERT(iobuf_rsize(buf) == 2048); TEST_ASSERT(memneq(iobuf_rstart(buf), 1, iobuf_rsize(buf))); iobuf_free(buf); }
static void test_reclaim() { struct iobuf *buf = iobuf_new(); iobuf_reserve(buf, 4096); TEST_ASSERT(iobuf_wsize(buf) == 4096); memset(iobuf_wstart(buf), 1, 2048); iobuf_fill(buf, 2048); TEST_ASSERT(iobuf_wsize(buf) == 2048); TEST_ASSERT(iobuf_rsize(buf) == 2048); TEST_ASSERT(memneq(iobuf_rstart(buf), 1, iobuf_rsize(buf))); iobuf_drain(buf, 1024); TEST_ASSERT_EQUAL(2048, iobuf_wsize(buf)); TEST_ASSERT_EQUAL(1024, iobuf_rsize(buf)); iobuf_reserve(buf, 4096); TEST_ASSERT_EQUAL(4096, iobuf_wsize(buf)); TEST_ASSERT_EQUAL(1024, iobuf_rsize(buf)); TEST_ASSERT(memneq(iobuf_rstart(buf), 1, iobuf_rsize(buf))); iobuf_free(buf); }
static void test_fill_drain() { struct iobuf *buf = iobuf_new(); iobuf_reserve(buf, 4096); TEST_ASSERT(iobuf_wsize(buf) == 4096); iobuf_fill(buf, 2048); TEST_ASSERT(iobuf_wsize(buf) == 2048); TEST_ASSERT(iobuf_rsize(buf) == 2048); iobuf_reserve(buf, 4096); TEST_ASSERT(iobuf_wsize(buf) == 4096); TEST_ASSERT(iobuf_rsize(buf) == 2048); iobuf_fill(buf, 2048); TEST_ASSERT(iobuf_wsize(buf) == 2048); TEST_ASSERT(iobuf_rsize(buf) == 4096); iobuf_drain(buf, 2048); TEST_ASSERT_EQUAL(2048, iobuf_wsize(buf)); TEST_ASSERT(iobuf_rsize(buf) == 2048); iobuf_drain(buf, 2048); TEST_ASSERT_EQUAL(4096 + 2048, iobuf_wsize(buf)); iobuf_free(buf); }
int peer_kill(struct peer *p) { if(!p) return 0; if(__sync_bool_compare_and_swap(&p->status,PEER_CONNECTED,PEER_DISCONNECTED)) { close(p->sd); fdev_del(&p->ioev); log_error(p->ns->log,"ns peer socket closed,peer ip:%s.", inet_ntoa(p->addr.sin_addr)); //push one msg to notify disconnect if(!p->ns->close_func) { struct msg_t *msg = (struct msg_t *)mmalloc(p->ns->allocator, sizeof(struct msg_t)); msg->buf = NULL; msg->len = 0; msg->peer_id = p->id; msg->type = MSG_DISCONNECT; queue_push(p->ns->recv_queue,msg); log_error(p->ns->log,"ns push notify msg for client:%s disconneced.", inet_ntoa(p->addr.sin_addr)); } else { log_error(p->ns->log,"ns call close_func for client:%s disconneced.", inet_ntoa(p->addr.sin_addr)); p->ns->close_func(p->ns,p->id); } } if(__sync_bool_compare_and_swap(&p->refcount,0,1)) { log_error(p->ns->log,"ns peer freed,peer ip:%s.", inet_ntoa(p->addr.sin_addr)); iobuf_free(p->allocator,&p->recvbuf); iobuf_free(p->allocator,&p->sendbuf); //free send queue struct msg_t *msg = NULL,*next = NULL; thread_mutex_lock(p->sq_mutex); msg = BTPDQ_FIRST(&p->send_queue); while(msg){ next = BTPDQ_NEXT(msg,msg_entry); BTPDQ_REMOVE(&p->send_queue,msg,msg_entry); mfree(p->allocator,msg->buf); mfree(p->allocator,msg); msg = next; } thread_mutex_unlock(p->sq_mutex); thread_mutex_destroy(p->mpool_mutex); thread_mutex_destroy(p->sq_mutex); allocator_destroy(p->allocator); mfree(p->ns->allocator,p); thread_mutex_lock(p->ns->ptbl_mutex); ptbl_remove(p->ns->ptbl,&p->id); p->ns->npeers--; thread_mutex_unlock(p->ns->ptbl_mutex); } return 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 backup_phase2_client_burp2(struct asfd *asfd, struct conf *conf, int resume) { int ret=-1; int sigs_end=0; int backup_end=0; int requests_end=0; int blk_requests_end=0; struct win *win=NULL; // Rabin sliding window. struct slist *slist=NULL; struct blist *blist=NULL; struct iobuf *rbuf=NULL; struct iobuf *wbuf=NULL; logp("Phase 2 begin (send backup data)\n"); if(!(slist=slist_alloc()) || !(blist=blist_alloc()) || !(wbuf=iobuf_alloc()) || blks_generate_init(conf) || !(win=win_alloc(&conf->rconf))) goto end; rbuf=asfd->rbuf; if(!resume) { // Only do this bit if the server did not tell us to resume. if(asfd->write_str(asfd, CMD_GEN, "backupphase2") || asfd->read_expect(asfd, CMD_GEN, "ok")) goto end; } else if(conf->send_client_cntr) { // On resume, the server might update the client with the // counters. if(cntr_recv(asfd, conf)) goto end; } while(!backup_end) { if(!wbuf->len) { get_wbuf_from_data(conf, wbuf, slist, blist, blk_requests_end); if(!wbuf->len) { get_wbuf_from_blks(wbuf, slist, requests_end, &sigs_end); } } if(wbuf->len) asfd->append_all_to_write_buffer(asfd, wbuf); if(asfd->as->read_write(asfd->as)) { logp("error in %s\n", __func__); goto end; } if(rbuf->buf && deal_with_read(rbuf, slist, blist, conf, &backup_end, &requests_end, &blk_requests_end)) goto end; if(slist->head // Need to limit how many blocks are allocated at once. && (!blist->head || blist->tail->index - blist->head->index<BLKS_MAX_IN_MEM) ) { if(add_to_blks_list(asfd, conf, slist, blist, win)) goto end; } if(blk_requests_end) { // If got to the end of the file request list // and the last block of the last file, and // the write buffer is empty, we got to the end. if(slist->head==slist->tail) { if(!slist->tail || blist->last_sent==slist->tail->burp2->bend) { if(!wbuf->len) break; } } } } if(asfd->write_str(asfd, CMD_GEN, "backup_end")) goto end; ret=0; end: blk_print_alloc_stats(); //sbuf_print_alloc_stats(); win_free(win); slist_free(&slist); blist_free(&blist); // Write buffer did not allocate 'buf'. wbuf->buf=NULL; iobuf_free(&wbuf); cntr_print_end(conf->cntr); cntr_print(conf->cntr, ACTION_BACKUP); if(ret) logp("Error in backup\n"); logp("End backup\n"); return ret; }
int backup_phase2_server(struct async *as, struct sdirs *sdirs, const char *manifest_dir, int resume, struct conf *conf) { int ret=-1; int sigs_end=0; int backup_end=0; int requests_end=0; int blk_requests_end=0; struct slist *slist=NULL; struct blist *blist=NULL; struct iobuf *wbuf=NULL; struct dpth *dpth=NULL; struct manio *cmanio=NULL; // current manifest struct manio *p1manio=NULL; // phase1 scan manifest struct manio *chmanio=NULL; // changed manifest struct manio *unmanio=NULL; // unchanged manifest // This is used to tell the client that a number of consecutive blocks // have been found and can be freed. uint64_t wrap_up=0; // Main fd is first in the list. struct asfd *asfd=as->asfd; // Champ chooser fd is second in the list. struct asfd *chfd=asfd->next; logp("Phase 2 begin (recv backup data)\n"); //if(champ_chooser_init(sdirs->data, conf) if(!(cmanio=manio_alloc()) || !(p1manio=manio_alloc()) || !(chmanio=manio_alloc()) || !(unmanio=manio_alloc()) || manio_init_read(cmanio, sdirs->cmanifest) || manio_init_read(p1manio, sdirs->phase1data) || manio_init_write(chmanio, sdirs->changed) || manio_init_write(unmanio, sdirs->unchanged) || !(slist=slist_alloc()) || !(blist=blist_alloc()) || !(wbuf=iobuf_alloc()) || !(dpth=dpth_alloc(sdirs->data)) || dpth_init(dpth)) goto end; // The phase1 manifest looks the same as a burp1 one. manio_set_protocol(p1manio, PROTO_BURP1); while(!backup_end) { if(maybe_add_from_scan(asfd, p1manio, cmanio, unmanio, slist, conf)) goto end; if(!wbuf->len) { if(get_wbuf_from_sigs(wbuf, slist, blist, sigs_end, &blk_requests_end, dpth, conf)) goto end; if(!wbuf->len) { get_wbuf_from_files(wbuf, slist, p1manio, &requests_end); } } if(wbuf->len) asfd->append_all_to_write_buffer(asfd, wbuf); append_for_champ_chooser(chfd, blist, sigs_end); if(as->read_write(as)) { logp("error in %s\n", __func__); goto end; } while(asfd->rbuf->buf) { if(deal_with_read(asfd->rbuf, slist, blist, conf, &sigs_end, &backup_end, dpth)) goto end; // Get as much out of the // readbuf as possible. if(asfd->parse_readbuf(asfd)) goto end; } while(chfd->rbuf->buf) { if(deal_with_read_from_chfd(asfd, chfd, blist, &wrap_up, dpth)) goto end; // Get as much out of the // readbuf as possible. if(chfd->parse_readbuf(chfd)) goto end; } if(write_to_changed_file(asfd, chfd, chmanio, slist, blist, dpth, backup_end, conf)) goto end; } // Hack: If there are some entries left after the last entry that // contains block data, it will not be written to the changed file // yet because the last entry of block data has not had // sb->burp2->bend set. if(slist->head && slist->head->next) { slist->head=slist->head->next; if(write_to_changed_file(asfd, chfd, chmanio, slist, blist, dpth, backup_end, conf)) goto end; } if(manio_close(unmanio) || manio_close(chmanio)) goto end; if(blist->head) { logp("ERROR: finishing but still want block: %lu\n", blist->head->index); goto end; } // Need to release the last left. There should be one at most. if(dpth->head && dpth->head->next) { logp("ERROR: More data locks remaining after: %s\n", dpth->head->save_path); goto end; } if(dpth_release_all(dpth)) goto end; ret=0; end: logp("End backup\n"); slist_free(slist); blist_free(blist); iobuf_free_content(asfd->rbuf); iobuf_free_content(chfd->rbuf); // Write buffer did not allocate 'buf'. if(wbuf) wbuf->buf=NULL; iobuf_free(wbuf); dpth_release_all(dpth); dpth_free(&dpth); manio_free(&cmanio); manio_free(&p1manio); manio_free(&chmanio); manio_free(&unmanio); return ret; }
// Return p1manio position. static man_off_t *do_resume_work(struct sdirs *sdirs, struct dpth *dpth, struct conf **cconfs) { man_off_t *pos=NULL; man_off_t *p1pos=NULL; struct iobuf *chb=NULL; struct manio *cmanio=NULL; struct manio *umanio=NULL; struct manio *p1manio=NULL; enum protocol protocol=get_protocol(cconfs); struct cntr *cntr=get_cntr(cconfs); int compression=get_int(cconfs[OPT_COMPRESSION]); if(!(p1manio=manio_open_phase1(sdirs->phase1data, "rb", protocol)) || !(cmanio=manio_open_phase2(sdirs->changed, "rb", protocol)) || !(umanio=manio_open_phase2(sdirs->unchanged, "rb", protocol))) goto end; if(!(chb=iobuf_alloc())) return NULL; logp("Setting up resume positions...\n"); if(get_last_good_entry(cmanio, chb, cntr, dpth, protocol, &pos)) goto error; if(manio_close_and_truncate(&cmanio, pos, compression)) goto error; man_off_t_free(&pos); if(chb->buf) { logp(" last good entry: %s\n", chb->buf); // Now need to go to the appropriate places in p1manio and // unchanged. if(forward_past_entry(p1manio, chb, protocol, &p1pos)) goto error; // The unchanged file needs to be positioned just before the // found entry, otherwise it ends up having a duplicated entry. if(forward_before_entry(umanio, chb, cntr, dpth, protocol, &pos)) goto error; if(manio_close_and_truncate(&umanio, pos, compression)) goto error; man_off_t_free(&pos); } else { logp(" nothing previously transferred\n"); if(!(p1pos=manio_tell(p1manio))) goto error; if(!(pos=manio_tell(umanio))) goto error; if(manio_close_and_truncate(&umanio, pos, compression)) goto error; } // Now should have all file pointers in the right places to resume. goto end; error: man_off_t_free(&p1pos); end: iobuf_free(&chb); man_off_t_free(&pos); manio_close(&p1manio); manio_close(&cmanio); manio_close(&umanio); return p1pos; }
int backup_phase2_client_protocol2(struct asfd *asfd, struct conf **confs, int resume) { int ret=-1; uint8_t end_flags=0; struct slist *slist=NULL; struct iobuf *rbuf=NULL; struct iobuf *wbuf=NULL; struct cntr *cntr=NULL; if(confs) cntr=get_cntr(confs); if(!asfd || !asfd->as) { logp("%s() called without async structs!\n", __func__); goto end; } logp("Phase 2 begin (send backup data)\n"); logfmt("\n"); if(!(slist=slist_alloc()) || !(wbuf=iobuf_alloc()) || blks_generate_init()) goto end; rbuf=asfd->rbuf; if(!resume) { // Only do this bit if the server did not tell us to resume. if(asfd->write_str(asfd, CMD_GEN, "backupphase2") || asfd_read_expect(asfd, CMD_GEN, "ok")) goto end; } else { // On resume, the server might update the client with cntr. if(cntr_recv(asfd, confs)) goto end; } while(!(end_flags&END_BACKUP)) { if(!wbuf->len) { get_wbuf_from_data(confs, wbuf, slist, end_flags); if(!wbuf->len) { if(get_wbuf_from_blks(wbuf, slist, &end_flags)) goto end; } } if(wbuf->len) { if(asfd->append_all_to_write_buffer(asfd, wbuf) ==APPEND_ERROR) goto end; } if(asfd->as->read_write(asfd->as)) { logp("error in %s\n", __func__); goto end; } if(rbuf->buf && deal_with_read(rbuf, slist, cntr, &end_flags)) goto end; if(slist->head // Need to limit how many blocks are allocated at once. && (!slist->blist->head || slist->blist->tail->index - slist->blist->head->index<BLKS_MAX_IN_MEM) ) { if(add_to_blks_list(asfd, confs, slist)) goto end; } if(end_flags&END_BLK_REQUESTS) { // If got to the end of the file request list // and the last block of the last file, and // the write buffer is empty, we got to the end. if(slist->head==slist->tail) { if(!slist->tail || slist->blist->last_sent== slist->tail->protocol2->bend) { if(!wbuf->len) break; } } } } if(asfd->write_str(asfd, CMD_GEN, "backup_end")) goto end; ret=0; end: slist_free(&slist); blks_generate_free(); if(wbuf) { // Write buffer did not allocate 'buf'. wbuf->buf=NULL; iobuf_free(&wbuf); } cntr_print_end(cntr); cntr_print(cntr, ACTION_BACKUP, asfd); if(ret) logp("Error in backup\n"); logp("End backup\n"); 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 || dir == NULL) 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; } 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 autoupgrade_client(struct async *as, struct conf *conf) { int a=0; int ret=-1; char *cp=NULL; char *copy=NULL; char *script_path=NULL; char script_name[32]=""; char package_name[32]=""; char write_str[256]=""; const char *args[2]; struct iobuf *rbuf=NULL; struct asfd *asfd; asfd=as->asfd; if(!conf->autoupgrade_dir) { logp("autoupgrade_dir not set!\n"); goto end; } if(!conf->autoupgrade_os) { logp("autoupgrade_os not set!\n"); goto end; } if(!(copy=strdup(conf->autoupgrade_dir))) { log_out_of_memory(__func__); goto end; } strip_trailing_slashes(©); if((cp=strchr(copy, '/'))) *cp='\0'; if(mkpath(&(conf->autoupgrade_dir), copy)) goto end; // Let the server know we are ready. snprintf(write_str, sizeof(write_str), "autoupgrade:%s", conf->autoupgrade_os); if(asfd->write_str(asfd, CMD_GEN, write_str)) goto end; if(!(a=asfd->simple_loop(asfd, conf, NULL, __func__, autoupgrade_func))) { ret=0; // No autoupgrade. goto end; } else if(a<0) // Error. #ifdef HAVE_WIN32 win32_enable_backup_privileges(); snprintf(script_name, sizeof(script_name), "script.bat"); snprintf(package_name, sizeof(package_name), "package.exe"); #else snprintf(script_name, sizeof(script_name), "script"); snprintf(package_name, sizeof(package_name), "package"); #endif if(receive_file(asfd, conf->autoupgrade_dir, script_name, conf)) { logp("Problem receiving %s/%s\n", conf->autoupgrade_dir, script_name); goto end; } if(receive_file(asfd, conf->autoupgrade_dir, package_name, conf)) { logp("Problem receiving %s/%s\n", conf->autoupgrade_dir, package_name); goto end; } if(!(script_path=prepend_s(conf->autoupgrade_dir, script_name))) goto end; chmod(script_path, 0755); /* Run the script here. */ a=0; args[a++]=script_path; args[a++]=NULL; ret=run_script(asfd, args, NULL, conf, 0 /* do not wait */, 1 /* use logp */, 1 /* use logw */); /* To get round Windows problems to do with installing over files that the current process is running from, I am forking the child, then immediately exiting the parent process. */ printf("\n"); logp("The server tried to upgrade your client.\n"); logp("You will need to try your command again.\n"); asfd_free(&as->asfd); exit(0); end: if(copy) free(copy); if(script_path) free(script_path); iobuf_free(rbuf); return ret; }