first commit

This commit is contained in:
ngn
2024-06-20 03:34:32 +03:00
commit 637b8c02e6
19 changed files with 949 additions and 0 deletions

36
src/error.c Normal file
View File

@ -0,0 +1,36 @@
#include "../include/error.h"
#include "../include/util.h"
#include <stdlib.h>
lm_error_t error = LM_ERR_NoError;
void lm_error_set(lm_error_t code){
error = 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_URLBadPath, .desc=_("URL does not have a valid path")},
{.code=LM_ERR_URLBadPort, .desc=_("URL does not contain a hostname with a valid port number")},
{.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")},
};
for(int i = 0; i < sizeof(errors)/sizeof(lm_error_desc_t); i++){
if(errors[i].code == error)
return errors[i].desc;
}
return NULL;
}
lm_error_t lm_error(){
return error;
}

45
src/libmp.c Normal file
View File

@ -0,0 +1,45 @@
// 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 <https://www.gnu.org/licenses/>.
*/
// clang-format on
#include "../include/libmp.h"
#include "../include/pool.h"
#include <locale.h>
#include <libintl.h>
#include <stdlib.h>
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;
}
void lm_ctx_free(lm_ctx_t *ctx){
lm_ctx_pool_clear(ctx);
return;
}

89
src/pool.c Normal file
View File

@ -0,0 +1,89 @@
#include "../include/error.h"
#include "../include/util.h"
#include "../include/pool.h"
#include <stdio.h>
#include <stdlib.h>
void lm_pool_free(lm_pool_t *pool){
lm_url_free(&pool->url);
free(pool);
}
lm_pool_t *lm_pool_new(char *name, char *url){
lm_pool_t *pool = malloc(sizeof(lm_pool_t));
if(!lm_url_parse(&pool->url, url)){
free(pool);
return NULL;
}
if(!eq(pool->url.protocol, "mptp")){
lm_error_set(LM_ERR_PoolNoSupport);
lm_pool_free(pool);
return NULL;
}
pool->name = name;
return pool;
}
bool lm_ctx_pool_add(lm_ctx_t *ctx, char *name, char *url){
lm_pool_t *pool = lm_pool_new(name, url);
if(NULL == pool)
return false;
pdebug(ctx, __func__, "pool name is %s", pool->name);
pdebug(ctx, __func__, "pool URL is %s://%s%s", pool->url.protocol, pool->url.host, pool->url.path);
if(NULL == ctx->pools){
ctx->pools = pool;
return true;
}
lm_pool_t *cur = ctx->pools;
while(NULL != cur) {
if(NULL == cur->next){
cur->next = pool;
return true;
}
cur = cur->next;
}
return false;
}
bool lm_ctx_pool_del(lm_ctx_t *ctx, char *name){
lm_pool_t *cur = ctx->pools, *prev = NULL;
while(NULL != cur) {
if(!eq(cur->name, name)){
cur = cur->next;
continue;
}
if(NULL == prev){
ctx->pools = cur->next;
lm_pool_free(cur);
return true;
}
prev->next = cur->next;
lm_pool_free(cur);
return true;
}
return false;
}
void lm_ctx_pool_clear(lm_ctx_t *ctx){
lm_pool_t *cur = ctx->pools, *prev = NULL;
while(NULL != cur) {
prev = cur;
cur = cur->next;
lm_pool_free(prev);
}
ctx->pools = NULL;
}
void lm_ctx_pool_test(lm_ctx_t *ctx){
return;
}

203
src/url.c Normal file
View File

