xref: /minix3/minix/tests/test38.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1 /* Many of the tests require 1.6.n, n > 16, so we may as well assume that
2  * POSIX signals are implemented.
3  */
4 #define SIGACTION
5 
6 /* test38: read(), write()	Author: Jan-Mark Wams (jms@cs.vu.nl) */
7 
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <sys/wait.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <string.h>
14 #include <fcntl.h>
15 #include <limits.h>
16 #include <errno.h>
17 #include <time.h>
18 #include <signal.h>
19 #include <stdio.h>
20 
21 int max_error = 	4;
22 #include "common.h"
23 
24 #define ITERATIONS      3
25 #define BUF_SIZE 1024
26 
27 #define System(cmd)	if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
28 #define Chdir(dir)	if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
29 #define Stat(a,b)	if (stat(a,b) != 0) printf("Can't stat %s\n", a)
30 
31 
32 int superuser;
33 int signumber = 0;
34 
35 void test38a(void);
36 void test38b(void);
37 void test38c(void);
38 void setsignumber(int _signumber);
39 
main(int argc,char * argv[])40 int main(int argc, char *argv[])
41 {
42   int i, m = 0xFFFF;
43 
44   sync();
45   start(38);
46 
47   if (argc == 2) m = atoi(argv[1]);
48   superuser = (geteuid() == 0);
49   umask(0000);
50 
51   for (i = 0; i < ITERATIONS; i++) {
52 	if (m & 0001) test38a();
53 	if (m & 0002) test38b();
54 	if (m & 0004) test38c();
55   }
56   quit();
57 
58   return(-1);	/* Unreachable */
59 }
60 
test38a()61 void test38a()
62 {				/* Try normal operation. */
63   int fd1;
64   struct stat st1, st2;
65   time_t time1;
66   char buf[BUF_SIZE];
67   int stat_loc;
68   int i, j;
69   int tube[2];
70 
71   subtest = 1;
72   System("rm -rf ../DIR_38/*");
73 
74   /* Let's open bar. */
75   if ((fd1 = open("bar", O_RDWR | O_CREAT, 0777)) != 3) e(1);
76   Stat("bar", &st1);
77 
78   /* Writing nothing should not affect the file at all. */
79   if (write(fd1, "", 0) != 0) e(2);
80   Stat("bar", &st2);
81   if (st1.st_uid != st2.st_uid) e(3);
82   if (st1.st_gid != st2.st_gid) e(4);	/* should be same */
83   if (st1.st_mode != st2.st_mode) e(5);
84   if (st1.st_size != st2.st_size) e(6);
85   if (st1.st_nlink != st2.st_nlink) e(7);
86   if (st1.st_mtime != st2.st_mtime) e(8);
87   if (st1.st_ctime != st2.st_ctime) e(9);
88   if (st1.st_atime != st2.st_atime) e(10);
89 
90   /* A write should update some status fields. */
91   time(&time1);
92   while (time1 >= time((time_t *)0))
93 	;
94   if (write(fd1, "foo", 4) != 4) e(11);
95   Stat("bar", &st2);
96   if (st1.st_mode != st2.st_mode) e(12);
97   if (st1.st_size >= st2.st_size) e(13);
98   if ((off_t) 4 != st2.st_size) e(14);
99   if (st1.st_nlink != st2.st_nlink) e(15);
100   if (st1.st_mtime >= st2.st_mtime) e(16);
101   if (st1.st_ctime >= st2.st_ctime) e(17);
102   if (st1.st_atime != st2.st_atime) e(18);
103 
104   /* Lseeks should not change the file status. */
105   if (lseek(fd1, (off_t) - 2, SEEK_END) != 2) e(19);
106   Stat("bar", &st1);
107   if (st1.st_mode != st2.st_mode) e(20);
108   if (st1.st_size != st2.st_size) e(21);
109   if (st1.st_nlink != st2.st_nlink) e(22);
110   if (st1.st_mtime != st2.st_mtime) e(23);
111   if (st1.st_ctime != st2.st_ctime) e(24);
112   if (st1.st_atime != st2.st_atime) e(25);
113 
114   /* Writing should start at the current (2) position. */
115   if (write(fd1, "foo", 4) != 4) e(26);
116   Stat("bar", &st2);
117   if (st1.st_mode != st2.st_mode) e(27);
118   if (st1.st_size >= st2.st_size) e(28);
119   if ((off_t) 6 != st2.st_size) e(29);
120   if (st1.st_nlink != st2.st_nlink) e(30);
121   if (st1.st_mtime > st2.st_mtime) e(31);
122   if (st1.st_ctime > st2.st_ctime) e(32);
123   if (st1.st_atime != st2.st_atime) e(33);
124 
125   /* A read of zero bytes should not affect anything. */
126   if (read(fd1, buf, 0) != 0) e(34);
127   Stat("bar", &st1);
128   if (st1.st_uid != st2.st_uid) e(35);
129   if (st1.st_gid != st2.st_gid) e(36);	/* should be same */
130   if (st1.st_mode != st2.st_mode) e(37);
131   if (st1.st_size != st2.st_size) e(38);
132   if (st1.st_nlink != st2.st_nlink) e(39);
133   if (st1.st_mtime != st2.st_mtime) e(40);
134   if (st1.st_ctime != st2.st_ctime) e(41);
135   if (st1.st_atime != st2.st_atime) e(42);
136 
137   /* The file now should contain ``fofoo\0'' Let's check that. */
138   if (lseek(fd1, (off_t) 0, SEEK_SET) != 0) e(43);
139   if (read(fd1, buf, BUF_SIZE) != 6) e(44);
140   if (strcmp(buf, "fofoo") != 0) e(45);
141 
142   /* Only the Access Time should be updated. */
143   Stat("bar", &st2);
144   if (st1.st_mtime != st2.st_mtime) e(46);
145   if (st1.st_ctime != st2.st_ctime) e(47);
146   if (st1.st_atime >= st2.st_atime) e(48);
147 
148   /* A read of zero bytes should do nothing even at the end of the file. */
149   time(&time1);
150   while (time1 >= time((time_t *)0))
151 	;
152   if (read(fd1, buf, 0) != 0) e(49);
153   Stat("bar", &st1);
154   if (st1.st_size != st2.st_size) e(50);
155   if (st1.st_mtime != st2.st_mtime) e(51);
156   if (st1.st_ctime != st2.st_ctime) e(52);
157   if (st1.st_atime != st2.st_atime) e(53);
158 
159   /* Reading should be done from the current offset. */
160   if (read(fd1, buf, BUF_SIZE) != 0) e(54);
161   if (lseek(fd1, (off_t) 2, SEEK_SET) != 2) e(55);
162   if (read(fd1, buf, BUF_SIZE) != 4) e(56);
163   if (strcmp(buf, "foo") != 0) e(57);
164 
165   /* Reading should effect the current file position. */
166   if (lseek(fd1, (off_t) 2, SEEK_SET) != 2) e(58);
167   if (read(fd1, buf, 1) != 1) e(59);
168   if (*buf != 'f') e(60);
169   if (lseek(fd1, (off_t) 0, SEEK_CUR) != 3) e(61);
170   if (read(fd1, buf, 1) != 1) e(62);
171   if (*buf != 'o') e(63);
172   if (lseek(fd1, (off_t) 0, SEEK_CUR) != 4) e(64);
173   if (read(fd1, buf, 1) != 1) e(65);
174   if (*buf != 'o') e(66);
175   if (lseek(fd1, (off_t) 0, SEEK_CUR) != 5) e(67);
176   if (read(fd1, buf, 1) != 1) e(68);
177   if (*buf != '\0') e(69);
178   if (lseek(fd1, (off_t) 0, SEEK_CUR) != 6) e(70);
179 
180   /* Read's at EOF should return 0. */
181   if (read(fd1, buf, BUF_SIZE) != 0) e(71);
182   if (lseek(fd1, (off_t) 0, SEEK_CUR) != 6) e(72);
183   if (read(fd1, buf, BUF_SIZE) != 0) e(73);
184   if (lseek(fd1, (off_t) 0, SEEK_CUR) != 6) e(74);
185   if (read(fd1, buf, BUF_SIZE) != 0) e(75);
186   if (lseek(fd1, (off_t) 0, SEEK_CUR) != 6) e(76);
187   if (read(fd1, buf, BUF_SIZE) != 0) e(77);
188   if (lseek(fd1, (off_t) 0, SEEK_CUR) != 6) e(78);
189   if (read(fd1, buf, BUF_SIZE) != 0) e(79);
190   if (lseek(fd1, (off_t) 0, SEEK_CUR) != 6) e(80);
191 
192   /* Writing should not always change the file size. */
193   if (lseek(fd1, (off_t) 2, SEEK_SET) != 2) e(81);
194   if (write(fd1, "ba", 2) != 2) e(82);
195   if (lseek(fd1, (off_t) 0, SEEK_CUR) != 4) e(83);
196   Stat("bar", &st1);
197   if (st1.st_size != 6) e(84);
198 
199   /* Kill the \0 at the end. */
200   if (lseek(fd1, (off_t) 5, SEEK_SET) != 5) e(85);
201   if (write(fd1, "x", 1) != 1) e(86);
202 
203   /* And close the bar. */
204   if (close(fd1) != 0) e(87);
205 
206   /* Try some stuff with O_APPEND. Bar contains ``fobaox'' */
207   if ((fd1 = open("bar", O_RDWR | O_APPEND)) != 3) e(88);
208 
209   /* No matter what the file position is. Writes should append. */
210   if (lseek(fd1, (off_t) 2, SEEK_SET) != 2) e(89);
211   if (write(fd1, "y", 1) != 1) e(90);
212   Stat("bar", &st1);
213   if (st1.st_size != (off_t) 7) e(91);
214   if (lseek(fd1, (off_t) 0, SEEK_CUR) != 7) e(92);
215   if (lseek(fd1, (off_t) 2, SEEK_SET) != 2) e(93);
216   if (write(fd1, "z", 2) != 2) e(94);
217 
218   /* The file should contain ``fobaoxyz\0'' == 9 chars long. */
219   Stat("bar", &st1);
220   if (st1.st_size != (off_t) 9) e(95);
221   if (lseek(fd1, (off_t) 0, SEEK_CUR) != 9) e(96);
222 
223   /* Reading on a O_APPEND flag should be from the current offset. */
224   if (lseek(fd1, (off_t) 0, SEEK_SET) != 0) e(97);
225   if (read(fd1, buf, BUF_SIZE) != 9) e(98);
226   if (strcmp(buf, "fobaoxyz") != 0) e(99);
227   if (lseek(fd1, (off_t) 0, SEEK_CUR) != 9) e(100);
228 
229   if (close(fd1) != 0) e(101);
230 
231   /* Let's test fifo writes. First blocking. */
232   if (mkfifo("fifo", 0777) != 0) e(102);
233 
234   /* Read from fifo but no writer. */
235   System("rm -rf /tmp/sema.38a");
236   switch (fork()) {
237       case -1:	printf("Can't fork\n");	break;
238 
239       case 0:
240 	alarm(20);
241 	if ((fd1 = open("fifo", O_RDONLY)) != 3) e(103);
242 	system("> /tmp/sema.38a");
243 	system("while test -f /tmp/sema.38a; do sleep 1; done");
244 errno =0;
245 	if (read(fd1, buf, BUF_SIZE) != 0) e(104);
246 	if (read(fd1, buf, BUF_SIZE) != 0) e(105);
247 	if (read(fd1, buf, BUF_SIZE) != 0) e(106);
248 	if (close(fd1) != 0) e(107);
249 	exit(0);
250 
251       default:
252 	if ((fd1 = open("fifo", O_WRONLY)) != 3) e(108);
253 	while (stat("/tmp/sema.38a", &st1) != 0) sleep(1);
254 	if (close(fd1) != 0) e(109);
255 	unlink("/tmp/sema.38a");
256 	if (wait(&stat_loc) == -1) e(110);
257 	if (stat_loc != 0) e(111);	/* Alarm? */
258   }
259 
260   /* Read from fifo should wait for writer. */
261   switch (fork()) {
262       case -1:	printf("Can't fork\n");	break;
263 
264       case 0:
265 	alarm(20);
266 	if ((fd1 = open("fifo", O_RDONLY)) != 3) e(112);
267 	if (read(fd1, buf, BUF_SIZE) != 10) e(113);
268 	if (strcmp(buf, "Hi reader") != 0) e(114);
269 	if (close(fd1) != 0) e(115);
270 	exit(0);
271 
272       default:
273 	if ((fd1 = open("fifo", O_WRONLY)) != 3) e(116);
274 	sleep(1);
275 	if (write(fd1, "Hi reader", 10) != 10) e(117);
276 	if (close(fd1) != 0) e(118);
277 	if (wait(&stat_loc) == -1) e(119);
278 	if (stat_loc != 0) e(120);	/* Alarm? */
279   }
280 
281 #if DEAD_CODE
282   /* Does this test test what it is supposed to test??? */
283 
284   /* Read from fifo should wait for all writers to close. */
285   switch (fork()) {
286       case -1:	printf("Can't fork\n");	break;
287 
288       case 0:
289 	alarm(60);
290 	switch (fork()) {
291 	    case -1:	printf("Can't fork\n");	break;
292 	    case 0:
293 		alarm(20);
294 		if ((fd1 = open("fifo", O_WRONLY)) != 3) e(121);
295 		printf("C2 did open\n");
296 		if (close(fd1) != 0) e(122);
297 		printf("C2 did close\n");
298 		exit(0);
299 	    default:
300 		printf("C1 scheduled\n");
301 		if ((fd1 = open("fifo", O_WRONLY)) != 3) e(123);
302 		printf("C1 did open\n");
303 		sleep(2);
304 		if (close(fd1) != 0) e(124);
305 		printf("C1 did close\n");
306 		sleep(1);
307 		if (wait(&stat_loc) == -1) e(125);
308 		if (stat_loc != 0) e(126);	/* Alarm? */
309 	}
310 	exit(stat_loc);
311 
312       default: {
313 	int wait_status;
314 	printf("Parent running\n");
315 	sleep(1);				/* open in childs first */
316 	if ((fd1 = open("fifo", O_RDONLY)) != 3) e(127);
317 	if (read(fd1, buf, BUF_SIZE) != 0) e(128);
318 	if (close(fd1) != 0) e(129);
319 	printf("Parent closed\n");
320 	if ((wait_status=wait(&stat_loc)) == -1) e(130);
321 
322       printf("wait_status %d, stat_loc %d:", wait_status, stat_loc);
323       if (WIFSIGNALED(stat_loc)) {
324           printf(" killed, signal number %d\n", WTERMSIG(stat_loc));
325       }
326       else if (WIFEXITED(stat_loc)) {
327           printf(" normal exit, status %d\n", WEXITSTATUS(stat_loc));
328       }
329 
330 	if (stat_loc != 0) e(131);	/* Alarm? */
331       }
332   }
333 #endif
334 
335   /* PIPE_BUF has to have a nice value. */
336   if (PIPE_BUF < 5) e(132);
337   if (BUF_SIZE < 1000) e(133);
338 
339   /* Writes of blocks smaller than PIPE_BUF should be atomic. */
340   System("rm -rf /tmp/sema.38b;> /tmp/sema.38b");
341   switch (fork()) {
342       case -1:	printf("Can't fork\n");	break;
343 
344       case 0:
345 	alarm(20);
346 	switch (fork()) {
347 	    case -1:	printf("Can't fork\n");	break;
348 
349 	    case 0:
350 		alarm(20);
351 		if ((fd1 = open("fifo", O_WRONLY)) != 3) e(134);
352 		for (i = 0; i < 100; i++) write(fd1, "1234 ", 5);
353 		system("while test -f /tmp/sema.38b; do sleep 1; done");
354 		if (close(fd1) != 0) e(135);
355 		exit(0);
356 
357 	    default:
358 		if ((fd1 = open("fifo", O_WRONLY)) != 3) e(136);
359 		for (i = 0; i < 100; i++) write(fd1, "1234 ", 5);
360 		while (stat("/tmp/sema.38b", &st1) == 0) sleep(1);
361 		if (close(fd1) != 0) e(137);
362 		if (wait(&stat_loc) == -1) e(138);
363 		if (stat_loc != 0) e(139);	/* Alarm? */
364 	}
365 	exit(stat_loc);
366 
367       default:
368 	if ((fd1 = open("fifo", O_RDONLY)) != 3) e(140);
369 	i = 0;
370 	memset(buf, '\0', BUF_SIZE);
371 
372 	/* Read buffer full or till EOF. */
373 	do {
374 		j = read(fd1, buf + i, BUF_SIZE - i);
375 		if (j > 0) {
376 			if (j % 5 != 0) e(141);
377 			i += j;
378 		}
379 	} while (j > 0 && i < 1000);
380 
381 	/* Signal the children to close write ends. This should not be */
382 	/* Necessary. But due to a bug in 1.16.6 this is necessary. */
383 	unlink("/tmp/sema.38b");
384 	if (j < 0) e(142);
385 	if (i != 1000) e(143);
386 	if (wait(&stat_loc) == -1) e(144);
387 	if (stat_loc != 0) e(145);	/* Alarm? */
388 
389 	/* Check 200 times 1234. */
390 	for (i = 0; i < 200; i++)
391 		if (strncmp(buf + (i * 5), "1234 ", 5) != 0) break;
392 	if (i != 200) e(146);
393 	if (buf[1000] != '\0') e(147);
394 	if (buf[1005] != '\0') e(148);
395 	if (buf[1010] != '\0') e(149);
396 	if (read(fd1, buf, BUF_SIZE) != 0) e(150);
397 	if (close(fd1) != 0) e(151);
398   }
399 
400   /* Read from pipe should wait for writer. */
401   if (pipe(tube) != 0) e(152);
402   switch (fork()) {
403       case -1:	printf("Can't fork\n");	break;
404       case 0:
405 	alarm(20);
406 	if (close(tube[1]) != 0) e(153);
407 	if (read(tube[0], buf, BUF_SIZE) != 10) e(154);
408 	if (strcmp(buf, "Hi reader") != 0) e(155);
409 	if (close(tube[0]) != 0) e(156);
410 	exit(0);
411       default:
412 	if (close(tube[0]) != 0) e(157);
413 	sleep(1);
414 	if (write(tube[1], "Hi reader", 10) != 10) e(158);
415 	if (close(tube[1]) != 0) e(159);
416 	if (wait(&stat_loc) == -1) e(160);
417 	if (stat_loc != 0) e(161);	/* Alarm? */
418   }
419 
420   /* Read from pipe should wait for all writers to close. */
421   if (pipe(tube) != 0) e(162);
422   switch (fork()) {
423       case -1:	printf("Can't fork\n");	break;
424       case 0:
425 	alarm(20);
426 	if (close(tube[0]) != 0) e(163);
427 	switch (fork()) {
428 	    case -1:	printf("Can't fork\n");	break;
429 	    case 0:
430 		alarm(20);
431 		if (close(tube[1]) != 0) e(164);
432 		exit(0);
433 	    default:
434 		sleep(1);
435 		if (close(tube[1]) != 0) e(165);
436 		if (wait(&stat_loc) == -1) e(166);
437 		if (stat_loc != 0) e(167);	/* Alarm? */
438 	}
439 	exit(stat_loc);
440       default:
441 	if (close(tube[1]) != 0) e(168);
442 	if (read(tube[0], buf, BUF_SIZE) != 0) e(169);
443 	if (close(tube[0]) != 0) e(170);
444 	if (wait(&stat_loc) == -1) e(171);
445 	if (stat_loc != 0) e(172);	/* Alarm? */
446   }
447 
448   /* Writes of blocks smaller than PIPE_BUF should be atomic. */
449   System("rm -rf /tmp/sema.38c;> /tmp/sema.38c");
450   if (pipe(tube) != 0) e(173);
451   switch (fork()) {
452       case -1:	printf("Can't fork\n");	break;
453       case 0:
454 	alarm(20);
455 	if (close(tube[0]) != 0) e(174);
456 	switch (fork()) {
457 	    case -1:	printf("Can't fork\n");	break;
458 	    case 0:
459 		alarm(20);
460 		for (i = 0; i < 100; i++) write(tube[1], "1234 ", 5);
461 		system("while test -f /tmp/sema.38c; do sleep 1; done");
462 		if (close(tube[1]) != 0) e(175);
463 		exit(0);
464 	    default:
465 		for (i = 0; i < 100; i++) write(tube[1], "1234 ", 5);
466 		while (stat("/tmp/sema.38c", &st1) == 0) sleep(1);
467 		if (close(tube[1]) != 0) e(176);
468 		if (wait(&stat_loc) == -1) e(177);
469 		if (stat_loc != 0) e(178);	/* Alarm? */
470 	}
471 	exit(stat_loc);
472       default:
473 	i = 0;
474 	if (close(tube[1]) != 0) e(179);
475 	memset(buf, '\0', BUF_SIZE);
476 	do {
477 		j = read(tube[0], buf + i, BUF_SIZE - i);
478 		if (j > 0) {
479 			if (j % 5 != 0) e(180);
480 			i += j;
481 		} else
482 			break;	/* EOF seen. */
483 	} while (i < 1000);
484 	unlink("/tmp/sema.38c");
485 	if (j < 0) e(181);
486 	if (i != 1000) e(182);
487 	if (close(tube[0]) != 0) e(183);
488 	if (wait(&stat_loc) == -1) e(184);
489 	if (stat_loc != 0) e(185);	/* Alarm? */
490 
491 	/* Check 200 times 1234. */
492 	for (i = 0; i < 200; i++)
493 		if (strncmp(buf + (i * 5), "1234 ", 5) != 0) break;
494 	if (i != 200) e(186);
495   }
496 }
497 
test38b()498 void test38b()
499 {
500   int i, fd, stat_loc;
501   char buf[BUF_SIZE];
502   char buf2[BUF_SIZE];
503   struct stat st;
504 
505   subtest = 2;
506   System("rm -rf ../DIR_38/*");
507 
508   /* Lets try sequential writes. */
509   system("rm -rf /tmp/sema.38d");
510   System("> testing");
511   switch (fork()) {
512       case -1:	printf("Can't fork\n");	break;
513       case 0:
514 	alarm(20);
515 	if ((fd = open("testing", O_WRONLY | O_APPEND)) != 3) e(1);
516 	if (write(fd, "one ", 4) != 4) e(2);
517 	if (close(fd) != 0) e(3);
518 	system("> /tmp/sema.38d");
519 	system("while test -f /tmp/sema.38d; do sleep 1; done");
520 	if ((fd = open("testing", O_WRONLY | O_APPEND)) != 3) e(4);
521 	if (write(fd, "three ", 6) != 6) e(5);
522 	if (close(fd) != 0) e(6);
523 	system("> /tmp/sema.38d");
524 	exit(0);
525       default:
526 	while (stat("/tmp/sema.38d", &st) != 0) sleep(1);
527 	if ((fd = open("testing", O_WRONLY | O_APPEND)) != 3) e(7);
528 	if (write(fd, "two ", 4) != 4) e(8);
529 	if (close(fd) != 0) e(9);
530 	unlink("/tmp/sema.38d");
531 	while (stat("/tmp/sema.38d", &st) != 0) sleep(1);
532 	if ((fd = open("testing", O_WRONLY | O_APPEND)) != 3) e(10);
533 	if (write(fd, "four", 5) != 5) e(11);
534 	if (close(fd) != 0) e(12);
535 	if (wait(&stat_loc) == -1) e(13);
536 	if (stat_loc != 0) e(14);	/* The alarm went off? */
537 	unlink("/tmp/sema.38d");
538   }
539   if ((fd = open("testing", O_RDONLY)) != 3) e(15);
540   if (read(fd, buf, BUF_SIZE) != 19) e(16);
541   if (strcmp(buf, "one two three four") != 0) e(17);
542   if (close(fd) != 0) e(18);
543 
544   /* Non written bytes in regular files should be zero. */
545   memset(buf2, '\0', BUF_SIZE);
546   if ((fd = open("bigfile", O_RDWR | O_CREAT, 0644)) != 3) e(19);
547   if (lseek(fd, (off_t) 102400, SEEK_SET) != (off_t) 102400L) e(20);
548   if (read(fd, buf, BUF_SIZE) != 0) e(21);
549   if (write(fd, ".", 1) != 1) e(22);
550   Stat("bigfile", &st);
551   if (st.st_size != (off_t) 102401) e(23);
552   if (lseek(fd, (off_t) 0, SEEK_SET) != 0) e(24);
553   for (i = 0; i < 102400 / BUF_SIZE; i++) {
554 	if (read(fd, buf, BUF_SIZE) != BUF_SIZE) e(25);
555 	if (memcmp(buf, buf2, BUF_SIZE) != 0) e(26);
556   }
557   if (close(fd) != 0) e(27);
558 }
559 
test38c()560 void test38c()
561 {				/* Test correct error behavior. */
562   char buf[BUF_SIZE];
563   int fd, tube[2], stat_loc;
564   struct stat st;
565   pid_t pid;
566 #ifdef SIGACTION
567   struct sigaction act, oact;
568 #else
569   void (*oldfunc) (int);
570 #endif
571 
572   subtest = 3;
573   System("rm -rf ../DIR_38/*");
574 
575   /* To test if writing processes on closed pipes are signumbered. */
576 #ifdef SIGACTION
577   act.sa_handler = setsignumber;
578   sigemptyset(&act.sa_mask);
579   act.sa_flags = 0;
580   if (sigaction(SIGPIPE, &act, &oact) != 0) e(1);
581 #else
582   oldfunc = signal(SIGPIPE, setsignumber);
583 #endif
584 
585   /* Non valid file descriptors should be an error. */
586   for (fd = -111; fd < 0; fd++) {
587 	errno = 0;
588 	if (read(fd, buf, BUF_SIZE) != -1) e(2);
589 	if (errno != EBADF) e(3);
590   }
591   for (fd = 3; fd < 111; fd++) {
592 	errno = 0;
593 	if (read(fd, buf, BUF_SIZE) != -1) e(4);
594 	if (errno != EBADF) e(5);
595   }
596   for (fd = -111; fd < 0; fd++) {
597 	errno = 0;
598 	if (write(fd, buf, BUF_SIZE) != -1) e(6);
599 	if (errno != EBADF) e(7);
600   }
601   for (fd = 3; fd < 111; fd++) {
602 	errno = 0;
603 	if (write(fd, buf, BUF_SIZE) != -1) e(8);
604 	if (errno != EBADF) e(9);
605   }
606 
607   /* Writing a pipe with no readers should trigger SIGPIPE. */
608   if (pipe(tube) != 0) e(10);
609   close(tube[0]);
610   switch (fork()) {
611       case -1:	printf("Can't fork\n");	break;
612       case 0:
613 	alarm(20);
614 	signumber = 0;
615 	if (write(tube[1], buf, BUF_SIZE) != -1) e(11);
616 	if (errno != EPIPE) e(12);
617 	if (signumber != SIGPIPE) e(13);
618 	if (close(tube[1]) != 0) e(14);
619 	exit(0);
620       default:
621 	close(tube[1]);
622 	if (wait(&stat_loc) == -1) e(15);
623 	if (stat_loc != 0) e(16);	/* Alarm? */
624   }
625 
626   /* Writing a fifo with no readers should trigger SIGPIPE. */
627   System("> /tmp/sema.38e");
628   if (mkfifo("fifo", 0666) != 0) e(17);
629   switch (fork()) {
630       case -1:	printf("Can't fork\n");	break;
631       case 0:
632 	alarm(20);
633 	if ((fd = open("fifo", O_WRONLY)) != 3) e(18);
634 	system("while test -f /tmp/sema.38e; do sleep 1; done");
635 	signumber = 0;
636 	if (write(fd, buf, BUF_SIZE) != -1) e(19);
637 	if (errno != EPIPE) e(20);
638 	if (signumber != SIGPIPE) e(21);
639 	if (close(fd) != 0) e(22);
640 	exit(0);
641       default:
642 	if ((fd = open("fifo", O_RDONLY)) != 3) e(23);
643 	if (close(fd) != 0) e(24);
644 	unlink("/tmp/sema.38e");
645 	if (wait(&stat_loc) == -1) e(25);
646 	if (stat_loc != 0) e(26);	/* Alarm? */
647   }
648 
649 #ifdef SIGACTION
650   /* Restore normal (re)action to SIGPIPE. */
651   if (sigaction(SIGPIPE, &oact, NULL) != 0) e(27);
652 #else
653   signal(SIGPIPE, oldfunc);
654 #endif
655 
656   /* Read from fifo should return -1 and set errno to EAGAIN. */
657   System("rm -rf /tmp/sema.38[fgh]");
658   switch (fork()) {
659       case -1:	printf("Can't fork\n");	break;
660       case 0:
661 	alarm(20);
662 	system("while test ! -f /tmp/sema.38f; do sleep 1; done");
663 	System("rm -rf /tmp/sema.38f");
664 	if ((fd = open("fifo", O_WRONLY | O_NONBLOCK)) != 3) e(28);
665 	close(creat("/tmp/sema.38g", 0666));
666 	system("while test ! -f /tmp/sema.38h; do sleep 1; done");
667 	if (close(fd) != 0) e(38);
668 	System("rm -rf /tmp/sema.38h");
669 	exit(0);
670       default:
671 	if ((fd = open("fifo", O_RDONLY | O_NONBLOCK)) != 3) e(30);
672 	close(creat("/tmp/sema.38f", 0666));
673 	system("while test ! -f /tmp/sema.38g; do sleep 1; done");
674 	System("rm -rf /tmp/sema.38g");
675 	if (read(fd, buf, BUF_SIZE) != -1) e(31);
676 	if (errno != EAGAIN) e(32);
677 	if (read(fd, buf, BUF_SIZE) != -1) e(33);
678 	if (errno != EAGAIN) e(34);
679 	if (read(fd, buf, BUF_SIZE) != -1) e(35);
680 	if (errno != EAGAIN) e(36);
681 	close(creat("/tmp/sema.38h", 0666));
682 	while (stat("/tmp/sema.38h", &st) == 0) sleep(1);
683 	if (read(fd, buf, BUF_SIZE) != 0) e(37);
684 	if (close(fd) != 0) e(38);
685 	if (wait(&stat_loc) == -1) e(39);
686 	if (stat_loc != 0) e(40);	/* Alarm? */
687   }
688   System("rm -rf fifo");
689 
690   /* If a read is interrupted by a SIGNAL. */
691   if (pipe(tube) != 0) e(41);
692   switch (pid = fork()) {
693       case -1:	printf("Can't fork\n");	break;
694       case 0:
695 	alarm(20);
696 #ifdef SIGACTION
697 	act.sa_handler = setsignumber;
698 	sigemptyset(&act.sa_mask);
699 	act.sa_flags = 0;
700 	if (sigaction(SIGUSR1, &act, &oact) != 0) e(42);
701 #else
702 	oldfunc = signal(SIGUSR1, setsignumber);
703 #endif
704 	if (read(tube[0], buf, BUF_SIZE) != -1) e(43);
705 	if (errno != EINTR) e(44);
706 	if (signumber != SIGUSR1) e(45);
707 #ifdef SIGACTION
708 	/* Restore normal (re)action to SIGPIPE. */
709 	if (sigaction(SIGUSR1, &oact, NULL) != 0) e(46);
710 #else
711 	signal(SIGUSR1, oldfunc);
712 #endif
713 	close(tube[0]);
714 	close(tube[1]);
715 	exit(0);
716       default:
717 	/* The sleep 1 should give the child time to start the read. */
718 	sleep(1);
719 	close(tube[0]);
720 	kill(pid, SIGUSR1);
721 	wait(&stat_loc);
722 	if (stat_loc != 0) e(47);	/* Alarm? */
723 	close(tube[1]);
724   }
725 }
726 
setsignumber(signum)727 void setsignumber(signum)
728 int signum;
729 {
730   signumber = signum;
731 }
732 
733