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