dte test coverage


Directory: ./
File: src/util/fd.c
Date: 2025-07-19 20:13:10
Exec Total Coverage
Lines: 28 55 50.9%
Functions: 5 6 83.3%
Branches: 6 53 11.3%

Line Branch Exec Source
1 #include "feature.h"
2 #include <sys/stat.h>
3 #include "fd.h"
4 #include "debug.h"
5 #include "xreadwrite.h"
6
7 42 int xpipe2(int fd[2], int flags)
8 {
9 42 BUG_ON((flags & (O_CLOEXEC | O_NONBLOCK)) != flags);
10
11 #if HAVE_PIPE2
12
1/2
✗ Branch 0 (5→6) not taken.
✓ Branch 1 (5→24) taken 42 times.
42 if (likely(pipe2(fd, flags) == 0)) {
13 return 0;
14 }
15 // If pipe2() fails with ENOSYS, it means the function is just a stub
16 // and not actually supported. In that case, the pure POSIX fallback
17 // implementation should be tried instead. In other cases, the failure
18 // is probably caused by a normal error condition.
19 if (errno != ENOSYS) {
20 return -1;
21 }
22 #endif
23
24 // NOLINTNEXTLINE(android-cloexec-pipe)
25 if (unlikely(pipe(fd) != 0)) {
26 return -1;
27 }
28
29 if (flags & O_CLOEXEC) {
30 if (unlikely(!fd_set_cloexec(fd[0], true) || !fd_set_cloexec(fd[1], true))) {
31 goto error;
32 }
33 }
34 if (flags & O_NONBLOCK) {
35 if (unlikely(!fd_set_nonblock(fd[0], true) || !fd_set_nonblock(fd[1], true))) {
36 goto error;
37 }
38 }
39
40 return 0;
41
42 error:;
43 xclose(fd[0]);
44 xclose(fd[1]);
45 return -1;
46 }
47
48 63 int xdup3(int oldfd, int newfd, int flags)
49 {
50 63 BUG_ON((flags & O_CLOEXEC) != flags);
51 63 int fd;
52
53 #if HAVE_DUP3
54 126 do {
55 63 fd = dup3(oldfd, newfd, flags);
56
1/4
✗ Branch 0 (5→6) not taken.
✓ Branch 1 (5→7) taken 63 times.
✗ Branch 2 (6→4) not taken.
✗ Branch 3 (6→7) not taken.
63 } while (unlikely(fd < 0 && errno == EINTR));
57
58
1/4
✗ Branch 0 (7→8) not taken.
✓ Branch 1 (7→17) taken 63 times.
✗ Branch 2 (8→9) not taken.
✗ Branch 3 (8→17) not taken.
63 if (fd != -1 || errno != ENOSYS) {
59 return fd;
60 }
61
62 // If execution reaches this point, dup3() failed with ENOSYS
63 // ("function not supported"), so we fall through to the pure
64 // POSIX implementation below.
65 #endif
66
67 if (unlikely(oldfd == newfd)) {
68 // Replicate dup3() behaviour:
69 errno = EINVAL;
70 return -1;
71 }
72
73 do {
74 fd = dup2(oldfd, newfd);
75 } while (unlikely(fd < 0 && errno == EINTR));
76
77 if (fd >= 0 && (flags & O_CLOEXEC)) {
78 (void)!fd_set_cloexec(fd, true);
79 }
80
81 return fd;
82 }
83
84 2 int xfchown(int fd, uid_t owner, gid_t group)
85 {
86 2 int r;
87 4 do {
88 2 r = fchown(fd, owner, group);
89
1/4
✗ Branch 0 (4→5) not taken.
✓ Branch 1 (4→6) taken 2 times.
✗ Branch 2 (5→3) not taken.
✗ Branch 3 (5→6) not taken.
2 } while (unlikely(r != 0 && errno == EINTR));
90 2 return r;
91 }
92
93 21 int xfchmod(int fd, mode_t mode)
94 {
95 21 int r;
96 42 do {
97 21 r = fchmod(fd, mode);
98
1/4
✗ Branch 0 (4→5) not taken.
✓ Branch 1 (4→6) taken 21 times.
✗ Branch 2 (5→3) not taken.
✗ Branch 3 (5→6) not taken.
21 } while (unlikely(r != 0 && errno == EINTR));
99 21 return r;
100 }
101
102 21 int xftruncate(int fd, off_t length)
103 {
104 21 int r;
105 42 do {
106 21 r = ftruncate(fd, length);
107
1/4
✗ Branch 0 (4→5) not taken.
✓ Branch 1 (4→6) taken 21 times.
✗ Branch 2 (5→3) not taken.
✗ Branch 3 (5→6) not taken.
21 } while (unlikely(r != 0 && errno == EINTR));
108 21 return r;
109 }
110
111 int xfsync(int fd)
112 {
113 #if HAVE_FSYNC
114 retry:
115 if (fsync(fd) == 0) {
116 return 0;
117 }
118
119 switch (errno) {
120 // EINVAL is ignored because it just means "operation not possible
121 // on this descriptor" rather than indicating an actual error
122 case EINVAL:
123 case ENOTSUP:
124 case ENOSYS:
125 return 0;
126 case EINTR:
127 goto retry;
128 }
129
130 return -1;
131 #else
132 (void)fd;
133 return 0;
134 #endif
135 }
136