diff options
Diffstat (limited to 'misc')
| -rw-r--r-- | misc/benc.c | 323 | ||||
| -rw-r--r-- | misc/benc.h | 50 | ||||
| -rw-r--r-- | misc/metainfo.c | 64 |
3 files changed, 253 insertions, 184 deletions
diff --git a/misc/benc.c b/misc/benc.c index 68f7f95..6a57e2e 100644 --- a/misc/benc.c +++ b/misc/benc.c @@ -2,6 +2,7 @@ #include <ctype.h> #include <errno.h> #include <inttypes.h> +#include <stdarg.h> #include <stdlib.h> #include <string.h> @@ -99,7 +100,7 @@ benc_length(const char *p) ; return next - p + 1; default: - assert(benc_str(p, &next, &blen, NULL) == 0); + assert((next = benc_mem(p, &blen, NULL)) != NULL); return next - p + blen; } } @@ -127,11 +128,12 @@ benc_next(const char *p) return *(p + blen) == 'e' ? NULL : p + blen; } -int -benc_str(const char *p, const char **out, size_t *len, const char**next) +const char * +benc_mem(const char *p, size_t *len, const char**next) { + if (!benc_isstr(p)) + return NULL; size_t blen = 0; - assert(isdigit(*p)); blen = *p - '0'; p++; while (isdigit(*p)) { @@ -141,53 +143,49 @@ benc_str(const char *p, const char **out, size_t *len, const char**next) } assert(*p == ':'); benc_safeset(len, blen); - benc_safeset(out, p + 1); benc_safeset(next, *(p + blen + 1) == 'e' ? NULL : p + blen + 1); - return 0; + return p + 1; } -int -benc_strz(const char *p, char **out, size_t *len, const char **next) +char * +benc_str(const char *p, size_t *len, const char **next) { - int err; size_t blen; const char *bstr; - - if ((err = benc_str(p, &bstr, &blen, next)) == 0) { - if ((*out = malloc(blen + 1)) != NULL) { - memcpy(*out, bstr, blen); - (*out)[blen] = '\0'; - benc_safeset(len, blen); - } else - err = ENOMEM; - } - return err; + char *ret; + if ((bstr = benc_mem(p, &blen, next)) == NULL) + return NULL; + if ((ret = malloc(blen + 1)) == NULL) + return NULL; + bcopy(bstr, ret, blen); + ret[blen] = '\0'; + benc_safeset(len, blen); + return ret; } -int -benc_stra(const char *p, char **out, size_t *len, const char **next) +char * +benc_mema(const char *p, size_t *len, const char **next) { - int err; size_t blen; const char *bstr; - - if ((err = benc_str(p, &bstr, &blen, next)) == 0) { - if ((*out = malloc(blen)) != NULL) { - memcpy(*out, bstr, blen); - benc_safeset(len, blen); - } else - err = ENOMEM; - } - return err; + char *ret; + if ((bstr = benc_mem(p, &blen, next)) == NULL) + return NULL; + if ((ret = malloc(blen)) == NULL) + return NULL; + bcopy(bstr, ret, blen); + benc_safeset(len, blen); + return ret; } -int -benc_int64(const char *p, int64_t *out, const char **next) +long long +benc_int(const char *p, const char **next) { int sign = 1; - int64_t res = 0; + long long res = 0; - assert(*p == 'i'); + if (!benc_isint(p)) + return 0; p++; if (*p == '-') { sign = -1; @@ -202,122 +200,79 @@ benc_int64(const char *p, int64_t *out, const char **next) p++; } assert(*p == 'e'); - benc_safeset(out, res); - benc_safeset(next, *(p + 1) == 'e' ? NULL : p + 1); - - return 0; -} - -int -benc_uint32(const char *p, uint32_t *out, const char **next) -{ - int err; - int64_t res; - if ((err = benc_int64(p, &res, next)) == 0) { - if (res >= 0 && res <= 0xffffffffUL) - *out = (uint32_t)res; - else - err = EINVAL; - } - return err; + benc_safeset(next, *(p + 1) == 'e' ? NULL : p + 1); + return res; } -int -benc_dget_any(const char *p, const char *key, const char **val) +const char * +benc_dget_any(const char *p, const char *key) { - int res; + int cmp; size_t len, blen; const char *bstr; - assert(benc_isdct(p)); + if (!benc_isdct(p)) + return NULL; len = strlen(key); p = benc_first(p); while (p != NULL) { - if ((res = benc_str(p, &bstr, &blen, &p)) != 0) - return res; - - res = strncmp(bstr, key, blen); - if (res == 0 && len == blen) { - *val = p; - return 0; - } else if (res <= 0) { + if (!benc_isstr(p)) + return NULL; + bstr = benc_mem(p, &blen, &p); + + cmp = strncmp(bstr, key, blen); + if (cmp == 0 && len == blen) + return p; + else if (cmp <= 0) p = benc_next(p); - } else - return ENOENT; + else + return NULL; } - return ENOENT; + return NULL; } -int -benc_dget_lst(const char *p, const char *key, const char **val) -{ - int err; - if ((err = benc_dget_any(p, key, val)) == 0) - if (!benc_islst(*val)) - err = EINVAL; - return err; -} - -int -benc_dget_dct(const char *p, const char *key, const char **val) +const char * +benc_dget_lst(const char *p, const char *key) { - int err; - if ((err = benc_dget_any(p, key, val)) == 0) - if (!benc_isdct(*val)) - err = EINVAL; - return err; + const char *ret = benc_dget_any(p, key); + return ret != NULL && benc_islst(ret) ? ret : NULL; } -int -benc_dget_str(const char *p, const char *key, const char **val, size_t *len) +const char * +benc_dget_dct(const char *p, const char *key) { - int err; - const char *sp; - if ((err = benc_dget_any(p, key, &sp)) == 0) - err = benc_isstr(sp) ? benc_str(sp, val, len, NULL) : EINVAL; - return err; + const char *ret = benc_dget_any(p, key); + return ret != NULL && benc_isdct(ret) ? ret : NULL; } -int -benc_dget_stra(const char *p, const char *key, char **val, size_t *len) +const char * +benc_dget_mem(const char *p, const char *key, size_t *len) { - int err; - const char *sp; - if ((err = benc_dget_any(p, key, &sp)) == 0) - err = benc_isstr(sp) ? benc_stra(sp, val, len, NULL) : EINVAL; - return err; + const char *str = benc_dget_any(p, key); + return str != NULL && benc_isstr(str) ? benc_mem(str, len, NULL) : NULL; } -int -benc_dget_strz(const char *p, const char *key, char **val, size_t *len) +char * +benc_dget_mema(const char *p, const char *key, size_t *len) { - int err; - const char *sp; - if ((err = benc_dget_any(p, key, &sp)) == 0) - err = benc_isstr(sp) ? benc_strz(sp, val, len, NULL) : EINVAL; - return err; + const char *str = benc_dget_any(p, key); + return str != NULL && benc_isstr(str) ? benc_mema(str, len, NULL) : NULL; } -int -benc_dget_int64(const char *p, const char *key, int64_t *val) +char * +benc_dget_str(const char *p, const char *key, size_t *len) { - int err; - const char *ip; - if ((err = benc_dget_any(p, key, &ip)) == 0) - err = benc_isint(ip) ? benc_int64(ip, val, NULL) : EINVAL; - return err; + const char *str = benc_dget_any(p, key); + return str != NULL && benc_isstr(str) ? benc_str(str, len, NULL) : NULL; } -int -benc_dget_uint32(const char *p, const char *key, uint32_t *val) +long long +benc_dget_int(const char *p, const char *key) { - int err; - const char *ip; - if ((err = benc_dget_any(p, key, &ip)) == 0) - err = benc_isint(ip) ? benc_uint32(ip, val, NULL) : EINVAL; - return err; + const char *intp = benc_dget_any(p, key); + return intp != NULL && benc_isint(intp) ? benc_int(intp, NULL) : 0; } int @@ -343,3 +298,131 @@ benc_isstr(const char *p) { return isdigit(*p); } + +int +benc_istype(const char *p, enum be_type type) +{ + switch (type) { + case BE_ANY: + return benc_isdct(p) || benc_isint(p) || + benc_islst(p) || benc_isstr(p); + case BE_DCT: + return benc_isdct(p); + case BE_INT: + return benc_isint(p); + case BE_LST: + return benc_islst(p); + case BE_STR: + return benc_isstr(p); + default: + abort(); + } +} + +int +benc_dct_chk(const char *p, int count, ...) +{ + int i, ok = 1; + va_list ap; + + if (!benc_isdct(p)) + ok = 0; + + va_start(ap, count); + for (i = 0; ok && i < count; i++) { + enum be_type type = va_arg(ap, enum be_type); + int level = va_arg(ap, int); + const char *dct = p; + const char *key = va_arg(ap, const char *); + while (ok && level > 1) { + if ((dct = benc_dget_dct(dct, key)) != NULL) { + level--; + key = va_arg(ap, const char *); + } else + ok = 0; + } + if (ok) { + const char *val = benc_dget_any(dct, key); + if (val == NULL || !benc_istype(val, type)) + ok = 0; + } + } + va_end(ap); + return ok; +} + +#if 0 +int +benc_dct_type_check(const char *p, int count, ...) +{ + int i; + va_list ap; + + benc_validate_dct(p, 2, BE_INT, "code", BE_STR, "hash", + + if (!benc_isdct(p)) + return EINVAL; + + va_start(ap, count); + for (i = 0; i < count; i++) { + + + } +} + +int +benc_dget_many(const char *p, int count, ...) +{ + int i; + va_list ap; + if (!benc_isdct(p)) + return 0; + va_start(ap, count); + for (i = 0; i < count; i++) { + const char *name = va_arg(ap, const char *); + enum be_type type = va_arg(ap, enum be_type); + int64_t *iret; + size_t *lret; + const char **mret; + char **aret; + + switch (type) { + case BE_INT: + iret = va_arg(ap, int64_t *); + if (benc_dget_int64(p, name, iret) != 0) + goto out; + break; + case BE_LST: + mret = va_arg(ap, const char **); + lret = va_arg(ap, size_t *); + if (benc_dget_lst(p, name, mret) != 0) + goto out; + if (lret != NULL) + *lret = benc_nelems(*mret); + break; + case BE_DCT: + mret = va_arg(ap, const char **); + if (benc_dget_dct(p, name, mret) != 0) + goto out; + break; + case BE_MEM: + mret = va_arg(ap, const char **); + lret = va_arg(ap, size_t *); + if (benc_dget_str(p, name, mret, lret) != 0) + goto out; + break; + case BE_STRZ: + aret = va_arg(ap, char **); + lret = va_arg(ap, size_t *); + if (benc_dget_strz(p, name, aret, lret) != 0) + goto out; + break; + default: + abort(); + } + } +out: + va_end(ap); + return i; +} +#endif diff --git a/misc/benc.h b/misc/benc.h index 8088190..69c5f57 100644 --- a/misc/benc.h +++ b/misc/benc.h @@ -1,7 +1,21 @@ #ifndef BTPD_BENC_H #define BTPD_BENC_H +enum be_type { + BE_ANY, + BE_DCT, + BE_INT, + BE_LST, + BE_STR +}; + int benc_validate(const char *p, size_t len); +int benc_dct_chk(const char *p, int count, ...); + +int benc_islst(const char *p); +int benc_isdct(const char *p); +int benc_isint(const char *p); +int benc_isstr(const char *p); size_t benc_length(const char *p); size_t benc_nelems(const char *p); @@ -9,29 +23,17 @@ size_t benc_nelems(const char *p); const char *benc_first(const char *p); const char *benc_next(const char *p); -int benc_str(const char *p, const char **mem, size_t *len, const char**next); -int benc_stra(const char *p, char **out, size_t *len, const char **next); -int benc_strz(const char *p, char **out, size_t *len, const char **next); -int benc_int64(const char *p, int64_t *out, const char **next); -int benc_uint32(const char *p, uint32_t *out, const char **next); - -#define benc_off benc_int64 - -int benc_dget_any(const char *p, const char *key, const char **val); -int benc_dget_lst(const char *p, const char *key, const char **val); -int benc_dget_dct(const char *p, const char *key, const char **val); -int benc_dget_str(const char *p, const char *key, - const char **val, size_t *len); -int benc_dget_stra(const char *p, const char *key, char **val, size_t *len); -int benc_dget_strz(const char *p, const char *key, char **val, size_t *len); -int benc_dget_int64(const char *p, const char *key, int64_t *val); -int benc_dget_uint32(const char *p, const char *key, uint32_t *val); - -#define benc_dget_off benc_dget_int64 - -int benc_islst(const char *p); -int benc_isdct(const char *p); -int benc_isint(const char *p); -int benc_isstr(const char *p); +long long benc_int(const char *p, const char **next); +const char *benc_mem(const char *p, size_t *len, const char **next); +char *benc_mema(const char *p, size_t *len, const char **next); +char *benc_str(const char *p, size_t *len, const char **next); + +const char *benc_dget_any(const char *p, const char *key); +const char *benc_dget_lst(const char *p, const char *key); +const char *benc_dget_dct(const char *p, const char *key); +long long benc_dget_int(const char *p, const char *key); +const char *benc_dget_mem(const char *p, const char *key, size_t *len); +char *benc_dget_mema(const char *p, const char *key, size_t *len); +char *benc_dget_str(const char *p, const char *key, size_t *len); #endif diff --git a/misc/metainfo.c b/misc/metainfo.c index 1b90247..d8f3a7c 100644 --- a/misc/metainfo.c +++ b/misc/metainfo.c @@ -69,22 +69,22 @@ check_path(const char *path, size_t len) int fill_fileinfo(const char *fdct, struct fileinfo *tfp) { - int err; + //int err; size_t npath, plen, len; const char *plst, *iter, *str; - if ((err = benc_dget_off(fdct, "length", &tfp->length)) != 0) - return err; + if (!benc_dct_chk(fdct, 2, BE_INT, 1, "length", BE_LST, 1, "path")) + return EINVAL; - if ((err = benc_dget_lst(fdct, "path", &plst)) != 0) - return err; + tfp->length = benc_dget_int(fdct, "length"); + plst = benc_dget_lst(fdct, "path"); npath = plen = 0; iter = benc_first(plst); while (iter != NULL) { if (!benc_isstr(iter)) return EINVAL; - benc_str(iter, &str, &len, &iter); + str = benc_mem(iter, &len, &iter); if (!check_path(str, len)) return EINVAL; npath++; @@ -97,13 +97,13 @@ fill_fileinfo(const char *fdct, struct fileinfo *tfp) return ENOMEM; iter = benc_first(plst); - benc_str(iter, &str, &len, &iter); + str = benc_mem(iter, &len, &iter); memcpy(tfp->path, str, len); plen = len; npath--; while (npath > 0) { tfp->path[plen++] = '/'; - benc_str(iter, &str, &len, &iter); + str = benc_mem(iter, &len, &iter); memcpy(tfp->path + plen, str, len); plen += len; npath--; @@ -135,35 +135,25 @@ int fill_metainfo(const char *bep, struct metainfo *tp, int mem_hashes) { size_t len; - int err; + int err = 0; const char *base_addr = bep; const char *hash_addr; - if (!benc_isdct(bep)) + if (!benc_dct_chk(bep, 5, + BE_STR, 1, "announce", + BE_DCT, 1, "info", + BE_INT, 2, "info", "piece length", + BE_STR, 2, "info", "pieces", + BE_STR, 2, "info", "name")) return EINVAL; - if ((err = benc_dget_strz(bep, "announce", &tp->announce, NULL)) != 0) - goto out; - - if ((err = benc_dget_dct(bep, "info", &bep)) != 0) - goto out; - + tp->announce = benc_dget_str(bep, "announce", NULL); + bep = benc_dget_dct(bep, "info"); SHA1(bep, benc_length(bep), tp->info_hash); - - if ((err = benc_dget_off(bep, "piece length", &tp->piece_length)) != 0) - goto out; - - if ((err = benc_dget_str(bep, "pieces", &hash_addr, &len)) != 0) - goto out; - - if (len % 20 != 0) { - err = EINVAL; - goto out; - } + tp->piece_length = benc_dget_int(bep, "piece length"); + hash_addr = benc_dget_mem(bep, "pieces", &len); tp->npieces = len / 20; - tp->pieces_off = hash_addr - base_addr; - if (mem_hashes) { if ((tp->piece_hash = malloc(len)) == NULL) { err = ENOMEM; @@ -171,12 +161,10 @@ fill_metainfo(const char *bep, struct metainfo *tp, int mem_hashes) } bcopy(hash_addr, tp->piece_hash, len); } + tp->name = benc_dget_str(bep, "name", NULL); - if ((err = benc_dget_strz(bep, "name", &tp->name, NULL)) != 0) - goto out; - - err = benc_dget_off(bep, "length", &tp->total_length); - if (err == 0) { + if (benc_dct_chk(bep, 1, BE_INT, 1, "length")) { + tp->total_length = benc_dget_int(bep, "length"); tp->nfiles = 1; tp->files = calloc(1, sizeof(struct fileinfo)); if (tp->files != NULL) { @@ -190,14 +178,11 @@ fill_metainfo(const char *bep, struct metainfo *tp, int mem_hashes) err = ENOMEM; goto out; } - } - else if (err == ENOENT) { + } else if (benc_dct_chk(bep, 1, BE_LST, 1, "files")) { int i; const char *flst, *fdct; - if ((err = benc_dget_lst(bep, "files", &flst)) != 0) - goto out; - + flst = benc_dget_lst(bep, "files"); tp->nfiles = benc_nelems(flst); if (tp->nfiles < 1) { err = EINVAL; @@ -258,7 +243,6 @@ load_metainfo(const char *path, off_t size, int mem_hashes, if (err == 0) if ((*res = calloc(1, sizeof(**res))) == NULL) err = ENOMEM; - if (err == 0) if ((err = fill_metainfo(buf, *res, mem_hashes)) != 0) free(*res); |