X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=lib%2Fbuck2obj.c;h=d75b48ab19e212b2d65e8996981db3b6dda85325;hb=c673da72822d7704572716de80402829921efdc3;hp=b19963f7803284acdbaed5c5f53ef9d8d7db9bfa;hpb=271d2a02e7b798fd9781018c060d49e47f277cba;p=libucw.git diff --git a/lib/buck2obj.c b/lib/buck2obj.c index b19963f7..d75b48ab 100644 --- a/lib/buck2obj.c +++ b/lib/buck2obj.c @@ -1,5 +1,5 @@ /* - * Bucket -> Object Converter + * Generating Objects from Buckets * * (c) 2004, Robert Spalek * (c) 2004, Martin Mares @@ -7,13 +7,14 @@ #include "lib/lib.h" #include "lib/unaligned.h" -#include "lib/pools.h" +#include "lib/mempool.h" #include "lib/fastbuf.h" -#include "charset/unicode.h" +#include "lib/unicode.h" #include "lib/object.h" #include "lib/bucket.h" #include "lib/lizard.h" -#include "lib/buck2obj.h" +#include "lib/bbuf.h" +#include "lib/ff-utf8.h" #include #include @@ -21,10 +22,6 @@ #define RET_ERR(num) ({ errno = num; return -1; }) -#define GBUF_TYPE byte -#define GBUF_PREFIX(x) bb_##x -#include "lib/gbuf.h" - struct buck2obj_buf { bb_t bb; @@ -87,26 +84,57 @@ decode_attributes(byte *ptr, byte *end, struct odes *o, uns can_overwrite) int buck2obj_parse(struct buck2obj_buf *buf, uns buck_type, uns buck_len, struct fastbuf *body, struct odes *o_hdr, uns *body_start, struct odes *o_body) { - if (buck_type == BUCKET_TYPE_PLAIN) + if (buck_type <= BUCKET_TYPE_PLAIN) { - if (body_start) + if (body_start) // there is no header part *body_start = 0; - obj_read_multi(body, o_hdr); // ignore empty lines, read until EOF or NUL + // ignore empty lines and read until the end of the bucket + sh_off_t end = btell(body) + buck_len; + byte buf[MAX_ATTR_SIZE]; + while (btell(body) < end && bgets(body, buf, sizeof(buf))) + if (buf[0]) + obj_add_attr(o_hdr, buf[0], buf+1); + ASSERT(btell(body) == end); } else if (buck_type == BUCKET_TYPE_V30) { sh_off_t start = btell(body); - obj_read(body, o_hdr); // end on EOF or the first empty line + sh_off_t end = start + buck_len; + byte buf[MAX_ATTR_SIZE]; + while (btell(body) < end && bgets(body, buf, sizeof(buf)) && buf[0]) + obj_add_attr(o_hdr, buf[0], buf+1); if (body_start) *body_start = btell(body) - start; else { - obj_read(body, o_body); - bgetc(body); + while (btell(body) < end && bgets(body, buf, sizeof(buf))) + if (buf[0]) + obj_add_attr(o_body, buf[0], buf+1); + ASSERT(btell(body) == end); } } else if (buck_type == BUCKET_TYPE_V33 || buck_type == BUCKET_TYPE_V33_LIZARD) { + /* Avoid reading the whole bucket if only its header is needed. */ + if (body_start) + { + sh_off_t start = btell(body); + sh_off_t end = start + buck_len; + while (btell(body) < end) + { + uns len = bget_utf8(body); + if (!len) + break; + byte *buf = mp_alloc_fast_noalign(o_hdr->pool, len); + bread(body, buf, len); + uns type = buf[--len]; + buf[len] = 0; + obj_add_attr_ref(o_hdr, type, buf); + } + *body_start = btell(body) - start; + return 0; + } + /* Read all the bucket into 1 buffer, 0-copy if possible. */ byte *ptr, *end; uns len = bdirect_read_prepare(body, &ptr); @@ -121,26 +149,22 @@ buck2obj_parse(struct buck2obj_buf *buf, uns buck_type, uns buck_len, struct fas ptr = buf->bb.ptr; copied = 1; } - end = ptr + len; + end = ptr + buck_len; - byte *start = ptr; ptr = decode_attributes(ptr, end, o_hdr, 0); // header - if (body_start) - { - *body_start = ptr - start; - if (!copied) - bdirect_read_commit(body, ptr); - return 0; - } if (buck_type == BUCKET_TYPE_V33_LIZARD) // decompression { - if (ptr + 4 > end) + if (ptr + 8 > end) RET_ERR(EINVAL); len = GET_U32(ptr); ptr += 4; + uns adler = GET_U32(ptr); + ptr += 4; byte *new_ptr = lizard_decompress_safe(ptr, buf->lizard, len); if (!new_ptr) return -1; + if (adler32(new_ptr, len) != adler) + RET_ERR(EINVAL); if (!copied) bdirect_read_commit(body, end); ptr = new_ptr; @@ -154,7 +178,10 @@ buck2obj_parse(struct buck2obj_buf *buf, uns buck_type, uns buck_len, struct fas bdirect_read_commit_modified(body, ptr); } else - RET_ERR(EINVAL); + { + bskip(body, buck_len); + RET_ERR(EINVAL); + } return 0; } @@ -167,3 +194,17 @@ obj_read_bucket(struct buck2obj_buf *buf, struct mempool *pool, uns buck_type, u else return o; } + +int +obj_read(struct fastbuf *f, struct odes *o) +{ + byte buf[MAX_ATTR_SIZE]; + + while (bgets(f, buf, sizeof(buf))) + { + if (!buf[0]) + return 1; + obj_add_attr(o, buf[0], buf+1); + } + return 0; +}