LCOV - code coverage report
Current view: top level - include/client/syscalls - args.hpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 103 124 83.1 %
Date: 2024-04-23 00:09:24 Functions: 21 24 87.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   Copyright 2018-2024, Barcelona Supercomputing Center (BSC), Spain
       3             :   Copyright 2015-2024, Johannes Gutenberg Universitaet Mainz, Germany
       4             : 
       5             :   This software was partially supported by the
       6             :   EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu).
       7             : 
       8             :   This software was partially supported by the
       9             :   ADA-FS project under the SPPEXA project funded by the DFG.
      10             : 
      11             :   This file is part of GekkoFS' POSIX interface.
      12             : 
      13             :   GekkoFS' POSIX interface is free software: you can redistribute it and/or
      14             :   modify it under the terms of the GNU Lesser General Public License as
      15             :   published by the Free Software Foundation, either version 3 of the License,
      16             :   or (at your option) any later version.
      17             : 
      18             :   GekkoFS' POSIX interface is distributed in the hope that it will be useful,
      19             :   but WITHOUT ANY WARRANTY; without even the implied warranty of
      20             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      21             :   GNU Lesser General Public License for more details.
      22             : 
      23             :   You should have received a copy of the GNU Lesser General Public License
      24             :   along with GekkoFS' POSIX interface.  If not, see
      25             :   <https://www.gnu.org/licenses/>.
      26             : 
      27             :   SPDX-License-Identifier: LGPL-3.0-or-later
      28             : */
      29             : 
      30             : // This file uses special C formatting for a better overview
      31             : // clang-format off
      32             : 
      33             : #ifndef GKFS_SYSCALLS_ARGS_HPP
      34             : #define GKFS_SYSCALLS_ARGS_HPP
      35             : 
      36             : #include <fcntl.h>
      37             : #include <csignal>
      38             : #include <cassert>
      39             : #include <sys/mman.h>
      40             : #include <sys/stat.h>
      41             : #include <sys/types.h>
      42             : #include <syscall.h>
      43             : #include <unistd.h>
      44             : #include <optional>
      45             : 
      46             : #include <type_traits>
      47             : #include <fmt/format.h>
      48             : #include <client/syscalls/detail/syscall_info.h>
      49             : 
      50             : namespace gkfs::syscall::arg {
      51             : 
      52             : /** Allowed arg types (based on the values of the corresponding C enum) */
      53             : enum class type {
      54             :     none          = ::arg_type_t::none,
      55             :     fd            = ::arg_type_t::fd,
      56             :     atfd          = ::arg_type_t::atfd,
      57             :     cstr          = ::arg_type_t::cstr,
      58             :     open_flags    = ::arg_type_t::open_flags,
      59             :     octal_mode    = ::arg_type_t::octal_mode,
      60             :     ptr           = ::arg_type_t::ptr,
      61             :     dec           = ::arg_type_t::dec,
      62             :     dec32         = ::arg_type_t::dec32,
      63             :     offset        = ::arg_type_t::offset,
      64             :     whence        = ::arg_type_t::whence,
      65             :     mmap_prot     = ::arg_type_t::mmap_prot,
      66             :     mmap_flags    = ::arg_type_t::mmap_flags,
      67             :     clone_flags   = ::arg_type_t::clone_flags,
      68             :     signum        = ::arg_type_t::signum,
      69             :     sigproc_how   = ::arg_type_t::sigproc_how,
      70             :     generic       = ::arg_type_t::arg,
      71             : };
      72             : 
      73             : /* Some constant definitions for convenience */
      74             : static constexpr auto none          = type::none;
      75             : static constexpr auto fd            = type::fd;
      76             : static constexpr auto atfd          = type::atfd;
      77             : static constexpr auto cstr          = type::cstr;
      78             : static constexpr auto open_flags    = type::open_flags;
      79             : static constexpr auto octal_mode    = type::octal_mode;
      80             : static constexpr auto ptr           = type::ptr;
      81             : static constexpr auto dec           = type::dec;
      82             : static constexpr auto dec32         = type::dec32;
      83             : static constexpr auto offset        = type::offset;
      84             : static constexpr auto whence        = type::whence;
      85             : static constexpr auto mmap_prot     = type::mmap_prot;
      86             : static constexpr auto mmap_flags    = type::mmap_flags;
      87             : static constexpr auto clone_flags   = type::clone_flags;
      88             : static constexpr auto signum        = type::signum;
      89             : static constexpr auto sigproc_how   = type::sigproc_how;
      90             : static constexpr auto generic       = type::generic;
      91             : 
      92             : 
      93             : /** An argument value with an optional size */
      94             : struct printable_arg {
      95             :     const char* const name;
      96             :     const long value;
      97             :     std::optional<long> size;
      98             : };
      99             : 
     100             : 
     101             : /** All arg formatters must follow this prototype */
     102             : template <typename FmtBuffer>
     103             : using formatter = std::add_pointer_t<void(FmtBuffer&, const printable_arg&)>;
     104             : 
     105             : 
     106             : /** forward declare formatters */
     107             : template <typename FmtBuffer> inline void
     108             : format_none_arg_to(FmtBuffer& buffer, const printable_arg& parg);
     109             : 
     110             : template <typename FmtBuffer> inline void
     111             : format_fd_arg_to(FmtBuffer& buffer, const printable_arg& parg);
     112             : 
     113             : template <typename FmtBuffer> inline void
     114             : format_atfd_arg_to(FmtBuffer& buffer, const printable_arg& parg);
     115             : 
     116             : template <typename FmtBuffer> inline void
     117             : format_cstr_arg_to(FmtBuffer& buffer, const printable_arg& parg);
     118             : 
     119             : template <typename FmtBuffer> inline void
     120             : format_open_flags_to(FmtBuffer& buffer, const printable_arg& parg);
     121             : 
     122             : template <typename FmtBuffer> inline void
     123             : format_octal_mode_to(FmtBuffer& buffer, const printable_arg& parg);
     124             : 
     125             : template <typename FmtBuffer> inline void
     126             : format_ptr_arg_to(FmtBuffer& buffer, const printable_arg& parg);
     127             : 
     128             : template <typename FmtBuffer> inline void
     129             : format_dec_arg_to(FmtBuffer& buffer, const printable_arg& parg);
     130             : 
     131             : template <typename FmtBuffer> inline void
     132             : format_dec32_arg_to(FmtBuffer& buffer, const printable_arg& parg);
     133             : 
     134             : template <typename FmtBuffer> inline void
     135             : format_whence_arg_to(FmtBuffer& buffer, const printable_arg& parg);
     136             : 
     137             : template <typename FmtBuffer> inline void
     138             : format_mmap_prot_arg_to(FmtBuffer& buffer, const printable_arg& parg);
     139             : 
     140             : template <typename FmtBuffer> inline void
     141             : format_mmap_flags_arg_to(FmtBuffer& buffer, const printable_arg& parg);
     142             : 
     143             : template <typename FmtBuffer> inline void
     144             : format_clone_flags_arg_to(FmtBuffer& buffer, const printable_arg& parg);
     145             : 
     146             : template <typename FmtBuffer> inline void
     147             : format_signum_arg_to(FmtBuffer& buffer, const printable_arg& parg);
     148             : 
     149             : template <typename FmtBuffer> inline void
     150             : format_sigproc_how_arg_to(FmtBuffer& buffer, const printable_arg& parg);
     151             : 
     152             : template <typename FmtBuffer> inline void
     153             : format_arg_to(FmtBuffer& buffer, const printable_arg& parg);
     154             : 
     155             : 
     156             : /** Known formatters */
     157             : template <typename FmtBuffer>
     158             : static const constexpr 
     159             : std::array<formatter<FmtBuffer>, arg_type_max> formatters = {
     160             :     /* [none]          = */ format_none_arg_to,
     161             :     /* [fd]            = */ format_fd_arg_to,
     162             :     /* [atfd]          = */ format_atfd_arg_to,
     163             :     /* [cstr]          = */ format_cstr_arg_to,
     164             :     /* [open_flags]    = */ format_open_flags_to,
     165             :     /* [octal_mode]    = */ format_octal_mode_to,
     166             :     /* [ptr]           = */ format_ptr_arg_to,
     167             :     /* [dec]           = */ format_dec_arg_to,
     168             :     /* [dec32]         = */ format_dec32_arg_to,
     169             :     /* [offset]        = */ format_dec_arg_to,
     170             :     /* [whence]        = */ format_whence_arg_to,
     171             :     /* [mmap_prot]     = */ format_mmap_prot_arg_to,
     172             :     /* [mmap_flags]    = */ format_mmap_flags_arg_to,
     173             :     /* [clone_flags]   = */ format_clone_flags_arg_to,
     174             :     /* [signum]        = */ format_signum_arg_to,
     175             :     /* [sigproc_how]   = */ format_sigproc_how_arg_to,
     176             :     /* [arg]           = */ format_arg_to,
     177             : };
     178             : 
     179             : /** An argument descriptor */
     180             : struct desc {
     181             :     arg::type type_;
     182             :     const char* name_;
     183             : 
     184             :     arg::type
     185             :     type() const {
     186             :         return type_;
     187             :     }
     188             : 
     189             :     const char*
     190     3632974 :     name() const {
     191     3632974 :         return name_;
     192             :     }
     193             : 
     194             :     template <typename FmtBuffer>
     195             :     formatter<FmtBuffer>
     196     3632990 :     formatter() const {
     197     3632990 :         const auto idx = static_cast<int>(type_);
     198             : 
     199             :         // if the type is unknown fall back to the default formatter
     200     3632990 :         if(idx < 0 || idx >= static_cast<int>(formatters<FmtBuffer>.size())) {
     201             :             return format_arg_to;
     202             :         }
     203             : 
     204     3632990 :         assert(formatters<FmtBuffer>.at(idx) != nullptr);
     205             : 
     206     3632990 :         return formatters<FmtBuffer>.at(idx);
     207             :     }
     208             : };
     209             : 
     210             : 
     211             : /** Specific formatter implementations follow */
     212             : 
     213             : /** Flag descriptor */
     214             : typedef struct {
     215             :         long               flag_;
     216             :         const char * const name_;
     217             : } flag_desc;
     218             : 
     219             : #define FLAG_ENTRY(f) flag_desc{ f, #f }
     220             : 
     221             : #define LIKELY(x)      __builtin_expect(!!(x), 1)
     222             : #define UNLIKELY(x)    __builtin_expect(!!(x), 0)
     223             : 
     224             : template <typename FmtBuffer, typename FlagDescriptorArray>
     225             : static void
     226       25640 : format_flag(FmtBuffer& buffer, long flag, FlagDescriptorArray&& desc) {
     227             : 
     228             :     // we assume that if a flag value is zero, its printable
     229             :     // name will always be at position 0 in the array
     230       25640 :     if(flag == 0 && desc[0].flag_ == 0) {
     231        6158 :         fmt::format_to(std::back_inserter(buffer), "{}", desc[0].name_);
     232        6158 :         return;
     233             :     }
     234             : 
     235       70650 :     for(std::size_t i = 0; i < desc.size(); ++i) {
     236             : 
     237       70650 :         if(desc[i].name_ == nullptr) {
     238           0 :             continue;
     239             :         }
     240             : 
     241       70650 :         if((flag == desc[i].flag_)) {
     242       19482 :             fmt::format_to(std::back_inserter(buffer), "{}", desc[i].name_);
     243       19482 :             return;
     244             :         }
     245             :     }
     246             : 
     247           0 :     fmt::format_to(std::back_inserter(buffer), "{:#x}", flag);
     248             : }
     249             : 
     250             : template <typename FmtBuffer, typename FlagDescriptorArray>
     251             : static void
     252       54569 : format_flag_set(FmtBuffer& buffer, long flags, FlagDescriptorArray&& desc) {
     253             : 
     254             :     // we assume that if a flag value is zero, its printable
     255             :     // name will always be at position 0 in the array
     256       54569 :     if(flags == 0 && desc[0].flag_ == 0) {
     257       19968 :         fmt::format_to(std::back_inserter(buffer), "{}", desc[0].name_);
     258       19968 :         return;
     259             :     }
     260             : 
     261       34601 :     std::size_t i = 0;
     262       34601 :     const auto buffer_start = buffer.size();
     263             : 
     264      212709 :     while(flags != 0 && i < desc.size()) {
     265             : 
     266      178108 :         if(desc[i].name_ == nullptr) {
     267           0 :             ++i;
     268           0 :             continue;
     269             :         }
     270             : 
     271      178108 :         if((flags & desc[i].flag_) != 0) {
     272       80541 :             fmt::format_to(std::back_inserter(buffer), "{}{}",
     273       80541 :                            buffer.size() != buffer_start ? "|" : "",
     274       80541 :                            desc[i].name_);
     275       80541 :             flags &= ~desc[i].flag_;
     276             :         }
     277             : 
     278      178108 :         ++i;
     279             :     }
     280             : 
     281       34601 :     if(flags != 0) {
     282           8 :         if(buffer.size() != buffer_start) {
     283           4 :             fmt::format_to(std::back_inserter(buffer), "|");
     284             :         }
     285             : 
     286           8 :         fmt::format_to(std::back_inserter(buffer), "{:#x}", flags);
     287           8 :         return;
     288             :     }
     289             : 
     290       34593 :     if(buffer_start == buffer.size()) {
     291           0 :         fmt::format_to(std::back_inserter(buffer), "0x0");
     292             :     }
     293             : }
     294             : 
     295             : /**
     296             :  * format_whence_arg_to - format a 'whence' argument
     297             :  *
     298             :  * Format a 'whence' argument from the lseek() syscall, modifying the provided
     299             :  * buffer by appending to it a string representation of the form:
     300             :  *   name = formatted_val
     301             :  */
     302             : template <typename FmtBuffer>
     303             : inline void
     304       17178 : format_whence_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
     305             : 
     306             :     /* Names for lseek() whence arg */
     307       17178 :     const auto flag_names =
     308             :             utils::make_array(
     309             :             FLAG_ENTRY(SEEK_SET),
     310             :             FLAG_ENTRY(SEEK_CUR),
     311             :             FLAG_ENTRY(SEEK_END)
     312             :         );
     313             : 
     314       17178 :     fmt::format_to(std::back_inserter(buffer), "{}=", parg.name);
     315       17178 :     format_flag_set(buffer, parg.value, flag_names);
     316       17178 : }
     317             : 
     318             : 
     319             : /**
     320             :  * format_mmap_prot_arg_to - format a 'prot' argument
     321             :  *
     322             :  * Format a 'prot' argument (such as those passed to mmap())
     323             :  * and append the resulting string to the provided buffer.
     324             :  */
     325             : template <typename FmtBuffer>
     326             : inline void
     327        8994 : format_mmap_prot_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
     328             : 
     329             :     /* Names for mmap() prot arg */
     330        8994 :     const auto flag_names =
     331             :             utils::make_array(
     332             :             FLAG_ENTRY(PROT_NONE),
     333             :             FLAG_ENTRY(PROT_READ),
     334             :             FLAG_ENTRY(PROT_WRITE),
     335             :             FLAG_ENTRY(PROT_EXEC));
     336             : 
     337        8994 :     fmt::format_to(std::back_inserter(buffer), "{}=", parg.name);
     338        8994 :     format_flag_set(buffer, parg.value, flag_names);
     339             : 
     340        8994 :     return;
     341             : }
     342             : 
     343             : 
     344             : /**
     345             :  * format_mmap_flags_arg_to - format a 'flags' argument
     346             :  *
     347             :  * Format a 'flags' argument (such as those passed to mmap())
     348             :  * and append the resulting string to the provided buffer.
     349             :  */
     350             : template <typename FmtBuffer>
     351             : inline void
     352        6188 : format_mmap_flags_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
     353             : 
     354             :     /* Names for mmap() flags arg */
     355        6188 :     const auto flag_names =
     356             :             utils::make_array(
     357             :             FLAG_ENTRY(MAP_SHARED),
     358             :             FLAG_ENTRY(MAP_PRIVATE),
     359             : #ifdef MAP_SHARED_VALIDATE
     360             :             FLAG_ENTRY(MAP_SHARED_VALIDATE),
     361             : #endif
     362             :             FLAG_ENTRY(MAP_FIXED),
     363             :             FLAG_ENTRY(MAP_ANONYMOUS),
     364             :             FLAG_ENTRY(MAP_GROWSDOWN),
     365             :             FLAG_ENTRY(MAP_DENYWRITE),
     366             :             FLAG_ENTRY(MAP_EXECUTABLE),
     367             :             FLAG_ENTRY(MAP_LOCKED),
     368             :             FLAG_ENTRY(MAP_NORESERVE),
     369             :             FLAG_ENTRY(MAP_POPULATE),
     370             :             FLAG_ENTRY(MAP_NONBLOCK),
     371             :             FLAG_ENTRY(MAP_STACK),
     372             :             FLAG_ENTRY(MAP_HUGETLB)
     373             : #ifdef MAP_SYNC
     374             :             ,
     375             :             FLAG_ENTRY(MAP_SYNC)
     376             : #endif
     377             :             );
     378             : 
     379        6188 :     fmt::format_to(std::back_inserter(buffer), "{}=", parg.name);
     380        6188 :     format_flag_set(buffer, parg.value, flag_names);
     381        6188 :     return;
     382             : }
     383             : 
     384             : /**
     385             :  * format_clone_flags_arg_to - format a 'flags' argument
     386             :  *
     387             :  * Format a 'flags' argument (such as those passed to clone())
     388             :  * and append the resulting string to the provided buffer.
     389             :  */
     390             : template <typename FmtBuffer>
     391             : inline void
     392        3291 : format_clone_flags_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
     393             : 
     394             :     /* Names for clone() flags arg */
     395        3291 :     const auto flag_names =
     396             :             utils::make_array(
     397             :             FLAG_ENTRY(CLONE_VM),
     398             :             FLAG_ENTRY(CLONE_FS),
     399             :             FLAG_ENTRY(CLONE_FILES),
     400             :             FLAG_ENTRY(CLONE_SIGHAND),
     401             :             FLAG_ENTRY(CLONE_PTRACE),
     402             :             FLAG_ENTRY(CLONE_VFORK),
     403             :             FLAG_ENTRY(CLONE_PARENT),
     404             :             FLAG_ENTRY(CLONE_THREAD),
     405             :             FLAG_ENTRY(CLONE_NEWNS),
     406             :             FLAG_ENTRY(CLONE_SYSVSEM),
     407             :             FLAG_ENTRY(CLONE_SETTLS),
     408             :             FLAG_ENTRY(CLONE_PARENT_SETTID),
     409             :             FLAG_ENTRY(CLONE_CHILD_CLEARTID),
     410             :             FLAG_ENTRY(CLONE_DETACHED),
     411             :             FLAG_ENTRY(CLONE_UNTRACED),
     412             :             FLAG_ENTRY(CLONE_CHILD_SETTID),
     413             : #ifdef CLONE_NEWCGROUP
     414             :             FLAG_ENTRY(CLONE_NEWCGROUP),
     415             : #endif
     416             :             FLAG_ENTRY(CLONE_NEWUTS),
     417             :             FLAG_ENTRY(CLONE_NEWIPC),
     418             :             FLAG_ENTRY(CLONE_NEWUSER),
     419             :             FLAG_ENTRY(CLONE_NEWPID),
     420             :             FLAG_ENTRY(CLONE_NEWNET),
     421             :             FLAG_ENTRY(CLONE_IO));
     422             : 
     423        3291 :     fmt::format_to(std::back_inserter(buffer), "{}=", parg.name);
     424             : 
     425             :     // the low byte in clone flags contains the number of the termination
     426             :     // signal sent to the parent when the child dies
     427        3291 :     format_flag_set(buffer, parg.value & ~0x11l, flag_names);
     428             : 
     429        3291 :     if((parg.value & 0x11l) != 0) {
     430           0 :         fmt::format_to(std::back_inserter(buffer), "|", parg.name);
     431           0 :         format_signum_arg_to(buffer, {"", parg.value & 0x11l});
     432             :     }
     433        3291 :     return;
     434             : }
     435             : 
     436             : /**
     437             :  * format_signum_arg_to - format a 'signum' argument
     438             :  *
     439             :  * Format a 'signum' argument (such as those passed to rt_sigaction())
     440             :  * and append the resulting string to the provided buffer.
     441             :  */
     442             : template <typename FmtBuffer>
     443             : inline void
     444        2152 : format_signum_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
     445             : 
     446             :     /* Names for signum args */
     447        2152 :     const auto flag_names =
     448             :             utils::make_array(
     449             :             FLAG_ENTRY(SIGHUP),
     450             :             FLAG_ENTRY(SIGINT),
     451             :             FLAG_ENTRY(SIGQUIT),
     452             :             FLAG_ENTRY(SIGILL),
     453             :             FLAG_ENTRY(SIGTRAP),
     454             :             FLAG_ENTRY(SIGABRT),
     455             :             FLAG_ENTRY(SIGBUS),
     456             :             FLAG_ENTRY(SIGFPE),
     457             :             FLAG_ENTRY(SIGKILL),
     458             :             FLAG_ENTRY(SIGUSR1),
     459             :             FLAG_ENTRY(SIGSEGV),
     460             :             FLAG_ENTRY(SIGUSR2),
     461             :             FLAG_ENTRY(SIGPIPE),
     462             :             FLAG_ENTRY(SIGALRM),
     463             :             FLAG_ENTRY(SIGTERM),
     464             :             FLAG_ENTRY(SIGSTKFLT),
     465             :             FLAG_ENTRY(SIGCHLD),
     466             :             FLAG_ENTRY(SIGCONT),
     467             :             FLAG_ENTRY(SIGSTOP),
     468             :             FLAG_ENTRY(SIGTSTP),
     469             :             FLAG_ENTRY(SIGTTIN),
     470             :             FLAG_ENTRY(SIGTTOU),
     471             :             FLAG_ENTRY(SIGURG),
     472             :             FLAG_ENTRY(SIGXCPU),
     473             :             FLAG_ENTRY(SIGXFSZ),
     474             :             FLAG_ENTRY(SIGVTALRM),
     475             :             FLAG_ENTRY(SIGPROF),
     476             :             FLAG_ENTRY(SIGWINCH),
     477             :             FLAG_ENTRY(SIGIO),
     478             :             FLAG_ENTRY(SIGPWR),
     479             :             FLAG_ENTRY(SIGSYS));
     480             : 
     481        2152 :     if(std::strcmp(parg.name, "")) {
     482        2152 :         fmt::format_to(std::back_inserter(buffer), "{}=", parg.name);
     483             :     }
     484             : 
     485        2152 :     format_flag(buffer, parg.value, flag_names);
     486        2152 :     return;
     487             : }
     488             : 
     489             : 
     490             : /**
     491             :  * format_sigproc_how_arg_to - format a 'sigproc how' argument
     492             :  *
     493             :  * Format a 'sigproc how' argument (such as those passed to sigprocmask())
     494             :  * and append the resulting string to the provided buffer.
     495             :  */
     496             : template <typename FmtBuffer>
     497             : inline void
     498           0 : format_sigproc_how_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
     499             : 
     500             :     /* Names for sigproc how args */
     501           0 :     const auto flag_names =
     502             :             utils::make_array(
     503             :             FLAG_ENTRY(SIG_BLOCK),
     504             :             FLAG_ENTRY(SIG_UNBLOCK),
     505             :             FLAG_ENTRY(SIG_SETMASK));
     506             : 
     507           0 :     fmt::format_to(std::back_inserter(buffer), "{}=", parg.name);
     508           0 :     format_flag(buffer, parg.value, flag_names);
     509           0 :     return;
     510             : }
     511             : 
     512             : /** 
     513             :  * format_none_arg_to - format a 'none' argument
     514             :  *
     515             :  * Format a 'none' argument and append the resulting "void" string to the
     516             :  * provided buffer.
     517             :  */
     518             : template <typename FmtBuffer>
     519             : inline void
     520           0 : format_none_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
     521           0 :     fmt::format_to(std::back_inserter(buffer), "void");
     522           0 : }
     523             : 
     524             : 
     525             : /**
     526             :  * format_fd_arg_to - format a 'fd' argument
     527             :  *
     528             :  * Format a 'fd' argument (such as those passed to read())
     529             :  * and append the resulting string to the provided buffer.
     530             :  */
     531             : template <typename FmtBuffer>
     532             : inline void
     533      896590 : format_fd_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
     534      896590 :     fmt::format_to(std::back_inserter(buffer), "{}={}", parg.name, static_cast<int>(parg.value));
     535      896581 : }
     536             : 
     537             : 
     538             : /**
     539             :  * format_atfd_arg_to - format a 'at_fd' argument
     540             :  *
     541             :  * Format a 'at_fd' argument (such as those passed to openat())
     542             :  * and append the resulting string to the provided buffer.
     543             :  */
     544             : template <typename FmtBuffer>
     545             : inline void
     546       23520 : format_atfd_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
     547             : 
     548       23520 :     if(static_cast<int>(parg.value) == AT_FDCWD) {
     549       23512 :         fmt::format_to(std::back_inserter(buffer), "{}=AT_FDCWD", parg.name);
     550       23512 :         return;
     551             :     }
     552             : 
     553           8 :     fmt::format_to(std::back_inserter(buffer), "{}={}", parg.name, static_cast<int>(parg.value));
     554             : }
     555             : 
     556             : 
     557             : /**
     558             :  * format_cstr_arg_to - format a 'cstr' argument
     559             :  *
     560             :  * Format a 'cstr' argument (i.e. a null-terminated C string)
     561             :  * and append the resulting string to the provided buffer.
     562             :  */
     563             : template <typename FmtBuffer>
     564             : inline void
     565      285254 : format_cstr_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
     566             : 
     567      285254 :     if(LIKELY(reinterpret_cast<const char*>(parg.value) != nullptr)) {
     568      285254 :         fmt::format_to(std::back_inserter(buffer), "{}=\"{}\"", parg.name,
     569      285254 :                        reinterpret_cast<const char*>(parg.value));
     570      285254 :         return;
     571             :     }
     572             : 
     573           0 :     fmt::format_to(std::back_inserter(buffer), "{}=NULL", parg.name);
     574             : }
     575             : 
     576             : /** 
     577             :  * format_open_flags_to - format a 'flags' argument
     578             :  *
     579             :  * Format a 'flags' argument (such as those passed to open()) and append 
     580             :  * the resulting string to the provided buffer.
     581             :  */
     582             : template <typename FmtBuffer>
     583             : inline void
     584       23488 : format_open_flags_to(FmtBuffer& buffer,
     585             :                      const printable_arg& parg) {
     586             : 
     587             :     /* Names for O_ACCMODE args */
     588       23488 :     const auto flag_names =
     589             :             utils::make_array(
     590             :             FLAG_ENTRY(O_RDONLY),
     591             :             FLAG_ENTRY(O_WRONLY),
     592             :             FLAG_ENTRY(O_RDWR));
     593             : 
     594       23488 :     const auto extra_flag_names =
     595             :             utils::make_array(
     596             : #ifdef O_EXEC
     597             :             FLAG_ENTRY(O_EXEC),
     598             : #endif
     599             : #ifdef O_SEARCH
     600             :             FLAG_ENTRY(O_SEARCH),
     601             : #endif
     602             :             FLAG_ENTRY(O_APPEND),
     603             :             FLAG_ENTRY(O_CLOEXEC),
     604             :             FLAG_ENTRY(O_CREAT),
     605             :             FLAG_ENTRY(O_DIRECTORY),
     606             :             FLAG_ENTRY(O_DSYNC),
     607             :             FLAG_ENTRY(O_EXCL),
     608             :             FLAG_ENTRY(O_NOCTTY),
     609             :             FLAG_ENTRY(O_NOFOLLOW),
     610             :             FLAG_ENTRY(O_NONBLOCK),
     611             :             FLAG_ENTRY(O_RSYNC),
     612             :             FLAG_ENTRY(O_SYNC),
     613             :             FLAG_ENTRY(O_TRUNC)
     614             : #ifdef O_TTY_INIT
     615             :             , FLAG_ENTRY(O_TTY_INIT)
     616             : #endif
     617             :             );
     618             : 
     619       23488 :     long flags = parg.value;
     620             : 
     621       23488 :     fmt::format_to(std::back_inserter(buffer), "{}=", parg.name);
     622       23488 :     format_flag(buffer, flags & O_ACCMODE, flag_names);
     623             : 
     624       23488 :     flags &= ~O_ACCMODE;
     625             : 
     626             : #ifdef O_TMPFILE
     627             :     // processing it with the other flags can result in
     628             :     // printing O_DIRECTORY when it should not be listed.
     629             :     //
     630             :     // See O_TMPFILE' definition in fcntl-linux.h :
     631             :     //     #define __O_TMPFILE   (020000000 | __O_DIRECTORY)
     632       23488 :     if((flags & O_TMPFILE) == O_TMPFILE) {
     633           0 :         format_flag(buffer, O_TMPFILE, flag_names);
     634           0 :         flags &= ~O_TMPFILE;
     635             :     }
     636             : #endif // !O_TMPFILE
     637             : 
     638       23488 :     if(flags != 0) {
     639       18918 :         fmt::format_to(std::back_inserter(buffer), "|", parg.name);
     640       18918 :         format_flag_set(buffer, flags, extra_flag_names);
     641             :     }
     642       23488 : }
     643             : 
     644             : /**
     645             :  * format_octal_mode_to - format a 'mode' argument
     646             :  *
     647             :  * Format a 'mode' argument (such as those passed to open()) and append the
     648             :  * generated string to the provided buffer.
     649             :  */
     650             : template <typename FmtBuffer>
     651             : inline void
     652       19322 : format_octal_mode_to(FmtBuffer& buffer, const printable_arg& parg) {
     653       19322 :     fmt::format_to(std::back_inserter(buffer), "{}={:#04o}", parg.name, parg.value);
     654       19322 : }
     655             : 
     656             : /**
     657             :  * format_ptr_arg_to - format a 'ptr' argument
     658             :  *
     659             :  * Format a 'ptr' argument (i.e. a C pointer)
     660             :  * and append the resulting string to the provided buffer.
     661             :  */
     662             : template <typename FmtBuffer>
     663             : inline void
     664     1268683 : format_ptr_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
     665             : 
     666     1268683 :     if(LIKELY(reinterpret_cast<const void*>(parg.value) != nullptr)) {
     667     1184428 :         fmt::format_to(std::back_inserter(buffer), "{}={}", parg.name,
     668     1184428 :                        reinterpret_cast<const void*>(parg.value));
     669     1184276 :         return;
     670             :     }
     671             : 
     672       84255 :     fmt::format_to(std::back_inserter(buffer), "{}=NULL", parg.name);
     673             : }
     674             : 
     675             : 
     676             : /**
     677             :  * format_dec_arg_to - format a 'dec' argument
     678             :  *
     679             :  * Format a 'dec' argument (i.e. an integer of unknwon size)
     680             :  * and append the resulting string to the provided buffer.
     681             :  */
     682             : template <typename FmtBuffer>
     683             : inline void
     684       50502 : format_dec_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
     685       50502 :     fmt::format_to(std::back_inserter(buffer), "{}={}", parg.name, parg.value);
     686       50494 : }
     687             : 
     688             : 
     689             : /**
     690             :  * format_dec32_arg_to - format a 'dec32' argument
     691             :  *
     692             :  * Format a 'dec32' argument (i.e. a 32-bit integer)
     693             :  * and append the resulting string to the provided buffer.
     694             :  */
     695             : template <typename FmtBuffer>
     696             : inline void
     697           0 : format_dec32_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
     698           0 :     fmt::format_to(std::back_inserter(buffer), "{}={}", parg.name, static_cast<int>(parg.value));
     699           0 : }
     700             : 
     701             : 
     702             : /**
     703             :  * format_arg_to - format an arbitrary argument
     704             :  *
     705             :  * Format an arbitrary argument and append the resulting
     706             :  * string to the provided buffer.
     707             :  */
     708             : template <typename FmtBuffer>
     709             : inline void
     710     1027921 : format_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
     711     1027921 :     fmt::format_to(std::back_inserter(buffer), "{}={:#x}", parg.name, parg.value);
     712     1027339 : }
     713             : 
     714             : #undef FLAG_ENTRY
     715             : #undef LIKELY
     716             : #undef UNLIKELY
     717             : 
     718             : } // namespace gkfs::syscall::arg
     719             : 
     720             : #endif // GKFS_SYSCALLS_ARGS_HPP
     721             : 
     722             : // clang-format on

Generated by: LCOV version 1.16