make it act properly on iobuf errors.master
@@ -27,21 +27,19 @@ write_buffer(struct cli *cli, struct io_buffer *iob) | |||
{ | |||
int err = 0; | |||
if (!iob->error) { | |||
uint32_t len = iob->buf_off; | |||
uint32_t len = iob->off; | |||
write_fully(cli->sd, &len, sizeof(len)); | |||
err = write_fully(cli->sd, iob->buf, iob->buf_off); | |||
err = write_fully(cli->sd, iob->buf, iob->off); | |||
} else | |||
btpd_err("Out of memory.\n"); | |||
if (iob->buf != NULL) | |||
free(iob->buf); | |||
buf_free(iob); | |||
return err; | |||
} | |||
static int | |||
write_code_buffer(struct cli *cli, enum ipc_err code) | |||
{ | |||
struct io_buffer iob; | |||
buf_init(&iob, 16); | |||
struct io_buffer iob = buf_init(16); | |||
buf_print(&iob, "d4:codei%uee", code); | |||
return write_buffer(cli, &iob); | |||
} | |||
@@ -49,8 +47,7 @@ write_code_buffer(struct cli *cli, enum ipc_err code) | |||
static int | |||
write_add_buffer(struct cli *cli, unsigned num) | |||
{ | |||
struct io_buffer iob; | |||
buf_init(&iob, 32); | |||
struct io_buffer iob = buf_init(32); | |||
buf_print(&iob, "d4:codei%ue3:numi%uee", IPC_OK, num); | |||
return write_buffer(cli, &iob); | |||
} | |||
@@ -200,7 +197,7 @@ cmd_tget(struct cli *cli, int argc, const char *args) | |||
for (int i = 0; i < nkeys; i++) | |||
opts[i] = benc_int(p, &p); | |||
buf_init(&iob, (1 << 15)); | |||
iob = buf_init(1 << 15); | |||
buf_swrite(&iob, "d4:codei0e6:resultl"); | |||
p = benc_dget_any(args, "from"); | |||
if (benc_isint(p)) { | |||
@@ -225,7 +222,7 @@ cmd_tget(struct cli *cli, int argc, const char *args) | |||
else if (benc_isstr(p) && benc_strlen(p) == 20) | |||
tl = tlib_by_hash(benc_mem(p, NULL, NULL)); | |||
else { | |||
free(iob.buf); | |||
buf_free(&iob); | |||
free(opts); | |||
return IPC_COMMERR; | |||
} | |||
@@ -70,7 +70,7 @@ cmd_add(int argc, char **argv) | |||
if ((mi = mi_load(argv[0], &mi_size)) == NULL) | |||
err(1, "error loading '%s'", argv[0]); | |||
buf_init(&iob, PATH_MAX); | |||
iob = buf_init(PATH_MAX); | |||
buf_write(&iob, dir, dirlen); | |||
if (topdir) { | |||
size_t tdlen; | |||
@@ -115,7 +115,6 @@ static enum ipc_err | |||
ipc_req_res(struct ipc *ipc, const char *req, uint32_t qlen, char **res, | |||
uint32_t *rlen) | |||
{ | |||
assert(benc_validate(req, qlen) == 0); | |||
if (write_fully(ipc->sd, &qlen, sizeof(qlen)) != 0) | |||
return IPC_COMMERR; | |||
if (write_fully(ipc->sd, req, qlen) != 0) | |||
@@ -133,8 +132,12 @@ static enum ipc_err | |||
ipc_buf_req_res(struct ipc *ipc, struct io_buffer *iob, char **res, | |||
uint32_t *rlen) | |||
{ | |||
enum ipc_err err = ipc_req_res(ipc, iob->buf, iob->buf_off, res, rlen); | |||
free(iob->buf); | |||
enum ipc_err err; | |||
if (iob->error) | |||
err = IPC_COMMERR; | |||
else | |||
err = ipc_req_res(ipc, iob->buf, iob->off, res, rlen); | |||
buf_free(iob); | |||
return err; | |||
} | |||
@@ -155,8 +158,7 @@ ipc_buf_req_code(struct ipc *ipc, struct io_buffer *iob) | |||
enum ipc_err | |||
btpd_die(struct ipc *ipc, int seconds) | |||
{ | |||
struct io_buffer iob; | |||
buf_init(&iob, 16); | |||
struct io_buffer iob = buf_init(16); | |||
if (seconds >= 0) | |||
buf_print(&iob, "l3:diei%dee", seconds); | |||
else | |||
@@ -222,7 +224,7 @@ btpd_tget(struct ipc *ipc, struct ipc_torrent *tps, size_t ntps, | |||
if (nkeys == 0 || ntps == 0) | |||
return IPC_COMMERR; | |||
buf_init(&iob, 1 << 14); | |||
iob = buf_init(1 << 14); | |||
buf_swrite(&iob, "l4:tgetd4:froml"); | |||
for (int i = 0; i < ntps; i++) { | |||
if (tps[i].by_hash) { | |||
@@ -253,7 +255,7 @@ btpd_tget_wc(struct ipc *ipc, enum ipc_twc twc, enum ipc_tval *keys, | |||
if (nkeys == 0) | |||
return IPC_COMMERR; | |||
buf_init(&iob, 1 << 14); | |||
iob = buf_init(1 << 14); | |||
buf_print(&iob, "l4:tgetd4:fromi%de4:keysl", twc); | |||
for (int i = 0; i < nkeys; i++) | |||
buf_print(&iob, "i%de", keys[i]); | |||
@@ -268,8 +270,7 @@ enum ipc_err | |||
btpd_add(struct ipc *ipc, const char *mi, size_t mi_size, const char *content, | |||
const char *name) | |||
{ | |||
struct io_buffer iob; | |||
buf_init(&iob, (1 << 10)); | |||
struct io_buffer iob = buf_init(1 << 10); | |||
buf_print(&iob, "l3:addd7:content%d:%s", (int)strlen(content), | |||
content); | |||
if (name != NULL) | |||
@@ -283,8 +284,7 @@ btpd_add(struct ipc *ipc, const char *mi, size_t mi_size, const char *content, | |||
static enum ipc_err | |||
simple_treq(struct ipc *ipc, char *cmd, struct ipc_torrent *tp) | |||
{ | |||
struct io_buffer iob; | |||
buf_init(&iob, 32); | |||
struct io_buffer iob = buf_init(32); | |||
if (tp->by_hash) { | |||
buf_print(&iob, "l%d:%s20:", (int)strlen(cmd), cmd); | |||
buf_write(&iob, tp->u.hash, 20); | |||
@@ -1,4 +1,3 @@ | |||
#include <errno.h> | |||
#include <inttypes.h> | |||
#include <stdarg.h> | |||
#include <stdio.h> | |||
@@ -9,18 +8,21 @@ | |||
#define GROWLEN (1 << 14) | |||
int | |||
buf_init(struct io_buffer *iob, size_t size) | |||
struct io_buffer | |||
buf_init(size_t size) | |||
{ | |||
iob->buf_off = 0; | |||
iob->buf_len = size; | |||
iob->error = 0; | |||
iob->buf = malloc(size); | |||
if (iob->buf == NULL) { | |||
iob->error = ENOMEM; | |||
return ENOMEM; | |||
} else | |||
return 0; | |||
struct io_buffer iob; | |||
iob.off = 0; | |||
iob.len = size; | |||
iob.error = (iob.buf = malloc(size)) == NULL ? 1 : 0; | |||
return iob; | |||
} | |||
void | |||
buf_free(struct io_buffer *iob) | |||
{ | |||
if (iob->buf != NULL) | |||
free(iob->buf); | |||
} | |||
int | |||
@@ -28,14 +30,14 @@ buf_grow(struct io_buffer *iob, size_t addlen) | |||
{ | |||
if (iob->error) | |||
return iob->error; | |||
char *nbuf = realloc(iob->buf, iob->buf_len + addlen); | |||
char *nbuf = realloc(iob->buf, iob->len + addlen); | |||
if (nbuf == NULL) { | |||
iob->error = ENOMEM; | |||
return ENOMEM; | |||
iob->error = 1; | |||
return 0; | |||
} else { | |||
iob->buf = nbuf; | |||
iob->buf_len += addlen; | |||
return 0; | |||
iob->len += addlen; | |||
return 1; | |||
} | |||
} | |||
@@ -43,31 +45,31 @@ int | |||
buf_print(struct io_buffer *iob, const char *fmt, ...) | |||
{ | |||
if (iob->error) | |||
return iob->error; | |||
return 0; | |||
int np; | |||
va_list ap; | |||
va_start(ap, fmt); | |||
np = vsnprintf(NULL, 0, fmt, ap); | |||
va_end(ap); | |||
if (np + 1 > iob->buf_len - iob->buf_off) | |||
if (buf_grow(iob, (1 + (np + 1) / GROWLEN) * GROWLEN) != 0) | |||
return ENOMEM; | |||
if (np + 1 > iob->len - iob->off) | |||
if (!buf_grow(iob, (1 + (np + 1) / GROWLEN) * GROWLEN)) | |||
return 0; | |||
va_start(ap, fmt); | |||
vsnprintf(iob->buf + iob->buf_off, np + 1, fmt, ap); | |||
vsnprintf(iob->buf + iob->off, np + 1, fmt, ap); | |||
va_end(ap); | |||
iob->buf_off += np; | |||
return 0; | |||
iob->off += np; | |||
return 1; | |||
} | |||
int | |||
buf_write(struct io_buffer *iob, const void *buf, size_t len) | |||
{ | |||
if (iob->error) | |||
return iob->error; | |||
if (len > iob->buf_len - iob->buf_off) | |||
if (buf_grow(iob, (1 + len / GROWLEN) * GROWLEN) != 0) | |||
return ENOMEM; | |||
bcopy(buf, iob->buf + iob->buf_off, len); | |||
iob->buf_off += len; | |||
return 0; | |||
return 0; | |||
if (len > iob->len - iob->off) | |||
if (!buf_grow(iob, (1 + len / GROWLEN) * GROWLEN)) | |||
return 0; | |||
bcopy(buf, iob->buf + iob->off, len); | |||
iob->off += len; | |||
return 1; | |||
} |
@@ -2,13 +2,14 @@ | |||
#define BTPD_IOBUF_H | |||
struct io_buffer { | |||
size_t buf_off; | |||
size_t buf_len; | |||
size_t off; | |||
size_t len; | |||
char *buf; | |||
int error; | |||
}; | |||
int buf_init(struct io_buffer *iob, size_t size); | |||
struct io_buffer buf_init(size_t size); | |||
void buf_free(struct io_buffer *iob); | |||
int buf_grow(struct io_buffer *iob, size_t size); | |||
int buf_write(struct io_buffer *iob, const void *data, size_t size); | |||
__attribute__((format (printf, 2, 3))) | |||