From ae41dbfa8c4124da9bae3204eb50b6bfe492dcbe Mon Sep 17 00:00:00 2001 From: Baptiste Wicht Date: Sun, 7 Aug 2016 18:13:02 +0200 Subject: [PATCH] Complete procfs --- kernel/include/vfs/file.hpp | 4 ++ kernel/src/fs/procfs.cpp | 140 +++++++++++++++++++++++++++++++++--- 2 files changed, 135 insertions(+), 9 deletions(-) diff --git a/kernel/include/vfs/file.hpp b/kernel/include/vfs/file.hpp index 189a15a0..5854bed3 100644 --- a/kernel/include/vfs/file.hpp +++ b/kernel/include/vfs/file.hpp @@ -27,6 +27,10 @@ struct file { //File system specific size_t location; size_t position; + + file(){}; + file(std::string file_name, bool directory, bool hidden, bool system, uint64_t size) + : file_name(file_name), directory(directory), hidden(hidden), system(system), size(size) {}; }; } //end of namespace vfs diff --git a/kernel/src/fs/procfs.cpp b/kernel/src/fs/procfs.cpp index b9586221..7972b885 100644 --- a/kernel/src/fs/procfs.cpp +++ b/kernel/src/fs/procfs.cpp @@ -13,11 +13,63 @@ #include "fs/procfs.hpp" #include "scheduler.hpp" +#include "logging.hpp" namespace { const scheduler::process_control_t* pcb = nullptr; +std::vector standard_contents; + +//TODO Move into tstl +uint64_t atoui(const std::string& s){ + uint64_t value = 0; + uint64_t mul = 1; + + for(size_t i = s.size(); i > 0; --i){ + auto c = s[i - 1]; + + if(c < '0' || c > '9'){ + return value; + } + + value += mul * (c - '0'); + + mul *= 10; + } + + return value; +} + +size_t read(const std::string& value, char* buffer, size_t count, size_t offset, size_t& read){ + if(offset > value.size()){ + return std::ERROR_INVALID_OFFSET; + } + + read = std::min(count, value.size() - offset); + std::copy_n(buffer, value.c_str() + offset, read); + + return 0; +} + +std::string get_value(uint64_t pid, const std::string& name){ + auto& process = pcb[pid]; + + if(name == "pid"){ + return std::to_string(process.process.pid); + } else if(name == "ppid"){ + return std::to_string(process.process.ppid); + } else if(name == "state"){ + return std::to_string(static_cast(process.state)); + } else if(name == "system"){ + return process.process.system ? "true" : "false"; + } else if(name == "priority"){ + return std::to_string(process.process.priority); + } else { + return ""; + } +} + } //end of anonymous namespace void procfs::set_pcb(const scheduler::process_control_t* pcb_ptr){ @@ -25,7 +77,11 @@ void procfs::set_pcb(const scheduler::process_control_t* pcb_ptr){ } procfs::procfs_file_system::procfs_file_system(std::string mp) : mount_point(mp) { - //Nothing to init + standard_contents.emplace_back("pid", false, false, false, 0); + standard_contents.emplace_back("ppid", false, false, false, 0); + standard_contents.emplace_back("state", false, false, false, 0); + standard_contents.emplace_back("system", false, false, false, 0); + standard_contents.emplace_back("priority", false, false, false, 0); } procfs::procfs_file_system::~procfs_file_system(){ @@ -33,6 +89,7 @@ procfs::procfs_file_system::~procfs_file_system(){ } size_t procfs::procfs_file_system::get_file(const std::vector& file_path, vfs::file& f){ + // Access the root folder if(file_path.empty()){ f.file_name = "/"; f.directory = true; @@ -43,23 +100,85 @@ size_t procfs::procfs_file_system::get_file(const std::vector& file return 0; } - if(file_path.size() == 1){ - //TODO + auto i = atoui(file_path[0]); + + // Check the pid folder + if(i >= scheduler::MAX_PROCESS){ + return std::ERROR_NOT_EXISTS; } + auto& process = pcb[i]; + + if(process.state == scheduler::process_state::EMPTY){ + return std::ERROR_NOT_EXISTS; + } + + // Access a pid folder + if(file_path.size() == 1){ + f.file_name = file_path[0]; + f.directory = true; + f.hidden = false; + f.system = false; + f.size = 0; + + return 0; + } + + // Access a file directly + if(file_path.size() == 2){ + auto value = get_value(i, file_path[1]); + + if(value.size()){ + f.file_name = file_path[1]; + f.directory = false; + f.hidden = false; + f.system = false; + f.size = value.size(); + + return 0; + } else { + return std::ERROR_NOT_EXISTS; + } + } + + // There are no more levels return std::ERROR_NOT_EXISTS; } size_t procfs::procfs_file_system::read(const std::vector& file_path, char* buffer, size_t count, size_t offset, size_t& read){ - //Cannot access the root for reading + //Cannot access the root nor the pid directores for reading if(file_path.size() < 2){ return std::ERROR_PERMISSION_DENIED; } + if(file_path.size() == 2){ + auto i = atoui(file_path[0]); + + if(i >= scheduler::MAX_PROCESS){ + return std::ERROR_NOT_EXISTS; + } + + auto& process = pcb[i]; + + if(process.state == scheduler::process_state::EMPTY){ + return std::ERROR_NOT_EXISTS; + } + + auto value = get_value(i, file_path[1]); + + if(value.size()){ + return ::read(value, buffer, count, offset, read); + } else { + return std::ERROR_NOT_EXISTS; + } + } + return std::ERROR_NOT_EXISTS; } size_t procfs::procfs_file_system::ls(const std::vector& file_path, std::vector& contents){ + logging::logf(logging::log_level::DEBUG, "procfs ls %u\n", file_path.size()); + if(file_path.size() == 0){ for(size_t i = 0; i < scheduler::MAX_PROCESS; ++i){ auto& process = pcb[i]; @@ -67,21 +186,24 @@ size_t procfs::procfs_file_system::ls(const std::vector& file_path, if(process.state != scheduler::process_state::EMPTY){ vfs::file f; f.file_name = std::to_string(process.process.pid); - f.directory = false; + f.directory = true; f.hidden = false; f.system = false; f.size = 0; contents.emplace_back(std::move(f)); } } + + return 0; } - //No subfolder support - if(file_path.size() > 0){ - return std::ERROR_NOT_EXISTS; + if(file_path.size() == 1){ + contents = standard_contents; + return 0; } - return 0; + //No more subfolder support + return std::ERROR_NOT_EXISTS; } size_t procfs::procfs_file_system::statfs(statfs_info& file){