// Compression/Decompression buffer size
#define BUFFER_SIZE 64 * 1024
+// Settings for XZ
+#define XZ_COMPRESSION_LEVEL 6
+
const struct compressor {
char magic[MAX_MAGIC_LENGTH];
size_t magic_length;
uint8_t buffer[BUFFER_SIZE];
};
-
static ssize_t xz_read(void* data, char* buffer, size_t size) {
struct xz_cookie* cookie = (struct xz_cookie*)data;
if (!cookie)
}
}
+static ssize_t xz_write(void* data, const char* buffer, size_t size) {
+ struct xz_cookie* cookie = (struct xz_cookie*)data;
+ if (!cookie)
+ return -1;
+
+ // Do not write when mode is "r"
+ if (cookie->mode == 'r')
+ return 0;
+
+ // Return nothing when there is no input
+ if (size == 0)
+ return 0;
+
+ // Set input to allocated buffer
+ cookie->stream.next_out = (uint8_t *)buffer;
+ cookie->stream.avail_out = size;
+
+ while (1) {
+ cookie->stream.next_out = cookie->buffer;
+ cookie->stream.avail_out = sizeof(cookie->buffer);
+
+ lzma_ret ret = lzma_code(&cookie->stream, LZMA_RUN);
+ if (ret != LZMA_OK)
+ return -1;
+
+ size_t bytes_to_write = sizeof(cookie->buffer) - cookie->stream.avail_out;
+ if (bytes_to_write) {
+ size_t bytes_written = fwrite(cookie->buffer, 1, bytes_to_write, cookie->f);
+
+ if (bytes_written != bytes_to_write)
+ return -1;
+ }
+
+ // Report that all data has been written
+ if (cookie->stream.avail_in == 0)
+ return size;
+ }
+}
+
static int xz_close(void* data) {
struct xz_cookie* cookie = (struct xz_cookie*)data;
.done = 0,
};
- // Initialise the decoder
- lzma_ret ret = lzma_stream_decoder(&cookie.stream, UINT64_MAX, 0);
+ lzma_ret ret;
+
+ // Initialise the encoder/decoder
+ switch (cookie.mode) {
+ case 'r':
+ ret = lzma_stream_decoder(&cookie.stream, UINT64_MAX, 0);
+ break;
+
+ case 'w':
+ ret = lzma_easy_encoder(&cookie.stream, XZ_COMPRESSION_LEVEL, LZMA_CHECK_SHA256);
+ break;
+
+ default:
+ errno = ENOTSUP;
+ return NULL;
+ }
+
if (ret != LZMA_OK)
return NULL;
cookie_io_functions_t functions = {
.read = xz_read,
- .write = NULL,
+ .write = xz_write,
.seek = NULL,
.close = xz_close,
};