From 6c2f34e8d5246c9da1142c245c80b0fac8b3174d Mon Sep 17 00:00:00 2001 From: ngn Date: Thu, 27 Jun 2024 23:05:39 +0300 Subject: [PATCH] new: implement pool info for client/server --- Makefile | 1 + examples/pool/main.c | 15 +++- examples/server/main.c | 10 ++- examples/tests/pool/INFO | 4 + include/all.h | 26 +++++- include/{libmp.h => ctx.h} | 7 ++ include/error.h | 94 +++++++++++++--------- include/pkg.h | 6 ++ include/pool.h | 7 ++ include/util.h | 6 ++ locale/tr/LC_MESSAGES/libmp.po | 59 +++++++++++++- src/ctx/ctx.c | 104 ++++++++++++++++++++++++ src/{libmp.c => ctx/pools.c} | 143 ++++++++++++++++++++++----------- src/error.c | 94 +++++++++++++--------- src/pkg/data.c | 93 ++++++++++++++++++++- src/pkg/pkg.c | 6 +- src/pool/info.c | 22 ++--- src/pool/list.c | 10 +++ src/pool/pool.c | 9 +++ src/pool/serve.c | 8 ++ src/util.c | 39 +++++++++ 21 files changed, 611 insertions(+), 152 deletions(-) create mode 100644 examples/tests/pool/INFO rename include/{libmp.h => ctx.h} (50%) create mode 100644 src/ctx/ctx.c rename src/{libmp.c => ctx/pools.c} (59%) diff --git a/Makefile b/Makefile index bd3578a..1aef7d3 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,7 @@ dist/libmp.so: $(OBJS) $(CC) -shared -o $@ $^ $(LIBS) $(CFLAGS) dist/%.o: src/%.c + mkdir -p dist/ctx mkdir -p dist/pkg mkdir -p dist/mptp mkdir -p dist/pool diff --git a/examples/pool/main.c b/examples/pool/main.c index 0f31981..8db31b1 100644 --- a/examples/pool/main.c +++ b/examples/pool/main.c @@ -1,7 +1,10 @@ #include "../../include/all.h" + #include #include +#define DATA_DIR "/tmp/data" + int main(int argc, char *argv[]) { int ret = EXIT_FAILURE; @@ -12,15 +15,23 @@ int main(int argc, char *argv[]) { lm_ctx_t ctx; lm_ctx_init(&ctx); - ctx.debug = true; + if (!lm_ctx_set_data(&ctx, DATA_DIR)) { + printf("failed to set data dir: %s (%d)\n", lm_strerror(), lm_error()); + goto end; + } + if (!lm_ctx_pools_add(&ctx, "test", argv[1])) { printf("failed to add pool: %s (%d)\n", lm_strerror(), lm_error()); goto end; } - lm_ctx_pools_test(&ctx); + if (!lm_ctx_pools_load(&ctx, true, NULL, NULL)) { + printf("failed to load pools: %s (%d)\n", lm_strerror(), lm_error()); + goto end; + } + ret = EXIT_SUCCESS; end: diff --git a/examples/server/main.c b/examples/server/main.c index 03519f1..c608b1c 100644 --- a/examples/server/main.c +++ b/examples/server/main.c @@ -11,16 +11,22 @@ int main(int argc, char *argv[]) { return ret; } - lm_ctx_t ctx; + lm_ctx_t ctx; + lm_pool_t *pool; lm_ctx_init(&ctx); ctx.debug = true; - if (!lm_ctx_pools_add(&ctx, "test", "mptp://127.0.0.1:5858")) { + if ((pool = lm_ctx_pools_add(&ctx, "test", "mptp://127.0.0.1:5858")) == NULL) { printf("failed to add pool: %s (%d)\n", lm_strerror(), lm_error()); goto end; } + if (!lm_pool_info_load(pool, "./examples/tests/pool/INFO")) { + printf("failed to load pool info: %s (%d)\n", lm_strerror(), lm_error()); + goto end; + } + if (!lm_ctx_pools_serve(&ctx, argv[1], 10)) { printf("failed to serve the pools: %s (%d)\n", lm_strerror(), lm_error()); goto end; diff --git a/examples/tests/pool/INFO b/examples/tests/pool/INFO new file mode 100644 index 0000000..8bac9a7 --- /dev/null +++ b/examples/tests/pool/INFO @@ -0,0 +1,4 @@ +[test] +size = 18221 +author = ngn +pubkey = F9E70878C2FB389AEC2BA34CA3654DF5AD9F641 diff --git a/include/all.h b/include/all.h index 4807a5a..091440f 100644 --- a/include/all.h +++ b/include/all.h @@ -1,4 +1,28 @@ +// clang-format off + +/* + + * libmp | MatterLinux package management library + * MatterLinux 2023-2024 (https://matterlinux.xyz) + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + +*/ + +// clang-format on + +#include "ctx.h" #include "error.h" -#include "libmp.h" #include "pool.h" #include "types.h" diff --git a/include/libmp.h b/include/ctx.h similarity index 50% rename from include/libmp.h rename to include/ctx.h index 8e32a2e..715efe9 100644 --- a/include/libmp.h +++ b/include/ctx.h @@ -1,7 +1,13 @@ #pragma once #include "types.h" +#include + +typedef void (*lm_ctx_pools_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); +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); @@ -9,3 +15,4 @@ bool lm_ctx_pools_del(lm_ctx_t *ctx, char *name); void lm_ctx_pools_clear(lm_ctx_t *ctx); void lm_ctx_pools_test(lm_ctx_t *ctx); bool lm_ctx_pools_serve(lm_ctx_t *ctx, char *addr, uint8_t threads); +bool lm_ctx_pools_load(lm_ctx_t *ctx, bool force_update, lm_ctx_pools_callback_t callback, void *data); diff --git a/include/error.h b/include/error.h index cbb81fb..99cad30 100644 --- a/include/error.h +++ b/include/error.h @@ -1,46 +1,60 @@ #pragma once 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_GetCwdFail = 38, - LM_ERR_PoolListDirFail = 39, + 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_GetCwdFail = 38, + LM_ERR_PoolListDirFail = 39, + LM_ERR_PoolListCantRead = 40, + LM_ERR_PoolInfoCantRead = 41, + LM_ERR_PkgBadName = 42, + LM_ERR_PkgDataBad = 43, + LM_ERR_CtxDataNULL = 44, + LM_ERR_CtxTempFail = 45, + LM_ERR_CtxTempNotDir = 46, + LM_ERR_CtxTempNoWrite = 47, + LM_ERR_CtxRootFail = 48, + LM_ERR_CtxRootNotDir = 49, + LM_ERR_CtxRootNoWrite = 50, + LM_ERR_CtxDataNotDir = 51, + LM_ERR_CtxDataNoWrite = 52, + LM_ERR_CtxDataFailMkdir = 53, } lm_error_t; diff --git a/include/pkg.h b/include/pkg.h index 3bac697..57b8751 100644 --- a/include/pkg.h +++ b/include/pkg.h @@ -2,7 +2,13 @@ #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 e052a7d..5fbc2c6 100644 --- a/include/pool.h +++ b/include/pool.h @@ -5,6 +5,10 @@ #include #include +#define POOL_INFO_SIZE "size" +#define POOL_INFO_PUBKEY "pubkey" +#define POOL_INFO_MAINTAINER "maintainer" + typedef struct lm_pool_thread_arg { int sock; struct sockaddr addr; @@ -21,5 +25,8 @@ bool lm_pool_info_load(lm_pool_t *pool, char *file); bool lm_pool_info_get(lm_pool_t *pool, char *file); void lm_pool_info_free(lm_pool_t *pool); +bool lm_pool_list_load(lm_pool_t *pool, char *file); +bool lm_pool_list_get(lm_pool_t *pool, char *file); + void lm_pool_serve(lm_pool_t *pool, lm_mptp_t *packet, int sock, struct sockaddr *addr); void lm_pool_serve_thread(void *arg); diff --git a/include/util.h b/include/util.h index f92bc7a..895b545 100644 --- a/include/util.h +++ b/include/util.h @@ -15,3 +15,9 @@ 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 is_file(char *path); +bool is_dir(char *path); +bool can_read(char *path); +bool can_write(char *path); diff --git a/locale/tr/LC_MESSAGES/libmp.po b/locale/tr/LC_MESSAGES/libmp.po index 8847f1f..c0f6cb1 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-26 22:32+0300\n" +"POT-Creation-Date: 2024-06-27 23:02+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -182,3 +182,60 @@ msgstr "" #: src/error.c:52 msgid "failed to open extracted pool list directory" msgstr "" + +#: src/error.c:53 +msgid "failed to read access the pool list file" +msgstr "" + +#: src/error.c:54 +msgid "failed to read access the pool info file" +msgstr "" + +#: src/error.c:55 +msgid "failed to parse package data" +msgstr "" + +#: src/error.c:56 +#, fuzzy +msgid "package name is invalid" +msgstr "URL hostname is too large" + +#: src/error.c:57 +msgid "data path is not set with in the ctx" +msgstr "" + +#: src/error.c:58 +msgid "specified temp path does not exist" +msgstr "" + +#: src/error.c:59 +msgid "specified temp path is not a directory" +msgstr "" + +#: src/error.c:60 +msgid "specified temp directory does not have write access" +msgstr "" + +#: src/error.c:61 +msgid "specified root path does not exist" +msgstr "" + +#: src/error.c:62 +msgid "specified root path is not a directory" +msgstr "" + +#: src/error.c:63 +msgid "specified root directory does not have write access" +msgstr "" + +#: src/error.c:64 +msgid "specified data path does not exist" +msgstr "" + +#: src/error.c:65 +msgid "specified data path is not a directory" +msgstr "" + +#: src/error.c:66 +msgid "failed to create specified data directory" +msgstr "" diff --git a/src/ctx/ctx.c b/src/ctx/ctx.c new file mode 100644 index 0000000..8cf86ac --- /dev/null +++ b/src/ctx/ctx.c @@ -0,0 +1,104 @@ +#include "../../include/error.h" +#include "../../include/util.h" +#include "../../include/ctx.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void lm_ctx_init(lm_ctx_t *ctx) { + setlocale(LC_ALL, ""); + textdomain("libmp"); + + bzero(ctx, sizeof(lm_ctx_t)); + ctx->debug = false; +} + +bool lm_ctx_set_temp(lm_ctx_t *ctx, char *dir){ + if(!exists(dir)){ + lm_error_set(LM_ERR_CtxTempFail); + return false; + } + + if(!is_dir(dir)){ + lm_error_set(LM_ERR_CtxTempNotDir); + return false; + } + + if(!can_write(dir)){ + lm_error_set(LM_ERR_CtxTempNoWrite); + return false; + } + + ctx->temp = strdup(dir); + return true; +} + +bool lm_ctx_set_root(lm_ctx_t *ctx, char *dir){ + if(!exists(dir)){ + lm_error_set(LM_ERR_CtxRootFail); + return false; + } + + if(!is_dir(dir)){ + lm_error_set(LM_ERR_CtxRootNotDir); + return false; + } + + if(!can_write(dir)){ + lm_error_set(LM_ERR_CtxRootNoWrite); + return false; + } + + ctx->root = strdup(dir); + return true; +} + +bool lm_ctx_set_data(lm_ctx_t *ctx, char *dir){ + if(!exists(dir)) + goto mkdir; + + if(!is_dir(dir)){ + lm_error_set(LM_ERR_CtxDataNotDir); + return false; + } + + if(!can_write(dir)){ + lm_error_set(LM_ERR_CtxDataNoWrite); + return false; + } + + ctx->data = strdup(dir); + return true; + +mkdir: + if(mkdir(dir, 0700) < 0){ + lm_error_set(LM_ERR_CtxDataFailMkdir); + return false; + } + + char poolsdir[strlen(dir)+10]; + snprintf(poolsdir, sizeof(poolsdir), "%s/pools", dir); + + if(mkdir(poolsdir, 0700) < 0){ + lm_error_set(LM_ERR_CtxDataFailMkdir); + return false; + } + + ctx->data = strdup(dir); + return true; +} + +void lm_ctx_free(lm_ctx_t *ctx) { + lm_ctx_pools_clear(ctx); + free(ctx->data); + free(ctx->root); + free(ctx->temp); + return; +} diff --git a/src/libmp.c b/src/ctx/pools.c similarity index 59% rename from src/libmp.c rename to src/ctx/pools.c index 8cfc8f1..16235f9 100644 --- a/src/libmp.c +++ b/src/ctx/pools.c @@ -1,50 +1,15 @@ -// clang-format off +#include "../../include/ctx.h" +#include "../../include/pool.h" +#include "../../include/util.h" +#include "../../include/error.h" +#include "../../include/thpool.h" -/* - - * libmp | MatterLinux package management library - * MatterLinux 2023-2024 (https://matterlinux.xyz) - - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - -*/ - -// clang-format on - -#include "../include/libmp.h" -#include "../include/error.h" -#include "../include/mptp.h" -#include "../include/pool.h" -#include "../include/thpool.h" -#include "../include/util.h" - -#include -#include +#include #include +#include #include -#include - -void lm_ctx_init(lm_ctx_t *ctx) { - setlocale(LC_ALL, ""); - textdomain("libmp"); - - ctx->pools = NULL; - ctx->data = NULL; - ctx->root = NULL; - ctx->temp = NULL; - ctx->debug = false; -} +#include +#include lm_pool_t *lm_ctx_pools_add(lm_ctx_t *ctx, char *name, char *url) { lm_pool_t *pool = lm_pool_new(name, url); @@ -93,6 +58,16 @@ void lm_ctx_pools_test(lm_ctx_t *ctx) { } } +void lm_ctx_pools_get_info(lm_ctx_t *ctx) { + lm_pool_t *cur = ctx->pools; + while (NULL != cur) { + lm_pool_test(cur); + if (!cur->available) + pdebug(ctx, __func__, "%s is not avaliable: %s", cur->name, lm_strerror()); + cur = cur->next; + } +} + lm_pool_t *lm_ctx_pools_find(lm_ctx_t *ctx, char *name) { lm_pool_t *cur = ctx->pools; while (NULL != cur) { @@ -113,6 +88,80 @@ lm_pool_t *lm_ctx_pools_by_url(lm_ctx_t *ctx, char *host, char *path) { return NULL; } +bool lm_ctx_pool_load(lm_ctx_t *ctx, lm_pool_t *pool, bool force_update){ + if(NULL == ctx->data){ + printf("hello chat\n"); + lm_error_set(LM_ERR_CtxDataNULL); + return false; + } + + 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); + + if(mkdir(poolp, 0700) < 0 && errno != EEXIST){ + 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); + + if(force_update) + goto update; + + if(!lm_pool_info_load(pool, infop)){ + pdebug(ctx, __func__, "failed to load info for %s gonna try updating", pool->name); + goto update; + } + + if(!lm_pool_info_load(pool, listp)){ + pdebug(ctx, __func__, "failed to load list for %s gonna try updating", pool->name); + goto update; + } + +update: + unlink(infop); + unlink(listp); + + if(!lm_pool_info_get(pool, infop)){ + pdebug(ctx, __func__, "failed to get info for %s", pool->name); + return false; + } + + if(!lm_pool_list_get(pool, listp)){ + pdebug(ctx, __func__, "failed to get list for %s", pool->name); + return false; + } + + return true; +} + +bool lm_ctx_pools_load(lm_ctx_t *ctx, bool force_update, lm_ctx_pools_callback_t callback, void *data){ + if(NULL == ctx){ + lm_error_set(LM_ERR_ArgNULL); + return false; + } + + lm_pool_t *cur = ctx->pools; + while(NULL != cur){ + bool status = lm_ctx_pool_load(ctx, cur, force_update); + + if(!status) + pdebug(ctx, __func__, "failed to load pool: %s", cur->name); + + if(NULL != callback) + callback(ctx, cur, status, data); + + cur = cur->next; + } + + return true; +} + bool lm_ctx_pools_serve(lm_ctx_t *ctx, char *addr, uint8_t threads) { if (NULL == addr || threads < 0) { lm_error_set(LM_ERR_ArgNULL); @@ -171,6 +220,7 @@ bool lm_ctx_pools_serve(lm_ctx_t *ctx, char *addr, uint8_t threads) { memcpy(&arg->addr, &saddr, sizeof(struct sockaddr)); lm_mptp_copy(&arg->packet, &packet); + arg->pool = pool; arg->sock = sock; lm_thpool_add(&tp, lm_pool_serve_thread, arg); @@ -179,8 +229,3 @@ bool lm_ctx_pools_serve(lm_ctx_t *ctx, char *addr, uint8_t threads) { lm_thpool_stop(&tp); return true; } - -void lm_ctx_free(lm_ctx_t *ctx) { - lm_ctx_pools_clear(ctx); - return; -} diff --git a/src/error.c b/src/error.c index 4cf0ad6..1b114fa 100644 --- a/src/error.c +++ b/src/error.c @@ -10,46 +10,60 @@ 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_GetCwdFail, .desc = _("failed to obtain current working directory") }, - {.code = LM_ERR_PoolListDirFail, .desc = _("failed to open extracted pool list directory") }, + {.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_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") }, }; for (int i = 0; i < sizeof(errors) / sizeof(lm_error_desc_t); i++) { diff --git a/src/pkg/data.c b/src/pkg/data.c index 09109f1..b116e01 100644 --- a/src/pkg/data.c +++ b/src/pkg/data.c @@ -1,7 +1,94 @@ +#include "../../include/error.h" +#include "../../include/util.h" #include "../../include/pkg.h" -#include -bool lm_pkg_data_load(lm_pkg_t *pkg, char *file){ - // TODO: implement lol +#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); + for(int i = 0; pkg->depends[i] != NULL; i++) + free(pkg->depends[i]); +} diff --git a/src/pkg/pkg.c b/src/pkg/pkg.c index 3baff82..ccec367 100644 --- a/src/pkg/pkg.c +++ b/src/pkg/pkg.c @@ -12,9 +12,5 @@ lm_pkg_t *lm_pkg_new(){ } void lm_pkg_free(lm_pkg_t *pkg){ - free(pkg->desc); - free(pkg->name); - free(pkg->version); - for(int i = 0; pkg->depends[i] != NULL; i++) - free(pkg->depends[i]); + lm_pkg_data_free(pkg); } diff --git a/src/pool/info.c b/src/pool/info.c index 903160b..9c10d99 100644 --- a/src/pool/info.c +++ b/src/pool/info.c @@ -3,11 +3,13 @@ #include "../../include/mptp.h" #include "../../include/util.h" +#include #include #include #include #include #include +#include int lm_pool_info_handler(void *data, const char *_section, const char *_key, const char *_value) { char *section = (char *)_section, *value = (char *)_value, *key = (char *)_key; @@ -16,11 +18,11 @@ int lm_pool_info_handler(void *data, const char *_section, const char *_key, con if (!eq(pool->name, section)) return 0; - if (eq(key, "size")) + if (eq(key, POOL_INFO_SIZE)) pool->info.size = atol(value); - else if (eq(key, "maintainer")) + else if (eq(key, POOL_INFO_MAINTAINER)) pool->info.maintainer = strdup(value); - else if (eq(key, "pubkey")) + else if (eq(key, POOL_INFO_PUBKEY)) pool->info.pubkey = strdup(value); else return 0; @@ -31,6 +33,11 @@ int lm_pool_info_handler(void *data, const char *_section, const char *_key, con bool lm_pool_info_load(lm_pool_t *pool, char *file) { lm_pool_info_free(pool); + if(!can_read(file)){ + lm_error_set(LM_ERR_PoolInfoCantRead); + return false; + } + if (ini_parse(file, lm_pool_info_handler, pool) < 0) { lm_error_set(LM_ERR_PoolInfoBad); return false; @@ -65,18 +72,15 @@ bool lm_pool_info_get(lm_pool_t *pool, char *file) { if(!lm_mptp_client_send(sock, &packet)) goto end; - if(!lm_mptp_client_recv(sock, &packet)) - goto end; - while(lm_mptp_client_recv(sock, &packet)){ if(!lm_mptp_client_verify(&packet)) goto end; + + if(MPTP_IS_LAST(&packet)) + break; if(fwrite(packet.data, 1, packet.header.data_size, info)==0) goto end; - - if(MPTP_IS_LAST(&packet)) - break; } ret = true; diff --git a/src/pool/list.c b/src/pool/list.c index ac60fd8..dda887c 100644 --- a/src/pool/list.c +++ b/src/pool/list.c @@ -10,6 +10,16 @@ #include bool lm_pool_list_load(lm_pool_t *pool, char *file){ + if(NULL == pool || NULL == file){ + lm_error_set(LM_ERR_ArgNULL); + return false; + } + + if(!can_read(file)){ + lm_error_set(LM_ERR_PoolListCantRead); + return false; + } + size_t file_len = strlen(file), ent_len = 0; char filecp[file_len+1], *dir = NULL; struct dirent *ent = NULL; diff --git a/src/pool/pool.c b/src/pool/pool.c index 1a41d2e..0661a56 100644 --- a/src/pool/pool.c +++ b/src/pool/pool.c @@ -1,6 +1,7 @@ #include "../../include/error.h" #include "../../include/util.h" #include "../../include/pool.h" +#include "../../include/pkg.h" #include #include @@ -89,5 +90,13 @@ bool lm_pool_add(lm_pool_t *pool, lm_pkg_t *pkg){ void lm_pool_free(lm_pool_t *pool) { lm_url_free(&pool->url); lm_pool_info_free(pool); + + lm_pkg_t *cur = pool->pkg, *prev = NULL; + while(NULL != cur){ + prev = cur; + cur = cur->next; + lm_pkg_free(prev); + } + free(pool); } diff --git a/src/pool/serve.c b/src/pool/serve.c index b8361e1..5022209 100644 --- a/src/pool/serve.c +++ b/src/pool/serve.c @@ -19,7 +19,15 @@ void lm_pool_serve(lm_pool_t *pool, lm_mptp_t *packet, int sock, struct sockaddr FILE *info = fopen(pool->info.file, "r"); size_t read = 0; + if(NULL == info){ + lm_mptp_init(packet, false, MPTP_S2C_BRUH, true); + goto end; + } + + lm_mptp_init(packet, false, MPTP_S2C_COOL, false); + while ((read = fread(packet->data, 1, MPTP_DATA_MAX, info)) > 0) { + packet->header.data_size = read; lm_mptp_server_send(sock, packet, addr); lm_mptp_init(packet, false, MPTP_S2C_COOL, false); } diff --git a/src/util.c b/src/util.c index 8c7c677..63081fb 100644 --- a/src/util.c +++ b/src/util.c @@ -9,6 +9,7 @@ #include #include #include +#include #include void pdebug(lm_ctx_t *ctx, const char *func, const char *fmt, ...) { @@ -189,3 +190,41 @@ 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; +} + +bool is_file(char *path) { + struct stat st; + if (stat(path, &st) < 0) + return false; + return S_ISREG(st.st_mode); +} + +bool is_dir(char *path) { + struct stat st; + if (stat(path, &st) < 0) + return false; + return S_ISDIR(st.st_mode); +} + +bool can_read(char *path) { + return access(path, R_OK) == 0; +} + +bool can_write(char *path) { + return access(path, W_OK) == 0; +}