#include #include #include #include "boot/answer_code.hpp" #include "drivers/fs/handlers.hpp" #include "drivers/fs/fs.hpp" Handler_vfs boot_handler("/boot"); void parse_and_fill_arg_c(const char* start, size_t len, arg* out_arg) { if (len == 0) { out_arg->type = argNONE_t; return; } size_t copy_len = (len > 31) ? 31 : len; char tmp[33]; memcpy(tmp, start, copy_len); tmp[copy_len] = '\0'; char* endptr; long int_val = strtol(tmp, &endptr, 10); if (*endptr == '\0') { out_arg->type = argINT_t; out_arg->value.valueINT = (int)int_val; return; } float float_val = strtof(tmp, &endptr); if (*endptr == '\0') { out_arg->type = argFLOAT_t; out_arg->value.valueFLOAT = float_val; return; } out_arg->type = argSTRING_t; memcpy(out_arg->value.valueSTRING, tmp, copy_len + 1); } void parse_args_c_style(const char* input, arg* args_array) { for (int i = 0; i < 8; i++) { args_array[i].type = argNONE_t; } if (input == nullptr) return; const char* token_start = input; if (input[0] == '\\' && input[1] == '$') { input += 2; token_start = input; } int arg_index = 0; while (*input != '\0') { if (*input == '\\' && *(input + 1) == '$') { if (input != token_start && *(input - 1) == '\\') { input += 2; continue; } size_t token_len = input - token_start; if (arg_index < 8) { parse_and_fill_arg_c(token_start, token_len, &args_array[arg_index]); arg_index++; } input += 2; token_start = input; continue; } input++; } size_t last_len = input - token_start; if (last_len > 0 && arg_index < 8) { parse_and_fill_arg_c(token_start, last_len, &args_array[arg_index]); } } Handler_vfs::Handler_vfs(const char *path) { strcpy(this->path, path); count_fn = 0; count_ds = 0; capacity_fn = 10; capacity_ds = 10; functions = (function_file*)malloc(capacity_fn * sizeof(function_file)); descriptors = (descriptor*)malloc(capacity_ds * sizeof(descriptor)); }; Handler_vfs::~Handler_vfs() { if (functions != nullptr) free(functions); if (descriptors != nullptr) free(descriptors); } int Handler_vfs::link_function(const char *name, func_t func) { if (count_fn + 1 > capacity_fn) { int new_capacity = capacity_fn + 10; size_t new_size = new_capacity * sizeof(function_file); function_file* temp = (function_file*)realloc(functions, new_size); if (temp != nullptr) { functions = temp; capacity_fn = new_capacity; } else { return -1; } } strncpy(functions[count_fn].name, name, 31); functions[count_fn].name[31] = '\0'; functions[count_fn].handler = func; count_fn++; return 0; } int Handler_vfs::unlink_function(const char *name) { int index = -1; for (int i = 0; i < count_fn; i++) { if (strcmp(functions[i].name, name) == 0) { index = i; break; } } if (index == -1) return -1; for (int i = index; i < count_fn - 1; i++) { functions[i] = functions[i + 1]; } count_fn--; if (capacity_fn - count_fn >= 15 && capacity_fn > 10) { int new_capacity = capacity_fn - 10; size_t new_size = new_capacity * sizeof(function_file); function_file* temp = (function_file*)realloc(functions, new_size); if (temp != nullptr || new_size == 0) { functions = temp; capacity_fn = new_capacity; } } return 0; } int Handler_vfs::open(const char *name, int flags, int mode) { int fn_idx = -1; for (int i = 0; i < count_fn; i++) { if (strcmp(functions[i].name, name) == 0) { fn_idx = i; break; } } if (fn_idx == -1) return OS_ERR_NOT_FOUND; int target_fd = -1; for (int i = 0; i < count_ds; i++) { if (descriptors[i].handler == nullptr) { target_fd = i; break; } } if (target_fd == -1) { if (count_ds + 1 > capacity_ds) { int new_capacity = capacity_ds + 10; descriptor* temp = (descriptor*)realloc(descriptors, new_capacity * sizeof(descriptor)); if (temp == nullptr) return OS_ERR_NO_MEMORY; descriptors = temp; capacity_ds = new_capacity; } target_fd = count_ds; count_ds++; } memset(descriptors[target_fd].name, 0, 32); strncpy(descriptors[target_fd].name, name, 31); descriptors[target_fd].handler = functions[fn_idx].handler; for(int i=0; i<8; ++i) descriptors[target_fd].args[i].type = argNONE_t; return target_fd; } int Handler_vfs::open_vfs(void* ctx, const char *path, int flags, int mode) { Handler_vfs* self = (Handler_vfs*)ctx; return self->open(path, flags, mode); } ssize_t Handler_vfs::read(int fd, void *dst, size_t size) { if (fd < 0 || fd >= count_ds || descriptors[fd].handler == nullptr) return OS_ERR_NOT_FOUND; if (dst == nullptr) { descriptors[fd].handler(&descriptors[fd]); return 0; } if (size < sizeof(Result)) return OS_ERR_NO_MEMORY; Result res = descriptors[fd].handler(&descriptors[fd]); memcpy(dst, &res, sizeof(res)); return sizeof(res); } ssize_t Handler_vfs::read_vfs(void* ctx, int fd, void *dst, size_t size) { Handler_vfs* self = (Handler_vfs*)ctx; return self->read(fd, dst, size); } ssize_t Handler_vfs::write(int fd, const void *src, size_t size) { if (fd < 0 || fd >= count_ds || descriptors[fd].handler == nullptr) { return OS_ERR_NOT_FOUND; } if (src == nullptr || size == 0) { return OS_ERR_INVALID_ARG; } char tmp_input[128]; size_t copy_size = (size > 127) ? 127 : size; memcpy(tmp_input, src, copy_size); tmp_input[copy_size] = '\0'; parse_args_c_style(tmp_input, descriptors[fd].args); return (ssize_t)size; } ssize_t Handler_vfs::write_vfs(void* ctx, int fd, const void *src, size_t size) { Handler_vfs* self = (Handler_vfs*)ctx; return self->write(fd, src, size); } int Handler_vfs::close(int fd) { if (fd < 0 || fd >= count_ds) return OS_ERR_INVALID_ARG; descriptors[fd].handler = nullptr; return 0; } int Handler_vfs::close_vfs(void* ctx, int fd) { Handler_vfs* self = (Handler_vfs*)ctx; return self->close(fd); } int Handler_vfs::rename(const char *src, const char *dst) { int fn_idx = -1; for (int i = 0; i < count_fn; i++) { if (strcmp(functions[i].name, src) == 0) { fn_idx = i; break; } } if (fn_idx == -1) return OS_ERR_NOT_FOUND; strncpy(functions[fn_idx].name, dst, 31); functions[fn_idx].name[31] = '\0'; return 0; } int Handler_vfs::rename_vfs(void* ctx, const char *src, const char *dst) { Handler_vfs* self = (Handler_vfs*)ctx; return self->rename(src, dst); } // --- РЕАЛИЗАЦИЯ РАБОТЫ С ДИРЕКТОРИЯМИ И STAT --- DIR* Handler_vfs::opendir(const char* name) { // Выделяем память для состояния директории descriptor_dir* dd = new descriptor_dir(); strncpy(dd->path, name, 127); dd->path[127] = '\0'; dd->current_index = 0; dd->handler = this; // Cast в DIR*, так как для VFS это просто непрозрачный указатель return (DIR*)dd; } DIR* Handler_vfs::opendir_vfs(void* ctx, const char* name) { Handler_vfs* self = (Handler_vfs*)ctx; return self->opendir(name); } struct dirent* Handler_vfs::readdir(DIR* pdir) { if (!pdir) return nullptr; descriptor_dir* dd = (descriptor_dir*)pdir; Handler_vfs* self = dd->handler; if (dd->current_index >= self->count_fn) { return nullptr; } static struct dirent entry; memset(&entry, 0, sizeof(entry)); const char* fn_name = self->functions[dd->current_index].name; if (fn_name[0] == '/') { fn_name++; } strncpy(entry.d_name, fn_name, sizeof(entry.d_name) - 1); entry.d_name[sizeof(entry.d_name) - 1] = '\0'; dd->current_index++; return &entry; } struct dirent* Handler_vfs::readdir_vfs(void* ctx, DIR* pdir) { Handler_vfs* self = (Handler_vfs*)ctx; return self->readdir(pdir); } int Handler_vfs::closedir(DIR* pdir) { if (!pdir) return -1; descriptor_dir* dd = (descriptor_dir*)pdir; delete dd; // Освобождаем память, выделенную в opendir return 0; } int Handler_vfs::closedir_vfs(void* ctx, DIR* pdir) { Handler_vfs* self = (Handler_vfs*)ctx; return self->closedir(pdir); } int Handler_vfs::stat(const char * path, struct stat * st) { if (!st) return -1; memset(st, 0, sizeof(struct stat)); // Ищем, является ли путь именем зарегистрированной функции (файлом) for (int i = 0; i < count_fn; i++) { if (strcmp(functions[i].name, path) == 0) { st->st_mode = S_IFREG | 0666; // Обычный файл st->st_size = sizeof(Result); return 0; } } // Проверяем, является ли путь самой директорией (точкой монтирования) if (strcmp(path, this->path) == 0 || strcmp(path, "/") == 0) { st->st_mode = S_IFDIR | 0777; // Директория return 0; } return -1; // Не найдено } int Handler_vfs::stat_vfs(void* ctx, const char * path, struct stat * st) { Handler_vfs* self = (Handler_vfs*)ctx; return self->stat(path, st); }