dte test coverage


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