summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--include/cookbook.h8
-rw-r--r--include/lib/archive.h8
-rw-r--r--include/net.h6
-rw-r--r--include/parser.h2
-rw-r--r--include/pkgman.h8
-rw-r--r--src/cookbook.c70
-rw-r--r--src/lib/archive.c54
-rw-r--r--src/lib/url.c91
-rw-r--r--src/main.c89
-rw-r--r--src/net.c113
-rw-r--r--src/parser.c27
-rw-r--r--src/pkgman.c222
13 files changed, 584 insertions, 116 deletions
diff --git a/Makefile b/Makefile
index 1720a5f..b2c820a 100644
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,7 @@ INCLUDE_DIR = ./include
SRC_FILES = $(shell find $(SRC_DIR) -name '*.c')
OBJ_FILES = $(SRC_FILES:%=$(BUILD_DIR)/%.o)
-CFLAGS = -Wall -Wpedantic -Werror -lcurl -larchive -lzstd -I./include
+CFLAGS = -lcurl -larchive -lzstd -lgpgme -I./include
$(BUILD_DIR)/%.c.o: %.c
@mkdir -p $(dir $@)
diff --git a/include/cookbook.h b/include/cookbook.h
new file mode 100644
index 0000000..86f66aa
--- /dev/null
+++ b/include/cookbook.h
@@ -0,0 +1,8 @@
+#ifndef COOKBOOK_H
+#define COOKBOOK_H
+
+typedef struct url url;
+
+int cookbook_run(struct url *script_loc, char *script);
+
+#endif
diff --git a/include/lib/archive.h b/include/lib/archive.h
new file mode 100644
index 0000000..f0dde8f
--- /dev/null
+++ b/include/lib/archive.h
@@ -0,0 +1,8 @@
+#ifndef ARCHIVE_H
+#define ARCHIVE_H
+
+typedef struct url url;
+
+int pkg_extract(char *archive_path, struct url *out_dir);
+
+#endif
diff --git a/include/net.h b/include/net.h
index e6cb32a..b2b415f 100644
--- a/include/net.h
+++ b/include/net.h
@@ -9,18 +9,18 @@
typedef struct string_view string_view;
-struct memory {
+struct net_write_data {
char *buffer;
size_t size;
};
-struct net_fwrite_userdata {
+struct net_file_write_data {
FILE *file;
};
int net_init();
void net_shutdown();
-int net_send_request(char *url, struct memory *mem, int write_opts);
+int net_send_request(char *url, int write_opts, void *userdata);
#endif
diff --git a/include/parser.h b/include/parser.h
index a8a2a11..9358115 100644
--- a/include/parser.h
+++ b/include/parser.h
@@ -34,7 +34,7 @@ struct parser {
};
int parser_init(struct parser *parser,
- struct memory *mem,
+ struct string_view *mem,
struct parser_backend *backend,
void *userdata);
int parser_parse(struct parser *parser);
diff --git a/include/pkgman.h b/include/pkgman.h
new file mode 100644
index 0000000..0d17622
--- /dev/null
+++ b/include/pkgman.h
@@ -0,0 +1,8 @@
+#ifndef PKGMAN_H
+#define PKGMAN_H
+
+int pkgman_upstream_check(const char *pkg);
+int pkgman_install_pkg(const char *pkg);
+int pkgman_upstream_integrity_download(const char *pkg);
+
+#endif
diff --git a/src/cookbook.c b/src/cookbook.c
new file mode 100644
index 0000000..db2c81a
--- /dev/null
+++ b/src/cookbook.c
@@ -0,0 +1,70 @@
+#include <cookbook.h>
+
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+
+#include <lib/url.h>
+#include <err.h>
+
+int cookbook_run(struct url *script_loc, char *script)
+{
+ printf("Launching build script...\n");
+
+ int pipefd[2];
+
+ if (pipe(pipefd) == -1)
+ return -FORKERR;
+
+ pid_t ps = fork();
+
+ switch (ps) {
+ case -1:
+ perror("fork");
+ return -FORKERR;
+ case 0:
+ close(pipefd[0]);
+ dup2(pipefd[1], STDOUT_FILENO);
+ close(pipefd[1]);
+
+ chdir(script_loc->buffer);
+ url_append(script_loc, "build.sh");
+ if(execve(script_loc->buffer,
+ (char*[]){ script_loc->buffer, script,NULL},
+ (char*[]){
+ "PWD=/tmp/pkgman/nvim-extract",
+ "PATH=/bin:/usr/bin",
+ NULL }) == -1) {
+ fprintf(stderr, "An error was encountered!\n");
+ }
+ break;
+ default: {
+ size_t size = 0;
+ size_t cap = 40;
+ char *mem = malloc(40);
+ char buf[1024];
+ memset(buf, 0, 1024);
+
+ close(pipefd[1]);
+ while (read(pipefd[0], buf, 1) > 0) {
+ if (size >= cap) {
+ cap *= 2;
+ mem = realloc(mem, cap);
+ printf("Realloced!");
+ }
+
+ memcpy(mem + size, buf, 1);
+ size++;
+ }
+
+ printf("Build script stdouts: %.*s\n", size, mem);
+
+ free(mem);
+ int ret;
+ waitpid(ps, &ret, 0);
+ printf("Build script exited with code %d\n", ret);
+ }
+ }
+}
diff --git a/src/lib/archive.c b/src/lib/archive.c
new file mode 100644
index 0000000..2dcd2ec
--- /dev/null
+++ b/src/lib/archive.c
@@ -0,0 +1,54 @@
+#include <lib/archive.h>
+
+#include <err.h>
+#include <lib/url.h>
+
+#include <assert.h>
+
+#include <archive.h>
+#include <archive_entry.h>
+
+int pkg_extract(char *archive_path, struct url *out_dir)
+{
+ assert(out_dir != NULL);
+
+ struct archive *read = archive_read_new();
+ struct archive *disk = archive_write_disk_new();
+ // Read opts
+ archive_read_support_filter_zstd(read);
+ archive_read_support_format_tar(read);
+
+ archive_read_open_filename(read, archive_path, 65535);
+ // Write opts
+ archive_write_disk_set_options(disk, ARCHIVE_EXTRACT_TIME);
+
+ // tmp archive entry (for iterating read)
+ struct archive_entry *entry;
+
+ while (archive_read_next_header(read, &entry) == ARCHIVE_OK) {
+ const char *entry_path = archive_entry_pathname(entry);
+
+ struct url fullpath = {0};
+ url_copy(out_dir, &fullpath);
+ url_append(&fullpath, entry_path);
+
+ archive_entry_set_pathname(entry, fullpath.buffer);
+
+ archive_write_header(disk, entry);
+
+ const void *buf;
+ size_t len;
+ off_t offset;
+
+ while(archive_read_data_block(read, &buf, &len, &offset) == ARCHIVE_OK)
+ archive_write_data_block(disk, buf, len, offset);
+
+ archive_write_finish_entry(disk);
+ url_free(&fullpath);
+ }
+
+ archive_free(disk);
+ archive_free(read);
+
+ return SUCCESS;
+}
diff --git a/src/lib/url.c b/src/lib/url.c
new file mode 100644
index 0000000..7a15558
--- /dev/null
+++ b/src/lib/url.c
@@ -0,0 +1,91 @@
+#include <lib/url.h>
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+
+//TODO: Audit this implementation. Potentially an arena alloc?
+
+int url_init(struct url *url, char *base)
+{
+ assert(url != NULL);
+
+ size_t len = strlen(base) + 1;
+ void *ptr = malloc(len);
+
+ if (ptr == NULL)
+ return -URLINITERR;
+
+ url->buffer = ptr;
+ memcpy(url->buffer, base, len);
+ url->len = len;
+ url->buffer[url->len - 1] = '\0';
+
+ return SUCCESS;
+}
+
+void url_free(struct url *url)
+{
+ assert(url != NULL);
+ free(url->buffer);
+}
+
+
+int url_copy(struct url *from, struct url *to)
+{
+ assert(from != NULL);
+ assert(to != NULL);
+
+ to->buffer = malloc(from->len);
+ if(to->buffer == NULL)
+ return -ERR;
+
+ memcpy(to->buffer, from->buffer, from->len);
+
+ to->len = from->len;
+ return SUCCESS;
+}
+
+int url_append(struct url *url, const char *add)
+{
+ assert(url != NULL);
+ assert(add != NULL);
+
+ if (url->buffer == NULL || url->len < 8) {
+ return -URLPATHERR;
+ }
+
+ url->len--;
+ size_t addlen = strlen(add);
+ size_t nlen = url->len + addlen + 1;
+
+ url->buffer = realloc(url->buffer, nlen);
+
+ memcpy(url->buffer + url->len, add, addlen);
+
+ url->len = nlen;
+ url->buffer[url->len - 1] = '\0';
+}
+
+int url_append_path(struct url *url, const char *add)
+{
+ assert(url != NULL);
+ assert(add != NULL);
+
+ if (url->buffer == NULL || url->len < 8) {
+ return -URLPATHERR;
+ }
+
+ url->buffer[url->len - 1] = '/'; //TODO: Check existence of "/"
+ size_t addlen = strlen(add);
+ size_t nlen = url->len + addlen + 1;
+
+ url->buffer = realloc(url->buffer, nlen);
+
+ memcpy(url->buffer + url->len, add, addlen);
+
+ url->len = nlen;
+ url->buffer[url->len - 1] = '\0';
+}
diff --git a/src/main.c b/src/main.c
index 4ed2ff4..c866c89 100644
--- a/src/main.c
+++ b/src/main.c
@@ -2,12 +2,17 @@
#include <string.h>
#include <stdlib.h>
+#include <zstd.h>
+#include <stdio.h>
+#include <sodium.h>
+#include <pkgman.h>
#include <um.h>
#include <err.h>
#include <parser.h>
#include <lib/sv.h>
#include <net.h>
+#include <lib/url.h>
/**
* Install package:
@@ -19,7 +24,10 @@
* Update:
* pkgman update
* pkgman update <package_name>
- *
+ *
+ * Kernel Update:
+ * pkgman kupdate
+ *
* Fetch:
* pkgman fetch <query>
*
@@ -40,59 +48,36 @@ void install_usage()
int cmd_install(int argc, char **argv)
{
- if(argc < 1) {
- install_usage();
- return USAGE;
- }
-
- int ret = 1;
-
- struct memory mem = { 0 };
- net_send_request("https://packages.0xinfinity.dev/list", &mem, WRITE_OPT_MEMORY);
-
- struct um_user_data userdata = { 0 };
- struct parser parser;
- struct parser_backend backend = um_backend();
-
- parser_init(&parser, &mem, &backend, (void*)&userdata);
- parser_parse(&parser);
-
- struct string_view pkg = sv_create(argv[0], strlen(argv[0]));
+ if (argc < 1) {
+ install_usage();
+ return USAGE;
+ }
+
+ char *pkg = argv[0];
+
+ int ret = pkgman_upstream_check(pkg);
+
+ if (ret != SUCCESS)
+ return -PKGNOTFND;
+
+ ret = pkgman_upstream_integrity_download(pkg);
- int found = 0;
+ if (ret != SUCCESS)
+ return ret;
- LL_FOREACH(manifest, &userdata.manifest) {
- if (!current->data.key.buf)
- continue;
+ ret = pkgman_install_pkg(pkg);
- if (sv_equal(&pkg, &current->data.key))
- found = 1;
- }
-
- if (!found) {
- printf("Package '%s' not found!\n",argv[0]);
- ret = -PKGNOTFND;
- goto cleanup;
- }
-
- printf("Package '%s' found on upstream!\n", argv[0]);
- ret = SUCCESS;
-
-cleanup:
- // clean LL items
- LL_FOREACH(manifest, &userdata.manifest) {
- if (current->data.key.buf == NULL)
- continue;
-
- free(current->data.key.buf);
- free(current->data.value.buf);
- }
-
- ll_manifest_free(&userdata.manifest);
+ if (ret != SUCCESS)
+ return ret;
- free(mem.buffer);
+ return SUCCESS;
+}
- return ret;
+int cmd_build(int argc, char** argv)
+{
+ // ZSTD_compress("test", 60, "aaa.pkg", 30, 3);
+ printf("Produced a tar file!");
+ return SUCCESS;
}
typedef int (*cmd_fn)(int, char**);
@@ -105,6 +90,7 @@ struct cmd_entry
// First-level command table
struct cmd_entry table[] = {
+ { SV("build"), cmd_build },
{ SV("install"), cmd_install },
{ SV(NULL), NULL },
};
@@ -118,6 +104,7 @@ void usage()
printf("-------------------------------\n");
printf("Available commands:\n");
printf(" pkgman install <pkg>\n");
+ printf(" pkgman build\n");
printf(" pkgman update <pkg?>\n");
}
@@ -130,11 +117,13 @@ int main(int argc, char **argv)
cmd_fn cmd_func = NULL;
- struct string_view argv1 = SV(argv[1]);
+ struct string_view argv1 = (struct string_view)
+ {.buf = argv[1], .len = strlen(argv[1])};
for (int i = 0; i < ARRAY_SIZE(table); i++) {
if (table[i].key.buf == NULL)
break;
+
if (sv_equal(&argv1, &table[i].key))
cmd_func = table[i].func;
}
diff --git a/src/net.c b/src/net.c
index 6f14089..6d566f2 100644
--- a/src/net.c
+++ b/src/net.c
@@ -6,83 +6,90 @@
#include <curl/curl.h>
#include <stdlib.h>
-size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
+size_t write_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
{
- assert(ptr != NULL);
- assert(userdata != NULL);
+ assert(ptr != NULL);
+ assert(userdata != NULL);
- struct memory *chunk = (struct memory*)userdata;
- size_t nsize = chunk->size + nmemb;
+ struct net_write_data *chunk = (struct net_write_data*)userdata;
+ size_t nsize = chunk->size + nmemb;
- chunk->buffer = realloc(chunk->buffer, nsize);
+ chunk->buffer = realloc(chunk->buffer, nsize);
- if (nsize > chunk->size)
- memcpy(&chunk->buffer[chunk->size], ptr, nmemb);
+ if (nsize > chunk->size)
+ memcpy(&chunk->buffer[chunk->size], ptr, nmemb);
- chunk->size = nsize;
+ chunk->size = nsize;
- return nmemb;
+ return nmemb;
}
size_t write_file_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
{
- assert(ptr != NULL);
- assert(ptr != NULL);
+ assert(ptr != NULL);
+ assert(ptr != NULL);
+
+ struct net_file_write_data * user =
+ (struct net_file_write_data*)userdata;
+
+ if (user->file == NULL) {
+ fprintf(stderr, "net: Write failed, "
+ "file stream could not be found!\n");
+ return 0;
+ }
- struct net_fwrite_userdata *user = (struct net_fwrite_userdata*)userdata;
-
- if (user->file == NULL) {
- fprintf(stderr, "net: Write failed, file stream could not be found!\n");
- return 0;
- }
-
- return fwrite(ptr, nmemb, 1, user->file);
+ return fwrite(ptr, size, nmemb, user->file);
}
int net_init()
{
- CURLcode result = curl_global_init(CURL_GLOBAL_ALL);
- if (result != CURLE_OK)
- return -NETINITERR;
- return 0;
+ CURLcode result = curl_global_init(CURL_GLOBAL_ALL);
+ if (result != CURLE_OK)
+ return -NETINITERR;
+ return SUCCESS;
}
void net_shutdown()
{
- curl_global_cleanup();
+ curl_global_cleanup();
}
-int net_send_request(char *url, struct memory *mem, int write_opts)
+int net_send_request(char *url, int write_opts, void* userdata)
{
- assert(mem != NULL);
- CURL *curl;
- curl = curl_easy_init();
- if (!curl)
- return -CONINITERR;
-
- curl_easy_setopt(curl, CURLOPT_URL, url);
+ assert(url != NULL);
+ assert(userdata != NULL);
+ CURL *curl;
+ curl = curl_easy_init();
+
+ if (!curl)
+ return -CONINITERR;
- if (write_opts == WRITE_OPT_MEMORY)
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
- else if (write_opts == WRITE_OPT_FILE)
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_file_cb);
- else {
- fprintf(stderr, "net: a valid write_opts must be specified! current: %d", write_opts);
- }
-
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)mem);
- curl_easy_setopt(curl, CURLOPT_CA_CACHE_TIMEOUT, 604800L);
-
- CURLcode result;
- result = curl_easy_perform(curl);
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+
+ if (write_opts == WRITE_OPT_MEMORY) {
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
+ } else if (write_opts == WRITE_OPT_FILE) {
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_file_cb);
+ } else {
+ fprintf(stderr, "net: a valid write_opts must be specified! "
+ "current: %d",
+ write_opts);
+ return -CONINITERR;
+ }
+
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, userdata);
+ curl_easy_setopt(curl, CURLOPT_CA_CACHE_TIMEOUT, 604800L);
+
+ CURLcode result;
+ result = curl_easy_perform(curl);
- if (result != CURLE_OK) {
- fprintf(stderr, "curl_easy_perform() failed: %s\n",
- curl_easy_strerror(result));
- return -(CONREQERR + result);
- }
+ if (result != CURLE_OK) {
+ fprintf(stderr, "curl_easy_perform() failed: %s\n",
+ curl_easy_strerror(result));
+ return -(CONREQERR + result);
+ }
- curl_easy_cleanup(curl);
+ curl_easy_cleanup(curl);
- return 0;
+ return SUCCESS;
}
diff --git a/src/parser.c b/src/parser.c
index c195764..602de51 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -87,7 +87,7 @@ void skip_whitespace(struct parser *parser)
}
int parser_init(struct parser *parser,
- struct memory *mem,
+ struct string_view *mem,
struct parser_backend *backend,
void *userdata)
{
@@ -98,12 +98,12 @@ int parser_init(struct parser *parser,
if ((backend->on_block_start == NULL) ||
(backend->on_block_end == NULL) ||
(backend->on_kv == NULL) ||
- (mem->buffer == NULL))
+ (mem->buf == NULL))
return -PARINITERR;
parser->pos = 0;
- parser->src = mem->buffer;
- parser->len = mem->size;
+ parser->src = mem->buf;
+ parser->len = mem->len;
parser->state = PARSER_STATE_GRACEFUL;
parser->backend = backend;
parser->userdata = userdata;
@@ -122,13 +122,15 @@ int parser_parse(struct parser *parser)
char nc = parser_peek(parser, 1);
if (c == '[' && nc == '/')
- parser_parse_block_end(parser);
+ parser_parse_block_end(parser);
else if (c == '[')
- parser_parse_block_start(parser);
+ parser_parse_block_start(parser);
else if (c == '-')
- parser_parse_kv(parser);
+ parser_parse_kv(parser);
+ /* else if (c == '+') */
+ /* parser_parse_blocklist(parser); */
else
- parser_advance(parser, 1);
+ parser_advance(parser, 1);
}
if (parser->state == PARSER_STATE_ERROR)
@@ -224,3 +226,12 @@ void parser_parse_kv(struct parser *parser)
struct string_view value = sv_create(&parser->src[valpos], vallen);
parser->backend->on_kv(&key, &value, parser->userdata);
}
+
+/* void parser_parse_blocklist(struct parser *parser) */
+/* { */
+/* assert(parser != NULL); */
+
+
+
+/* /\* parser->backend->on_blocklist(&value, parser->userdata); *\/ */
+/* } */
diff --git a/src/pkgman.c b/src/pkgman.c
new file mode 100644
index 0000000..c21d0c5
--- /dev/null
+++ b/src/pkgman.c
@@ -0,0 +1,222 @@
+#include <pkgman.h>
+
+#include <net.h>
+#include <parser.h>
+#include <um.h>
+#include <lib/sv.h>
+#include <err.h>
+#include <lib/url.h>
+#include <lib/archive.h>
+#include <cookbook.h>
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <gpgme.h>
+#include <archive.h>
+#include <archive_entry.h>
+
+#define UPSTREAM_URL "https://packages.0xinfinity.dev"
+
+int pkgman_upstream_check(const char *pkg)
+{
+ assert(pkg != NULL);
+
+ int ret = -ERR;
+
+ struct net_write_data mem = { 0 };
+ if ((ret = net_send_request(UPSTREAM_URL "/list",
+ WRITE_OPT_MEMORY,
+ (void*)&mem)) != SUCCESS)
+ goto cleanup;
+
+ struct um_user_data userdata = { 0 };
+ struct parser parser;
+ struct parser_backend backend = um_backend();
+ struct string_view parser_src = {0};
+ parser_src.buf = mem.buffer;
+ parser_src.len = mem.size;
+
+ parser_init(&parser, &parser_src, &backend, (void*)&userdata);
+ parser_parse(&parser);
+
+ struct string_view sv_pkg = sv_create(pkg, strlen(pkg));
+
+ int found = 0;
+
+ LL_FOREACH(manifest, &userdata.manifest) {
+ if (!current->data.key.buf)
+ continue;
+
+ if (sv_equal(&sv_pkg, &current->data.key)) {
+ found = 1;
+ printf("Package '%s' found on upstream!\n", pkg);
+ ret = SUCCESS;
+ }
+ }
+
+ if (!found) {
+ printf("Package '%s' not found!\n", pkg);
+ ret = -PKGNOTFND;
+ }
+
+
+ LL_FOREACH(manifest, &userdata.manifest) {
+ if (current->data.key.buf == NULL)
+ continue;
+
+ free(current->data.key.buf);
+ free(current->data.value.buf);
+ }
+
+ ll_manifest_free(&userdata.manifest);
+
+ cleanup:
+ free(mem.buffer);
+
+ return ret;
+}
+
+int pkgman_download(const char *url, const char *dst)
+{
+ struct net_file_write_data fwdata;
+
+ printf("url: %s, dst: %s\n", url, dst);
+
+ fwdata.file = fopen(dst, "w"); // change to tmp dir
+
+ if (!fwdata.file) {
+ return -PKGNOTFND;
+ }
+
+ net_send_request(url, WRITE_OPT_FILE, (void*)&fwdata);
+
+ fclose(fwdata.file);
+ return SUCCESS;
+}
+
+int pkgman_install_pkg(const char *pkg)
+{
+ struct url path = {0};
+ url_init(&path, "/tmp/pkgman");
+ url_append_path(&path, pkg);
+
+ struct url dst_path = {0};
+ url_init(&dst_path, "/tmp/pkgman");
+ url_append_path(&dst_path, pkg);
+ url_append(&dst_path, "-extract/");
+
+ mkdir(dst_path.buffer, 0777);
+
+ pkg_extract(path.buffer, &dst_path);
+
+ cookbook_run(&dst_path, "artifacts");
+ cookbook_run(&dst_path, "install");
+
+ url_free(&dst_path);
+ url_free(&path);
+ return SUCCESS;
+}
+
+int pkgman_upstream_integrity_download(const char *pkg)
+{
+ int ret = -ERR;
+ struct url url_pkg = {0};
+ struct url url_sig = {0};
+
+ url_init(&url_pkg, UPSTREAM_URL);
+ url_append_path(&url_pkg, pkg);
+ url_append(&url_pkg, ".tar.zstd");
+
+ url_copy(&url_pkg, &url_sig);
+ url_append(&url_sig, ".sig");
+
+ struct url path_pkg = {0};
+ struct url path_sig = {0};
+
+ url_init(&path_pkg, "/tmp/pkgman");
+ url_append_path(&path_pkg, pkg);
+
+ url_copy(&path_pkg, &path_sig);
+ url_append(&path_sig, ".sig");
+
+ ///// I need to abstract away the cache filemgmt feature in the future.
+
+ mkdir("/tmp/pkgman/", 0777);
+
+ ////
+
+ if(pkgman_download(url_pkg.buffer, path_pkg.buffer) != SUCCESS) {
+ ret = -PKGNOTFND;
+ goto cleanup;
+ }
+
+ printf("'%s' package downloaded.\n", pkg);
+
+ // Download signature file
+ if(pkgman_download(url_sig.buffer, path_sig.buffer) != SUCCESS) {
+ ret = -PKGNOTFND;
+ goto cleanup;
+ }
+
+ printf("Signature for '%s' downloaded.\n", url_sig.buffer);
+
+ // Verify integrity
+
+ gpgme_check_version(NULL);
+
+ gpgme_ctx_t ctx;
+
+ gpgme_new(&ctx);
+ gpgme_set_protocol(ctx, GPGME_PROTOCOL_OPENPGP);
+
+ int fd = open(path_pkg.buffer, O_RDONLY);
+ int sigfd = open(path_sig.buffer, O_RDONLY);
+
+ gpgme_data_t file;
+ gpgme_data_t sig;
+
+ gpgme_data_new_from_fd(&file, fd);
+ gpgme_data_new_from_fd(&sig, sigfd);
+
+ if (gpgme_op_verify(ctx, sig, file, NULL) == GPG_ERR_NO_ERROR) {
+ printf("Signature operation ran successfully.\n");
+ } else {
+ printf("Integrity verification failed!\n");
+ ret = -INTEGRITYERR;
+ gpgme_release(ctx);
+ goto cleanup;
+ }
+
+
+ gpgme_verify_result_t integ_res = gpgme_op_verify_result(ctx);
+
+ // Checking the first signature for now should be fine.
+ //TODO: Revisit this.
+ if ((integ_res->signatures->summary & GPGME_SIGSUM_VALID) &&
+ (integ_res->signatures->status == GPG_ERR_NO_ERROR)) {
+ printf("Integrity check successful, "
+ "package can be installed.\n");
+ } else {
+ printf("Signature invalid!\n");
+ ret = -INTEGRITYERR;
+ gpgme_release(ctx);
+ goto cleanup;
+ }
+
+ ret = SUCCESS;
+
+ gpgme_release(ctx);
+
+ cleanup:
+
+ url_free(&url_pkg);
+ url_free(&url_sig);
+
+ url_free(&path_pkg);
+ url_free(&path_sig);
+
+ return ret;
+}