- /* 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);
+ sh_off_t start = btell(body);
+ 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
+ {
+ 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_32(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;
+ }