X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=lib%2Fbuck2obj.c;h=c0ee98c66af9486f34338353dfc4e0fec629b9a9;hb=bc5bc0b52b57d424c64a382aeba9def6eb8de45d;hp=b2eb455ee165537e70bb16fbc28172f726c4f719;hpb=9780ba15ffcc350431943320f4c3eb485a758b40;p=libucw.git diff --git a/lib/buck2obj.c b/lib/buck2obj.c index b2eb455e..c0ee98c6 100644 --- a/lib/buck2obj.c +++ b/lib/buck2obj.c @@ -18,24 +18,25 @@ #include #include -#define MAX_HEADER_SIZE 1024 // extra space for the header not counted in MaxObjSize #define RET_ERR(num) ({ errno = num; return NULL; }) +#define GBUF_TYPE byte +#define GBUF_PREFIX(x) bb_##x +#include "lib/gbuf.h" + struct buck2obj_buf { - byte *raw; - uns raw_len; + bb_t bb; struct lizard_buffer *lizard; struct mempool *mp; }; struct buck2obj_buf * -buck2obj_alloc(uns max_len, struct mempool *mp) +buck2obj_alloc(struct mempool *mp) { struct buck2obj_buf *buf = xmalloc(sizeof(struct buck2obj_buf)); - buf->raw_len = max_len * LIZARD_MAX_MULTIPLY + LIZARD_MAX_ADD + MAX_HEADER_SIZE; - buf->raw = xmalloc(buf->raw_len); - buf->lizard = lizard_alloc(max_len); + bb_init(&buf->bb); + buf->lizard = lizard_alloc(); buf->mp = mp; return buf; } @@ -44,10 +45,16 @@ void buck2obj_free(struct buck2obj_buf *buf) { lizard_free(buf->lizard); - xfree(buf->raw); + bb_done(&buf->bb); xfree(buf); } +void +buck2obj_flush(struct buck2obj_buf *buf) +{ + mp_flush(buf->mp); +} + static inline byte * decode_attributes(byte *ptr, byte *end, struct odes *o, uns can_overwrite) { @@ -100,23 +107,29 @@ decode_attributes(byte *ptr, byte *end, struct odes *o, uns can_overwrite) } struct odes * -buck2obj_convert(struct buck2obj_buf *buf, uns buck_type, struct fastbuf *body) +obj_read_bucket(struct buck2obj_buf *buf, uns buck_type, uns buck_len, struct fastbuf *body, uns *body_start) { - mp_flush(buf->mp); struct odes *o = obj_new(buf->mp); if (buck_type < BUCKET_TYPE_V33) - obj_read_multi(body, o); + { + if (!body_start) // header + body: ignore empty lines, read until EOF + { + obj_read_multi(body, o); + bgetc(body); + } + else // header only: end on EOF or the first empty line + { + sh_off_t start = btell(body); + obj_read(body, o); + *body_start = btell(body) - start; + } + } else { - /* Compute the length of the bucket. We cannot fetch this attribute - * directly due to remote indexing. */ - bseek(body, 0, SEEK_END); - sh_off_t buck_len = btell(body); - bsetpos(body, 0); - /* Read all the bucket into 1 buffer, 0-copy if possible. */ - int can_overwrite = bconfig(body, BCONFIG_CAN_OVERWRITE, 0); + int can_overwrite = bconfig(body, BCONFIG_CAN_OVERWRITE, -1); + /* FIXME: This could be cached in buck2obj_buf */ if (can_overwrite < 0) can_overwrite = 0; uns overwritten; @@ -127,10 +140,9 @@ buck2obj_convert(struct buck2obj_buf *buf, uns buck_type, struct fastbuf *body) { /* Copy if the original buffer is too small. * If it is write-protected, copy it also if it is uncompressed. */ - if (buck_len > buf->raw_len) - RET_ERR(EFBIG); - len = bread(body, buf->raw, buck_len); - ptr = buf->raw; + bb_grow(&buf->bb, buck_len); + len = bread(body, buf->bb.ptr, buck_len); + ptr = buf->bb.ptr; can_overwrite = 2; overwritten = 0; } @@ -138,21 +150,29 @@ buck2obj_convert(struct buck2obj_buf *buf, uns buck_type, struct fastbuf *body) overwritten = can_overwrite > 1; end = ptr + len; + byte *start = ptr; ptr = decode_attributes(ptr, end, o, can_overwrite);// header + if (body_start) + { + *body_start = ptr - start; + return o; + } if (buck_type == BUCKET_TYPE_V33) ; else if (buck_type == BUCKET_TYPE_V33_LIZARD) // decompression { len = GET_U32(ptr); ptr += 4; - int res = lizard_decompress_safe(ptr, buf->lizard, len); + int res; + byte *new_ptr; + res = lizard_decompress_safe(ptr, buf->lizard, len, &new_ptr); if (res != (int) len) { if (res >= 0) errno = EINVAL; return NULL; } - ptr = buf->lizard->ptr; + ptr = new_ptr; end = ptr + len; can_overwrite = 2; }