summaryrefslogtreecommitdiff
path: root/platform/default/uv_zip.c
diff options
context:
space:
mode:
Diffstat (limited to 'platform/default/uv_zip.c')
-rw-r--r--platform/default/uv_zip.c202
1 files changed, 202 insertions, 0 deletions
diff --git a/platform/default/uv_zip.c b/platform/default/uv_zip.c
new file mode 100644
index 0000000000..b6d2c2ebe0
--- /dev/null
+++ b/platform/default/uv_zip.c
@@ -0,0 +1,202 @@
+#include "uv_zip.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+
+void uv__zip_open_error(uv_zip_t *zip, int error) {
+ zip->result = -error;
+ if (zip->message) {
+ free((char *)zip->message);
+ zip->message = NULL;
+ }
+ const zip_uint64_t size = zip_error_to_str(NULL, 0, error, errno) + 1;
+ zip->message = malloc(size);
+ zip_error_to_str((char *)zip->message, size, error, errno);
+}
+
+void uv__zip_store_error(uv_zip_t *zip, const char *message) {
+ if (zip->message) {
+ free((char *)zip->message);
+ zip->message = NULL;
+ }
+ const unsigned long length = strlen(message);
+ zip->message = malloc(length);
+ strncpy((char *)zip->message, message, length);
+}
+
+void uv__zip_error(uv_zip_t *zip) {
+ int error;
+ zip_error_get(zip->archive, &error, NULL);
+ zip->result = -error;
+ uv__zip_store_error(zip, zip_strerror(zip->archive));
+}
+
+void uv__zip_file_error(uv_zip_t *zip) {
+ int error;
+ zip_file_error_get(zip->file, &error, NULL);
+ zip->result = -error;
+ uv__zip_store_error(zip, zip_file_strerror(zip->file));
+}
+
+void uv__zip_work_open(uv_work_t *req) {
+ uv_zip_t *zip = (uv_zip_t *)req->data;
+ assert(!zip->archive);
+
+ int error;
+ zip->archive = zip_open(zip->path, zip->flags, &error);
+ if (!zip->archive) {
+ uv__zip_open_error(zip, error);
+ } else {
+ zip->result = 0;
+ }
+}
+
+void uv__zip_work_fdopen(uv_work_t *req) {
+ uv_zip_t *zip = (uv_zip_t *)req->data;
+ assert(!zip->archive);
+
+ // extract the fd
+ uv_file fd = *(uv_file *)zip->path;
+ free((uv_file *)zip->path);
+ zip->path = NULL;
+
+ int error;
+ zip->archive = zip_fdopen(fd, zip->flags, &error);
+ if (!zip->archive) {
+ uv__zip_open_error(zip, error);
+ } else {
+ zip->result = 0;
+ }
+}
+
+void uv__zip_work_stat(uv_work_t *req) {
+ uv_zip_t *zip = (uv_zip_t *)req->data;
+ assert(zip->archive);
+ if (!zip->stat) {
+ zip->stat = malloc(sizeof(struct zip_stat));
+ zip_stat_init(zip->stat);
+ }
+ if (0 != zip_stat(zip->archive, zip->path, zip->flags, zip->stat)) {
+ uv__zip_error(zip);
+ }
+}
+
+void uv__zip_work_fopen(uv_work_t *req) {
+ uv_zip_t *zip = (uv_zip_t *)req->data;
+ assert(zip->archive);
+ zip->file = zip_fopen(zip->archive, zip->path, zip->flags);
+ if (!zip->file) {
+ uv__zip_error(zip);
+ }
+}
+
+void uv__zip_work_fread(uv_work_t *req) {
+ uv_zip_t *zip = (uv_zip_t *)req->data;
+ assert(zip->file);
+ assert(zip->buf);
+ zip->result = zip_fread(zip->file, zip->buf->base, zip->buf->len);
+ if (zip->result < 0) {
+ uv__zip_file_error(zip);
+ }
+}
+
+void uv__zip_work_fclose(uv_work_t *req) {
+ uv_zip_t *zip = (uv_zip_t *)req->data;
+ assert(zip->file);
+ zip->result = zip_fclose(zip->file);
+ if (zip->result != 0) {
+ uv__zip_file_error(zip);
+ }
+}
+
+void uv__zip_work_discard(uv_work_t *req) {
+ uv_zip_t *zip = (uv_zip_t *)req->data;
+ assert(zip->archive);
+ zip_discard(zip->archive);
+ zip->archive = NULL;
+ zip->result = 0;
+}
+
+void uv__zip_after_work(uv_work_t *req, int status) {
+ uv_zip_t *zip = (uv_zip_t *)req->data;
+ if (zip->cb) {
+ zip->cb(zip);
+ }
+}
+
+void uv_zip_init(uv_zip_t *zip) {
+ zip->work.data = zip;
+ zip->message = NULL;
+ zip->stat = NULL;
+ uv_zip_cleanup(zip);
+}
+
+void uv_zip_cleanup(uv_zip_t *zip) {
+ zip->data = NULL;
+ zip->flags = 0;
+ zip->result = 0;
+ zip->path = NULL;
+ zip->cb = NULL;
+ zip->archive = NULL;
+ zip->file = NULL;
+ zip->buf = NULL;
+
+ if (zip->message) {
+ free((char *)zip->message);
+ zip->message = NULL;
+ }
+
+ if (zip->stat) {
+ free(zip->stat);
+ zip->stat = NULL;
+ }
+}
+
+int uv_zip_open(uv_loop_t* loop, uv_zip_t *zip, const char *path, zip_flags_t flags, uv_zip_cb cb) {
+ zip->path = path;
+ zip->flags = flags;
+ zip->cb = cb;
+ return uv_queue_work(loop, &zip->work, uv__zip_work_open, uv__zip_after_work);
+}
+
+int uv_zip_fdopen(uv_loop_t* loop, uv_zip_t *zip, uv_file fd, int flags, uv_zip_cb cb) {
+ zip->path = malloc(sizeof(uv_file));
+ *(uv_file *)zip->path = fd;
+ zip->flags = flags;
+ zip->cb = cb;
+ return uv_queue_work(loop, &zip->work, uv__zip_work_fdopen, uv__zip_after_work);
+}
+
+int uv_zip_stat(uv_loop_t* loop, uv_zip_t *zip, const char *fname, zip_flags_t flags, uv_zip_cb cb) {
+ zip->path = fname;
+ zip->flags = flags;
+ zip->cb = cb;
+ return uv_queue_work(loop, &zip->work, uv__zip_work_stat, uv__zip_after_work);
+}
+
+int uv_zip_fopen(uv_loop_t* loop, uv_zip_t *zip, const char *fname, zip_flags_t flags, uv_zip_cb cb) {
+ zip->path = fname;
+ zip->flags = flags;
+ zip->cb = cb;
+ return uv_queue_work(loop, &zip->work, uv__zip_work_fopen, uv__zip_after_work);
+}
+
+int uv_zip_fclose(uv_loop_t* loop, uv_zip_t *zip, struct zip_file *file, uv_zip_cb cb) {
+ zip->file = file;
+ zip->cb = cb;
+ return uv_queue_work(loop, &zip->work, uv__zip_work_fclose, uv__zip_after_work);
+}
+
+int uv_zip_fread(uv_loop_t* loop, uv_zip_t *zip, struct zip_file *file, uv_buf_t *buf, uv_zip_cb cb) {
+ zip->file = file;
+ zip->buf = buf;
+ zip->cb = cb;
+ return uv_queue_work(loop, &zip->work, uv__zip_work_fread, uv__zip_after_work);
+}
+
+int uv_zip_discard(uv_loop_t* loop, uv_zip_t *zip, uv_zip_cb cb) {
+ zip->cb = cb;
+ return uv_queue_work(loop, &zip->work, uv__zip_work_discard, uv__zip_after_work);
+}