From 32a1425294ffaa22a94aa54c0c3d8ad19f203bde Mon Sep 17 00:00:00 2001 From: Enrico Fraccaroli Date: Fri, 17 Dec 2021 23:54:21 +0100 Subject: [PATCH] Improved ELF loading, and overall OS performances. --- mentos/src/elf/elf.c | 555 ++++++++++++++++++------------------------- mentos/src/fs/ext2.c | 19 +- 2 files changed, 247 insertions(+), 327 deletions(-) diff --git a/mentos/src/elf/elf.c b/mentos/src/elf/elf.c index b501b6d..a84cbfa 100644 --- a/mentos/src/elf/elf.c +++ b/mentos/src/elf/elf.c @@ -21,207 +21,213 @@ #include "fs/vfs.h" #include "assert.h" -/// @brief Reads the elf header from file. -/// @param file the file from which we extract the elf header. -/// @param header where we store the content we read. -/// @return true on success, false on failure. -static inline bool_t read_elf_header(vfs_file_t *file, elf_header_t *header) +// ============================================================================ +// GET ELF TABLES +// ============================================================================ + +/// @brief Returns the pointer to where the section headers reside. +/// @param header a pointer to the ELF header. +/// @return a pointer to the section headers table. +static inline elf_section_header_t *elf_get_section_header_table(elf_header_t *header) { - size_t expected = sizeof(elf_header_t); - ssize_t nread = vfs_read(file, header, 0, expected); - if (nread != expected) { - pr_err("Failed to read elf header (read: %ld, expected: %ld)\n", nread, expected); - return false; - } - return true; + return (elf_section_header_t *)((uintptr_t)header + header->shoff); } -/// @brief Reads the program header from file. -/// @param file The file from which we extract the program header. -/// @param header A pointer to the ELF header. -/// @param idx The index of the program header. -/// @param phdr Where we store the content we read. -/// @return The amount of bytes we read. -static inline ssize_t read_elf_program_header(vfs_file_t *file, const elf_header_t *header, unsigned idx, elf_program_header_t *phdr) +/// @brief Returns the pointer to where the program headers reside. +/// @param header a pointer to the ELF header. +/// @return a pointer to the program headers table. +static inline elf_program_header_t *elf_get_program_header_table(elf_header_t *header) { - return vfs_read(file, phdr, header->phoff + header->phentsize * idx, sizeof(elf_program_header_t)); + return (elf_program_header_t *)((uintptr_t)header + header->phoff); } -/// @brief Reads the section header from file. -/// @param file The file from which we extract the section header. -/// @param header A pointer to the ELF header. +// ============================================================================ +// GET ELF OBJECTS +// ============================================================================ + +/// @brief Returns a pointer to the desired section header. +/// @param header a pointer to the ELF header. /// @param idx The index of the section header. /// @param shdr Where we store the content we read. -/// @return The amount of bytes we read. -static inline ssize_t read_elf_section_header(vfs_file_t *file, const elf_header_t *header, unsigned idx, elf_section_header_t *shdr) +/// @return a pointer to the desired section header. +static inline elf_section_header_t *elf_get_section_header(elf_header_t *header, unsigned idx) { - return vfs_read(file, shdr, header->shoff + header->shentsize * idx, sizeof(elf_section_header_t)); + return &elf_get_section_header_table(header)[idx]; } -/// @brief Reads the symbol from file. -/// @param file The file from which we extract the symbol. -/// @param shdr A pointer to the ELF symbol table header. -/// @param idx The index of the symbol. -/// @param symbol Where we store the content we read. -/// @return The amount of bytes we read. -static inline ssize_t read_elf_symbol(vfs_file_t *file, const elf_section_header_t *shdr, unsigned idx, elf_symbol_t *symbol) -{ - // TODO: Here it should use `shdr->entsize`. - return vfs_read(file, symbol, shdr->offset + sizeof(elf_symbol_t) * idx, sizeof(elf_symbol_t)); -} - -/// @brief Reads the symbol from file. -/// @param file The file from which we extract the symbol. -/// @param shdr A pointer to the ELF symbol table header. -/// @param idx The index of the symbol. -/// @param symbol Where we store the content we read. -/// @return The amount of bytes we read. -static inline ssize_t read_elf_symbol_name(vfs_file_t *file, const elf_section_header_t *shdr, unsigned offset, char *name, size_t name_len) -{ - return vfs_read(file, name, shdr->offset + offset, name_len); -} - -/// @brief Reads all program headers from file. -/// @param file the file from which we extract the program header. +/// @brief Returns a pointer to the desired program header. /// @param header a pointer to the ELF header. -/// @return The program headers, free them when finished. -static inline elf_program_header_t *read_elf_program_headers(vfs_file_t *file, const elf_header_t *header) +/// @param idx the index of the program header. +/// @return a pointer to the desired section header. +static inline elf_program_header_t *elf_get_program_header(elf_header_t *header, unsigned idx) { - assert(sizeof(elf_program_header_t) == header->phentsize); - // Compute the size. - size_t size = header->phnum * header->phentsize; - // Allocate the memory for the headers. - elf_program_header_t *program_headers = (elf_program_header_t *)kmalloc(size); - if (program_headers == NULL) { - pr_err("Failed to allocate memory for program headers.\n"); - return NULL; - } - // Clean up the memory. - memset(program_headers, 0, size); - // Read the headers. - if (vfs_read(file, program_headers, header->phoff, size) != size) { - pr_err("Failed to read program headers.\n"); - kfree(program_headers); - return NULL; - } - return program_headers; + return &elf_get_program_header_table(header)[idx]; } -/// @brief Reads all section headers from file. -/// @param file the file from which we extract the section header. +// ============================================================================ +// GET STRING TABLES +// ============================================================================ + +/// @brief Returns a pointer to the section header string table. /// @param header a pointer to the ELF header. -/// @return The section headers, free them when finished. -static inline elf_section_header_t *read_elf_section_headers(vfs_file_t *file, const elf_header_t *header) +/// @return a pointer to the section header string table, or NULL on failure. +static inline const char *elf_get_section_header_string_table(elf_header_t *header) { - assert(sizeof(elf_section_header_t) == header->shentsize); - // Compute the size. - size_t size = header->shnum * header->shentsize; - // Allocate the memory for the headers. - elf_section_header_t *section_headers = (elf_section_header_t *)kmalloc(size); - if (section_headers == NULL) { - pr_err("Failed to allocate memory for section headers.\n"); + if (header->shstrndx == SHT_NULL) return NULL; - } - // Clean up the memory. - memset(section_headers, 0, size); - // Read the headers. - if (vfs_read(file, section_headers, header->shoff, size) != size) { - pr_err("Failed to read section headers.\n"); - kfree(section_headers); - return NULL; - } - return section_headers; + return (const char *)((uintptr_t)header + elf_get_section_header(header, header->shstrndx)->offset); } -static inline char *read_elf_strtable( - vfs_file_t *file, - const elf_header_t *header, - const elf_section_header_t *section_header) +/// @brief Returns a pointer to the section header string table. +/// @param header a pointer to the ELF header. +/// @return a pointer to the section header string table, or NULL on failure. +static inline const char *elf_get_symbol_string_table(elf_header_t *header, elf_section_header_t *section_header) { - // Check if the header points to a string table. - if (section_header->type != SHT_STRTAB) { - pr_err("The header is not a STRTAB but a `%s` instead.\n", elf_type_to_string(section_header->type)); + if (section_header->link == SHT_NULL) return NULL; - } - // Allocate the memory for the string table. - char *strtab = kmalloc(section_header->size); - // Initialize the memory. - memset(strtab, 0, section_header->size); - // Read the string table. - if (vfs_read(file, strtab, section_header->offset, section_header->size) != section_header->size) { - pr_err("Failed to read the string table at %d.\n", section_header->offset); - kfree(strtab); - return NULL; - } - return strtab; + return (const char *)((uintptr_t)header + elf_get_section_header(header, section_header->link)->offset); } -static inline elf_symbol_t *read_elf_symtable( - vfs_file_t *file, - const elf_header_t *header, - const elf_section_header_t *section_header) +// ============================================================================ +// GET ELF OBJECTS NAME +// ============================================================================ + +/// @brief Returns the name of the given entry in the section header string table. +/// @param header a pointer to the ELF header. +/// @param name_offset the offset where the desired name resides inside the table. +/// @return a pointer to the name, or NULL on failure. +static inline const char *elf_get_section_header_name(elf_header_t *header, elf_section_header_t *section_header) { - // Check if the header points to a string table. - if (section_header->type != SHT_SYMTAB) { - pr_err("The header is not a SYMTAB but a `%s` instead.\n", elf_type_to_string(section_header->type)); + const char *strtab = elf_get_section_header_string_table(header); + if (strtab == NULL) return NULL; - } - if (sizeof(elf_symbol_t) != section_header->entsize) { - pr_err("Entities inside the symbol table have wrong size, %ld instead of %ld.\n", - section_header->entsize, sizeof(elf_symbol_t)); - return NULL; - } - // Allocate the memory for the string table. - elf_symbol_t *symtab = kmalloc(section_header->size); - // Initialize the memory. - memset(symtab, 0, section_header->size); - // Read the string table. - if (vfs_read(file, symtab, section_header->offset, section_header->size) != section_header->size) { - pr_err("Failed to read the symbol table at %d.\n", section_header->offset); - kfree(symtab); - return NULL; - } - return symtab; + return strtab + section_header->name; } -static inline const elf_section_header_t *elf_find_section_header( - const elf_header_t *header, - const elf_section_header_t *section_headers, - const char *shstrtab, - const char *name) +/// @brief Returns a pointer to the section header string table. +/// @param header a pointer to the ELF header. +/// @return a pointer to the section header string table, or NULL on failure. +static inline const char *elf_get_symbol_name(elf_header_t *header, elf_section_header_t *section_header, elf_symbol_t *symbol) { - for (unsigned i = 0; i < header->shnum; ++i) - if (strcmp(shstrtab + section_headers[i].name, name) == 0) - return §ion_headers[i]; + const char *strtab = elf_get_symbol_string_table(header, section_header); + if (strtab == NULL) + return NULL; + return strtab + symbol->name; +} + +// ============================================================================ +// SEARCH FUNCTIONS +// ============================================================================ + +static inline elf_section_header_t *elf_find_section_header(elf_header_t *header, const char *name) +{ + for (unsigned i = 0; i < header->shnum; ++i) { + // Get the section header. + elf_section_header_t *section_header = elf_get_section_header(header, i); + // Get the section header name. + const char *section_header_name = elf_get_section_header_name(header, section_header); + if (section_header_name) { + // Check the section header name. + if (strcmp(section_header_name, name) == 0) { + return section_header; + } + } + } return NULL; } -static inline const elf_symbol_t *elf_find_symbol( - const elf_section_header_t *symbol_table_header, - const elf_symbol_t *symbol_table, - const char *symbol_table_strtab, - const char *name) +static inline elf_symbol_t *elf_find_symbol(elf_header_t *header, const char *name) { - // Compute the entries in the symbol table. - uint32_t symtab_entries = symbol_table_header->size / sizeof(elf_symbol_t); - // Search the symbol. - for (unsigned i = 0; i < symtab_entries; ++i) - if (strcmp(symbol_table_strtab + symbol_table[i].name, name) == 0) - return &symbol_table[i]; + for (unsigned i = 0; i < header->shnum; ++i) { + // Get the section header. + elf_section_header_t *section_header = elf_get_section_header(header, i); + // Check if it is valid, and it is a symbol table. + if (section_header && (section_header->type == SHT_SYMTAB)) { + // Count the number of entries. + unsigned symtab_entries = section_header->size / section_header->entsize; + // Get the addresss of the symbol table. + elf_symbol_t *symtab = (elf_symbol_t *)((uintptr_t)header + section_header->offset); + // Iterate the entries. + for (unsigned j = 0; j < symtab_entries; ++j) { + // Get the symbol. + elf_symbol_t *symbol = &symtab[j]; + // Get the name of the symbol. + const char *symbol_name = elf_get_symbol_name(header, section_header, symbol); + if (symbol_name) { + // Check the symbol name. + if (strcmp(symbol_name, name) == 0) { + return symbol; + } + } + } + } + } return NULL; } -static inline int elf_load_sigreturn( - const elf_section_header_t *symbol_table_header, - const elf_symbol_t *symbol_table, - const char *symbol_table_strtab, - task_struct *task) +// ============================================================================ +// DUMP FUNCTIONS +// ============================================================================ + +static inline void elf_dump_section_headers(elf_header_t *header) { - const elf_symbol_t *sigreturn = elf_find_symbol(symbol_table_header, symbol_table, symbol_table_strtab, "sigreturn"); + pr_debug("[Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n"); + for (unsigned idx = 0; idx < header->shnum; ++idx) { + // Get the section header. + elf_section_header_t *section_header = elf_get_section_header(header, idx); + // Get the section header name. + const char *section_header_name = elf_get_section_header_name(header, section_header); + // Dump the information. + pr_debug("[%2d] %-20s %-15s %08x %06x %06x %2u %3u %2u %3u %2u\n", + idx, section_header_name, elf_section_header_type_to_string(section_header->type), + section_header->addr, section_header->offset, section_header->size, + section_header->entsize, section_header->flags, section_header->link, + section_header->info, section_header->addralign); + } +} + +static inline void elf_dump_symbol_table(elf_header_t *header) +{ + for (unsigned i = 0; i < header->shnum; ++i) { + // Get the section header. + elf_section_header_t *section_header = elf_get_section_header(header, i); + if (section_header->type != SHT_SYMTAB) + continue; + // Count the number of entries. + uint32_t symtab_entries = section_header->size / section_header->entsize; + // Get the addresss of the symbol table. + elf_symbol_t *symtab = (elf_symbol_t *)((uintptr_t)header + section_header->offset); + // Dump the table. + for (int j = 0; j < symtab_entries; ++j) { + // Get the symbol. + elf_symbol_t *symbol = &symtab[j]; + // Get the name of the symbol. + const char *symbol_name = elf_get_symbol_name(header, section_header, symbol); + if (symbol_name == NULL) { + pr_err("Null symbol name.\n"); + return; + } + // Dump the symbol. + pr_debug("[%4d] %08x %5d %-7s %-6s %-8s %3d %s\n", j, symbol->value, symbol->size, + elf_symbol_type_to_string(ELF32_ST_TYPE(symbol->info)), + elf_symbol_bind_to_string(ELF32_ST_BIND(symbol->info)), + "-", symbol->ndx, symbol_name); + } + } +} + +// ============================================================================ +// EXEC-RELATED FUNCTIONS +// ============================================================================ + +static inline int elf_set_sigreturn(elf_header_t *header, task_struct *task) +{ + elf_symbol_t *sigreturn = elf_find_symbol(header, "sigreturn"); if (sigreturn == NULL) { pr_err("Failed to find `sigreturn`!\n"); return false; } + task->sigreturn_eip = sigreturn->value; return true; } @@ -230,78 +236,35 @@ static inline int elf_load_sigreturn( /// @param file The ELF file. /// @param header The header of the ELF file. /// @return The ELF entry. -static inline int elf_load_exec( - task_struct *task, - vfs_file_t *file, - const elf_header_t *header, - const elf_program_header_t *phdrs) +static inline int elf_load_exec(elf_header_t *header, task_struct *task) { -#if 0 pr_debug(" Type | Mem. Size | File Size | VADDR\n"); for (unsigned i = 0; i < header->phnum; ++i) { // Get the header. + elf_program_header_t *program_header = elf_get_program_header(header, i); + // Dump the information about the header. pr_debug(" %-9s | %9s | %9s | 0x%08x - 0x%08x\n", - elf_type_to_string(phdrs[i].type), - to_human_size(phdrs[i].memsz), - to_human_size(phdrs[i].filesz), - phdrs[i].vaddr, phdrs[i].vaddr + phdrs[i].memsz); - if (phdrs[i].type == PT_LOAD) { - uint32_t virt_addr = create_vm_area(task->mm, phdrs[i].vaddr, phdrs[i].memsz, MM_USER | MM_RW | MM_COW, GFP_KERNEL); - virt_map_page_t *vpage = virt_map_alloc(phdrs[i].memsz); - uint32_t dst_addr = virt_map_vaddress(task->mm, vpage, virt_addr, phdrs[i].memsz); + elf_type_to_string(program_header->type), + to_human_size(program_header->memsz), + to_human_size(program_header->filesz), + program_header->vaddr, + program_header->vaddr + program_header->memsz); + if (program_header->type == PT_LOAD) { + uint32_t virt_addr = create_vm_area(task->mm, program_header->vaddr, program_header->memsz, MM_USER | MM_RW | MM_COW, GFP_KERNEL); + virt_map_page_t *vpage = virt_map_alloc(program_header->memsz); + uint32_t dst_addr = virt_map_vaddress(task->mm, vpage, virt_addr, program_header->memsz); // Load the memory area. - vfs_read(file, (void *)dst_addr, phdrs[i].offset, phdrs[i].filesz); + memcpy((void *)dst_addr, (void *)((uintptr_t)header + program_header->offset), program_header->filesz); - if (phdrs[i].memsz > phdrs[i].filesz) { - uint32_t zmem_sz = phdrs[i].memsz - phdrs[i].filesz; - memset((void *)(dst_addr + phdrs[i].filesz), 0, zmem_sz); + if (program_header->memsz > program_header->filesz) { + uint32_t zmem_sz = program_header->memsz - program_header->filesz; + memset((void *)(dst_addr + program_header->filesz), 0, zmem_sz); } virt_unmap_pg(vpage); } } -#endif - return 0; -} - -static inline void dump_elf_section_headers( - vfs_file_t *file, - const elf_header_t *header, - const elf_section_header_t *shdrs, - const char *shstrtab) -{ - pr_debug("[Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n"); - for (int i = 0; i < header->shnum; ++i) { - pr_debug("[%2d] %-20s %-15s %08x %06x %06x %2u %3u %2u %3u %2u\n", - i, shstrtab + shdrs[i].name, elf_section_header_type_to_string(shdrs[i].type), - shdrs[i].addr, shdrs[i].offset, shdrs[i].size, - shdrs[i].entsize, shdrs[i].flags, shdrs[i].link, shdrs[i].info, shdrs[i].addralign); - } -} - -static inline void dump_elf_symbol_table( - vfs_file_t *file, - const elf_header_t *header, - const elf_section_header_t *symtab_header, - const char *symtab_strtab) -{ - // Count the number of entries. - uint32_t symtab_entries = symtab_header->size / sizeof(elf_symbol_t); - pr_debug("Symbol table '.symtab' contains %d entries (%d/%d):\n", symtab_entries, symtab_header->size, sizeof(elf_symbol_t)); - pr_debug("[ Nr ] Value Size Type Bind Vis Ndx Name\n"); - elf_symbol_t symbol; - for (int i = 0; i < symtab_entries; ++i) { - if (read_elf_symbol(file, symtab_header, i, &symbol) == -1) { - pr_err("Failed to read the elf symbol at index %d.\n", i); - continue; - } - pr_debug("[%4d] %08x %5d %-7s %-6s %-8s %3d %s\n", i, symbol.value, symbol.size, - elf_symbol_type_to_string(ELF32_ST_TYPE(symbol.info)), - elf_symbol_bind_to_string(ELF32_ST_BIND(symbol.info)), - "-", - symbol.ndx, - symtab_strtab + symbol.name); - } + return true; } int elf_load_file(task_struct *task, vfs_file_t *file, uint32_t *entry) @@ -309,121 +272,61 @@ int elf_load_file(task_struct *task, vfs_file_t *file, uint32_t *entry) // Open the file. if (file == NULL) return false; - - // Read the elf header. - elf_header_t header; - if (!read_elf_header(file, &header)) + // Get the size of the file. + stat_t stat_buf; + if (vfs_fstat(file, &stat_buf) < 0) { + pr_err("Failed to stat the file `%s`.\n", file->name); return false; - + } + // Allocate the memory for the file. + char *buffer = kmalloc(stat_buf.st_size); + if (buffer == NULL) { + pr_err("Failed to allocate %d bytes of memory for reading the file `%s`.\n", stat_buf.st_size, file->name); + return false; + } + // Clean the memory. + memset(buffer, 0, stat_buf.st_size); + // Read the file. + if (vfs_read(file, buffer, 0, stat_buf.st_size) != stat_buf.st_size) { + pr_err("Failed to read %d bytes from the file `%s`.\n", stat_buf.st_size, file->name); + goto return_error_free_buffer; + } + // The first thing inside the file is the ELF header. + elf_header_t *header = (elf_header_t *)buffer; // Print header info. - pr_debug("Version : 0x%x\n", header.version); - pr_debug("Entry : 0x%x\n", header.entry); - pr_debug("Headers offset : 0x%x\n", header.phoff); - pr_debug("Headers count : %d\n", header.phnum); - + pr_debug("Type : %s\n", elf_type_to_string(header->type)); + pr_debug("Version : 0x%x\n", header->version); + pr_debug("Entry : 0x%x\n", header->entry); + pr_debug("Headers offset : 0x%x\n", header->phoff); + pr_debug("Headers count : %d\n", header->phnum); // Check the elf header. - if (!elf_check_file_header(&header)) - return false; - + if (!elf_check_file_header(header)) { + pr_err("File %s is not a valid ELF file.\n", stat_buf.st_size, file->name); + goto return_error_free_buffer; + } // Check if the elf file is an executable. - if (header.type != ET_EXEC) { + if (header->type != ET_EXEC) { pr_err("Elf file is not an executable.\n"); - return false; + goto return_error_free_buffer; + } + // Set the sigreturn of the task. + if (!elf_set_sigreturn(header, task)) { + pr_err("Failed to set `sigreturn` for the executable.\n"); + goto return_error_free_buffer; + } + if (!elf_load_exec(header, task)) { + pr_err("Failed to load the executable.\n"); + goto return_error_free_buffer; } - // Load section headers. - elf_section_header_t *section_headers = read_elf_section_headers(file, &header); - if (section_headers == NULL) { - pr_err("Failed to load section headers.\n"); - return false; - } - - // Load program headers. - elf_program_header_t *program_headers = read_elf_program_headers(file, &header); - if (program_headers == NULL) { - pr_err("Failed to load program headers.\n"); - goto free_section_headers; - } - - // Get the header pointing to the section headers string table. - elf_section_header_t *shstrtab_hdr = §ion_headers[header.shstrndx]; - // Read the section headers string table. - char *shstrtab = read_elf_strtable(file, &header, shstrtab_hdr); - if (shstrtab == NULL) { - pr_err("Cannot retrieve the symbol table.\n"); - goto free_program_headers; - } - - // Find the symbol table header. - const elf_section_header_t *symtab_header = elf_find_section_header(&header, section_headers, shstrtab, ".symtab"); - if (symtab_header == NULL) { - pr_err("Cannot find symbol table.\n"); - goto free_string_table; - } - - // Find the string table header associated with the symbol table header. - const elf_section_header_t *symtab_strtab_header = §ion_headers[symtab_header->link]; - if (symtab_strtab_header == NULL) { - pr_err("Cannot find strtab of symbol table.\n"); - goto free_string_table; - } - - // Load the symbol table. - elf_symbol_t *symtab = read_elf_symtable(file, &header, symtab_header); - if (symtab == NULL) { - pr_err("Cannot load symbol table.\n"); - goto free_symbol_table_strtab; - } - - // Read the symbol table section header. - char *symtab_strtab = read_elf_strtable(file, &header, symtab_strtab_header); - if (symtab_strtab == NULL) { - pr_err("Cannot retrieve the symbol table.\n"); - goto free_symbol_table; - } - - if (elf_load_sigreturn(symtab_header, symtab, symtab_strtab, task) == -1) { - pr_err("Failed to load `sigreturn`.\n"); - goto free_symbol_table; - } - dump_elf_section_headers(file, &header, section_headers, shstrtab); - dump_elf_symbol_table(file, &header, symtab_header, symtab_strtab); - - -free_symbol_table: - kfree(symtab_strtab); -free_symbol_table_strtab: - kfree(symtab); -free_string_table: - kfree(shstrtab); -free_program_headers: - kfree(program_headers); -free_section_headers: - kfree(section_headers); - - while (true) {} -#if 0 - return false; - - while (true) {} - - //dump_elf_symbol_table(file, &header); - if (elf_load_exec(task, file, &header, phdrs) == -1) { - // Free up the memory. - kfree(shdrs); - kfree(phdrs); - return 0; - } // Set the entry. - (*entry) = header.entry; + (*entry) = header->entry; - // Free up the memory. - kfree(shdrs); - kfree(phdrs); - - while (true) {} -#endif - return 1; + kfree(buffer); + return true; +return_error_free_buffer: + kfree(buffer); + return false; } int elf_check_file_type(vfs_file_t *file, Elf_Type type) diff --git a/mentos/src/fs/ext2.c b/mentos/src/fs/ext2.c index 468580c..1abc409 100644 --- a/mentos/src/fs/ext2.c +++ b/mentos/src/fs/ext2.c @@ -1292,7 +1292,9 @@ static int ext2_find_entry(ext2_filesystem_t *fs, ino_t ino, const char *name, e } // Get the directory entry. entry = (ext2_dirent_t *)((uintptr_t)cache + dir_offset); - + if (!strcmp(entry->name, ".") && !strcmp(name, "/")) { + break; + } // Check if the entry has the same name. if ((entry->inode != 0) && (strlen(name) == entry->name_len)) if (!strncmp(entry->name, name, entry->name_len)) @@ -1322,6 +1324,7 @@ free_cache_return_error: /// @return 0 on success, -1 on failure. static int ext2_resolve_path(vfs_file_t *directory, char *path, ext2_dirent_t *direntry) { + pr_debug("ext2_resolve_path(%s, %s, %p)\n", directory->name, path, direntry); // Check the pointers. if (directory == NULL) { pr_err("You provided a NULL directory.\n"); @@ -1341,6 +1344,10 @@ static int ext2_resolve_path(vfs_file_t *directory, char *path, ext2_dirent_t *d pr_err("The file does not belong to an EXT2 filesystem `%s`.\n", directory->name); return -1; } + if (strcmp(path, "/") == 0) { + ext2_find_entry(fs, directory->ino, path, direntry); + return 0; + } ino_t ino = directory->ino; char *token = strtok(path, "/"); while (token) { @@ -1535,6 +1542,16 @@ static vfs_file_t *ext2_open(const char *path, int flags, mode_t mode) /// @param file The file structure. static int ext2_close(vfs_file_t *file) { + // Get the filesystem. + ext2_filesystem_t *fs = (ext2_filesystem_t *)file->device; + if (fs == NULL) { + pr_err("The file does not belong to an EXT2 filesystem `%s`.\n", file->name); + return -1; + } + // We cannot close the root. + if (file == fs->root) { + return -1; + } pr_debug("ext2_close(%p) : Closing file `%s`\n", file, file->name); // Remove the file from the list of opened files. list_head_del(&file->siblings);