@ -0,0 +1,203 @@
#include "../include/error.h"
#include "../include/util.h"
#include "../include/url.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char valid_path[] = "-._~:/?#[]@!$&'()*+,;%=";
typedef enum lm_state {
URL_PROTOCOL_0 = 0,
URL_SPLIT_1 = 1,
URL_HOST_2 = 2,
URL_PATH_3 = 3,
} lm_state_t;
uint16_t lm_url_default(char *protocol){
if(eq(protocol, "ftp"))
return 21;
else if(eq(protocol, "ftps"))
return 990;
else if(eq(protocol, "http"))
return 80;
else if(eq(protocol, "https"))
return 443;
else if(eq(protocol, "mptp"))
return 5858;
return 0;
}
bool lm_url_parse(lm_url_t *url, char *str){
// clear out every variable
bzero(url->protocol, sizeof(url->protocol));
url->host = NULL;
url->path = NULL;
url->port = 0;
// stores the string size
size_t strl = 0, index = 0, pos = 0;
// make sure the URL string size is not too large
// extra 4 for "://" and ":"
if((strl = strlen(str)) > URL_PROTOCOL_MAX+URL_PATH_MAX+URL_HOST_MAX+4){
lm_error_set(LM_ERR_URLTooLarge);
return false;
}
lm_state_t state = URL_PROTOCOL_0;
char buffer[strl+1]; // temporary buffer
bool ret = false; // return value
// clear out the temporary buffer
bzero(buffer, strl+1);
while ((buffer[index] = *(str+pos)) != 0) {
switch (state) {
case URL_PROTOCOL_0:
if(index > URL_PROTOCOL_MAX){
lm_error_set(LM_ERR_URLBadProtocol);
goto end;
}
if (!is_letter(buffer[index]) && !is_digit(buffer[index]) && buffer[index] != ':'){
lm_error_set(LM_ERR_URLBadChar);
goto end;
}
if(buffer[index] != ':')
break;
if(0 == index){
lm_error_set(LM_ERR_URLBadProtocol);
goto end;
}
buffer[index] = 0;
memcpy(url->protocol, buffer, index+1);
goto next;
case URL_SPLIT_1:
if(index > 1){
lm_error_set(LM_ERR_URLBadProtocol);
goto end;
}
if (buffer[index] != '/'){
lm_error_set(LM_ERR_URLBadChar);
goto end;
}
if(index != 1)
break;
if(buffer[index-1] != '/' || buffer[index] != '/'){
lm_error_set(LM_ERR_URLBadProtocol);
goto end;
}
goto next;
case URL_HOST_2:
if(index > URL_HOST_MAX){
lm_error_set(LM_ERR_URLHostLarge);
goto end;
}
if (!is_letter(buffer[index]) && !is_digit(buffer[index]) && buffer[index] != '.' && buffer[index] != ':' && buffer[index] != '/'){
lm_error_set(LM_ERR_URLBadChar);
goto end;
}
if(buffer[index] != '/')
break;
if(index == 0){
lm_error_set(LM_ERR_URLBadHost);
goto end;
}
buffer[index] = 0;
url->host = malloc((index+1)*sizeof(char));
memcpy(url->host, buffer, index+1);
goto next;
case URL_PATH_3:
if(index > URL_PATH_MAX){
lm_error_set(LM_ERR_URLPathLarge);
goto end;
}
if (!is_letter(buffer[index]) && !is_digit(buffer[index]) && !contains(valid_path, buffer[index])){
lm_error_set(LM_ERR_URLBadChar);
goto end;
}
break;
default:
assert(false);
}
index++;
pos++;
continue;
next:
bzero(buffer, strl+1);
state++;
index = 0;
pos++;
}
switch (state) {
case URL_HOST_2:
if(index == 0){
lm_error_set(LM_ERR_URLBadHost);
goto end;
}
if(index > URL_HOST_MAX){
lm_error_set(LM_ERR_URLHostLarge);
goto end;
}
url->host = malloc((index+1)*sizeof(char));
memcpy(url->host, buffer, index+1);
url->path = malloc(2*sizeof(char));
url->path[0] = '/';
url->path[1] = 0;
break;
case URL_PATH_3:
url->path = malloc((index+2)*sizeof(char));
url->path[0] = '/';
memcpy(url->path+1, buffer, index+1);
break;
default:
lm_error_set(LM_ERR_URLEnd);
goto end;
}
ret = true;
end:
if(!ret && NULL != url->host)
free(url->host);
if(!ret && NULL != url->path)
free(url->path);
return ret;
}
void lm_url_free(lm_url_t *url){
if(NULL != url->host)
free(url->host);
if(NULL != url->path)
free(url->path);
}

45
src/util.c Normal file
View File

@ -0,0 +1,45 @@
#include "../include/util.h"
#include "../include/types.h"
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void pdebug(lm_ctx_t *ctx, const char *func, const char *fmt, ...){
if(!ctx->debug)
return;
va_list args;
va_start(args, fmt);
printf("[DEBUG] %s: ", func);
vprintf(fmt, args);
printf("\n");
va_end(args);
}
bool eq(char *s1, char *s2) {
if (NULL == s1 || NULL == s2)
return false;
if (strlen(s1) != strlen(s2))
return false;
return strcmp(s1, s2) == 0;
}
bool is_letter(char c) {
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
}
bool is_digit(char c) {
return c >= '0' && c <= '9';
}
bool contains(char *str, char s) {
for (char *c = str; *c != 0; c++)
if (*c == s)
return true;
return false;
}