dte test coverage


Directory: ./
File: src/util/fd.h
Date: 2025-09-07 23:01:39
Exec Total Coverage
Lines: 13 13 100.0%
Functions: 5 5 100.0%
Branches: 8 16 50.0%

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 0 (3→4) taken 27 times.
✗ Branch 1 (3→12) not taken.
27 if (unlikely(flags < 0)) {
28 return false;
29 }
30
2/2
✓ Branch 0 (4→5) taken 23 times.
✓ Branch 1 (4→6) taken 4 times.
27 int new_flags = state ? (flags | flag) : (flags & ~flag);
31
3/4
✓ Branch 0 (7→8) taken 25 times.
✓ Branch 1 (7→11) taken 2 times.
✓ Branch 2 (9→10) taken 25 times.
✗ Branch 3 (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 0 (3→4) not taken.
✓ Branch 1 (3→6) taken 9 times.
✗ Branch 2 (4→5) not taken.
✗ Branch 3 (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 0 (3→4) not taken.
✓ Branch 1 (3→7) taken 3 times.
✗ Branch 2 (5→6) not taken.
✗ Branch 3 (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