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