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