diff --git a/src/fatal.hpp b/src/fatal.hpp new file mode 100644 index 00000000..8bde8317 --- /dev/null +++ b/src/fatal.hpp @@ -0,0 +1,40 @@ +/* + ISC License + + Copyright (c) 2026, Antonio SJ Musumeci + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#pragma once + +#include "syslog.hpp" + +#include "fmt/core.h" + +#include + +namespace fatal +{ + template + [[noreturn]] + void + abort(fmt::format_string format_, + Args&&... args_) + { + auto msg = fmt::format(format_,std::forward(args_)...); + fmt::println(stderr,"mergerfs: FATAL - {}",msg); + SysLog::crit("{}",msg); + std::abort(); + } +} diff --git a/src/procfs.cpp b/src/procfs.cpp index 70f3427a..f754aa0c 100644 --- a/src/procfs.cpp +++ b/src/procfs.cpp @@ -22,47 +22,56 @@ #include "procfs.hpp" -#include "errno.hpp" +#include "fatal.hpp" #include "fs_close.hpp" #include "fs_open.hpp" #include "fs_openat.hpp" #include "fs_read.hpp" #include "fmt/core.h" +#include "scope_guard.hpp" #include -#include - -#include +#include static int g_PROCFS_DIR_FD = -1; namespace procfs { int PROC_SELF_FD_FD = -1; } static constexpr const char PROCFS_PATH[] = "/proc"; -int +void procfs::init() { - int rv; - if(g_PROCFS_DIR_FD >= 0) - return 0; + return; - rv = fs::open(PROCFS_PATH,O_PATH|O_DIRECTORY); - if(rv < 0) - return rv; - - g_PROCFS_DIR_FD = rv; + g_PROCFS_DIR_FD = fs::open(PROCFS_PATH,O_PATH|O_DIRECTORY); + if(g_PROCFS_DIR_FD < 0) + fatal::abort("failed to open {}: {}",PROCFS_PATH,strerror(-g_PROCFS_DIR_FD)); #if defined(__linux__) -// This is critical to the function of the app. abort if failed to -// open. static constexpr const char PROC_SELF_FD[] = "/proc/self/fd"; procfs::PROC_SELF_FD_FD = fs::open(PROC_SELF_FD,O_PATH|O_DIRECTORY); - assert(procfs::PROC_SELF_FD_FD >= 0); + if(procfs::PROC_SELF_FD_FD < 0) + fatal::abort("failed to open /proc/self/fd: {}",strerror(-procfs::PROC_SELF_FD_FD)); #endif +} - return 0; +void +procfs::shutdown() +{ + if(g_PROCFS_DIR_FD >= 0) + { + fs::close(g_PROCFS_DIR_FD); + g_PROCFS_DIR_FD = -1; + } +#if defined(__linux__) + if(procfs::PROC_SELF_FD_FD >= 0) + { + fs::close(procfs::PROC_SELF_FD_FD); + procfs::PROC_SELF_FD_FD = -1; + } +#endif } std::string @@ -73,21 +82,26 @@ procfs::get_name(const int tid_) std::array commpath; fmt::format_to_n_result frv; + if(g_PROCFS_DIR_FD < 0) + fatal::abort("procfs::get_name called before procfs::init()"); + + // Reserve 1 byte for the NUL terminator that format_to_n does not write. frv = fmt::format_to_n(commpath.data(),commpath.size()-1,"{}/comm",tid_); frv.out[0] = '\0'; fd = fs::openat(g_PROCFS_DIR_FD,commpath.data(),O_RDONLY); if(fd < 0) return {}; + DEFER { fs::close(fd); }; - rv = fs::read(fd,commpath.data(),commpath.size()); - if(rv < 0) + rv = fs::read(fd,commpath.data(),commpath.size()-1); + if(rv <= 0) return {}; - // Overwrite the newline with NUL - commpath[rv-1] = '\0'; - - fs::close(fd); + if(commpath[rv-1] == '\n') + commpath[rv-1] = '\0'; + else + commpath[rv] = '\0'; return commpath.data(); } diff --git a/src/procfs.hpp b/src/procfs.hpp index 9484cdda..22167718 100644 --- a/src/procfs.hpp +++ b/src/procfs.hpp @@ -24,6 +24,7 @@ namespace procfs { extern int PROC_SELF_FD_FD; - int init(); + void init(); + void shutdown(); std::string get_name(const int tid); }