From 08246f25fa077708c02dbff1b258f7e1093e59fa Mon Sep 17 00:00:00 2001 From: konect-V <66421869+konect-V@users.noreply.github.com> Date: Fri, 14 Jun 2024 14:00:34 +0200 Subject: [PATCH] Net bug fix and store update --- .vscode/settings.json | 5 +- sources/core/apps/init/source/core/core.c | 1 + sources/core/apps/store/source/apps/apps.c | 138 ++++++++------- sources/core/apps/store/source/apps/apps.h | 12 +- sources/core/apps/store/source/core/core.c | 46 ++--- sources/core/apps/store/source/deps/deps.c | 67 ++++++++ sources/core/apps/store/source/deps/deps.h | 6 + .../apps/store/source/download/download.c | 59 +++++++ .../apps/store/source/download/download.h | 9 + .../core/apps/store/source/install/install.c | 95 +++++++++++ .../core/apps/store/source/install/install.h | 9 + sources/core/kernel/source/global/heap.c | 7 +- sources/core/kernel/source/global/syscall.c | 25 ++- sources/core/kernel/source/parameters.h | 1 + .../mlibc/sysdeps/kot/generic/filesystem.cpp | 10 ++ .../mlibc/sysdeps/kot/generic/generic.cpp | 53 ++++++ .../mlibc/sysdeps/kot/include/kot/syscall.h | 35 ++-- sources/core/modules/fat32/source/core.c | 15 +- sources/core/modules/net/source/ip.c | 4 +- sources/core/modules/net/source/socket.c | 158 +++++++++++++----- sources/core/modules/net/source/socket.h | 10 +- target/makefile | 2 +- 22 files changed, 595 insertions(+), 172 deletions(-) create mode 100644 sources/core/apps/store/source/deps/deps.c create mode 100644 sources/core/apps/store/source/deps/deps.h create mode 100644 sources/core/apps/store/source/download/download.c create mode 100644 sources/core/apps/store/source/download/download.h create mode 100644 sources/core/apps/store/source/install/install.c create mode 100644 sources/core/apps/store/source/install/install.h diff --git a/.vscode/settings.json b/.vscode/settings.json index 672ece33b..e512a3a9e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -200,7 +200,10 @@ "inet_ntop.h": "c", "inet_pton.h": "c", "progress.h": "c", - "curl_memory.h": "c" + "curl_memory.h": "c", + "apps.h": "c", + "download.h": "c", + "stdlib.h": "c" }, "files.exclude": { "bundled": true, diff --git a/sources/core/apps/init/source/core/core.c b/sources/core/apps/init/source/core/core.c index 37c99a55e..492c82c94 100644 --- a/sources/core/apps/init/source/core/core.c +++ b/sources/core/apps/init/source/core/core.c @@ -12,6 +12,7 @@ int main(int argc, char* argv[]){ setenv("HOME", "/usr", 1); setenv("PWD", getenv("HOME"), 1); setenv("PATH", "/usr/bin", 1); + setenv("PATHSTORE", "/usr/store", 1); setenv("USER", "root", 1); setenv("HOSTNAME", "kot", 1); diff --git a/sources/core/apps/store/source/apps/apps.c b/sources/core/apps/store/source/apps/apps.c index 36cbaefc0..a048dc765 100644 --- a/sources/core/apps/store/source/apps/apps.c +++ b/sources/core/apps/store/source/apps/apps.c @@ -18,52 +18,41 @@ static size_t write_callback(void *contents, size_t size, size_t nmemb, void *us return real_size; } -fetch_apps_data_t* fetch_apps_data(void){ - CURL *curl; - CURLcode res; - - curl_global_init(CURL_GLOBAL_DEFAULT); - curl = curl_easy_init(); - if(curl){ - fetch_apps_data_t* buffer_info = malloc(sizeof(fetch_apps_data_t)); - buffer_info->buffer = NULL; - buffer_info->size = 0; - curl_easy_setopt(curl, CURLOPT_URL, "https://kot-store.github.io/apps/"); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, buffer_info); - curl_easy_setopt(curl, CURLOPT_CAINFO, "/usr/etc/ssl/cert.pem"); - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); - res = curl_easy_perform(curl); - - if(res != CURLE_OK){ - fprintf(stderr, "Error : curl_%s\n", curl_easy_strerror(res)); - free(buffer_info->buffer); - free(buffer_info); - return NULL; - }else{ - return buffer_info; - } - - curl_easy_cleanup(curl); +fetch_apps_data_t* fetch_apps_data(CURL* curl){ + fetch_apps_data_t* buffer_info = malloc(sizeof(fetch_apps_data_t)); + buffer_info->buffer = NULL; + buffer_info->size = 0; + curl_easy_setopt(curl, CURLOPT_URL, "https://kot-store.github.io/apps/"); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, buffer_info); + curl_easy_setopt(curl, CURLOPT_CAINFO, "/usr/etc/ssl/cert.pem"); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + CURLcode res = curl_easy_perform(curl); + + if(res != CURLE_OK){ + fprintf(stderr, "Error : curl_%s\n", curl_easy_strerror(res)); + free(buffer_info->buffer); + free(buffer_info); + return NULL; + }else{ + return buffer_info; } - curl_global_cleanup(); - - return NULL; } -char* find_apps_url_by_name(char* name){ - fetch_apps_data_t* data_info = fetch_apps_data(); +char* find_apps_url_by_name(CURL* curl, char* name){ + fetch_apps_data_t* data_info = fetch_apps_data(curl); if(data_info != NULL){ cJSON* root = cJSON_Parse(data_info->buffer); - cJSON* applications = cJSON_GetObjectItem(root, "applications"); - - for(int i = 0 ; i < cJSON_GetArraySize(applications); i++){ - cJSON* application = cJSON_GetArrayItem(applications, i); - cJSON* application_name = cJSON_GetObjectItem(application, "name"); - if(cJSON_IsString(application_name) && (application_name->valuestring != NULL)){ - if(!strcmp(name, application_name->valuestring)){ - cJSON* json_link_application_url = cJSON_GetObjectItem(application, "json_link"); - if(cJSON_IsString(json_link_application_url) && (json_link_application_url->valuestring != NULL)){ + if(root != NULL){ + cJSON* applications = cJSON_GetObjectItem(root, "applications"); + + for(int i = 0 ; i < cJSON_GetArraySize(applications); i++){ + cJSON* application = cJSON_GetArrayItem(applications, i); + cJSON* application_name = cJSON_GetObjectItem(application, "name"); + if(cJSON_IsString(application_name) && (application_name->valuestring != NULL)){ + if(!strcmp(name, application_name->valuestring)){ + cJSON* json_link_application_url = cJSON_GetObjectItem(application, "json_link"); + if(cJSON_IsString(json_link_application_url) && (json_link_application_url->valuestring != NULL)){ char* return_value = malloc(strlen(json_link_application_url->valuestring) + 1); strcpy(return_value, json_link_application_url->valuestring); cJSON_Delete(root); @@ -72,9 +61,11 @@ char* find_apps_url_by_name(char* name){ free(data_info); return return_value; + } } - } - } + } + } + } cJSON_Delete(root); @@ -86,30 +77,38 @@ char* find_apps_url_by_name(char* name){ return NULL; } -char** find_apps_url_by_tag(char* tag){ - fetch_apps_data_t* data_info = fetch_apps_data(); - char** return_value = NULL; +app_url_by_tag_t** find_apps_url_by_tag(CURL* curl, char* tag){ + fetch_apps_data_t* data_info = fetch_apps_data(curl); + app_url_by_tag_t** return_value = NULL; if(data_info != NULL){ cJSON* root = cJSON_Parse(data_info->buffer); - cJSON* applications = cJSON_GetObjectItem(root, "applications"); - - size_t return_value_count_url = 0; - for(int i = 0 ; i < cJSON_GetArraySize(applications); i++){ - cJSON* application = cJSON_GetArrayItem(applications, i); - cJSON* application_tags = cJSON_GetObjectItem(application, "tags"); - - for(int y = 0 ; y < cJSON_GetArraySize(application_tags); y++){ - cJSON* application_tag = cJSON_GetArrayItem(application_tags, y); - if(cJSON_IsString(application_tag) && (application_tag->valuestring != NULL)){ - if(!strcmp(tag, application_tag->valuestring)){ - cJSON* json_link_application_url = cJSON_GetObjectItem(application, "json_link"); - if(cJSON_IsString(json_link_application_url) && (json_link_application_url->valuestring != NULL)){ - return_value = realloc(return_value, (return_value_count_url + 2) * sizeof(char*)); - return_value[return_value_count_url + 1] = NULL; - return_value[return_value_count_url] = malloc(strlen(json_link_application_url->valuestring) + 1); - strcpy(return_value[return_value_count_url], json_link_application_url->valuestring); - return_value_count_url++; + if(root != NULL){ + cJSON* applications = cJSON_GetObjectItem(root, "applications"); + + size_t return_value_count_url = 0; + for(int i = 0 ; i < cJSON_GetArraySize(applications); i++){ + cJSON* application = cJSON_GetArrayItem(applications, i); + cJSON* application_tags = cJSON_GetObjectItem(application, "tags"); + cJSON* application_name = cJSON_GetObjectItem(application, "name"); + + if(cJSON_IsString(application_name) && (application_name->valuestring != NULL)){ + for(int y = 0 ; y < cJSON_GetArraySize(application_tags); y++){ + cJSON* application_tag = cJSON_GetArrayItem(application_tags, y); + if(cJSON_IsString(application_tag) && (application_tag->valuestring != NULL)){ + if(!strcmp(tag, application_tag->valuestring)){ + cJSON* json_link_application_url = cJSON_GetObjectItem(application, "json_link"); + if(cJSON_IsString(json_link_application_url) && (json_link_application_url->valuestring != NULL)){ + return_value = realloc(return_value, (return_value_count_url + 2) * sizeof(app_url_by_tag_t*)); + return_value[return_value_count_url + 1] = NULL; + return_value[return_value_count_url] = malloc(sizeof(app_url_by_tag_t)); + return_value[return_value_count_url]->name = malloc(strlen(application_name->valuestring) + 1); + strcpy(return_value[return_value_count_url]->name, application_name->valuestring); + return_value[return_value_count_url]->url = malloc(strlen(json_link_application_url->valuestring) + 1); + strcpy(return_value[return_value_count_url]->url, json_link_application_url->valuestring); + return_value_count_url++; + } + } } } } @@ -123,4 +122,15 @@ char** find_apps_url_by_tag(char* tag){ } return return_value; +} + +void free_app_url_by_tag(app_url_by_tag_t** data){ + int i = 0; + while(data[i] != NULL){ + free(data[i]->name); + free(data[i]->url); + free(data[i]); + i++; + } + free(data); } \ No newline at end of file diff --git a/sources/core/apps/store/source/apps/apps.h b/sources/core/apps/store/source/apps/apps.h index 6857cf7df..c3a403615 100644 --- a/sources/core/apps/store/source/apps/apps.h +++ b/sources/core/apps/store/source/apps/apps.h @@ -8,8 +8,14 @@ typedef struct{ size_t size; }fetch_apps_data_t; -fetch_apps_data_t* fetch_apps_data(void); -char* find_apps_url_by_name(char* name); -char** find_apps_url_by_tag(char* tag); +typedef struct{ + char* url; + char* name; +}app_url_by_tag_t; + +fetch_apps_data_t* fetch_apps_data(CURL* curl); +char* find_apps_url_by_name(CURL* curl, char* name); +app_url_by_tag_t** find_apps_url_by_tag(CURL* curl, char* tag); +void free_app_url_by_tag(app_url_by_tag_t** data); #endif // APPS_H \ No newline at end of file diff --git a/sources/core/apps/store/source/core/core.c b/sources/core/apps/store/source/core/core.c index 1c1cbbf94..cb59e9096 100644 --- a/sources/core/apps/store/source/core/core.c +++ b/sources/core/apps/store/source/core/core.c @@ -4,6 +4,7 @@ #include #include "../apps/apps.h" +#include "../install/install.h" void print_help(){ printf("For help: ./store --help\n"); @@ -11,13 +12,15 @@ void print_help(){ } int main(int argc, char *argv[]){ - CURL *curl; - CURLcode res; + curl_global_init(CURL_GLOBAL_DEFAULT); + CURL *curl = curl_easy_init(); - if(argc > 1){ + if(curl == NULL){ + printf("Can't load curl"); + return -1; + }else if(argc > 1){ if(!strcmp(argv[1], "--help")){ print_help(); - return 0; }else if(!strcmp(argv[1], "--install") && argc == 2){ char search_mode[3]; printf("Search with > T(tag)/N(name)\n"); @@ -29,12 +32,12 @@ int main(int argc, char *argv[]){ fgets(tag, sizeof(tag), stdin); tag[strcspn(tag, "\n")] = 0; - char** url = find_apps_url_by_tag(tag); + app_url_by_tag_t** apps_available = find_apps_url_by_tag(curl, tag); - if(url != NULL){ + if(apps_available != NULL){ int i = 0; - while(url[i] != NULL){ - printf("%d) %s\n", i, url[i]); + while(apps_available[i] != NULL){ + printf("%d) %s\n", i, apps_available[i]->name); i++; } @@ -47,11 +50,11 @@ int main(int argc, char *argv[]){ if(index_to_install >= 0 && index_to_install < i){ char allow_install[3]; - printf("%s > Would you like to install it? (Y/N)\n", url[index_to_install]); + printf("%s > Would you like to install it? (Y/N)\n", apps_available[index_to_install]->name); fgets(allow_install, sizeof(allow_install), stdin); allow_install[strcspn(allow_install, "\n")] = 0; if(!strcmp("Y", allow_install)){ - // TODO + install_app(curl, apps_available[index_to_install]->url, apps_available[index_to_install]->name); }else{ printf("Cancel the installation\n"); } @@ -59,11 +62,9 @@ int main(int argc, char *argv[]){ printf("Unknow index !\n"); } - free(url); - return 0; + free_app_url_by_tag(apps_available); }else{ printf("No application found with tag: %s. Please check the spelling or try a different tag.\n", tag); - return 0; } }else if(!strcmp("N", search_mode)){ char name[512]; @@ -71,7 +72,7 @@ int main(int argc, char *argv[]){ fgets(name, sizeof(name), stdin); name[strcspn(name, "\n")] = 0; - char* url = find_apps_url_by_name(name); + char* url = find_apps_url_by_name(curl, name); if(url != NULL){ char allow_install[3]; @@ -79,40 +80,35 @@ int main(int argc, char *argv[]){ fgets(allow_install, sizeof(allow_install), stdin); allow_install[strcspn(allow_install, "\n")] = 0; if(!strcmp("Y", allow_install)){ - // TODO + install_app(curl, url, name); }else{ printf("Cancel the installation\n"); } free(url); - return 0; }else{ printf("Can't find %s in the store. Did you spell it correctly?\n", name); - return 0; } }else{ printf("Unknow search method !\n"); - return 0; } }else if(!strcmp(argv[1], "--install") && argc == 3){ char* name = argv[2]; - char* url = find_apps_url_by_name(name); - + char* url = find_apps_url_by_name(curl, name); + if(url != NULL){ char allow_install[3]; printf("%s found in the store. Would you like to install it? (Y/N)\n", name); fgets(allow_install, sizeof(allow_install), stdin); allow_install[strcspn(allow_install, "\n")] = 0; if(!strcmp("Y", allow_install)){ - // TODO + install_app(curl, url, name); }else{ printf("Cancel the installation\n"); } free(url); - return 0; }else{ printf("Can't find %s in the store. Did you spell it correctly?\n", name); - return 0; } }else{ print_help(); @@ -121,5 +117,9 @@ int main(int argc, char *argv[]){ print_help(); } + curl_easy_cleanup(curl); + + curl_global_cleanup(); + return 0; } diff --git a/sources/core/apps/store/source/deps/deps.c b/sources/core/apps/store/source/deps/deps.c new file mode 100644 index 000000000..20cbe16d8 --- /dev/null +++ b/sources/core/apps/store/source/deps/deps.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include +#include + +#include "deps.h" + +static bool is_file_exists(char* path){ + struct stat sb; + return (stat(path, &sb) == 0); +} + +int check_dependencies(char* app_info_json_path, char** installation_file_url){ + FILE* fp = fopen(app_info_json_path, "r"); + + if(fp == NULL){ + printf("Error: Unable to open the file : %s\n", app_info_json_path); + return -1; + } + + fseek(fp, 0, SEEK_END); + size_t size = ftell(fp); + fseek(fp, 0, SEEK_SET); + + void* buffer = malloc(size); + int len = fread(buffer, 1, size, fp); + fclose(fp); + + cJSON* root = cJSON_Parse(buffer); + + int r = 0; + + if(root != NULL){ + cJSON* dependencies = cJSON_GetObjectItem(root, "dependencies_file"); + if(dependencies != NULL){ + for(int i = 0 ; i < cJSON_GetArraySize(dependencies); i++){ + cJSON* dependency = cJSON_GetArrayItem(dependencies, i); + if(cJSON_IsString(dependency) && (dependency->valuestring != NULL)){ + if(!is_file_exists(dependency->valuestring)){ + printf("Depency %s not found !\n", dependency->valuestring); + r = -1; + break; + } + } + } + } + + cJSON* installation_file = cJSON_GetObjectItem(root, "installation_file"); + if(cJSON_IsString(installation_file) && (installation_file->valuestring != NULL)){ + *installation_file_url = malloc(strlen(installation_file->valuestring) + 1); + strcpy(*installation_file_url, installation_file->valuestring); + } + }else{ + const char *error_ptr = cJSON_GetErrorPtr(); + if(error_ptr != NULL){ + printf("Error: %s\n", error_ptr); + } + r = -1; + } + + + cJSON_Delete(root); + free(buffer); + return r; +} \ No newline at end of file diff --git a/sources/core/apps/store/source/deps/deps.h b/sources/core/apps/store/source/deps/deps.h new file mode 100644 index 000000000..11ec47f80 --- /dev/null +++ b/sources/core/apps/store/source/deps/deps.h @@ -0,0 +1,6 @@ +#ifndef DEPS_H +#define DEPS_H + +int check_dependencies(char* app_info_json_path, char** installation_file_url); + +#endif // DEPS_H \ No newline at end of file diff --git a/sources/core/apps/store/source/download/download.c b/sources/core/apps/store/source/download/download.c new file mode 100644 index 000000000..20a02a399 --- /dev/null +++ b/sources/core/apps/store/source/download/download.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include + +static size_t write_callback(void *contents, size_t size, size_t nmemb, void *userp){ + size_t real_size = size * nmemb; + fwrite(contents, size, nmemb, (FILE*)userp); + return real_size; +} + +static int progress_callback(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow){ + double time_begin = *(double*)clientp; + + double download_speed = (double)dlnow / (time(NULL) - time_begin); + if(download_speed > 0){ + int eta = (int)((dltotal - dlnow) / download_speed); + printf("\033[-1B"); + printf("%d/%d ETA : %d s\n", (int)dlnow, (int)dltotal, eta); + } + + return 0; +} + + +int download_file(CURL* curl, char* url, char* path){ + printf("Initiating download of `%s` to `%s`\n", url, path); + int r = -1; + FILE* fp = fopen(path, "wb"); + + if(fp == NULL){ + printf("Failed to open file `%s` for writing. Error: %s\n", path, strerror(errno)); + }else{ + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); + curl_easy_setopt(curl, CURLOPT_CAINFO, "/usr/etc/ssl/cert.pem"); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); + + double time_begin = time(NULL); + curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &time_begin); + curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback); + + printf("N/A\n"); + CURLcode res = curl_easy_perform(curl); + if(res == CURLE_OK){ + r = 0; + printf("Completed successfully.\n"); + } else { + printf("Failed. Error: %s\n", curl_easy_strerror(res)); + } + + fclose(fp); + } + + return r; +} \ No newline at end of file diff --git a/sources/core/apps/store/source/download/download.h b/sources/core/apps/store/source/download/download.h new file mode 100644 index 000000000..77891661b --- /dev/null +++ b/sources/core/apps/store/source/download/download.h @@ -0,0 +1,9 @@ +#ifndef DOWNLOAD_H +#define DOWNLOAD_H + +#include +#include + +int download_file(CURL* curl, char* url, char* path); + +#endif // DOWNLOAD_H \ No newline at end of file diff --git a/sources/core/apps/store/source/install/install.c b/sources/core/apps/store/source/install/install.c new file mode 100644 index 000000000..77e4109e8 --- /dev/null +++ b/sources/core/apps/store/source/install/install.c @@ -0,0 +1,95 @@ +#include +#include +#include +#include +#include + +#include "install.h" +#include "../deps/deps.h" +#include "../download/download.h" + +static bool is_dir_exist(char* path){ + struct stat sb; + return (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)); +} + +static int create_dir_if_not_exist(char* path){ + if(!is_dir_exist(path)){ + mkdir(path, 0777); + } + + return 0; +} + +int install_app(CURL* curl, char* url, char* name){ + char* path_store = getenv("PATHSTORE"); + create_dir_if_not_exist(path_store); + + char* path_store_app = malloc(strlen(path_store) + sizeof((char)'/') + strlen(name) + sizeof((char)'/') + 1); + strcpy(path_store_app, path_store); + strcat(path_store_app, "/"); + strcat(path_store_app, name); + strcat(path_store_app, "/"); + create_dir_if_not_exist(path_store_app); + + char* path_store_app_info_json = malloc(strlen(path_store_app) + strlen("app-info.json") + 1); + strcpy(path_store_app_info_json, path_store_app); + strcat(path_store_app_info_json, "app-info.json"); + + if(download_file(curl, url, path_store_app_info_json)){ + printf("Error: Aborting installation of %s!\n", name); + + free(path_store_app_info_json); + free(path_store_app); + return -1; + } + + printf("Checking dependencies...\n"); + char* installation_file_url = NULL; + if(check_dependencies(path_store_app_info_json, &installation_file_url)){ + char force_install[3]; + printf("Some dependencies required for installation are not found. If you choose to continue, the installation may not work as expected. Do you still want to proceed with the installation? (Y/N)\n"); + fgets(force_install, sizeof(force_install), stdin); + force_install[strcspn(force_install, "\n")] = 0; + if(strcmp("Y", force_install)){ + printf("Aborting installation of %s!\n", name); + + remove(path_store_app_info_json); + rmdir(path_store_app); + + free(path_store_app_info_json); + free(path_store_app); + return -1; + } + }else{ + printf("All dependencies found\n"); + } + + if(installation_file_url != NULL){ + char* installation_file_name = strrchr(installation_file_url, '/'); + if(installation_file_name != NULL){ + installation_file_name++; + char* path_store_installation_file = malloc(strlen(path_store_app) + strlen(installation_file_name) + 1); + strcpy(path_store_installation_file, path_store_app); + strcat(path_store_installation_file, installation_file_name); + + if(download_file(curl, "https://raw.githubusercontent.com/dscape/spell/master/test/resources/big.txt", path_store_installation_file)){ + printf("Error: Aborting installation of %s!\n", name); + + remove(path_store_app_info_json); + rmdir(path_store_app); + + free(installation_file_url); + free(path_store_installation_file); + free(path_store_app_info_json); + free(path_store_app); + return -1; + } + } + } + + free(path_store_app_info_json); + free(path_store_app); + + return 0; +} \ No newline at end of file diff --git a/sources/core/apps/store/source/install/install.h b/sources/core/apps/store/source/install/install.h new file mode 100644 index 000000000..0ced0bddd --- /dev/null +++ b/sources/core/apps/store/source/install/install.h @@ -0,0 +1,9 @@ +#ifndef INSTALL_H +#define INSTALL_H + +#include +#include + +int install_app(CURL* curl, char* url, char* name); + +#endif // INSTALL_H \ No newline at end of file diff --git a/sources/core/kernel/source/global/heap.c b/sources/core/kernel/source/global/heap.c index cf9ac3aa3..691551d6a 100644 --- a/sources/core/kernel/source/global/heap.c +++ b/sources/core/kernel/source/global/heap.c @@ -1,17 +1,16 @@ -#include #include #include #include #include #include #include +#include #include #include +#include #include -// #define HEAP_DEBUG 0 - -#ifdef HEAP_DEBUG +#ifdef DEBUG_HEAP static void* heap_end = 0; static spinlock_t lock = SPINLOCK_INIT; diff --git a/sources/core/kernel/source/global/syscall.c b/sources/core/kernel/source/global/syscall.c index 5ddad1ff5..19e857d71 100644 --- a/sources/core/kernel/source/global/syscall.c +++ b/sources/core/kernel/source/global/syscall.c @@ -331,10 +331,6 @@ static void syscall_handler_read(cpu_context_t* ctx){ size_t size = (size_t)ARCH_CONTEXT_SYSCALL_ARG2(ctx); descriptor_t* descriptor = get_descriptor(&ARCH_CONTEXT_CURRENT_THREAD(ctx)->process->descriptors_ctx, fd); - - if(descriptor == NULL){ - SYSCALL_RETURN(ctx, -EBADF); - } if(descriptor->type == DESCRIPTOR_TYPE_FILE){ kernel_file_t* file = descriptor->data.file; @@ -572,6 +568,26 @@ static void syscall_handler_dir_remove(cpu_context_t* ctx){ SYSCALL_RETURN(ctx, -ENOSYS); } +static void syscall_handler_dir_create(cpu_context_t* ctx){ + char* path = (char*)ARCH_CONTEXT_SYSCALL_ARG0(ctx); + size_t path_len = (size_t)ARCH_CONTEXT_SYSCALL_ARG1(ctx); + mode_t mode = (mode_t)ARCH_CONTEXT_SYSCALL_ARG2(ctx); + + if(path_len >= PATH_MAX){ + SYSCALL_RETURN(ctx, -EINVAL); + } + + if(vmm_check_memory(vmm_get_current_space(), (memory_range_t){path, path_len + 1})){ + SYSCALL_RETURN(ctx, -EINVAL); + } + + path[path_len] = '\0'; + + int error = d_create(ARCH_CONTEXT_CURRENT_THREAD(ctx)->process->vfs_ctx, path, mode); + + SYSCALL_RETURN(ctx, error); +} + static void syscall_handler_unlink_at(cpu_context_t* ctx){ log_warning("%s : syscall not implemented\n", __FUNCTION__); SYSCALL_RETURN(ctx, -ENOSYS); @@ -1003,6 +1019,7 @@ static syscall_handler_t handlers[SYS_COUNT] = { syscall_handler_ioctl, syscall_handler_dir_read_entries, syscall_handler_dir_remove, + syscall_handler_dir_create, syscall_handler_unlink_at, syscall_handler_rename_at, syscall_handler_path_stat, diff --git a/sources/core/kernel/source/parameters.h b/sources/core/kernel/source/parameters.h index fd43a05d5..b59716f14 100644 --- a/sources/core/kernel/source/parameters.h +++ b/sources/core/kernel/source/parameters.h @@ -1,6 +1,7 @@ #ifndef _PARAMETERS_H #define _PARAMETERS_H 1 +// #define DEBUG_HEAP #define DEBUG_MODULES // #define DEBUG_SYSCALL diff --git a/sources/core/libs/mlibc/sysdeps/kot/generic/filesystem.cpp b/sources/core/libs/mlibc/sysdeps/kot/generic/filesystem.cpp index b88a322da..5d58c920d 100644 --- a/sources/core/libs/mlibc/sysdeps/kot/generic/filesystem.cpp +++ b/sources/core/libs/mlibc/sysdeps/kot/generic/filesystem.cpp @@ -163,6 +163,16 @@ namespace mlibc{ return 0; } + int sys_mkdir(const char *path, mode_t mode) { + auto result = do_syscall(SYS_DIR_CREATE, path, strlen(path), mode); + + if (result < 0) { + return -result; + } + + return 0; + } + int sys_unlinkat(int dirfd, const char *path, int flags){ auto result = do_syscall(SYS_UNLINK_AT, AT_FDCWD, path, AT_REMOVEDIR); diff --git a/sources/core/libs/mlibc/sysdeps/kot/generic/generic.cpp b/sources/core/libs/mlibc/sysdeps/kot/generic/generic.cpp index 5394ff8f5..3b0bfd321 100644 --- a/sources/core/libs/mlibc/sysdeps/kot/generic/generic.cpp +++ b/sources/core/libs/mlibc/sysdeps/kot/generic/generic.cpp @@ -358,6 +358,59 @@ namespace mlibc{ return 0; } + int sys_setsockopt(int fd, int layer, int number, const void *buffer, socklen_t size) { + (void)fd; + (void)buffer; + (void)size; + + if (layer == SOL_SOCKET && number == SO_PASSCRED) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt(SO_PASSCRED) is not " + "implemented correctly\e[39m" + << frg::endlog; + return 0; + } else if (layer == SOL_SOCKET && number == SO_ATTACH_FILTER) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt(SO_ATTACH_FILTER) is " + "not implemented correctly\e[39m" + << frg::endlog; + return 0; + } else if (layer == SOL_SOCKET && number == SO_RCVBUFFORCE) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt(SO_RCVBUFFORCE) is not " + "implemented correctly\e[39m" + << frg::endlog; + return 0; + } else if (layer == SOL_SOCKET && number == SO_SNDBUF) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt() call with SOL_SOCKET " + "and SO_SNDBUF is unimplemented\e[39m" + << frg::endlog; + return 0; + } else if (layer == SOL_SOCKET && number == SO_KEEPALIVE) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt() call with SOL_SOCKET " + "and SO_KEEPALIVE is unimplemented\e[39m" + << frg::endlog; + return 0; + } else if (layer == SOL_SOCKET && number == SO_REUSEADDR) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt() call with SOL_SOCKET " + "and SO_REUSEADDR is unimplemented\e[39m" + << frg::endlog; + return 0; + } else if (layer == AF_NETLINK && number == SO_ACCEPTCONN) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt() call with AF_NETLINK " + "and SO_ACCEPTCONN is unimplemented\e[39m" + << frg::endlog; + return 0; + }else if (layer == AF_BRIDGE && number == SO_ACCEPTCONN) { + mlibc::infoLogger() << "\e[31mmlibc: setsockopt() call with AF_BRIDGE " + "and SO_ACCEPTCONN is unimplemented\e[39m" + << frg::endlog; + return 0; + } else { + mlibc::panicLogger() + << "\e[31mmlibc: Unexpected setsockopt() call, layer: " << layer + << " number: " << number << "\e[39m" << frg::endlog; + __builtin_unreachable(); + } + } + int sys_getentropy(void *buffer, size_t length){ mlibc::infoLogger() << "mlibc: " << __func__ << " is a stub" << frg::endlog; return 0; diff --git a/sources/core/libs/mlibc/sysdeps/kot/include/kot/syscall.h b/sources/core/libs/mlibc/sysdeps/kot/include/kot/syscall.h index bd995043f..9ac5073fc 100644 --- a/sources/core/libs/mlibc/sysdeps/kot/include/kot/syscall.h +++ b/sources/core/libs/mlibc/sysdeps/kot/include/kot/syscall.h @@ -8,7 +8,7 @@ typedef long sc_word_t; /* list */ -#define SYS_COUNT 46 +#define SYS_COUNT 47 #define SYS_LOG 0 #define SYS_ARCH_PRCTL 1 @@ -40,22 +40,23 @@ typedef long sc_word_t; #define SYS_FILE_IOCTL 27 #define SYS_DIR_READ_ENTRIES 28 #define SYS_DIR_REMOVE 29 -#define SYS_UNLINK_AT 30 -#define SYS_RENAME_AT 31 -#define SYS_PATH_STAT 32 -#define SYS_FD_STAT 33 -#define SYS_FCNTL 34 -#define SYS_GETCWD 35 -#define SYS_CHDIR 36 -#define SYS_SOCKET 37 -#define SYS_BIND 38 -#define SYS_CONNECT 39 -#define SYS_LISTEN 40 -#define SYS_ACCEPT 41 -#define SYS_SOCKET_SEND 42 -#define SYS_SOCKET_RECV 43 -#define SYS_SOCKET_PAIR 44 -#define SYS_PPOLL 45 +#define SYS_DIR_CREATE 30 +#define SYS_UNLINK_AT 31 +#define SYS_RENAME_AT 32 +#define SYS_PATH_STAT 33 +#define SYS_FD_STAT 34 +#define SYS_FCNTL 35 +#define SYS_GETCWD 36 +#define SYS_CHDIR 37 +#define SYS_SOCKET 38 +#define SYS_BIND 39 +#define SYS_CONNECT 40 +#define SYS_LISTEN 41 +#define SYS_ACCEPT 42 +#define SYS_SOCKET_SEND 43 +#define SYS_SOCKET_RECV 44 +#define SYS_SOCKET_PAIR 45 +#define SYS_PPOLL 46 /* extern functions */ diff --git a/sources/core/modules/fat32/source/core.c b/sources/core/modules/fat32/source/core.c index 44a9627fe..992e0b119 100644 --- a/sources/core/modules/fat32/source/core.c +++ b/sources/core/modules/fat32/source/core.c @@ -157,15 +157,14 @@ static int fat_free_cluster(fat_context_t* ctx, uint32_t cluster){ } static int fat_free_all_following_clusters(fat_context_t* ctx, uint32_t cluster){ - uint32_t next_cluster = fat_get_next_cluster(ctx, cluster); + uint32_t next_cluster = cluster; - fat_free_cluster(ctx, cluster); - - if(next_cluster < 0x0FFFFFF8){ - return fat_free_all_following_clusters(ctx, next_cluster); - }else{ - return 0; + while(next_cluster < 0x0FFFFFF8){ + fat_free_cluster(ctx, next_cluster); + next_cluster = fat_get_next_cluster(ctx, cluster); } + + return 0; } @@ -1049,7 +1048,7 @@ int fat_file_write(fat_file_internal_t* file, uint64_t start, size_t size, size_ uint64_t size_write_tmp = 0; - uint32_t base_cluster = fat_get_cluster_file(&file->entry); + uint32_t base_cluster = fat_get_cluster_file(&file->entry); if(base_cluster == 0){ // Allocate the first cluster of the entry diff --git a/sources/core/modules/net/source/ip.c b/sources/core/modules/net/source/ip.c index 198fab044..4ae755605 100644 --- a/sources/core/modules/net/source/ip.c +++ b/sources/core/modules/net/source/ip.c @@ -162,7 +162,7 @@ void compute_tcp_checksum(struct iphdr* ip_header, uint16_t* data, size_t length } if(length > 0){ - result += ((*data) & htons(0xFF00)); + result += ((*((uint8_t*)data)) & htons(0xFF00)); } while(result >> 16){ @@ -194,7 +194,7 @@ void compute_udp_checksum(struct iphdr* ip_header, uint16_t* data, size_t length } if(length > 0){ - result += ((*data) & htons(0xFF00)); + result += ((*((uint8_t*)data)) & htons(0xFF00)); } while(result >> 16){ diff --git a/sources/core/modules/net/source/socket.c b/sources/core/modules/net/source/socket.c index 8d7bc76f5..fb76c0ed8 100644 --- a/sources/core/modules/net/source/socket.c +++ b/sources/core/modules/net/source/socket.c @@ -24,6 +24,17 @@ static int get_tcp_listener(int listen_accept_count, socket_tcp_listener_t* list return -1; } +static void tcp_send_buffer(socket_tcp_listener_t* listener, void* buffer, size_t size){ + tcp_listener_buffer_t* next_data_buffer = malloc(sizeof(tcp_listener_buffer_t)); + next_data_buffer->size = 0; /* invalid the next data for now */ + + listener->last_allocated->next = next_data_buffer; + listener->last_allocated->buffer = buffer; + listener->last_allocated->size = size; + + listener->last_allocated = next_data_buffer; /* update the last allocated */ +} + void tcp_socket_handler(void* external_data, net_device_t* net_device, struct tcphdr* tcp_header, size_t size, uint32_t saddr){ kernel_socket_t* socket = (kernel_socket_t*)external_data; socket_internal_data_t* internal_data = (socket_internal_data_t*)socket->internal_data; @@ -59,7 +70,7 @@ void tcp_socket_handler(void* external_data, net_device_t* net_device, struct tc bool is_need_to_ack = false; size_t data_offset = tcp_header->th_off * sizeof(uint32_t); - size_t size_data = size - data_offset; + size_t data_size = size - data_offset; if(listener->sequence_waiting_for_ack && tcp_header->th_flags & TH_ACK){ listener->sequence_waiting_for_ack = 0; @@ -76,40 +87,82 @@ void tcp_socket_handler(void* external_data, net_device_t* net_device, struct tc is_need_to_ack = true; } - if(size_data){ - is_need_to_ack = true; - + if(data_size){ + bool ignore_data = false; void* data = (void*)((uintptr_t)tcp_header + (uintptr_t)data_offset); size_t awaiting_data_to_read = listener->buffer_read_size_allocated - listener->buffer_read_size; - size_t next_sequence = ntohl(tcp_header->th_seq) + size_data; + size_t next_sequence = ntohl(tcp_header->th_seq) + data_size; if(awaiting_data_to_read == 0){ - listener->buffer_read_size_allocated = next_sequence - listener->sequence_receive; - listener->buffer_read = malloc(listener->buffer_read_size_allocated); - listener->buffer_read_size = 0; - listener->start_offset = listener->sequence_receive; - - } - - if(listener->buffer_read_size + size_data <= listener->buffer_read_size_allocated){ - size_t offset = listener->sequence_receive - listener->start_offset; - void* data_dst = (void*)((uintptr_t)listener->buffer_read + (uintptr_t)offset); - - memcpy(data_dst, data, size_data); - listener->buffer_read_size += size_data; - listener->sequence_receive = next_sequence; + size_t size_to_allocate = next_sequence - listener->sequence_receive; + if(size_to_allocate <= ntohs(tcp_header->th_win)){ + listener->buffer_read_size_allocated = size_to_allocate; + listener->buffer_read = malloc(size_to_allocate); + listener->buffer_read_size = 0; + listener->start_offset = listener->sequence_receive; + listener->smallest_write_offset = ntohl(tcp_header->th_seq); + }else{ + ignore_data = true; + } } - if(listener->buffer_read_size_allocated == listener->buffer_read_size){ - tcp_listener_buffer_t* next_data_buffer = malloc(sizeof(tcp_listener_buffer_t)); - next_data_buffer->size = 0; /* invalid the next data for now */ + if(ntohl(tcp_header->th_seq) >= listener->start_offset){ + size_t offset = ntohl(tcp_header->th_seq) - listener->start_offset; + size_t end_size = offset + data_size; + if(end_size > listener->buffer_read_size_allocated){ + if(end_size <= ntohs(tcp_header->th_win)){ + listener->buffer_read = realloc(listener->buffer_read, end_size); + listener->buffer_read_size_allocated = end_size; + }else{ + ignore_data = true; + } + } - listener->last_allocated->next = next_data_buffer; - listener->last_allocated->buffer = listener->buffer_read; - listener->last_allocated->size = listener->buffer_read_size_allocated; + if(!ignore_data){ + listener->is_receiving_data = true; + + if(listener->smallest_write_offset > ntohl(tcp_header->th_seq)){ + if(listener->smallest_write_offset == next_sequence){ + listener->smallest_continuous_size += data_size; + }else{ + listener->smallest_continuous_size = data_size; + } + listener->smallest_write_offset = ntohl(tcp_header->th_seq); + } - listener->last_allocated = next_data_buffer; /* update the last allocated */ + void* data_dst = (void*)((uintptr_t)listener->buffer_read + (uintptr_t)offset); + + memcpy(data_dst, data, data_size); + listener->buffer_read_size += data_size; + + if(listener->buffer_read_size_allocated == listener->buffer_read_size){ + listener->sequence_receive = listener->start_offset + listener->buffer_read_size_allocated; + tcp_send_buffer(listener, listener->buffer_read, listener->buffer_read_size_allocated); + is_need_to_ack = true; + }else if(listener->smallest_write_offset == listener->start_offset){ + listener->sequence_receive = next_sequence; + size_t low_buffer_size = listener->smallest_continuous_size; + void* low_buffer = malloc(low_buffer_size); + memcpy(low_buffer, listener->buffer_read, low_buffer_size); + tcp_send_buffer(listener, low_buffer, low_buffer_size); + + size_t high_buffer_size = listener->buffer_read_size_allocated - low_buffer_size; + void* high_buffer = malloc(high_buffer_size); + void* high_buffer_src = (void*)((uintptr_t)listener->buffer_read + (uintptr_t)low_buffer_size); + memcpy(high_buffer, high_buffer_src, high_buffer_size); + + free(listener->buffer_read); + + listener->start_offset += low_buffer_size; + listener->buffer_read_size_allocated -= low_buffer_size; + listener->buffer_read = high_buffer; + listener->buffer_read_size -= low_buffer_size; + listener->smallest_continuous_size = 0; + listener->smallest_write_offset = listener->start_offset + listener->buffer_read_size_allocated; + is_need_to_ack = true; + } + } } } @@ -149,12 +202,12 @@ void udp_socket_handler(void* external_data, net_device_t* net_device, struct ud socket_internal_data_t* internal_data = (socket_internal_data_t*)socket->internal_data; size_t data_offset = sizeof(struct udphdr); - size_t size_data = size - data_offset; + size_t data_size = size - data_offset; - if(size_data){ + if(data_size){ if(internal_data->data.udp->is_awaiting_read){ void* data = (void*)((uintptr_t)udp_header + (uintptr_t)data_offset); - size_t size_to_copy = MIN(size_data, internal_data->data.udp->buffer_read_max_size); + size_t size_to_copy = MIN(data_size, internal_data->data.udp->buffer_read_max_size); vmm_space_swap(internal_data->data.udp->read_buffer_vmm_space); memcpy(internal_data->data.udp->buffer_read, data, size_to_copy); @@ -164,11 +217,11 @@ void udp_socket_handler(void* external_data, net_device_t* net_device, struct ud internal_data->data.udp->is_awaiting_read = false; }else if(!internal_data->data.udp->cache_size_used){ void* data = (void*)((uintptr_t)udp_header + (uintptr_t)data_offset); - size_t size_to_copy = MIN(size_data, internal_data->data.udp->cache_size); + size_t size_to_copy = MIN(data_size, internal_data->data.udp->cache_size); memcpy(internal_data->data.udp->cache_buffer, data, size_to_copy); - internal_data->data.udp->cache_size_used = size_data; + internal_data->data.udp->cache_size_used = data_size; } } } @@ -194,7 +247,10 @@ int socket_general_receive_handler(void* buffer, size_t size, size_t* size_recei size_t size_to_read = size; - while(size_to_read == size && !listener->is_fin){ + int timeout = TIMEOUT_RECEIVE; + + listener->is_receiving_data = false; + while(size_to_read == size && !listener->is_fin && timeout > 0){ if(listener->last_read != NULL){ uintptr_t offset = 0; while((listener->last_read->next->size > 0) && (size_to_read > 0)){ @@ -221,13 +277,19 @@ int socket_general_receive_handler(void* buffer, size_t size, size_t* size_recei offset += size_reading; } } + timeout--; + kernel_sleep_us(1000); + + if(listener->is_receiving_data){ + /* Reset timeout each time we receive data */ + timeout = TIMEOUT_RECEIVE; + listener->is_receiving_data = false; + } } *size_receive = size - size_to_read; spinlock_release(&listener->lock); - - return 0; } case TYPE_TCP:{ if(internal_data->data.tcp->is_connect){ @@ -236,7 +298,10 @@ int socket_general_receive_handler(void* buffer, size_t size, size_t* size_recei size_t size_to_read = size; - while(size_to_read == size && !listener->is_fin){ + int timeout = TIMEOUT_RECEIVE; + + listener->is_receiving_data = false; + while(size_to_read == size && !listener->is_fin && timeout > 0){ if(listener->last_read != NULL){ uintptr_t offset = 0; while((listener->last_read->next->size > 0) && (size_to_read > 0)){ @@ -263,6 +328,14 @@ int socket_general_receive_handler(void* buffer, size_t size, size_t* size_recei offset += size_reading; } } + timeout--; + kernel_sleep_us(1000); + + if(listener->is_receiving_data){ + /* Reset timeout each time we receive data */ + timeout = TIMEOUT_RECEIVE; + listener->is_receiving_data = false; + } } @@ -831,14 +904,11 @@ int socket_get_event(struct kernel_socket_t* socket, short events, short* revent *revents = internal_data->events & events; - int events_count = internal_data->events_count; - switch (internal_data->data_type){ case TYPE_TCP_CHILD:{ socket_tcp_listener_t* listener = internal_data->data.tcp_child->listener; if((listener->last_read->next->size > 0) && (events & POLLIN)){ *revents |= POLLIN; - events_count++; } return 0; } @@ -847,14 +917,20 @@ int socket_get_event(struct kernel_socket_t* socket, short events, short* revent socket_tcp_listener_t* listener = &internal_data->data.tcp->listeners[0]; if((listener->last_read->next->size > 0) && (events & POLLIN)){ *revents |= POLLIN; - events_count++; } } break; } } - return events_count; + int return_value; + if(*revents == 0){ + return_value = 0; + }else{ + return_value = 1; + } + + return return_value; } kernel_socket_t* socket_accept_handler(kernel_socket_t* socket, struct sockaddr* addr_ptr, socklen_t* addr_length, int* error){ @@ -950,7 +1026,6 @@ kernel_socket_t* socket_accept_handler(kernel_socket_t* socket, struct sockaddr* } child_internal_data->events = POLLOUT; - child_internal_data->events_count = 1; *error = 0; return socket_child; @@ -1001,7 +1076,6 @@ kernel_socket_t* socket_handler(int family, int type, int protocol, int* error){ } internal_data->events = POLLOUT; - internal_data->events_count = 1; *error = 0; return socket; diff --git a/sources/core/modules/net/source/socket.h b/sources/core/modules/net/source/socket.h index 2e5c0f1a6..8936eece0 100644 --- a/sources/core/modules/net/source/socket.h +++ b/sources/core/modules/net/source/socket.h @@ -7,6 +7,7 @@ #include #include +#define TIMEOUT_RECEIVE 5000 #define MIN_LISTENING_PORT 1024 #define MAX_LISTENING_PORT 65535 @@ -40,14 +41,18 @@ typedef struct{ /* all buffers */ tcp_listener_buffer_t* last_allocated; - tcp_listener_buffer_t* last_read; + tcp_listener_buffer_t* last_read; /* current buffer */ void* buffer_read; - size_t start_offset; + tcp_seq start_offset; + tcp_seq smallest_write_offset; + size_t smallest_continuous_size; size_t buffer_read_size; size_t buffer_read_size_allocated; + bool is_receiving_data; + struct socket_internal_data_t* internal_data_parent; }socket_tcp_listener_t; @@ -97,7 +102,6 @@ typedef struct socket_internal_data_t{ }data; short events; - int events_count; }socket_internal_data_t; int socket_connect_handler(kernel_socket_t* socket, const struct sockaddr* addr_ptr, socklen_t addr_length); diff --git a/target/makefile b/target/makefile index 77d9e61ad..9274891d3 100644 --- a/target/makefile +++ b/target/makefile @@ -27,7 +27,7 @@ LIAMD_QEMU_FLAGS = \ -bios $(EXTERN)/ovmf-amd64/OVMF.fd \ -drive file=liamd/boot-kot.img \ -machine q35 \ - -m 2G \ + -m 4G \ -smp cores=4 \ -serial stdio \ -device e1000e,netdev=net0 \