dte test coverage


Directory: ./
File: src/util/fd.h
Date: 2025-12-03 13:13:24
Coverage Exec Excl Total
Lines: 100.0% 13 0 13
Functions: 100.0% 5 0 5
Branches: 50.0% 8 0 16

Line Branch Exec Source
1 #ifndef UTIL_FD_H
2 #define UTIL_FD_H
3
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <stdbool.h>
7 #include <sys/types.h>
8 #include <unistd.h>
9 #include "macros.h"
10
11 #define IS_STD_FD(fd) ((fd) >= STDIN_FILENO && (fd) <= STDERR_FILENO)
12
13 /*
14 * "The arg values to F_GETFD, F_SETFD, F_GETFL, and F_SETFL all
15 * represent flag values to allow for future growth. Applications
16 * using these functions should do a read-modify-write operation on
17 * them, rather than assuming that only the values defined by this
18 * volume of POSIX.1-2017 are valid. It is a common error to forget
19 * this, particularly in the case of F_SETFD."
20 *
21 * https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html#tag_16_122_07
22 */
23 WARN_UNUSED_RESULT
24 27 static inline bool fd_set_flag(int fd, int flag, int get_cmd, int set_cmd, bool state)
25 {
26 27 int flags = fcntl(fd, get_cmd);
27
1/2
✓ Branch 3 → 4 taken 27 times.
✗ Branch 3 → 12 not taken.
27 if (unlikely(flags < 0)) {
28 return false;
29 }
30
2/2
✓ Branch 4 → 5 taken 23 times.
✓ Branch 4 → 6 taken 4 times.
27 int new_flags = state ? (flags | flag) : (flags & ~flag);
31
3/4
✓ Branch 7 → 8 taken 25 times.
✓ Branch 7 → 11 taken 2 times.
✓ Branch 9 → 10 taken 25 times.
✗ Branch 9 → 11 not taken.
52 return new_flags == flags || fcntl(fd, set_cmd, new_flags) != -1;
32 }
33
34 WARN_UNUSED_RESULT
35 3 static inline bool fd_set_cloexec(int fd, bool cloexec)
36 {
37 3 return fd_set_flag(fd, FD_CLOEXEC, F_GETFD, F_SETFD, cloexec);
38 }
39
40 WARN_UNUSED_RESULT
41 24 static inline bool fd_set_nonblock(int fd, bool nonblock)
42 {
43 24 return fd_set_flag(fd, O_NONBLOCK, F_GETFL, F_SETFL, nonblock);
44 }
45
46 WARN_UNUSED_RESULT
47 9 static inline bool fd_is_valid(int fd)
48 {
49
1/4
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 6 taken 9 times.
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 6 not taken.
9 return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
50 }
51
52 WARN_UNUSED_RESULT
53 3 static inline bool is_controlling_tty(int fd)
54 {
55 /*
56 * POSIX requires tcgetpgrp() to return -1 and set errno to ENOTTY if
57 * `fd` isn't the controlling terminal, so this check alone should be
58 * sufficient here. However, OpenBSD 7.5 and FreeBSD 14.0 don't seem
59 * to conform to this requirement, so as a best-effort workaround we
60 * also check isatty(). This means that the function name used here
61 * isn't entirely accurate on those platforms, although it'd take a
62 * very unusual set of stdio(3) redirections for it to be a problem
63 * in practice (for the use cases in this codebase).
64 *
65 * See also: https://gitlab.com/craigbarnes/dte/-/issues/216#note_1939534295
66 */
67
1/4
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 7 taken 3 times.
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 7 not taken.
3 return isatty(fd) && tcgetpgrp(fd) != -1;
68 }
69
70 int xpipe2(int fd[static 2], int flags) WARN_UNUSED_RESULT;
71 int xdup3(int oldfd, int newfd, int flags) WARN_UNUSED_RESULT;
72 int xfchown(int fd, uid_t owner, gid_t group) WARN_UNUSED_RESULT;
73 int xfchmod(int fd, mode_t mode) WARN_UNUSED_RESULT;
74 int xftruncate(int fd, off_t length) WARN_UNUSED_RESULT;
75 int xfsync(int fd) WARN_UNUSED_RESULT;
76
77 #endif
78