Merge branch 'release/v0.5.0'

This commit is contained in:
Enrico Fraccaroli
2022-12-04 11:56:39 -05:00
17 changed files with 349 additions and 243 deletions
+2
View File
@@ -143,6 +143,7 @@ set(EMULATOR_FLAGS ${EMULATOR_FLAGS} -drive file=${CMAKE_BINARY_DIR}/rootfs.img,
# This first target runs the emualtor passing the kernel binary file.
add_custom_target(
qemu
COMMAND test -e ${CMAKE_BINARY_DIR}/rootfs.img || ${CMAKE_COMMAND} -E cmake_echo_color --red "No filesystem file detected, you need to run: make filesystem"
COMMAND ${EMULATOR} ${EMULATOR_FLAGS} -kernel ${CMAKE_BINARY_DIR}/mentos/kernel-bootloader.bin
DEPENDS kernel-bootloader.bin
)
@@ -174,6 +175,7 @@ add_custom_target(
# debug mode, and pause it up until a debugger connects to it.
add_custom_target(
qemu-gdb
COMMAND test -e ${CMAKE_BINARY_DIR}/rootfs.img || ${CMAKE_COMMAND} -E cmake_echo_color --red "No filesystem file detected, you need to run: make filesystem"
COMMAND echo "\n\n"
COMMAND echo "Now, QEMU has loaded the kernel, and it is waiting that you\n"
COMMAND echo "remotely connect to it. To start debugging, open a new shell\n"
View File
View File
+14
View File
@@ -0,0 +1,14 @@
NAME
ls - list directory contents
SYNOPSIS
ls [OPTIONS] [FILE/FOLDER]
DESCRIPTION
List information about the given file, or the files contained in the given
folder. If not argument is provided it will list information about files
inside the current folder.
OPTIONS
-a : list all entries.
-l : show the entries as a detailed list.
-5
View File
@@ -35,8 +35,3 @@ int __libc_start_main(int (*main)(int, char **, char **), int argc, char *argv[]
//dbg_print("== END %-30s =======================================\n", argv[0]);
return result;
}
// WARNING: This declaration must be here, because libc_start is compiled
// with all the programs, and all the programs NEED to have the `sigreturn`
// symbol. It must be this way, period.
_syscall0(int, sigreturn)
+1
View File
@@ -162,6 +162,7 @@ int getpwnam_r(const char *name, passwd_t *pwd, char *buf, size_t buflen, passwd
// Return success.
return 1;
}
errno = ENOENT;
// Close the file.
close(fd);
// Return fail.
+16 -4
View File
@@ -10,6 +10,10 @@
#include "signal.h"
#include "sys/bitops.h"
_syscall0(int, sigreturn)
_syscall3(int, sigprocmask, int, how, const sigset_t *, set, sigset_t *, oldset)
static const char *sys_siglist[] = {
"HUP",
"INT",
@@ -45,11 +49,19 @@ static const char *sys_siglist[] = {
NULL,
};
_syscall2(sighandler_t, signal, int, signum, sighandler_t, handler)
sighandler_t signal(int signum, sighandler_t handler)
{
long __res;
__inline_syscall3(__res, signal, signum, handler, (unsigned int)sigreturn);
__syscall_return(sighandler_t, __res);
}
_syscall3(int, sigaction, int, signum, const sigaction_t *, act, sigaction_t *, oldact)
_syscall3(int, sigprocmask, int, how, const sigset_t *, set, sigset_t *, oldset)
int sigaction(int signum, const sigaction_t *act, sigaction_t *oldact)
{
long __res;
__inline_syscall4(__res, sigaction, signum, act, oldact, (unsigned int)sigreturn);
__syscall_return(int, __res);
}
const char *strsignal(int sig)
{
+2 -3
View File
@@ -119,9 +119,8 @@ typedef struct task_struct {
/// The current working directory.
char cwd[PATH_MAX];
// struct signal_struct *signal;
/// Instruction Pointer of the LIBC Signal Handler.
uint32_t sigreturn_eip;
/// Address of the LIBC sigreturn function.
uint32_t sigreturn_addr;
/// Pointer to the processs signal handler descriptor
sighand_t sighand;
/// Mask of blocked signals.
+2 -2
View File
@@ -269,14 +269,14 @@ int sys_kill(pid_t pid, int sig);
/// @param signum The signal number.
/// @param handler The handler for the signal.
/// @return The previous value of the signal handler, or SIG_ERR on error.
sighandler_t sys_signal(int signum, sighandler_t handler);
sighandler_t sys_signal(int signum, sighandler_t handler, uint32_t sigreturn_addr);
/// @brief Examine and change a signal action.
/// @param signum Specifies the signal and can be any valid signal except SIGKILL and SIGSTOP.
/// @param act If non-NULL, the new action for signal signum is installed from act.
/// @param oldact If non-NULL, the previous action is saved in oldact.
/// @return returns 0 on success; on error, -1 is returned, and errno is set to indicate the error.
int sys_sigaction(int signum, const sigaction_t *act, sigaction_t *oldact);
int sys_sigaction(int signum, const sigaction_t *act, sigaction_t *oldact, uint32_t sigreturn_addr);
/// @brief Examine and change blocked signals.
/// @param how Determines the behavior of the call.
-16
View File
@@ -222,17 +222,6 @@ static inline void elf_dump_symbol_table(elf_header_t *header)
// 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;
}
/// @brief Loads an ELF executable.
/// @param task The task for which we load the ELF.
/// @param file The ELF file.
@@ -311,11 +300,6 @@ int elf_load_file(task_struct *task, vfs_file_t *file, uint32_t *entry)
pr_err("Elf file is not an executable.\n");
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;
+103 -70
View File
@@ -386,7 +386,6 @@ static int ext2_mkdir(const char *path, mode_t mode);
static int ext2_rmdir(const char *path);
static int ext2_stat(const char *path, stat_t *stat);
static vfs_file_t *ext2_creat(const char *path, mode_t permission);
static vfs_file_t *ext2_mount(vfs_file_t *block_device, const char *path);
// ============================================================================
@@ -430,6 +429,28 @@ static const char *uuid_to_string(uint8_t uuid[16])
return s;
}
/// @brief Turns an ext2_file_type to string.
/// @param ext2_type the ext2_file_type to turn to string.
/// @return the string representing the ext2_file_type.
static const char *ext2_file_type_to_string(ext2_file_type_t ext2_type)
{
if (ext2_type == ext2_file_type_regular_file)
return "REG";
if (ext2_type == ext2_file_type_directory)
return "DIR";
if (ext2_type == ext2_file_type_character_device)
return "CHR";
if (ext2_type == ext2_file_type_block_device)
return "BLK";
if (ext2_type == ext2_file_type_named_pipe)
return "FIFO";
if (ext2_type == ext2_file_type_socket)
return "SOCK";
if (ext2_type == ext2_file_type_symbolic_link)
return "LNK";
return "UNK";
}
static int ext2_file_type_to_vfs_file_type(int ext2_type)
{
if (ext2_type == ext2_file_type_regular_file)
@@ -502,63 +523,63 @@ static bool_t ext2_valid_permissions(int flags, mode_t mask, uid_t uid, gid_t gi
/// @param sb the object to dump.
static void ext2_dump_superblock(ext2_superblock_t *sb)
{
pr_debug("inodes_count : %d\n", sb->inodes_count);
pr_debug("blocks_count : %d\n", sb->blocks_count);
pr_debug("r_blocks_count : %d\n", sb->r_blocks_count);
pr_debug("free_blocks_count : %d\n", sb->free_blocks_count);
pr_debug("free_inodes_count : %d\n", sb->free_inodes_count);
pr_debug("first_data_block : %d\n", sb->first_data_block);
pr_debug("log_block_size : %d\n", sb->log_block_size);
pr_debug("log_frag_size : %d\n", sb->log_frag_size);
pr_debug("blocks_per_group : %d\n", sb->blocks_per_group);
pr_debug("frags_per_group : %d\n", sb->frags_per_group);
pr_debug("inodes_per_group : %d\n", sb->inodes_per_group);
pr_debug("inodes_count : %u\n", sb->inodes_count);
pr_debug("blocks_count : %u\n", sb->blocks_count);
pr_debug("r_blocks_count : %u\n", sb->r_blocks_count);
pr_debug("free_blocks_count : %u\n", sb->free_blocks_count);
pr_debug("free_inodes_count : %u\n", sb->free_inodes_count);
pr_debug("first_data_block : %u\n", sb->first_data_block);
pr_debug("log_block_size : %u\n", sb->log_block_size);
pr_debug("log_frag_size : %u\n", sb->log_frag_size);
pr_debug("blocks_per_group : %u\n", sb->blocks_per_group);
pr_debug("frags_per_group : %u\n", sb->frags_per_group);
pr_debug("inodes_per_group : %u\n", sb->inodes_per_group);
pr_debug("mtime : %s\n", time_to_string(sb->mtime));
pr_debug("wtime : %s\n", time_to_string(sb->wtime));
pr_debug("mnt_count : %d\n", sb->mnt_count);
pr_debug("max_mnt_count : %d\n", sb->max_mnt_count);
pr_debug("magic : 0x%0x\n", sb->magic);
pr_debug("magic : 0x%0x (== 0x%0x)\n", sb->magic, EXT2_SUPERBLOCK_MAGIC);
pr_debug("state : %d\n", sb->state);
pr_debug("errors : %d\n", sb->errors);
pr_debug("minor_rev_level : %d\n", sb->minor_rev_level);
pr_debug("lastcheck : %s\n", time_to_string(sb->lastcheck));
pr_debug("checkinterval : %d\n", sb->checkinterval);
pr_debug("creator_os : %d\n", sb->creator_os);
pr_debug("rev_level : %d\n", sb->rev_level);
pr_debug("def_resuid : %d\n", sb->def_resuid);
pr_debug("def_resgid : %d\n", sb->def_resgid);
pr_debug("first_ino : %d\n", sb->first_ino);
pr_debug("inode_size : %d\n", sb->inode_size);
pr_debug("block_group_nr : %d\n", sb->block_group_nr);
pr_debug("feature_compat : %d\n", sb->feature_compat);
pr_debug("feature_incompat : %d\n", sb->feature_incompat);
pr_debug("feature_ro_compat : %d\n", sb->feature_ro_compat);
pr_debug("checkinterval : %u\n", sb->checkinterval);
pr_debug("creator_os : %u\n", sb->creator_os);
pr_debug("rev_level : %u\n", sb->rev_level);
pr_debug("def_resuid : %u\n", sb->def_resuid);
pr_debug("def_resgid : %u\n", sb->def_resgid);
pr_debug("first_ino : %u\n", sb->first_ino);
pr_debug("inode_size : %u\n", sb->inode_size);
pr_debug("block_group_nr : %u\n", sb->block_group_nr);
pr_debug("feature_compat : %u\n", sb->feature_compat);
pr_debug("feature_incompat : %u\n", sb->feature_incompat);
pr_debug("feature_ro_compat : %u\n", sb->feature_ro_compat);
pr_debug("uuid : %s\n", uuid_to_string(sb->uuid));
pr_debug("volume_name : %s\n", (char *)sb->volume_name);
pr_debug("last_mounted : %s\n", (char *)sb->last_mounted);
pr_debug("algo_bitmap : %d\n", sb->algo_bitmap);
pr_debug("prealloc_blocks : %d\n", sb->prealloc_blocks);
pr_debug("prealloc_dir_blocks : %d\n", sb->prealloc_dir_blocks);
pr_debug("algo_bitmap : %u\n", sb->algo_bitmap);
pr_debug("prealloc_blocks : %u\n", sb->prealloc_blocks);
pr_debug("prealloc_dir_blocks : %u\n", sb->prealloc_dir_blocks);
pr_debug("journal_uuid : %s\n", uuid_to_string(sb->journal_uuid));
pr_debug("journal_inum : %d\n", sb->journal_inum);
pr_debug("jounral_dev : %d\n", sb->jounral_dev);
pr_debug("last_orphan : %d\n", sb->last_orphan);
pr_debug("journal_inum : %u\n", sb->journal_inum);
pr_debug("jounral_dev : %u\n", sb->jounral_dev);
pr_debug("last_orphan : %u\n", sb->last_orphan);
pr_debug("hash_seed : %u %u %u %u\n", sb->hash_seed[0], sb->hash_seed[1], sb->hash_seed[2], sb->hash_seed[3]);
pr_debug("def_hash_version : %d\n", sb->def_hash_version);
pr_debug("default_mount_options : %d\n", sb->default_mount_options);
pr_debug("first_meta_bg : %d\n", sb->first_meta_block_group_id);
pr_debug("def_hash_version : %u\n", sb->def_hash_version);
pr_debug("default_mount_options : %u\n", sb->default_mount_options);
pr_debug("first_meta_bg : %u\n", sb->first_meta_block_group_id);
}
/// @brief Dumps on debugging output the group descriptor.
/// @param gd the object to dump.
static void ext2_dump_group_descriptor(ext2_group_descriptor_t *gd)
{
pr_debug("block_bitmap : %d\n", gd->block_bitmap);
pr_debug("inode_bitmap : %d\n", gd->inode_bitmap);
pr_debug("inode_table : %d\n", gd->inode_table);
pr_debug("free_blocks_count : %d\n", gd->free_blocks_count);
pr_debug("free_inodes_count : %d\n", gd->free_inodes_count);
pr_debug("used_dirs_count : %d\n", gd->used_dirs_count);
pr_debug("block_bitmap : %u\n", gd->block_bitmap);
pr_debug("inode_bitmap : %u\n", gd->inode_bitmap);
pr_debug("inode_table : %u\n", gd->inode_table);
pr_debug("free_blocks_count : %u\n", gd->free_blocks_count);
pr_debug("free_inodes_count : %u\n", gd->free_inodes_count);
pr_debug("used_dirs_count : %u\n", gd->used_dirs_count);
}
/// @brief Dumps on debugging output the inode.
@@ -601,6 +622,13 @@ static void ext2_dump_inode(ext2_inode_t *inode)
inode->generation, inode->file_acl, inode->dir_acl);
}
/// @brief Dumps on debugging output the dirent.
/// @param dirent the object to dump.
static void ext2_dump_dirent(ext2_dirent_t *dirent)
{
pr_debug("Inode: %4u Rec. Len.: %4u Name Len.: %4u Type:%4s Name: %s\n", dirent->inode, dirent->rec_len, dirent->name_len, ext2_file_type_to_string(dirent->file_type), dirent->name);
}
/// @brief Dumps on debugging output the BGDT.
/// @param fs the filesystem of which we print the BGDT.
static void ext2_dump_bgdt(ext2_filesystem_t *fs)
@@ -612,21 +640,21 @@ static void ext2_dump_bgdt(ext2_filesystem_t *fs)
for (uint32_t i = 0; i < fs->block_groups_count; ++i) {
// Get the pointer to the current group descriptor.
ext2_group_descriptor_t *gd = &(fs->block_groups[i]);
pr_debug("Block Group Descriptor [%d] @ %d:\n", i, fs->bgdt_start_block + i * fs->superblock.blocks_per_group);
pr_debug(" block_bitmap : %d\n", gd->block_bitmap);
pr_debug(" inode_bitmap : %d\n", gd->inode_bitmap);
pr_debug(" inode_table : %d\n", gd->inode_table);
pr_debug(" Used Dirs : %d\n", gd->used_dirs_count);
pr_debug(" Free Blocks : %4d of %d\n", gd->free_blocks_count, fs->superblock.blocks_per_group);
pr_debug(" Free Inodes : %4d of %d\n", gd->free_inodes_count, fs->superblock.inodes_per_group);
pr_debug("Block Group Descriptor [%u] @ %u:\n", i, fs->bgdt_start_block + i * fs->superblock.blocks_per_group);
pr_debug(" block_bitmap : %u\n", gd->block_bitmap);
pr_debug(" inode_bitmap : %u\n", gd->inode_bitmap);
pr_debug(" inode_table : %u\n", gd->inode_table);
pr_debug(" Used Dirs : %u\n", gd->used_dirs_count);
pr_debug(" Free Blocks : %4u of %u\n", gd->free_blocks_count, fs->superblock.blocks_per_group);
pr_debug(" Free Inodes : %4u of %u\n", gd->free_inodes_count, fs->superblock.inodes_per_group);
// Dump the block bitmap.
ext2_read_block(fs, gd->block_bitmap, cache);
pr_debug(" Block Bitmap at %d\n", gd->block_bitmap);
pr_debug(" Block Bitmap at %u\n", gd->block_bitmap);
for (uint32_t j = 0; j < fs->block_size; ++j) {
if ((j % 8) == 0)
pr_debug(" Block index: %4d, Bitmap: %s\n", j / 8, dec_to_binary(cache[j / 8], 8));
pr_debug(" Block index: %4u, Bitmap: %s\n", j / 8, dec_to_binary(cache[j / 8], 8));
if (!ext2_check_bitmap_bit(cache, j)) {
pr_debug(" First free block in group is in block %d, the linear index is %d\n", j / 8, j);
pr_debug(" First free block in group is in block %u, the linear index is %u\n", j / 8, j);
break;
}
}
@@ -674,6 +702,7 @@ static void ext2_dump_filesystem(ext2_filesystem_t *fs)
/// @details Remember that inode addressing starts from 1.
static uint32_t ext2_get_group_index_from_inode(ext2_filesystem_t *fs, uint32_t inode_index)
{
assert(inode_index != 0 && "Your are trying to access inode 0.");
return (inode_index - 1) / fs->superblock.inodes_per_group;
}
@@ -684,6 +713,7 @@ static uint32_t ext2_get_group_index_from_inode(ext2_filesystem_t *fs, uint32_t
/// @details Remember that inode addressing starts from 1.
static uint32_t ext2_get_inode_offest_in_group(ext2_filesystem_t *fs, uint32_t inode_index)
{
assert(inode_index != 0 && "Your are trying to access inode 0.");
return (inode_index - 1) % fs->superblock.inodes_per_group;
}
@@ -852,7 +882,6 @@ static int ext2_write_superblock(ext2_filesystem_t *fs)
/// @return the amount of data we read, or negative value for an error.
static int ext2_read_block(ext2_filesystem_t *fs, uint32_t block_index, uint8_t *buffer)
{
//pr_debug("Read block %4d for EXT2 filesystem (0x%x)\n", block_index, fs);
if (block_index == 0) {
pr_err("You are trying to read an invalid block index (%d).\n", block_index);
return -1;
@@ -871,7 +900,6 @@ static int ext2_read_block(ext2_filesystem_t *fs, uint32_t block_index, uint8_t
/// @return the amount of data we wrote, or negative value for an error.
static int ext2_write_block(ext2_filesystem_t *fs, uint32_t block_index, uint8_t *buffer)
{
//pr_debug("Write block %4d for EXT2 filesystem (0x%x)\n", block_index, fs);
if (block_index == 0) {
pr_err("You are trying to write on an invalid block index (%d).\n", block_index);
return -1;
@@ -920,30 +948,33 @@ static int ext2_write_bgdt(ext2_filesystem_t *fs)
/// @return 0 on success, -1 on failure.
static int ext2_read_inode(ext2_filesystem_t *fs, ext2_inode_t *inode, uint32_t inode_index)
{
uint32_t group_index, block_index, inode_offset;
if (inode_index == 0) {
pr_err("You are trying to read an invalid inode index (%d).\n", inode_index);
return -1;
}
// Retrieve the group index.
uint32_t group_index = ext2_get_group_index_from_inode(fs, inode_index);
group_index = ext2_get_group_index_from_inode(fs, inode_index);
if (group_index > fs->block_groups_count) {
pr_err("Invalid group index computed from inode index `%d`.\n", inode_index);
return -1;
}
// Get the index of the inode inside the group.
uint32_t offset = ext2_get_inode_offest_in_group(fs, inode_index);
inode_offset = ext2_get_inode_offest_in_group(fs, inode_index);
// Get the block offest.
uint32_t block = ext2_get_block_index_from_inode_offset(fs, offset);
block_index = ext2_get_block_index_from_inode_offset(fs, inode_offset);
// Get the real inode offset inside the block.
offset %= fs->inodes_per_block_count;
inode_offset %= fs->inodes_per_block_count;
// Log the address to the inode.
pr_debug("Read inode (inode:%4u block:%4u offset:%4u)\n", inode_index, block_index, inode_offset);
// Allocate the cache.
uint8_t *cache = kmem_cache_alloc(fs->ext2_buffer_cache, GFP_KERNEL);
// Clean the cache.
memset(cache, 0, fs->block_size);
// Read the block containing the inode table.
ext2_read_block(fs, fs->block_groups[group_index].inode_table + block, cache);
ext2_read_block(fs, fs->block_groups[group_index].inode_table + block_index, cache);
// Save the inode content.
memcpy(inode, (ext2_inode_t *)((uintptr_t)cache + (offset * fs->superblock.inode_size)), fs->superblock.inode_size);
memcpy(inode, (ext2_inode_t *)((uintptr_t)cache + (inode_offset * fs->superblock.inode_size)), sizeof(ext2_inode_t));
// Free the cache.
kmem_cache_free(cache);
return 0;
@@ -956,32 +987,35 @@ static int ext2_read_inode(ext2_filesystem_t *fs, ext2_inode_t *inode, uint32_t
/// @return 0 on success, -1 on failure.
static int ext2_write_inode(ext2_filesystem_t *fs, ext2_inode_t *inode, uint32_t inode_index)
{
uint32_t group_index, block_index, inode_offset;
if (inode_index == 0) {
pr_err("You are trying to read an invalid inode index (%d).\n", inode_index);
return -1;
}
// Retrieve the group index.
uint32_t group_index = ext2_get_group_index_from_inode(fs, inode_index);
group_index = ext2_get_group_index_from_inode(fs, inode_index);
if (group_index > fs->block_groups_count) {
pr_err("Invalid group index computed from inode index `%d`.\n", inode_index);
return -1;
}
// Get the offset of the inode inside the group.
uint32_t offset = ext2_get_inode_offest_in_group(fs, inode_index);
inode_offset = ext2_get_inode_offest_in_group(fs, inode_index);
// Get the block offest.
uint32_t block = ext2_get_block_index_from_inode_offset(fs, offset);
block_index = ext2_get_block_index_from_inode_offset(fs, inode_offset);
// Get the real inode offset inside the block.
offset %= fs->inodes_per_block_count;
inode_offset %= fs->inodes_per_block_count;
// Log the address to the inode.
pr_debug("Write inode (inode:%4u block:%4u offset:%4u)\n", inode_index, block_index, inode_offset);
// Allocate the cache.
uint8_t *cache = kmem_cache_alloc(fs->ext2_buffer_cache, GFP_KERNEL);
// Clean the cache.
memset(cache, 0, fs->block_size);
// Read the block containing the inode table.
ext2_read_block(fs, fs->block_groups[group_index].inode_table + block, cache);
ext2_read_block(fs, fs->block_groups[group_index].inode_table + block_index, cache);
// Write the inode.
memcpy((ext2_inode_t *)((uintptr_t)cache + (offset * fs->superblock.inode_size)), inode, fs->superblock.inode_size);
memcpy((ext2_inode_t *)((uintptr_t)cache + (inode_offset * fs->superblock.inode_size)), inode, sizeof(ext2_inode_t));
// Write back the block.
ext2_write_block(fs, fs->block_groups[group_index].inode_table + block, cache);
ext2_write_block(fs, fs->block_groups[group_index].inode_table + block_index, cache);
// Free the cache.
kmem_cache_free(cache);
return 0;
@@ -1380,6 +1414,8 @@ static ssize_t ext2_read_inode_block(ext2_filesystem_t *fs, ext2_inode_t *inode,
uint32_t real_index = ext2_get_real_block_index(fs, inode, block_index);
if (real_index == 0)
return -1;
// Log the address to the inode block.
pr_debug("Read inode block (block:%4u real:%4u)\n", block_index, real_index);
// Read the block.
return ext2_read_block(fs, real_index, buffer);
}
@@ -1401,6 +1437,8 @@ static ssize_t ext2_write_inode_block(ext2_filesystem_t *fs, ext2_inode_t *inode
uint32_t real_index = ext2_get_real_block_index(fs, inode, block_index);
if (real_index == 0)
return -1;
// Log the address to the inode block.
pr_debug("Write inode block (block:%4u real:%4u inode:%4u)\n", block_index, real_index, inode_index);
// Write the block.
return ext2_write_block(fs, real_index, buffer);
}
@@ -1919,7 +1957,6 @@ static int ext2_resolve_path(vfs_file_t *directory, char *path, ext2_direntry_se
pr_err("You provided a NULL direntry.\n");
return -1;
}
pr_debug("ext2_resolve_path(directory: \"%s\", path: \"%s\")\n", directory->name, path);
// Get the filesystem.
ext2_filesystem_t *fs = (ext2_filesystem_t *)directory->device;
if (fs == NULL) {
@@ -1943,8 +1980,6 @@ static int ext2_resolve_path(vfs_file_t *directory, char *path, ext2_direntry_se
token = strtok(NULL, "/");
}
kfree(tmp_path);
pr_debug("ext2_resolve_path(directory: \"%s\", path: \"%s\") -> (ino: %d, name: \"%s\")\n",
directory->name, path, search->direntry->inode, search->direntry->name);
return 0;
}
@@ -1955,7 +1990,6 @@ static int ext2_resolve_path(vfs_file_t *directory, char *path, ext2_direntry_se
/// @return 0 on success, -1 on failure.
static int ext2_resolve_path_direntry(vfs_file_t *directory, char *path, ext2_dirent_t *direntry)
{
pr_debug("ext2_resolve_path_direntry(%s, %s, %p)\n", directory->name, path, direntry);
// Check the pointers.
if (directory == NULL) {
pr_err("You provided a NULL directory.\n");
@@ -1985,7 +2019,6 @@ static int ext2_resolve_path_direntry(vfs_file_t *directory, char *path, ext2_di
/// @return a pointer to the EXT2 filesystem, NULL otherwise.
static ext2_filesystem_t *get_ext2_filesystem(const char *absolute_path)
{
pr_debug("get_ext2_filesystem(%s)\n", absolute_path);
if (absolute_path == NULL) {
pr_err("We received a NULL absolute path.\n");
return NULL;
@@ -2924,7 +2957,7 @@ static vfs_file_t *ext2_mount(vfs_file_t *block_device, const char *path)
NULL,
NULL);
// Compute the maximum number of inodes per block.
fs->inodes_per_block_count = fs->block_size / sizeof(ext2_inode_t);
fs->inodes_per_block_count = fs->block_size / fs->superblock.inode_size;
// Compute the number of blocks per block. This value is mostly used for
// inodes.
// If you check inside the inode structure you will find the `blocks_count`
-2
View File
@@ -374,8 +374,6 @@ int kmain(boot_info_t *boot_informations)
// We have completed the booting procedure.
pr_notice("Booting done, jumping into init process.\n");
// Print the welcome message.
printf("\n .: Welcome to MentOS :.\n\n");
// Switch to the page directory of init.
paging_switch_directory_va(init_p->mm->pgd);
// Jump into init process.
+9 -5
View File
@@ -300,7 +300,7 @@ static inline int __handle_signal(int signr, siginfo_t *info, sigaction_t *ka, s
PUSH_VALUE_ON_STACK(regs->useresp, signr);
// Push on the stack the function required to handle the signal return.
PUSH_VALUE_ON_STACK(regs->useresp, current->sigreturn_eip);
PUSH_VALUE_ON_STACK(regs->useresp, current->sigreturn_addr);
return 1;
}
@@ -631,9 +631,9 @@ int sys_kill(pid_t pid, int sig)
return __send_sig_info(sig, &info, current);
}
sighandler_t sys_signal(int signum, sighandler_t handler)
sighandler_t sys_signal(int signum, sighandler_t handler, uint32_t sigreturn_addr)
{
pr_debug("sys_signal(%d, %p)\n", signum, handler);
pr_debug("sys_signal(%d, %p, %p)\n", signum, handler, sigreturn_ptr);
// Check the signal that we want to send.
if ((signum < 0) || (signum >= NSIG)) {
pr_err("sys_signal(%d, %p): Wrong signal number!\n", signum, handler);
@@ -658,6 +658,8 @@ sighandler_t sys_signal(int signum, sighandler_t handler)
sigemptyset(&new_sigaction.sa_mask);
// Lock the signal handling for the given task.
__lock_task_sighand(current);
// Set the address of the sigreturn.
current->sigreturn_addr = sigreturn_addr;
// Get the old sigaction.
sigaction_t *old_sigaction = &current->sighand.action[signum - 1];
pr_err("sys_signal(%d, %p): Signal action ptr %p\n", signum, handler, old_sigaction);
@@ -672,9 +674,9 @@ sighandler_t sys_signal(int signum, sighandler_t handler)
return old_handler;
}
int sys_sigaction(int signum, const sigaction_t *act, sigaction_t *oldact)
int sys_sigaction(int signum, const sigaction_t *act, sigaction_t *oldact, uint32_t sigreturn_addr)
{
pr_debug("sys_sigaction(%d, %p, %p)\n", signum, act, oldact);
pr_debug("sys_sigaction(%d, %p, %p, %p)\n", signum, act, oldact, sigreturn_ptr);
// Check the signal that we want to send.
if ((signum < 0) || (signum >= NSIG)) {
pr_err("sys_sigaction(%d, %p, %p): Wrong signal number!\n", signum, act, oldact);
@@ -691,6 +693,8 @@ int sys_sigaction(int signum, const sigaction_t *act, sigaction_t *oldact)
}
// Lock the signal handling for the given task.
__lock_task_sighand(current);
// Set the address of the sigreturn.
current->sigreturn_addr = sigreturn_addr;
// Get a pointer to the entry in the sighand.action array.
sigaction_t *current_sigaction = &current->sighand.action[signum - 1];
pr_debug("sys_sigaction(%d, %p, %p): : Signal old action ptr %p\n", signum, act, oldact, current_sigaction);
+61
View File
@@ -0,0 +1,61 @@
/// @file ansi_colors.h
/// @author Enrico Fraccaroli (enry.frak@gmail.com)
/// @brief Macros for ANSI colors.
#pragma once
#define FG_RESET "\033[0m" ///< ANSI code for resetting.
#define FG_BLACK "\033[30m" ///< ANSI code for setting a BLACK foreground.
#define FG_RED "\033[31m" ///< ANSI code for setting a RED foreground.
#define FG_GREEN "\033[32m" ///< ANSI code for setting a GREEN foreground.
#define FG_YELLOW "\033[33m" ///< ANSI code for setting a YELLOW foreground.
#define FG_BLUE "\033[34m" ///< ANSI code for setting a BLUE foreground.
#define FG_MAGENTA "\033[35m" ///< ANSI code for setting a MAGENTA foreground.
#define FG_CYAN "\033[36m" ///< ANSI code for setting a CYAN foreground.
#define FG_WHITE "\033[37m" ///< ANSI code for setting a WHITE foreground.
#define FG_BLACK_BOLD "\033[1;30m" ///< ANSI code for setting a BLACK foreground.
#define FG_RED_BOLD "\033[1;31m" ///< ANSI code for setting a RED foreground.
#define FG_GREEN_BOLD "\033[1;32m" ///< ANSI code for setting a GREEN foreground.
#define FG_YELLOW_BOLD "\033[1;33m" ///< ANSI code for setting a YELLOW foreground.
#define FG_BLUE_BOLD "\033[1;34m" ///< ANSI code for setting a BLUE foreground.
#define FG_MAGENTA_BOLD "\033[1;35m" ///< ANSI code for setting a MAGENTA foreground.
#define FG_CYAN_BOLD "\033[1;36m" ///< ANSI code for setting a CYAN foreground.
#define FG_WHITE_BOLD "\033[1;37m" ///< ANSI code for setting a WHITE foreground.
#define FG_BLACK_BRIGHT "\033[90m" ///< ANSI code for setting a BRIGHT_BLACK foreground.
#define FG_RED_BRIGHT "\033[91m" ///< ANSI code for setting a BRIGHT_RED foreground.
#define FG_GREEN_BRIGHT "\033[92m" ///< ANSI code for setting a BRIGHT_GREEN foreground.
#define FG_YELLOW_BRIGHT "\033[93m" ///< ANSI code for setting a BRIGHT_YELLOW foreground.
#define FG_BLUE_BRIGHT "\033[94m" ///< ANSI code for setting a BRIGHT_BLUE foreground.
#define FG_MAGENTA_BRIGHT "\033[95m" ///< ANSI code for setting a BRIGHT_MAGENTA foreground.
#define FG_CYAN_BRIGHT "\033[96m" ///< ANSI code for setting a BRIGHT_CYAN foreground.
#define FG_WHITE_BRIGHT "\033[97m" ///< ANSI code for setting a BRIGHT_WHITE foreground.
#define FG_BLACK_BRIGHT_BOLD "\033[1;90m" ///< ANSI code for setting a BRIGHT_BLACK foreground.
#define FG_RED_BRIGHT_BOLD "\033[1;91m" ///< ANSI code for setting a BRIGHT_RED foreground.
#define FG_GREEN_BRIGHT_BOLD "\033[1;92m" ///< ANSI code for setting a BRIGHT_GREEN foreground.
#define FG_YELLOW_BRIGHT_BOLD "\033[1;93m" ///< ANSI code for setting a BRIGHT_YELLOW foreground.
#define FG_BLUE_BRIGHT_BOLD "\033[1;94m" ///< ANSI code for setting a BRIGHT_BLUE foreground.
#define FG_MAGENTA_BRIGHT_BOLD "\033[1;95m" ///< ANSI code for setting a BRIGHT_MAGENTA foreground.
#define FG_CYAN_BRIGHT_BOLD "\033[1;96m" ///< ANSI code for setting a BRIGHT_CYAN foreground.
#define FG_WHITE_BRIGHT_BOLD "\033[1;97m" ///< ANSI code for setting a BRIGHT_WHITE foreground.
#define BG_BLACK "\033[40m" ///< ANSI code for setting a BLACK background.
#define BG_RED "\033[41m" ///< ANSI code for setting a RED background.
#define BG_GREEN "\033[42m" ///< ANSI code for setting a GREEN background.
#define BG_YELLOW "\033[43m" ///< ANSI code for setting a YELLOW background.
#define BG_BLUE "\033[44m" ///< ANSI code for setting a BLUE background.
#define BG_MAGENTA "\033[45m" ///< ANSI code for setting a MAGENTA background.
#define BG_CYAN "\033[46m" ///< ANSI code for setting a CYAN background.
#define BG_WHITE "\033[47m" ///< ANSI code for setting a WHITE background.
#define BG_BRIGHT_BLACK "\033[100m" ///< ANSI code for setting a BRIGHT_BLACK background.
#define BG_BRIGHT_RED "\033[101m" ///< ANSI code for setting a BRIGHT_RED background.
#define BG_BRIGHT_GREEN "\033[102m" ///< ANSI code for setting a BRIGHT_GREEN background.
#define BG_BRIGHT_YELLOW "\033[103m" ///< ANSI code for setting a BRIGHT_YELLOW background.
#define BG_BRIGHT_BLUE "\033[104m" ///< ANSI code for setting a BRIGHT_BLUE background.
#define BG_BRIGHT_MAGENTA "\033[105m" ///< ANSI code for setting a BRIGHT_MAGENTA background.
#define BG_BRIGHT_CYAN "\033[106m" ///< ANSI code for setting a BRIGHT_CYAN background.
#define BG_BRIGHT_WHITE "\033[107m" ///< ANSI code for setting a BRIGHT_WHITE background.
+83 -65
View File
@@ -3,7 +3,6 @@
/// @copyright (c) 2014-2022 This file is distributed under the MIT License.
/// See LICENSE.md for details.
/// Maximum length of credentials.
#include <string.h>
#include <stdbool.h>
#include <sys/unistd.h>
@@ -15,50 +14,74 @@
#include <pwd.h>
#include <strerror.h>
#include <stdlib.h>
#include <debug.h>
#include "ansi_colors.h"
/// Maximum length of credentials.
#define CREDENTIALS_LENGTH 50
#define FG_BLACK "\033[30m"
#define FG_WHITE "\033[37m"
#define FG_RED "\033[31m"
#define BG_WHITE "\033[47m"
#define BG_BLACK "\033[40m"
static inline int __setup_env(passwd_t *pwd)
{
// Set the USER.
if (setenv("USER", pwd->pw_name, 1) == -1) {
printf("Failed to set env: `USER`\n");
return 0;
}
// Set the SHELL.
if (setenv("SHELL", pwd->pw_shell, 1) == -1) {
printf("Failed to set env: `SHELL`\n");
return 0;
}
// Set the HOME.
if (setenv("HOME", pwd->pw_dir, 1) == -1) {
printf("Failed to set env: `HOME`\n");
return 0;
}
return 1;
}
void set_echo(bool_t active)
static inline void __set_io_flags(unsigned flag, bool_t active)
{
struct termios _termios;
tcgetattr(STDIN_FILENO, &_termios);
if (active)
_termios.c_lflag |= (ICANON | ECHO);
_termios.c_lflag |= flag;
else
_termios.c_lflag &= ~(ICANON | ECHO);
_termios.c_lflag &= ~flag;
tcsetattr(STDIN_FILENO, 0, &_termios);
}
void set_erase(bool_t active)
static inline void __print_message_file(const char * file)
{
struct termios _termios;
tcgetattr(STDIN_FILENO, &_termios);
if (active)
_termios.c_lflag |= ECHOE;
else
_termios.c_lflag &= ~ECHOE;
tcsetattr(STDIN_FILENO, 0, &_termios);
char buffer[256];
ssize_t nbytes, total = 0;
int fd;
// Try to open the file.
if ((fd = open(file, O_RDONLY, 0600)) == -1)
return;
// Read the lines of the file.
while ((nbytes = read(fd, buffer, sizeof(char) * 256)) > 0) {
// TODO: Parsing message files for special characters (such as `\t` for time).
printf("%s\n", buffer);
total += nbytes;
}
close(fd);
if (total > 0)
printf("\n");
}
/// @brief Gets the inserted command.
static bool_t get_input(char *input, size_t max_len, bool_t hide)
static inline bool_t __get_input(char *input, size_t max_len, bool_t hide)
{
size_t index = 0;
int c;
bool_t result = false;
//set_erase(false);
if (hide) {
set_echo(false);
}
__set_io_flags(ICANON, false);
if (hide)
__set_io_flags(ECHO, false);
memset(input, 0, max_len);
do {
@@ -104,6 +127,8 @@ static bool_t get_input(char *input, size_t max_len, bool_t hide)
putchar('\b');
--index;
}
} else if (c == 0) {
// Do nothing.
} else {
input[index++] = c;
if (index == (max_len - 1)) {
@@ -114,59 +139,34 @@ static bool_t get_input(char *input, size_t max_len, bool_t hide)
}
} while (index < max_len);
//set_erase(true);
if (hide) {
set_echo(true);
__set_io_flags(ECHO, true);
putchar('\n');
}
__set_io_flags(ICANON, true);
return result;
}
static inline int setup_env(passwd_t *pwd)
{
// Set the USER.
if (setenv("USER", pwd->pw_name, 1) == -1) {
printf("Failed to set env: `USER`\n");
return 0;
}
// Set the SHELL.
if (setenv("SHELL", pwd->pw_shell, 1) == -1) {
printf("Failed to set env: `SHELL`\n");
return 0;
}
// Set the HOME.
if (setenv("HOME", pwd->pw_dir, 1) == -1) {
printf("Failed to set env: `HOME`\n");
return 0;
}
return 1;
}
int main(int argc, char **argv)
{
// Print /etc/issue if it exists
// TODO: Parsing /etc/issue for special characters (such as `\t` for time)
int issues_fd = open("/etc/issue", O_RDONLY, 0600);
if (issues_fd != -1){
char buffer[256];
if(read(issues_fd, buffer, sizeof(char)*256) != -1){
printf("%s \n", buffer);
}
close(issues_fd);
}
// Print /etc/issue if it exists.
__print_message_file("/etc/issue");
passwd_t *pwd;
char username[50], password[50];
char username[CREDENTIALS_LENGTH], password[CREDENTIALS_LENGTH];
do {
// Get the username.
do {
printf("Username :");
} while (!get_input(username, 50, false));
} while (!__get_input(username, CREDENTIALS_LENGTH, false));
// Get the password.
do {
printf("Password :");
} while (!get_input(password, 50, true));
} while (!__get_input(password, CREDENTIALS_LENGTH, true));
// Check if we can find the user.
if ((pwd = getpwnam(username)) == NULL) {
if (errno == ENOENT) {
printf("The given name was not found.\n");
@@ -177,29 +177,47 @@ int main(int argc, char **argv)
}
continue;
}
// Check if the password is correct.
if (strcmp(pwd->pw_passwd, password) != 0) {
printf("Wrong password.\n");
continue;
}
break;
} while (true);
// If there is not shell set for the user, should we rollback to standard shell?
if (pwd->pw_shell == NULL) {
printf("%s: There is no shell set for the user `%s`.\n", argv[0], pwd->pw_name);
printf("login: There is no shell set for the user `%s`.\n", pwd->pw_name);
return 1;
}
if (!setup_env(pwd)) {
printf("%s: Failed to setup the environmental variables.\n", argv[0]);
// Set the standard environmental variables.
if (!__setup_env(pwd)) {
printf("login: Failed to setup the environmental variables.\n");
return 1;
}
// Set the group id.
setgid(pwd->pw_gid);
// Set the user id.
setuid(pwd->pw_uid);
// Print /etc/motd if it exists.
__print_message_file("/etc/motd");
// Welcome the user.
puts(BG_WHITE FG_BLACK);
printf("Welcome " FG_RED "%s" FG_BLACK "...\n", pwd->pw_name);
puts(BG_BLACK FG_WHITE_BRIGHT);
// Call the shell.
char *_argv[] = { pwd->pw_shell, (char *)NULL };
if (execv(pwd->pw_shell, _argv) == -1) {
printf("%s: Failed to execute the shell.\n", argv[0]);
printf("%s: %s.\n", argv[0], strerror(errno));
printf("login: Failed to execute the shell.\n");
printf("login: %s.\n", strerror(errno));
return 1;
}
return 0;
+54 -19
View File
@@ -3,32 +3,67 @@
/// @copyright (c) 2014-2022 This file is distributed under the MIT License.
/// See LICENSE.md for details.
#include <strerror.h>
#include <sys/dirent.h>
#include <sys/unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <strerror.h>
#include <string.h>
#include <sys/dirent.h>
#include <sys/unistd.h>
int main(int argc, char *argv[])
{
int fd = open("/bin", O_RDONLY | O_DIRECTORY, 0);
if (fd == -1) {
printf("%s: cannot access '/bin': %s\n\n", argv[0], strerror(errno));
return 1;
}
dirent_t dent;
int per_line = 0;
while (getdents(fd, &dent, sizeof(dirent_t)) == sizeof(dirent_t)) {
// Shows only regular files
if(dent.d_type == DT_REG){
printf("%10s ", dent.d_name);
if (++per_line == 6) {
per_line = 0;
putchar('\n');
if (argc == 1)
{
int fd = open("/bin", O_RDONLY | O_DIRECTORY, 0);
if (fd == -1)
{
printf("%s: cannot access '/bin': %s\n\n", argv[0], strerror(errno));
return 1;
}
dirent_t dent;
int per_line = 0;
while (getdents(fd, &dent, sizeof(dirent_t)) == sizeof(dirent_t))
{
// Shows only regular files
if (dent.d_type == DT_REG)
{
printf("%10s ", dent.d_name);
if (++per_line == 6)
{
per_line = 0;
putchar('\n');
}
}
}
putchar('\n');
close(fd);
}
else if (argc == 2)
{
char filepath[PATH_MAX];
strcpy(filepath, "/usr/share/man/");
strcat(filepath, argv[1]);
strcat(filepath, ".man");
int fd = open(filepath, O_RDONLY, 42);
if (fd < 0)
{
printf("%s: No manual entry for %s\n\n", argv[0], argv[1]);
}
else
{
// Prepare the buffer for reading the man file.
char buffer[BUFSIZ];
// Put on the standard output the characters.
while (read(fd, buffer, BUFSIZ) > 0)
{
puts(buffer);
}
// Close the file descriptor.
close(fd);
// Terminate with a pair of newlines.
putchar('\n');
putchar('\n');
}
}
putchar('\n');
close(fd);
return 0;
}
+2 -52
View File
@@ -21,46 +21,13 @@
#include "limits.h"
#include "sys/utsname.h"
#include "ctype.h"
#include "ansi_colors.h"
/// Maximum length of commands.
#define CMD_LEN 32
/// Maximum lenght of the history.
#define HISTORY_MAX 10
/// @brief A set of colors.
#define FG_BLACK "\033[30m"
#define FG_RED "\033[31m"
#define FG_GREEN "\033[32m"
#define FG_YELLOW "\033[33m"
#define FG_BLUE "\033[34m"
#define FG_MAGENTA "\033[35m"
#define FG_CYAN "\033[36m"
#define FG_WHITE "\033[37m"
#define FG_BRIGHT_BLACK "\033[90m"
#define FG_BRIGHT_RED "\033[91m"
#define FG_BRIGHT_GREEN "\033[92m"
#define FG_BRIGHT_YELLOW "\033[93m"
#define FG_BRIGHT_BLUE "\033[94m"
#define FG_BRIGHT_MAGENTA "\033[95m"
#define FG_BRIGHT_CYAN "\033[96m"
#define FG_BRIGHT_WHITE "\033[97m"
#define BG_BLACK "\033[40m"
#define BG_RED "\033[41m"
#define BG_GREEN "\033[42m"
#define BG_YELLOW "\033[43m"
#define BG_BLUE "\033[44m"
#define BG_MAGENTA "\033[45m"
#define BG_CYAN "\033[46m"
#define BG_WHITE "\033[47m"
#define BG_BRIGHT_BLACK "\033[100m"
#define BG_BRIGHT_RED "\033[101m"
#define BG_BRIGHT_GREEN "\033[102m"
#define BG_BRIGHT_YELLOW "\033[103m"
#define BG_BRIGHT_BLUE "\033[104m"
#define BG_BRIGHT_MAGENTA "\033[105m"
#define BG_BRIGHT_CYAN "\033[106m"
#define BG_BRIGHT_WHITE "\033[107m"
// Required by `export`
#define ENV_NORM 1
#define ENV_BRAK 2
@@ -188,7 +155,7 @@ static inline void __prompt_print()
} else {
HOSTNAME = buffer.nodename;
}
printf(FG_GREEN "%s" FG_WHITE "@" FG_CYAN "%s " FG_BRIGHT_BLUE "[%02d:%02d:%02d]" FG_WHITE " [%s] " FG_BRIGHT_WHITE "%% ",
printf(FG_GREEN "%s" FG_WHITE "@" FG_CYAN "%s " FG_BLUE_BRIGHT "[%02d:%02d:%02d]" FG_WHITE " [%s] " FG_WHITE_BRIGHT "%% ",
USER, HOSTNAME, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, CWD);
}
@@ -704,23 +671,6 @@ int main(int argc, char *argv[])
printf("Failed to set signal handler (%s).\n", SIGCHLD, strerror(errno));
return 1;
}
// Clear the screen.
puts("\033[J");
// Welcome the user.
puts(BG_WHITE FG_BLACK);
printf("Welcome " FG_RED "%s" FG_BLACK "...\n\n", USER);
puts(BG_BLACK FG_BRIGHT_WHITE);
// Print /etc/motd if it exists
int motd_fd = open("/etc/motd", O_RDONLY, 0600);
if (motd_fd != -1){
char buffer[256];
if(read(motd_fd, buffer, sizeof(char)*256) != -1){
printf("%s \n", buffer);
}
close(motd_fd);
}
// Move inside the home directory.
__cd(0, NULL);