From 6f27a8e2ff75366bdb3e72cfedbd61263dafacb5 Mon Sep 17 00:00:00 2001 From: Adam Harrison Date: Sun, 1 Jan 2023 15:28:52 -0500 Subject: Updated extraction process to chmod, as well as unzip first for much better speed. --- src/lpm.c | 42 +++++++++++++++++++++++++++++++++++++----- src/lpm.lua | 15 ++++++++++++--- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/src/lpm.c b/src/lpm.c index 0309496..54eca32 100644 --- a/src/lpm.c +++ b/src/lpm.c @@ -535,7 +535,7 @@ static int lpm_certs(lua_State* L) { static int mkdirp(char* path, int len) { for (int i = 0; i < len; ++i) { - if (path[i] == '/') { + if (path[i] == '/' && i > 0) { path[i] = 0; #ifndef _WIN32 if (mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) && errno != EEXIST) @@ -610,14 +610,42 @@ static int lpm_extract(lua_State* L) { } else if (strstr(src, ".tar")) { mtar_t tar = {0}; int err; + char actual_src[PATH_MAX]; if (strstr(src, ".gz")) { - tar.stream = gzopen(src, "rb"); - if (!tar.stream) + gzFile gzfile = gzopen(src, "rb"); + if (!gzfile) return luaL_error(L, "can't open tar.gz archive %s: %s", src, strerror(errno)); + /* It's increidbly slow to do it this way, probably because of all the seeking. + For now, just gunzip the whole file at once, and then untar it. tar.read = gzip_read; tar.seek = gzip_seek; - tar.close = gzip_close; - } else if ((err = mtar_open(&tar, src, "r"))) + tar.close = gzip_close;*/ + char buffer[8192]; + int len = strlen(src); + strncpy(actual_src, src, len - 3); + actual_src[len-3] = 0; + FILE* file = fopen(actual_src, "wb"); + while (1) { + int length = gzread(gzfile, buffer, sizeof(buffer)); + if (length == 0) + break; + fwrite(buffer, sizeof(char), length, file); + } + char error[128]; + error[0] = 0; + if (!gzeof(gzfile)) { + int error_number; + strncpy(error, gzerror(gzfile, &error_number), sizeof(error)); + error[sizeof(error)-1] = 0; + } + fclose(file); + gzclose(gzfile); + if (error[0]) + return luaL_error(L, "can't unzip tar archive %s: %s", src, error); + } else { + strcpy(actual_src, src); + } + if ((err = mtar_open(&tar, actual_src, "r"))) return luaL_error(L, "can't open tar archive %s: %s", src, mtar_strerror(err)); mtar_header_t h; while ((mtar_read_header(&tar, &h)) != MTAR_ENULLRECORD ) { @@ -634,6 +662,8 @@ static int lpm_extract(lua_State* L) { mtar_close(&tar); return luaL_error(L, "can't extract tar archive file %s, can't create file %s: %s", src, target, strerror(errno)); } + if (chmod(target, h.mode)) + return luaL_error(L, "can't extract tar archive file %s, can't chmod file %s: %s", src, target, strerror(errno)); int remaining = h.size; while (remaining > 0) { int read_size = remaining < sizeof(buffer) ? remaining : sizeof(buffer); @@ -650,6 +680,8 @@ static int lpm_extract(lua_State* L) { mtar_next(&tar); } mtar_close(&tar); + if (strstr(src, ".gz")) + unlink(actual_src); } else return luaL_error(L, "unrecognized archive format %s", src); return 0; diff --git a/src/lpm.lua b/src/lpm.lua index 70299eb..d37f46b 100644 --- a/src/lpm.lua +++ b/src/lpm.lua @@ -486,7 +486,7 @@ function common.get(source, target, checksum, callback, depth) if not source then error("requires url") end if (depth or 0) > 10 then error("too many redirects") end local _, _, protocol, hostname, port, rest = source:find("^(https?)://([^:/?]+):?(%d*)(.*)$") - log_progress_action("Downloading " .. source .. "...") + log_progress_action("Downloading " .. source:sub(1, 60) .. "...") if not protocol then error("malfomed url " .. source) end if not port or port == "" then port = protocol == "https" and 443 or 80 end if not checksum then @@ -682,6 +682,7 @@ function Plugin:install(bottle, installing) elseif self.path then local path = install_path .. (self.organization == 'complex' and self.path and system.stat(self.local_path).type ~= "dir" and (PATHSEP .. "init.lua") or "") local temporary_path = temporary_install_path .. (self.organization == 'complex' and self.path and system.stat(self.local_path).type ~= "dir" and (PATHSEP .. "init.lua") or "") + if self.organization == 'complex' and self.path and system.stat(self.local_path).type ~= "dir" then common.mkdirp(temporary_install_path) end log_action("Copying " .. self.local_path .. " to " .. path) common.copy(self.local_path, temporary_path) elseif self.organization == 'complex' then @@ -696,7 +697,13 @@ function Plugin:install(bottle, installing) log_action("Downloading file " .. file.url .. "...") common.get(file.url, temporary_path, file.checksum, write_progress_bar) log_action("Downloaded file " .. file.url .. " to " .. path) - if file.arch then system.chmod(temporary_path, 448) end -- chmod any ARCH tagged file to rwx------- + local basename = common.basename(path) + if basename:find("%.zip$") or basename:find("%.tar%.gz$") then + log_action("Extracting file " .. basename .. " in " .. install_path) + system.extract(temporary_path, temporary_install_path) + else + if file.arch then system.chmod(temporary_path, 448) end -- chmod any ARCH tagged file to rwx------- + end end end end @@ -785,7 +792,9 @@ function Repository:parse_manifest(already_pulling) if system.stat(self.local_path) and system.stat(self.local_path .. PATHSEP .. (self.commit or self.branch)) then self.manifest_path = self.local_path .. PATHSEP .. (self.commit or self.branch) .. PATHSEP .. "manifest.json" if not system.stat(self.manifest_path) then self:generate_manifest() end - self.manifest = json.decode(common.read(self.manifest_path)) + local status, manifest = pcall(json.decode, common.read(self.manifest_path)) + if not status then error("error parsing manifest for " .. self:url() .. ": " .. manifest) end + self.manifest = manifest self.plugins = {} self.remotes = {} for i, metadata in ipairs(self.manifest["plugins"] or {}) do -- cgit v1.2.3