diff options
-rw-r--r-- | .gitmodules | 6 | ||||
-rw-r--r-- | README.md | 4 | ||||
-rwxr-xr-x | build.sh | 7 | ||||
m--------- | lib/libtar | 0 | ||||
m--------- | lib/microtar | 0 | ||||
-rw-r--r-- | src/lpm.c | 99 |
6 files changed, 67 insertions, 49 deletions
diff --git a/.gitmodules b/.gitmodules index ef53f82..5f540c7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -8,9 +8,9 @@ [submodule "lib/zlib"] path = lib/zlib url = https://github.com/madler/zlib.git -[submodule "lib/libtar"] - path = lib/libtar - url = https://github.com/tklauser/libtar.git [submodule "lib/libzip"] path = lib/libzip url = https://github.com/nih-at/libzip.git +[submodule "lib/microtar"] + path = lib/microtar + url = https://github.com/rxi/microtar.git @@ -52,7 +52,7 @@ build `lpm`: * `libgit2` (accessing git repositories directly) * `libz` (supporting library for everything) * `libzip` (for unpacking .zip files) -* `libtar` (for unpacking .tar.gz files) +* `libmicrotar` (for unpacking .tar.gz files) ## Use in CI @@ -86,7 +86,7 @@ lpm --help ### Linux to Windows ``` -CC=x86_64-w64-mingw32-gcc AR=x86_64-w64-mingw32-gcc-ar WINDRES=x86_64-w64-mingw32-windres CMAKE_DEFAULT_FLAGS="-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=NEVER -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=NEVER -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_SYSTEM_INCLUDE_PATH=/usr/share/mingw-w64/include" GIT2_CONFIGURE="-DDLLTOOL=x86_64-w64-mingw32-dlltool" ./build.sh -DLPM_VERSION='"'$VERSION-x86_64-windows-`git rev-parse --short HEAD`'"' +CC=x86_64-w64-mingw32-gcc AR=x86_64-w64-mingw32-gcc-ar WINDRES=x86_64-w64-mingw32-windres CMAKE_DEFAULT_FLAGS="-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=NEVER -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=NEVER -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_SYSTEM_INCLUDE_PATH=/usr/share/mingw-w64/include" TAR_CONFIGURE="--host=x86_64-w64-mingw32" GIT2_CONFIGURE="-DDLLTOOL=x86_64-w64-mingw32-dlltool" ./build.sh -DLPM_VERSION='"'$VERSION-x86_64-windows-`git rev-parse --short HEAD`'"' ``` @@ -16,7 +16,7 @@ CMAKE_DEFAULT_FLAGS=" $CMAKE_DEFAULT_FLAGS -DCMAKE_BUILD_TYPE=Release -DCMAKE_PR mkdir -p lib/prefix/include lib/prefix/lib if [[ "$@" != *"-lz"* ]]; then [ ! -e "lib/zlib" ] && echo "Make sure you've cloned submodules. (git submodule update --init --depth=1)" && exit -1 - [[ ! -e "lib/zlib/build" && $OSTYPE != 'msys'* ]] && cd lib/zlib && mkdir build && cd build && ../configure --prefix=`pwd`/../../prefix && $MAKE -j $JOBS && $MAKE install && cd ../../../ + [[ ! -e "lib/zlib/build" && $OSTYPE != 'msys'* ]] && cd lib/zlib && mkdir build && cd build && ../configure --static --prefix=`pwd`/../../prefix && $MAKE -j $JOBS && $MAKE install && cd ../../../ [[ ! -e "lib/zlib/build" && $OSTYPE == 'msys'* ]] && cd lib/zlib && mkdir build && $MAKE -f ../win32/Makefile.gcc -j $JOBS && cp *.a ../prefix/lib && cp *.h ../prefix/include && cd ../../ LDFLAGS="$LDFLAGS -l:libz.a" fi @@ -32,10 +32,7 @@ if [[ "$@" != *"-lzip"* ]]; then [ ! -e "lib/libzip/build" ] && cd lib/libzip && mkdir build && cd build && cmake .. -G "Unix Makefiles" $CMAKE_DEFAULT_FLAGS -DBUILD_TOOLS=OFF -DBUILD_EXAMPLES=OFF -DBUILD_DOC=OFF -DENABLE_COMMONCRYPTO=OFF -DENABLE_GNUTLS=OFF -DENABLE_OPENSSL=OFF -DENABLE_BZIP2=OFF -DENABLE_LZMA=OFF -DENABLE_ZSTD=OFF && $MAKE -j $JOBS && $MAKE install && cd ../../../ LDFLAGS="$LDFLAGS -l:libzip.a" fi -if [[ "$@" != *"-ltar"* ]]; then - [ ! -e "lib/libtar/build" ] && cd lib/libtar && mkdir build && autoreconf --force --install && cd build && ../configure --prefix=`pwd`/../../prefix && $MAKE -j $JOBS && $MAKE install && cd ../../../ - LDFLAGS="$LDFLAGS -l:libtar.a" -fi +[[ "$@" != *"-lmicrotar"* ]] && CFLAGS="$CFLAGS -Ilib/microtar/src" && SRCS="$SRCS lib/microtar/src/microtar.c" [[ "$@" != *"-llua"* ]] && CFLAGS="$CFLAGS -Ilib/lua -DMAKE_LIB=1" && SRCS="$SRCS lib/lua/onelua.c" # Build the pre-packaged lua file into the executbale. diff --git a/lib/libtar b/lib/libtar deleted file mode 160000 -Subproject 6379b5d2ae777dad576aeae7056674067005782 diff --git a/lib/microtar b/lib/microtar new file mode 160000 +Subproject 27076e1b9290e9c7842bb7890a54fcf172406c8 @@ -35,7 +35,7 @@ #include <mbedtls/net.h> #include <zlib.h> -#include <libtar.h> +#include <microtar.h> #include <zip.h> static char hex_digits[] = "0123456789abcdef"; @@ -438,27 +438,21 @@ static int lpm_certs(lua_State* L) { } -// We can have one because we're single-threaded, and extracting is an atomic operation. -static gzFile gzf; -static int gzopen_frontend(char *pathname, int oflags, int mode) { - int fd = open(pathname, oflags, mode); - if (fd == -1) - return -1; - if (!(gzf = gzdopen(fd, "rb"))) { - errno = ENOMEM; - gzf = NULL; - return -1; - } - return fd; +static int mkdirp(char* path, int len) { + for (int i = 0; i < len; ++i) { + if (path[i] == '/') { + path[i] = 0; + if (mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) && errno != EEXIST) + return -1; + path[i] = '/'; + } + } + return 0; } -static int gzread_frontend(int fd, void* buf, size_t len) { return gzread(gzf, buf, len); } -static int gzwrite_frontend(int fd, void* buf, size_t len) { return gzwrite(gzf, buf, len); } -static int gzclose_frontend(int fd) { gzclose(gzf); } -tartype_t gztype = { - (openfunc_t) gzopen_frontend, (closefunc_t) gzclose_frontend, - (readfunc_t) gzread_frontend, (writefunc_t) gzwrite_frontend -}; +static int gzip_read(mtar_t* tar, void* data, unsigned int size) { return gzread(tar->stream, data, size) >= 0 ? MTAR_ESUCCESS : -1; } +static int gzip_seek(mtar_t* tar, unsigned int pos) { return gzseek(tar->stream, pos, SEEK_SET) >= 0 ? MTAR_ESUCCESS : -1; } +static int gzip_close(mtar_t* tar) { return gzclose(tar->stream) == Z_OK ? MTAR_ESUCCESS : -1; } static int lpm_extract(lua_State* L) { const char* src = luaL_checkstring(L, 1); @@ -485,16 +479,10 @@ static int lpm_extract(lua_State* L) { } char target[MAX_PATH]; int target_length = snprintf(target, sizeof(target), "%s/%s", dst, zip_name); - for (int i = 0; i < target_length; ++i) { - if (target[i] == '/') { - target[i] = 0; - if (mkdir(target, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) && errno != EEXIST) { - zip_fclose(zip_file); - zip_close(archive); - return luaL_error(L, "can't extract zip archive file %s, can't create directory %s: %s", src, target, strerror(errno)); - } - target[i] = '/'; - } + if (!mkdirp(target, target_length)) { + zip_fclose(zip_file); + zip_close(archive); + return luaL_error(L, "can't extract zip archive file %s, can't create directory %s: %s", src, target, strerror(errno)); } if (target[target_length-1] != '/') { FILE* file = fopen(target, "wb"); @@ -521,15 +509,48 @@ static int lpm_extract(lua_State* L) { } zip_close(archive); } else if (strstr(src, ".tar")) { - TAR* archive; - if (tar_open(&archive, src, strstr(src, ".gz") ? &gztype : NULL, O_RDONLY, 0, TAR_GNU)) - return luaL_error(L, "can't open tar archive %s: %s", src, strerror(errno)); - if (tar_extract_all(archive, (char*)dst)) { - tar_close(archive); - return luaL_error(L, "can't extract tar archive %s to %s: %s", src, dst, strerror(errno)); - } - if (tar_close(archive)) - return luaL_error(L, "can't close tar archive %s: %s", src, strerror(errno)); + mtar_t tar = {0}; + int err; + if (strstr(src, ".gz")) { + tar.stream = gzopen(src, "rb"); + if (!tar.stream) + return luaL_error(L, "can't open tar.gz archive %s: %s", src, strerror(errno)); + tar.read = gzip_read; + tar.seek = gzip_seek; + tar.close = gzip_close; + } else if ((err = mtar_open(&tar, 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 ) { + if (h.type == MTAR_TREG) { + char target[MAX_PATH]; + int target_length = snprintf(target, sizeof(target), "%s/%s", dst, h.name); + if (mkdirp(target, target_length)) { + mtar_close(&tar); + return luaL_error(L, "can't extract tar archive file %s, can't create directory %s: %s", src, target, strerror(errno)); + } + char buffer[8192]; + FILE* file = fopen(target, "wb"); + if (!file) { + mtar_close(&tar); + return luaL_error(L, "can't extract tar archive file %s, can't create file %s: %s", src, target, strerror(errno)); + } + int remaining = h.size; + while (remaining > 0) { + int read_size = remaining < sizeof(buffer) ? remaining : sizeof(buffer); + if (mtar_read_data(&tar, buffer, read_size) != MTAR_ESUCCESS) { + fclose(file); + mtar_close(&tar); + return luaL_error(L, "can't write file %s: %s", target, strerror(errno)); + } + fwrite(buffer, sizeof(char), read_size, file); + remaining -= read_size; + } + fclose(file); + } + mtar_next(&tar); + } + mtar_close(&tar); } else return luaL_error(L, "unrecognized archive format %s", src); return 0; |