/*
- * LiZzaRd -- Fast compression method based on Lempel-Ziv 77
+ * LiZaRd -- Fast compression method based on Lempel-Ziv 77
*
* (c) 2004, Robert Spalek <robert@ucw.cz>
*
*/
#include "lib/lib.h"
-#include "lib/lizzard.h"
+#include "lib/lizard.h"
#include <string.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/user.h>
+#include <fcntl.h>
+#include <signal.h>
typedef u16 hash_ptr_t;
struct hash_record {
}
int
-lizzard_compress(byte *in, uns in_len, byte *out)
- /* Requires out being allocated for at least in_len * LIZZARD_MAX_MULTIPLY +
- * LIZZARD_MAX_ADD. There must be at least LIZZARD_NEEDS_CHARS characters
+lizard_compress(byte *in, uns in_len, byte *out)
+ /* Requires out being allocated for at least in_len * LIZARD_MAX_MULTIPLY +
+ * LIZARD_MAX_ADD. There must be at least LIZARD_NEEDS_CHARS characters
* allocated after in. Returns the actual compressed length. */
{
hash_ptr_t hash_tab[HASH_SIZE];
}
int
-lizzard_decompress(byte *in, byte *out)
+lizard_decompress(byte *in, byte *out)
/* Requires out being allocated for the decompressed length must be known
* beforehand. It is desirable to lock the following memory page for
* read-only access to prevent buffer overflow. Returns the actual
return out - out_start;
}
+struct lizard_buffer *
+lizard_alloc(uns max_len)
+{
+ int fd = open("/dev/zero", O_RDWR);
+ if (fd < 0)
+ die("open(/dev/zero): %m");
+ struct lizard_buffer *buf = xmalloc(sizeof(struct lizard_buffer));
+ buf->len = (max_len + 2*PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE;
+ buf->ptr = mmap(NULL, buf->len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (buf->ptr == MAP_FAILED)
+ die("mmap(/dev/zero): %m");
+ return buf;
+}
+
+void
+lizard_free(struct lizard_buffer *buf)
+{
+ munmap(buf->ptr, buf->len);
+ xfree(buf);
+}
+
+static void
+sigsegv_handler(int UNUSED whatsit)
+{
+ die("SIGSEGV caught when decompressing.");
+}
+
+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. Negative return values signalise errors. If something goes wrong
+ * and buffer would overflow, SIGSEGV is raised. */
+{
+ uns lock_offset = (expected_length + PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE;
+ if (lock_offset + PAGE_SIZE > buf->len)
+ return -1;
+ mprotect(buf->ptr, lock_offset, PROT_READ | PROT_WRITE);
+ mprotect(buf->ptr + lock_offset, PAGE_SIZE, PROT_READ);
+ sighandler_t old_handler = signal(SIGSEGV, sigsegv_handler);
+ int len = lizard_decompress(in, buf->ptr);
+ signal(SIGSEGV, old_handler);
+ return len;
+}
+
/*
Description of the LZO1X format :