1*433d6423SLionel Sambuc /* Tests for truncate(2) call family - by D.C. van Moolenbroek */
2*433d6423SLionel Sambuc #include <sys/stat.h>
3*433d6423SLionel Sambuc #include <sys/param.h>
4*433d6423SLionel Sambuc #include <unistd.h>
5*433d6423SLionel Sambuc #include <fcntl.h>
6*433d6423SLionel Sambuc #include <assert.h>
7*433d6423SLionel Sambuc
8*433d6423SLionel Sambuc #define ITERATIONS 1
9*433d6423SLionel Sambuc int max_error = 4;
10*433d6423SLionel Sambuc #include "common.h"
11*433d6423SLionel Sambuc
12*433d6423SLionel Sambuc
13*433d6423SLionel Sambuc #define TESTFILE "testfile"
14*433d6423SLionel Sambuc #define TESTSIZE 4096
15*433d6423SLionel Sambuc #define THRESHOLD 1048576
16*433d6423SLionel Sambuc
17*433d6423SLionel Sambuc
18*433d6423SLionel Sambuc int main(int argc, char *argv[]);
19*433d6423SLionel Sambuc void prepare(void);
20*433d6423SLionel Sambuc int make_file(off_t size);
21*433d6423SLionel Sambuc void check_file(int fd, off_t size, off_t hole_start, off_t hole_end);
22*433d6423SLionel Sambuc void all_sizes(void (*call) (off_t osize, off_t nsize));
23*433d6423SLionel Sambuc void test50a(void);
24*433d6423SLionel Sambuc void test50b(void);
25*433d6423SLionel Sambuc void test50c(void);
26*433d6423SLionel Sambuc void test50d(void);
27*433d6423SLionel Sambuc void sub50e(off_t osize, off_t nsize);
28*433d6423SLionel Sambuc void test50e(void);
29*433d6423SLionel Sambuc void sub50f(off_t osize, off_t nsize);
30*433d6423SLionel Sambuc void test50f(void);
31*433d6423SLionel Sambuc void sub50g(off_t osize, off_t nsize);
32*433d6423SLionel Sambuc void test50g(void);
33*433d6423SLionel Sambuc void sub50h(off_t osize, off_t nsize);
34*433d6423SLionel Sambuc void test50h(void);
35*433d6423SLionel Sambuc void sub50i(off_t size, off_t off, size_t len, int type);
36*433d6423SLionel Sambuc void test50i(void);
37*433d6423SLionel Sambuc
38*433d6423SLionel Sambuc /* Some of the sizes have been chosen in such a way that they should be on the
39*433d6423SLionel Sambuc * edge of direct/single indirect/double indirect switchovers for a MINIX
40*433d6423SLionel Sambuc * file system with 4K block size.
41*433d6423SLionel Sambuc */
42*433d6423SLionel Sambuc static off_t sizes[] = {
43*433d6423SLionel Sambuc 0L, 1L, 511L, 512L, 513L, 1023L, 1024L, 1025L, 2047L, 2048L, 2049L, 3071L,
44*433d6423SLionel Sambuc 3072L, 3073L, 4095L, 4096L, 4097L, 16383L, 16384L, 16385L, 28671L, 28672L,
45*433d6423SLionel Sambuc 28673L, 65535L, 65536L, 65537L, 4222975L, 4222976L, 4222977L
46*433d6423SLionel Sambuc };
47*433d6423SLionel Sambuc
48*433d6423SLionel Sambuc static unsigned char *data;
49*433d6423SLionel Sambuc
main(argc,argv)50*433d6423SLionel Sambuc int main(argc, argv)
51*433d6423SLionel Sambuc int argc;
52*433d6423SLionel Sambuc char *argv[];
53*433d6423SLionel Sambuc {
54*433d6423SLionel Sambuc int j, m = 0xFFFF;
55*433d6423SLionel Sambuc
56*433d6423SLionel Sambuc start(50);
57*433d6423SLionel Sambuc prepare();
58*433d6423SLionel Sambuc if (argc == 2) m = atoi(argv[1]);
59*433d6423SLionel Sambuc for (j = 0; j < ITERATIONS; j++) {
60*433d6423SLionel Sambuc if (m & 00001) test50a();
61*433d6423SLionel Sambuc if (m & 00002) test50b();
62*433d6423SLionel Sambuc if (m & 00004) test50c();
63*433d6423SLionel Sambuc if (m & 00010) test50d();
64*433d6423SLionel Sambuc if (m & 00020) test50e();
65*433d6423SLionel Sambuc if (m & 00040) test50f();
66*433d6423SLionel Sambuc if (m & 00100) test50g();
67*433d6423SLionel Sambuc if (m & 00200) test50h();
68*433d6423SLionel Sambuc if (m & 00400) test50i();
69*433d6423SLionel Sambuc }
70*433d6423SLionel Sambuc
71*433d6423SLionel Sambuc quit();
72*433d6423SLionel Sambuc return(-1); /* impossible */
73*433d6423SLionel Sambuc }
74*433d6423SLionel Sambuc
prepare()75*433d6423SLionel Sambuc void prepare()
76*433d6423SLionel Sambuc {
77*433d6423SLionel Sambuc size_t largest;
78*433d6423SLionel Sambuc int i;
79*433d6423SLionel Sambuc
80*433d6423SLionel Sambuc largest = 0;
81*433d6423SLionel Sambuc for (i = 0; i < sizeof(sizes) / sizeof(sizes[0]); i++)
82*433d6423SLionel Sambuc if (largest < sizes[i]) largest = sizes[i];
83*433d6423SLionel Sambuc
84*433d6423SLionel Sambuc /* internal integrity check: this is needed for early tests */
85*433d6423SLionel Sambuc assert(largest >= TESTSIZE);
86*433d6423SLionel Sambuc
87*433d6423SLionel Sambuc data = malloc(largest);
88*433d6423SLionel Sambuc if (data == NULL) e(1000);
89*433d6423SLionel Sambuc
90*433d6423SLionel Sambuc srand(1);
91*433d6423SLionel Sambuc
92*433d6423SLionel Sambuc for (i = 0; i < largest; i++)
93*433d6423SLionel Sambuc data[i] = (unsigned char) (rand() % 255 + 1);
94*433d6423SLionel Sambuc }
95*433d6423SLionel Sambuc
96*433d6423SLionel Sambuc void all_sizes(call)
97*433d6423SLionel Sambuc void(*call) (off_t osize, off_t nsize);
98*433d6423SLionel Sambuc {
99*433d6423SLionel Sambuc int i, j;
100*433d6423SLionel Sambuc
101*433d6423SLionel Sambuc for (i = 0; i < sizeof(sizes) / sizeof(sizes[0]); i++)
102*433d6423SLionel Sambuc for (j = 0; j < sizeof(sizes) / sizeof(sizes[0]); j++)
103*433d6423SLionel Sambuc call(sizes[i], sizes[j]);
104*433d6423SLionel Sambuc }
105*433d6423SLionel Sambuc
make_file(size)106*433d6423SLionel Sambuc int make_file(size)
107*433d6423SLionel Sambuc off_t size;
108*433d6423SLionel Sambuc {
109*433d6423SLionel Sambuc off_t off;
110*433d6423SLionel Sambuc int fd, r;
111*433d6423SLionel Sambuc
112*433d6423SLionel Sambuc if ((fd = open(TESTFILE, O_RDWR|O_CREAT|O_EXCL, 0600)) < 0) e(1001);
113*433d6423SLionel Sambuc
114*433d6423SLionel Sambuc off = 0;
115*433d6423SLionel Sambuc while (off < size) {
116*433d6423SLionel Sambuc r = write(fd, data + off, size - off);
117*433d6423SLionel Sambuc
118*433d6423SLionel Sambuc if (r != size - off) e(1002);
119*433d6423SLionel Sambuc
120*433d6423SLionel Sambuc off += r;
121*433d6423SLionel Sambuc }
122*433d6423SLionel Sambuc
123*433d6423SLionel Sambuc return fd;
124*433d6423SLionel Sambuc }
125*433d6423SLionel Sambuc
check_file(fd,hole_start,hole_end,size)126*433d6423SLionel Sambuc void check_file(fd, hole_start, hole_end, size)
127*433d6423SLionel Sambuc int fd;
128*433d6423SLionel Sambuc off_t hole_start;
129*433d6423SLionel Sambuc off_t hole_end;
130*433d6423SLionel Sambuc off_t size;
131*433d6423SLionel Sambuc {
132*433d6423SLionel Sambuc static unsigned char buf[16384];
133*433d6423SLionel Sambuc struct stat statbuf;
134*433d6423SLionel Sambuc off_t off;
135*433d6423SLionel Sambuc int i, chunk;
136*433d6423SLionel Sambuc
137*433d6423SLionel Sambuc /* The size must match. */
138*433d6423SLionel Sambuc if (fstat(fd, &statbuf) != 0) e(1003);
139*433d6423SLionel Sambuc if (statbuf.st_size != size) e(1004);
140*433d6423SLionel Sambuc
141*433d6423SLionel Sambuc if (lseek(fd, 0L, SEEK_SET) != 0L) e(1005);
142*433d6423SLionel Sambuc
143*433d6423SLionel Sambuc /* All bytes in the file must be equal to what we wrote, except for the bytes
144*433d6423SLionel Sambuc * in the hole, which must be zero.
145*433d6423SLionel Sambuc */
146*433d6423SLionel Sambuc for (off = 0; off < size; off += chunk) {
147*433d6423SLionel Sambuc chunk = MIN(sizeof(buf), size - off);
148*433d6423SLionel Sambuc
149*433d6423SLionel Sambuc if (read(fd, buf, chunk) != chunk) e(1006);
150*433d6423SLionel Sambuc
151*433d6423SLionel Sambuc for (i = 0; i < chunk; i++) {
152*433d6423SLionel Sambuc if (off + i >= hole_start && off + i < hole_end) {
153*433d6423SLionel Sambuc if (buf[i] != 0) e(1007);
154*433d6423SLionel Sambuc }
155*433d6423SLionel Sambuc else {
156*433d6423SLionel Sambuc if (buf[i] != data[off+i]) e(1008);
157*433d6423SLionel Sambuc }
158*433d6423SLionel Sambuc }
159*433d6423SLionel Sambuc }
160*433d6423SLionel Sambuc
161*433d6423SLionel Sambuc /* We must get back EOF at the end. */
162*433d6423SLionel Sambuc if (read(fd, buf, sizeof(buf)) != 0) e(1009);
163*433d6423SLionel Sambuc }
164*433d6423SLionel Sambuc
test50a()165*433d6423SLionel Sambuc void test50a()
166*433d6423SLionel Sambuc {
167*433d6423SLionel Sambuc struct stat statbuf;
168*433d6423SLionel Sambuc int fd;
169*433d6423SLionel Sambuc
170*433d6423SLionel Sambuc subtest = 1;
171*433d6423SLionel Sambuc
172*433d6423SLionel Sambuc if ((fd = open(TESTFILE, O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0) e(1);
173*433d6423SLionel Sambuc
174*433d6423SLionel Sambuc if (write(fd, data, TESTSIZE) != TESTSIZE) e(2);
175*433d6423SLionel Sambuc
176*433d6423SLionel Sambuc /* Negative sizes should result in EINVAL. */
177*433d6423SLionel Sambuc if (truncate(TESTFILE, -1) != -1) e(3);
178*433d6423SLionel Sambuc if (errno != EINVAL) e(4);
179*433d6423SLionel Sambuc
180*433d6423SLionel Sambuc /* Make sure the file size did not change. */
181*433d6423SLionel Sambuc if (fstat(fd, &statbuf) != 0) e(5);
182*433d6423SLionel Sambuc if (statbuf.st_size != TESTSIZE) e(6);
183*433d6423SLionel Sambuc
184*433d6423SLionel Sambuc close(fd);
185*433d6423SLionel Sambuc if (unlink(TESTFILE) != 0) e(7);
186*433d6423SLionel Sambuc
187*433d6423SLionel Sambuc /* An empty path should result in ENOENT. */
188*433d6423SLionel Sambuc if (truncate("", 0) != -1) e(8);
189*433d6423SLionel Sambuc if (errno != ENOENT) e(9);
190*433d6423SLionel Sambuc
191*433d6423SLionel Sambuc /* A non-existing file name should result in ENOENT. */
192*433d6423SLionel Sambuc if (truncate(TESTFILE"2", 0) != -1) e(10);
193*433d6423SLionel Sambuc if (errno != ENOENT) e(11);
194*433d6423SLionel Sambuc }
195*433d6423SLionel Sambuc
test50b()196*433d6423SLionel Sambuc void test50b()
197*433d6423SLionel Sambuc {
198*433d6423SLionel Sambuc struct stat statbuf;
199*433d6423SLionel Sambuc int fd;
200*433d6423SLionel Sambuc
201*433d6423SLionel Sambuc subtest = 2;
202*433d6423SLionel Sambuc
203*433d6423SLionel Sambuc if ((fd = open(TESTFILE, O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0) e(1);
204*433d6423SLionel Sambuc
205*433d6423SLionel Sambuc if (write(fd, data, TESTSIZE) != TESTSIZE) e(2);
206*433d6423SLionel Sambuc
207*433d6423SLionel Sambuc /* Negative sizes should result in EINVAL. */
208*433d6423SLionel Sambuc if (ftruncate(fd, -1) != -1) e(3);
209*433d6423SLionel Sambuc if (errno != EINVAL) e(4);
210*433d6423SLionel Sambuc
211*433d6423SLionel Sambuc /* Make sure the file size did not change. */
212*433d6423SLionel Sambuc if (fstat(fd, &statbuf) != 0) e(5);
213*433d6423SLionel Sambuc if (statbuf.st_size != TESTSIZE) e(6);
214*433d6423SLionel Sambuc
215*433d6423SLionel Sambuc close(fd);
216*433d6423SLionel Sambuc
217*433d6423SLionel Sambuc /* Calls on an invalid file descriptor should return EBADF or EINVAL. */
218*433d6423SLionel Sambuc if (ftruncate(fd, 0) != -1) e(7);
219*433d6423SLionel Sambuc if (errno != EBADF && errno != EINVAL) e(8);
220*433d6423SLionel Sambuc
221*433d6423SLionel Sambuc if ((fd = open(TESTFILE, O_RDONLY)) < 0) e(9);
222*433d6423SLionel Sambuc
223*433d6423SLionel Sambuc /* Calls on a file opened read-only should return EBADF or EINVAL. */
224*433d6423SLionel Sambuc if (ftruncate(fd, 0) != -1) e(10);
225*433d6423SLionel Sambuc if (errno != EBADF && errno != EINVAL) e(11);
226*433d6423SLionel Sambuc
227*433d6423SLionel Sambuc close(fd);
228*433d6423SLionel Sambuc
229*433d6423SLionel Sambuc if (unlink(TESTFILE) != 0) e(12);
230*433d6423SLionel Sambuc }
231*433d6423SLionel Sambuc
test50c()232*433d6423SLionel Sambuc void test50c()
233*433d6423SLionel Sambuc {
234*433d6423SLionel Sambuc struct stat statbuf;
235*433d6423SLionel Sambuc struct flock flock;
236*433d6423SLionel Sambuc off_t off;
237*433d6423SLionel Sambuc int fd;
238*433d6423SLionel Sambuc
239*433d6423SLionel Sambuc subtest = 3;
240*433d6423SLionel Sambuc
241*433d6423SLionel Sambuc if ((fd = open(TESTFILE, O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0) e(1);
242*433d6423SLionel Sambuc
243*433d6423SLionel Sambuc if (write(fd, data, TESTSIZE) != TESTSIZE) e(2);
244*433d6423SLionel Sambuc
245*433d6423SLionel Sambuc off = TESTSIZE / 2;
246*433d6423SLionel Sambuc if (lseek(fd, off, SEEK_SET) != off) e(3);
247*433d6423SLionel Sambuc
248*433d6423SLionel Sambuc flock.l_len = 0;
249*433d6423SLionel Sambuc
250*433d6423SLionel Sambuc /* Negative sizes should result in EINVAL. */
251*433d6423SLionel Sambuc flock.l_whence = SEEK_SET;
252*433d6423SLionel Sambuc flock.l_start = -1;
253*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != -1) e(4);
254*433d6423SLionel Sambuc if (errno != EINVAL) e(5);
255*433d6423SLionel Sambuc
256*433d6423SLionel Sambuc flock.l_whence = SEEK_CUR;
257*433d6423SLionel Sambuc flock.l_start = -off - 1;
258*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != -1) e(6);
259*433d6423SLionel Sambuc if (errno != EINVAL) e(7);
260*433d6423SLionel Sambuc
261*433d6423SLionel Sambuc flock.l_whence = SEEK_END;
262*433d6423SLionel Sambuc flock.l_start = -TESTSIZE - 1;
263*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != -1) e(8);
264*433d6423SLionel Sambuc if (errno != EINVAL) e(9);
265*433d6423SLionel Sambuc
266*433d6423SLionel Sambuc /* Make sure the file size did not change. */
267*433d6423SLionel Sambuc if (fstat(fd, &statbuf) != 0) e(10);
268*433d6423SLionel Sambuc if (statbuf.st_size != TESTSIZE) e(11);
269*433d6423SLionel Sambuc
270*433d6423SLionel Sambuc /* Proper negative values should work, however. */
271*433d6423SLionel Sambuc flock.l_whence = SEEK_CUR;
272*433d6423SLionel Sambuc flock.l_start = -1;
273*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != 0) e(12);
274*433d6423SLionel Sambuc
275*433d6423SLionel Sambuc if (fstat(fd, &statbuf) != 0) e(13);
276*433d6423SLionel Sambuc if (statbuf.st_size != off - 1) e(14);
277*433d6423SLionel Sambuc
278*433d6423SLionel Sambuc flock.l_whence = SEEK_END;
279*433d6423SLionel Sambuc flock.l_start = -off + 1;
280*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != 0) e(15);
281*433d6423SLionel Sambuc
282*433d6423SLionel Sambuc if (fstat(fd, &statbuf) != 0) e(16);
283*433d6423SLionel Sambuc if (statbuf.st_size != 0L) e(17);
284*433d6423SLionel Sambuc
285*433d6423SLionel Sambuc close(fd);
286*433d6423SLionel Sambuc
287*433d6423SLionel Sambuc /* Calls on an invalid file descriptor should return EBADF or EINVAL. */
288*433d6423SLionel Sambuc flock.l_whence = SEEK_SET;
289*433d6423SLionel Sambuc flock.l_start = 0;
290*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != -1) e(18);
291*433d6423SLionel Sambuc if (errno != EBADF && errno != EINVAL) e(19);
292*433d6423SLionel Sambuc
293*433d6423SLionel Sambuc if ((fd = open(TESTFILE, O_RDONLY)) < 0) e(20);
294*433d6423SLionel Sambuc
295*433d6423SLionel Sambuc /* Calls on a file opened read-only should return EBADF or EINVAL. */
296*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != -1) e(21);
297*433d6423SLionel Sambuc if (errno != EBADF && errno != EINVAL) e(22);
298*433d6423SLionel Sambuc
299*433d6423SLionel Sambuc close(fd);
300*433d6423SLionel Sambuc
301*433d6423SLionel Sambuc if (unlink(TESTFILE) != 0) e(23);
302*433d6423SLionel Sambuc }
303*433d6423SLionel Sambuc
test50d()304*433d6423SLionel Sambuc void test50d()
305*433d6423SLionel Sambuc {
306*433d6423SLionel Sambuc struct stat statbuf;
307*433d6423SLionel Sambuc struct flock flock;
308*433d6423SLionel Sambuc off_t off;
309*433d6423SLionel Sambuc int fd;
310*433d6423SLionel Sambuc
311*433d6423SLionel Sambuc subtest = 4;
312*433d6423SLionel Sambuc
313*433d6423SLionel Sambuc if ((fd = open(TESTFILE, O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0) e(1);
314*433d6423SLionel Sambuc
315*433d6423SLionel Sambuc if (write(fd, data, TESTSIZE) != TESTSIZE) e(2);
316*433d6423SLionel Sambuc
317*433d6423SLionel Sambuc off = TESTSIZE / 2;
318*433d6423SLionel Sambuc if (lseek(fd, off, SEEK_SET) != off) e(3);
319*433d6423SLionel Sambuc
320*433d6423SLionel Sambuc /* The given length must be positive. */
321*433d6423SLionel Sambuc flock.l_whence = SEEK_CUR;
322*433d6423SLionel Sambuc flock.l_start = 0;
323*433d6423SLionel Sambuc flock.l_len = -1;
324*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != -1) e(4);
325*433d6423SLionel Sambuc if (errno != EINVAL) e(5);
326*433d6423SLionel Sambuc
327*433d6423SLionel Sambuc /* Negative start positions are not allowed. */
328*433d6423SLionel Sambuc flock.l_whence = SEEK_SET;
329*433d6423SLionel Sambuc flock.l_start = -1;
330*433d6423SLionel Sambuc flock.l_len = 1;
331*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != -1) e(6);
332*433d6423SLionel Sambuc if (errno != EINVAL) e(7);
333*433d6423SLionel Sambuc
334*433d6423SLionel Sambuc flock.l_whence = SEEK_CUR;
335*433d6423SLionel Sambuc flock.l_start = -off - 1;
336*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != -1) e(8);
337*433d6423SLionel Sambuc if (errno != EINVAL) e(9);
338*433d6423SLionel Sambuc
339*433d6423SLionel Sambuc flock.l_whence = SEEK_END;
340*433d6423SLionel Sambuc flock.l_start = -TESTSIZE - 1;
341*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != -1) e(10);
342*433d6423SLionel Sambuc if (errno != EINVAL) e(11);
343*433d6423SLionel Sambuc
344*433d6423SLionel Sambuc /* Start positions at or beyond the end of the file are no good, either. */
345*433d6423SLionel Sambuc flock.l_whence = SEEK_SET;
346*433d6423SLionel Sambuc flock.l_start = TESTSIZE;
347*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != -1) e(12);
348*433d6423SLionel Sambuc if (errno != EINVAL) e(13);
349*433d6423SLionel Sambuc
350*433d6423SLionel Sambuc flock.l_start = TESTSIZE + 1;
351*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != -1) e(13);
352*433d6423SLionel Sambuc if (errno != EINVAL) e(14);
353*433d6423SLionel Sambuc
354*433d6423SLionel Sambuc flock.l_whence = SEEK_CUR;
355*433d6423SLionel Sambuc flock.l_start = TESTSIZE - off;
356*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != -1) e(15);
357*433d6423SLionel Sambuc if (errno != EINVAL) e(16);
358*433d6423SLionel Sambuc
359*433d6423SLionel Sambuc flock.l_whence = SEEK_END;
360*433d6423SLionel Sambuc flock.l_start = 1;
361*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != -1) e(17);
362*433d6423SLionel Sambuc if (errno != EINVAL) e(18);
363*433d6423SLionel Sambuc
364*433d6423SLionel Sambuc /* End positions beyond the end of the file may be silently bounded. */
365*433d6423SLionel Sambuc flock.l_whence = SEEK_SET;
366*433d6423SLionel Sambuc flock.l_start = 0;
367*433d6423SLionel Sambuc flock.l_len = TESTSIZE + 1;
368*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != 0) e(19);
369*433d6423SLionel Sambuc
370*433d6423SLionel Sambuc flock.l_whence = SEEK_CUR;
371*433d6423SLionel Sambuc flock.l_len = TESTSIZE - off + 1;
372*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != 0) e(20);
373*433d6423SLionel Sambuc
374*433d6423SLionel Sambuc flock.l_whence = SEEK_END;
375*433d6423SLionel Sambuc flock.l_start = -1;
376*433d6423SLionel Sambuc flock.l_len = 2;
377*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != 0) e(21);
378*433d6423SLionel Sambuc
379*433d6423SLionel Sambuc /* However, this must never cause the file size to change. */
380*433d6423SLionel Sambuc if (fstat(fd, &statbuf) != 0) e(22);
381*433d6423SLionel Sambuc if (statbuf.st_size != TESTSIZE) e(23);
382*433d6423SLionel Sambuc
383*433d6423SLionel Sambuc close(fd);
384*433d6423SLionel Sambuc
385*433d6423SLionel Sambuc /* Calls on an invalid file descriptor should return EBADF or EINVAL. */
386*433d6423SLionel Sambuc flock.l_whence = SEEK_SET;
387*433d6423SLionel Sambuc flock.l_start = 0;
388*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != -1) e(24);
389*433d6423SLionel Sambuc if (errno != EBADF && errno != EINVAL) e(25);
390*433d6423SLionel Sambuc
391*433d6423SLionel Sambuc if ((fd = open(TESTFILE, O_RDONLY)) < 0) e(26);
392*433d6423SLionel Sambuc
393*433d6423SLionel Sambuc /* Calls on a file opened read-only should return EBADF or EINVAL. */
394*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != -1) e(27);
395*433d6423SLionel Sambuc if (errno != EBADF && errno != EINVAL) e(28);
396*433d6423SLionel Sambuc
397*433d6423SLionel Sambuc close(fd);
398*433d6423SLionel Sambuc
399*433d6423SLionel Sambuc if (unlink(TESTFILE) != 0) e(29);
400*433d6423SLionel Sambuc }
401*433d6423SLionel Sambuc
sub50e(osize,nsize)402*433d6423SLionel Sambuc void sub50e(osize, nsize)
403*433d6423SLionel Sambuc off_t osize;
404*433d6423SLionel Sambuc off_t nsize;
405*433d6423SLionel Sambuc {
406*433d6423SLionel Sambuc int fd;
407*433d6423SLionel Sambuc
408*433d6423SLionel Sambuc fd = make_file(osize);
409*433d6423SLionel Sambuc
410*433d6423SLionel Sambuc if (truncate(TESTFILE, nsize) != 0) e(1);
411*433d6423SLionel Sambuc
412*433d6423SLionel Sambuc check_file(fd, osize, nsize, nsize);
413*433d6423SLionel Sambuc
414*433d6423SLionel Sambuc if (nsize < osize) {
415*433d6423SLionel Sambuc if (truncate(TESTFILE, osize) != 0) e(2);
416*433d6423SLionel Sambuc
417*433d6423SLionel Sambuc check_file(fd, nsize, osize, osize);
418*433d6423SLionel Sambuc }
419*433d6423SLionel Sambuc
420*433d6423SLionel Sambuc close(fd);
421*433d6423SLionel Sambuc
422*433d6423SLionel Sambuc if (unlink(TESTFILE) != 0) e(3);
423*433d6423SLionel Sambuc
424*433d6423SLionel Sambuc }
425*433d6423SLionel Sambuc
test50e()426*433d6423SLionel Sambuc void test50e()
427*433d6423SLionel Sambuc {
428*433d6423SLionel Sambuc subtest = 5;
429*433d6423SLionel Sambuc
430*433d6423SLionel Sambuc /* truncate(2) on a file that is open. */
431*433d6423SLionel Sambuc all_sizes(sub50e);
432*433d6423SLionel Sambuc }
433*433d6423SLionel Sambuc
sub50f(osize,nsize)434*433d6423SLionel Sambuc void sub50f(osize, nsize)
435*433d6423SLionel Sambuc off_t osize;
436*433d6423SLionel Sambuc off_t nsize;
437*433d6423SLionel Sambuc {
438*433d6423SLionel Sambuc int fd;
439*433d6423SLionel Sambuc
440*433d6423SLionel Sambuc fd = make_file(osize);
441*433d6423SLionel Sambuc
442*433d6423SLionel Sambuc close(fd);
443*433d6423SLionel Sambuc
444*433d6423SLionel Sambuc if (truncate(TESTFILE, nsize) != 0) e(1);
445*433d6423SLionel Sambuc
446*433d6423SLionel Sambuc if ((fd = open(TESTFILE, O_RDONLY)) < 0) e(2);
447*433d6423SLionel Sambuc
448*433d6423SLionel Sambuc check_file(fd, osize, nsize, nsize);
449*433d6423SLionel Sambuc
450*433d6423SLionel Sambuc if (nsize < osize) {
451*433d6423SLionel Sambuc close(fd);
452*433d6423SLionel Sambuc
453*433d6423SLionel Sambuc if (truncate(TESTFILE, osize) != 0) e(3);
454*433d6423SLionel Sambuc
455*433d6423SLionel Sambuc if ((fd = open(TESTFILE, O_RDONLY)) < 0) e(4);
456*433d6423SLionel Sambuc
457*433d6423SLionel Sambuc check_file(fd, nsize, osize, osize);
458*433d6423SLionel Sambuc }
459*433d6423SLionel Sambuc
460*433d6423SLionel Sambuc close(fd);
461*433d6423SLionel Sambuc
462*433d6423SLionel Sambuc if (unlink(TESTFILE) != 0) e(5);
463*433d6423SLionel Sambuc }
464*433d6423SLionel Sambuc
test50f()465*433d6423SLionel Sambuc void test50f()
466*433d6423SLionel Sambuc {
467*433d6423SLionel Sambuc subtest = 6;
468*433d6423SLionel Sambuc
469*433d6423SLionel Sambuc /* truncate(2) on a file that is not open. */
470*433d6423SLionel Sambuc all_sizes(sub50f);
471*433d6423SLionel Sambuc }
472*433d6423SLionel Sambuc
sub50g(osize,nsize)473*433d6423SLionel Sambuc void sub50g(osize, nsize)
474*433d6423SLionel Sambuc off_t osize;
475*433d6423SLionel Sambuc off_t nsize;
476*433d6423SLionel Sambuc {
477*433d6423SLionel Sambuc int fd;
478*433d6423SLionel Sambuc
479*433d6423SLionel Sambuc fd = make_file(osize);
480*433d6423SLionel Sambuc
481*433d6423SLionel Sambuc if (ftruncate(fd, nsize) != 0) e(1);
482*433d6423SLionel Sambuc
483*433d6423SLionel Sambuc check_file(fd, osize, nsize, nsize);
484*433d6423SLionel Sambuc
485*433d6423SLionel Sambuc if (nsize < osize) {
486*433d6423SLionel Sambuc if (ftruncate(fd, osize) != 0) e(2);
487*433d6423SLionel Sambuc
488*433d6423SLionel Sambuc check_file(fd, nsize, osize, osize);
489*433d6423SLionel Sambuc }
490*433d6423SLionel Sambuc
491*433d6423SLionel Sambuc close(fd);
492*433d6423SLionel Sambuc
493*433d6423SLionel Sambuc if (unlink(TESTFILE) != 0) e(3);
494*433d6423SLionel Sambuc }
495*433d6423SLionel Sambuc
test50g()496*433d6423SLionel Sambuc void test50g()
497*433d6423SLionel Sambuc {
498*433d6423SLionel Sambuc subtest = 7;
499*433d6423SLionel Sambuc
500*433d6423SLionel Sambuc /* ftruncate(2) on an open file. */
501*433d6423SLionel Sambuc all_sizes(sub50g);
502*433d6423SLionel Sambuc }
503*433d6423SLionel Sambuc
sub50h(osize,nsize)504*433d6423SLionel Sambuc void sub50h(osize, nsize)
505*433d6423SLionel Sambuc off_t osize;
506*433d6423SLionel Sambuc off_t nsize;
507*433d6423SLionel Sambuc {
508*433d6423SLionel Sambuc struct flock flock;
509*433d6423SLionel Sambuc int fd;
510*433d6423SLionel Sambuc
511*433d6423SLionel Sambuc fd = make_file(osize);
512*433d6423SLionel Sambuc
513*433d6423SLionel Sambuc flock.l_whence = SEEK_SET;
514*433d6423SLionel Sambuc flock.l_start = nsize;
515*433d6423SLionel Sambuc flock.l_len = 0;
516*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != 0) e(1);
517*433d6423SLionel Sambuc
518*433d6423SLionel Sambuc check_file(fd, osize, nsize, nsize);
519*433d6423SLionel Sambuc
520*433d6423SLionel Sambuc if (nsize < osize) {
521*433d6423SLionel Sambuc flock.l_whence = SEEK_SET;
522*433d6423SLionel Sambuc flock.l_start = osize;
523*433d6423SLionel Sambuc flock.l_len = 0;
524*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != 0) e(2);
525*433d6423SLionel Sambuc
526*433d6423SLionel Sambuc check_file(fd, nsize, osize, osize);
527*433d6423SLionel Sambuc }
528*433d6423SLionel Sambuc
529*433d6423SLionel Sambuc close(fd);
530*433d6423SLionel Sambuc
531*433d6423SLionel Sambuc if (unlink(TESTFILE) != 0) e(3);
532*433d6423SLionel Sambuc }
533*433d6423SLionel Sambuc
test50h()534*433d6423SLionel Sambuc void test50h()
535*433d6423SLionel Sambuc {
536*433d6423SLionel Sambuc subtest = 8;
537*433d6423SLionel Sambuc
538*433d6423SLionel Sambuc /* fcntl(2) with F_FREESP and l_len=0. */
539*433d6423SLionel Sambuc all_sizes(sub50h);
540*433d6423SLionel Sambuc }
541*433d6423SLionel Sambuc
sub50i(size,off,len,type)542*433d6423SLionel Sambuc void sub50i(size, off, len, type)
543*433d6423SLionel Sambuc off_t size;
544*433d6423SLionel Sambuc off_t off;
545*433d6423SLionel Sambuc size_t len;
546*433d6423SLionel Sambuc int type;
547*433d6423SLionel Sambuc {
548*433d6423SLionel Sambuc struct flock flock;
549*433d6423SLionel Sambuc int fd;
550*433d6423SLionel Sambuc
551*433d6423SLionel Sambuc fd = make_file(size);
552*433d6423SLionel Sambuc
553*433d6423SLionel Sambuc switch (type) {
554*433d6423SLionel Sambuc case 0:
555*433d6423SLionel Sambuc flock.l_whence = SEEK_SET;
556*433d6423SLionel Sambuc flock.l_start = off;
557*433d6423SLionel Sambuc break;
558*433d6423SLionel Sambuc case 1:
559*433d6423SLionel Sambuc if (lseek(fd, off, SEEK_SET) != off) e(1);
560*433d6423SLionel Sambuc flock.l_whence = SEEK_CUR;
561*433d6423SLionel Sambuc flock.l_start = 0;
562*433d6423SLionel Sambuc break;
563*433d6423SLionel Sambuc case 2:
564*433d6423SLionel Sambuc flock.l_whence = SEEK_END;
565*433d6423SLionel Sambuc flock.l_start = off - size;
566*433d6423SLionel Sambuc break;
567*433d6423SLionel Sambuc default:
568*433d6423SLionel Sambuc e(1);
569*433d6423SLionel Sambuc }
570*433d6423SLionel Sambuc
571*433d6423SLionel Sambuc flock.l_len = len;
572*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != 0) e(2);
573*433d6423SLionel Sambuc
574*433d6423SLionel Sambuc check_file(fd, off, off + len, size);
575*433d6423SLionel Sambuc
576*433d6423SLionel Sambuc /* Repeat the call in order to see whether the file system can handle holes
577*433d6423SLionel Sambuc * while freeing up. If not, the server would typically crash; we need not
578*433d6423SLionel Sambuc * check the results again.
579*433d6423SLionel Sambuc */
580*433d6423SLionel Sambuc flock.l_whence = SEEK_SET;
581*433d6423SLionel Sambuc flock.l_start = off;
582*433d6423SLionel Sambuc if (fcntl(fd, F_FREESP, &flock) != 0) e(3);
583*433d6423SLionel Sambuc
584*433d6423SLionel Sambuc close(fd);
585*433d6423SLionel Sambuc
586*433d6423SLionel Sambuc if (unlink(TESTFILE) != 0) e(4);
587*433d6423SLionel Sambuc }
588*433d6423SLionel Sambuc
test50i()589*433d6423SLionel Sambuc void test50i()
590*433d6423SLionel Sambuc {
591*433d6423SLionel Sambuc off_t off;
592*433d6423SLionel Sambuc int i, j, k, l;
593*433d6423SLionel Sambuc
594*433d6423SLionel Sambuc subtest = 9;
595*433d6423SLionel Sambuc
596*433d6423SLionel Sambuc /* fcntl(2) with F_FREESP and l_len>0. */
597*433d6423SLionel Sambuc
598*433d6423SLionel Sambuc /* This loop determines the size of the test file. */
599*433d6423SLionel Sambuc for (i = 0; i < sizeof(sizes) / sizeof(sizes[0]); i++) {
600*433d6423SLionel Sambuc /* Big files simply take too long. We have to compromise here. */
601*433d6423SLionel Sambuc if (sizes[i] >= THRESHOLD) continue;
602*433d6423SLionel Sambuc
603*433d6423SLionel Sambuc /* This loop determines one of the two values for the offset. */
604*433d6423SLionel Sambuc for (j = 0; j < sizeof(sizes) / sizeof(sizes[0]); j++) {
605*433d6423SLionel Sambuc if (sizes[j] >= sizes[i]) continue;
606*433d6423SLionel Sambuc
607*433d6423SLionel Sambuc /* This loop determines the other. */
608*433d6423SLionel Sambuc for (k = 0; k < sizeof(sizes) / sizeof(sizes[0]); k++) {
609*433d6423SLionel Sambuc if (sizes[k] > sizes[j]) continue;
610*433d6423SLionel Sambuc
611*433d6423SLionel Sambuc /* Construct an offset by adding the two sizes. */
612*433d6423SLionel Sambuc off = sizes[j] + sizes[k];
613*433d6423SLionel Sambuc
614*433d6423SLionel Sambuc if (j + 1 < sizeof(sizes) / sizeof(sizes[0]) &&
615*433d6423SLionel Sambuc off >= sizes[j + 1]) continue;
616*433d6423SLionel Sambuc
617*433d6423SLionel Sambuc /* This loop determines the length of the hole. */
618*433d6423SLionel Sambuc for (l = 0; l < sizeof(sizes) / sizeof(sizes[0]); l++) {
619*433d6423SLionel Sambuc if (sizes[l] == 0 || off + sizes[l] > sizes[i])
620*433d6423SLionel Sambuc continue;
621*433d6423SLionel Sambuc
622*433d6423SLionel Sambuc /* This could have been a loop, too! */
623*433d6423SLionel Sambuc sub50i(sizes[i], off, sizes[l], 0);
624*433d6423SLionel Sambuc sub50i(sizes[i], off, sizes[l], 1);
625*433d6423SLionel Sambuc sub50i(sizes[i], off, sizes[l], 2);
626*433d6423SLionel Sambuc }
627*433d6423SLionel Sambuc }
628*433d6423SLionel Sambuc }
629*433d6423SLionel Sambuc }
630*433d6423SLionel Sambuc }
631