diff --git a/Makefile b/Makefile index 0466f95..2683f74 100644 --- a/Makefile +++ b/Makefile @@ -22,9 +22,9 @@ dist/libmp.so: $(OBJS) dist/%.o: src/%.c mkdir -p dist/ctx - mkdir -p dist/pkg mkdir -p dist/mptp mkdir -p dist/pool + mkdir -p dist/package $(CC) -c -Wall -fPIC -o $@ $^ $(LIBS) $(CFLAGS) -DLM_VERSION=\"${VERSION}\" -DLM_DEBUG=${DEBUG} locale/%.mo: locale/%.po diff --git a/examples/client/main.c b/examples/client/main.c index 6d782ea..c47161a 100644 --- a/examples/client/main.c +++ b/examples/client/main.c @@ -21,14 +21,19 @@ int main(int argc, char *argv[]) { goto end; } - if (lm_ctx_pools_add(&ctx, "test", argv[1]) == NULL) { + if (lm_ctx_pool_add(&ctx, "base", argv[1]) == NULL) { printf("failed to add pool: %s (%d)\n", lm_strerror(), lm_error()); goto end; } - lm_ctx_pools_test(&ctx, NULL, NULL); - lm_ctx_pools_get_info(&ctx, true, NULL, NULL); - lm_ctx_pools_get_list(&ctx, true, NULL, NULL); + lm_ctx_pool_test(&ctx, NULL, NULL); + lm_ctx_pool_get_info(&ctx, true, true, NULL, NULL); + lm_ctx_pool_get_list(&ctx, true, true, NULL, NULL); + + if (lm_ctx_package_get(&ctx, "which", NULL) == NULL) { + printf("failed to get the package: %s (%d)\n", lm_strerror(), lm_error()); + goto end; + } ret = EXIT_SUCCESS; diff --git a/examples/pools/.gitignore b/examples/pools/.gitignore new file mode 100644 index 0000000..e422589 --- /dev/null +++ b/examples/pools/.gitignore @@ -0,0 +1 @@ +*/LIST_extracted diff --git a/examples/pools/test/INFO b/examples/pools/base/INFO similarity index 100% rename from examples/pools/test/INFO rename to examples/pools/base/INFO diff --git a/examples/pools/test/LIST b/examples/pools/base/LIST similarity index 100% rename from examples/pools/test/LIST rename to examples/pools/base/LIST diff --git a/examples/pools/test/grep_3.11.mpf b/examples/pools/base/grep_3.11.mpf similarity index 100% rename from examples/pools/test/grep_3.11.mpf rename to examples/pools/base/grep_3.11.mpf diff --git a/examples/pools/test/grep_3.11.mpf.sig b/examples/pools/base/grep_3.11.mpf.sig similarity index 100% rename from examples/pools/test/grep_3.11.mpf.sig rename to examples/pools/base/grep_3.11.mpf.sig diff --git a/examples/pools/test/which_2.21.mpf b/examples/pools/base/which_2.21.mpf similarity index 100% rename from examples/pools/test/which_2.21.mpf rename to examples/pools/base/which_2.21.mpf diff --git a/examples/pools/test/which_2.21.mpf.sig b/examples/pools/base/which_2.21.mpf.sig similarity index 100% rename from examples/pools/test/which_2.21.mpf.sig rename to examples/pools/base/which_2.21.mpf.sig diff --git a/examples/pools/test/.gitignore b/examples/pools/test/.gitignore deleted file mode 100644 index 4cc6347..0000000 --- a/examples/pools/test/.gitignore +++ /dev/null @@ -1 +0,0 @@ -LIST_extracted diff --git a/examples/server/main.c b/examples/server/main.c index 43a8d61..0d51d07 100644 --- a/examples/server/main.c +++ b/examples/server/main.c @@ -21,12 +21,15 @@ int main(int argc, char *argv[]) { goto end; } - if (lm_ctx_pools_add(&ctx, "test", "mptp://127.0.0.1:5858") == NULL) { + if (lm_ctx_pool_add(&ctx, "base", "mptp://127.0.0.1:5858") == NULL) { printf("failed to add pool: %s (%d)\n", lm_strerror(), lm_error()); goto end; } - if (!lm_ctx_pools_serve(&ctx, argv[1], 10)) { + lm_ctx_pool_get_info(&ctx, false, false, NULL, NULL); + lm_ctx_pool_get_list(&ctx, false, false, NULL, NULL); + + if (!lm_ctx_pool_serve(&ctx, argv[1], 10)) { printf("failed to serve the pools: %s (%d)\n", lm_strerror(), lm_error()); goto end; } diff --git a/include/ctx.h b/include/ctx.h index d163a58..fbefb88 100644 --- a/include/ctx.h +++ b/include/ctx.h @@ -2,7 +2,7 @@ #include "types.h" #include -typedef void (*lm_ctx_pools_callback_t)(lm_ctx_t *ctx, lm_pool_t *pool, bool status, void *data); +typedef void (*lm_ctx_pool_callback_t)(lm_ctx_t *ctx, lm_pool_t *pool, bool status, void *data); void lm_ctx_init(lm_ctx_t *ctx); bool lm_ctx_set_data(lm_ctx_t *ctx, char *dir); @@ -10,10 +10,15 @@ 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_pool_t *lm_ctx_pools_add(lm_ctx_t *ctx, char *name, char *url); -bool lm_ctx_pools_del(lm_ctx_t *ctx, char *name); -void lm_ctx_pools_clear(lm_ctx_t *ctx); -bool lm_ctx_pools_serve(lm_ctx_t *ctx, char *addr, uint8_t threads); -void lm_ctx_pools_test(lm_ctx_t *ctx, lm_ctx_pools_callback_t callback, void *data); -void lm_ctx_pools_get_info(lm_ctx_t *ctx, bool force_update, lm_ctx_pools_callback_t callback, void *data); -void lm_ctx_pools_get_list(lm_ctx_t *ctx, bool force_update, lm_ctx_pools_callback_t callback, void *data); +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_pkg_t *lm_ctx_package_install(lm_ctx_t *ctx, char *name, char *version); +lm_pkg_t *lm_ctx_package_get(lm_ctx_t *ctx, char *name, char *version); diff --git a/include/error.h b/include/error.h index e41f1e1..6beaef8 100644 --- a/include/error.h +++ b/include/error.h @@ -59,6 +59,13 @@ typedef enum lm_error { LM_ERR_CtxDataFailMkdir = 54, LM_ERR_ArcRealpathFail = 55, LM_ERR_PoolTestNotPong = 56, + LM_ERR_PackagePathsEmpty = 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_error_t; typedef struct lm_error_desc { diff --git a/include/package.h b/include/package.h new file mode 100644 index 0000000..4eb8a1e --- /dev/null +++ b/include/package.h @@ -0,0 +1,22 @@ +#pragma once +#include "types.h" +#include + +#define PKG_DATA_SIZE "size" +#define PKG_DATA_DESC "desc" +#define PKG_DATA_VERSION "version" +#define PKG_DATA_DEPENDS "depends" + +lm_pkg_t *lm_package_new(); +void lm_package_free(lm_pkg_t *pkg); + +bool lm_package_data_load(lm_pkg_t *pkg, char *file); +void lm_package_data_free(lm_pkg_t *pkg); + +bool lm_package_depend_add(lm_pkg_t *pkg, char *depend); +size_t lm_package_depend_count(lm_pkg_t *pkg); + +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); diff --git a/include/pkg.h b/include/pkg.h deleted file mode 100644 index 57b8751..0000000 --- a/include/pkg.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include "types.h" -#include - -#define PKG_DATA_SIZE "size" -#define PKG_DATA_DESC "desc" -#define PKG_DATA_VERSION "version" -#define PKG_DATA_DEPENDS "depends" - -lm_pkg_t *lm_pkg_new(); -void lm_pkg_free(lm_pkg_t *pkg); - -bool lm_pkg_data_load(lm_pkg_t *pkg, char *file); -void lm_pkg_data_free(lm_pkg_t *pkg); diff --git a/include/pool.h b/include/pool.h index 0fe67c7..8ffb678 100644 --- a/include/pool.h +++ b/include/pool.h @@ -19,12 +19,16 @@ typedef struct lm_pool_thread_arg { lm_pool_t *lm_pool_new(char *name, char *url); void lm_pool_test(lm_pool_t *pool); void lm_pool_free(lm_pool_t *pool); -bool lm_pool_add(lm_pool_t *pool, lm_pkg_t *pkg); -void lm_pool_paths_set_info(lm_pool_t *pool, char *info_path); -void lm_pool_paths_set_list(lm_pool_t *pool, char *list_path); -bool lm_pool_paths_is_empty(lm_pool_t *pool); -void lm_pool_paths_free(lm_pool_t *pool); +lm_pkg_t *lm_pool_package_find(lm_pool_t *pool, char *name, char *version); +bool lm_pool_package_add(lm_pool_t *pool, lm_pkg_t *pkg); +bool lm_pool_package_get(lm_pool_t *pool, lm_pkg_t *pkg); + +bool lm_pool_path_set_info(lm_pool_t *pool, char *info_path); +bool lm_pool_path_set_list(lm_pool_t *pool, char *list_path); +bool lm_pool_path_set_packages(lm_pool_t *pool, char *packaes_path); +bool lm_pool_path_is_empty(lm_pool_t *pool); +void lm_pool_path_free(lm_pool_t *pool); bool lm_pool_info_load(lm_pool_t *pool); bool lm_pool_info_get(lm_pool_t *pool); diff --git a/include/types.h b/include/types.h index 6b4ff42..fcbdfdc 100644 --- a/include/types.h +++ b/include/types.h @@ -1,32 +1,41 @@ #pragma once #include "url.h" + #include #include +#include + +typedef struct lm_pkg_path { + char *archive; + char *signature; +} lm_pkg_path_t; typedef struct lm_pkg { - size_t size; struct lm_pkg *next; + lm_pkg_path_t paths; char *name; char *desc; char **depends; char *version; + size_t size; } lm_pkg_t; typedef struct lm_pool_info { - char *maintainer; - char *pubkey; - size_t size; + char *maintainer; + char *pubkey; + ssize_t size; } lm_pool_info_t; -typedef struct lm_pool_paths { +typedef struct lm_pool_path { + char *packages; char *list; char *info; -} lm_pool_paths_t; +} lm_pool_path_t; typedef struct lm_pool { struct lm_pool *next; lm_pool_info_t info; - lm_pool_paths_t paths; + lm_pool_path_t paths; lm_url_t url; lm_pkg_t *pkg; bool available; diff --git a/include/util.h b/include/util.h index 1246634..9d69d3c 100644 --- a/include/util.h +++ b/include/util.h @@ -7,20 +7,30 @@ #define _(x) gettext(x) -void pdebug(const char *func, const char *fmt, ...); -bool parse_host(char *addr, char *host, uint16_t *port); bool contains(char *str, char s); bool eq(char *s1, char *s2); bool is_letter(char c); bool is_digit(char c); -bool copy_to_buffer(void *buffer, void *src, size_t size, ssize_t *total, ssize_t *used); + bool copy_from_buffer(void *dst, void *buffer, size_t size, ssize_t *total, ssize_t *used); -bool extract_archive(char *dst, char *src); -bool is_pkg_name_valid(char *name); -bool exists(char *path); +bool copy_to_buffer(void *buffer, void *src, size_t size, ssize_t *total, ssize_t *used); + +bool can_write(char *path); +bool can_read(char *path); bool is_file(char *path); bool is_dir(char *path); -bool can_read(char *path); -bool can_write(char *path); +bool exists(char *path); + +bool package_parse(char *package, char *name, char *version); +bool package_version_valid(char *name); +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 extract_archive(char *dst, char *src); bool mkdir_ifnot(char *path); void sockaddr_to_str(struct sockaddr *addr, char *str); + +int join_multiple(char *res, const char *base, const char *pth, const char *pth2); +int join(char *res, const char *base, const char *pth); +char *join_alloc(const char *base, const char *pth); diff --git a/locale/tr/LC_MESSAGES/libmp.po b/locale/tr/LC_MESSAGES/libmp.po index 2c99857..6cde0de 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-06-28 23:08+0300\n" +"POT-Creation-Date: 2024-07-01 06:41+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -152,7 +152,7 @@ msgid "host port not specified" msgstr "" #: src/error.c:45 -msgid "failed to parse pool info" +msgid "pool info is badly formatted or is not complete" msgstr "" #: src/error.c:46 @@ -255,3 +255,32 @@ msgstr "" #: src/error.c:70 msgid "pool did not respond ping with pong" msgstr "" + +#: src/error.c:71 +msgid "package file and directory paths are empty" +msgstr "" + +#: src/error.c:72 +msgid "failed to to open target file for sending" +msgstr "" + +#: src/error.c:73 +msgid "failed to to delete target file for receiving" +msgstr "" + +#: src/error.c:74 +msgid "failed to to open target file for receiving" +msgstr "" + +#: src/error.c:75 +msgid "got a bad response code for receiving the target file" +msgstr "" + +#: src/error.c:76 +msgid "failed to write to the target file for receiving" +msgstr "" + +#: src/error.c:77 +#, fuzzy +msgid "package not found" +msgstr "URL hostname is too large" diff --git a/src/ctx/ctx.c b/src/ctx/ctx.c index 906b8fb..6f9538e 100644 --- a/src/ctx/ctx.c +++ b/src/ctx/ctx.c @@ -73,7 +73,7 @@ bool lm_ctx_set_data(lm_ctx_t *ctx, char *dir){ } char poolsdir[strlen(dir)+10]; - snprintf(poolsdir, sizeof(poolsdir), "%s/pools", dir); + join(poolsdir, dir, "pools"); if(!mkdir_ifnot(poolsdir)){ lm_error_set(LM_ERR_CtxDataFailMkdir); @@ -85,7 +85,7 @@ bool lm_ctx_set_data(lm_ctx_t *ctx, char *dir){ } void lm_ctx_free(lm_ctx_t *ctx) { - lm_ctx_pools_clear(ctx); + lm_ctx_pool_clear(ctx); free(ctx->data); free(ctx->root); free(ctx->temp); diff --git a/src/ctx/pakcage.c b/src/ctx/pakcage.c new file mode 100644 index 0000000..853a570 --- /dev/null +++ b/src/ctx/pakcage.c @@ -0,0 +1,29 @@ +#include "../../include/ctx.h" +#include "../../include/pool.h" +#include "../../include/util.h" +#include "../../include/error.h" + +lm_pkg_t *lm_ctx_package_get(lm_ctx_t *ctx, char *name, char *version) { + lm_pool_t *pool = ctx->pools; + lm_pkg_t *pkg = NULL; + + while (NULL != pool) { + if((pkg = lm_pool_package_find(pool, name, version)) != NULL) + break; + pool = pool->next; + } + + if(NULL == pool && NULL == pkg){ + lm_error_set(LM_ERR_PkgNotFound); + return NULL; + } + + if(!lm_pool_package_get(pool, pkg)) + return NULL; + + return pkg; +} + +lm_pkg_t *lm_ctx_package_install(lm_ctx_t *ctx, char *name, char *version){ + return NULL; +} diff --git a/src/ctx/pools.c b/src/ctx/pool.c similarity index 68% rename from src/ctx/pools.c rename to src/ctx/pool.c index e64edee..ac65d57 100644 --- a/src/ctx/pools.c +++ b/src/ctx/pool.c @@ -4,11 +4,13 @@ #include "../../include/error.h" #include "../../include/thpool.h" -#include +#include #include +#include +#include #include -lm_pool_t *lm_ctx_pools_add(lm_ctx_t *ctx, char *name, char *url) { +lm_pool_t *lm_ctx_pool_add(lm_ctx_t *ctx, char *name, char *url) { if(NULL == name) return NULL; @@ -21,22 +23,22 @@ lm_pool_t *lm_ctx_pools_add(lm_ctx_t *ctx, char *name, char *url) { if(NULL != ctx->data){ char poolp[strlen(ctx->data) + strlen(pool->name) + 20]; - snprintf(poolp, sizeof(poolp), "%s/pools/%s", ctx->data, pool->name); - size_t poolp_sz = strlen(poolp); + join_multiple(poolp, ctx->data, "pools", pool->name); if(!mkdir_ifnot(poolp)){ lm_error_set(LM_ERR_CtxDataFailMkdir); return false; } - char infop[poolp_sz + 10]; - sprintf(infop, "%s/INFO", poolp); - - char listp[poolp_sz + 10]; - sprintf(listp, "%s/LIST", poolp); + size_t poolp_sz = strlen(poolp); + char infop[poolp_sz + 10], listp[poolp_sz + 10]; - lm_pool_paths_set_info(pool, infop); - lm_pool_paths_set_list(pool, listp); + join(infop, poolp, "INFO"); + join(listp, poolp, "LIST"); + + lm_pool_path_set_packages(pool, poolp); + lm_pool_path_set_info(pool, infop); + lm_pool_path_set_list(pool, listp); } if (NULL == ctx->pools) { @@ -57,7 +59,7 @@ lm_pool_t *lm_ctx_pools_add(lm_ctx_t *ctx, char *name, char *url) { return NULL; } -void lm_ctx_pools_clear(lm_ctx_t *ctx) { +void lm_ctx_pool_clear(lm_ctx_t *ctx) { lm_pool_t *cur = ctx->pools, *prev = NULL; while (NULL != cur) { prev = cur; @@ -68,7 +70,7 @@ void lm_ctx_pools_clear(lm_ctx_t *ctx) { ctx->pools = NULL; } -void lm_ctx_pools_test(lm_ctx_t *ctx, lm_ctx_pools_callback_t callback, void *data) { +void lm_ctx_pool_test(lm_ctx_t *ctx, lm_ctx_pool_callback_t callback, void *data) { lm_pool_t *cur = ctx->pools; while (NULL != cur) { lm_pool_test(cur); @@ -83,7 +85,7 @@ void lm_ctx_pools_test(lm_ctx_t *ctx, lm_ctx_pools_callback_t callback, void *da } } -lm_pool_t *lm_ctx_pools_find(lm_ctx_t *ctx, char *name) { +lm_pool_t *lm_ctx_pool_find(lm_ctx_t *ctx, char *name) { lm_pool_t *cur = ctx->pools; while (NULL != cur) { if (eq(cur->name, name)) @@ -93,7 +95,7 @@ lm_pool_t *lm_ctx_pools_find(lm_ctx_t *ctx, char *name) { return NULL; } -lm_pool_t *lm_ctx_pools_by_url(lm_ctx_t *ctx, char *host, char *path) { +lm_pool_t *lm_ctx_pool_by_url(lm_ctx_t *ctx, char *host, char *path) { lm_pool_t *cur = ctx->pools; while (NULL != cur) { if (eq(cur->url.host, host) && eq(cur->url.path, path)) @@ -103,12 +105,12 @@ lm_pool_t *lm_ctx_pools_by_url(lm_ctx_t *ctx, char *host, char *path) { return NULL; } -void lm_ctx_pools_get_info(lm_ctx_t *ctx, bool force_update, lm_ctx_pools_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){ lm_pool_t *cur = ctx->pools; bool status = false; while(NULL != cur){ - if(lm_pool_paths_is_empty(cur)){ + if(lm_pool_path_is_empty(cur)){ pdebug(__func__, "(%s) failed to load info, pool paths are empty", cur->name); goto next; } @@ -116,15 +118,22 @@ void lm_ctx_pools_get_info(lm_ctx_t *ctx, bool force_update, lm_ctx_pools_callba if(force_update) goto update; - if(!lm_pool_info_load(cur)) - pdebug(__func__, "(%s) failed to load info, gonna try updating", cur->name); + if(!lm_pool_info_load(cur)){ + pdebug(__func__, "(%s) failed to load info: %s", cur->name, lm_strerror()); + if(!allow_update) + goto next; + pdebug(__func__, "(%s) gonna try updating", cur->name); + } + + goto success; update: if(!lm_pool_info_get(cur)){ - pdebug(__func__, "(%s) failed to update info", cur->name); + pdebug(__func__, "(%s) failed to update info: %s", cur->name, lm_strerror()); goto next; } + success: pdebug(__func__, "(%s) loaded pool info", cur->name); status = true; @@ -136,12 +145,12 @@ void lm_ctx_pools_get_info(lm_ctx_t *ctx, bool force_update, lm_ctx_pools_callba } } -void lm_ctx_pools_get_list(lm_ctx_t *ctx, bool force_update, lm_ctx_pools_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_pool_t *cur = ctx->pools; bool status = false; while(NULL != cur){ - if(lm_pool_paths_is_empty(cur)){ + if(lm_pool_path_is_empty(cur)){ pdebug(__func__, "(%s) failed to load list, pool paths are empty", cur->name); goto next; } @@ -149,15 +158,22 @@ void lm_ctx_pools_get_list(lm_ctx_t *ctx, bool force_update, lm_ctx_pools_callba if(force_update) goto update; - if(!lm_pool_list_load(cur)) - pdebug(__func__, "(%s) failed to load list, gonna try updating", cur->name); + if(!lm_pool_list_load(cur)){ + pdebug(__func__, "(%s) failed to load list: %s", cur->name, lm_strerror()); + if(!allow_update) + goto next; + pdebug(__func__, "(%s) gonna try updating", cur->name); + } + + goto success; update: if(!lm_pool_list_get(cur)){ - pdebug(__func__, "(%s) failed to update list", cur->name); + pdebug(__func__, "(%s) failed to update list: %s", cur->name, lm_strerror()); goto next; } + success: pdebug(__func__, "(%s) loaded pool list", cur->name); status = true; @@ -169,7 +185,7 @@ void lm_ctx_pools_get_list(lm_ctx_t *ctx, bool force_update, lm_ctx_pools_callba } } -bool lm_ctx_pools_serve(lm_ctx_t *ctx, char *addr, uint8_t threads) { +bool lm_ctx_pool_serve(lm_ctx_t *ctx, char *addr, uint8_t threads) { if (NULL == addr || threads < 0) { lm_error_set(LM_ERR_ArgNULL); return false; @@ -202,28 +218,33 @@ bool lm_ctx_pools_serve(lm_ctx_t *ctx, char *addr, uint8_t threads) { } char hostname[packet.header.host_size + 1]; // +1 for NULL terminator - char path[packet.header.data_size + 1]; - - if (!lm_mptp_get_data(&packet, path)) { - pdebug(__func__, "skipping packet, failed to get path: %s", lm_strerror()); - continue; - } + char path[packet.header.data_size + 1], *ppath = path; if (!lm_mptp_get_host(&packet, hostname)) { pdebug(__func__, "skipping packet, failed to get hostname: %s", lm_strerror()); continue; } - lm_pool_t *pool = lm_ctx_pools_by_url(ctx, hostname, path); + if (!lm_mptp_get_data(&packet, path)) { + pdebug(__func__, "skipping packet, failed to get path: %s", lm_strerror()); + continue; + } + + if(MPTP_FLAGS_CODE(&packet) == MPTP_C2S_PULL && (ppath = dirname(path)) == NULL){ + pdebug(__func__, "skipping packet, failed to get dirname: %s", strerror(errno)); + continue; + } + + lm_pool_t *pool = lm_ctx_pool_by_url(ctx, hostname, ppath); if (NULL == pool) { - pdebug(__func__, "unknown pool, closing connection: %s", hostname); + pdebug(__func__, "unknown pool (%s) closing connection", hostname); lm_mptp_init(&packet, false, MPTP_S2C_BRUH, true); lm_mptp_server_send(sock, &packet, &saddr); continue; } - if(lm_pool_paths_is_empty(pool)){ + if(lm_pool_path_is_empty(pool)){ pdebug(__func__, "requested pool (%s) have empty paths, closing connection", pool->name); lm_mptp_init(&packet, false, MPTP_S2C_BRUH, true); lm_mptp_server_send(sock, &packet, &saddr); diff --git a/src/error.c b/src/error.c index 8d7f4a0..96d81a7 100644 --- a/src/error.c +++ b/src/error.c @@ -10,64 +10,71 @@ void lm_error_set(lm_error_t code) { char *lm_strerror() { 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 = _("failed to parse pool info") }, - {.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_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_PackagePathsEmpty, .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") }, }; for (int i = 0; i < sizeof(errors) / sizeof(lm_error_desc_t); i++) { diff --git a/src/mptp/utils.c b/src/mptp/utils.c index 7e4b788..13e1b62 100644 --- a/src/mptp/utils.c +++ b/src/mptp/utils.c @@ -1,12 +1,17 @@ #include "../../include/mptp.h" +#include "../../include/error.h" #include "../../include/util.h" + #include +#include #include #include bool lm_mptp_sendfile(int sock, struct sockaddr *addr, char *path){ - if (NULL == path) + if (NULL == path){ + lm_error_set(LM_ERR_ArgNULL); return false; + } lm_mptp_t packet; bool ret = false; @@ -16,6 +21,7 @@ bool lm_mptp_sendfile(int sock, struct sockaddr *addr, char *path){ if(NULL == file){ pdebug(__func__, "failed to open file: %s", path); + lm_error_set(LM_ERR_SendOpenFail); lm_mptp_init(&packet, false, MPTP_S2C_BRUH, true); goto end; } @@ -24,7 +30,8 @@ bool lm_mptp_sendfile(int sock, struct sockaddr *addr, char *path){ while ((read = fread(packet.data, 1, MPTP_DATA_MAX, file)) > 0) { packet.header.data_size = read; - lm_mptp_server_send(sock, &packet, addr); + if(!lm_mptp_server_send(sock, &packet, addr)) + goto end; lm_mptp_init(&packet, false, MPTP_S2C_COOL, false); } @@ -38,11 +45,15 @@ end: } bool lm_mptp_recvfile(int sock, char *path){ - if(NULL == path) + if(NULL == path){ + lm_error_set(LM_ERR_ArgNULL); return false; + } - if(unlink(path) < 0 && errno != ENOENT) + if(unlink(path) < 0 && errno != ENOENT){ + lm_error_set(LM_ERR_RecvDelFail); return false; + } FILE *file = fopen(path, "a"); bool ret = false; @@ -50,6 +61,7 @@ bool lm_mptp_recvfile(int sock, char *path){ if(NULL == file){ pdebug(__func__, "failed to open file: %s", path); + lm_error_set(LM_ERR_RecvOpenFail); goto end; } @@ -57,14 +69,18 @@ bool lm_mptp_recvfile(int sock, char *path){ if(!lm_mptp_client_verify(&packet)) goto end; - if(MPTP_FLAGS_CODE(&packet) != MPTP_S2C_COOL) + if(MPTP_FLAGS_CODE(&packet) != MPTP_S2C_COOL){ + lm_error_set(LM_ERR_RecvBadCode); goto end; + } if(MPTP_IS_LAST(&packet)) break; - if(fwrite(packet.data, 1, packet.header.data_size, file)==0) + if(fwrite(packet.data, 1, packet.header.data_size, file)==0){ + lm_error_set(LM_ERR_RecvWriteFail); goto end; + } } ret = true; diff --git a/src/package/data.c b/src/package/data.c new file mode 100644 index 0000000..c2b3efd --- /dev/null +++ b/src/package/data.c @@ -0,0 +1,63 @@ +#include "../../include/package.h" +#include "../../include/error.h" +#include "../../include/util.h" + +#include +#include +#include +#include + +int lm_package_data_handler(void *data, const char *_section, const char *_key, const char *_value) { + char *section = (char *)_section, *value = (char *)_value, *key = (char *)_key; + lm_pkg_t *pkg = data; + + if(NULL == pkg->name){ + if(!package_name_valid(section)) + return 0; + pkg->name = strdup(section); + } + + else if(!eq(pkg->name, section)) + return 0; + + if(eq(key, PKG_DATA_DESC)) + pkg->desc = strdup(value); + + else if(eq(key, PKG_DATA_VERSION)){ + if(!package_version_valid(value)) + return 0; + pkg->version = strdup(value); + } + + else if(eq(key, PKG_DATA_SIZE)) + pkg->size = atol(value); + + else if(eq(key, PKG_DATA_DEPENDS)){ + if(!lm_package_depend_add(pkg, value)) + return 0; + } + + return 1; +} + +bool lm_package_data_load(lm_pkg_t *pkg, char *file){ + lm_package_data_free(pkg); + + if (ini_parse(file, lm_package_data_handler, pkg) < 0) { + lm_error_set(LM_ERR_PkgDataBad); + return false; + } + + return true; +} + +void lm_package_data_free(lm_pkg_t *pkg){ + free(pkg->desc); + free(pkg->name); + free(pkg->version); + + if(NULL != pkg->depends){ + for(int i = 0; pkg->depends[i] != NULL; i++) + free(pkg->depends[i]); + } +} diff --git a/src/package/depend.c b/src/package/depend.c new file mode 100644 index 0000000..ac0b3c6 --- /dev/null +++ b/src/package/depend.c @@ -0,0 +1,44 @@ +#include "../../include/package.h" +#include "../../include/error.h" +#include "../../include/types.h" +#include "../../include/util.h" + +#include +#include + +size_t lm_package_depend_count(lm_pkg_t *pkg){ + size_t index = 0; + + if(NULL == pkg->depends) + return 0; + + while(pkg->depends[index] != NULL) + index++; + + return index; +} + +bool lm_package_depend_add(lm_pkg_t *pkg, char *depend){ + if(NULL == depend){ + lm_error_set(LM_ERR_ArgNULL); + return false; + } + + if(!package_name_valid(depend)){ + lm_error_set(LM_ERR_PkgBadName); + return false; + } + + if(NULL == pkg->depends){ + pkg->depends = malloc(sizeof(char*)*2); + pkg->depends[0] = strdup(depend); + pkg->depends[1] = NULL; + return true; + } + + size_t count = lm_package_depend_count(pkg); + pkg->depends = realloc(pkg->depends, sizeof(char*)*(count+2)); + pkg->depends[count++] = strdup(depend); + pkg->depends[count] = NULL; + return true; +} diff --git a/src/pkg/pkg.c b/src/package/package.c similarity index 55% rename from src/pkg/pkg.c rename to src/package/package.c index ccec367..6b89375 100644 --- a/src/pkg/pkg.c +++ b/src/package/package.c @@ -1,16 +1,17 @@ -#include "../../include/types.h" +#include "../../include/package.h" #include "../../include/error.h" -#include "../../include/pkg.h" +#include "../../include/types.h" +#include "../../include/mptp.h" #include #include -lm_pkg_t *lm_pkg_new(){ +lm_pkg_t *lm_package_new(){ lm_pkg_t *pkg = malloc(sizeof(lm_pkg_t)); bzero(pkg, sizeof(lm_pkg_t)); return pkg; } -void lm_pkg_free(lm_pkg_t *pkg){ - lm_pkg_data_free(pkg); +void lm_package_free(lm_pkg_t *pkg){ + lm_package_data_free(pkg); } diff --git a/src/package/path.c b/src/package/path.c new file mode 100644 index 0000000..4369e7e --- /dev/null +++ b/src/package/path.c @@ -0,0 +1,44 @@ +#include "../../include/package.h" +#include "../../include/types.h" +#include "../../include/util.h" + +#include +#include + +bool lm_package_path_set_archive(lm_pkg_t *pkg, char *archive_path){ + free(pkg->paths.archive); + pkg->paths.archive = NULL; + + if(NULL == archive_path) + return true; + + if(is_dir(archive_path)) + return false; + + pkg->paths.archive = strdup(archive_path); + return true; +} + +bool lm_package_path_set_signature(lm_pkg_t *pkg, char *signature_path){ + free(pkg->paths.signature); + pkg->paths.signature = NULL; + + if(NULL == signature_path) + return true; + + if(is_dir(signature_path)) + return false; + + pkg->paths.signature = strdup(signature_path); + return true; +} + +bool lm_package_path_is_empty(lm_pkg_t *pkg){ + return NULL == pkg->paths.signature || + NULL == pkg->paths.archive; +} + +void lm_package_path_free(lm_pkg_t *pkg){ + free(pkg->paths.signature); + free(pkg->paths.archive); +} diff --git a/src/pkg/data.c b/src/pkg/data.c deleted file mode 100644 index b3fa7e1..0000000 --- a/src/pkg/data.c +++ /dev/null @@ -1,97 +0,0 @@ -#include "../../include/error.h" -#include "../../include/util.h" -#include "../../include/pkg.h" - -#include -#include -#include -#include - -size_t lm_pkg_data_depend_count(lm_pkg_t *pkg){ - size_t index = 0; - - if(NULL == pkg->depends) - return 0; - - while(pkg->depends[index] != NULL) - index++; - - return index; -} - -bool lm_pkg_data_depend_add(lm_pkg_t *pkg, char *depend){ - if(NULL == depend){ - lm_error_set(LM_ERR_ArgNULL); - return false; - } - - if(!is_pkg_name_valid(depend)){ - lm_error_set(LM_ERR_PkgBadName); - return false; - } - - if(NULL == pkg->depends){ - pkg->depends = malloc(sizeof(char*)*2); - pkg->depends[0] = strdup(depend); - pkg->depends[1] = NULL; - return true; - } - - size_t count = lm_pkg_data_depend_count(pkg); - pkg->depends = realloc(pkg->depends, sizeof(char*)*(count+2)); - pkg->depends[count++] = strdup(depend); - pkg->depends[count] = NULL; - return true; -} - -int lm_pkg_data_handler(void *data, const char *_section, const char *_key, const char *_value) { - char *section = (char *)_section, *value = (char *)_value, *key = (char *)_key; - lm_pkg_t *pkg = data; - - if(NULL == pkg->name){ - if(!is_pkg_name_valid(section)) - return 0; - pkg->name = strdup(section); - } - - else if(!eq(pkg->name, section)) - return 0; - - if(eq(key, PKG_DATA_DESC)) - pkg->desc = strdup(value); - - else if(eq(key, PKG_DATA_VERSION)) - pkg->version = strdup(value); - - else if(eq(key, PKG_DATA_SIZE)) - pkg->size = atol(value); - - else if(eq(key, PKG_DATA_DEPENDS)){ - if(!lm_pkg_data_depend_add(pkg, value)) - return 0; - } - - return 1; -} - -bool lm_pkg_data_load(lm_pkg_t *pkg, char *file){ - lm_pkg_data_free(pkg); - - if (ini_parse(file, lm_pkg_data_handler, pkg) < 0) { - lm_error_set(LM_ERR_PkgDataBad); - return false; - } - - return true; -} - -void lm_pkg_data_free(lm_pkg_t *pkg){ - free(pkg->desc); - free(pkg->name); - free(pkg->version); - - if(NULL != pkg->depends){ - for(int i = 0; pkg->depends[i] != NULL; i++) - free(pkg->depends[i]); - } -} diff --git a/src/pool/info.c b/src/pool/info.c index 8497fbb..66c4cdd 100644 --- a/src/pool/info.c +++ b/src/pool/info.c @@ -48,6 +48,14 @@ bool lm_pool_info_load(lm_pool_t *pool) { return false; } + if(pool->info.size <= 0 || + pool->info.pubkey == NULL || + pool->info.maintainer == NULL){ + printf("%lu %s %s\n", pool->info.size, pool->info.pubkey, pool->info.maintainer); + lm_error_set(LM_ERR_PoolInfoBad); + return false; + } + return true; } @@ -69,10 +77,13 @@ bool lm_pool_info_get(lm_pool_t *pool) { if(NULL == pool->url.path) return false; - int sock = lm_mptp_client_connect(pool->url.host, pool->url.port); + int sock = -1; lm_mptp_t packet; bool ret = false; + if((sock = lm_mptp_client_connect(pool->url.host, pool->url.port)) < 0) + return false; + lm_mptp_init(&packet, true, MPTP_C2S_INFO, true); lm_mptp_set_host(&packet, pool->url.host); lm_mptp_set_data(&packet, pool->url.path, strlen(pool->url.path)); diff --git a/src/pool/list.c b/src/pool/list.c index 39be6aa..bf463c6 100644 --- a/src/pool/list.c +++ b/src/pool/list.c @@ -1,8 +1,8 @@ +#include "../../include/package.h" #include "../../include/error.h" #include "../../include/pool.h" #include "../../include/mptp.h" #include "../../include/util.h" -#include "../../include/pkg.h" #include #include @@ -24,9 +24,9 @@ bool lm_pool_list_load(lm_pool_t *pool){ } size_t file_len = strlen(pool->paths.list); - char file_copy[file_len + 1]; - char file_copy2[file_len + 1]; char *list_dir = NULL, *list_name = NULL; + char file_copy[file_len + 1], file_copy2[file_len + 1]; + char extract_dir[file_len+15]; memcpy(file_copy, pool->paths.list, file_len+1); memcpy(file_copy2, pool->paths.list, file_len+1); @@ -34,9 +34,10 @@ bool lm_pool_list_load(lm_pool_t *pool){ list_dir = dirname(file_copy); list_name = basename(file_copy2); - char extract_dir[file_len+15]; - snprintf(extract_dir, sizeof(extract_dir), "%s/%s_extracted", list_dir, list_name); + char extract_name[strlen(list_name)+20]; + snprintf(extract_name, sizeof(extract_name), "%s_extracted", list_name); + join(extract_dir, list_dir, extract_name); pdebug(__func__, "extracting pool to %s", extract_dir); if(!mkdir_ifnot(extract_dir)){ @@ -63,19 +64,19 @@ bool lm_pool_list_load(lm_pool_t *pool){ ent_len = strlen(ent->d_name); char datap[ent_len+sizeof(extract_dir)+10]; - snprintf(datap, sizeof(datap), "%s/%s/DATA", extract_dir, ent->d_name); + join_multiple(datap, extract_dir, ent->d_name, "DATA"); - lm_pkg_t *pkg = lm_pkg_new(); + lm_pkg_t *pkg = lm_package_new(); - if(!lm_pkg_data_load(pkg, datap)){ + if(!lm_package_data_load(pkg, datap)){ pdebug(__func__, "(%s) failed to load new package from %s", pool->name, datap); - lm_pkg_free(pkg); + lm_package_free(pkg); continue; } - if(!lm_pool_add(pool, pkg)){ + if(!lm_pool_package_add(pool, pkg)){ pdebug(__func__, "(%s) failed to add new package: %s", pool->name, pkg->name); - lm_pkg_free(pkg); + lm_package_free(pkg); continue; } @@ -108,10 +109,13 @@ bool lm_pool_list_get(lm_pool_t *pool) { if(NULL == pool->url.path) return false; - int sock = lm_mptp_client_connect(pool->url.host, pool->url.port); + int sock = -1; lm_mptp_t packet; bool ret = false; + if((sock = lm_mptp_client_connect(pool->url.host, pool->url.port)) < 0) + return false; + lm_mptp_init(&packet, true, MPTP_C2S_LIST, true); lm_mptp_set_host(&packet, pool->url.host); lm_mptp_set_data(&packet, pool->url.path, strlen(pool->url.path)); diff --git a/src/pool/package.c b/src/pool/package.c new file mode 100644 index 0000000..893e18e --- /dev/null +++ b/src/pool/package.c @@ -0,0 +1,113 @@ +#include "../../include/package.h" +#include "../../include/error.h" +#include "../../include/util.h" +#include "../../include/pool.h" + +#include +#include + +lm_pkg_t *lm_pool_package_find(lm_pool_t *pool, char *name, char *version){ + if(NULL == name && NULL == version){ + lm_error_set(LM_ERR_ArgNULL); + return NULL; + } + + lm_pkg_t *cur = pool->pkg; + while(NULL != cur){ + if(NULL == version && eq(cur->name, name)) + return cur; + + else if(NULL == name && eq(cur->version, version)) + return cur; + + else if(eq(cur->name, name) && eq(cur->version, version)) + return cur; + + cur = cur->next; + } + + return NULL; +} + +bool lm_pool_package_add(lm_pool_t *pool, lm_pkg_t *pkg){ + if(NULL == pool || NULL == pkg){ + lm_error_set(LM_ERR_ArgNULL); + return false; + } + + if(!lm_pool_path_is_empty(pool)){ + size_t path_size = strlen(pool->paths.packages)+strlen(pkg->name)+strlen(pkg->version); + size_t name_size = path_size - strlen(pool->paths.packages); + + char archive_path[path_size+10], sig_path[path_size+20]; + char archive_name[name_size+10], sig_name[name_size+20]; + + sprintf(archive_name, "%s_%s.mpf", pkg->name, pkg->version); + sprintf(sig_name, "%s_%s.mpf.sig", pkg->name, pkg->version); + + join(archive_path, pool->paths.packages, archive_name); + join(sig_path, pool->paths.packages, sig_name); + + lm_package_path_set_archive(pkg, archive_path); + lm_package_path_set_signature(pkg, sig_path); + } + + if(NULL == pool->pkg){ + pool->pkg = pkg; + return true; + } + + lm_pkg_t *cur = pool->pkg; + while(NULL != cur){ + if(NULL == cur->next){ + cur->next = pkg; + return true; + } + cur = cur->next; + } + + return false; +} + +bool lm_pool_package_get(lm_pool_t *pool, lm_pkg_t *pkg){ + if(NULL == pool || NULL == pkg){ + lm_error_set(LM_ERR_ArgNULL); + return false; + } + + if(lm_package_path_is_empty(pkg)){ + lm_error_set(LM_ERR_PackagePathsEmpty); + return false; + } + + char data[strlen(pool->url.path)+strlen(pkg->name)+strlen(pkg->version)+20]; + char name[strlen(pkg->name)+strlen(pkg->version)+10]; + + lm_mptp_t packet; + bool ret = false; + int sock = -1; + + snprintf(name, sizeof(name), "%s_%s", pkg->name, pkg->version); + join(data, pool->url.path, name); + + if((sock = lm_mptp_client_connect(pool->url.host, pool->url.port)) < 0) + return false; + + lm_mptp_init(&packet, true, MPTP_C2S_PULL, true); + lm_mptp_set_host(&packet, pool->url.host); + lm_mptp_set_data(&packet, data, strlen(data)); + + if(!lm_mptp_client_send(sock, &packet)) + goto end; + + if(!lm_mptp_recvfile(sock, pkg->paths.archive)) + goto end; + + if(!lm_mptp_recvfile(sock, pkg->paths.signature)) + goto end; + + ret = true; +end: + lm_mptp_close(sock); + return ret; +} diff --git a/src/pool/path.c b/src/pool/path.c new file mode 100644 index 0000000..18167fc --- /dev/null +++ b/src/pool/path.c @@ -0,0 +1,60 @@ +#include "../../include/types.h" +#include "../../include/pool.h" +#include "../../include/util.h" + +#include +#include + +bool lm_pool_path_set_info(lm_pool_t *pool, char *info_path){ + free(pool->paths.info); + pool->paths.info = NULL; + + if(NULL == info_path) + return true; + + if(is_dir(info_path)) + return false; + + pool->paths.info = strdup(info_path); + return true; +} + +bool lm_pool_path_set_list(lm_pool_t *pool, char *list_path){ + free(pool->paths.list); + pool->paths.list = NULL; + + if(NULL == list_path) + return true; + + if(is_dir(list_path)) + return false; + + pool->paths.list = strdup(list_path); + return true; +} + +bool lm_pool_path_set_packages(lm_pool_t *pool, char *packages_path){ + free(pool->paths.packages); + pool->paths.packages = NULL; + + if(NULL == packages_path) + return true; + + if(is_file(packages_path)) + return false; + + pool->paths.packages = strdup(packages_path); + return true; +} + +bool lm_pool_path_is_empty(lm_pool_t *pool){ + return NULL == pool->paths.info || + NULL == pool->paths.list || + NULL == pool->paths.packages; +} + +void lm_pool_path_free(lm_pool_t *pool){ + free(pool->paths.packages); + free(pool->paths.info); + free(pool->paths.list); +} diff --git a/src/pool/paths.c b/src/pool/paths.c deleted file mode 100644 index 35e7b45..0000000 --- a/src/pool/paths.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "../../include/types.h" -#include "../../include/pool.h" - -#include -#include -#include - -void lm_pool_paths_set_info(lm_pool_t *pool, char *info_path){ - free(pool->paths.info); - if(NULL == info_path){ - pool->paths.list = NULL; - return; - } - pool->paths.info = strdup(info_path); -} - -void lm_pool_paths_set_list(lm_pool_t *pool, char *list_path){ - free(pool->paths.list); - if(NULL == list_path){ - pool->paths.list = NULL; - return; - } - pool->paths.list = strdup(list_path); -} - -bool lm_pool_paths_is_empty(lm_pool_t *pool){ - return NULL == pool->paths.info || NULL == pool->paths.list; -} - -void lm_pool_paths_free(lm_pool_t *pool){ - free(pool->paths.info); - free(pool->paths.list); -} diff --git a/src/pool/pool.c b/src/pool/pool.c index 60f6aa7..0ab1301 100644 --- a/src/pool/pool.c +++ b/src/pool/pool.c @@ -1,7 +1,7 @@ +#include "../../include/package.h" #include "../../include/error.h" #include "../../include/util.h" #include "../../include/pool.h" -#include "../../include/pkg.h" #include #include @@ -63,29 +63,6 @@ end: return; } -bool lm_pool_add(lm_pool_t *pool, lm_pkg_t *pkg){ - if(NULL == pool || NULL == pkg){ - lm_error_set(LM_ERR_ArgNULL); - return false; - } - - if(NULL == pool->pkg){ - pool->pkg = pkg; - return true; - } - - lm_pkg_t *cur = pool->pkg; - while(NULL != cur){ - if(NULL == cur->next){ - cur->next = pkg; - return true; - } - cur = cur->next; - } - - return false; -} - void lm_pool_free(lm_pool_t *pool) { lm_url_free(&pool->url); lm_pool_info_free(pool); @@ -94,7 +71,7 @@ void lm_pool_free(lm_pool_t *pool) { while(NULL != cur){ prev = cur; cur = cur->next; - lm_pkg_free(prev); + lm_package_free(prev); } free(pool); diff --git a/src/pool/serve.c b/src/pool/serve.c index db212a7..95382aa 100644 --- a/src/pool/serve.c +++ b/src/pool/serve.c @@ -2,6 +2,9 @@ #include "../../include/util.h" #include "../../include/pool.h" +#include +#include +#include #include #include @@ -28,9 +31,58 @@ void lm_pool_serve(lm_pool_t *pool, lm_mptp_t *packet, int sock, struct sockaddr // when LIST file is requested, send the file case MPTP_C2S_LIST: pdebug(__func__, "(%s) LIST from %s attempting to send list", pool->name, ipaddr); - lm_mptp_sendfile(sock, addr, pool->paths.list); break; + lm_mptp_sendfile(sock, addr, pool->paths.list); break; + + // when the request code is PULL, send the requested package archive and + // requested package signature + case MPTP_C2S_PULL: + // PULL request should contain package path, + // if path (stored in the data field) is empty it's an invalid request + if(packet->header.data_size <= 0){ + lm_mptp_init(packet, false, MPTP_S2C_WHAT, true); + lm_mptp_server_send(sock, packet, addr); + break; + } + + pdebug(__func__, "(%s) PULL from %s attempting to send package archive and signature", pool->name, ipaddr); + char path[packet->header.data_size + 1], *package = path; + if(!lm_mptp_get_data(packet, path)){ + // we should never be able to get here, if we do theres definetly a bug + pdebug(__func__, "(%s) skipping PULL from %s, failed to get path: %s", pool->name, ipaddr, lm_strerror()); + break; + } + + // if we can't get the package name, then theres something wrong with the request + if((package = basename(path)) == NULL){ + lm_mptp_init(packet, false, MPTP_S2C_WHAT, true); + lm_mptp_server_send(sock, packet, addr); + break; + } + + size_t package_size = strlen(package); + char name[package_size+1], version[package_size+1]; + lm_pkg_t *pkg = NULL; + + // if we can't parse the package name, request is invalid + if(!package_parse(package, name, version)){ + lm_mptp_init(packet, false, MPTP_S2C_WHAT, true); + lm_mptp_server_send(sock, packet, addr); + break; + } + + // if the package is not found in the pool, tell the client + if((pkg = lm_pool_package_find(pool, name, version)) == NULL){ + lm_mptp_init(packet, false, MPTP_S2C_BRUH, true); + lm_mptp_server_send(sock, packet, addr); + break; + } + + // send package archive and the signature file + lm_mptp_sendfile(sock, addr, pkg->paths.archive); + lm_mptp_sendfile(sock, addr, pkg->paths.signature); + break; } } diff --git a/src/util.c b/src/util.c index 020e698..c2209be 100644 --- a/src/util.c +++ b/src/util.c @@ -206,17 +206,6 @@ end: return ret; } -bool is_pkg_name_valid(char *name) { - for (char *c = name; *c != 0; c++) { - if (*c == '_') - return false; - - if (*c == ' ') - return false; - } - return true; -} - bool exists(char *path) { struct stat st; return stat(path, &st) == 0; @@ -264,3 +253,75 @@ void sockaddr_to_str(struct sockaddr *addr, char *str) { break; } } + +bool package_name_valid(char *name) { + for (char *c = name; *c != 0; c++) { + if (!is_digit(*c) && !is_letter(*c) && *c != '-' && *c != '.') + return false; + } + return true; +} + +bool package_version_valid(char *version) { + for (char *c = version; *c != 0; c++) { + if (!is_digit(*c) && !is_letter(*c) && *c != '-' && *c != '+' && *c != '.') + return false; + } + return true; +} + +bool package_parse(char *package, char *name, char *version) { + ssize_t ni = 0, vi = -1; + + for (char *c = package; *c != 0; c++) { + if (vi < 0 && *c == '_') { + vi = 0; + continue; + } + + if (vi < 0) + name[ni++] = *c; + else + version[vi++] = *c; + } + + if (ni > 0 && vi > 0) { + name[ni] = 0; + version[vi] = 0; + return package_name_valid(name) && package_version_valid(version); + } + + return false; +} + +int join(char *res, const char *base, const char *pth) { + int blen = strlen(base); + + if ((base[blen - 1] == '/' && pth[0] != '/') || (base[blen - 1] != '/' && pth[0] == '/')) { + return sprintf(res, "%s%s", base, pth); + } else if (base[blen - 1] != '/' && pth[0] != '/') { + return sprintf(res, "%s/%s", base, pth); + } else if (base[blen - 1] == '/' && pth[0] == '/') { + char *basedup = strdup(base); + basedup[blen - 1] = '\0'; + + return sprintf(res, "%s%s", basedup, pth); + } + + return -1; +} + +int join_multiple(char *res, const char *base, const char *pth, const char *pth2) { + char firstp[strlen(base) + strlen(pth) + 5]; + if (join(firstp, base, pth) < 0) + return -1; + return join(res, firstp, pth2); +} + +char *join_alloc(const char *base, const char *pth) { + int pthlen = strlen(base) + strlen(pth); + char *path = malloc(pthlen + 5); + + join(path, base, pth); + return path; +}