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 3348583 : name() const {
191 3348583 : return name_;
192 : }
193 :
194 : template <typename FmtBuffer>
195 : formatter<FmtBuffer>
196 3348288 : formatter() const {
197 3348288 : const auto idx = static_cast<int>(type_);
198 :
199 : // if the type is unknown fall back to the default formatter
200 3348288 : if(idx < 0 || idx >= static_cast<int>(formatters<FmtBuffer>.size())) {
201 : return format_arg_to;
202 : }
203 :
204 3348288 : assert(formatters<FmtBuffer>.at(idx) != nullptr);
205 :
206 3348288 : 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 23540 : 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 23540 : if(flag == 0 && desc[0].flag_ == 0) {
231 5590 : fmt::format_to(buffer, "{}", desc[0].name_);
232 5590 : return;
233 : }
234 :
235 65108 : for(std::size_t i = 0; i < desc.size(); ++i) {
236 :
237 65108 : if(desc[i].name_ == nullptr) {
238 0 : continue;
239 : }
240 :
241 65108 : if((flag == desc[i].flag_)) {
242 17950 : fmt::format_to(buffer, "{}", desc[i].name_);
243 17950 : return;
244 : }
245 : }
246 :
247 0 : fmt::format_to(buffer, "{:#x}", flag);
248 : }
249 :
250 : template <typename FmtBuffer, typename FlagDescriptorArray>
251 : static void
252 50072 : 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 50072 : if(flags == 0 && desc[0].flag_ == 0) {
257 18346 : fmt::format_to(buffer, "{}", desc[0].name_);
258 18346 : return;
259 : }
260 :
261 31726 : std::size_t i = 0;
262 31726 : const auto buffer_start = buffer.size();
263 :
264 194258 : while(flags != 0 && i < desc.size()) {
265 :
266 162531 : if(desc[i].name_ == nullptr) {
267 0 : ++i;
268 0 : continue;
269 : }
270 :
271 162531 : if((flags & desc[i].flag_) != 0) {
272 73400 : fmt::format_to(buffer, "{}{}",
273 73400 : buffer.size() != buffer_start ? "|" : "",
274 73400 : desc[i].name_);
275 73401 : flags &= ~desc[i].flag_;
276 : }
277 :
278 162532 : ++i;
279 : }
280 :
281 31727 : if(flags != 0) {
282 8 : if(buffer.size() != buffer_start) {
283 4 : fmt::format_to(buffer, "|");
284 : }
285 :
286 8 : fmt::format_to(buffer, "{:#x}", flags);
287 8 : return;
288 : }
289 :
290 31719 : if(buffer_start == buffer.size()) {
291 0 : fmt::format_to(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 15834 : format_whence_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
305 :
306 : /* Names for lseek() whence arg */
307 15834 : 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 15834 : fmt::format_to(buffer, "{}=", parg.name);
315 15834 : format_flag_set(buffer, parg.value, flag_names);
316 15834 : }
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 8180 : format_mmap_prot_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
328 :
329 : /* Names for mmap() prot arg */
330 8180 : 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 8180 : fmt::format_to(buffer, "{}=", parg.name);
338 8180 : format_flag_set(buffer, parg.value, flag_names);
339 :
340 8180 : 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 5652 : format_mmap_flags_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
353 :
354 : /* Names for mmap() flags arg */
355 5652 : 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 5652 : fmt::format_to(buffer, "{}=", parg.name);
380 5652 : format_flag_set(buffer, parg.value, flag_names);
381 5652 : 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 2975 : format_clone_flags_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
393 :
394 : /* Names for clone() flags arg */
395 2975 : 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 2975 : fmt::format_to(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 2974 : format_flag_set(buffer, parg.value & ~0x11l, flag_names);
428 :
429 2975 : if((parg.value & 0x11l) != 0) {
430 0 : fmt::format_to(buffer, "|", parg.name);
431 0 : format_signum_arg_to(buffer, {"", parg.value & 0x11l});
432 : }
433 2975 : 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 1984 : format_signum_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
445 :
446 : /* Names for signum args */
447 1984 : 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 1984 : if(std::strcmp(parg.name, "")) {
482 1984 : fmt::format_to(buffer, "{}=", parg.name);
483 : }
484 :
485 1984 : format_flag(buffer, parg.value, flag_names);
486 1984 : 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(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 16 : format_none_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
521 16 : fmt::format_to(buffer, "void");
522 16 : }
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 828275 : format_fd_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
534 828275 : fmt::format_to(buffer, "{}={}", parg.name, static_cast<int>(parg.value));
535 828280 : }
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 21588 : format_atfd_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
547 :
548 21588 : if(static_cast<int>(parg.value) == AT_FDCWD) {
549 21580 : fmt::format_to(buffer, "{}=AT_FDCWD", parg.name);
550 21580 : return;
551 : }
552 :
553 8 : fmt::format_to(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 260178 : format_cstr_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
566 :
567 260178 : if(LIKELY(reinterpret_cast<const char*>(parg.value) != nullptr)) {
568 260178 : fmt::format_to(buffer, "{}=\"{}\"", parg.name,
569 260178 : reinterpret_cast<const char*>(parg.value));
570 260178 : return;
571 : }
572 :
573 0 : fmt::format_to(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 21556 : format_open_flags_to(FmtBuffer& buffer,
585 : const printable_arg& parg) {
586 :
587 : /* Names for O_ACCMODE args */
588 21556 : 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 21556 : 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 21556 : long flags = parg.value;
620 :
621 21556 : fmt::format_to(buffer, "{}=", parg.name);
622 21556 : format_flag(buffer, flags & O_ACCMODE, flag_names);
623 :
624 21556 : 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 21556 : 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 21556 : if(flags != 0) {
639 17432 : fmt::format_to(buffer, "|", parg.name);
640 17432 : format_flag_set(buffer, flags, extra_flag_names);
641 : }
642 21556 : }
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 17968 : format_octal_mode_to(FmtBuffer& buffer, const printable_arg& parg) {
653 17968 : fmt::format_to(buffer, "{}={:#04o}", parg.name, parg.value);
654 17968 : }
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 1163235 : format_ptr_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
665 :
666 1163235 : if(LIKELY(reinterpret_cast<const void*>(parg.value) != nullptr)) {
667 1094067 : fmt::format_to(buffer, "{}={}", parg.name,
668 1094067 : reinterpret_cast<const void*>(parg.value));
669 1094064 : return;
670 : }
671 :
672 69168 : fmt::format_to(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 58350 : format_dec_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
685 58350 : fmt::format_to(buffer, "{}={}", parg.name, parg.value);
686 58346 : }
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 6039 : format_dec32_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
698 6039 : fmt::format_to(buffer, "{}={}", parg.name, static_cast<int>(parg.value));
699 6039 : }
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 937059 : format_arg_to(FmtBuffer& buffer, const printable_arg& parg) {
711 937059 : fmt::format_to(buffer, "{}={:#x}", parg.name, parg.value);
712 937039 : }
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
|