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