diff --git a/kernel/include/scheduler.hpp b/kernel/include/scheduler.hpp index a5ef0ac5..3bcb33e2 100644 --- a/kernel/include/scheduler.hpp +++ b/kernel/include/scheduler.hpp @@ -36,6 +36,8 @@ void reschedule(); void sleep_ms(pid_t pid, size_t time); +size_t register_new_handle(const std::string& path); + } //end of namespace scheduler #endif diff --git a/kernel/include/vfs.hpp b/kernel/include/vfs.hpp new file mode 100644 index 00000000..89ddf0e6 --- /dev/null +++ b/kernel/include/vfs.hpp @@ -0,0 +1,19 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013-2014. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef VFS_H +#define VFS_H + +//TODO Once userspace is done, integrate parts of disks.hpp here + +namespace vfs { + +int64_t open(const char* file); + +} //end of namespace vfs + +#endif diff --git a/kernel/src/scheduler.cpp b/kernel/src/scheduler.cpp index d9eeb7b3..e1757476 100644 --- a/kernel/src/scheduler.cpp +++ b/kernel/src/scheduler.cpp @@ -40,6 +40,7 @@ struct process_control_t { scheduler::process_state state; size_t rounds; size_t sleep_timeout; + std::vector handles; }; //The Process Control Block @@ -129,7 +130,11 @@ void gc_task(){ desc.context = nullptr; desc.brk_start = desc.brk_end = 0; - //8. Release the PCB slot + //8 Clean file handles + //TODO If not empty, probably something should be done + process.handles.clear(); + + //9. Release the PCB slot process.state = scheduler::process_state::EMPTY; } } @@ -803,6 +808,12 @@ void scheduler::sleep_ms(pid_t pid, size_t time){ reschedule(); } +size_t scheduler::register_new_handle(const std::string& path){ + pcb[current_pid].handles.push_back(path); + + return pcb[current_pid].handles.size() - 1; +} + //Provided for task_switch.s extern "C" { diff --git a/kernel/src/system_calls.cpp b/kernel/src/system_calls.cpp index 031b1e2d..b283f954 100644 --- a/kernel/src/system_calls.cpp +++ b/kernel/src/system_calls.cpp @@ -11,6 +11,7 @@ #include "keyboard.hpp" #include "terminal.hpp" #include "acpi.hpp" +#include "vfs.hpp" namespace { @@ -102,6 +103,12 @@ void sc_shutdown(interrupt::syscall_regs*){ acpi::shutdown(); } +void sc_open(interrupt::syscall_regs* regs){ + auto file = reinterpret_cast(regs->rbx); + + regs->rax = vfs::open(file); +} + } //End of anonymous namespace void system_call_entry(interrupt::syscall_regs* regs){ @@ -164,6 +171,10 @@ void system_call_entry(interrupt::syscall_regs* regs){ sc_shutdown(regs); break; + case 300: + sc_open(regs); + break; + case 0x666: //TODO Do something with return code scheduler::kill_current_process(); diff --git a/kernel/src/vfs.cpp b/kernel/src/vfs.cpp new file mode 100644 index 00000000..9ae78ab1 --- /dev/null +++ b/kernel/src/vfs.cpp @@ -0,0 +1,58 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013-2014. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#include +#include +#include + +#include "vfs.hpp" +#include "scheduler.hpp" + +#include "fat32.hpp" + +#include "disks.hpp" + +int64_t vfs::open(const char* file_path){ + if(!disks::mounted_partition() || !disks::mounted_disk()){ + return -std::ERROR_NOTHING_MOUNTED; + } + + std::string file(file_path); + + if(file.empty()){ + return -std::ERROR_INVALID_FILE_PATH; + } + + if(file[0] != '/'){ + return -std::ERROR_INVALID_FILE_PATH; + } + + auto parts = std::split(file, '/'); + + if(parts.empty()){ + return -std::ERROR_INVALID_FILE_PATH; + } + + auto last = parts.back(); + parts.pop_back(); + + //TODO file search should be done entirely by the file system + + auto files = fat32::ls(*disks::mounted_disk(), *disks::mounted_partition(), parts); + + for(auto& f : files){ + if(f.file_name == file){ + if(f.directory){ + return -std::ERROR_DIRECTORY; + } + + return scheduler::register_new_handle(file); + } + } + + return -std::ERROR_NOT_EXISTS; +} diff --git a/tlib/include/errors.hpp b/tlib/include/errors.hpp index b6279a1c..fcbd6fb8 100644 --- a/tlib/include/errors.hpp +++ b/tlib/include/errors.hpp @@ -8,11 +8,18 @@ #ifndef ERRORS_H #define ERRORS_H +#include + +//TODO Rename this namespace namespace std { +//TODO Use an enum constexpr const size_t ERROR_NOT_EXISTS = 1; constexpr const size_t ERROR_NOT_EXECUTABLE = 2; constexpr const size_t ERROR_FAILED_EXECUTION = 3; +constexpr const size_t ERROR_NOTHING_MOUNTED = 4; +constexpr const size_t ERROR_INVALID_FILE_PATH = 5; +constexpr const size_t ERROR_DIRECTORY = 6; inline const char* error_message(size_t error){ switch(error){ @@ -22,6 +29,12 @@ inline const char* error_message(size_t error){ return "The file is not an executable"; case ERROR_FAILED_EXECUTION: return "Execution failed"; + case ERROR_NOTHING_MOUNTED: + return "Nothing is mounted"; + case ERROR_INVALID_FILE_PATH: + return "The file path is not valid"; + case ERROR_DIRECTORY: + return "The file is a directory"; default: return "Unknonwn error"; } diff --git a/tlib/include/file.hpp b/tlib/include/file.hpp new file mode 100644 index 00000000..26cc3f37 --- /dev/null +++ b/tlib/include/file.hpp @@ -0,0 +1,17 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013-2014. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef USER_SYSTEM_HPP +#define USER_SYSTEM_HPP + +#include +#include +#include + +std::expected open(const char* file); + +#endif diff --git a/tlib/src/file.cpp b/tlib/src/file.cpp new file mode 100644 index 00000000..21cd4b18 --- /dev/null +++ b/tlib/src/file.cpp @@ -0,0 +1,22 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013-2014. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#include + +std::expected open(const char* file){ + int64_t fd; + asm volatile("mov rax, 300; mov rbx, %[path]; int 50; mov %[fd], rax" + : [fd] "=m" (fd) + : [path] "g" (reinterpret_cast(file)) + : "rax", "rbx"); + + if(fd < 0){ + return std::make_expected_from_error(-fd); + } else { + return std::make_expected(fd); + } +} diff --git a/tstl/include/string.hpp b/tstl/include/string.hpp index a0300207..0776520d 100644 --- a/tstl/include/string.hpp +++ b/tstl/include/string.hpp @@ -332,13 +332,13 @@ size_t digits(N number){ } template -std::vector> split(const std::basic_string& s){ +std::vector> split(const std::basic_string& s, char sep = ' '){ std::vector> parts; std::basic_string current(s.size()); for(char c : s){ - if(c == ' ' && !current.empty()){ + if(c == sep && !current.empty()){ parts.push_back(current); current.clear(); } else {