diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..f331a27 --- /dev/null +++ b/TODO.md @@ -0,0 +1,3 @@ +- Implement callbacks for recvfile and sendfile +- Remove/refactor unused functions +- Add all the ctx methods diff --git a/examples/client/main.c b/examples/client/main.c index 8c4235d..0ea66ea 100644 --- a/examples/client/main.c +++ b/examples/client/main.c @@ -30,7 +30,7 @@ int main(int argc, char *argv[]) { lm_ctx_pool_get_info(&ctx, true, true, NULL, NULL); lm_ctx_pool_get_list(&ctx, true, true, NULL, NULL); - if(!lm_ctx_install(&ctx, "which")){ + if (!lm_ctx_install(&ctx, "which")) { printf("failed to install the package: %s (%d)\n", lm_strerror(), lm_error()); goto end; } diff --git a/include/all.h b/include/all.h index c78b90b..6cf4314 100644 --- a/include/all.h +++ b/include/all.h @@ -28,3 +28,4 @@ #include "error.h" #include "pool.h" #include "types.h" +#include "util.h" diff --git a/include/ctx.h b/include/ctx.h index 369af8d..d018195 100644 --- a/include/ctx.h +++ b/include/ctx.h @@ -1,46 +1,97 @@ #pragma once #include "database.h" #include "types.h" + #include typedef struct lm_ctx { - lm_pool_t *pools; // pool list - char *root; // root path for package installtion - char *temp; // temp path - char *data; // package database path - const char *version; // libmp version (read-only) + lm_database_t *db; // package database + lm_pool_t *pools; // pool list + char *root; // root path for package installtion + char *temp; // temp path + char *data; // package database path + const char *version; // libmp version (read-only) } lm_ctx_t; -typedef bool (*lm_ctx_pool_callback_t)(lm_ctx_t *ctx, lm_pool_t *pool, bool status, void *data); -typedef bool (*lm_ctx_database_callback_t)(lm_ctx_t *ctx, lm_pkg_t *pkg, void *data); +typedef struct lm_ctx_resolve_list { + lm_pkg_t *resolving; + lm_pkg_t *packages; + lm_pkg_t *cur; + size_t count; +} lm_ctx_resolve_list_t; +typedef struct lm_ctx_update_list { + lm_pkg_t **packages; + size_t count; + size_t index; +} lm_ctx_update_list_t; + +/* ################### + ## ctx callbacks ## + ################### */ +typedef bool (*lm_ctx_database_callback_t)(lm_ctx_t *ctx, lm_pkg_t *pkg, void *data); +typedef bool (*lm_ctx_download_callback_t)(lm_ctx_t *ctx, lm_pkg_t *pkg, size_t current, size_t total, void *data); +typedef bool (*lm_ctx_install_callback_t)( + lm_ctx_t *ctx, lm_pkg_t *pkg, char *file, size_t current, size_t total, void *data); +typedef bool (*lm_ctx_sync_callback_t)( + lm_ctx_t *ctx, lm_pool_t *pool, bool status, size_t current, size_t total, void *data); +typedef lm_ctx_install_callback_t lm_ctx_remove_callback_t; +typedef lm_ctx_install_callback_t lm_ctx_check_callback_t; + +/* ############### + ## ctx stuff ## + ############### */ void lm_ctx_init(lm_ctx_t *ctx); bool lm_ctx_set_data(lm_ctx_t *ctx, char *dir); bool lm_ctx_set_root(lm_ctx_t *ctx, char *dir); bool lm_ctx_set_temp(lm_ctx_t *ctx, char *dir); void lm_ctx_free(lm_ctx_t *ctx); -lm_pkg_t *lm_ctx_find(lm_ctx_t *ctx, char *name, char *version); -bool lm_ctx_install(lm_ctx_t *ctx, char *package); -bool lm_ctx_remove(lm_ctx_t *ctx, char *package); -bool lm_ctx_verify(lm_ctx_t *ctx, char *package); -bool lm_ctx_update(lm_ctx_t *ctx); +/* #################### + ## main fucntions ## + #################### */ +lm_pkg_t *lm_ctx_find(lm_ctx_t *ctx, char *name, char *version); // find package by name (and version) -lm_pool_t *lm_ctx_pool_add(lm_ctx_t *ctx, char *name, char *url); -bool lm_ctx_pool_del(lm_ctx_t *ctx, char *name); -void lm_ctx_pool_clear(lm_ctx_t *ctx); -bool lm_ctx_pool_serve(lm_ctx_t *ctx, char *addr, uint8_t threads); -void lm_ctx_pool_test(lm_ctx_t *ctx, lm_ctx_pool_callback_t callback, void *data); -void lm_ctx_pool_get_info( - lm_ctx_t *ctx, bool allow_update, bool force_update, lm_ctx_pool_callback_t callback, void *data); -void lm_ctx_pool_get_list( - lm_ctx_t *ctx, bool allow_update, bool force_update, lm_ctx_pool_callback_t callback, void *data); +lm_ctx_resolve_list_t *lm_ctx_resolve( + lm_ctx_t *ctx, lm_pkg_t *pkg); // resolves a package and returns a list of packages to install +lm_pkg_t *lm_ctx_resolve_next(lm_ctx_t *ctx, lm_ctx_resolve_list_t *list); // returns the next package in the list +void lm_ctx_resolve_free( + lm_ctx_t *ctx, lm_ctx_resolve_list_t *list); // frees the resolved list returned by lm_ctx_resolve -bool lm_ctx_package_install(lm_ctx_t *ctx, lm_pkg_t *pkg); -bool lm_ctx_package_remove(lm_ctx_t *ctx, lm_pkg_t *pkg); -bool lm_ctx_package_verify(lm_ctx_t *ctx, lm_pkg_t *pkg); +lm_ctx_update_list_t *lm_ctx_update(lm_ctx_t *ctx); // returns a list of packages to update +lm_pkg_t *lm_ctx_update_next(lm_ctx_t *ctx, lm_ctx_update_list_t *list); // returns the next package in the list +void lm_ctx_update_free(lm_ctx_t *ctx, lm_ctx_update_list_t *list); // frees the update list returned by lm_ctx_update -lm_database_t *lm_ctx_database_new(lm_ctx_t *ctx); -bool lm_ctx_database_is_installed(lm_ctx_t *ctx, lm_pkg_t *pkg, bool check_version); -bool lm_ctx_database_find(lm_ctx_t *ctx, lm_pkg_t *pkg, char *name); -bool lm_ctx_database_foreach(lm_ctx_t *ctx, lm_ctx_database_callback_t callback, void *data); +bool lm_ctx_download(lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_download_callback_t callback, + void *data); // downloads a single package if its not already downloaded +bool lm_ctx_install( + lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_install_callback_t callback, void *data); // installs/updates a single package +bool lm_ctx_remove( + lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_remove_callback_t callback, void *data); // removes a single package +bool lm_ctx_check( + lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_check_callback_t callback, void *data); // checks a single package +bool lm_ctx_sync(lm_ctx_t *ctx, bool do_update, lm_ctx_sync_callback_t callback, void *data); // syncs all the pools +bool lm_ctx_serve(lm_ctx_t *ctx, char *add, uint8_t threads); // serves all the pools + +/* #################### + ## pool fucntions ## + #################### */ +lm_pool_t *lm_ctx_pool_add(lm_ctx_t *ctx, char *name, char *url); // add a pool to the ctx pool list +bool lm_ctx_pool_del(lm_ctx_t *ctx, char *name); // remove a pool from the ctx pool list +void lm_ctx_pool_clear(lm_ctx_t *ctx); // clear all the pools in the ctx pool list +bool lm_ctx_pool_serve( + lm_ctx_t *ctx, char *addr, uint8_t threads); // serve all the pools on a MPTP server hosted at the given address +void lm_ctx_pool_test(lm_ctx_t *ctx); // test (ping) all the pool connetions +void lm_ctx_pool_get_info(lm_ctx_t *ctx, bool do_update, lm_ctx_sync_callback_t callback, + void *data); // get pool info of all the pools in the ctx list +void lm_ctx_pool_get_list(lm_ctx_t *ctx, bool do_update, lm_ctx_sync_callback_t callback, + void *data); // get pool list of all the pools in the ctx list + +/* ######################## + ## database fucntions ## + ######################## */ +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_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 41017eb..21d0ec1 100644 --- a/include/database.h +++ b/include/database.h @@ -42,3 +42,7 @@ bool lm_database_keeps_foreach(lm_database_t *db, lm_pkg_t *pkg, lm_database_kee bool lm_database_keeps_load(lm_database_t *db, lm_pkg_t *pkg); bool lm_database_keeps_save(lm_database_t *db, lm_pkg_t *pkg); bool lm_database_keeps_del(lm_database_t *db, lm_pkg_t *pkg); + +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); +bool lm_database_changes_del(lm_database_t *db, lm_pkg_t *pkg); diff --git a/include/error.h b/include/error.h index 0e2907a..3cc6cf5 100644 --- a/include/error.h +++ b/include/error.h @@ -1,99 +1,102 @@ #pragma once +#define lm_strerror_dup() \ + { strdup(lm_strerror()) } + typedef enum lm_error { - LM_ERR_NoError = 0, - LM_ERR_URLBadChar = 1, - LM_ERR_URLBadProtocol = 2, - LM_ERR_URLTooLarge = 3, - LM_ERR_URLHostLarge = 4, - LM_ERR_URLPathLarge = 5, - LM_ERR_URLBadHost = 6, - LM_ERR_URLBadPort = 7, - LM_ERR_URLBadPath = 8, - LM_ERR_URLPortUnknown = 9, - LM_ERR_BadPort = 10, - LM_ERR_BadHost = 11, - LM_ERR_PoolNoSupport = 12, - LM_ERR_URLEnd = 13, - LM_ERR_MPTPBadVersion = 14, - LM_ERR_MPTPBadCode = 15, - LM_ERR_MPTPBadUrl = 16, - LM_ERR_MPTPHostFail = 17, - LM_ERR_MPTPSocketFail = 18, - LM_ERR_MPTPConnectFail = 19, - LM_ERR_MPTPRecvFail = 20, - LM_ERR_MPTPSendFail = 21, - LM_ERR_MPTPBadData = 22, - LM_ERR_MPTPBadHost = 23, - LM_ERR_MPTPSetsockopt = 24, - LM_ERR_MPTPTimeout = 25, - LM_ERR_MPTPBindFail = 26, - LM_ERR_ArgNULL = 27, - LM_ERR_MPTPNotResponse = 28, - LM_ERR_MPTPNotRequest = 29, - LM_ERR_MPTPNotLast = 30, - LM_ERR_NoPort = 31, - LM_ERR_PoolInfoBad = 32, - LM_ERR_ArcWBlockFail = 33, - LM_ERR_ArcRBlockFail = 34, - LM_ERR_ArcOpenFail = 35, - LM_ERR_ArcWHeaderFail = 36, - LM_ERR_ArcWEntryFail = 37, - LM_ERR_ArcNewFail = 38, - LM_ERR_ArcNextHeaderFail = 39, - LM_ERR_GetCwdFail = 39, - LM_ERR_PoolListDirFail = 40, - LM_ERR_PoolListCantRead = 41, - LM_ERR_PoolInfoCantRead = 42, - LM_ERR_PkgBadName = 43, - LM_ERR_PkgDataBad = 44, - LM_ERR_CtxDataNULL = 45, - LM_ERR_CtxTempFail = 46, - LM_ERR_CtxTempNotDir = 47, - LM_ERR_CtxTempNoWrite = 48, - LM_ERR_CtxRootFail = 49, - LM_ERR_CtxRootNotDir = 50, - LM_ERR_CtxRootNoWrite = 51, - LM_ERR_CtxDataNotDir = 52, - LM_ERR_CtxDataNoWrite = 53, - LM_ERR_CtxDataFailMkdir = 54, - LM_ERR_ArcRealpathFail = 55, - LM_ERR_PoolTestNotPong = 56, - LM_ERR_PkgPathsEmpty = 57, - LM_ERR_SendOpenFail = 58, - LM_ERR_RecvDelFail = 59, - LM_ERR_RecvOpenFail = 60, - LM_ERR_RecvBadCode = 61, - LM_ERR_RecvWriteFail = 62, - LM_ERR_PkgNotFound = 63, - LM_ERR_DbCantAccess = 64, - LM_ERR_DbSqlOpenFail = 65, - LM_ERR_DbSqlCreateFail = 66, - LM_ERR_DbSqlPrepareFail = 67, - LM_ERR_DbSqlInsertFail = 68, - LM_ERR_PkgGPGFail = 69, - LM_ERR_PkgGPGSigFail = 70, - LM_ERR_PkgGPGArchiveFail = 71, - LM_ERR_PkgSigNoMatch = 72, - LM_ERR_PkgSigNoResult = 73, - LM_ERR_PoolPathsEmpty = 74, - LM_ERR_PoolNotAvailable = 75, - LM_ERR_PoolUrlEmpty = 76, - LM_ERR_PoolBadDir = 77, - LM_ERR_PoolBadPaths = 78, - LM_ERR_DbFilesNotFound = 79, - LM_ERR_DbFilesOpenFail = 80, - LM_ERR_DbFilesDirFail = 81, - LM_ERR_DbFilesUnlinkFail = 82, - LM_ERR_DbFilesWriteFail = 83, - LM_ERR_DbKeepsNotFound = 84, - LM_ERR_DbKeepsOpenFail = 85, - LM_ERR_DbKeepsDirFail = 86, - LM_ERR_DbKeepsUnlinkFail = 87, - LM_ERR_DbSqlNotFound = 88, - LM_ERR_DependNotFound = 89, - LM_ERR_InstallDownloadFail = 90, - LM_ERR_PkgNotDownloaded = 91, + LM_ERR_NoError = 0, + LM_ERR_URLBadChar = 1, + LM_ERR_URLBadProtocol = 2, + LM_ERR_URLTooLarge = 3, + LM_ERR_URLHostLarge = 4, + LM_ERR_URLPathLarge = 5, + LM_ERR_URLBadHost = 6, + LM_ERR_URLBadPort = 7, + LM_ERR_URLBadPath = 8, + LM_ERR_URLPortUnknown = 9, + LM_ERR_BadPort = 10, + LM_ERR_BadHost = 11, + LM_ERR_PoolNoSupport = 12, + LM_ERR_URLEnd = 13, + LM_ERR_MPTPBadVersion = 14, + LM_ERR_MPTPBadCode = 15, + LM_ERR_MPTPBadUrl = 16, + LM_ERR_MPTPHostFail = 17, + LM_ERR_MPTPSocketFail = 18, + LM_ERR_MPTPConnectFail = 19, + LM_ERR_MPTPRecvFail = 20, + LM_ERR_MPTPSendFail = 21, + LM_ERR_MPTPBadData = 22, + LM_ERR_MPTPBadHost = 23, + LM_ERR_MPTPSetsockopt = 24, + LM_ERR_MPTPTimeout = 25, + LM_ERR_MPTPBindFail = 26, + LM_ERR_ArgNULL = 27, + LM_ERR_MPTPNotResponse = 28, + LM_ERR_MPTPNotRequest = 29, + LM_ERR_MPTPNotLast = 30, + LM_ERR_NoPort = 31, + LM_ERR_PoolInfoBad = 32, + LM_ERR_ArcWBlockFail = 33, + LM_ERR_ArcRBlockFail = 34, + LM_ERR_ArcOpenFail = 35, + LM_ERR_ArcWHeaderFail = 36, + LM_ERR_ArcWEntryFail = 37, + LM_ERR_ArcNewFail = 38, + LM_ERR_ArcNextHeaderFail = 39, + LM_ERR_GetCwdFail = 39, + LM_ERR_PoolListDirFail = 40, + LM_ERR_PoolListCantRead = 41, + LM_ERR_PoolInfoCantRead = 42, + LM_ERR_PkgBadName = 43, + LM_ERR_PkgDataBad = 44, + LM_ERR_CtxDataNULL = 45, + LM_ERR_CtxTempFail = 46, + LM_ERR_CtxTempNotDir = 47, + LM_ERR_CtxTempNoWrite = 48, + LM_ERR_CtxRootFail = 49, + LM_ERR_CtxRootNotDir = 50, + LM_ERR_CtxRootNoWrite = 51, + LM_ERR_CtxDataNotDir = 52, + LM_ERR_CtxDataNoWrite = 53, + LM_ERR_CtxDataFailMkdir = 54, + LM_ERR_ArcRealpathFail = 55, + LM_ERR_PoolTestNotPong = 56, + LM_ERR_PkgPathsEmpty = 57, + LM_ERR_SendOpenFail = 58, + LM_ERR_RecvDelFail = 59, + LM_ERR_RecvOpenFail = 60, + LM_ERR_RecvBadCode = 61, + LM_ERR_RecvWriteFail = 62, + LM_ERR_PkgNotFound = 63, + LM_ERR_DbCantAccess = 64, + LM_ERR_DbSqlOpenFail = 65, + LM_ERR_DbSqlCreateFail = 66, + LM_ERR_DbSqlPrepareFail = 67, + LM_ERR_DbSqlInsertFail = 68, + LM_ERR_PkgGPGFail = 69, + LM_ERR_PkgGPGSigFail = 70, + LM_ERR_PkgGPGArchiveFail = 71, + LM_ERR_PkgSigNoMatch = 72, + LM_ERR_PkgSigNoResult = 73, + LM_ERR_PoolPathsEmpty = 74, + LM_ERR_PoolNotAvailable = 75, + LM_ERR_PoolUrlEmpty = 76, + LM_ERR_PoolBadDir = 77, + LM_ERR_PoolBadPaths = 78, + LM_ERR_DbFilesNotFound = 79, + LM_ERR_DbFilesOpenFail = 80, + LM_ERR_DbFilesDirFail = 81, + LM_ERR_DbFilesUnlinkFail = 82, + LM_ERR_DbFilesWriteFail = 83, + LM_ERR_DbKeepsNotFound = 84, + LM_ERR_DbKeepsOpenFail = 85, + LM_ERR_DbKeepsDirFail = 86, + LM_ERR_DbKeepsUnlinkFail = 87, + LM_ERR_DbSqlNotFound = 88, + LM_ERR_DependNotFound = 89, + LM_ERR_InstallDownloadFail = 90, + LM_ERR_PkgNotDownloaded = 91, LM_ERR_PkgRemoveDownloadFail = 92, } lm_error_t; diff --git a/include/package.h b/include/package.h index 2dc0192..c0addcd 100644 --- a/include/package.h +++ b/include/package.h @@ -33,3 +33,4 @@ bool lm_package_path_set_signature(lm_pkg_t *pkg, char *signature_path); bool lm_package_path_set_archive(lm_pkg_t *pkg, char *archive_path); bool lm_package_path_is_empty(lm_pkg_t *pkg); void lm_package_path_free(lm_pkg_t *pkg); +bool lm_package_is_same(lm_pkg_t *one, lm_pkg_t *two); diff --git a/include/util.h b/include/util.h index 034d336..5d0caff 100644 --- a/include/util.h +++ b/include/util.h @@ -15,6 +15,7 @@ bool is_digit(char c); bool copy_from_buffer(void *dst, void *buffer, size_t size, ssize_t *total, ssize_t *used); bool copy_to_buffer(void *buffer, void *src, size_t size, ssize_t *total, ssize_t *used); +bool copy_file(char *dst, char *src); bool can_write(char *path); bool can_read(char *path); bool is_file(char *path); diff --git a/locale/tr/LC_MESSAGES/libmp.po b/locale/tr/LC_MESSAGES/libmp.po index e3f531a..f6da909 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-04 03:04+0300\n" +"POT-Creation-Date: 2024-07-04 03:19+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/src/ctx/ctx.c b/src/ctx/ctx.c index 7f1b663..865c4cf 100644 --- a/src/ctx/ctx.c +++ b/src/ctx/ctx.c @@ -2,6 +2,7 @@ #include "../../include/util.h" #include "../../include/ctx.h" +#include #include #include #include @@ -34,7 +35,10 @@ bool lm_ctx_set_temp(lm_ctx_t *ctx, char *dir){ return false; } - ctx->temp = strdup(dir); + char fullpath[PATH_MAX + 1]; + realpath(dir, fullpath); + + ctx->temp = strdup(fullpath); return true; } @@ -54,7 +58,10 @@ bool lm_ctx_set_root(lm_ctx_t *ctx, char *dir){ return false; } - ctx->root = strdup(dir); + char fullpath[PATH_MAX + 1]; + realpath(dir, fullpath); + + ctx->root = strdup(fullpath); return true; } @@ -74,7 +81,10 @@ bool lm_ctx_set_data(lm_ctx_t *ctx, char *dir){ return false; } - ctx->data = strdup(dir); + char fullpath[PATH_MAX + 1]; + realpath(dir, fullpath); + + ctx->data = strdup(fullpath); return true; } @@ -83,6 +93,9 @@ void lm_ctx_free(lm_ctx_t *ctx) { free(ctx->data); free(ctx->root); free(ctx->temp); + + if(NULL != ctx->db) + lm_database_free(ctx->db); lm_error_clear(); return; diff --git a/src/ctx/database.c b/src/ctx/database.c index 4aeec46..886bfeb 100644 --- a/src/ctx/database.c +++ b/src/ctx/database.c @@ -5,30 +5,32 @@ #include -lm_database_t *lm_ctx_database_new(lm_ctx_t *ctx){ +bool lm_ctx_database_init(lm_ctx_t *ctx){ + if(ctx->db != NULL) + return true; + char dbpath[strlen(ctx->data)+10]; join(dbpath, ctx->data, "db"); - return lm_database_new(dbpath); + + ctx->db = lm_database_new(dbpath); + return ctx->db != NULL; // error set by function } bool lm_ctx_database_is_installed(lm_ctx_t *ctx, lm_pkg_t *pkg, bool check_version){ - lm_database_t *db = lm_ctx_database_new(ctx); + if(!lm_ctx_database_init(ctx)) + return false; // error set by function lm_pkg_t found; - bool ret = false; - if(NULL == db) + if(NULL == ctx->db) return false; - if(!lm_database_find(db, &found, pkg->name)) - goto end; + if(!lm_database_find(ctx->db, &found, pkg->name)) + return false; // error set by function if(check_version && !eq(found.version, pkg->version)) - goto end; + return false; - ret = true; -end: - lm_database_free(db); - return ret; + return true; } bool lm_ctx_database_find(lm_ctx_t *ctx, lm_pkg_t *pkg, char *name){ @@ -37,10 +39,11 @@ bool lm_ctx_database_find(lm_ctx_t *ctx, lm_pkg_t *pkg, char *name){ return false; } - lm_database_t *db = lm_ctx_database_new(ctx); - if(!lm_database_find(db, pkg, name)) - return false; - return true; + if(!lm_ctx_database_init(ctx)) + return false; // error set by function + + lm_error_clear(); + return lm_database_find(ctx->db, pkg, name); } bool lm_ctx_database_foreach(lm_ctx_t *ctx, lm_ctx_database_callback_t callback, void *data){ @@ -48,11 +51,13 @@ bool lm_ctx_database_foreach(lm_ctx_t *ctx, lm_ctx_database_callback_t callback, lm_error_set(LM_ERR_ArgNULL); return false; } - - lm_database_t *db = lm_ctx_database_new(ctx); + + if(!lm_ctx_database_init(ctx)) + return false; // error set by function + lm_pkg_t pkg; - while(lm_database_next(db, &pkg)){ + while(lm_database_next(ctx->db, &pkg)){ if(!callback(ctx, &pkg, data)) break; } diff --git a/src/ctx/install.c b/src/ctx/install.c index e7b84d0..ad4d9d1 100644 --- a/src/ctx/install.c +++ b/src/ctx/install.c @@ -7,82 +7,90 @@ #include #include -typedef struct install_list { - lm_pkg_t *packages; - lm_pkg_t *resolving; - size_t count; -} install_list_t; - -bool install_resolve(lm_ctx_t *ctx, install_list_t *list, lm_pkg_t *pkg){ - if(pkglist_contains(list->packages, pkg)) - return true; - - if(NULL == pkg->depends) - goto end; - - list->resolving = pkglist_add(list->resolving, pkg); - - for(int i = 0; pkg->depends[i] != NULL; i++){ - lm_pkg_t *depend = lm_ctx_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; - } - - if(!install_resolve(ctx, list, pkg)) - return false; +bool lm_ctx_install(lm_ctx_t *ctx, lm_pkg_t *pkg, lm_ctx_install_callback_t callback, void *data) { + if(NULL == ctx->temp){ + lm_error_set(LM_ERR_CtxTempNULL); + return false; } - list->resolving = pkglist_del(list->resolving, pkg); -end: - list->packages = pkglist_add(list->packages, pkg); - list->count++; - return true; -} + if(NULL == ctx->root){ + lm_error_set(LM_ERR_CtxRootNULL); + return false; + } -bool lm_ctx_install(lm_ctx_t *ctx, char *package){ - lm_pkg_t *pkg = lm_ctx_find(ctx, package, NULL); - install_list_t list = { - .packages = NULL, - .resolving = NULL, - .count = 0, - }; + if(mkdir_ifnot(ctx->temp)){ + lm_error_set(LM_ERR_CtxTempFailMkdir); + return false; + } + + if(!lm_ctx_database_init(ctx)) + return false; // error set by function + + if(!extract_archive(ctx->temp, pkg->paths.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) || !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)){ + lm_error_set(LM_ERR_PkgBadArchive); + return false; + } + + if(!lm_package_data_load(&temp, data_file)) + return false; // error set by function + + if(!lm_package_is_same(&temp, pkg)){ + lm_error_set(LM_ERR_PkgDataNotMatch); + return false; + } + + if(!lm_database_changes_update(ctx->db, pkg, changes_file)){ + char *suberr = lm_strerror_dup(); + lm_error_set(LM_ERR_PkgChangesUpdateFail, suberr); + return false; + } + + char *line = NULL, *hash = NULL, *file = NULL; + size_t line_len = 0; + FILE *hashes = NULL; bool ret = false; - if(NULL == pkg) - return ret; - - if(!install_resolve(ctx, &list, pkg)) - goto end; - - pkg = list.packages; - - while(pkg != NULL){ - if(lm_package_downloaded(pkg) && lm_package_verify(pkg)) - continue; - - if(!lm_pool_package_download(pkg->pool, pkg)){ - char *suberror = strdup(lm_strerror()); - lm_error_set(LM_ERR_InstallDownloadFail, pkg->name, suberror); - free(suberror); - return false; - } - - pkg = pkg->next; + if((hashes = fopen(hashes_file, "r")) != NULL){ + lm_error_set(LM_ERR_PkgHashesOpenFail); + return false; } - // actually install packages + while((line_len = getline(&line, 0, hashes)) > 0){ + if(HASH_LEN+1 >= line_len) + continue; + line[HASH_LEN] = 0; + hash = line; + file = line+HASH_LEN+1; + + if(!lm_database_files_add(ctx->db, pkg, file, hash)) + return false; // error set by function + } + + ret = true; end: - pkglist_free(list.packages); - pkglist_free(list.resolving); - return true; + if(NULL != hashes) + fclose(hashes); + + return ret; } diff --git a/src/ctx/pakcage.c b/src/ctx/pakcage.c deleted file mode 100644 index e372f91..0000000 --- a/src/ctx/pakcage.c +++ /dev/null @@ -1,18 +0,0 @@ -#include "../../include/pool.h" -#include "../../include/package.h" -#include "../../include/database.h" -#include "../../include/util.h" -#include "../../include/error.h" -#include "../../include/ctx.h" - -bool lm_ctx_package_install(lm_ctx_t *ctx, lm_pkg_t *pkg){ - return true; -} - -bool lm_ctx_package_remove(lm_ctx_t *ctx, lm_pkg_t *pkg){ - return true; -} - -bool lm_ctx_package_verify(lm_ctx_t *ctx, lm_pkg_t *pkg){ - return true; -} diff --git a/src/ctx/resolve.c b/src/ctx/resolve.c new file mode 100644 index 0000000..0e497fa --- /dev/null +++ b/src/ctx/resolve.c @@ -0,0 +1,93 @@ +#include "../../include/package.h" +#include "../../include/error.h" +#include "../../include/pool.h" +#include "../../include/util.h" +#include "../../include/ctx.h" + +#include +#include + +bool __lm_ctx_resolve(lm_ctx_t *ctx, lm_ctx_resolve_list_t *list, lm_pkg_t *pkg){ + if(pkglist_contains(list->packages, pkg)) + return true; + + if(NULL == pkg->depends) + goto end; + + list->resolving = pkglist_add(list->resolving, pkg); + + for(int i = 0; pkg->depends[i] != NULL; i++){ + lm_pkg_t *depend = lm_ctx_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; + } + + if(!__lm_ctx_resolve(ctx, list, pkg)) + return false; + } + + list->resolving = pkglist_del(list->resolving, pkg); +end: + list->packages = pkglist_add(list->packages, pkg); + list->count++; + return true; +} + +lm_ctx_resolve_list_t *lm_ctx_resolve(lm_ctx_t *ctx, lm_pkg_t *pkg){ + if(NULL == ctx || NULL == pkg){ + lm_error_set(LM_ERR_ArgNULL); + return NULL; + } + + lm_ctx_resolve_list_t *list = malloc(sizeof(lm_ctx_resolve_list_t)); + list->resolving = NULL; + list->packages = NULL; + list->cur = NULL; + list->count = 0; + + if(!__lm_ctx_resolve(ctx, list, pkg)){ + pkglist_free(list->resolving); + pkglist_free(list->packages); + free(list); + return NULL; + } + + pkglist_free(list->resolving); + list->resolving = NULL; + return list; +} + +lm_pkg_t *lm_ctx_resolve_next(lm_ctx_t *ctx, lm_ctx_resolve_list_t *list){ + if(NULL == ctx || NULL == list){ + lm_error_set(LM_ERR_ArgNULL); + return NULL; + } + + if(NULL == list->cur){ + list->cur = list->packages; + return list->cur; + } + + list->cur = list->cur->next; + return list->cur; +} + +void lm_ctx_resolve_free(lm_ctx_t *ctx, lm_ctx_resolve_list_t *list){ + if(NULL == ctx || NULL == list){ + lm_error_set(LM_ERR_ArgNULL); + return; + } + + pkglist_free(list->packages); + free(list); + return; +} diff --git a/src/ctx/update.c b/src/ctx/update.c new file mode 100644 index 0000000..3e1b8a9 --- /dev/null +++ b/src/ctx/update.c @@ -0,0 +1,61 @@ +#include "../../include/package.h" +#include "../../include/database.h" +#include "../../include/error.h" +#include "../../include/pool.h" +#include "../../include/util.h" +#include "../../include/ctx.h" + +#include +#include + +lm_ctx_update_list_t *lm_ctx_update(lm_ctx_t *ctx){ + lm_ctx_update_list_t *list = malloc(sizeof(lm_ctx_update_list_t)); + list->packages = NULL; + list->index = 0; + list->count = 0; + + if(!lm_ctx_database_init(ctx)) + return NULL; + + lm_pkg_t *pkg = malloc(sizeof(lm_pkg_t)); + + while(lm_database_next(ctx->db, pkg)){ + if(NULL == list->packages) + list->packages = malloc(sizeof(lm_pkg_t*)); + else + list->packages = realloc(list->packages, (list->count+1)*sizeof(lm_pkg_t*)); + + list->packages[list->count++] = pkg; + pkg = malloc(sizeof(lm_pkg_t)); + } + + return list; +} + +lm_pkg_t *lm_ctx_update_next(lm_ctx_t *ctx, lm_ctx_update_list_t *list){ + if(NULL == ctx || NULL == list){ + lm_error_set(LM_ERR_ArgNULL); + return NULL; + } + + if(list->index >= list->count-1){ + list->index = 0; + return NULL; + } + + return list->packages[list->index++]; +} + +void lm_ctx_update_free(lm_ctx_t *ctx, lm_ctx_update_list_t *list){ + if(NULL == ctx || NULL == list){ + lm_error_set(LM_ERR_ArgNULL); + return; + } + + for(int i = 0; i < list->count; i++){ + lm_package_free(list->packages[i]); + free(list->packages[i]); + } + + free(list); +} diff --git a/src/database/changes.c b/src/database/changes.c new file mode 100644 index 0000000..966cd92 --- /dev/null +++ b/src/database/changes.c @@ -0,0 +1,52 @@ +#include "../../include/database.h" +#include "../../include/error.h" +#include "../../include/util.h" + +#include +#include +#include +#include + +bool lm_database_changes_update(lm_database_t *db, lm_pkg_t *pkg, char *file){ + if(NULL == db || NULL == pkg || NULL == file){ + lm_error_set(LM_ERR_ArgNULL); + return false; + } + + char changes_file[strlen(db->dir)+strlen(pkg->name)+20]; + join_multiple(changes_file, db->dir, pkg->name, "changes"); + + if(!copy_file(changes_file, file)) + return false; // error set by function + + return true; +} + +bool lm_database_changes_del(lm_database_t *db, lm_pkg_t *pkg){ + if(NULL == db || NULL == pkg){ + lm_error_set(LM_ERR_ArgNULL); + return false; + } + + char changes_file[strlen(db->dir)+strlen(pkg->name)+20]; + join_multiple(changes_file, db->dir, pkg->name, "changes"); + + if(unlink(changes_file) < 0 && errno != ENOENT){ + lm_error_set(LM_ERR_DbChangesUnlinkFail); + return false; + } + + return true; +} + +char *lm_database_changes_get(lm_database_t *db, lm_pkg_t *pkg){ + char *changes_file = malloc(strlen(db->dir)+strlen(pkg->name)+20); + join_multiple(changes_file, db->dir, pkg->name, "changes"); + + if(!exists(changes_file)){ + free(changes_file); + return NULL; + } + + return changes_file; +} diff --git a/src/database/files.c b/src/database/files.c index 262de1c..b4831ad 100644 --- a/src/database/files.c +++ b/src/database/files.c @@ -34,13 +34,11 @@ bool lm_database_files_foreach(lm_database_t *db, lm_pkg_t *pkg, lm_database_fil goto end; } - while(getline(&line, 0, files) > 0){ - line_len = strlen(line); - char path[line_len+1]; - + while((line_len = getline(&line, 0, files)) > 0){ if(HASH_LEN >= line_len) continue; + char path[line_len+1]; memcpy(path, line+HASH_LEN+1, line_len-HASH_LEN); memcpy(hash, line, HASH_LEN+1); hash[HASH_LEN] = 0; @@ -102,13 +100,13 @@ end: } bool lm_database_files_get(lm_database_t *db, lm_pkg_t *pkg, char *path, char *hash){ - if(NULL == db || NULL == pkg || NULL == path || NULL == hash){ + if(NULL == db || NULL == pkg || NULL == path){ lm_error_set(LM_ERR_ArgNULL); return false; } - // zero out the hash - bzero(hash, HASH_LEN+1); + if(NULL != hash) + bzero(hash, HASH_LEN+1); // zero out the hash char files_list[strlen(db->dir)+strlen(pkg->name)+10]; join_multiple(files_list, db->dir, pkg->name, "files"); @@ -119,8 +117,8 @@ bool lm_database_files_get(lm_database_t *db, lm_pkg_t *pkg, char *path, char *h } FILE *files = fopen(files_list, "r"); - char *line = NULL; size_t line_len = 0; + char *line = NULL; bool ret = false; if(NULL == files){ @@ -128,18 +126,18 @@ bool lm_database_files_get(lm_database_t *db, lm_pkg_t *pkg, char *path, char *h goto end; } - while(getline(&line, 0, files) > 0){ - line_len = strlen(line); - char lpath[line_len+1]; - + while((line_len = getline(&line, 0, files)) > 0){ if(HASH_LEN >= line_len) continue; + char lpath[line_len+1]; memcpy(lpath, line+HASH_LEN+1, line_len-HASH_LEN); if(eq(lpath, path)){ - memcpy(hash, line, HASH_LEN+1); - hash[HASH_LEN] = 0; + if(NULL != hash){ + memcpy(hash, line, HASH_LEN+1); + hash[HASH_LEN] = 0; + } ret = true; goto end; } diff --git a/src/error.c b/src/error.c index d5633df..fe44ce9 100644 --- a/src/error.c +++ b/src/error.c @@ -16,100 +16,102 @@ 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_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_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_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_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_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_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") }, }; char *fmt = NULL; @@ -134,9 +136,9 @@ void lm_error_set(lm_error_t code, ...) { va_start(args, code); va_copy(argscp, args); - int size = vsnprintf(NULL, 0, fmt, args); - error_str = malloc(size + 1); - vsnprintf(error_str, size, fmt, args); + int size = vsnprintf(NULL, 0, fmt, args) + 2; + error_str = malloc(size); + vsnprintf(error_str, size, fmt, argscp); va_end(args); va_end(argscp); diff --git a/src/package/package.c b/src/package/package.c index 41bbc14..2c5e621 100644 --- a/src/package/package.c +++ b/src/package/package.c @@ -47,6 +47,13 @@ bool lm_package_remove_download(lm_pkg_t *pkg){ return true; } +bool lm_package_is_same(lm_pkg_t *one, lm_pkg_t *two){ + return eq(one->version, two->version) && + eq(one->name, two->name) && + eq(one->desc, two->desc) && + one->size == two->size; +} + void lm_package_free(lm_pkg_t *pkg){ lm_package_data_free(pkg); bzero(pkg, sizeof(lm_pkg_t)); diff --git a/src/util.c b/src/util.c index f3d72ec..252ca7e 100644 --- a/src/util.c +++ b/src/util.c @@ -389,3 +389,38 @@ void pkglist_free(lm_pkg_t *list) { free(old); } } + +bool copy_file(char *dst, char *src) { + FILE *dstp = NULL, *srcp = NULL; + bool ret = false; + + if ((dstp = fopen(dst, "w")) == NULL) { + lm_error_set(LM_ERR_DstOpenFail); + goto end; + } + + if ((srcp = fopen(src, "r")) == NULL) { + lm_error_set(LM_ERR_SrcOpenFail); + goto end; + } + + char buf[255]; + size_t bufsize = sizeof(buf), read = 0; + + while ((read = fread(buf, 1, bufsize, srcp)) > 0) { + if (fwrite(buf, 1, read, dstp) <= 0) { + lm_error_set(LM_ERR_DstWriteFail); + goto end; + } + } + + ret = true; +end: + if (NULL != dstp) + fclose(dstp); + + if (NULL != srcp) + fclose(srcp); + + return ret; +}