From d2d667906062bd86b5f68e7816055d65678f1ab9 Mon Sep 17 00:00:00 2001 From: ngn Date: Sun, 4 Aug 2024 13:11:25 +0300 Subject: [PATCH] update: better handling of the keep files --- examples/client/install.c | 2 +- examples/client/update.c | 8 +++++++ include/ctx.h | 5 ++-- include/error.h | 2 ++ include/util.h | 2 +- locale/tr/LC_MESSAGES/libmp.po | 12 +++++++++- src/ctx/check.c | 41 +++++++++++++++++++++++++-------- src/ctx/install.c | 42 +++++++++++++++++++++++++--------- src/ctx/remove.c | 2 +- src/ctx/sync.c | 6 ++++- src/ctx/temp.c | 13 ++++++++--- src/database/changes.c | 2 +- src/database/database.c | 6 ++--- src/error.c | 2 ++ src/package/package.c | 2 +- src/pool/info.c | 2 +- src/pool/list.c | 2 +- src/pool/path.c | 6 ++--- src/util.c | 14 +++++++++--- 19 files changed, 128 insertions(+), 43 deletions(-) diff --git a/examples/client/install.c b/examples/client/install.c index 30126cc..d3721e5 100644 --- a/examples/client/install.c +++ b/examples/client/install.c @@ -12,7 +12,7 @@ int main(int argc, char *argv[]) { int ret = EXIT_FAILURE; char pooldir[strlen(TEMP_DIR) + 10]; - sprintf(pooldir, "%s/%s", TEMP_DIR, "pool"); + sprintf(pooldir, "%s/%s", DATA_DIR, "pool"); if (argc != 4) { printf("usage: %s \n", argv[0]); diff --git a/examples/client/update.c b/examples/client/update.c index 010eb03..29a76ef 100644 --- a/examples/client/update.c +++ b/examples/client/update.c @@ -17,11 +17,19 @@ int main(int argc, char *argv[]) { return ret; } + char pooldir[strlen(TEMP_DIR) + 10]; + sprintf(pooldir, "%s/%s", DATA_DIR, "pool"); + if (!lm_ctx_init(&ctx, ROOT_DIR, TEMP_DIR, DATA_DIR)) { printf("failed to init the ctx: %s (%d)\n", lm_strerror(), lm_error()); goto end; } + if (lm_ctx_pool_add(&ctx, argv[1], argv[2], pooldir) == NULL) { + printf("failed to add pool: %s (%d)\n", lm_strerror(), lm_error()); + goto end; + } + lm_ctx_ping(&ctx, NULL, NULL); lm_ctx_sync(&ctx, true, NULL, NULL); diff --git a/include/ctx.h b/include/ctx.h index 3078e07..1c5887e 100644 --- a/include/ctx.h +++ b/include/ctx.h @@ -49,7 +49,8 @@ typedef bool (*lm_ctx_serve_callback_t)(lm_pool_t *pool, lm_mptp_t *packet, stru typedef bool (*lm_ctx_ping_callback_t)(lm_ctx_t *ctx, lm_pool_t *pool, bool status, void *data); typedef bool (*lm_ctx_remove_callback_t)( lm_ctx_t *ctx, lm_entry_t *pkg, char *file, size_t current, size_t total, void *data); -typedef lm_ctx_remove_callback_t lm_ctx_check_callback_t; +typedef bool (*lm_ctx_check_callback_t)( + lm_ctx_t *ctx, lm_entry_t *pkg, char *file, bool success, size_t current, size_t total, void *data); /* ############### ## ctx stuff ## @@ -89,7 +90,7 @@ bool lm_ctx_serve( ## temp directory fucntions ## ############################## */ char *lm_ctx_temp_dir(lm_ctx_t *ctx, char *dir); -void lm_ctx_temp_clear(lm_ctx_t *ctx); +bool lm_ctx_temp_clear(lm_ctx_t *ctx); /* #################### ## pool fucntions ## diff --git a/include/error.h b/include/error.h index 961835e..174fa5e 100644 --- a/include/error.h +++ b/include/error.h @@ -142,6 +142,8 @@ typedef enum lm_error { LM_ERR_NotDir = 140, LM_ERR_NoWrite = 141, LM_ERR_PoolListBadDir = 142, + LM_ERR_FileNotExist = 143, + LM_ERR_FileNotLink = 144, } lm_error_t; typedef struct lm_error_desc { diff --git a/include/util.h b/include/util.h index 8adfe79..5d5b15b 100644 --- a/include/util.h +++ b/include/util.h @@ -23,7 +23,7 @@ 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 exists(char *path, struct stat *st); bool is_empty(char *p); bool is_dir_empty(char *p); bool rmrf(char *p); diff --git a/locale/tr/LC_MESSAGES/libmp.po b/locale/tr/LC_MESSAGES/libmp.po index 7d289fc..29e45a1 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-03 22:16+0300\n" +"POT-Creation-Date: 2024-08-04 13:06+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -603,3 +603,13 @@ msgstr "" #: src/error.c:161 msgid "specified list extraction directory is not accessible" msgstr "" + +#: src/error.c:162 +#, c-format +msgid "file does not exist: %s" +msgstr "" + +#: src/error.c:163 +#, c-format +msgid "file is a symbolic link: %s" +msgstr "" diff --git a/src/ctx/check.c b/src/ctx/check.c index d4c8cd9..1409e41 100644 --- a/src/ctx/check.c +++ b/src/ctx/check.c @@ -5,6 +5,7 @@ #include #include #include +#include bool lm_ctx_check(lm_ctx_t *ctx, lm_entry_t *entry, lm_ctx_check_callback_t callback, void *data){ if(NULL == ctx || NULL == entry){ @@ -22,24 +23,37 @@ bool lm_ctx_check(lm_ctx_t *ctx, lm_entry_t *entry, lm_ctx_check_callback_t call size_t rootlen = strlen(ctx->root), current = 0, total = 0; char *path = NULL, *hash = NULL, *fhash = NULL; - bool keep = false, ret = false; + bool keep = false, ret = false, success = false; + struct stat st; total = lm_database_files_count(ctx->db, entry); while(lm_database_files_next(ctx->db, entry, &path, &hash, &keep)){ char fp[rootlen+strlen(path)+10]; join(fp, ctx->root, path); + bzero(&st, sizeof(st)); + + success = false; current++; pdebug(__func__, "(%d/%d) checking %s", current, total, fp); - if(NULL != callback) - if(!callback(ctx, entry, fp, current, total, data)) - goto end; + if(!exists(fp, &st)){ + pdebug(__func__, "%s does not exist, check will fail", fp); + lm_error_set(LM_ERR_FileNotExist, fp); + goto next; + } - if(!exists(fp)){ - pdebug(__func__, "skipping %s because file does not exists", fp); - continue; + if(S_ISLNK(st.st_mode)){ + pdebug(__func__, "%s seems to be a link, no hash verification to do", fp); + + if(hash[0] != '\0'){ + lm_error_set(LM_ERR_FileNotLink, fp); + goto end; + } + + success = true; + goto next; } if((fhash = get_md5(fp)) == NULL){ @@ -47,16 +61,25 @@ bool lm_ctx_check(lm_ctx_t *ctx, lm_entry_t *entry, lm_ctx_check_callback_t call pdebug(__func__, "failed to get hash of %s: %s", fp, suberr); lm_error_set(LM_ERR_FileHashFail, fp, suberr); free(suberr); - goto end; + goto next; } if(!eq(fhash, hash)){ lm_error_set(LM_ERR_FileHashNoMatch, fp); - goto end; + goto next; } + success = true; + next: free(fhash); fhash = NULL; + + if(NULL != callback) + if(!callback(ctx, entry, fp, success, current, total, data)) + goto end; + + if(!success) + goto end; } ret = true; diff --git a/src/ctx/install.c b/src/ctx/install.c index 29b4322..b6d3245 100644 --- a/src/ctx/install.c +++ b/src/ctx/install.c @@ -136,14 +136,28 @@ bool __lm_ctx_extract_files(lm_ctx_t *ctx, lm_pkg_t *pkg, char *files, lm_ctx_in current += archive_entry_size(entry); type = archive_entry_filetype(entry); - if(type == AE_IFREG && !lm_database_files_contains(ctx->db, &pkg->data, entry_path)){ - pdebug(__func__, "archive file not included in the database: %s (%s)", entry_path, pkg->data.name); + if(exists(entry_path, NULL) && lm_database_files_iskeep(ctx->db, entry_path)){ + pdebug(__func__, "not extracting %s, file is set as KEEP", entry_path); continue; } - if(exists(entry_path) && lm_database_files_iskeep(ctx->db, entry_path)){ - pdebug(__func__, "not extracting %s, file is set as KEEP", entry_path); - continue; + switch (type) { + case AE_IFLNK: + if(!lm_database_files_add(ctx->db, &pkg->data, entry_path, "")){ + char *suberr = lm_strerror_dup(); + pdebug(__func__, "failed to add link to the database for %s: %s", pkg->data.name, suberr); + lm_error_set(LM_ERR_PkgFilesAddFail, entry_path, suberr); + free(suberr); + goto end; + } + break; + + case AE_IFREG: + if(!lm_database_files_contains(ctx->db, &pkg->data, entry_path)){ + pdebug(__func__, "archive file not included in the database: %s (%s)", entry_path, pkg->data.name); + goto next; + } + break; } rc = archive_write_header(writer, entry); @@ -164,6 +178,9 @@ bool __lm_ctx_extract_files(lm_ctx_t *ctx, lm_pkg_t *pkg, char *files, lm_ctx_in if(NULL != callback) if(!callback(ctx, pkg, entry_path, current, total, data)) goto end; + + next: + continue; } if (rc != ARCHIVE_EOF) { @@ -239,11 +256,11 @@ bool lm_ctx_install(lm_ctx_t *ctx, lm_pkg_t *pkg, bool run_install, lm_ctx_insta join(install_file, ctx->temp, "INSTALL"); join(files_archive, ctx->temp, "files.tar.gz"); - if(!exists(data_file) || !is_file(data_file) || - !exists(hashes_file) || !is_file(hashes_file) || - !exists(changes_file) || !is_file(changes_file) || - !exists(install_file) || !is_file(install_file) || - !exists(files_archive) || !is_file(files_archive)){ + 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; } @@ -297,7 +314,10 @@ bool lm_ctx_install(lm_ctx_t *ctx, lm_pkg_t *pkg, bool run_install, lm_ctx_insta pdebug(__func__, "(%lu) %s => %s", line_len, file, hash); - lm_database_files_del_single(ctx->db, file); + if(!lm_database_files_del_single(ctx->db, file)){ + pdebug(__func__, "failed to remove file from the database for %s: %s", pkg->data.name, lm_error()); + goto end; + } if(!lm_database_files_add(ctx->db, &pkg->data, file, hash)){ char *suberr = lm_strerror_dup(); diff --git a/src/ctx/remove.c b/src/ctx/remove.c index a34ff7c..603d318 100644 --- a/src/ctx/remove.c +++ b/src/ctx/remove.c @@ -63,7 +63,7 @@ bool lm_ctx_remove(lm_ctx_t *ctx, lm_entry_t *entry, lm_ctx_remove_callback_t ca fpath = join_alloc(ctx->root, path); pdebug(__func__, "removing file %s (%s)", fpath, entry->name); - if(!exists(fpath)){ + if(!exists(fpath, NULL)){ pdebug(__func__, "found file in database, but its not on the file system: %s", fpath); goto next; } diff --git a/src/ctx/sync.c b/src/ctx/sync.c index 1b92f9c..b9d85e6 100644 --- a/src/ctx/sync.c +++ b/src/ctx/sync.c @@ -100,7 +100,11 @@ size_t lm_ctx_sync(lm_ctx_t *ctx, bool do_update, lm_ctx_sync_callback_t callbac } lm_ctx_temp_clear(ctx); - tempdir = lm_ctx_temp_dir(ctx, "list_extracted"); + + if((tempdir = lm_ctx_temp_dir(ctx, "list_extracted")) == NULL){ + pdebug(__func__, "(%s) failed to access list extract directory: %s", cur->name, lm_strerror()); + goto next_list; + } if(!do_update && !lm_pool_list_load(cur, tempdir)){ pdebug(__func__, "(%s) failed to load list: %s", cur->name, lm_strerror()); diff --git a/src/ctx/temp.c b/src/ctx/temp.c index 014c3af..f038178 100644 --- a/src/ctx/temp.c +++ b/src/ctx/temp.c @@ -27,12 +27,19 @@ char *lm_ctx_temp_dir(lm_ctx_t *ctx, char *dir){ return strdup(td); } -void lm_ctx_temp_clear(lm_ctx_t *ctx) { +bool lm_ctx_temp_clear(lm_ctx_t *ctx) { if(NULL == ctx->temp){ lm_error_set(LM_ERR_CtxTempNULL); - return; + return false; + } + + rmrf(ctx->temp); + + if(!mkdir_ifnot(ctx->temp)){ + lm_error_set(LM_ERR_CtxTempFailMkdir); + return false; } - rmrf(ctx->temp); + return true; } diff --git a/src/database/changes.c b/src/database/changes.c index e5194b0..11c558b 100644 --- a/src/database/changes.c +++ b/src/database/changes.c @@ -58,7 +58,7 @@ char *lm_database_changes_get(lm_database_t *db, lm_entry_t *entry){ char *changes_path = malloc(strlen(db->dir)+sizeof(changes_file)); join(changes_path, db->dir, changes_file); - if(!exists(changes_path)){ + if(!exists(changes_path, NULL)){ lm_error_set(LM_ERR_DbChangesNotExists); free(changes_path); return NULL; diff --git a/src/database/database.c b/src/database/database.c index 97922c6..5a8958a 100644 --- a/src/database/database.c +++ b/src/database/database.c @@ -43,7 +43,7 @@ char *queries[] = { "INSERT INTO files VALUES (?, ?, ?, ?)", // QUERY_DELETE_FILE_ALL - "DELETE FROM files WHERE package = ? AND keep = 1", + "DELETE FROM files WHERE package = ? AND keep = 0", // QUERY_DELETE_FILE_SINGLE "DELETE FROM files WHERE path = ?", @@ -66,12 +66,12 @@ lm_database_t *lm_database_new(char *path){ char *err = NULL; bzero(db, sizeof(lm_database_t)); - if(exists(path) && (is_file(path) || !can_read(path) || !can_write(path))){ + if(exists(path, NULL) && (is_file(path) || !can_read(path) || !can_write(path))){ lm_error_set(LM_ERR_DbCantAccess); return NULL; } - if(!exists(path) && !mkdir_ifnot(path)){ + if(!exists(path, NULL) && !mkdir_ifnot(path)){ lm_error_set(LM_ERR_DbCantAccess); return NULL; } diff --git a/src/error.c b/src/error.c index 6320187..cb3c1d2 100644 --- a/src/error.c +++ b/src/error.c @@ -159,6 +159,8 @@ void lm_error_set(lm_error_t code, ...) { {.code = LM_ERR_NotDir, .desc = _("specified path is not a directory") }, {.code = LM_ERR_FailMkdir, .desc = _("failed to create the specified directory") }, {.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") }, }; char *fmt = NULL; diff --git a/src/package/package.c b/src/package/package.c index 583be43..b5256e5 100644 --- a/src/package/package.c +++ b/src/package/package.c @@ -25,7 +25,7 @@ bool lm_package_downloaded(lm_pkg_t *pkg){ return false; } - if(!exists(pkg->archive) || !exists(pkg->signature)){ + if(!exists(pkg->archive, NULL) || !exists(pkg->signature, NULL)){ lm_error_set(LM_ERR_PkgNotDownloaded); return false; } diff --git a/src/pool/info.c b/src/pool/info.c index f5930c7..d42d3b8 100644 --- a/src/pool/info.c +++ b/src/pool/info.c @@ -40,7 +40,7 @@ bool lm_pool_info_load(lm_pool_t *pool) { return false; } - if(!exists(pool->info_file) || !can_read(pool->info_file)){ + if(!exists(pool->info_file, NULL) || !can_read(pool->info_file)){ lm_error_set(LM_ERR_PoolInfoCantRead); return false; } diff --git a/src/pool/list.c b/src/pool/list.c index efe6e19..f363323 100644 --- a/src/pool/list.c +++ b/src/pool/list.c @@ -22,7 +22,7 @@ bool lm_pool_list_load(lm_pool_t *pool, char *dir){ return false; } - if(!exists(pool->list_file) || !can_read(pool->list_file)){ + if(!exists(pool->list_file, NULL) || !can_read(pool->list_file)){ lm_error_set(LM_ERR_PoolListCantRead); return false; } diff --git a/src/pool/path.c b/src/pool/path.c index 2915948..d003b3f 100644 --- a/src/pool/path.c +++ b/src/pool/path.c @@ -17,7 +17,7 @@ bool lm_pool_path_set_dir(lm_pool_t *pool, char *dir){ if(NULL == dir) return true; - if(exists(dir) && (is_file(dir) || !can_read(dir) || !can_write(dir))){ + if(exists(dir, NULL) && (is_file(dir) || !can_read(dir) || !can_write(dir))){ lm_error_set(LM_ERR_PoolBadDir); return false; } @@ -26,12 +26,12 @@ bool lm_pool_path_set_dir(lm_pool_t *pool, char *dir){ pool->info_file = join_alloc(dir, "INFO"); pool->list_file = join_alloc(dir, "LIST"); - if(exists(pool->info_file) && (!is_file(pool->info_file) || !can_read(pool->info_file) || !can_write(pool->info_file))){ + if(exists(pool->info_file, NULL) && (!is_file(pool->info_file) || !can_read(pool->info_file) || !can_write(pool->info_file))){ lm_error_set(LM_ERR_PoolBadPaths); return false; } - if(exists(pool->list_file) && (!is_file(pool->list_file) || !can_read(pool->list_file) || !can_write(pool->list_file))){ + if(exists(pool->list_file, NULL) && (!is_file(pool->list_file) || !can_read(pool->list_file) || !can_write(pool->list_file))){ lm_error_set(LM_ERR_PoolBadPaths); return false; } diff --git a/src/util.c b/src/util.c index 93fb9f3..2bd72f7 100644 --- a/src/util.c +++ b/src/util.c @@ -12,6 +12,7 @@ #include #include #include +#include #include void pdebug(const char *func, const char *fmt, ...) { @@ -220,9 +221,16 @@ end: return ret; } -bool exists(char *path) { - struct stat st; - return stat(path, &st) == 0; +bool exists(char *path, struct stat *st) { + if (NULL == path) + return false; + + if (NULL == st) { + struct stat tmpst; + return lstat(path, &tmpst) == 0; + } + + return lstat(path, st) == 0; } bool is_file(char *path) {