tar: use utime() to restore timestamps
[minix.git] / test / t40d.c
blob4834ab17c07563dafc3f1a16b53269ff60aa9306
1 /* t40d.c
3 * Test FIFOs and pipes
5 * Select works on regular files, (pseudo) terminal devices, streams-based
6 * files, FIFOs, pipes, and sockets. This test verifies selecting for FIFOs
7 * (named pipes) and pipes (anonymous pipes). This test will not verify most
8 * error file descriptors, as the setting of this fdset in the face of an error
9 * condition is implementation-specific (except for regular files (alway set)
10 * and sockets (protocol-specific or OOB data received), but those file types
11 * are not being tested in this specific test).
13 * This test is part of a bigger select test. It expects as argument which sub-
14 * test it is.
16 * [1] If a socket has a pending error, it shall be considered to have an
17 * exceptional condition pending. Otherwise, what constitutes an exceptional
18 * condition is file type-specific. For a file descriptor for use with a
19 * socket, it is protocol-specific except as noted below. For other file types
20 * it is implementation-defined. If the operation is meaningless for a
21 * particular file type, pselect() or select() shall indicate that the
22 * descriptor is ready for read or write operations, and shall indicate that
23 * the descriptor has no exceptional condition pending.
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <sys/select.h>
33 #include <errno.h>
34 #include <sys/wait.h>
35 #include <string.h>
36 #include <time.h>
37 #include <assert.h>
39 #define NAMEDPIPE1 "selecttestd-1"
40 #define NAMEDPIPE2 "selecttestd-2"
41 #define SENDSTRING "minixrocks"
42 #define DO_HANDLEDATA 1
43 #define DO_PAUSE 3
44 #define DO_TIMEOUT 7
45 #define MAX_ERROR 5
47 int errct = 0, subtest = -1;
48 char errbuf[1000];
49 int fd_ap[2]; /* Anonymous pipe; read from fd_ap[0], write to fd_ap[1] */
50 int fd_np1; /* Named pipe */
51 int fd_np2; /* Named pipe */
53 void e(int n, char *s) {
54 printf("Subtest %d, error %d, %s\n", subtest, n, s);
56 if (errct++ > MAX_ERROR) {
57 printf("Too many errors; test aborted\n");
58 exit(errct);
62 void do_child(void) {
63 struct timeval tv;
65 /* Open named pipe for writing. This will block until a reader arrives. */
66 if((fd_np1 = open(NAMEDPIPE1, O_WRONLY)) == -1) {
67 printf("Error opening %s for writing, signalling parent to quit\n",
68 NAMEDPIPE1);
69 perror(NULL);
70 printf("Please make sure that %s is not in use while running this test\n",
71 NAMEDPIPE1);
72 exit(-1);
75 /* Going to sleep for three seconds to allow the parent proc to get ready */
76 tv.tv_sec = DO_HANDLEDATA;
77 tv.tv_usec = 0;
78 select(0, NULL, NULL, NULL, &tv);
80 /* Try to write. Doesn't matter how many bytes we actually send. */
81 (void) write(fd_np1, SENDSTRING, strlen(SENDSTRING));
83 /* Wait for another second to allow the parent to process incoming data */
84 tv.tv_sec = DO_HANDLEDATA;
85 tv.tv_usec = 0;
86 (void) select(0,NULL, NULL, NULL, &tv);
88 close(fd_np1);
90 /* Wait for another second to allow the parent to process incoming data */
91 tv.tv_sec = DO_HANDLEDATA;
92 tv.tv_usec = 0;
93 (void) select(0,NULL, NULL, NULL, &tv);
95 /* Open named pipe for reading. This will block until a writer arrives. */
96 if((fd_np2 = open(NAMEDPIPE2, O_RDONLY)) == -1) {
97 printf("Error opening %s for reading, signalling parent to quit\n",
98 NAMEDPIPE2);
99 perror(NULL);
100 printf("Please make sure that %s is not in use while running this test\n",
101 NAMEDPIPE2);
102 exit(-1);
105 /* Wait for another second to allow the parent to run some tests. */
106 tv.tv_sec = DO_HANDLEDATA;
107 tv.tv_usec = 0;
108 (void) select(0, NULL, NULL, NULL, &tv);
110 close(fd_np2);
112 /* Anonymous pipe */
114 /* Let the parent do initial read and write tests from and to the pipe. */
115 tv.tv_sec = DO_PAUSE;
116 tv.tv_usec = 0;
117 (void) select(0, NULL, NULL, NULL, &tv);
119 /* Unblock blocking read select by writing data */
120 if(write(fd_ap[1], SENDSTRING, strlen(SENDSTRING)) < 0) {
121 perror("Could not write to anonymous pipe");
122 exit(-1);
125 exit(0);
128 int count_fds(int nfds, fd_set *fds) {
129 /* Return number of bits set in fds */
130 int i, result = 0;
131 assert(fds != NULL && nfds > 0);
132 for(i = 0; i < nfds; i++) {
133 if(FD_ISSET(i, fds)) result++;
135 return result;
138 int empty_fds(int nfds, fd_set *fds) {
139 /* Returns nonzero if the first bits up to nfds in fds are not set */
140 int i;
141 assert(fds != NULL && nfds > 0);
142 for(i = 0; i < nfds; i++) if(FD_ISSET(i, fds)) return 0;
143 return 1;
146 int compare_fds(int nfds, fd_set *lh, fd_set *rh) {
147 /* Returns nonzero if lh equals rh up to nfds bits */
148 int i;
149 assert(lh != NULL && rh != NULL && nfds > 0);
150 for(i = 0; i < nfds; i++) {
151 if((FD_ISSET(i, lh) && !FD_ISSET(i, rh)) ||
152 (!FD_ISSET(i, lh) && FD_ISSET(i, rh))) {
153 return 0;
156 return 1;
159 void dump_fds(int nfds, fd_set *fds) {
160 /* Print a graphical representation of bits in fds */
161 int i;
162 if(fds != NULL && nfds > 0) {
163 for(i = 0; i < nfds; i++) printf("%d ", (FD_ISSET(i, fds) ? 1 : 0));
164 printf("\n");
168 void do_parent(int child) {
169 fd_set fds_read, fds_write, fds_error;
170 fd_set fds_compare_read, fds_compare_write;
171 struct timeval tv;
172 time_t start, end;
173 int retval;
174 char buf[20];
176 /* Open named pipe for reading. This will block until a writer arrives. */
177 if((fd_np1 = open(NAMEDPIPE1, O_RDONLY)) == -1) {
178 printf("Error opening %s for reading\n", NAMEDPIPE1);
179 perror(NULL);
180 printf("Please make sure that %s is not in use while running this test.\n",
181 NAMEDPIPE1);
182 waitpid(child, &retval, 0);
183 exit(-1);
186 /* Clear bit masks */
187 FD_ZERO(&fds_read); FD_ZERO(&fds_write);
188 /* Set read and write bits */
189 FD_SET(fd_np1, &fds_read);
190 FD_SET(fd_np1, &fds_write);
191 tv.tv_sec = DO_TIMEOUT;
192 tv.tv_usec = 0;
194 /* Test if we can read or write from/to fd_np1. As fd_np1 is opened read only
195 * we cannot actually write, so the select should return immediately [1] and
196 * the offending bit set in the fd set. We read from a pipe that is opened
197 * with O_NONBLOCKING cleared, so it is guaranteed we can read.
198 * However, at this moment the writer is sleeping, so the pipe is empty and
199 * read is supposed to block. Therefore, only 1 file descriptor should be
200 * ready. A timeout value is still set in case an error occurs in a faulty
201 * implementation. */
202 retval = select(fd_np1+1, &fds_read, &fds_write, NULL, &tv);
204 /* Did we receive an error? */
205 if(retval <= 0) {
206 snprintf(errbuf, sizeof(errbuf),
207 "one fd should be set%s", (retval == 0 ? " (TIMEOUT)" : ""));
208 e(1, errbuf);
211 if(!empty_fds(fd_np1+1,&fds_read)) e(2, "no read bits should be set");
214 /* Make sure the write bit is set (and just 1 bit) */
215 FD_ZERO(&fds_compare_write); FD_SET(fd_np1, &fds_compare_write);
216 if(!compare_fds(fd_np1+1, &fds_compare_write, &fds_write))
217 e(3, "write should be set");
219 /* Clear sets and set up new bit masks */
220 FD_ZERO(&fds_read); FD_ZERO(&fds_write);
221 FD_SET(fd_np1, &fds_read);
222 tv.tv_sec = DO_TIMEOUT; /* To make sure we get to see some error messages
223 instead of blocking forever when the
224 implementation is faulty. A timeout causes retval
225 to be 0. */
226 tv.tv_usec = 0;
227 /* The sleeping writer is about to wake up and write data to the pipe. */
228 retval = select(fd_np1+1, &fds_read, &fds_write, NULL, &tv);
230 /* Correct amount of ready file descriptors? Just 1 read */
231 if(retval != 1) {
232 snprintf(errbuf, sizeof(errbuf),
233 "one fd should be set%s", (retval == 0 ? " (TIMEOUT)" : ""));
234 e(4, errbuf);
237 if(!FD_ISSET(fd_np1, &fds_read)) e(5, "read should be set");
239 /* Note that we left the write set empty. This should be equivalent to
240 * setting this parameter to NULL. */
241 if(!empty_fds(fd_np1+1, &fds_write)) e(6, "write should NOT be set");
243 /* In case something went wrong above, we might end up with a child process
244 * blocking on a write call we close the file descriptor now. Synchronize on
245 * a read. */
246 if(read(fd_np1, buf, sizeof(SENDSTRING)) < 0) perror("Read error");
248 /* Close file descriptor. We're going to reverse the test */
249 close(fd_np1);
251 /* Wait for a second to allow the child to close the pipe as well */
252 tv.tv_sec = DO_HANDLEDATA;
253 tv.tv_usec = 0;
254 retval = select(0,NULL, NULL, NULL, &tv);
256 /* Open named pipe for writing. This call blocks until a reader arrives. */
257 if((fd_np2 = open(NAMEDPIPE2, O_WRONLY)) == -1) {
258 printf("Error opening %s for writing\n",
259 NAMEDPIPE2);
260 perror(NULL);
261 printf("Please make sure that %s is not in use while running this test\n",
262 NAMEDPIPE2);
263 exit(-1);
266 /* At this moment the child process has opened the named pipe for reading and
267 * we have opened it for writing. We're now going to reverse some of the
268 * tests we've done earlier. */
270 /* Clear sets and set up bit masks */
271 FD_ZERO(&fds_read); FD_ZERO(&fds_write); FD_ZERO(&fds_error);
272 FD_SET(fd_np2, &fds_read);
273 FD_SET(fd_np2, &fds_write);
274 tv.tv_sec = DO_TIMEOUT;
275 tv.tv_usec = 0;
276 /* Select for reading from an fd opened O_WRONLY. This should return
277 * immediately as it is not a meaningful operation [1] and is therefore not
278 * blocking. The select should return two file descriptors are ready (the
279 * failing read and valid write). */
281 retval = select(fd_np2+1, &fds_read, &fds_write, &fds_error, &tv);
283 /* Did we receive an error? */
284 if(retval <= 0) {
285 snprintf(errbuf, sizeof(errbuf),
286 "two fds should be set%s", (retval == 0 ? " (TIMEOUT)" : ""));
287 e(7, errbuf);
290 /* Make sure read bit is set (and just 1 bit) */
291 FD_ZERO(&fds_compare_read); FD_SET(fd_np2, &fds_compare_read);
292 if(!compare_fds(fd_np2+1, &fds_compare_read, &fds_read))
293 e(8, "read should be set");
295 /* Write bit should be set (and just 1 bit) */
296 FD_ZERO(&fds_compare_write); FD_SET(fd_np2, &fds_compare_write);
297 if(!compare_fds(fd_np2+1, &fds_compare_write, &fds_write))
298 e(9, "write should be set");
300 if(!empty_fds(fd_np2+1, &fds_error))
301 e(10, "Error should NOT be set");
303 FD_ZERO(&fds_read); FD_ZERO(&fds_write);
304 FD_SET(fd_np2, &fds_write);
305 tv.tv_sec = DO_TIMEOUT;
306 tv.tv_usec = 0;
307 retval = select(fd_np2+1, &fds_read, &fds_write, NULL, &tv);
309 /* Correct amount of ready file descriptors? Just 1 write */
310 if(retval != 1) {
311 snprintf(errbuf, sizeof(errbuf),
312 "one fd should be set%s", (retval == 0 ? " (TIMEOUT)" : ""));
313 e(11, errbuf);
316 if(!empty_fds(fd_np2+1, &fds_read)) e(12, "read should NOT be set");
318 /* Anonymous pipe */
320 /* Check if we can write to the pipe */
321 FD_ZERO(&fds_read); FD_ZERO(&fds_write);
322 FD_SET(fd_ap[1], &fds_write);
323 tv.tv_sec = DO_TIMEOUT;
324 tv.tv_usec = 0;
325 retval = select(fd_ap[1]+1, NULL, &fds_write, NULL, &tv);
327 /* Correct amount of ready file descriptors? Just 1 write */
328 if(retval != 1) {
329 snprintf(errbuf, sizeof(errbuf),
330 "one fd should be set%s", (retval == 0 ? " (TIMEOUT)" : ""));
331 e(13, errbuf);
334 /* Make sure write bit is set (and just 1 bit) */
335 FD_ZERO(&fds_compare_write); FD_SET(fd_ap[1], &fds_compare_write);
336 if(!compare_fds(fd_ap[1]+1, &fds_compare_write, &fds_write))
337 e(14, "write should be set");
339 /* Intentionally test reading from pipe and letting it time out. */
340 FD_SET(fd_ap[0], &fds_read);
341 tv.tv_sec = 1;
342 tv.tv_usec = 0;
343 start = time(NULL);
344 retval = select(fd_ap[0]+1, &fds_read, NULL, NULL, &tv);
345 end = time(NULL);
347 /* Did we time out? */
348 if(retval != 0) e(15, "we should have timed out");
350 /* Did it take us approximately 1 second? */
351 if((int) (end - start) != 1) {
352 snprintf(errbuf, sizeof(errbuf),
353 "time out is not 1 second (instead, it is %ld)",
354 (long int) (end - start));
355 e(16, errbuf);
358 /* Do another read, but this time we expect incoming data from child. */
359 FD_ZERO(&fds_read);
360 FD_SET(fd_ap[0], &fds_read);
361 tv.tv_sec = DO_TIMEOUT;
362 tv.tv_usec = 0;
363 retval = select(fd_ap[0]+1, &fds_read, NULL, NULL, &tv);
365 /* Correct amount of ready file descriptors? Just 1 read. */
366 if(retval != 1) e(17, "one fd should be set");
368 /* Is the read bit set? And just 1 bit. */
369 FD_ZERO(&fds_compare_read); FD_SET(fd_ap[0], &fds_compare_read);
370 if(!compare_fds(fd_ap[0]+1, &fds_compare_read, &fds_read))
371 e(18, "read should be set.");
373 /* By convention fd_ap[0] is meant to be used for reading from the pipe and
374 * fd_ap[1] is meant for writing, where fd_ap is a an anonymous pipe.
375 * However, it is unspecified what happens when fd_ap[0] is used for writing
376 * and fd_ap[1] for reading. (It is unsupported on Minix.) As such, it is not
377 * necessary to make test cases for wrong pipe file descriptors using select.
380 waitpid(child, &retval, 0);
381 unlink(NAMEDPIPE2);
382 unlink(NAMEDPIPE1);
383 exit(errct);
386 int main(int argc, char **argv) {
387 int forkres;
389 /* Get subtest number */
390 if(argc != 2) {
391 printf("Usage: %s subtest_no\n", argv[0]);
392 exit(-2);
393 } else if(sscanf(argv[1], "%d", &subtest) != 1) {
394 printf("Usage: %s subtest_no\n", argv[0]);
395 exit(-2);
398 /* Set up anonymous pipe */
399 if(pipe(fd_ap) < 0) {
400 perror("Could not create anonymous pipe");
401 exit(-1);
404 /* Create named pipe2. It is unlinked by do_parent. */
405 if(mkfifo(NAMEDPIPE1, 0600) < 0) {
406 printf("Could not create named pipe %s", NAMEDPIPE1);
407 perror(NULL);
408 exit(-1);
411 if(mkfifo(NAMEDPIPE2, 0600) < 0) {
412 printf("Could not create named pipe %s", NAMEDPIPE2);
413 perror(NULL);
414 exit(-1);
417 forkres = fork();
418 if(forkres == 0) do_child();
419 else if(forkres > 0) do_parent(forkres);
420 else { /* Fork failed */
421 perror("Unable to fork");
422 exit(-1);
425 exit(-2); /* We're not supposed to get here. Both do_* routines should exit*/