#include <errno.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <lzma.h>
static int xz_close(void* data) {
struct xz_cookie* cookie = (struct xz_cookie*)data;
+ if (!cookie)
+ return -1;
+
+ if (cookie->mode == 'w') {
+ while (1) {
+ cookie->stream.next_out = cookie->buffer;
+ cookie->stream.avail_out = sizeof(cookie->buffer);
+
+ lzma_ret ret = lzma_code(&cookie->stream, LZMA_FINISH);
+ if (ret != LZMA_OK && ret != LZMA_STREAM_END)
+ 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;
+ }
+
+ if (ret == LZMA_STREAM_END)
+ break;
+ }
+ }
- // Free the deocder
lzma_end(&cookie->stream);
// Close input file
- fclose(cookie->f);
+ int r = fclose(cookie->f);
+ free(cookie);
- return 0;
+ return r;
}
+static cookie_io_functions_t xz_functions = {
+ .read = xz_read,
+ .write = xz_write,
+ .seek = NULL,
+ .close = xz_close,
+};
+
FILE* pakfire_xzfopen(FILE* f, const char* mode) {
+ lzma_ret ret;
+
if (!f) {
errno = EBADFD;
return NULL;
return NULL;
}
- struct xz_cookie cookie = {
- .f = f,
- .mode = *mode,
- .stream = LZMA_STREAM_INIT,
- .done = 0,
- };
+ struct xz_cookie* cookie = calloc(1, sizeof(*cookie));
+ if (!cookie)
+ return NULL;
- lzma_ret ret;
+ cookie->f = f;
+ cookie->mode = *mode;
- // Initialise the encoder/decoder
- switch (cookie.mode) {
+ switch (cookie->mode) {
case 'r':
- ret = lzma_stream_decoder(&cookie.stream, UINT64_MAX, 0);
+ ret = lzma_stream_decoder(&cookie->stream, UINT64_MAX, 0);
break;
case 'w':
- ret = lzma_easy_encoder(&cookie.stream, XZ_COMPRESSION_LEVEL, LZMA_CHECK_SHA256);
+ ret = lzma_easy_encoder(&cookie->stream, XZ_COMPRESSION_LEVEL, LZMA_CHECK_SHA256);
break;
default:
errno = ENOTSUP;
+ free(cookie);
return NULL;
}
if (ret != LZMA_OK)
return NULL;
- cookie_io_functions_t functions = {
- .read = xz_read,
- .write = xz_write,
- .seek = NULL,
- .close = xz_close,
- };
-
- return fopencookie(&cookie, mode, functions);
+ return fopencookie(cookie, mode, xz_functions);
}