]> mj.ucw.cz Git - libucw.git/commitdiff
- encapsulation: hide struct lizard_buffer in the source code
authorRobert Spalek <robert@ucw.cz>
Mon, 28 Jun 2004 09:34:27 +0000 (09:34 +0000)
committerRobert Spalek <robert@ucw.cz>
Mon, 28 Jun 2004 09:34:27 +0000 (09:34 +0000)
  ===> interface changed, now it returns the pointer in one extra parameter
- lizard_alloc() allocates no memory, hence no size parameter needed
- lizard_realloc() made static and it is automatically called by the
  decompression routine

lib/lizard-safe.c
lib/lizard.h

index 218faec2d3bc7436dc00bf8a7a074720479b8c15..dcc01d11f59a6a69528eac1fd75f86f867230d35 100644 (file)
 #include <setjmp.h>
 #include <errno.h>
 
-static void
-lizard_alloc_internal(struct lizard_buffer *buf, uns max_len)
-{
-  if (!max_len)
-  {
-    buf->len = 0;
-    buf->start = NULL;
-    return;
-  }
-  buf->len = ALIGN(max_len + 3, PAGE_SIZE);            // +3 due to the unaligned access
-  buf->start = mmap(NULL, buf->len + PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
-  if (buf->start == MAP_FAILED)
-    die("mmap(anonymous): %m");
-  if (mprotect(buf->start + buf->len, PAGE_SIZE, PROT_NONE) < 0)
-    die("mprotect: %m");
-}
+struct lizard_buffer {
+  uns len;
+  void *ptr;
+  struct sigaction *old_sigsegv_handler;
+};
 
 struct lizard_buffer *
-lizard_alloc(uns max_len)
+lizard_alloc(void)
 {
   struct lizard_buffer *buf = xmalloc(sizeof(struct lizard_buffer));
-  lizard_alloc_internal(buf, max_len);
+  buf->len = 0;
+  buf->ptr = NULL;
   buf->old_sigsegv_handler = xmalloc(sizeof(struct sigaction));
   handle_signal(SIGSEGV, buf->old_sigsegv_handler);
   return buf;
@@ -48,24 +38,30 @@ lizard_alloc(uns max_len)
 void
 lizard_free(struct lizard_buffer *buf)
 {
-  if (buf->start)
-    munmap(buf->start, buf->len + PAGE_SIZE);
+  if (buf->ptr)
+    munmap(buf->ptr, buf->len + PAGE_SIZE);
   unhandle_signal(SIGSEGV, buf->old_sigsegv_handler);
   xfree(buf->old_sigsegv_handler);
   xfree(buf);
 }
 
-void
+static void
 lizard_realloc(struct lizard_buffer *buf, uns max_len)
+  /* max_len needs to be aligned to PAGE_SIZE */
 {
-  max_len += 3;
   if (max_len <= buf->len)
     return;
-  if (max_len < 2*buf->len)                            // to ensure amortized logarithmic complexity
+  if (max_len < 2*buf->len)                            // to ensure logarithmic cost
     max_len = 2*buf->len;
-  if (buf->start)
-    munmap(buf->start - 3, buf->len + PAGE_SIZE);
-  lizard_alloc_internal(buf, max_len);
+
+  if (buf->ptr)
+    munmap(buf->ptr, buf->len + PAGE_SIZE);
+  buf->len = max_len;
+  buf->ptr = mmap(NULL, buf->len + PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+  if (buf->ptr == MAP_FAILED)
+    die("mmap(anonymous): %m");
+  if (mprotect(buf->ptr + buf->len, PAGE_SIZE, PROT_NONE) < 0)
+    die("mprotect: %m");
 }
 
 static jmp_buf safe_decompress_jump;
@@ -78,29 +74,27 @@ sigsegv_handler(int signal UNUSED)
 }
 
 int
-lizard_decompress_safe(byte *in, struct lizard_buffer *buf, uns expected_length)
-  /* Decompresses into buf->ptr and returns the length of the uncompressed
-   * file.  If an error has occured, -1 is returned and errno is set.  SIGSEGV
-   * is caught in the case of buffer-overflow.  The function is not re-entrant
-   * because of a static longjmp handler.  */
+lizard_decompress_safe(byte *in, struct lizard_buffer *buf, uns expected_length, byte **ptr)
+  /* Decompresses in into buf, sets *ptr to the data, and returns the
+   * uncompressed length.  If an error has occured, -1 is returned and errno is
+   * set.  The buffer buf is automatically reallocated.  SIGSEGV is caught in
+   * case of buffer-overflow.  The function is not re-entrant because of a
+   * static longjmp handler.  */
 {
   uns lock_offset = ALIGN(expected_length + 3, PAGE_SIZE);     // +3 due to the unaligned access
   if (lock_offset > buf->len)
-  {
-    errno = EFBIG;
-    return -1;
-  }
+    lizard_realloc(buf, lock_offset);
   volatile sh_sighandler_t old_handler = signal_handler[SIGSEGV];
   signal_handler[SIGSEGV] = sigsegv_handler;
   int len;
   if (!setjmp(safe_decompress_jump))
   {
-    buf->ptr = buf->start + buf->len - lock_offset;
-    len = lizard_decompress(in, buf->ptr);
+    *ptr = buf->ptr + buf->len - lock_offset;
+    len = lizard_decompress(in, *ptr);
   }
   else
   {
-    buf->ptr = NULL;
+    *ptr = NULL;
     len = -1;
     errno = EFAULT;
   }
index 3f72b96cdce392bdca47b26d4e6498982a5c2e38..bbd2a838a628928cd735570bf91169e1e47d69af 100644 (file)
@@ -20,7 +20,7 @@
    * The multiplicative constant comes from 19-byte incompressible string
    * followed by a 3-sequence that can be compressed into 2-byte link.  This
    * breaks the copy-mode and it needs to be restarted with a new header.  The
-   * total length is 2(header) + 2(link) + 19(string) = 23.
+   * total length is 2(header) + 19(string) + 2(link) = 23.
    */
 
 /* lizard.c */
@@ -28,14 +28,8 @@ int lizard_compress(byte *in, uns in_len, byte *out);
 int lizard_decompress(byte *in, byte *out);
 
 /* lizard-safe.c */
-struct sigaction;
-struct lizard_buffer {
-  uns len;
-  void *start, *ptr;
-  struct sigaction *old_sigsegv_handler;
-};
+struct lizard_buffer;
 
-struct lizard_buffer *lizard_alloc(uns max_len);
+struct lizard_buffer *lizard_alloc(void);
 void lizard_free(struct lizard_buffer *buf);
-void lizard_realloc(struct lizard_buffer *buf, uns max_len);
-int lizard_decompress_safe(byte *in, struct lizard_buffer *buf, uns expected_length);
+int lizard_decompress_safe(byte *in, struct lizard_buffer *buf, uns expected_length, byte **ptr);