]>
Commit | Line | Data |
---|---|---|
813fb2f6 A |
1 | /* |
2 | * testname: pwrite_avoid_sigxfsz_28581610 | |
3 | */ | |
4 | ||
5 | #include <darwintest.h> | |
6 | #include <fcntl.h> | |
7 | #include <limits.h> | |
8 | #include <setjmp.h> | |
9 | #include <signal.h> | |
10 | #include <sys/resource.h> | |
11 | #include <sys/stat.h> | |
12 | #include <unistd.h> | |
13 | ||
cb323159 A |
14 | T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true)); |
15 | ||
16 | #define TMP_FILE_PATH "/tmp/test_pwrite_28581610" | |
813fb2f6 A |
17 | |
18 | static sigjmp_buf xfsz_jmpbuf; | |
19 | ||
20 | void xfsz_signal(int); | |
21 | ||
22 | void | |
23 | xfsz_signal(__unused int signo) | |
24 | { | |
25 | siglongjmp(xfsz_jmpbuf, 1); | |
26 | } | |
27 | ||
28 | T_DECL(pwrite, "Tests avoiding SIGXFSZ with pwrite and odd offsets", | |
0a7de745 | 29 | T_META_ASROOT(true)) |
813fb2f6 A |
30 | { |
31 | int fd, x; | |
32 | off_t ret; | |
33 | struct stat f_stat; | |
34 | struct rlimit crl; | |
35 | static const int offs[] = { -1, -1 * 1024, -1 * 1024 * 16, -1 * 1024 * 1024 * 16, 0 }; | |
36 | static unsigned char buffer[1048576]; | |
37 | ||
38 | T_SETUPBEGIN; | |
39 | /* We expect zero SIGXFSZ signals because we have no file size limits */ | |
40 | crl.rlim_cur = crl.rlim_max = RLIM_INFINITY; | |
41 | ret = setrlimit(RLIMIT_FSIZE, &crl); | |
42 | T_ASSERT_POSIX_SUCCESS(ret, "setting infinite file size limit"); | |
43 | ||
44 | /* we just needed root to setup unlimited file size */ | |
45 | remove(TMP_FILE_PATH); | |
46 | setuid(5000); | |
47 | ||
48 | /* We just want an empty regular file to test with */ | |
49 | fd = open(TMP_FILE_PATH, O_RDWR | O_CREAT | O_EXCL, 0777); | |
50 | T_ASSERT_POSIX_SUCCESS(fd, "opening fd on temp file %s.", TMP_FILE_PATH); | |
51 | ||
52 | /* sanity check that this new file is really zero bytes in size */ | |
53 | ret = fstat(fd, &f_stat); | |
54 | T_ASSERT_POSIX_SUCCESS(ret, "stat() fd on temp file."); | |
55 | T_ASSERT_TRUE(0 == f_stat.st_size, "ensure %s is empty", TMP_FILE_PATH); | |
56 | ||
57 | /* sanity check that ftruncate() considers negative offsets an error */ | |
58 | for (x = 0; offs[x] != 0; x++) { | |
59 | ret = ftruncate(fd, offs[x]); | |
60 | T_ASSERT_TRUE(((ret == -1) && (errno == EINVAL)), | |
0a7de745 | 61 | "negative offset %d", offs[x]); |
813fb2f6 A |
62 | } |
63 | ||
64 | T_SETUPEND; | |
65 | ||
66 | /* we want to get the EFBIG errno but without a SIGXFSZ signal */ | |
0a7de745 | 67 | T_EXPECTFAIL; |
813fb2f6 A |
68 | if (!sigsetjmp(xfsz_jmpbuf, 1)) { |
69 | signal(SIGXFSZ, xfsz_signal); | |
70 | ret = pwrite(fd, buffer, sizeof buffer, LONG_MAX); | |
71 | T_ASSERT_TRUE(((ret == -1) && (errno == EFBIG)), | |
0a7de745 | 72 | "large offset %d", 13); |
813fb2f6 A |
73 | } else { |
74 | signal(SIGXFSZ, SIG_DFL); | |
75 | T_FAIL("%s unexpected SIGXFSZ with offset %lX", | |
0a7de745 | 76 | "<rdar://problem/28581610>", LONG_MAX); |
813fb2f6 A |
77 | } |
78 | ||
79 | /* Negative offsets are invalid, no SIGXFSZ signals required */ | |
80 | for (x = 0; offs[x] != 0; x++) { | |
0a7de745 A |
81 | /* only -1 gives the correct result */ |
82 | if (-1 != offs[x]) { | |
83 | T_EXPECTFAIL; | |
84 | } | |
813fb2f6 A |
85 | |
86 | if (!sigsetjmp(xfsz_jmpbuf, 1)) { | |
87 | signal(SIGXFSZ, xfsz_signal); | |
88 | ret = pwrite(fd, buffer, sizeof buffer, offs[x]); | |
89 | T_ASSERT_TRUE(((ret == -1) && (errno == EINVAL)), | |
0a7de745 | 90 | "negative offset %d", offs[x]); |
813fb2f6 A |
91 | } else { |
92 | signal(SIGXFSZ, SIG_DFL); | |
93 | T_FAIL("%s unexpected SIGXFSZ with negative offset %d", | |
0a7de745 | 94 | "<rdar://problem/28581610>", offs[x]); |
813fb2f6 A |
95 | } |
96 | } | |
97 | ||
98 | remove(TMP_FILE_PATH); | |
99 | } |