]> mj.ucw.cz Git - libucw.git/blob - lib/buck2obj.c
df980a0b448424cb266e4f233a949503ea562125
[libucw.git] / lib / buck2obj.c
1 /*
2  *      Bucket -> Object converter
3  *
4  *      (c) 2004, Robert Spalek <robert@ucw.cz>
5  */
6
7 #include "lib/lib.h"
8 #include "lib/fastbuf.h"
9 #include "charset/unicode.h"
10 #include "lib/object.h"
11 #include "lib/bucket.h"
12 #include "lib/lizard.h"
13 #include "lib/buck2obj.h"
14
15 #include <errno.h>
16
17 static inline byte *
18 decode_attributes(byte *start, byte *end, struct odes *o)
19 {
20   byte *p = start;
21   while (p < end)
22   {
23     uns len;
24     GET_UTF8(p, len);
25     if (!len)
26       break;
27     byte type = p[len];
28     p[len] = 0;
29     obj_add_attr(o, type, p);
30   }
31   return p;
32 }
33
34 int
35 extract_odes(struct obuck_header *hdr, struct fastbuf *body, struct odes *o, byte *buf, uns buf_len, struct lizard_buffer *lizard_buf)
36 {
37   if (hdr->type < BUCKET_TYPE_V30C)
38   {
39     oa_allocate = 1;
40     obj_read_multi(body, o);
41   }
42   else
43   {
44     oa_allocate = 0;
45     /* Read all the bucket into 1 buffer, 0-copy if possible.  */
46     byte *start, *end;
47     uns len = bdirect_read_prepare(body, &start);
48     if (len < hdr->length)
49     {
50       if (hdr->length > buf_len)
51       {
52         errno = EFBIG;
53         return -1;
54       }
55       len = bread(body, buf, hdr->length);
56       start = buf;
57     }
58     end = start + len;
59
60     /* Decode the header, 0-copy.  */
61     byte *p = decode_attributes(start, end, o);
62
63     /* Decompress the body.  */
64     if (hdr->type == BUCKET_TYPE_V30C)
65     {
66       GET_UTF8(p, len);
67       int res = lizard_decompress_safe(p, lizard_buf, len);
68       if (res < 0)
69         return res;
70       if (res != (int) len)
71       {
72         errno = EINVAL;
73         return -1;
74       }
75       start = lizard_buf->ptr;
76       end = start + len;
77     }
78     else
79       start = p;
80
81     /* Decode the body, 0-copy.  */
82     p = decode_attributes(start, end, o);
83     if (p != end)
84     {
85       errno = EINVAL;
86       return -1;
87     }
88   }
89   return 0;
90 }