]> mj.ucw.cz Git - libucw.git/commitdiff
implemented all 3 overwrite-policies
authorRobert Spalek <robert@ucw.cz>
Fri, 25 Jun 2004 13:06:00 +0000 (13:06 +0000)
committerRobert Spalek <robert@ucw.cz>
Fri, 25 Jun 2004 13:06:00 +0000 (13:06 +0000)
lib/buck2obj.c

index ef53de2a378417cba63492a2e0f91cbf835651eb..f9375141314cffb8f1d2e2fb1206010988ab7ea7 100644 (file)
@@ -17,7 +17,8 @@
 #include <stdlib.h>
 #include <errno.h>
 
-#define        MAX_HEADER_SIZE 1024            // extra space for the header not countet to MaxObjSize
+#define        MAX_HEADER_SIZE 1024            // extra space for the header not counted in MaxObjSize
+#define        RET_ERR(num)    ({ errno = num; return NULL; })
 
 struct buck2obj_buf
 {
@@ -47,7 +48,7 @@ buck2obj_free(struct buck2obj_buf *buf)
 }
 
 static inline byte *
-decode_attributes(byte *ptr, byte *end, struct odes *o)
+decode_attributes(byte *ptr, byte *end, struct odes *o, uns can_overwrite)
 {
   while (ptr < end)
   {
@@ -56,14 +57,29 @@ decode_attributes(byte *ptr, byte *end, struct odes *o)
     if (!len--)
       break;
     byte type = ptr[len];
-    ptr[len] = 0;
-    obj_add_attr_ref(o, type, ptr);
+    if (can_overwrite == 2)
+    {
+      ptr[len] = 0;
+      obj_add_attr_ref(o, type, ptr);
+    }
+    else if (can_overwrite == 1)
+    {
+      ptr[len] = 0;
+      obj_add_attr(o, type, ptr);
+      ptr[len] = type;
+    }
+    else
+    {
+      byte *dup = mp_alloc(o->pool, len+1);
+      memcpy(dup, ptr, len);
+      dup[len] = 0;
+      obj_add_attr_ref(o, type, ptr);
+    }
     ptr += len + 1;
   }
   return ptr;
 }
 
-#define        RET_ERR(num)    ({ errno = num; return NULL; })
 struct odes *
 buck2obj_convert(struct buck2obj_buf *buf, struct obuck_header *hdr, struct fastbuf *body)
 {
@@ -75,18 +91,27 @@ buck2obj_convert(struct buck2obj_buf *buf, struct obuck_header *hdr, struct fast
   else
   {
     /* Read all the bucket into 1 buffer, 0-copy if possible.  */
+    int can_overwrite = MAX(bconfig(body, BCONFIG_CAN_OVERWRITE, 0), 0);
+    uns overwritten;
     byte *ptr, *end;
-    uns len = bdirect_read_prepare(body, &ptr);                // WARNING: must NOT use mmaped-I/O
-    if (len < hdr->length)
+    uns len = bdirect_read_prepare(body, &ptr);
+    if (len < hdr->length
+    || (can_overwrite < 2 && hdr->type == BUCKET_TYPE_V33))
     {
+      /* Copy if the original buffer is too small.
+       * If it is write-protected, copy it also if it is uncompressed.  */
       if (hdr->length > buf->raw_len)
        RET_ERR(EFBIG);
       len = bread(body, buf->raw, hdr->length);
       ptr = buf->raw;
+      can_overwrite = 2;
+      overwritten = 0;
     }
+    else
+      overwritten = can_overwrite > 1;
     end = ptr + len;
 
-    ptr = decode_attributes(ptr, end, o);              // header
+    ptr = decode_attributes(ptr, end, o, can_overwrite);// header
     if (hdr->type == BUCKET_TYPE_V33)
       ;
     else if (hdr->type == BUCKET_TYPE_V33_LIZARD)      // decompression
@@ -102,13 +127,17 @@ buck2obj_convert(struct buck2obj_buf *buf, struct obuck_header *hdr, struct fast
       }
       ptr = buf->lizard->ptr;
       end = ptr + len;
+      can_overwrite = 2;
     }
     else                                               // unknown bucket type
       RET_ERR(EINVAL);
-    ptr = decode_attributes(ptr, end, o);              // body
+    ASSERT(can_overwrite == 2);                                // because of the policy and decompression
+    ptr = decode_attributes(ptr, end, o, 2);           // body
 
     if (ptr != end)
       RET_ERR(EINVAL);
+    if (overwritten)
+      bflush(body);
   }
   return o;
 }