aboutsummaryrefslogtreecommitdiff
path: root/lpm.c
diff options
context:
space:
mode:
Diffstat (limited to 'lpm.c')
-rw-r--r--lpm.c54
1 files changed, 53 insertions, 1 deletions
diff --git a/lpm.c b/lpm.c
index fc2f75c..6a1a1cb 100644
--- a/lpm.c
+++ b/lpm.c
@@ -8,6 +8,8 @@
#include <lualib.h>
#include <dirent.h>
#include <unistd.h>
+#include <archive.h>
+#include <archive_entry.h>
#include <sys/stat.h>
#include <git2.h>
@@ -18,6 +20,8 @@
#include <direct.h>
#include <windows.h>
#include <fileapi.h>
+#else
+ #define MAX_PATH PATH_MAX
#endif
static char hex_digits[] = "0123456789abcdef";
@@ -375,13 +379,60 @@ static int lpm_certs(lua_State* L) {
return 0;
}
+static int lpm_extract(lua_State* L) {
+ const char* src = luaL_checkstring(L, 1);
+ const char* dst = luaL_optstring(L, 2, "./");
+
+ struct archive_entry *entry;
+ const void *buff;
+ int flags = 0;
+ int r;
+ size_t size;
+#if ARCHIVE_VERSION_NUMBER >= 3000000
+ int64_t offset;
+#else
+ off_t offset;
+#endif
+ struct archive *ar = archive_read_new();
+ struct archive *aw = archive_write_disk_new();
+ archive_write_disk_set_options(aw, flags);
+ archive_read_support_format_tar(ar);
+ archive_read_support_format_zip(ar);
+ if ((r = archive_read_open_filename(ar, src, 10240)))
+ luaL_error(L, "error extracting archive %s: %s", src, archive_error_string(ar));
+ for (;;) {
+ int r = archive_read_next_header(ar, &entry);
+ if (r == ARCHIVE_EOF)
+ break;
+ if (r != ARCHIVE_OK)
+ luaL_error(L, "error extracting archive %s: %s", src, archive_error_string(ar));
+ char path[MAX_PATH];
+ strcpy(path, dst);
+ strncat(path, archive_entry_pathname(entry), sizeof(path) - 3); path[MAX_PATH-1] = 0;
+ archive_entry_set_pathname(entry, path);
+ if (archive_write_header(aw, entry) != ARCHIVE_OK)
+ return luaL_error(L, "error extracting archive %s: %s", src, archive_error_string(aw));
+ for (;;) {
+ int r = archive_read_data_block(ar, &buff, &size, &offset);
+ if (r == ARCHIVE_EOF)
+ break;
+ if (r != ARCHIVE_OK)
+ return luaL_error(L, "error extracting archive %s: %s", src, archive_error_string(ar));
+ if (archive_write_data_block(aw, buff, size, offset) != ARCHIVE_OK)
+ return luaL_error(L, "error extracting archive %s: %s", src, archive_error_string(aw));
+ }
+ if (archive_write_finish_entry(aw) != ARCHIVE_OK)
+ return luaL_error(L, "error extracting archive %s: %s", src, archive_error_string(aw));
+ }
+ return 0;
+}
+
static size_t lpm_curl_write_callback(char *ptr, size_t size, size_t nmemb, void *BL) {
luaL_Buffer* B = BL;
luaL_addlstring(B, ptr, size*nmemb);
return size*nmemb;
}
-
static int lpm_get(lua_State* L) {
long response_code;
const char* url = luaL_checkstring(L, 1);
@@ -440,6 +491,7 @@ static const luaL_Reg system_lib[] = {
{ "fetch", lpm_fetch }, // Updates a git repository with the specified remote.
{ "reset", lpm_reset }, // Updates a git repository to the specified commit/hash/branch.
{ "get", lpm_get }, // HTTP(s) GET request.
+ { "extract", lpm_extract }, // Opens .tar.gz files.
{ "certs", lpm_certs }, // Sets the SSL certificate chain folder/file.
{ NULL, NULL }
};