#include "package.h" #include "lauxlib.h" #include "lualib.h" #include "malloc.h" #include "pow_lua.h" #include "stdio.h" #include "string.h" #include "log.h" #include int pow_extract_package_info(lua_State *L, pow_package *pkg) { lua_getfield(L, -1, "name"); if (!lua_isstring(L, -1)) { pow_log_error("invalid package, name is not string (or doesn't exist)"); return 1; } pkg->name = strdup(lua_tostring(L, -1)); if (!pkg->name) { pow_log_error("strdup failed trying to get package name"); return 1; } lua_pop(L, 1); lua_getfield(L, -1, "version"); if (!lua_isstring(L, -1)) { free(pkg->name); pow_log_error("invalid package, version is not string (or doesn't exist)"); return 1; } pkg->version = strdup(lua_tostring(L, -1)); lua_pop(L, 1); if (!pkg->version) { free(pkg->name); pow_log_error("strdup failed trying to get package name"); return 1; } lua_getfield(L, -1, "sources"); if (!lua_istable(L, -1)) { free(pkg->name); free(pkg->version); pow_log_error("sources is not table or doesn't exist"); return 1; } size_t sources_len = lua_objlen(L, -1); for (size_t i = 0; i < sources_len; i++) { lua_pushinteger(L, i + 1); lua_gettable(L, -2); if (lua_type(L, -1) == LUA_TNIL) break; lua_getfield(L, -1, "path"); pow_package_source *src = malloc(sizeof(pow_package_source)); if (!src) { pow_log_error("failed to malloc pow_package_source\n"); return 1; } if (!lua_isstring(L, -1)) { lua_pop(L, 1); pow_log_error("path is not string"); return 1; } const char *in = strdup(lua_tostring(L, -1)); if (!in) { pow_log_error("failed to strdup path?"); return 1; } src->in = in; lua_pop(L, 1); lua_getfield(L, -1, "out"); if (!lua_isstring(L, -1)) { lua_pop(L, 1); pow_log_error("out is not string"); return 1; } const char *out = strdup(lua_tostring(L, -1)); if (!out) { free(in); lua_pop(L, 1); pow_log_error("out strdup failed?"); return 1; } src->out = out; lua_pop(L, 1); lua_getfield(L, -1, "hash"); if (!lua_isstring(L, -1)) { free(in); free(out); pow_log_error("hash is not string?"); return 1; } const char *hash = strdup(lua_tostring(L, -1)); if (!hash) { free(in); free(out); pow_log_error("failed to strdup hash"); return 1; } src->hash = hash; pkg->source_count++; pkg->sources = realloc(pkg->sources, pkg->source_count * sizeof(pow_package_source *)); pkg->sources[pkg->source_count - 1] = src; lua_pop(L, 1); } lua_pop(L, 1); lua_pop(L, 1); return 0; } int pow_package_open(lua_State *L_global, pow_package *pkg, pow_config *cfg, const char *path) { FILE *fp; int c; int err; fp = fopen(path, "r"); if (!fp) { pow_log_error("error opening package definition, doesn't exist?"); return 1; } char *package_buffer = malloc(4096); size_t total = 0; size_t capacity = 4096; while ((c = fgetc(fp)) != EOF) { if (total + 1 >= capacity) { capacity *= 2; char *tmp = realloc(package_buffer, capacity); if (!tmp) { fclose(fp); free(package_buffer); pow_log_error("failed to realloc package buffer"); return 1; } pow_log_info("reallocated package buffer due to size constraints"); package_buffer = tmp; } package_buffer[total++] = c; } fclose(fp); package_buffer[total] = '\0'; lua_State *L = lua_newthread(L_global); pkg->L = L; // push the config object from cfg thread to pkg thread luaL_openlibs(L); pow_lua_load(L, cfg); luaL_loadstring(L, package_buffer); err = lua_pcall(L, 0, 1, 0); free(package_buffer); if (err) { pow_log_error("%s", lua_tostring(L, -1)); return 1; } if (!lua_istable(L, -1)) { pow_log_error("invalid package, scripts must return table"); return 1; } pkg->source_count = 0; pkg->sources = NULL; pow_extract_package_info(L, pkg); pkg->path = path; pkg->pkg_ref = luaL_ref(L, LUA_REGISTRYINDEX); return 0; } int pow_package_close(pow_package *pkg) { free(pkg->name); free(pkg->version); lua_close(pkg->L); for (size_t i = 0; i > pkg->source_count; i++) { pow_source_close(pkg->sources[i]); } free(pkg); return 0; }