first commit
This commit is contained in:
36
src/error.c
Normal file
36
src/error.c
Normal 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
45
src/libmp.c
Normal 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
89
src/pool.c
Normal 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
203
src/url.c
Normal 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
45
src/util.c
Normal 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;
|
||||
}
|
Reference in New Issue
Block a user