diff --git a/Makefile b/Makefile index 5935e6b7..f463c765 100644 --- a/Makefile +++ b/Makefile @@ -80,6 +80,8 @@ $(APP_OBJS): CFLAGS += \ -Ideps/libsodium \ -Ideps/libsodium/src/libsodium/include \ -Ideps/libuv/include \ + -Ideps/zlib \ + -Ideps/zlib/contrib/minizip \ -Ideps/picohttpparser \ -Ideps/quickjs \ -Ideps/sqlite \ @@ -307,7 +309,20 @@ $(LIBBACKTRACE_OBJS): CFLAGS += \ PICOHTTPPARSER_SOURCES := \ deps/picohttpparser/picohttpparser.c PICOHTTPPARSER_OBJS := $(call get_objs,PICOHTTPPARSER_SOURCES) -# $(PICOHTTPPARSER_OBJS): CFLAGS += + +MINIUNZIP_SOURCES := \ + deps/zlib/contrib/minizip/unzip.c \ + deps/zlib/contrib/minizip/ioapi.c \ + deps/zlib/adler32.c \ + deps/zlib/crc32.c \ + deps/zlib/inffast.c \ + deps/zlib/inflate.c \ + deps/zlib/inftrees.c \ + deps/zlib/zutil.c +MINIUNZIP_OBJS := $(call get_objs,MINIUNZIP_SOURCES) +$(MINIUNZIP_OBJS): CFLAGS += \ + -Ideps/zlib \ + -Wno-maybe-uninitialized LDFLAGS += \ -pthread \ @@ -342,6 +357,7 @@ ALL_APP_OBJS := \ $(APP_OBJS) \ $(BLOWFISH_OBJS) \ $(LIBBACKTRACE_OBJS) \ + $(MINIUNZIP_OBJS) \ $(PICOHTTPPARSER_OBJS) \ $(QUICKJS_OBJS) \ $(SODIUM_OBJS) \ diff --git a/src/main.c b/src/main.c index 6cd0aa89..b54c6377 100644 --- a/src/main.c +++ b/src/main.c @@ -324,6 +324,7 @@ typedef struct tf_run_args_t { const char* db_path; int count; const char* args; + const char* zip; bool help; } tf_run_args_t; @@ -339,6 +340,7 @@ static int _tf_run_task(const tf_run_args_t* args, int index) int result = -1; tf_task_t* task = tf_task_create(); tf_task_set_trusted(task, true); + tf_task_set_zip_path(task, args->zip); tf_task_set_ssb_port(task, args->ssb_port ? args->ssb_port + index : 0); tf_task_set_http_port(task, args->http_port ? args->http_port + index : 0); tf_task_set_https_port(task, args->https_port ? args->https_port + index : 0); @@ -382,6 +384,7 @@ static int _tf_command_run(const char* file, int argc, char* argv[]) { "db-path", 'd', offsetof(tf_run_args_t, db_path), NULL, XOPT_TYPE_STRING, NULL, "Sqlite database path (default: db.sqlite)." }, { "count", 'n', offsetof(tf_run_args_t, count), NULL, XOPT_TYPE_INT, NULL, "Number of instances to run." }, { "args", 'a', offsetof(tf_run_args_t, args), NULL, XOPT_TYPE_STRING, NULL, "Arguments of the form key=value,foo=bar,verbose=true." }, + { "zip", 'z', offsetof(tf_run_args_t, zip), NULL, XOPT_TYPE_STRING, NULL, "Zip archive from which to load files." }, { "help", 'h', offsetof(tf_run_args_t, help), NULL, XOPT_TYPE_BOOL, NULL, "Shows this help message." }, XOPT_NULLOPTION, }; @@ -737,7 +740,7 @@ done: static void _tf_android_thread(void* user_data) { - char* args[] = { "tildefriends" }; + char* args[] = { "tildefriends", "run" }; main(_countof(args), args); } diff --git a/src/task.c b/src/task.c index 9d90e446..bd1f2317 100644 --- a/src/task.c +++ b/src/task.c @@ -24,6 +24,8 @@ #include +#include "unzip.h" + #include "quickjs.h" #include "quickjs-libc.h" @@ -123,6 +125,8 @@ typedef struct _tf_task_t int _http_port; int _https_port; char _db_path[256]; + char _zip_path[256]; + unzFile _zip; const char* _args; promise_stack_t* _promise_stacks; @@ -305,19 +309,44 @@ bool tf_task_send_error_to_parent(tf_task_t* task, JSValue error) return false; } -static const char* _task_loadFile(const char* fileName) +static const char* _task_loadFile(tf_task_t* task, const char* fileName) { char* result = NULL; - FILE* file = fopen(fileName, "rb"); - if (file) + if (task->_zip) { - fseek(file, 0, SEEK_END); - long fileSize = ftell(file); - fseek(file, 0, SEEK_SET); - result = tf_malloc(fileSize + 1); - int bytes_read = fread(result, 1, fileSize, file); - result[bytes_read] = '\0'; - fclose(file); + if (unzLocateFile(task->_zip, fileName, 1) == UNZ_OK) + { + unz_file_info64 info = { 0 }; + if (unzGetCurrentFileInfo64(task->_zip, &info, NULL, 0, NULL, 0, NULL, 0) == UNZ_OK) + { + char* buffer = tf_malloc(info.uncompressed_size + 1); + if (unzOpenCurrentFile(task->_zip) == UNZ_OK) + { + if (unzReadCurrentFile(task->_zip, buffer, info.uncompressed_size) == (int)info.uncompressed_size) + { + buffer[info.uncompressed_size] = '\0'; + result = buffer; + buffer = NULL; + } + unzCloseCurrentFile(task->_zip); + } + tf_free(buffer); + } + } + } + else + { + FILE* file = fopen(fileName, "rb"); + if (file) + { + fseek(file, 0, SEEK_END); + long fileSize = ftell(file); + fseek(file, 0, SEEK_SET); + result = tf_malloc(fileSize + 1); + int bytes_read = fread(result, 1, fileSize, file); + result[bytes_read] = '\0'; + fclose(file); + } } return result; } @@ -338,7 +367,7 @@ int tf_task_execute(tf_task_t* task, const char* fileName) bool executed = false; tf_trace_begin(task->_trace, "tf_task_execute"); - const char* source = _task_loadFile(fileName); + const char* source = _task_loadFile(task, fileName); tf_printf("Running script %s\n", fileName); if (!*task->_scriptName) { @@ -1471,7 +1500,7 @@ JSModuleDef* _tf_task_module_loader(JSContext* context, const char* module_name, if (!source && task->_trusted) { - source = (char*)_task_loadFile(module_name); + source = (char*)_task_loadFile(task, module_name); length = source ? strlen(source) : 0; } @@ -1838,6 +1867,21 @@ void tf_task_set_db_path(tf_task_t* task, const char* db_path) snprintf(task->_db_path, sizeof(task->_db_path), "%s", db_path); } +void tf_task_set_zip_path(tf_task_t* task, const char* zip_path) +{ + if (task->_zip) + { + unzClose(task->_zip); + task->_zip = NULL; + } + snprintf(task->_zip_path, sizeof(task->_zip_path), "%s", zip_path); + if (zip_path) + { + task->_zip = unzOpen(zip_path); + tf_printf("Zip %s: %p\n", zip_path, task->_zip); + } +} + void tf_task_set_args(tf_task_t* task, const char* args) { task->_args = args; diff --git a/src/task.h b/src/task.h index d0207e11..d58f26e4 100644 --- a/src/task.h +++ b/src/task.h @@ -41,6 +41,7 @@ void tf_task_set_ssb_port(tf_task_t* task, int port); void tf_task_set_http_port(tf_task_t* task, int port); void tf_task_set_https_port(tf_task_t* task, int port); void tf_task_set_db_path(tf_task_t* task, const char* path); +void tf_task_set_zip_path(tf_task_t* task, const char* path); void tf_task_set_args(tf_task_t* task, const char* args); void tf_task_activate(tf_task_t* task); void tf_task_run(tf_task_t* task);