diff --git a/include/ctx.h b/include/ctx.h index d38d27f..849548f 100644 --- a/include/ctx.h +++ b/include/ctx.h @@ -124,3 +124,9 @@ bool lm_ctx_database_next(lm_ctx_t *ctx, lm_entry_t *entry); // load the n bool lm_ctx_database_next_free(lm_ctx_t *ctx, lm_entry_t *entry); // free the used next pointers char *lm_ctx_database_changes( lm_ctx_t *ctx, lm_entry_t *entry); // get changes file path for a package, FREE THE RETURNED POINTER + +/* ####################### + ## package fucntions ## + ####################### */ +bool lm_ctx_package_from(lm_ctx_t *ctx, lm_pkg_t *pkg, char *archive); +void lm_ctx_package_from_free(lm_pkg_t *pkg); diff --git a/include/error.h b/include/error.h index 174fa5e..72363b1 100644 --- a/include/error.h +++ b/include/error.h @@ -144,6 +144,7 @@ typedef enum lm_error { LM_ERR_PoolListBadDir = 142, LM_ERR_FileNotExist = 143, LM_ERR_FileNotLink = 144, + LM_ERR_ArchiveSetFail = 145, } lm_error_t; typedef struct lm_error_desc { diff --git a/include/package.h b/include/package.h index e1b64b6..d215424 100644 --- a/include/package.h +++ b/include/package.h @@ -8,6 +8,12 @@ #define PKG_DATA_DEPENDS "depends" #define PKG_DATA_KEEPS "keeps" +#define DATA_FILE "DATA" +#define HASHES_FILE "HASHES" +#define CHANGES_FILE "CHANGES" +#define INSTALL_FILE "INSTALL" +#define FILES_ARCHIVE "files.tar.gz" + typedef struct lm_pkg_data { char *name; char *desc; @@ -17,6 +23,14 @@ typedef struct lm_pkg_data { ssize_t size; } lm_pkg_data_t; +typedef struct lm_pkg_files { + char *data_file; + char *hashes_file; + char *changes_file; + char *install_file; + char *files_archive; +} lm_pkg_files_t; + typedef struct lm_pkg { struct lm_pkg_data data; struct lm_pool *pool; @@ -51,3 +65,6 @@ void lm_package_data_keep_free(lm_pkg_data_t *data); 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); + +lm_pkg_files_t *lm_package_extract(lm_pkg_t *pkg, char *target); +void lm_package_extract_free(lm_pkg_files_t *files); diff --git a/locale/tr/LC_MESSAGES/libmp.po b/locale/tr/LC_MESSAGES/libmp.po index 7227ab0..280f7dd 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-08-04 18:59+0300\n" +"POT-Creation-Date: 2024-08-06 04:34+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -613,3 +613,7 @@ msgstr "" #, c-format msgid "file is a symbolic link: %s" msgstr "" + +#: src/error.c:164 +msgid "failed to set the package archive" +msgstr "" diff --git a/src/ctx/install.c b/src/ctx/install.c index b6d3245..6060565 100644 --- a/src/ctx/install.c +++ b/src/ctx/install.c @@ -210,7 +210,12 @@ end: } bool lm_ctx_install(lm_ctx_t *ctx, lm_pkg_t *pkg, bool run_install, lm_ctx_install_callback_t callback, void *data) { - if(NULL == ctx->temp || NULL == pkg){ + if(NULL == ctx || NULL == pkg){ + lm_error_set(LM_ERR_ArgNULL); + return false; + } + + if(NULL == ctx->temp){ lm_error_set(LM_ERR_CtxTempNULL); return false; } @@ -238,58 +243,41 @@ bool lm_ctx_install(lm_ctx_t *ctx, lm_pkg_t *pkg, bool run_install, lm_ctx_insta return false; } - lm_ctx_temp_clear(ctx); - - if(!extract_archive(ctx->temp, pkg->archive)) - return false; // error set by function - - size_t bufsize = strlen(ctx->temp) + 25; - char data_file[bufsize], changes_file[bufsize], hashes_file[bufsize]; - char install_file[bufsize], files_archive[bufsize]; - lm_pkg_t temp; - - lm_package_init(&temp); - - join(data_file, ctx->temp, "DATA"); - join(hashes_file, ctx->temp, "HASHES"); - join(changes_file, ctx->temp, "CHANGES"); - join(install_file, ctx->temp, "INSTALL"); - join(files_archive, ctx->temp, "files.tar.gz"); - - if(!exists(data_file, NULL) || !is_file(data_file) || - !exists(hashes_file, NULL) || !is_file(hashes_file) || - !exists(changes_file, NULL) || !is_file(changes_file) || - !exists(install_file, NULL) || !is_file(install_file) || - !exists(files_archive, NULL) || !is_file(files_archive)){ - lm_error_set(LM_ERR_PkgBadArchive); - return false; - } - - if(!lm_package_data_load(&temp.data, data_file)) - return false; // error set by function - - if(!lm_package_is_same(&temp, pkg)){ - pdebug(__func__, "DATA file does not match with stored %s data", pkg->data.name); - lm_error_set(LM_ERR_PkgDataNotMatch); - return false; - } - - if(!lm_database_changes_update(ctx->db, &pkg->data, changes_file)){ - char *suberr = lm_strerror_dup(); - pdebug(__func__, "failed to update changes file for %s: %s", pkg->data.name, suberr); - lm_error_set(LM_ERR_PkgChangesUpdateFail, suberr); - return false; - } - + lm_pkg_files_t *files; char *line = NULL, *hash = NULL, *file = NULL; ssize_t line_len = 0, file_len = 0; FILE *hashes = NULL; bool ret = false; + lm_pkg_t temp; + + lm_ctx_temp_clear(ctx); + lm_package_init(&temp); - if((hashes = fopen(hashes_file, "r")) == NULL){ + if((files = lm_package_extract(pkg, ctx->temp)) == NULL){ + pdebug(__func__, "failed to extract %s: %s", pkg->data.name, lm_strerror()); + goto end; + } + + if(!lm_package_data_load(&temp.data, files->data_file)) + goto end; // error set by function + + if(!lm_package_is_same(&temp, pkg)){ + pdebug(__func__, "DATA file does not match with stored %s data", pkg->data.name); + lm_error_set(LM_ERR_PkgDataNotMatch); + goto end; + } + + if(!lm_database_changes_update(ctx->db, &pkg->data, files->changes_file)){ + char *suberr = lm_strerror_dup(); + pdebug(__func__, "failed to update changes file for %s: %s", pkg->data.name, suberr); + lm_error_set(LM_ERR_PkgChangesUpdateFail, suberr); + goto end; + } + + if((hashes = fopen(files->hashes_file, "r")) == NULL){ pdebug(__func__, "failed to open hash file for %s", pkg->data.name); lm_error_set(LM_ERR_PkgHashesOpenFail); - return false; + goto end; } while((line_len = getline(&line, (size_t*)&line_len, hashes)) > 0){ @@ -333,7 +321,7 @@ bool lm_ctx_install(lm_ctx_t *ctx, lm_pkg_t *pkg, bool run_install, lm_ctx_insta line_len = 0; } - if(!__lm_ctx_extract_files(ctx, pkg, files_archive, callback, data)){ + if(!__lm_ctx_extract_files(ctx, pkg, files->files_archive, callback, data)){ char *suberr = lm_strerror_dup(); pdebug(__func__, "failed to extract the files archive for %s: %s", pkg->data.name, suberr); lm_error_set(LM_ERR_PkgExtractFilesFail, suberr); @@ -349,7 +337,7 @@ bool lm_ctx_install(lm_ctx_t *ctx, lm_pkg_t *pkg, bool run_install, lm_ctx_insta goto end; } - if(run_install && !__lm_ctx_run_install(ctx->root, install_file)){ + if(run_install && !__lm_ctx_run_install(ctx->root, files->install_file)){ char *suberr = lm_strerror_dup(); pdebug(__func__, "failed to run install script: %s", lm_strerror()); lm_error_set(LM_ERR_InstallRunFail, suberr); @@ -357,7 +345,7 @@ bool lm_ctx_install(lm_ctx_t *ctx, lm_pkg_t *pkg, bool run_install, lm_ctx_insta goto end; } - if(!run_install && !__lm_ctx_save_install(ctx, pkg, install_file)){ + if(!run_install && !__lm_ctx_save_install(ctx, pkg, files->install_file)){ char *suberr = lm_strerror_dup(); pdebug(__func__, "failed to save install script: %s", lm_strerror()); lm_error_set(LM_ERR_InstallSaveFail, suberr); @@ -371,6 +359,9 @@ end: if(NULL != hashes) fclose(hashes); + + lm_package_free(&temp); + lm_package_extract_free(files); if(!ret){ lm_database_entry_del(ctx->db, &pkg->data); diff --git a/src/ctx/package.c b/src/ctx/package.c new file mode 100644 index 0000000..a2ef127 --- /dev/null +++ b/src/ctx/package.c @@ -0,0 +1,66 @@ +#include "../../include/package.h" +#include "../../include/error.h" +#include "../../include/util.h" +#include "../../include/ctx.h" + +#include +#include +#include + +bool lm_ctx_package_from(lm_ctx_t *ctx, lm_pkg_t *pkg, char *archive){ + if(NULL == ctx || NULL == pkg || NULL == archive){ + lm_error_set(LM_ERR_ArgNULL); + return false; + } + + // we should init the package pointer as soon as possible + // so if the caller calls ..._from_free we can prevent + // memory corruption + lm_package_init(pkg); + + if(NULL == ctx->temp) { + lm_error_set(LM_ERR_CtxTempNULL); + return false; + } + + size_t archive_len = strlen(archive); + char signature[archive_len+7]; + lm_pkg_files_t *files = NULL; + bool ret = false; + + sprintf(signature, "%s.sig", archive); + + if(!lm_package_path_set_archive(pkg, archive) || !lm_package_path_set_signature(pkg, signature)){ + lm_error_set(LM_ERR_ArchiveSetFail); + return false; + } + + if(!lm_ctx_temp_clear(ctx)){ + pdebug(__func__, "failed to clear the temp directory: %s", lm_strerror()); + return false; // error set by function + } + + if((files = lm_package_extract(pkg, ctx->temp)) == NULL){ + pdebug(__func__, "failed to extract the archive (%s): %s", archive, lm_strerror()); + return false; // error set by function + } + + if(!lm_package_data_load(&pkg->data, files->data_file)){ + pdebug(__func__, "failed to load the package data: %s", lm_strerror()); + goto end; // error set by function + } + + ret = true; +end: + lm_package_extract_free(files); + return ret; +} + +void lm_ctx_package_from_free(lm_pkg_t *pkg){ + if(NULL == pkg){ + lm_error_set(LM_ERR_ArgNULL); + return; + } + + lm_package_free(pkg); +} diff --git a/src/error.c b/src/error.c index cb3c1d2..f6a526b 100644 --- a/src/error.c +++ b/src/error.c @@ -161,6 +161,7 @@ void lm_error_set(lm_error_t code, ...) { {.code = LM_ERR_PoolListBadDir, .desc = _("specified list extraction directory is not accessible") }, {.code = LM_ERR_FileNotExist, .desc = _("file does not exist: %s") }, {.code = LM_ERR_FileNotLink, .desc = _("file is a symbolic link: %s") }, + {.code = LM_ERR_ArchiveSetFail, .desc = _("failed to set the package archive") }, }; char *fmt = NULL; diff --git a/src/package/extract.c b/src/package/extract.c new file mode 100644 index 0000000..42ea0df --- /dev/null +++ b/src/package/extract.c @@ -0,0 +1,71 @@ +#include "../../include/package.h" +#include "../../include/error.h" +#include "../../include/util.h" + +#include +#include +#include + +bool __lm_package_extract_check(char *file){ + if(!exists(file, NULL) || !is_file(file)){ + lm_error_set(LM_ERR_PkgBadArchive); + return false; + } + return true; +} + +lm_pkg_files_t *lm_package_extract(lm_pkg_t *pkg, char *target){ + if(NULL == pkg || NULL == target){ + lm_error_set(LM_ERR_ArgNULL); + return NULL; + } + + if(lm_package_path_is_empty(pkg)){ + lm_error_set(LM_ERR_PkgPathsEmpty); + return NULL; + } + + if(!extract_archive(target, pkg->archive)) + return NULL; + + lm_pkg_files_t *files = malloc(sizeof(lm_pkg_files_t)); + bool ret = false; + + bzero(files, sizeof(lm_pkg_files_t)); + + files->data_file = join_alloc(target, "DATA"); + files->hashes_file = join_alloc(target, "HASHES"); + files->changes_file = join_alloc(target, "CHANGES"); + files->install_file = join_alloc(target, "INSTALL"); + files->files_archive = join_alloc(target, "files.tar.gz"); + + if(!__lm_package_extract_check(files->data_file) || + !__lm_package_extract_check(files->hashes_file) || + !__lm_package_extract_check(files->changes_file) || + !__lm_package_extract_check(files->install_file) || + !__lm_package_extract_check(files->files_archive)){ + goto end; + } + + ret = true; +end: + if(!ret){ + lm_package_extract_free(files); + files = NULL; + } + return files; +} + +void lm_package_extract_free(lm_pkg_files_t *files){ + if(NULL == files) + return; + + free(files->data_file); + free(files->hashes_file); + free(files->changes_file); + free(files->install_file); + free(files->files_archive); + + bzero(files, sizeof(lm_pkg_files_t)); + free(files); +} diff --git a/src/pool/list.c b/src/pool/list.c index f363323..a99a365 100644 --- a/src/pool/list.c +++ b/src/pool/list.c @@ -7,6 +7,7 @@ #include #include #include +#include #include bool lm_pool_list_load(lm_pool_t *pool, char *dir){ @@ -144,6 +145,8 @@ void lm_pool_list_free(lm_pool_t *pool){ while(NULL != cur){ prev = cur; cur = cur->next; + lm_package_free(prev); + free(prev); } }