From 839bcb47bf20f22d4550ea46bd5ad5989dc741e0 Mon Sep 17 00:00:00 2001 From: ngn Date: Thu, 11 Jul 2024 07:31:36 +0300 Subject: [PATCH] new: implement check and update functions --- examples/Makefile | 14 +++- examples/client/check.c | 45 +++++++++++++ examples/client/list.c | 28 ++++++++ examples/client/update.c | 60 +++++++++++++++++ include/ctx.h | 25 ++++--- include/error.h | 5 ++ include/package.h | 2 + include/util.h | 13 ++-- locale/tr/LC_MESSAGES/libmp.po | 25 ++++++- src/ctx/check.c | 65 +++++++++++++++++++ src/ctx/database.c | 20 ++++-- src/ctx/install.c | 2 +- src/ctx/remove.c | 1 + src/ctx/update.c | 115 +++++++++++++++++++++++++-------- src/database/files.c | 1 + src/database/package.c | 4 +- src/error.c | 5 ++ src/package/package.c | 28 ++++++++ src/package/path.c | 12 ++++ src/util.c | 38 +++++++++++ 20 files changed, 456 insertions(+), 52 deletions(-) create mode 100644 examples/client/check.c create mode 100644 examples/client/list.c create mode 100644 examples/client/update.c create mode 100644 src/ctx/check.c diff --git a/examples/Makefile b/examples/Makefile index 639ad42..1371784 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,6 +1,6 @@ CC = gcc -all: ../dist/client_install ../dist/client_remove ../dist/server +all: ../dist/client_install ../dist/client_remove ../dist/client_update ../dist/client_check ../dist/client_list ../dist/server ../dist/client_install: client/install.c client/*.h ../dist/libmp.so mkdir -pv ../dist @@ -10,6 +10,18 @@ all: ../dist/client_install ../dist/client_remove ../dist/server mkdir -pv ../dist $(CC) -L../dist $< -lmp -o $@ +../dist/client_update: client/update.c client/*.h ../dist/libmp.so + mkdir -pv ../dist + $(CC) -L../dist $< -lmp -o $@ + +../dist/client_check: client/check.c client/*.h ../dist/libmp.so + mkdir -pv ../dist + $(CC) -L../dist $< -lmp -o $@ + +../dist/client_list: client/list.c client/*.h ../dist/libmp.so + mkdir -pv ../dist + $(CC) -L../dist $< -lmp -o $@ + ../dist/server: server/*.c ../dist/libmp.so mkdir -pv ../dist $(CC) -L../dist $< -lmp -o $@ diff --git a/examples/client/check.c b/examples/client/check.c new file mode 100644 index 0000000..8b2ba1e --- /dev/null +++ b/examples/client/check.c @@ -0,0 +1,45 @@ +#include "../../include/all.h" +#include "./common.h" + +#include +#include +#include + +int main(int argc, char *argv[]) { + int ret = EXIT_FAILURE; + lm_pkg_t pkg; + lm_ctx_t ctx; + + lm_package_init(&pkg); + + if (argc != 2) { + printf("usage: %s \n", argv[0]); + return ret; + } + + lm_ctx_init(&ctx); + + if (!lm_ctx_set_data(&ctx, DATA_DIR)) { + printf("failed to set data dir: %s (%d)\n", lm_strerror(), lm_error()); + goto end; + } + + if (!lm_ctx_database_find(&ctx, &pkg, argv[1], NULL)) { + printf("failed to find package: %s (%d)\n", lm_strerror(), lm_error()); + goto end; + } + + printf("checking %s (%s)...\n", pkg.name, pkg.version); + + if (!lm_ctx_check(&ctx, &pkg, NULL, NULL)) { + printf("failed to verify the package: %s (%d)\n", lm_strerror(), lm_error()); + goto end; + } + + ret = EXIT_SUCCESS; + +end: + lm_package_free(&pkg); + lm_ctx_free(&ctx); + return ret; +} diff --git a/examples/client/list.c b/examples/client/list.c new file mode 100644 index 0000000..e2e916a --- /dev/null +++ b/examples/client/list.c @@ -0,0 +1,28 @@ +#include "../../include/all.h" +#include "./common.h" + +#include +#include +#include + +int main(int argc, char *argv[]) { + lm_ctx_t ctx; + lm_pkg_t pkg; + int ret = EXIT_FAILURE; + + lm_ctx_init(&ctx); + + if (!lm_ctx_set_data(&ctx, DATA_DIR)) { + printf("failed to set data dir: %s (%d)\n", lm_strerror(), lm_error()); + goto end; + } + + printf("listing installed packages:\n"); + + while (lm_ctx_database_next(&ctx, &pkg)) + printf("%s (%s)\n", pkg.name, pkg.version); + +end: + lm_ctx_database_next_free(&ctx, &pkg); + return ret; +} diff --git a/examples/client/update.c b/examples/client/update.c new file mode 100644 index 0000000..36dd8e5 --- /dev/null +++ b/examples/client/update.c @@ -0,0 +1,60 @@ +#include "../../include/all.h" +#include "./common.h" + +#include +#include +#include + +int main(int argc, char *argv[]) { + lm_ctx_update_list_t *list = NULL; + int ret = EXIT_FAILURE; + lm_pkg_t pkg, *cur = NULL; + lm_ctx_t ctx; + + if (!mkdir_ifnot(ROOT_DIR)) { + printf("failed to create root dir: %s\n", ROOT_DIR); + return ret; + } + + lm_ctx_init(&ctx); + + if (!lm_ctx_set_data(&ctx, DATA_DIR)) { + printf("failed to set data dir: %s (%d)\n", lm_strerror(), lm_error()); + goto end; + } + + if (!lm_ctx_set_temp(&ctx, TEMP_DIR)) { + printf("failed to set temp dir: %s (%d)\n", lm_strerror(), lm_error()); + goto end; + } + + if (!lm_ctx_set_root(&ctx, ROOT_DIR)) { + printf("failed to set root dir: %s (%d)\n", lm_strerror(), lm_error()); + goto end; + } + + if ((list = lm_ctx_update_list(&ctx)) == NULL) { + printf("failed to get update list: %s (%d)", lm_strerror(), lm_error()); + goto end; + } + + if (list->count == 0) { + printf("all packages are up-to-date\n"); + goto end; + } + + while ((cur = lm_ctx_update_list_next(list)) != NULL) { + printf("updating %s (%s)...\n", cur->name, cur->version); + if (!lm_ctx_update(&ctx, cur, NULL, NULL)) { + printf("failed to update package: %s\n", lm_strerror()); + goto end; + } + } + + ret = EXIT_SUCCESS; + +end: + lm_ctx_update_list_free(list); + lm_ctx_free(&ctx); + return ret; +} diff --git a/include/ctx.h b/include/ctx.h index a756ebf..52032cd 100644 --- a/include/ctx.h +++ b/include/ctx.h @@ -21,9 +21,9 @@ typedef struct lm_ctx_resolve_list { } lm_ctx_resolve_list_t; typedef struct lm_ctx_update_list { - lm_pkg_t **packages; - size_t count; - size_t index; + lm_pkg_t *packages; + lm_pkg_t *cur; + size_t count; } lm_ctx_update_list_t; typedef enum lm_ctx_sync_state { @@ -35,6 +35,11 @@ typedef enum lm_ctx_sync_state { SYNC_LIST_FAIL = 5, } lm_ctx_sync_state_t; +typedef enum lm_ctx_update_state { + UPDATE_REMOVE = 0, + UPDATE_INSTALL = 1, +} lm_ctx_update_state_t; + /* ################### ## ctx callbacks ## ################### */ @@ -43,6 +48,8 @@ typedef bool (*lm_ctx_download_callback_t)( lm_ctx_t *ctx, lm_pkg_t *pkg, bool is_archive, size_t current, size_t total, void *data); typedef bool (*lm_ctx_install_callback_t)( lm_ctx_t *ctx, lm_pkg_t *pkg, char *file, size_t current, size_t total, void *data); +typedef bool (*lm_ctx_update_callback_t)( + lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_update_state_t state, char *file, size_t current, size_t total, void *data); typedef bool (*lm_ctx_sync_callback_t)( lm_ctx_t *ctx, lm_pool_t *pool, lm_ctx_sync_state_t state, size_t current, size_t total, void *data); typedef bool (*lm_ctx_ping_callback_t)(lm_ctx_t *ctx, lm_pool_t *pool, bool status, void *data); @@ -66,9 +73,11 @@ lm_ctx_resolve_list_t *lm_ctx_resolve( lm_pkg_t *lm_ctx_resolve_next(lm_ctx_resolve_list_t *list); // returns the next package in the list void lm_ctx_resolve_free(lm_ctx_resolve_list_t *list); // frees the resolved list returned by lm_ctx_resolve -lm_ctx_update_list_t *lm_ctx_update(lm_ctx_t *ctx); // returns a list of packages to update -lm_pkg_t *lm_ctx_update_next(lm_ctx_update_list_t *list); // returns the next package in the list -void lm_ctx_update_free(lm_ctx_update_list_t *list); // frees the update list returned by lm_ctx_update +lm_ctx_update_list_t *lm_ctx_update_list(lm_ctx_t *ctx); // get a list of packages to update +lm_pkg_t *lm_ctx_update_list_next(lm_ctx_update_list_t *list); // get the next package in the update list +void lm_ctx_update_list_free(lm_ctx_update_list_t *list); // free the update list +bool lm_ctx_update(lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_update_callback_t callback, + void *data); // returns a list of packages to update bool lm_ctx_download(lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_download_callback_t callback, void *data); // downloads a single package @@ -98,5 +107,5 @@ lm_pool_t *lm_ctx_pool_by_url(lm_ctx_t *ctx, char *host, char *path); // find p bool lm_ctx_database_init(lm_ctx_t *ctx); // init ctx database (if not already present) bool lm_ctx_database_is_installed(lm_ctx_t *ctx, lm_pkg_t *pkg, bool check_version); // check if a package is installed bool lm_ctx_database_find(lm_ctx_t *ctx, lm_pkg_t *pkg, char *name, char *version); // find a package by name -bool lm_ctx_database_foreach( - lm_ctx_t *ctx, lm_ctx_database_callback_t callback, void *data); // loop for each package in the database +bool lm_ctx_database_next(lm_ctx_t *ctx, lm_pkg_t *pkg); // load the next package into pkg pointer +bool lm_ctx_database_next_free(lm_ctx_t *ctx, lm_pkg_t *pkg); // free the used next pointers diff --git a/include/error.h b/include/error.h index 7916b0f..d7981ec 100644 --- a/include/error.h +++ b/include/error.h @@ -133,6 +133,11 @@ typedef enum lm_error { LM_ERR_InstallStatusFail = 125, LM_ERR_InstallScriptFail = 126, LM_ERR_PkgBreaks = 127, + LM_ERR_PkgUpToDate = 128, + LM_ERR_HashOpenFail = 129, + LM_ERR_HashDigestFail = 130, + LM_ERR_FileHashFail = 131, + LM_ERR_FileHashNoMatch = 132, } lm_error_t; typedef struct lm_error_desc { diff --git a/include/package.h b/include/package.h index fe5dbe8..3bac9f1 100644 --- a/include/package.h +++ b/include/package.h @@ -12,6 +12,7 @@ lm_pkg_t *lm_package_new(); void lm_package_free(lm_pkg_t *pkg); bool lm_package_verify(lm_pkg_t *pkg); void lm_package_init(lm_pkg_t *pkg); +bool lm_package_copy(lm_pkg_t *dst, lm_pkg_t *src); bool lm_package_data_load(lm_pkg_t *pkg, char *file); void lm_package_data_free(lm_pkg_t *pkg); @@ -34,4 +35,5 @@ bool lm_package_path_set_signature(lm_pkg_t *pkg, char *signature_path); bool lm_package_path_set_archive(lm_pkg_t *pkg, char *archive_path); bool lm_package_path_is_empty(lm_pkg_t *pkg); void lm_package_path_free(lm_pkg_t *pkg); +bool lm_package_path_copy(lm_pkg_t *dst, lm_pkg_t *src); bool lm_package_is_same(lm_pkg_t *one, lm_pkg_t *two); diff --git a/include/util.h b/include/util.h index de8a08c..4350b34 100644 --- a/include/util.h +++ b/include/util.h @@ -16,12 +16,13 @@ bool is_digit(char c); bool copy_from_buffer(void *dst, void *buffer, size_t size, ssize_t *total, ssize_t *used); bool copy_to_buffer(void *buffer, void *src, size_t size, ssize_t *total, ssize_t *used); -bool copy_file(char *dst, char *src); -bool can_write(char *path); -bool can_read(char *path); -bool is_file(char *path); -bool is_dir(char *path); -bool exists(char *path); +char *get_md5(char *path); +bool copy_file(char *dst, char *src); +bool can_write(char *path); +bool can_read(char *path); +bool is_file(char *path); +bool is_dir(char *path); +bool exists(char *path); bool package_parse(char *package, char *name, char *version); bool package_version_valid(char *name); diff --git a/locale/tr/LC_MESSAGES/libmp.po b/locale/tr/LC_MESSAGES/libmp.po index cf01fb2..f321d97 100644 --- a/locale/tr/LC_MESSAGES/libmp.po +++ b/locale/tr/LC_MESSAGES/libmp.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-07-10 16:36+0300\n" +"POT-Creation-Date: 2024-07-11 07:30+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -559,3 +559,26 @@ msgstr "" #, c-format msgid "removing package breaks %s" msgstr "" + +#: src/error.c:153 +#, fuzzy +msgid "package is already up-to-date" +msgstr "URL hostname is too large" + +#: src/error.c:154 +msgid "failed to open file for hashing" +msgstr "" + +#: src/error.c:155 +msgid "failed create digest for hashing" +msgstr "" + +#: src/error.c:156 +#, c-format +msgid "failed to get hash of %s: %s" +msgstr "" + +#: src/error.c:157 +#, c-format +msgid "file hash does not match for %s" +msgstr "" diff --git a/src/ctx/check.c b/src/ctx/check.c new file mode 100644 index 0000000..4d1ac39 --- /dev/null +++ b/src/ctx/check.c @@ -0,0 +1,65 @@ +#include "../../include/error.h" +#include "../../include/util.h" +#include "../../include/ctx.h" + +#include +#include +#include + +bool lm_ctx_check(lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_check_callback_t callback, void *data){ + if(NULL == ctx || NULL == pkg){ + lm_error_set(LM_ERR_ArgNULL); + return false; + } + + if(NULL == ctx->root){ + lm_error_set(LM_ERR_CtxRootNULL); + return false; + } + + if(!lm_ctx_database_init(ctx)) + return false; // error set by function + + size_t rootlen = strlen(ctx->root), current = 0, total = 0; + char *path = NULL, *hash = NULL, *fhash = NULL; + bool keep = false, ret = false; + + total = lm_database_files_count(ctx->db, pkg); + + while(lm_database_files_next(ctx->db, pkg, &path, &hash, &keep)){ + char fp[rootlen+strlen(path)+10]; + join(fp, ctx->root, path); + current++; + + if(NULL != callback) + if(!callback(ctx, pkg, fp, current, total, data)) + goto end; + + if(!exists(fp)){ + pdebug(__func__, "skipping %s because file does not exists", fp); + continue; + } + + if((fhash = get_md5(fp)) == NULL){ + char *suberr = lm_strerror_dup(); + pdebug(__func__, "failed to get hash of %s: %s", fp, suberr); + lm_error_set(LM_ERR_FileHashFail, fp, suberr); + free(suberr); + goto end; + } + + if(!eq(fhash, hash)){ + lm_error_set(LM_ERR_FileHashNoMatch, fp); + goto end; + } + + free(fhash); + fhash = NULL; + } + + ret = true; +end: + lm_database_files_next_free(ctx->db, pkg, &path, &hash, &keep); + free(fhash); + return ret; +} diff --git a/src/ctx/database.c b/src/ctx/database.c index 97cafa3..5eea083 100644 --- a/src/ctx/database.c +++ b/src/ctx/database.c @@ -39,8 +39,8 @@ bool lm_ctx_database_find(lm_ctx_t *ctx, lm_pkg_t *pkg, char *name, char *versio return lm_database_package_find(ctx->db, pkg, name, version); } -bool lm_ctx_database_foreach(lm_ctx_t *ctx, lm_ctx_database_callback_t callback, void *data){ - if(NULL == ctx || NULL == callback){ +bool lm_ctx_database_next(lm_ctx_t *ctx, lm_pkg_t *pkg){ + if(NULL == ctx || NULL == pkg){ lm_error_set(LM_ERR_ArgNULL); return false; } @@ -48,12 +48,18 @@ bool lm_ctx_database_foreach(lm_ctx_t *ctx, lm_ctx_database_callback_t callback, if(!lm_ctx_database_init(ctx)) return false; // error set by function - lm_pkg_t pkg; + return lm_database_package_next(ctx->db, pkg); +} - while(lm_database_package_next(ctx->db, &pkg)){ - if(!callback(ctx, &pkg, data)) - break; +bool lm_ctx_database_next_free(lm_ctx_t *ctx, lm_pkg_t *pkg){ + if(NULL == ctx || NULL == pkg){ + lm_error_set(LM_ERR_ArgNULL); + return false; } - + + if(!lm_ctx_database_init(ctx)) + return false; // error set by function + + lm_database_package_next_free(ctx->db, pkg); return true; } diff --git a/src/ctx/install.c b/src/ctx/install.c index 56d7f36..5c8c6a0 100644 --- a/src/ctx/install.c +++ b/src/ctx/install.c @@ -170,7 +170,7 @@ bool lm_ctx_install(lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_install_callback_t call return false; } - if(lm_ctx_database_is_installed(ctx, pkg, true)){ + if(lm_ctx_database_is_installed(ctx, pkg, false)){ lm_error_set(LM_ERR_PkgAlreadyInstalled); return false; } diff --git a/src/ctx/remove.c b/src/ctx/remove.c index 8012d41..3404f9c 100644 --- a/src/ctx/remove.c +++ b/src/ctx/remove.c @@ -94,6 +94,7 @@ bool lm_ctx_remove(lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_remove_callback_t callba ret = true; end: + lm_database_package_next_free(ctx->db, &cur); lm_database_files_next_free(ctx->db, pkg, &path, &hash, &in_keep); return ret; } diff --git a/src/ctx/update.c b/src/ctx/update.c index faa60dc..6cbc51e 100644 --- a/src/ctx/update.c +++ b/src/ctx/update.c @@ -8,54 +8,117 @@ #include #include -lm_ctx_update_list_t *lm_ctx_update(lm_ctx_t *ctx){ - lm_ctx_update_list_t *list = malloc(sizeof(lm_ctx_update_list_t)); - list->packages = NULL; - list->index = 0; - list->count = 0; +struct __lm_ctx_update_cb_data { + lm_ctx_update_callback_t callback; + lm_ctx_update_state_t state; + void *data; +}; - if(!lm_ctx_database_init(ctx)) +bool __lm_ctx_update_callback(lm_ctx_t *ctx, lm_pkg_t *pkg, char *file, size_t current, size_t total, void *data){ + struct __lm_ctx_update_cb_data *cbdata = data; + + if(NULL == cbdata->callback) + return true; + + return cbdata->callback(ctx, pkg, cbdata->state, file, current, total, cbdata->data); +} + +lm_ctx_update_list_t *lm_ctx_update_list(lm_ctx_t *ctx){ + if(NULL == ctx){ + lm_error_set(LM_ERR_ArgNULL); return NULL; - - lm_pkg_t *pkg = malloc(sizeof(lm_pkg_t)); - - while(lm_database_package_next(ctx->db, pkg)){ - if(NULL == list->packages) - list->packages = malloc(sizeof(lm_pkg_t*)); - else - list->packages = realloc(list->packages, (list->count+1)*sizeof(lm_pkg_t*)); - - list->packages[list->count++] = pkg; - pkg = malloc(sizeof(lm_pkg_t)); } + lm_ctx_update_list_t *list = malloc(sizeof(lm_ctx_update_list_t)); + lm_pkg_t cur, *new = NULL; + + bzero(list, sizeof(lm_ctx_update_list_t)); + lm_package_init(&cur); + + while(lm_ctx_database_next(ctx, &cur)){ + if((new = lm_ctx_pool_find(ctx, cur.name, NULL)) == NULL) + continue; + + if(eq(new->version, cur.version)) + continue; + + if(NULL == list->packages) + list->packages = malloc(sizeof(lm_pkg_t)); + else + list->packages = realloc(list->packages, (list->count+1)*sizeof(lm_pkg_t)); + lm_package_copy(&list->packages[list->count++], &cur); + } + + lm_ctx_database_next_free(ctx, &cur); return list; } -lm_pkg_t *lm_ctx_update_next(lm_ctx_update_list_t *list){ +lm_pkg_t *lm_ctx_update_list_next(lm_ctx_update_list_t *list){ if(NULL == list){ lm_error_set(LM_ERR_ArgNULL); return NULL; } - if(list->index >= list->count-1){ - list->index = 0; + if(NULL == list->packages) return NULL; + + if(NULL == list->cur) + list->cur = &list->packages[0]; + + for(int i = 0; i < list->count-1; i++){ + if(list->cur != &list->packages[i]) + continue; + list->cur = &list->packages[i+1]; + return list->cur; } - return list->packages[list->index++]; + list->cur = NULL; + return list->cur; } -void lm_ctx_update_free(lm_ctx_update_list_t *list){ +void lm_ctx_update_list_free(lm_ctx_update_list_t *list){ if(NULL == list){ lm_error_set(LM_ERR_ArgNULL); return; } - for(int i = 0; i < list->count; i++){ - lm_package_free(list->packages[i]); - free(list->packages[i]); + if(NULL != list->packages){ + for(int i = 0; i < list->count; i++) + lm_package_free(&list->packages[i]); + free(list->packages); } - + free(list); } + +bool lm_ctx_update(lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_update_callback_t callback, void *data){ + if(NULL == ctx || NULL == pkg){ + lm_error_set(LM_ERR_ArgNULL); + return false; + } + + struct __lm_ctx_update_cb_data cbdata = { + .state = UPDATE_REMOVE, + .callback = callback, + .data = data, + }; + lm_pkg_t *new = NULL; + + if((new = lm_ctx_pool_find(ctx, pkg->name, NULL)) == NULL){ + lm_error_set(LM_ERR_PkgNotFound); + return false; + } + + if(eq(new->version, pkg->version)){ + lm_error_set(LM_ERR_PkgUpToDate); + return false; + } + + if(!lm_ctx_remove(ctx, pkg, __lm_ctx_update_callback, &cbdata)) + return false; // error set by function + + if(!lm_ctx_install(ctx, new, __lm_ctx_update_callback, &cbdata)) + return false; // error set by function + + return true; +} diff --git a/src/database/files.c b/src/database/files.c index fb7498f..6f1c418 100644 --- a/src/database/files.c +++ b/src/database/files.c @@ -227,6 +227,7 @@ bool lm_database_files_next(lm_database_t *db, lm_pkg_t *pkg, char **path, char free(*hash); *path = NULL; *hash = NULL; + *keep = false; } if(sqlite3_step(db->files_st) != SQLITE_ROW){ diff --git a/src/database/package.c b/src/database/package.c index b011455..b97b828 100644 --- a/src/database/package.c +++ b/src/database/package.c @@ -156,6 +156,8 @@ bool lm_database_package_next(lm_database_t *db, lm_pkg_t *pkg){ lm_error_set(LM_ERR_DbSqlPrepareFail); return false; } + + lm_package_init(pkg); if(sqlite3_step(db->packages_st) != SQLITE_ROW){ sqlite3_finalize(db->packages_st); @@ -163,8 +165,6 @@ bool lm_database_package_next(lm_database_t *db, lm_pkg_t *pkg){ return false; } - lm_package_init(pkg); - pkg->name = strdup((char*)sqlite3_column_text(db->packages_st, PACKAGES_COLUMN_NAME-1)); pkg->desc = strdup((char*)sqlite3_column_text(db->packages_st, PACKAGES_COLUMN_DESC-1)); pkg->version = strdup((char*)sqlite3_column_text(db->packages_st, PACKAGES_COLUMN_VERSION-1)); diff --git a/src/error.c b/src/error.c index ba76d29..d55899d 100644 --- a/src/error.c +++ b/src/error.c @@ -150,6 +150,11 @@ void lm_error_set(lm_error_t code, ...) { {.code = LM_ERR_InstallStatusFail, .desc = _("install script returned a bad status code") }, {.code = LM_ERR_InstallScriptFail, .desc = _("failed to run the package install script: %s") }, {.code = LM_ERR_PkgBreaks, .desc = _("removing package breaks %s") }, + {.code = LM_ERR_PkgUpToDate, .desc = _("package is already up-to-date") }, + {.code = LM_ERR_HashOpenFail, .desc = _("failed to open file for hashing") }, + {.code = LM_ERR_HashDigestFail, .desc = _("failed create digest for hashing") }, + {.code = LM_ERR_FileHashFail, .desc = _("failed to get hash of %s: %s") }, + {.code = LM_ERR_FileHashNoMatch, .desc = _("file hash does not match for %s") }, }; char *fmt = NULL; diff --git a/src/package/package.c b/src/package/package.c index 2c5e621..6903147 100644 --- a/src/package/package.c +++ b/src/package/package.c @@ -5,6 +5,7 @@ #include "../../include/util.h" #include +#include #include #include #include @@ -48,12 +49,39 @@ bool lm_package_remove_download(lm_pkg_t *pkg){ } bool lm_package_is_same(lm_pkg_t *one, lm_pkg_t *two){ + if(NULL == one || NULL == two){ + lm_error_set(LM_ERR_ArgNULL); + return false; + } + return eq(one->version, two->version) && eq(one->name, two->name) && eq(one->desc, two->desc) && one->size == two->size; } +bool lm_package_copy(lm_pkg_t *dst, lm_pkg_t *src){ + lm_package_init(dst); + + dst->name = strdup(src->name); + dst->version = strdup(src->version); + dst->desc = strdup(src->desc); + dst->size = src->size; + dst->pool = src->pool; + + if(NULL != src->keeps){ + for(int i = 0; src->keeps[i] != NULL; i++) + lm_package_keep_add(dst, src->keeps[i]); + } + + if(NULL != src->depends){ + for(int i = 0; src->depends[i] != NULL; i++) + lm_package_depend_add(dst, src->depends[i]); + } + + return lm_package_path_copy(dst, src); +} + void lm_package_free(lm_pkg_t *pkg){ lm_package_data_free(pkg); bzero(pkg, sizeof(lm_pkg_t)); diff --git a/src/package/path.c b/src/package/path.c index 4369e7e..4da4ad0 100644 --- a/src/package/path.c +++ b/src/package/path.c @@ -1,4 +1,5 @@ #include "../../include/package.h" +#include "../../include/error.h" #include "../../include/types.h" #include "../../include/util.h" @@ -38,6 +39,17 @@ bool lm_package_path_is_empty(lm_pkg_t *pkg){ NULL == pkg->paths.archive; } +bool lm_package_path_copy(lm_pkg_t *dst, lm_pkg_t *src){ + if(NULL == dst || NULL == src){ + lm_error_set(LM_ERR_ArgNULL); + return false; + } + + dst->paths.archive = strdup(src->paths.archive); + dst->paths.signature = strdup(src->paths.signature); + return true; +} + void lm_package_path_free(lm_pkg_t *pkg){ free(pkg->paths.signature); free(pkg->paths.archive); diff --git a/src/util.c b/src/util.c index 9ae3fda..f90ab42 100644 --- a/src/util.c +++ b/src/util.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -435,3 +436,40 @@ end: return ret; } + +char *get_md5(char *path) { + const EVP_MD *alg = NULL; + EVP_MD_CTX *ctx = NULL; + FILE *file = NULL; + char *sum = NULL, buffer[255]; + unsigned char digest[16]; + unsigned int digest_len; + size_t read = 0; + + alg = EVP_md5(); + bzero(buffer, sizeof(buffer)); + bzero(digest, sizeof(digest)); + + if ((file = fopen(path, "r")) == NULL) { + lm_error_set(LM_ERR_HashOpenFail); + return NULL; + } + + if (EVP_DigestInit_ex(ctx, alg, NULL) <= 0) { + lm_error_set(LM_ERR_HashDigestFail); + return NULL; + } + + while ((read = fread(buffer, sizeof(buffer), 1, file)) > 0) + EVP_DigestUpdate(ctx, buffer, read); + + EVP_DigestFinal(ctx, digest, &digest_len); + EVP_MD_CTX_free(ctx); + + sum = malloc((digest_len * 2) + 1); + + for (int i = 0; i < sizeof(digest); i++) + sprintf(&sum[i * 2], "%02x", (unsigned int)digest[i]); + + return sum; +}