From 1d5880cfa640d21d1510057a72033e47f4319bc3 Mon Sep 17 00:00:00 2001 From: ngn Date: Mon, 8 Jul 2024 05:47:13 +0300 Subject: [PATCH] new: add remove operation --- include/database.h | 28 +++++- include/error.h | 14 ++- include/util.h | 2 + locale/tr/LC_MESSAGES/libmp.po | 51 +++++++++- src/ctx/install.c | 153 ++++++++++++++++++++++++++++- src/ctx/remove.c | 73 ++++++++++++++ src/database/changes.c | 5 +- src/database/database.c | 11 ++- src/database/files.c | 172 ++++++++++++++++++++++++--------- src/database/package.c | 48 +++++---- src/error.c | 10 ++ 11 files changed, 486 insertions(+), 81 deletions(-) create mode 100644 src/ctx/remove.c diff --git a/include/database.h b/include/database.h index 7b44fbd..ffc328c 100644 --- a/include/database.h +++ b/include/database.h @@ -4,7 +4,7 @@ #define HASH_LEN 32 -typedef enum lm_query_index { +enum lm_query_index { QUERY_CREATE_PACKAGE_TABLE = 0, QUERY_INSERT_PACKAGE_SINGLE = 1, QUERY_SELECT_PACKAGE_SINGLE = 2, @@ -17,7 +17,20 @@ typedef enum lm_query_index { QUERY_SELECT_FILE_ALL = 9, QUERY_UPDATE_FILE_1 = 10, QUERY_UPDATE_FILE_2 = 11, -} lm_query_index_t; +}; + +enum lm_columns { + FILES_COLUMN_PATH = 1, + FILES_COLUMN_HASH = 2, + FILES_COLUMN_KEEP = 3, + FILES_COLUMN_PACKAGE = 4, + + PACKAGES_COLUMN_NAME = 1, + PACKAGES_COLUMN_DESC = 2, + PACKAGES_COLUMN_VERSION = 3, + PACKAGES_COLUMN_SIZE = 4, + PACKAGES_COLUMN_DEPENDS = 5, +}; extern char *queries[]; @@ -34,13 +47,20 @@ typedef struct lm_database { lm_database_t *lm_database_new(char *path); void lm_database_free(lm_database_t *db); +bool lm_database_step_all(sqlite3_stmt *st); bool lm_database_package_find( lm_database_t *db, lm_pkg_t *pkg, char *name); // finds a package by its name, package stored in *pkg bool lm_database_package_next(lm_database_t *db, lm_pkg_t *pkg); // gets the next package in the database -bool lm_database_packege_add(lm_database_t *db, lm_pkg_t *pkg); // adds a package to the database +bool lm_database_package_add(lm_database_t *db, lm_pkg_t *pkg); // adds a package to the database bool lm_database_package_del(lm_database_t *db, lm_pkg_t *pkg); // delete a package from the database +void lm_database_package_next_free( + lm_database_t *db, lm_pkg_t *pkg); // frees resources used for lm_database_package_next +size_t lm_database_files_count( + lm_database_t *db, lm_pkg_t *pkg); // returns the count of files associated with a package +bool lm_database_files_contains( + lm_database_t *db, lm_pkg_t *pkg, char *path); // check if a package contains the given file bool lm_database_files_matches( lm_database_t *db, char *path, char *hash); // checks if the given file matches with the given hash bool lm_database_files_iskeep(lm_database_t *db, char *path); // checks if the given file is marked as keep @@ -49,6 +69,8 @@ bool lm_database_files_next( bool lm_database_files_add( lm_database_t *db, lm_pkg_t *pkg, char *path, char *hash); // adds a file to the files database bool lm_database_files_del(lm_database_t *db, lm_pkg_t *pkg); // dels all files of belonging to a package +void lm_database_files_next_free(lm_database_t *db, lm_pkg_t *pkg, char **path, char **hash, + bool *keep); // frees resources used for lm_database_files_next bool lm_database_changes_update(lm_database_t *db, lm_pkg_t *pkg, char *file); char *lm_database_changes_get(lm_database_t *db, lm_pkg_t *pkg); diff --git a/include/error.h b/include/error.h index b1d3025..fa8ff5b 100644 --- a/include/error.h +++ b/include/error.h @@ -1,7 +1,6 @@ #pragma once -#define lm_strerror_dup() \ - { strdup(lm_strerror()) } +#define lm_strerror_dup() {strdup(lm_strerror())} typedef enum lm_error { LM_ERR_NoError = 0, @@ -117,7 +116,16 @@ typedef enum lm_error { LM_ERR_RecvNotCompleted = 109, LM_ERR_DbSqlSelectFail = 110, LM_ERR_DbSqlDeleteFail = 111, - + LM_ERR_ExtractStatFail = 112, + LM_ERR_PkgFilesAddFail = 113, + LM_ERR_PkgExtractFilesFail = 114, + LM_ERR_PkgDatabaseAddFail = 115, + LM_ERR_PkgAlreadyInstalled = 116, + LM_ERR_PkgNotInstalled = 117, + LM_ERR_PkgFileUnlinkFail = 118, + LM_ERR_PkgDatabaseDelFail = 119, + LM_ERR_PkgFilesDelFail = 119, + LM_ERR_PkgChangesDelFail = 120, } lm_error_t; typedef struct lm_error_desc { diff --git a/include/util.h b/include/util.h index 5d0caff..307e949 100644 --- a/include/util.h +++ b/include/util.h @@ -1,5 +1,6 @@ #pragma once #include "types.h" +#include #include #include #include @@ -28,6 +29,7 @@ bool package_name_valid(char *name); void pdebug(const char *func, const char *fmt, ...); bool parse_host(char *addr, char *host, uint16_t *port); +bool copy_blocks(struct archive *w, struct archive *r); bool extract_archive(char *dst, char *src); bool mkdir_ifnot(char *path); void sockaddr_to_str(struct sockaddr *addr, char *str); diff --git a/locale/tr/LC_MESSAGES/libmp.po b/locale/tr/LC_MESSAGES/libmp.po index 0d0b1d7..ec22ffe 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-06 04:13+0300\n" +"POT-Creation-Date: 2024-07-08 05:46+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -480,3 +480,52 @@ msgstr "" #: src/error.c:134 msgid "target file is not fully received" msgstr "" + +#: src/error.c:135 +msgid "failed to stat for target extract archive" +msgstr "" + +#: src/error.c:136 +#, c-format +msgid "failed to add package file (%s) to the database: %s" +msgstr "" + +#: src/error.c:137 +#, c-format +msgid "failed to extract package files: %s" +msgstr "" + +#: src/error.c:138 +#, c-format +msgid "failed to add package to the database: %s" +msgstr "" + +#: src/error.c:139 +#, fuzzy +msgid "package is already installed" +msgstr "URL hostname is too large" + +#: src/error.c:140 +#, fuzzy +msgid "package is not installed" +msgstr "URL hostname is too large" + +#: src/error.c:141 +#, c-format +msgid "failed to remove package file (%s): %s" +msgstr "" + +#: src/error.c:142 +#, c-format +msgid "failed to remove package from the database: %s" +msgstr "" + +#: src/error.c:143 +#, c-format +msgid "failed to remove package files from the database: %s" +msgstr "" + +#: src/error.c:144 +#, c-format +msgid "failed to remove changes file for package: %s" +msgstr "" diff --git a/src/ctx/install.c b/src/ctx/install.c index a72f987..763417b 100644 --- a/src/ctx/install.c +++ b/src/ctx/install.c @@ -4,15 +4,127 @@ #include "../../include/util.h" #include "../../include/ctx.h" +#include +#include #include #include +#include +#include + +bool __lm_ctx_extract_files(lm_ctx_t *ctx, lm_pkg_t *pkg, char *files, lm_ctx_install_callback_t callback, void *data){ + struct archive *reader = NULL, *writer = NULL; + struct archive_entry *entry = NULL; + int flags = 0, rc = 0; + char *oldpwd = NULL, *entry_path = NULL; + bool ret = false; + size_t total = 0, current = 0; + mode_t type = 0; + struct stat st; + + if(stat(files, &st) < 0){ + lm_error_set(LM_ERR_ExtractStatFail); + goto end; + } + + oldpwd = getcwd(NULL, 0); + total = st.st_size; + + if (NULL == oldpwd) { + lm_error_set(LM_ERR_GetCwdFail); + goto end; + } + + chdir(ctx->root); + + flags = ARCHIVE_EXTRACT_PERM; + flags |= ARCHIVE_EXTRACT_UNLINK; + + reader = archive_read_new(); + writer = archive_write_disk_new(); + + if (NULL == reader || NULL == writer) { + lm_error_set(LM_ERR_ArcNewFail); + goto end; + } + + archive_write_disk_set_options(writer, flags); + archive_write_disk_set_standard_lookup(writer); + + archive_read_support_format_tar(reader); + archive_read_support_filter_gzip(reader); + + if (archive_read_open_filename(reader, files, 1024 * 10) != ARCHIVE_OK) { + lm_error_set(LM_ERR_ArcOpenFail); + goto end; + } + + while ((rc = archive_read_next_header(reader, &entry)) == ARCHIVE_OK) { + entry_path = (char *)archive_entry_pathname(entry); + current += archive_entry_size(entry); + type = archive_entry_filetype(entry); + + if(type == AE_IFREG && !lm_database_files_contains(ctx->db, pkg, entry_path)){ + pdebug(__func__, "archive file not included in the database: %s (%s)", entry_path, pkg->name); + continue; + } + + rc = archive_write_header(writer, entry); + if (rc != ARCHIVE_OK) { + lm_error_set(LM_ERR_ArcWHeaderFail); + goto end; + } + + if (!copy_blocks(writer, reader)) + goto end; + + rc = archive_write_finish_entry(writer); + if (rc != ARCHIVE_OK) { + lm_error_set(LM_ERR_ArcWEntryFail); + goto end; + } + + if(NULL != callback) + if(!callback(ctx, pkg, entry_path, current, total, data)) + goto end; + } + + if (rc != ARCHIVE_EOF) { + lm_error_set(LM_ERR_ArcNextHeaderFail); + goto end; + } + + ret = true; + +end: + if (NULL != reader) { + archive_read_close(reader); + archive_read_free(reader); + } + + if (NULL != writer) { + archive_write_close(writer); + archive_write_free(writer); + } + + if (NULL != oldpwd) { + chdir(oldpwd); + free(oldpwd); + } + + return ret; +} bool lm_ctx_install(lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_install_callback_t callback, void *data) { - if(NULL == ctx->temp){ + if(NULL == ctx->temp || NULL == pkg){ lm_error_set(LM_ERR_CtxTempNULL); return false; } + if(lm_ctx_database_is_installed(ctx, pkg, true)){ + lm_error_set(LM_ERR_PkgAlreadyInstalled); + return false; + } + if(NULL == ctx->root){ lm_error_set(LM_ERR_CtxRootNULL); return false; @@ -68,7 +180,7 @@ bool lm_ctx_install(lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_install_callback_t call } char *line = NULL, *hash = NULL, *file = NULL; - ssize_t line_len = 0; + ssize_t line_len = 0, file_len = 0; FILE *hashes = NULL; bool ret = false; @@ -82,22 +194,31 @@ bool lm_ctx_install(lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_install_callback_t call if(NULL == line) goto next; - if(HASH_LEN+1 >= line_len) + if(HASH_LEN+2 >= line_len) goto next; line[HASH_LEN] = 0; hash = line; file = line+HASH_LEN+2; - file[strlen(file)-1] = 0; + file_len = strlen(file); + file[file_len-1] = 0; if(file[0] == '.') file++; + if(file_len >= 2 && file[0] == '/') + file++; + pdebug(__func__, "(%lu) %s => %s", line_len, file, hash); - if(!lm_database_files_add(ctx->db, pkg, file, hash)) + if(!lm_database_files_add(ctx->db, pkg, file, hash)){ + char *suberr = lm_strerror_dup(); + pdebug(__func__, "failed to add file to the database for %s: %s", pkg->name, suberr); + lm_error_set(LM_ERR_PkgFilesAddFail, file, suberr); + free(suberr); goto end; + } next: free(line); @@ -105,6 +226,22 @@ bool lm_ctx_install(lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_install_callback_t call line_len = 0; } + if(!__lm_ctx_extract_files(ctx, pkg, files_archive, callback, data)){ + char *suberr = lm_strerror_dup(); + pdebug(__func__, "failed to extract the files archive for %s: %s", pkg->name, suberr); + lm_error_set(LM_ERR_PkgExtractFilesFail, suberr); + free(suberr); + goto end; + } + + if(!lm_database_package_add(ctx->db, pkg)){ + char *suberr = lm_strerror_dup(); + pdebug(__func__, "failed to add %s to the database: %s", pkg->name, lm_strerror()); + lm_error_set(LM_ERR_PkgDatabaseAddFail, suberr); + free(suberr); + goto end; + } + ret = true; end: free(line); @@ -112,5 +249,11 @@ end: if(NULL != hashes) fclose(hashes); + if(!ret){ + lm_database_package_del(ctx->db, pkg); + lm_database_changes_del(ctx->db, pkg); + lm_database_files_del(ctx->db, pkg); + } + return ret; } diff --git a/src/ctx/remove.c b/src/ctx/remove.c new file mode 100644 index 0000000..fcc444a --- /dev/null +++ b/src/ctx/remove.c @@ -0,0 +1,73 @@ +#include "../../include/error.h" +#include "../../include/pool.h" +#include "../../include/util.h" +#include "../../include/ctx.h" + +#include +#include +#include +#include + +bool lm_ctx_remove(lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_remove_callback_t callback, void *data){ + if(NULL == ctx && NULL == pkg){ + lm_error_set(LM_ERR_ArgNULL); + return false; + } + + if(!lm_ctx_database_is_installed(ctx, pkg, true)){ + lm_error_set(LM_ERR_PkgNotInstalled); + return false; + } + + if(!lm_ctx_database_init(ctx)) + return false; + + size_t total = 0, current = 0; + char *path = NULL, *hash = NULL; + bool in_keep = false, ret = false; + + total = lm_database_files_count(ctx->db, pkg); + + while(lm_database_files_next(ctx->db, pkg, &path, &hash, &in_keep)){ + if(in_keep) + goto next; + + if(exists(path) && unlink(path) < 0){ + pdebug(__func__, "failed to delete file for removing %s: %s", pkg->name, errno); + lm_error_set(LM_ERR_PkgFileUnlinkFail, path, strerror(errno)); + goto end; + } + next: + if(!callback(ctx, pkg, path, ++current, total, data)) + goto end; + } + + if(!lm_database_package_del(ctx->db, pkg)){ + char *suberr = lm_strerror_dup(); + pdebug(__func__, "failed to delete %s from the database: %s", pkg->name, lm_strerror()); + lm_error_set(LM_ERR_PkgDatabaseDelFail, suberr); + free(suberr); + goto end; + } + + if(!lm_database_files_del(ctx->db, pkg)){ + char *suberr = lm_strerror_dup(); + pdebug(__func__, "failed to delete files of %s from the database: %s", pkg->name, suberr); + lm_error_set(LM_ERR_PkgFilesDelFail, suberr); + free(suberr); + goto end; + } + + if(!lm_database_changes_del(ctx->db, pkg)){ + char *suberr = lm_strerror_dup(); + pdebug(__func__, "failed to delete changes file for %s: %s", pkg->name, suberr); + lm_error_set(LM_ERR_PkgChangesDelFail, suberr); + goto end; + } + + ret = true; +end: + lm_database_files_next_free(ctx->db, pkg, &path, &hash, &in_keep); + return ret; +} + diff --git a/src/database/changes.c b/src/database/changes.c index 28d7309..e5edae5 100644 --- a/src/database/changes.c +++ b/src/database/changes.c @@ -20,10 +20,7 @@ bool lm_database_changes_update(lm_database_t *db, lm_pkg_t *pkg, char *file){ char changes_path[strlen(db->dir)+sizeof(changes_file)]; join(changes_path, db->dir, changes_file); - if(!copy_file(changes_path, file)) - return false; // error set by function - - return true; + return copy_file(changes_path, file); } bool lm_database_changes_del(lm_database_t *db, lm_pkg_t *pkg){ diff --git a/src/database/database.c b/src/database/database.c index bc164fb..5cc8b20 100644 --- a/src/database/database.c +++ b/src/database/database.c @@ -43,7 +43,7 @@ char *queries[] = { "DELETE FROM files WHERE package = '?'", // QUERY_SELECT_FILE_SINGLE - "SELECT * FROM files WHERE path = '?'", + "SELECT * FROM files WHERE path = ?", // QUERY_SELECT_FILE_ALL "SELECT * FROM files WHERE package = '?'", @@ -126,3 +126,12 @@ void lm_database_free(lm_database_t *db){ free(db); } + +bool lm_database_step_all(sqlite3_stmt *st){ + int rc = 0; + + while((rc = sqlite3_step(st)) == SQLITE_ROW) + continue; + + return rc == SQLITE_DONE; +} diff --git a/src/database/files.c b/src/database/files.c index 183231e..ea102ec 100644 --- a/src/database/files.c +++ b/src/database/files.c @@ -3,6 +3,7 @@ #include "../../include/error.h" #include "../../include/util.h" +#include #include #include #include @@ -10,6 +11,65 @@ #include #include +size_t lm_database_files_count(lm_database_t *db, lm_pkg_t *pkg){ + size_t count = 0; + + if(NULL == db || NULL == pkg){ + lm_error_set(LM_ERR_ArgNULL); + goto end; + } + + if(sqlite3_prepare(db->files_db, queries[QUERY_SELECT_FILE_ALL], strlen(queries[QUERY_SELECT_FILE_ALL]), &db->files_st, NULL) != SQLITE_OK){ + pdebug(__func__, "failed to prepare statement for selecting all: %s", sqlite3_errmsg(db->files_db)); + lm_error_set(LM_ERR_DbSqlPrepareFail); + return false; + } + + sqlite3_bind_text(db->files_st, FILES_COLUMN_PACKAGE, pkg->name, strlen(pkg->name), SQLITE_STATIC); + + while(sqlite3_step(db->files_st) == SQLITE_ROW) + count++; +end: + if(NULL != db->files_st){ + sqlite3_finalize(db->files_st); + db->files_st = NULL; + } + return count; +} + +bool lm_database_files_contains(lm_database_t *db, lm_pkg_t *pkg, char *path){ + char *package = NULL; + bool ret = false; + + if(NULL == db || NULL == path){ + lm_error_set(LM_ERR_ArgNULL); + goto end; + } + + if(sqlite3_prepare(db->files_db, queries[QUERY_SELECT_FILE_SINGLE], strlen(queries[QUERY_SELECT_FILE_SINGLE]), &db->files_st, NULL) != SQLITE_OK){ + pdebug(__func__, "failed to prepare statement for selecting %s: %s", path, sqlite3_errmsg(db->files_db)); + lm_error_set(LM_ERR_DbSqlPrepareFail); + goto end; + } + + sqlite3_bind_text(db->files_st, FILES_COLUMN_PATH, path, strlen(path), SQLITE_STATIC); + + if(sqlite3_step(db->files_st) != SQLITE_ROW){ + pdebug(__func__, "failed to execute select statement for selecting %s: %s", path, sqlite3_errmsg(db->files_db)); + lm_error_set(LM_ERR_DbSqlSelectFail); + goto end; + } + + package = (char*)sqlite3_column_text(db->files_st, FILES_COLUMN_PACKAGE-1); + ret = eq(package, pkg->name); +end: + if(NULL != db->files_st){ + sqlite3_finalize(db->files_st); + db->files_st = NULL; + } + return ret; +} + bool lm_database_files_matches(lm_database_t *db, char *path, char *hash){ char *hashdb = NULL; bool ret = false; @@ -25,15 +85,15 @@ bool lm_database_files_matches(lm_database_t *db, char *path, char *hash){ goto end; } - sqlite3_bind_text(db->files_st, 1, path, strlen(path), SQLITE_STATIC); + sqlite3_bind_text(db->files_st, FILES_COLUMN_PATH, path, strlen(path), SQLITE_STATIC); - if(sqlite3_step(db->files_st) != SQLITE_DONE){ + if(sqlite3_step(db->files_st) != SQLITE_ROW){ pdebug(__func__, "failed to execute select statement for selecting %s: %s", path, sqlite3_errmsg(db->files_db)); lm_error_set(LM_ERR_DbSqlSelectFail); goto end; } - hashdb = (char*)sqlite3_column_text(db->files_st, 1); + hashdb = (char*)sqlite3_column_text(db->files_st, FILES_COLUMN_HASH-1); ret = eq(hashdb, hash); end: @@ -59,15 +119,15 @@ bool lm_database_files_iskeep(lm_database_t *db, char *path){ goto end; } - sqlite3_bind_text(db->files_st, 1, path, strlen(path), SQLITE_STATIC); + sqlite3_bind_text(db->files_st, FILES_COLUMN_PATH, path, strlen(path), SQLITE_STATIC); - if(sqlite3_step(db->files_st) != SQLITE_DONE){ + if(!lm_database_step_all(db->files_st)){ pdebug(__func__, "failed to execute select statement for selecting %s: %s", path, sqlite3_errmsg(db->files_db)); lm_error_set(LM_ERR_DbSqlSelectFail); goto end; } - iskeep = sqlite3_column_int64(db->files_st, 2); + iskeep = sqlite3_column_int64(db->files_st, FILES_COLUMN_KEEP-1); ret = iskeep == 1; end: @@ -79,38 +139,6 @@ end: } -bool lm_database_files_next(lm_database_t *db, lm_pkg_t *pkg, char **path, char **hash, bool *keep){ - if(NULL == db || NULL == pkg || NULL == path || NULL == hash || NULL == keep){ - lm_error_set(LM_ERR_ArgNULL); - return false; - } - - if(NULL == db->files_st && - sqlite3_prepare(db->files_db, queries[QUERY_SELECT_FILE_ALL], strlen(queries[QUERY_SELECT_FILE_ALL]), &db->files_st, NULL) != SQLITE_OK){ - pdebug(__func__, "failed to prepare statement for selecting all: %s", sqlite3_errmsg(db->files_db)); - lm_error_set(LM_ERR_DbSqlPrepareFail); - return false; - } - - else if(NULL != db->files_st){ - free(*path); - free(*hash); - *path = NULL; - *hash = NULL; - } - - if(sqlite3_step(db->files_st) != SQLITE_ROW){ - sqlite3_finalize(db->files_st); - db->files_st = NULL; - return false; - } - - *path = strdup((char*)sqlite3_column_text(db->files_st, 0)); - *hash = strdup((char*)sqlite3_column_text(db->files_st, 1)); - *keep = sqlite3_column_int(db->files_st, 2) == 1; - return true; -} - bool lm_database_files_add(lm_database_t *db, lm_pkg_t *pkg, char *path, char *hash){ bool ret = false; @@ -125,15 +153,15 @@ bool lm_database_files_add(lm_database_t *db, lm_pkg_t *pkg, char *path, char *h goto end; } - sqlite3_bind_text(db->files_st, 1, path, strlen(path), SQLITE_STATIC); - sqlite3_bind_text(db->files_st, 2, hash, strlen(hash), SQLITE_STATIC); + sqlite3_bind_text(db->files_st, FILES_COLUMN_PATH, path, strlen(path), SQLITE_STATIC); + sqlite3_bind_text(db->files_st, FILES_COLUMN_HASH, hash, strlen(hash), SQLITE_STATIC); if(lm_package_keep_contains(pkg, path)) - sqlite3_bind_int(db->files_st, 3, 1); + sqlite3_bind_int(db->files_st, FILES_COLUMN_KEEP, 1); else - sqlite3_bind_int(db->files_st, 3, 0); - sqlite3_bind_text(db->files_st, 4, pkg->name, strlen(pkg->name), SQLITE_STATIC); + sqlite3_bind_int(db->files_st, FILES_COLUMN_KEEP, 0); + sqlite3_bind_text(db->files_st, FILES_COLUMN_PACKAGE, pkg->name, strlen(pkg->name), SQLITE_STATIC); - if(sqlite3_step(db->files_st) != SQLITE_DONE){ + if(!lm_database_step_all(db->files_st)){ pdebug(__func__, "failed to execute insert statement for inserting %s: %s", pkg->name, sqlite3_errmsg(db->files_db)); lm_error_set(LM_ERR_DbSqlInsertFail); goto end; @@ -162,9 +190,9 @@ bool lm_database_files_del(lm_database_t *db, lm_pkg_t *pkg){ goto end; } - sqlite3_bind_text(db->files_st, 1, pkg->name, strlen(pkg->name), SQLITE_STATIC); + sqlite3_bind_text(db->files_st, FILES_COLUMN_PACKAGE, pkg->name, strlen(pkg->name), SQLITE_STATIC); - if(sqlite3_step(db->files_st) != SQLITE_DONE){ + if(!lm_database_step_all(db->files_st)){ pdebug(__func__, "failed to execute delete statement for deleting %s: %s", pkg->name, sqlite3_errmsg(db->files_db)); lm_error_set(LM_ERR_DbSqlDeleteFail); goto end; @@ -178,3 +206,55 @@ end: } return ret; } + +bool lm_database_files_next(lm_database_t *db, lm_pkg_t *pkg, char **path, char **hash, bool *keep){ + if(NULL == db || NULL == pkg || NULL == path || NULL == hash || NULL == keep){ + lm_error_set(LM_ERR_ArgNULL); + return false; + } + + if(NULL == db->files_st){ + if(sqlite3_prepare(db->files_db, queries[QUERY_SELECT_FILE_ALL], strlen(queries[QUERY_SELECT_FILE_ALL]), &db->files_st, NULL) != SQLITE_OK){ + pdebug(__func__, "failed to prepare statement for selecting all: %s", sqlite3_errmsg(db->files_db)); + lm_error_set(LM_ERR_DbSqlPrepareFail); + return false; + } + sqlite3_bind_text(db->files_st, FILES_COLUMN_PACKAGE, pkg->name, strlen(pkg->name), SQLITE_STATIC); + } + + else if(NULL != db->files_st){ + free(*path); + free(*hash); + *path = NULL; + *hash = NULL; + } + + if(sqlite3_step(db->files_st) != SQLITE_ROW){ + sqlite3_finalize(db->files_st); + db->files_st = NULL; + return false; + } + + *path = strdup((char*)sqlite3_column_text(db->files_st, FILES_COLUMN_PATH-1)); + *hash = strdup((char*)sqlite3_column_text(db->files_st, FILES_COLUMN_HASH-1)); + *keep = sqlite3_column_int(db->files_st, FILES_COLUMN_KEEP-1) == 1; + return true; +} + +void lm_database_files_next_free(lm_database_t *db, lm_pkg_t *pkg, char **path, char **hash, bool *keep){ + if(NULL == db || NULL == pkg || NULL == path || NULL == hash || NULL == keep){ + lm_error_set(LM_ERR_ArgNULL); + return; + } + + if(NULL != db->files_st) + sqlite3_finalize(db->files_st); + + if(NULL == *path) + free(*path); + + if(NULL == *hash) + free(*hash); + + *keep = false; +} diff --git a/src/database/package.c b/src/database/package.c index f0cc1d4..43e1a0c 100644 --- a/src/database/package.c +++ b/src/database/package.c @@ -8,7 +8,7 @@ #include #include -bool lm_database_packege_add(lm_database_t *db, lm_pkg_t *pkg){ +bool lm_database_package_add(lm_database_t *db, lm_pkg_t *pkg){ if(NULL == db || NULL == pkg){ lm_error_set(LM_ERR_ArgNULL); return false; @@ -23,16 +23,16 @@ bool lm_database_packege_add(lm_database_t *db, lm_pkg_t *pkg){ goto end; } - sqlite3_bind_text(db->packages_st, 1, pkg->name, strlen(pkg->name), SQLITE_STATIC); - sqlite3_bind_text(db->packages_st, 2, pkg->desc, strlen(pkg->desc), SQLITE_STATIC); - sqlite3_bind_text(db->packages_st, 3, pkg->version, strlen(pkg->version), SQLITE_STATIC); - sqlite3_bind_int64(db->packages_st, 4, pkg->size); + sqlite3_bind_text(db->packages_st, PACKAGES_COLUMN_NAME, pkg->name, strlen(pkg->name), SQLITE_STATIC); + sqlite3_bind_text(db->packages_st, PACKAGES_COLUMN_DESC, pkg->desc, strlen(pkg->desc), SQLITE_STATIC); + sqlite3_bind_text(db->packages_st, PACKAGES_COLUMN_VERSION, pkg->version, strlen(pkg->version), SQLITE_STATIC); + sqlite3_bind_int64(db->packages_st, PACKAGES_COLUMN_SIZE, pkg->size); if(!lm_package_depend_tostr(pkg, depends)){ pdebug(__func__, "failed to convert depends to string for inserting %s: %s", pkg->name, lm_strerror()); goto end; } - sqlite3_bind_text(db->packages_st, 5, depends, strlen(depends), SQLITE_STATIC); + sqlite3_bind_text(db->packages_st, PACKAGES_COLUMN_DEPENDS, depends, strlen(depends), SQLITE_STATIC); if(sqlite3_step(db->packages_st) != SQLITE_DONE){ pdebug(__func__, "failed to execute insert statement for inserting %s: %s", pkg->name, sqlite3_errmsg(db->packages_db)); @@ -63,7 +63,7 @@ bool lm_database_package_find(lm_database_t *db, lm_pkg_t *pkg, char *name){ goto end; } - sqlite3_bind_text(db->packages_st, 1, name, strlen(name), SQLITE_STATIC); + sqlite3_bind_text(db->packages_st, PACKAGES_COLUMN_NAME, name, strlen(name), SQLITE_STATIC); if(sqlite3_step(db->packages_st) != SQLITE_ROW){ pdebug(__func__, "got no rows for %s", name); @@ -80,12 +80,12 @@ bool lm_database_package_find(lm_database_t *db, lm_pkg_t *pkg, char *name){ // we are initing it just in case the caller didn't lm_package_init(pkg); - pkg->name = strdup((char*)sqlite3_column_text(db->packages_st, 0)); - pkg->desc = strdup((char*)sqlite3_column_text(db->packages_st, 1)); - pkg->version = strdup((char*)sqlite3_column_text(db->packages_st, 2)); - pkg->size = sqlite3_column_int64(db->packages_st, 3); + 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)); + pkg->size = sqlite3_column_int64(db->packages_st, PACKAGES_COLUMN_SIZE-1); - char *depends = (char*)sqlite3_column_text(db->packages_st, 3); + char *depends = (char*)sqlite3_column_text(db->packages_st, PACKAGES_COLUMN_DEPENDS-1); if(!lm_package_depend_fromstr(pkg, depends)){ pdebug(__func__, "failed to load depends for finding %s: %s", pkg->name, lm_strerror()); // error is set by the function @@ -115,7 +115,7 @@ bool lm_database_package_del(lm_database_t *db, lm_pkg_t *pkg){ goto end; } - sqlite3_bind_text(db->packages_st, 1, pkg->name, strlen(pkg->name), SQLITE_STATIC); + sqlite3_bind_text(db->packages_st, PACKAGES_COLUMN_NAME, pkg->name, strlen(pkg->name), SQLITE_STATIC); if(sqlite3_step(db->packages_st) != SQLITE_DONE){ pdebug(__func__, "failed to execute delete statement for deleting %s: %s", pkg->name, sqlite3_errmsg(db->packages_db)); @@ -156,12 +156,12 @@ bool lm_database_package_next(lm_database_t *db, lm_pkg_t *pkg){ lm_package_init(pkg); - pkg->name = strdup((char*)sqlite3_column_text(db->packages_st, 0)); - pkg->desc = strdup((char*)sqlite3_column_text(db->packages_st, 1)); - pkg->version = strdup((char*)sqlite3_column_text(db->packages_st, 2)); - pkg->size = sqlite3_column_int64(db->packages_st, 3); + 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)); + pkg->size = sqlite3_column_int64(db->packages_st, PACKAGES_COLUMN_SIZE-1); - char *depends = (char*)sqlite3_column_text(db->packages_st, 3); + char *depends = (char*)sqlite3_column_text(db->packages_st, PACKAGES_COLUMN_DEPENDS-1); if(!lm_package_depend_fromstr(pkg, depends)){ pdebug(__func__, "failed to load depends for finding %s: %s", pkg->name, lm_strerror()); sqlite3_finalize(db->packages_st); @@ -171,3 +171,15 @@ bool lm_database_package_next(lm_database_t *db, lm_pkg_t *pkg){ return true; } +void lm_database_package_next_free(lm_database_t *db, lm_pkg_t *pkg){ + if(NULL == db || NULL == pkg){ + lm_error_set(LM_ERR_ArgNULL); + return; + } + + if(NULL != db->packages_st) + sqlite3_finalize(db->packages_st); + + if(NULL != pkg) + lm_package_free(pkg); +} diff --git a/src/error.c b/src/error.c index 3023b7a..01ff253 100644 --- a/src/error.c +++ b/src/error.c @@ -132,6 +132,16 @@ void lm_error_set(lm_error_t code, ...) { {.code = LM_ERR_SendReadFail, .desc = _("failed to read target file size for sending") }, {.code = LM_ERR_RecvBadSize, .desc = _("failed to parse target file size for receiving") }, {.code = LM_ERR_RecvNotCompleted, .desc = _("target file is not fully received") }, + {.code = LM_ERR_ExtractStatFail, .desc = _("failed to stat for target extract archive") }, + {.code = LM_ERR_PkgFilesAddFail, .desc = _("failed to add package file (%s) to the database: %s") }, + {.code = LM_ERR_PkgExtractFilesFail, .desc = _("failed to extract package files: %s") }, + {.code = LM_ERR_PkgDatabaseAddFail, .desc = _("failed to add package to the database: %s") }, + {.code = LM_ERR_PkgAlreadyInstalled, .desc = _("package is already installed") }, + {.code = LM_ERR_PkgNotInstalled, .desc = _("package is not installed") }, + {.code = LM_ERR_PkgFileUnlinkFail, .desc = _("failed to remove package file (%s): %s") }, + {.code = LM_ERR_PkgDatabaseDelFail, .desc = _("failed to remove package from the database: %s") }, + {.code = LM_ERR_PkgFilesDelFail, .desc = _("failed to remove package files from the database: %s") }, + {.code = LM_ERR_PkgChangesDelFail, .desc = _("failed to remove changes file for package: %s") }, }; char *fmt = NULL;