From 216ca5c9ddd4db0d2e317038f5365cd3554dd180 Mon Sep 17 00:00:00 2001 From: ngn Date: Mon, 8 Jul 2024 12:49:22 +0300 Subject: [PATCH] update: add version support to database find, better depend checking for resolve --- README.md | 3 +- examples/client/remove.c | 5 +- include/ctx.h | 2 +- include/database.h | 37 ++--- include/error.h | 6 + locale/tr/LC_MESSAGES/libmp.po | 27 +++- src/ctx/database.c | 15 +- src/ctx/install.c | 49 ++++++- src/ctx/resolve.c | 11 +- src/database/database.c | 7 +- src/database/package.c | 12 +- src/error.c | 259 +++++++++++++++++---------------- 12 files changed, 264 insertions(+), 169 deletions(-) diff --git a/README.md b/README.md index 5ce7750..86ae1a8 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ To this you will need the following tools and libraries: - libarchive - libinih - gettext +- sqlite3 - gpgme After installing these dependencies, you should download the latest release. @@ -39,5 +40,5 @@ make examples ``` To run the examples, specify the library path: ```bash -LD_LIBRARY_PATH=./dist ./dist/example_version +LD_LIBRARY_PATH=./dist ./dist/server ``` diff --git a/examples/client/remove.c b/examples/client/remove.c index ae55f26..1994beb 100644 --- a/examples/client/remove.c +++ b/examples/client/remove.c @@ -10,6 +10,8 @@ int main(int argc, char *argv[]) { lm_pkg_t pkg; lm_ctx_t ctx; + lm_package_init(&pkg); + if (argc != 2) { printf("usage: %s \n", argv[0]); return ret; @@ -37,7 +39,7 @@ int main(int argc, char *argv[]) { goto end; } - if (!lm_ctx_database_find(&ctx, &pkg, argv[1])) { + if (!lm_ctx_database_find(&ctx, &pkg, argv[1], NULL)) { printf("failed to find package: %s (%d)\n", lm_strerror(), lm_error()); goto end; } @@ -50,6 +52,7 @@ int main(int argc, char *argv[]) { ret = EXIT_SUCCESS; end: + lm_package_free(&pkg); lm_ctx_free(&ctx); return ret; } diff --git a/include/ctx.h b/include/ctx.h index 2278c4c..fcca97c 100644 --- a/include/ctx.h +++ b/include/ctx.h @@ -98,6 +98,6 @@ 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); // find a package by name +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 diff --git a/include/database.h b/include/database.h index ffc328c..85ac649 100644 --- a/include/database.h +++ b/include/database.h @@ -5,18 +5,19 @@ #define HASH_LEN 32 enum lm_query_index { - QUERY_CREATE_PACKAGE_TABLE = 0, - QUERY_INSERT_PACKAGE_SINGLE = 1, - QUERY_SELECT_PACKAGE_SINGLE = 2, - QUERY_DELETE_PACKAGE_SINGLE = 3, - QUERY_SELECT_PACKAGE_ALL = 4, - QUERY_CREATE_FILE_TABLE = 5, - QUERY_INSERT_FILE_SINGLE = 6, - QUERY_DELETE_FILE_ALL = 7, - QUERY_SELECT_FILE_SINGLE = 8, - QUERY_SELECT_FILE_ALL = 9, - QUERY_UPDATE_FILE_1 = 10, - QUERY_UPDATE_FILE_2 = 11, + QUERY_CREATE_PACKAGE_TABLE = 0, + QUERY_INSERT_PACKAGE_SINGLE = 1, + QUERY_SELECT_PACKAGE_SINGLE_1 = 2, + QUERY_SELECT_PACKAGE_SINGLE_2 = 3, + QUERY_DELETE_PACKAGE_SINGLE = 4, + QUERY_SELECT_PACKAGE_ALL = 5, + QUERY_CREATE_FILE_TABLE = 6, + QUERY_INSERT_FILE_SINGLE = 7, + QUERY_DELETE_FILE_ALL = 8, + QUERY_SELECT_FILE_SINGLE = 9, + QUERY_SELECT_FILE_ALL = 10, + QUERY_UPDATE_FILE_1 = 11, + QUERY_UPDATE_FILE_2 = 12, }; enum lm_columns { @@ -26,8 +27,8 @@ enum lm_columns { FILES_COLUMN_PACKAGE = 4, PACKAGES_COLUMN_NAME = 1, - PACKAGES_COLUMN_DESC = 2, - PACKAGES_COLUMN_VERSION = 3, + PACKAGES_COLUMN_VERSION = 2, + PACKAGES_COLUMN_DESC = 3, PACKAGES_COLUMN_SIZE = 4, PACKAGES_COLUMN_DEPENDS = 5, }; @@ -50,10 +51,10 @@ 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_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 + lm_database_t *db, lm_pkg_t *pkg, char *name, char *version); // 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_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 diff --git a/include/error.h b/include/error.h index fa8ff5b..8b65354 100644 --- a/include/error.h +++ b/include/error.h @@ -126,6 +126,12 @@ typedef enum lm_error { LM_ERR_PkgDatabaseDelFail = 119, LM_ERR_PkgFilesDelFail = 119, LM_ERR_PkgChangesDelFail = 120, + LM_ERR_InstallCwdFail = 121, + LM_ERR_InstallRootChdirFail = 122, + LM_ERR_InstallSpawnFail = 123, + LM_ERR_InstallBackChdirFail = 124, + LM_ERR_InstallStatusFail = 125, + LM_ERR_InstallScriptFail = 126, } lm_error_t; typedef struct lm_error_desc { diff --git a/locale/tr/LC_MESSAGES/libmp.po b/locale/tr/LC_MESSAGES/libmp.po index a65f913..b660996 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-08 07:22+0300\n" +"POT-Creation-Date: 2024-07-08 12:47+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -529,3 +529,28 @@ msgstr "" #, c-format msgid "failed to remove changes file for package: %s" msgstr "" + +#: src/error.c:145 +msgid "failed to get current directory for running install" +msgstr "" + +#: src/error.c:146 +msgid "failed change directory to root for running install" +msgstr "" + +#: src/error.c:147 +msgid "failed run install spawn command" +msgstr "" + +#: src/error.c:149 +msgid "failed to change directory to old directory after running install" +msgstr "" + +#: src/error.c:150 +msgid "install script returned a bad status code" +msgstr "" + +#: src/error.c:151 +#, c-format +msgid "failed to run the package install script: %s" +msgstr "" diff --git a/src/ctx/database.c b/src/ctx/database.c index 32bd8ef..97cafa3 100644 --- a/src/ctx/database.c +++ b/src/ctx/database.c @@ -19,22 +19,15 @@ bool lm_ctx_database_init(lm_ctx_t *ctx){ bool lm_ctx_database_is_installed(lm_ctx_t *ctx, lm_pkg_t *pkg, bool check_version){ if(!lm_ctx_database_init(ctx)) return false; // error set by function - lm_pkg_t found; if(NULL == ctx->db) return false; - if(!lm_database_package_find(ctx->db, &found, pkg->name)) - return false; // error set by function - - if(check_version && !eq(found.version, pkg->version)) - return false; - - return true; + return lm_database_package_find(ctx->db, NULL, pkg->name, check_version ? pkg->version : NULL); } -bool lm_ctx_database_find(lm_ctx_t *ctx, lm_pkg_t *pkg, char *name){ - if(NULL == ctx || NULL == pkg || NULL == name){ +bool lm_ctx_database_find(lm_ctx_t *ctx, lm_pkg_t *pkg, char *name, char *version){ + if(NULL == ctx || NULL == name){ lm_error_set(LM_ERR_ArgNULL); return false; } @@ -43,7 +36,7 @@ bool lm_ctx_database_find(lm_ctx_t *ctx, lm_pkg_t *pkg, char *name){ return false; // error set by function lm_error_clear(); - return lm_database_package_find(ctx->db, pkg, name); + 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){ diff --git a/src/ctx/install.c b/src/ctx/install.c index 497d10a..0d49871 100644 --- a/src/ctx/install.c +++ b/src/ctx/install.c @@ -4,6 +4,8 @@ #include "../../include/util.h" #include "../../include/ctx.h" +#include +#include #include #include #include @@ -12,6 +14,45 @@ #include #include +bool __lm_ctx_run_install(char *root, char *install_path) { + char *args[] = {"/bin/bash", install_path, NULL}, *oldpwd = NULL; + bool ret = false; + int status = 0; + pid_t pid = 0; + + if((oldpwd = getcwd(NULL, 0)) == NULL){ + lm_error_set(LM_ERR_InstallCwdFail); + goto end; + } + + if(chdir(root) < 0){ + lm_error_set(LM_ERR_InstallRootChdirFail); + goto end; + } + + if (posix_spawn(&pid, "/bin/bash", NULL, NULL, args, NULL) != 0) { + lm_error_set(LM_ERR_InstallSpawnFail); + goto end; + } + + waitpid(pid, &status, 0); + + if(chdir(root) < 0){ + lm_error_set(LM_ERR_InstallBackChdirFail); + goto end; + } + + if(status != 0){ + lm_error_set(LM_ERR_InstallStatusFail); + goto end; + } + + ret = true; +end: + free(oldpwd); + return ret; +} + 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; @@ -243,7 +284,13 @@ bool lm_ctx_install(lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_install_callback_t call goto end; } - // TODO: run install script + if(!__lm_ctx_run_install(ctx->root, install_file)){ + char *suberr = lm_strerror_dup(); + pdebug(__func__, "failed to run install script: %s", lm_strerror()); + lm_error_set(LM_ERR_InstallScriptFail, suberr); + free(suberr); + goto end; + } ret = true; end: diff --git a/src/ctx/resolve.c b/src/ctx/resolve.c index 9169869..0ef730d 100644 --- a/src/ctx/resolve.c +++ b/src/ctx/resolve.c @@ -15,19 +15,20 @@ bool __lm_ctx_resolve(lm_ctx_t *ctx, lm_ctx_resolve_list_t *list, lm_pkg_t *pkg) goto end; list->resolving = pkglist_add(list->resolving, pkg); + lm_pkg_t *depend = NULL; for(int i = 0; pkg->depends[i] != NULL; i++){ - // TODO: check if exists in the db before checking pools - lm_pkg_t *depend = lm_ctx_pool_find(ctx, pkg->depends[i], NULL); + // if found then its already installed + if(lm_ctx_database_find(ctx, NULL, pkg->depends[i], NULL)) + continue; + + depend = lm_ctx_pool_find(ctx, pkg->depends[i], NULL); if(NULL == depend){ lm_error_set(LM_ERR_DependNotFound, pkg->depends[i], pkg->name); return false; } - if(lm_ctx_database_is_installed(ctx, depend, true)) - continue; - if(pkglist_contains(list->resolving, depend)){ lm_error_set(LM_ERR_DependNotFound, pkg->depends[i], pkg->name); return false; diff --git a/src/database/database.c b/src/database/database.c index bc39c06..df958e9 100644 --- a/src/database/database.c +++ b/src/database/database.c @@ -12,17 +12,20 @@ char *queries[] = { // QUERY_CREATE_PACKAGE_TABLE "CREATE TABLE IF NOT EXISTS packages (" \ " name TEXT PRIMARY KEY NOT NULL," \ - " desc TEXT NOT NULL," \ " version TEXT NOT NULL," \ + " desc TEXT NOT NULL," \ " size INT NOT NULL," \ " depends TEXT NOT NULL);", // QUERY_INSERT_PACKAGE_SINGLE "INSERT INTO packages VALUES (?, ?, ?, ?, ?)", - // QUERY_SELECT_PACKAGE_SINGLE + // QUERY_SELECT_PACKAGE_SINGLE_1 "SELECT * FROM packages WHERE name = ?", + // QUERY_SELECT_PACKAGE_SINGLE_2 + "SELECT * FROM packages WHERE name = ? AND version = ?", + // QUERY_DELETE_PACKAGE_SINGLE "DELETE FROM packages WHERE name = ?", diff --git a/src/database/package.c b/src/database/package.c index 6702d62..34c5ffe 100644 --- a/src/database/package.c +++ b/src/database/package.c @@ -50,21 +50,29 @@ end: return ret; } -bool lm_database_package_find(lm_database_t *db, lm_pkg_t *pkg, char *name){ +bool lm_database_package_find(lm_database_t *db, lm_pkg_t *pkg, char *name, char *version){ if(NULL == db || NULL == name){ lm_error_set(LM_ERR_ArgNULL); return false; } bool ret = false; + char *query = NULL; - if(sqlite3_prepare(db->packages_db, queries[QUERY_SELECT_PACKAGE_SINGLE], strlen(queries[QUERY_SELECT_PACKAGE_SINGLE]), &db->packages_st, NULL) != SQLITE_OK){ + if(NULL == version) + query = queries[QUERY_SELECT_PACKAGE_SINGLE_1]; + else + query = queries[QUERY_SELECT_PACKAGE_SINGLE_2]; + + if(sqlite3_prepare(db->packages_db, query, strlen(query), &db->packages_st, NULL) != SQLITE_OK){ pdebug(__func__, "failed to prepare statement for finding %s: %s", name, sqlite3_errmsg(db->packages_db)); lm_error_set(LM_ERR_DbSqlPrepareFail); goto end; } sqlite3_bind_text(db->packages_st, PACKAGES_COLUMN_NAME, name, strlen(name), SQLITE_STATIC); + if(NULL != version) + sqlite3_bind_text(db->packages_st, PACKAGES_COLUMN_VERSION, version, strlen(version), SQLITE_STATIC); if(sqlite3_step(db->packages_st) != SQLITE_ROW){ pdebug(__func__, "got no rows for %s", name); diff --git a/src/error.c b/src/error.c index 01ff253..4088475 100644 --- a/src/error.c +++ b/src/error.c @@ -16,132 +16,139 @@ void lm_error_clear() { void lm_error_set(lm_error_t code, ...) { lm_error_desc_t errors[] = { - {.code = LM_ERR_NoError, .desc = _("no error") }, - {.code = LM_ERR_URLBadChar, .desc = _("URL contains an invalid character") }, - {.code = LM_ERR_URLBadProtocol, .desc = _("URL does not have a valid protocol field") }, - {.code = LM_ERR_URLTooLarge, .desc = _("URL is too large") }, - {.code = LM_ERR_URLHostLarge, .desc = _("URL hostname is too large") }, - {.code = LM_ERR_URLPathLarge, .desc = _("URL path is too large") }, - {.code = LM_ERR_URLBadHost, .desc = _("URL does not have a valid hostname") }, - {.code = LM_ERR_URLBadPort, .desc = _("URL does not have a valid port number") }, - {.code = LM_ERR_URLBadPath, .desc = _("URL does not have a valid path") }, - {.code = LM_ERR_BadPort, .desc = _("hostname does not contain a valid port number") }, - {.code = LM_ERR_BadHost, .desc = _("hostname is not valid") }, - {.code = LM_ERR_URLPortUnknown, .desc = _("URL protocol port number is unknown") }, - {.code = LM_ERR_URLEnd, .desc = _("URL is incomplete") }, - {.code = LM_ERR_PoolNoSupport, .desc = _("pool does not support the specified protocol") }, - {.code = LM_ERR_MPTPBadVersion, .desc = _("unsupported MPTP version") }, - {.code = LM_ERR_MPTPBadCode, .desc = _("invalid MPTP request/response code") }, - {.code = LM_ERR_MPTPBadUrl, .desc = _("invalid MPTP URL") }, - {.code = LM_ERR_MPTPHostFail, .desc = _("failed to resolve hostname for MPTP connection") }, - {.code = LM_ERR_MPTPSocketFail, .desc = _("failed to create a MPTP socket") }, - {.code = LM_ERR_MPTPConnectFail, .desc = _("failed to connect to the MPTP host") }, - {.code = LM_ERR_MPTPRecvFail, .desc = _("failed receive MPTP data from host") }, - {.code = LM_ERR_MPTPSendFail, .desc = _("failed send MPTP data to host") }, - {.code = LM_ERR_MPTPBadData, .desc = _("MPTP data size is invalid") }, - {.code = LM_ERR_MPTPBadHost, .desc = _("MPTP host size is invalid") }, - {.code = LM_ERR_MPTPSetsockopt, .desc = _("failed to set MPTP socket options") }, - {.code = LM_ERR_MPTPTimeout, .desc = _("MPTP connection timed out") }, - {.code = LM_ERR_MPTPBindFail, .desc = _("failed to bind MPTP socket") }, - {.code = LM_ERR_ArgNULL, .desc = _("required argument is a NULL pointer or 0") }, - {.code = LM_ERR_MPTPNotRequest, .desc = _("not a MPTP request") }, - {.code = LM_ERR_MPTPNotResponse, .desc = _("not a MPTP response") }, - {.code = LM_ERR_MPTPNotLast, .desc = _("MPTP request last flag is not set") }, - {.code = LM_ERR_MPTPNotLast, .desc = _("MPTP request last flag is not set") }, - {.code = LM_ERR_NoPort, .desc = _("host port not specified") }, - {.code = LM_ERR_PoolInfoBad, .desc = _("pool info is badly formatted or is not complete") }, - {.code = LM_ERR_ArcWBlockFail, .desc = _("failed to write block from archive") }, - {.code = LM_ERR_ArcRBlockFail, .desc = _("failed to read block from archive") }, - {.code = LM_ERR_ArcOpenFail, .desc = _("failed to open archive") }, - {.code = LM_ERR_ArcWHeaderFail, .desc = _("failed to write archive header") }, - {.code = LM_ERR_ArcWEntryFail, .desc = _("failed to finish writing the archive entry") }, - {.code = LM_ERR_ArcNewFail, .desc = _("failed to create new archive reader/writer") }, - {.code = LM_ERR_ArcRealpathFail, .desc = _("failed to resolve full path for archive file") }, - {.code = LM_ERR_ArcNextHeaderFail, .desc = _("failed to read the next header of the archive") }, - {.code = LM_ERR_GetCwdFail, .desc = _("failed to obtain current working directory") }, - {.code = LM_ERR_PoolListDirFail, .desc = _("failed to open extracted pool list directory") }, - {.code = LM_ERR_PoolListCantRead, .desc = _("failed to read access the pool list file") }, - {.code = LM_ERR_PoolInfoCantRead, .desc = _("failed to read access the pool info file") }, - {.code = LM_ERR_PkgDataBad, .desc = _("failed to parse package data") }, - {.code = LM_ERR_PkgBadName, .desc = _("package name is invalid") }, - {.code = LM_ERR_CtxDataNULL, .desc = _("data path is not set with in the ctx") }, - {.code = LM_ERR_CtxTempNULL, .desc = _("temp path is not set with in the ctx") }, - {.code = LM_ERR_CtxRootNULL, .desc = _("root path is not set with in the ctx") }, - {.code = LM_ERR_CtxTempFail, .desc = _("specified temp path does not exist") }, - {.code = LM_ERR_CtxTempNotDir, .desc = _("specified temp path is not a directory") }, - {.code = LM_ERR_CtxTempNoWrite, .desc = _("specified temp directory does not have write access") }, - {.code = LM_ERR_CtxRootFail, .desc = _("specified root path does not exist") }, - {.code = LM_ERR_CtxRootNotDir, .desc = _("specified root path is not a directory") }, - {.code = LM_ERR_CtxRootNoWrite, .desc = _("specified root directory does not have write access") }, - {.code = LM_ERR_CtxDataNotDir, .desc = _("specified data path does not exist") }, - {.code = LM_ERR_CtxDataNoWrite, .desc = _("specified data path is not a directory") }, - {.code = LM_ERR_CtxDataFailMkdir, .desc = _("failed to create specified data directory") }, - {.code = LM_ERR_PoolTestNotPong, .desc = _("pool did not respond ping with pong") }, - {.code = LM_ERR_PkgPathsEmpty, .desc = _("package file and directory paths are empty") }, - {.code = LM_ERR_SendOpenFail, .desc = _("failed to to open target file for sending") }, - {.code = LM_ERR_RecvDelFail, .desc = _("failed to to delete target file for receiving") }, - {.code = LM_ERR_RecvOpenFail, .desc = _("failed to to open target file for receiving") }, - {.code = LM_ERR_RecvBadCode, .desc = _("got a bad response code for receiving the target file") }, - {.code = LM_ERR_RecvWriteFail, .desc = _("failed to write to the target file for receiving") }, - {.code = LM_ERR_PkgNotFound, .desc = _("package not found") }, - {.code = LM_ERR_DbCantAccess, .desc = _("failed to access to the database file/directory") }, - {.code = LM_ERR_DbSqlOpenFail, .desc = _("failed to open SQLite database") }, - {.code = LM_ERR_DbSqlCreateFail, .desc = _("failed to create table in SQLite database") }, - {.code = LM_ERR_DbSqlPrepareFail, .desc = _("failed to prepare statement for SQLite database") }, - {.code = LM_ERR_DbSqlInsertFail, .desc = _("failed to insert to the table in SQLite database") }, - {.code = LM_ERR_DbSqlSelectFail, .desc = _("failed to select from the table in SQLite database") }, - {.code = LM_ERR_DbSqlDeleteFail, .desc = _("failed to delete from the table in SQLite database") }, - {.code = LM_ERR_DbSqlNotFound, .desc = _("failed to find entry in SQLite database") }, - {.code = LM_ERR_PkgGPGFail, .desc = _("failed to init GPG for package verification") }, - {.code = LM_ERR_PkgGPGSigFail, .desc = _("failed to import signature to GPG for package verification")}, - {.code = LM_ERR_PkgGPGArchiveFail, .desc = _("failed to import archive to GPG for package verification") }, - {.code = LM_ERR_PkgSigNoMatch, .desc = _("package signature verification failed with zero matches") }, - {.code = LM_ERR_PkgSigNoResult, .desc = _("package signature verification failed with zero results") }, - {.code = LM_ERR_PoolPathsEmpty, .desc = _("pool file and directory paths are empty") }, - {.code = LM_ERR_PoolNotAvailable, .desc = _("pool is not avaliable for connection") }, - {.code = LM_ERR_PoolUrlEmpty, .desc = _("pool URL is empty or invalid") }, - {.code = LM_ERR_PoolBadDir, .desc = _("pool directory path is not accessible") }, - {.code = LM_ERR_PoolBadPaths, .desc = _("pool directory sub-paths are not accessible") }, - {.code = LM_ERR_DbFilesNotFound, .desc = _("package file list not found in the database") }, - {.code = LM_ERR_DbFilesOpenFail, .desc = _("failed to open package file list in the database") }, - {.code = LM_ERR_DbFilesDirFail, .desc = _("failed to access package file list database directory") }, - {.code = LM_ERR_DbFilesUnlinkFail, .desc = _("failed to remove package file list from the database") }, - {.code = LM_ERR_DbFilesWriteFail, .desc = _("failed to write to the file list in the database") }, - {.code = LM_ERR_DbKeepsNotFound, .desc = _("package keep list not found in the database") }, - {.code = LM_ERR_DbKeepsOpenFail, .desc = _("failed to open package keep list in the database") }, - {.code = LM_ERR_DbKeepsDirFail, .desc = _("failed to access package keep list database directory") }, - {.code = LM_ERR_DbKeepsUnlinkFail, .desc = _("failed to remove package keep list from the database") }, - {.code = LM_ERR_DependNotFound, .desc = _("failed to find %s (dependency of %s)") }, - {.code = LM_ERR_InstallDownloadFail, .desc = _("failed to download %s for installation: %s") }, - {.code = LM_ERR_PkgNotDownloaded, .desc = _("package is not downloaded") }, - {.code = LM_ERR_PkgRemoveDownloadFail, .desc = _("failed to remove downloaded package") }, - {.code = LM_ERR_PkgRemoveDownloadFail, .desc = _("failed to remove downloaded package") }, - {.code = LM_ERR_DstOpenFail, .desc = _("failed to open the destination file") }, - {.code = LM_ERR_SrcOpenFail, .desc = _("failed to open the source file") }, - {.code = LM_ERR_DstWriteFail, .desc = _("failed to write to the destination file") }, - {.code = LM_ERR_DstWriteFail, .desc = _("failed to write to the destination file") }, - {.code = LM_ERR_PkgNoPool, .desc = _("package does not have associated pool") }, - {.code = LM_ERR_CtxTempFailMkdir, .desc = _("failed to create specified temp directory") }, - {.code = LM_ERR_PkgBadArchive, .desc = _("package archive does not contain required files") }, - {.code = LM_ERR_PkgDataNotMatch, .desc = _("package data does not match with target package") }, - {.code = LM_ERR_PkgChangesUpdateFail, .desc = _("failed to update changes file for package: %s") }, - {.code = LM_ERR_PkgHashesOpenFail, .desc = _("failed to access package hashes file") }, - {.code = LM_ERR_DbChangesUnlinkFail, .desc = _("failed to remove package changes file from the database") }, - {.code = LM_ERR_SendStatFail, .desc = _("failed to stat target file for sending") }, - {.code = LM_ERR_SendSnprintfFail, .desc = _("failed to format target file size for sending") }, - {.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") }, + {.code = LM_ERR_NoError, .desc = _("no error") }, + {.code = LM_ERR_URLBadChar, .desc = _("URL contains an invalid character") }, + {.code = LM_ERR_URLBadProtocol, .desc = _("URL does not have a valid protocol field") }, + {.code = LM_ERR_URLTooLarge, .desc = _("URL is too large") }, + {.code = LM_ERR_URLHostLarge, .desc = _("URL hostname is too large") }, + {.code = LM_ERR_URLPathLarge, .desc = _("URL path is too large") }, + {.code = LM_ERR_URLBadHost, .desc = _("URL does not have a valid hostname") }, + {.code = LM_ERR_URLBadPort, .desc = _("URL does not have a valid port number") }, + {.code = LM_ERR_URLBadPath, .desc = _("URL does not have a valid path") }, + {.code = LM_ERR_BadPort, .desc = _("hostname does not contain a valid port number") }, + {.code = LM_ERR_BadHost, .desc = _("hostname is not valid") }, + {.code = LM_ERR_URLPortUnknown, .desc = _("URL protocol port number is unknown") }, + {.code = LM_ERR_URLEnd, .desc = _("URL is incomplete") }, + {.code = LM_ERR_PoolNoSupport, .desc = _("pool does not support the specified protocol") }, + {.code = LM_ERR_MPTPBadVersion, .desc = _("unsupported MPTP version") }, + {.code = LM_ERR_MPTPBadCode, .desc = _("invalid MPTP request/response code") }, + {.code = LM_ERR_MPTPBadUrl, .desc = _("invalid MPTP URL") }, + {.code = LM_ERR_MPTPHostFail, .desc = _("failed to resolve hostname for MPTP connection") }, + {.code = LM_ERR_MPTPSocketFail, .desc = _("failed to create a MPTP socket") }, + {.code = LM_ERR_MPTPConnectFail, .desc = _("failed to connect to the MPTP host") }, + {.code = LM_ERR_MPTPRecvFail, .desc = _("failed receive MPTP data from host") }, + {.code = LM_ERR_MPTPSendFail, .desc = _("failed send MPTP data to host") }, + {.code = LM_ERR_MPTPBadData, .desc = _("MPTP data size is invalid") }, + {.code = LM_ERR_MPTPBadHost, .desc = _("MPTP host size is invalid") }, + {.code = LM_ERR_MPTPSetsockopt, .desc = _("failed to set MPTP socket options") }, + {.code = LM_ERR_MPTPTimeout, .desc = _("MPTP connection timed out") }, + {.code = LM_ERR_MPTPBindFail, .desc = _("failed to bind MPTP socket") }, + {.code = LM_ERR_ArgNULL, .desc = _("required argument is a NULL pointer or 0") }, + {.code = LM_ERR_MPTPNotRequest, .desc = _("not a MPTP request") }, + {.code = LM_ERR_MPTPNotResponse, .desc = _("not a MPTP response") }, + {.code = LM_ERR_MPTPNotLast, .desc = _("MPTP request last flag is not set") }, + {.code = LM_ERR_MPTPNotLast, .desc = _("MPTP request last flag is not set") }, + {.code = LM_ERR_NoPort, .desc = _("host port not specified") }, + {.code = LM_ERR_PoolInfoBad, .desc = _("pool info is badly formatted or is not complete") }, + {.code = LM_ERR_ArcWBlockFail, .desc = _("failed to write block from archive") }, + {.code = LM_ERR_ArcRBlockFail, .desc = _("failed to read block from archive") }, + {.code = LM_ERR_ArcOpenFail, .desc = _("failed to open archive") }, + {.code = LM_ERR_ArcWHeaderFail, .desc = _("failed to write archive header") }, + {.code = LM_ERR_ArcWEntryFail, .desc = _("failed to finish writing the archive entry") }, + {.code = LM_ERR_ArcNewFail, .desc = _("failed to create new archive reader/writer") }, + {.code = LM_ERR_ArcRealpathFail, .desc = _("failed to resolve full path for archive file") }, + {.code = LM_ERR_ArcNextHeaderFail, .desc = _("failed to read the next header of the archive") }, + {.code = LM_ERR_GetCwdFail, .desc = _("failed to obtain current working directory") }, + {.code = LM_ERR_PoolListDirFail, .desc = _("failed to open extracted pool list directory") }, + {.code = LM_ERR_PoolListCantRead, .desc = _("failed to read access the pool list file") }, + {.code = LM_ERR_PoolInfoCantRead, .desc = _("failed to read access the pool info file") }, + {.code = LM_ERR_PkgDataBad, .desc = _("failed to parse package data") }, + {.code = LM_ERR_PkgBadName, .desc = _("package name is invalid") }, + {.code = LM_ERR_CtxDataNULL, .desc = _("data path is not set with in the ctx") }, + {.code = LM_ERR_CtxTempNULL, .desc = _("temp path is not set with in the ctx") }, + {.code = LM_ERR_CtxRootNULL, .desc = _("root path is not set with in the ctx") }, + {.code = LM_ERR_CtxTempFail, .desc = _("specified temp path does not exist") }, + {.code = LM_ERR_CtxTempNotDir, .desc = _("specified temp path is not a directory") }, + {.code = LM_ERR_CtxTempNoWrite, .desc = _("specified temp directory does not have write access") }, + {.code = LM_ERR_CtxRootFail, .desc = _("specified root path does not exist") }, + {.code = LM_ERR_CtxRootNotDir, .desc = _("specified root path is not a directory") }, + {.code = LM_ERR_CtxRootNoWrite, .desc = _("specified root directory does not have write access") }, + {.code = LM_ERR_CtxDataNotDir, .desc = _("specified data path does not exist") }, + {.code = LM_ERR_CtxDataNoWrite, .desc = _("specified data path is not a directory") }, + {.code = LM_ERR_CtxDataFailMkdir, .desc = _("failed to create specified data directory") }, + {.code = LM_ERR_PoolTestNotPong, .desc = _("pool did not respond ping with pong") }, + {.code = LM_ERR_PkgPathsEmpty, .desc = _("package file and directory paths are empty") }, + {.code = LM_ERR_SendOpenFail, .desc = _("failed to to open target file for sending") }, + {.code = LM_ERR_RecvDelFail, .desc = _("failed to to delete target file for receiving") }, + {.code = LM_ERR_RecvOpenFail, .desc = _("failed to to open target file for receiving") }, + {.code = LM_ERR_RecvBadCode, .desc = _("got a bad response code for receiving the target file") }, + {.code = LM_ERR_RecvWriteFail, .desc = _("failed to write to the target file for receiving") }, + {.code = LM_ERR_PkgNotFound, .desc = _("package not found") }, + {.code = LM_ERR_DbCantAccess, .desc = _("failed to access to the database file/directory") }, + {.code = LM_ERR_DbSqlOpenFail, .desc = _("failed to open SQLite database") }, + {.code = LM_ERR_DbSqlCreateFail, .desc = _("failed to create table in SQLite database") }, + {.code = LM_ERR_DbSqlPrepareFail, .desc = _("failed to prepare statement for SQLite database") }, + {.code = LM_ERR_DbSqlInsertFail, .desc = _("failed to insert to the table in SQLite database") }, + {.code = LM_ERR_DbSqlSelectFail, .desc = _("failed to select from the table in SQLite database") }, + {.code = LM_ERR_DbSqlDeleteFail, .desc = _("failed to delete from the table in SQLite database") }, + {.code = LM_ERR_DbSqlNotFound, .desc = _("failed to find entry in SQLite database") }, + {.code = LM_ERR_PkgGPGFail, .desc = _("failed to init GPG for package verification") }, + {.code = LM_ERR_PkgGPGSigFail, .desc = _("failed to import signature to GPG for package verification")}, + {.code = LM_ERR_PkgGPGArchiveFail, .desc = _("failed to import archive to GPG for package verification") }, + {.code = LM_ERR_PkgSigNoMatch, .desc = _("package signature verification failed with zero matches") }, + {.code = LM_ERR_PkgSigNoResult, .desc = _("package signature verification failed with zero results") }, + {.code = LM_ERR_PoolPathsEmpty, .desc = _("pool file and directory paths are empty") }, + {.code = LM_ERR_PoolNotAvailable, .desc = _("pool is not avaliable for connection") }, + {.code = LM_ERR_PoolUrlEmpty, .desc = _("pool URL is empty or invalid") }, + {.code = LM_ERR_PoolBadDir, .desc = _("pool directory path is not accessible") }, + {.code = LM_ERR_PoolBadPaths, .desc = _("pool directory sub-paths are not accessible") }, + {.code = LM_ERR_DbFilesNotFound, .desc = _("package file list not found in the database") }, + {.code = LM_ERR_DbFilesOpenFail, .desc = _("failed to open package file list in the database") }, + {.code = LM_ERR_DbFilesDirFail, .desc = _("failed to access package file list database directory") }, + {.code = LM_ERR_DbFilesUnlinkFail, .desc = _("failed to remove package file list from the database") }, + {.code = LM_ERR_DbFilesWriteFail, .desc = _("failed to write to the file list in the database") }, + {.code = LM_ERR_DbKeepsNotFound, .desc = _("package keep list not found in the database") }, + {.code = LM_ERR_DbKeepsOpenFail, .desc = _("failed to open package keep list in the database") }, + {.code = LM_ERR_DbKeepsDirFail, .desc = _("failed to access package keep list database directory") }, + {.code = LM_ERR_DbKeepsUnlinkFail, .desc = _("failed to remove package keep list from the database") }, + {.code = LM_ERR_DependNotFound, .desc = _("failed to find %s (dependency of %s)") }, + {.code = LM_ERR_InstallDownloadFail, .desc = _("failed to download %s for installation: %s") }, + {.code = LM_ERR_PkgNotDownloaded, .desc = _("package is not downloaded") }, + {.code = LM_ERR_PkgRemoveDownloadFail, .desc = _("failed to remove downloaded package") }, + {.code = LM_ERR_PkgRemoveDownloadFail, .desc = _("failed to remove downloaded package") }, + {.code = LM_ERR_DstOpenFail, .desc = _("failed to open the destination file") }, + {.code = LM_ERR_SrcOpenFail, .desc = _("failed to open the source file") }, + {.code = LM_ERR_DstWriteFail, .desc = _("failed to write to the destination file") }, + {.code = LM_ERR_DstWriteFail, .desc = _("failed to write to the destination file") }, + {.code = LM_ERR_PkgNoPool, .desc = _("package does not have associated pool") }, + {.code = LM_ERR_CtxTempFailMkdir, .desc = _("failed to create specified temp directory") }, + {.code = LM_ERR_PkgBadArchive, .desc = _("package archive does not contain required files") }, + {.code = LM_ERR_PkgDataNotMatch, .desc = _("package data does not match with target package") }, + {.code = LM_ERR_PkgChangesUpdateFail, .desc = _("failed to update changes file for package: %s") }, + {.code = LM_ERR_PkgHashesOpenFail, .desc = _("failed to access package hashes file") }, + {.code = LM_ERR_DbChangesUnlinkFail, .desc = _("failed to remove package changes file from the database") }, + {.code = LM_ERR_SendStatFail, .desc = _("failed to stat target file for sending") }, + {.code = LM_ERR_SendSnprintfFail, .desc = _("failed to format target file size for sending") }, + {.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") }, + {.code = LM_ERR_InstallCwdFail, .desc = _("failed to get current directory for running install") }, + {.code = LM_ERR_InstallRootChdirFail, .desc = _("failed change directory to root for running install") }, + {.code = LM_ERR_InstallSpawnFail, .desc = _("failed run install spawn command") }, + {.code = LM_ERR_InstallBackChdirFail, + .desc = _("failed to change directory to old directory after running install") }, + {.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") }, }; char *fmt = NULL;