Make test3 fail on the first error.
[minix.git] / test / test25.c
blob01a81dcb91b0173e8d8c4a833dfdf1b70a118009
1 /* test25: open (), close () (p) Jan-Mark Wams. email: jms@cs.vu.nl */
3 /* Not tested: O_NONBLOCK on special files, supporting it.
4 ** On a read-only file system, some error reports are to be expected.
5 */
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <sys/wait.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <string.h>
13 #include <fcntl.h>
14 #include <limits.h>
15 #include <errno.h>
16 #include <time.h>
17 #include <stdio.h>
19 #define MAX_ERROR 4
20 #define ITERATIONS 2
22 #include "common.c"
24 #define System(cmd) if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
25 #define Chdir(dir) if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
26 #define Stat(a,b) if (stat(a,b) != 0) printf("Can't stat %s\n", a)
27 #define Creat(f) if (close(creat(f,0777))!=0) printf("Can't creat %s\n",f)
28 #define Report(s,n) printf("Subtest %d" s,subtest,(n))
30 int subtest = 1;
31 int superuser;
32 char *MaxName; /* Name of maximum length */
33 char MaxPath[PATH_MAX]; /* Same for path */
34 char *ToLongName; /* Name of maximum +1 length */
35 char ToLongPath[PATH_MAX + 1]; /* Same for path, both too long */
37 void test25a(void);
38 void test25b(void);
39 void test25c(void);
40 void test25d(void);
41 void test25e(void);
42 void makelongnames(void);
44 int main(int argc, char *argv[])
46 int i, m = 0xFFFF;
48 sync();
50 start(25);
51 if (argc == 2) m = atoi(argv[1]);
52 makelongnames();
53 superuser = (geteuid() == 0);
55 /* Close all files, the parent might have opened. */
56 for (i = 3; i < 100; i++) close(i);
58 for (i = 0; i < ITERATIONS; i++) {
59 if (m & 001) test25a();
60 if (m & 002) test25b();
61 if (m & 004) test25c();
62 if (m & 010) test25d();
63 if (m & 020) test25e();
65 quit();
67 return(-1); /* Unreachable */
70 void test25a()
71 { /* Test fcntl flags. */
72 subtest = 1;
74 #define EXCLUDE(a,b) (((a)^(b)) == ((a)|(b)))
75 #define ADDIT (O_APPEND | O_CREAT | O_EXCL | O_NONBLOCK | O_TRUNC)
77 /* If this compiles all flags are defined but they have to be or-able. */
78 if (!(EXCLUDE(O_NONBLOCK, O_TRUNC))) e(1);
79 if (!(EXCLUDE(O_EXCL, O_NONBLOCK | O_TRUNC))) e(2);
80 if (!(EXCLUDE(O_CREAT, O_EXCL | O_NONBLOCK | O_TRUNC))) e(3);
81 if (!(EXCLUDE(O_APPEND, O_CREAT | O_EXCL | O_NONBLOCK | O_TRUNC))) e(4);
82 if (!(EXCLUDE(O_RDONLY, ADDIT))) e(5);
83 if (!(EXCLUDE(O_WRONLY, ADDIT))) e(6);
84 if (!(EXCLUDE(O_RDWR, ADDIT))) e(7);
87 void test25b()
88 { /* Test normal operation. */
90 #define BUF_SIZE 1024
92 int fd1, fd2, fd3, fd4, fd5;
93 char buf[BUF_SIZE];
94 struct stat st1, st2, st3;
95 time_t time1, time2;
96 int stat_loc;
98 subtest = 2;
100 System("rm -rf ../DIR_25/*");
102 System("echo Hello > he"); /* make test files */
103 System("echo Hello > ha"); /* size 6 bytes */
104 System("echo Hello > hi");
105 System("echo Hello > ho");
107 /* Check path resolution. Check if lowest fds are returned */
108 if ((fd1 = open("he", O_RDONLY)) != 3) e(1);
109 if (read(fd1, buf, BUF_SIZE) != 6) e(2);
110 if ((fd2 = open("./ha", O_RDONLY)) != 4) e(3);
111 if ((fd3 = open("../DIR_25/he", O_RDWR)) != 5) e(4);
112 if ((fd4 = open("ho", O_WRONLY)) != 6) e(5);
113 if (close(fd4) != 0) e(6);
114 if (close(fd1) != 0) e(7);
115 if ((fd1 = open("./././ho", O_RDWR)) != 3) e(8);
116 if ((fd4 = open("../DIR_25/he", O_RDONLY)) != 6) e(9);
117 if (close(fd2) != 0) e(10);
118 if (close(fd3) != 0) e(11);
119 if ((fd2 = open("ha", O_RDONLY)) != 4) e(12);
120 if ((fd3 = open("/etc/passwd", O_RDONLY)) != 5) e(13);
121 if (close(fd4) != 0) e(14); /* close all */
122 if (close(fd1) != 0) e(15);
123 if (close(fd3) != 0) e(16);
125 /* Check if processes share fd2, and if they have independent new fds */
126 System("rm -rf /tmp/sema.25");
127 switch (fork()) {
128 case -1: printf("Can't fork\n"); break;
130 case 0:
131 if ((fd1 = open("he", O_WRONLY)) != 3) e(17);
132 if ((fd3 = open("../././DIR_25/ha", O_WRONLY)) != 5) e(18);
133 if ((fd4 = open("../DIR_25/hi", O_WRONLY)) != 6) e(19);
134 if ((fd5 = open("ho", O_WRONLY)) != 7) e(20);
135 system("while test ! -f /tmp/sema.25; do sleep 1; done"); /* parent */
136 if (read(fd2, buf, BUF_SIZE) != 3) e(21); /* gets Hel */
137 if (strncmp(buf, "lo\n", 3) != 0) e(22); /* we get lo */
138 if (close(fd1) != 0) e(23);
139 if (close(fd2) != 0) e(24);
140 if (close(fd3) != 0) e(25);
141 if (close(fd4) != 0) e(26);
142 if (close(fd5) != 0) e(27);
143 exit(0);
145 default:
146 if ((fd1 = open("ha", O_RDONLY)) != 3) e(28);
147 if ((fd3 = open("./he", O_RDONLY)) != 5) e(29);
148 if ((fd4 = open("../DIR_25/hi", O_RDWR)) != 6) e(30);
149 if ((fd5 = open("ho", O_WRONLY)) != 7) e(31);
150 if (close(fd1) != 0) e(32);
151 if (read(fd2, buf, 3) != 3) e(33); /* get Hel */
152 Creat("/tmp/sema.25");
153 if (strncmp(buf, "Hel", 3) != 0) e(34);
154 if (close(fd2) != 0) e(35);
155 if (close(fd3) != 0) e(36);
156 if (close(fd4) != 0) e(37);
157 if (close(fd5) != 0) e(38);
158 if (wait(&stat_loc) == -1) e(39);
159 if (stat_loc != 0) e(40);
161 System("rm -f /tmp/sema.25");
163 /* Check if the file status information is updated correctly */
164 Stat("hi", &st1); /* get info */
165 Stat("ha", &st2); /* of files */
166 time(&time1);
167 while (time1 >= time((time_t *)0))
168 ; /* wait a sec */
169 if ((fd1 = open("hi", O_RDONLY)) != 3) e(41); /* open files */
170 if ((fd2 = open("ha", O_WRONLY)) != 4) e(42);
171 if (read(fd1, buf, 1) != 1) e(43); /* read one */
172 if (close(fd1) != 0) e(44); /* close one */
173 Stat("hi", &st3); /* get info */
174 if (st1.st_uid != st3.st_uid) e(45);
175 if (st1.st_gid != st3.st_gid) e(46); /* should be same */
176 if (st1.st_mode != st3.st_mode) e(47);
177 if (st1.st_size != st3.st_size) e(48);
178 if (st1.st_nlink != st3.st_nlink) e(49);
179 if (st1.st_mtime != st3.st_mtime) e(50);
180 if (st1.st_ctime != st3.st_ctime) e(51);
181 #ifndef V1_FILESYSTEM
182 if (st1.st_atime >= st3.st_atime) e(52); /* except for atime. */
183 #endif
184 if (write(fd2, "Howdy\n", 6) != 6) e(53); /* Update c & mtime. */
185 if ((fd1 = open("ha", O_RDWR)) != 3) e(54);
186 if (read(fd1, buf, 6) != 6) e(55); /* Update atime. */
187 if (strncmp(buf, "Howdy\n", 6) != 0) e(56);
188 if (close(fd1) != 0) e(57);
189 Stat("ha", &st3);
190 if (st2.st_uid != st3.st_uid) e(58);
191 if (st2.st_gid != st3.st_gid) e(59); /* should be same */
192 if (st2.st_mode != st3.st_mode) e(60);
193 if (st2.st_nlink != st3.st_nlink) e(61);
194 if (st2.st_ctime >= st3.st_ctime) e(62);
195 #ifndef V1_FILESYSTEM
196 if (st2.st_atime >= st3.st_atime) e(63);
197 #endif
198 if (st2.st_mtime >= st3.st_mtime) e(64);
199 if (st2.st_size != st3.st_size) e(65);
200 if (close(fd2) != 0) e(66);
202 /* Let's see if RDONLY files are read only. */
203 if ((fd1 = open("hi", O_RDONLY)) != 3) e(67);
204 if (write(fd1, " again", 7) != -1) e(68); /* we can't write */
205 if (errno != EBADF) e(69); /* a read only fd */
206 if (read(fd1, buf, 7) != 6) e(70); /* but we can read */
207 if (close(fd1) != 0) e(71);
209 /* Let's see if WRONLY files are write only. */
210 if ((fd1 = open("hi", O_WRONLY)) != 3) e(72);
211 if (read(fd1, buf, 7) != -1) e(73); /* we can't read */
212 if (errno != EBADF) e(74); /* a write only fd */
213 if (write(fd1, "hELLO", 6) != 6) e(75); /* but we can write */
214 if (close(fd1) != 0) e(76);
216 /* Let's see if files are closable only once. */
217 if (close(fd1) != -1) e(77);
218 if (errno != EBADF) e(78);
220 /* Let's see how calling close() with bad fds is handled. */
221 if (close(10) != -1) e(79);
222 if (errno != EBADF) e(80);
223 if (close(111) != -1) e(81);
224 if (errno != EBADF) e(82);
225 if (close(-432) != -1) e(83);
226 if (errno != EBADF) e(84);
228 /* Let's see if RDWR files are read & write able. */
229 if ((fd1 = open("hi", O_RDWR)) != 3) e(85);
230 if (read(fd1, buf, 6) != 6) e(86); /* we can read */
231 if (strncmp(buf, "hELLO", 6) != 0) e(87); /* and we can write */
232 if (write(fd1, "Hello", 6) != 6) e(88); /* a read write fd */
233 if (close(fd1) != 0) e(89);
235 /* Check if APPENDed files are realy appended */
236 if ((fd1 = open("hi", O_RDWR | O_APPEND)) != 3) e(90); /* open hi */
238 /* An open should set the file offset to 0. */
239 if (lseek(fd1, (off_t) 0, SEEK_CUR) != 0) e(91);
241 /* Writing 0 bytes should not have an effect. */
242 if (write(fd1, "", 0) != 0) e(92);
243 if (lseek(fd1, (off_t) 0, SEEK_CUR) != 0) e(93); /* the end? */
245 /* A seek befor a wirte should not matter with O_APPEND. */
246 Stat("hi", &st1);
247 if (lseek(fd1, (off_t) - 3, SEEK_END) != st1.st_size - 3) e(94);
249 /* By writing 1 byte, we force the offset to the end of the file */
250 if (write(fd1, "1", 1) != 1) e(95);
251 Stat("hi", &st1);
252 if (lseek(fd1, (off_t) 0, SEEK_CUR) != st1.st_size) e(96);
253 if (write(fd1, "2", 1) != 1) e(97);
254 Stat("hi", &st1);
255 if (lseek(fd1, (off_t) 0, SEEK_CUR) != st1.st_size) e(98);
256 if (write(fd1, "3", 1) != 1) e(99);
257 Stat("hi", &st1);
258 if (lseek(fd1, (off_t) 0, SEEK_CUR) != st1.st_size) e(100);
259 if (lseek(fd1, (off_t) - 2, SEEK_CUR) <= 0) e(101);
260 if (write(fd1, "4", 1) != 1) e(102);
262 /* Since the mode was O_APPEND, the offset should be reset to EOF */
263 Stat("hi", &st1);
264 if (lseek(fd1, (off_t) 0, SEEK_CUR) != st1.st_size) e(103);
265 if (lseek(fd1, (off_t) - 4, SEEK_CUR) != st1.st_size - 4) e(104);
266 if (read(fd1, buf, BUF_SIZE) != 4) e(105);
267 if (strncmp(buf, "1234", 4) != 0) e(106);
268 if (close(fd1) != 0) e(107);
270 /* Check the effect of O_CREAT */
271 Stat("ho", &st1);
272 fd1 = open("ho", O_RDWR | O_CREAT, 0000);
273 if (fd1 != 3) e(108);
274 Stat("ho", &st2);
275 if (memcmp(&st1, &st2, sizeof(struct stat)) != 0) e(109);
276 if (read(fd1, buf, 6) != 6) e(110);
277 if (strncmp(buf, "Hello\n", 6) != 0) e(111);
278 if (write(fd1, "@", 1) != 1) e(112);
279 if (close(fd1) != 0) e(113);
280 (void) umask(0000);
281 fd1 = open("ho", O_RDWR | O_CREAT | O_EXCL, 0777);
282 if (fd1 != -1) e(114); /* ho exists */
283 System("rm -rf new");
284 time(&time1);
285 while (time1 >= time((time_t *)0))
287 fd1 = open("new", O_RDWR | O_CREAT, 0716);
288 if (fd1 != 3) e(115); /* new file */
289 Stat("new", &st1);
290 time(&time2);
291 while (time2 >= time((time_t *)0))
293 time(&time2);
294 if (st1.st_uid != geteuid()) e(116); /* try this as superuser. */
295 if (st1.st_gid != getegid()) e(117);
296 if ((st1.st_mode & 0777) != 0716) e(118);
297 if (st1.st_nlink != 1) e(119);
298 if (st1.st_mtime <= time1) e(120);
299 if (st1.st_mtime >= time2) e(121);
300 #ifndef V1_FILESYSTEM
301 if (st1.st_atime != st1.st_mtime) e(122);
302 #endif
303 if (st1.st_ctime != st1.st_mtime) e(123);
304 if (st1.st_size != 0) e(124);
305 if (write(fd1, "I'm new in town", 16) != 16) e(125);
306 if (lseek(fd1, (off_t) - 5, SEEK_CUR) != 11) e(126);
307 if (read(fd1, buf, 5) != 5) e(127);
308 if (strncmp(buf, "town", 5) != 0) e(128);
309 if (close(fd1) != 0) e(129);
311 /* Let's test the O_TRUNC flag on this new file. */
312 time(&time1);
313 while (time1 >= time((time_t *)0));
314 if ((fd1 = open("new", O_RDWR | O_TRUNC)) != 3) e(130);
315 Stat("new", &st1);
316 time(&time2);
317 while (time2 >= time((time_t *)0));
318 time(&time2);
319 if ((st1.st_mode & 0777) != 0716) e(131);
320 if (st1.st_size != (size_t) 0) e(132); /* TRUNCed ? */
321 if (st1.st_mtime <= time1) e(133);
322 if (st1.st_mtime >= time2) e(134);
323 if (st1.st_ctime != st1.st_mtime) e(135);
324 if (close(fd1) != 0) e(136);
326 /* Test if file permission bits and the file ownership are unchanged. */
327 /* So we will see if `O_CREAT' has no effect if the file exists. */
328 if (superuser) {
329 System("echo > bar; chmod 077 bar"); /* Make bar 077 */
330 System("chown daemon bar");
331 System("chgrp daemon bar"); /* Daemon's bar */
332 fd1 = open("bar", O_RDWR | O_CREAT | O_TRUNC, 0777); /* knock knock */
333 if (fd1 == -1) e(137);
334 if (write(fd1, "foo", 3) != 3) e(138); /* rewrite bar */
335 if (close(fd1) != 0) e(139);
336 Stat("bar", &st1);
337 if (st1.st_uid != 1) e(140); /* bar is still */
338 if (st1.st_gid != 1) e(141); /* owned by daemon */
339 if ((st1.st_mode & 0777) != 077) e(142); /* mode still is 077 */
340 if (st1.st_size != (size_t) 3) e(143); /* 3 bytes long */
342 /* We do the whole thing again, but with O_WRONLY */
343 fd1 = open("bar", O_WRONLY | O_CREAT | O_TRUNC, 0777);
344 if (fd1 == -1) e(144);
345 if (write(fd1, "foobar", 6) != 6) e(145); /* rewrite bar */
346 if (close(fd1) != 0) e(146);
347 Stat("bar", &st1);
348 if (st1.st_uid != 1) e(147); /* bar is still */
349 if (st1.st_gid != 1) e(148); /* owned by daemon */
350 if ((st1.st_mode & 0777) != 077) e(149); /* mode still is 077 */
351 if (st1.st_size != (size_t) 6) e(150); /* 6 bytes long */
355 void test25c()
356 { /* Test normal operation Part two. */
357 int fd1, fd2;
358 char buf[BUF_SIZE];
359 struct stat st;
360 int stat_loc;
361 static int iteration=0;
363 subtest = 3;
364 iteration++;
366 System("rm -rf ../DIR_25/*");
368 /* Fifo file test here. */
369 if (mkfifo("fifo", 0777) != 0) e(1);
370 switch (fork()) {
371 case -1: printf("Can't fork\n"); break;
372 case 0:
373 alarm(20); /* Give child 20 seconds to live. */
374 if ((fd1 = open("fifo", O_RDONLY)) != 3) e(2);
375 if (read(fd1, buf, BUF_SIZE) != 23) e(3);
376 if (strncmp(buf, "1 2 3 testing testing\n", 23) != 0) e(4);
377 if (close(fd1) != 0) e(5);
378 exit(0);
379 default:
380 if ((fd1 = open("fifo", O_WRONLY)) != 3) e(6);
381 if (write(fd1, "1 2 3 testing testing\n", 23) != 23) e(7);
382 if (close(fd1) != 0) e(8);
383 if (wait(&stat_loc) == -1) e(9);
384 if (stat_loc != 0) e(10); /* The alarm went off? */
387 /* Try opening for writing with O_NONBLOCK. */
388 fd1 = open("fifo", O_WRONLY | O_NONBLOCK);
389 if (fd1 != -1) e(11);
390 if (errno != ENXIO) e(12);
391 close(fd1);
393 /* Try opening for writing with O_NONBLOCK and O_CREAT. */
394 fd1 = open("fifo", O_WRONLY | O_CREAT | O_NONBLOCK, 0777);
395 if (fd1 != -1) e(13);
396 if (errno != ENXIO) e(14);
397 close(fd1);
399 /* Both the NONBLOCK and the EXCLusive give raise to error. */
400 fd1 = open("fifo", O_WRONLY | O_CREAT | O_EXCL | O_NONBLOCK, 0777);
401 if (fd1 != -1) e(15);
402 if (errno != EEXIST && errno != ENXIO) e(16);
403 close(fd1); /* Just in case. */
405 /* Try opening for reading with O_NONBLOCK. */
406 fd1 = open("fifo", O_RDONLY | O_NONBLOCK);
407 if (fd1 != 3) e(17);
408 if (close(fd1) != 0) e(18);
410 /* Nopt runs out of memory. ;-< We just cut out some valid code */
411 /* FIFO's should always append. (They have no file position.) */
412 switch (fork()) {
413 case -1: printf("Can't fork\n"); break;
414 case 0:
415 alarm(20); /* Give child 20 seconds to live. */
416 if ((fd1 = open("fifo", O_WRONLY)) != 3) e(19);
417 if ((fd2 = open("fifo", O_WRONLY)) != 4) e(20);
418 if (write(fd1, "I did see Elvis.\n", 18) != 18) e(21);
419 if (write(fd2, "I DID.\n", 8) != 8) e(22);
420 if (close(fd2) != 0) e(23);
421 if (close(fd1) != 0) e(24);
422 exit(0);
423 default:
424 if ((fd1 = open("fifo", O_RDONLY)) != 3) e(25);
425 if (read(fd1, buf, 18) != 18) e(26);
426 if (strncmp(buf, "I did see Elvis.\n", 18) != 0) e(27);
427 if (read(fd1, buf, BUF_SIZE) != 8) e(28);
428 if (strncmp(buf, "I DID.\n", 8) != 0) e(29);
429 if (close(fd1) != 0) e(30);
430 if (wait(&stat_loc) == -1) e(31);
431 if (stat_loc != 0) e(32); /* The alarm went off? */
434 /* O_TRUNC should have no effect on FIFO files. */
435 switch (fork()) {
436 case -1: printf("Can't fork\n"); break;
437 case 0:
438 alarm(20); /* Give child 20 seconds to live. */
439 if ((fd1 = open("fifo", O_WRONLY)) != 3) e(33);
440 if (write(fd1, "I did see Elvis.\n", 18) != 18) e(34);
441 if ((fd2 = open("fifo", O_WRONLY | O_TRUNC)) != 4) e(35);
442 if (write(fd2, "I DID.\n", 8) != 8) e(36);
443 if (close(fd2) != 0) e(37);
444 if (close(fd1) != 0) e(38);
445 exit(0);
446 default:
447 if ((fd1 = open("fifo", O_RDONLY)) != 3) e(39);
448 if (read(fd1, buf, 18) != 18) e(40);
449 if (strncmp(buf, "I did see Elvis.\n", 18) != 0) e(41);
450 if (read(fd1, buf, BUF_SIZE) != 8) e(42);
451 if (strncmp(buf, "I DID.\n", 8) != 0) e(43);
452 if (close(fd1) != 0) e(44);
453 if (wait(&stat_loc) == -1) e(45);
454 if (stat_loc != 0) e(46); /* The alarm went off? */
457 /* Closing the last fd should flush all data to the bitbucket. */
458 System("rm -rf /tmp/sema.25");
459 switch (fork()) {
460 case -1: printf("Can't fork\n"); break;
462 case 0:
463 alarm(20); /* Give child 20 seconds to live. */
464 if ((fd1 = open("fifo", O_WRONLY)) != 3) e(47);
465 if (write(fd1, "I did see Elvis.\n", 18) != 18) e(48);
466 Creat("/tmp/sema.25");
467 sleep(2); /* give parent a chance to open */
468 /* this was sleep(1), but that's too short: child also sleeps(1) */
469 if (close(fd1) != 0) e(49);
470 exit(0);
472 default:
473 if ((fd1 = open("fifo", O_RDONLY)) != 3) e(50);
474 /* Make `sure' write has closed. */
475 while (stat("/tmp/sema.25", &st) != 0) sleep(1);
476 if (close(fd1) != 0) e(51);
477 if ((fd1 = open("fifo", O_RDONLY | O_NONBLOCK)) != 3) e(52);
478 if (read(fd1, buf, BUF_SIZE) != 18) e(53);
479 if (close(fd1) != 0) e(54);
480 if (wait(&stat_loc) == -1) e(55);
481 if (stat_loc != 0) e(56); /* The alarm went off? */
484 /* Let's try one too many. */
485 System("rm -rf /tmp/sema.25");
486 switch (fork()) {
487 case -1: printf("Can't fork\n"); break;
488 case 0:
489 alarm(20); /* Give child 20 seconds to live. */
490 if ((fd1 = open("fifo", O_WRONLY)) != 3) e(57);
491 if (write(fd1, "I did see Elvis.\n", 18) != 18) e(58);
493 /* Keep open till third reader is opened. */
494 while (stat("/tmp/sema.25", &st) != 0) sleep(1);
495 if (close(fd1) != 0) e(59);
496 exit(0);
497 default:
498 if ((fd1 = open("fifo", O_RDONLY)) != 3) e(60);
499 if (read(fd1, buf, 2) != 2) e(61);
500 if (strncmp(buf, "I ", 2) != 0) e(62);
501 if (close(fd1) != 0) e(63);
502 if ((fd1 = open("fifo", O_RDONLY)) != 3) e(64);
503 if (read(fd1, buf, 4) != 4) e(65);
504 if (strncmp(buf, "did ", 4) != 0) e(66);
505 if ((fd2 = open("fifo", O_RDONLY)) != 4) e(67);
507 /* Signal third reader is open. */
508 Creat("/tmp/sema.25");
509 if (read(fd2, buf, BUF_SIZE) != 12) e(68);
510 if (strncmp(buf, "see Elvis.\n", 12) != 0) e(69);
511 if (close(fd2) != 0) e(70);
512 if (close(fd1) != 0) e(71);
513 if (wait(&stat_loc) == -1) e(72);
514 if (stat_loc != 0) e(73); /* The alarm went off? */
516 System("rm -rf fifo /tmp/sema.25");
518 /* O_TRUNC should have no effect on directroys. */
519 System("mkdir dir; touch dir/f1 dir/f2 dir/f3");
520 if ((fd1 = open("dir", O_WRONLY | O_TRUNC)) != -1) e(74);
521 if (errno != EISDIR) e(75);
522 close(fd1);
524 /* Opening a directory for reading should be possible. */
525 if ((fd1 = open("dir", O_RDONLY)) != 3) e(76);
526 if (close(fd1) != 0) e(77);
527 if (unlink("dir/f1") != 0) e(78); /* Should still be there. */
528 if (unlink("dir/f2") != 0) e(79);
529 if (unlink("dir/f3") != 0) e(80);
530 if (rmdir("dir") != 0) e(81);
532 if (!superuser) {
533 /* Test if O_CREAT is not usable to open files with the wrong mode */
534 (void) umask(0200); /* nono has no */
535 System("touch nono"); /* write bit */
536 (void) umask(0000);
537 fd1 = open("nono", O_RDWR | O_CREAT, 0777); /* try to open */
538 if (fd1 != -1) e(82);
539 if (errno != EACCES) e(83); /* but no access */
543 void test25d()
545 int fd;
547 subtest = 4;
549 System("rm -rf ../DIR_25/*");
551 /* Test maximal file name length. */
552 if ((fd = open(MaxName, O_RDWR | O_CREAT, 0777)) != 3) e(1);
553 if (close(fd) != 0) e(2);
554 MaxPath[strlen(MaxPath) - 2] = '/';
555 MaxPath[strlen(MaxPath) - 1] = 'a'; /* make ././.../a */
556 if ((fd = open(MaxPath, O_RDWR | O_CREAT, 0777)) != 3) e(3);
557 if (close(fd) != 0) e(4);
558 MaxPath[strlen(MaxPath) - 1] = '/'; /* make ././.../a */
561 void test25e()
563 int fd, does_truncate;
564 char *noread = "noread"; /* Name for unreadable file. */
565 char *nowrite = "nowrite"; /* Same for unwritable. */
566 int stat_loc;
568 subtest = 5;
570 System("rm -rf ../DIR_25/*");
572 mkdir("bar", 0777); /* make bar */
574 /* Check if no access on part of path generates the correct error. */
575 System("chmod 677 bar"); /* rw-rwxrwx */
576 if (open("bar/nono", O_RDWR | O_CREAT, 0666) != -1) e(1);
577 if (errno != EACCES) e(2);
579 /* Ditto for no write permission. */
580 System("chmod 577 bar"); /* r-xrwxrwx */
581 if (open("bar/nono", O_RDWR | O_CREAT, 0666) != -1) e(3);
582 if (errno != EACCES) e(4);
584 /* Clean up bar. */
585 System("rm -rf bar");
587 /* Improper flags set on existing file. */
588 System("touch noread; chmod 377 noread"); /* noread */
589 if (open(noread, O_RDONLY) != -1) e(5);
590 if (open(noread, O_RDWR) != -1) e(6);
591 if (open(noread, O_RDWR | O_CREAT, 0777) != -1) e(7);
592 if (open(noread, O_RDWR | O_CREAT | O_TRUNC, 0777) != -1) e(8);
593 if ((fd = open(noread, O_WRONLY)) != 3) e(9);
594 if (close(fd) != 0) e(10);
595 System("touch nowrite; chmod 577 nowrite"); /* nowrite */
596 if (open(nowrite, O_WRONLY) != -1) e(11);
597 if (open(nowrite, O_RDWR) != -1) e(12);
598 if (open(nowrite, O_RDWR | O_CREAT, 0777) != -1) e(13);
599 if (open(nowrite, O_RDWR | O_CREAT | O_TRUNC, 0777) != -1) e(14);
600 if ((fd = open(nowrite, O_RDONLY)) != 3) e(15);
601 if (close(fd) != 0) e(16);
602 if (superuser) {
603 /* If we can make a file ownd by some one else, test access again. */
604 System("chmod 733 noread");
605 System("chown bin noread");
606 System("chgrp system noread");
607 System("chmod 755 nowrite");
608 System("chown bin nowrite");
609 System("chgrp system nowrite");
610 switch (fork()) {
611 case -1: printf("Can't fork\n"); break;
612 case 0:
613 setuid(1);
614 setgid(1); /* become daemon */
615 if (open(noread, O_RDONLY) != -1) e(17);
616 if (open(noread, O_RDWR) != -1) e(18);
617 if (open(noread, O_RDWR | O_CREAT, 0777) != -1) e(19);
618 fd = open(noread, O_RDWR | O_CREAT | O_TRUNC, 0777);
619 if (fd != -1) e(20);
620 if ((fd = open(noread, O_WRONLY)) != 3) e(21);
621 if (close(fd) != 0) e(22);
622 if (open(nowrite, O_WRONLY) != -1) e(23);
623 if (open(nowrite, O_RDWR) != -1) e(24);
624 if (open(nowrite, O_RDWR | O_CREAT, 0777) != -1) e(25);
625 fd = open(nowrite, O_RDWR | O_CREAT | O_TRUNC, 0777);
626 if (fd != -1) e(26);
627 if ((fd = open(nowrite, O_RDONLY)) != 3) e(27);
628 if (close(fd) != 0) e(28);
629 exit(0);
630 default:
631 if (wait(&stat_loc) == -1) e(29);
635 /* Clean up the noread and nowrite files. */
636 System("rm -rf noread nowrite");
638 /* Test the O_EXCL flag. */
639 System("echo > exists");
640 if (open("exists", O_RDWR | O_CREAT | O_EXCL, 0777) != -1) e(30);
641 if (errno != EEXIST) e(31);
642 if (open("exists", O_RDONLY | O_CREAT | O_EXCL, 0777) != -1) e(32);
643 if (errno != EEXIST) e(33);
644 if (open("exists", O_WRONLY | O_CREAT | O_EXCL, 0777) != -1) e(34);
645 if (errno != EEXIST) e(35);
646 fd = open("exists", O_RDWR | O_CREAT | O_EXCL | O_TRUNC, 0777);
647 if (fd != -1) e(36);
648 if (errno != EEXIST) e(37);
649 fd = open("exists", O_RDONLY | O_CREAT | O_EXCL | O_TRUNC, 0777);
650 if (fd != -1) e(38);
651 if (errno != EEXIST) e(39);
652 fd = open("exists", O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, 0777);
653 if (fd != -1) e(40);
654 if (errno != EEXIST) e(41);
656 /* open should fail when O_CREAT|O_EXCL are set and a symbolic link names
657 a file with EEXIST (regardless of link actually works or not) */
658 if (symlink("exists", "slinktoexists") == -1) e(42);
659 if (open("slinktoexists", O_RDWR | O_CREAT | O_EXCL, 0777) != -1) e(43);
660 if (unlink("exists") == -1) e(44);
661 /* "slinktoexists has become a dangling symlink. open(2) should still fail
662 with EEXIST */
663 if (open("slinktoexists", O_RDWR | O_CREAT | O_EXCL, 0777) != -1) e(45);
664 if (errno != EEXIST) e(46);
667 /* Test ToLongName and ToLongPath */
668 does_truncate = does_fs_truncate();
669 fd = open(ToLongName, O_RDWR | O_CREAT, 0777);
670 if (does_truncate) {
671 if (fd == -1) e(47);
672 if (close(fd) != 0) e(48);
673 } else {
674 if (fd != -1) e(49);
675 (void) close(fd); /* Just in case */
678 ToLongPath[PATH_MAX - 2] = '/';
679 ToLongPath[PATH_MAX - 1] = 'a';
680 if ((fd = open(ToLongPath, O_RDWR | O_CREAT, 0777)) != -1) e(50);
681 if (errno != ENAMETOOLONG) e(51);
682 if (close(fd) != -1) e(52);
683 ToLongPath[PATH_MAX - 1] = '/';
686 void makelongnames()
688 register int i;
689 int max_name_length;
691 max_name_length = name_max("."); /* Aka NAME_MAX, but not every FS supports
692 * the same length, hence runtime check */
693 MaxName = malloc(max_name_length + 1);
694 ToLongName = malloc(max_name_length + 1 + 1); /* Name of maximum +1 length */
695 memset(MaxName, 'a', max_name_length);
696 MaxName[max_name_length] = '\0';
698 for (i = 0; i < PATH_MAX - 1; i++) { /* idem path */
699 MaxPath[i++] = '.';
700 MaxPath[i] = '/';
702 MaxPath[PATH_MAX - 1] = '\0';
704 strcpy(ToLongName, MaxName); /* copy them Max to ToLong */
705 strcpy(ToLongPath, MaxPath);
707 ToLongName[max_name_length] = 'a';
708 ToLongName[max_name_length+1] = '\0';/* extend ToLongName by one too many */
709 ToLongPath[PATH_MAX - 1] = '/';
710 ToLongPath[PATH_MAX] = '\0'; /* inc ToLongPath by one */