xref: /freebsd/tests/sys/kern/pipe/pipe_fstat_bug_test.c (revision 42b388439bd3795e09258c57a74ce9eec3651c7b)
1e30a6200SEnji Cooper /*
2e30a6200SEnji Cooper Copyright (C) 2004 Michael J. Silbersack. All rights reserved.
3e30a6200SEnji Cooper 
4e30a6200SEnji Cooper Redistribution and use in source and binary forms, with or without
5e30a6200SEnji Cooper modification, are permitted provided that the following conditions
6e30a6200SEnji Cooper are met:
7e30a6200SEnji Cooper 1. Redistributions of source code must retain the above copyright
8e30a6200SEnji Cooper    notice, this list of conditions and the following disclaimer.
9e30a6200SEnji Cooper 2. Redistributions in binary form must reproduce the above copyright
10e30a6200SEnji Cooper    notice, this list of conditions and the following disclaimer in the
11e30a6200SEnji Cooper    documentation and/or other materials provided with the distribution.
12e30a6200SEnji Cooper 
13e30a6200SEnji Cooper THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14e30a6200SEnji Cooper ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15e30a6200SEnji Cooper IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16e30a6200SEnji Cooper ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17e30a6200SEnji Cooper FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18e30a6200SEnji Cooper DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19e30a6200SEnji Cooper OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20e30a6200SEnji Cooper HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21e30a6200SEnji Cooper LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22e30a6200SEnji Cooper OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23e30a6200SEnji Cooper SUCH DAMAGE.
24e30a6200SEnji Cooper */
25e30a6200SEnji Cooper 
26e30a6200SEnji Cooper #include <sys/types.h>
27e30a6200SEnji Cooper #include <sys/stat.h>
28e30a6200SEnji Cooper #include <sys/wait.h>
29*21a4258dSRuslan Bukin #include <sys/event.h>
30e30a6200SEnji Cooper #include <assert.h>
31e30a6200SEnji Cooper #include <err.h>
32e30a6200SEnji Cooper #include <errno.h>
33e30a6200SEnji Cooper #include <inttypes.h>
34e30a6200SEnji Cooper #include <stdio.h>
35e30a6200SEnji Cooper #include <stdlib.h>
36e30a6200SEnji Cooper #include <unistd.h>
37e30a6200SEnji Cooper 
38e30a6200SEnji Cooper /*
39e30a6200SEnji Cooper  * The goal of this program is to see if fstat reports the correct
40e30a6200SEnji Cooper  * data count for a pipe.  Prior to revision 1.172 of sys_pipe.c,
41e30a6200SEnji Cooper  * 0 would be returned once the pipe entered direct write mode.
42e30a6200SEnji Cooper  *
43e30a6200SEnji Cooper  * Linux (2.6) always returns zero, so it's not a valuable platform
44e30a6200SEnji Cooper  * for comparison.
45e30a6200SEnji Cooper  */
46e30a6200SEnji Cooper 
47e30a6200SEnji Cooper int
main(void)48e30a6200SEnji Cooper main(void)
49e30a6200SEnji Cooper {
50e30a6200SEnji Cooper 	char buffer[32768], buffer2[32768], go[] = "go", go2[] = "go2";
51e30a6200SEnji Cooper 	int desc[2], ipc_coord[2];
52*21a4258dSRuslan Bukin 	struct kevent event, ke;
53e30a6200SEnji Cooper 	ssize_t error;
54e30a6200SEnji Cooper 	int successes = 0;
55e30a6200SEnji Cooper 	struct stat status;
56e30a6200SEnji Cooper 	pid_t new_pid;
57*21a4258dSRuslan Bukin 	int kq;
58e30a6200SEnji Cooper 
59e30a6200SEnji Cooper 	error = pipe(desc);
60e30a6200SEnji Cooper 	if (error == -1)
61e30a6200SEnji Cooper 		err(1, "Couldn't allocate data pipe");
62e30a6200SEnji Cooper 
63e30a6200SEnji Cooper 	error = pipe(ipc_coord);
64e30a6200SEnji Cooper 	if (error == -1)
65e30a6200SEnji Cooper 		err(1, "Couldn't allocate IPC coordination pipe");
66e30a6200SEnji Cooper 
67e30a6200SEnji Cooper 	new_pid = fork();
68e30a6200SEnji Cooper 	assert(new_pid != -1);
69e30a6200SEnji Cooper 
70e30a6200SEnji Cooper 	close(new_pid == 0 ? desc[0] : desc[1]);
71e30a6200SEnji Cooper 
72e30a6200SEnji Cooper #define	SYNC_R(i, _buf) do {	\
73e30a6200SEnji Cooper 	int _error = errno; \
74e30a6200SEnji Cooper 	warnx("%d: waiting for synchronization", __LINE__); \
75e30a6200SEnji Cooper 	if (read(ipc_coord[i], &_buf, sizeof(_buf)) != sizeof(_buf)) \
76e30a6200SEnji Cooper 		err(1, "failed to synchronize (%s)", (i == 0 ? "parent" : "child")); \
77e30a6200SEnji Cooper 	errno = _error; \
78e30a6200SEnji Cooper 	} while(0)
79e30a6200SEnji Cooper 
80e30a6200SEnji Cooper #define	SYNC_W(i, _buf) do {	\
81e30a6200SEnji Cooper 	int _error = errno; \
82e30a6200SEnji Cooper 	warnx("%d: sending synchronization", __LINE__); \
83e30a6200SEnji Cooper 	if (write(ipc_coord[i], &_buf, sizeof(_buf)) != sizeof(_buf)) \
84e30a6200SEnji Cooper 		err(1, "failed to synchronize (%s)", (i == 0 ? "child" : "parent")); \
85e30a6200SEnji Cooper 	errno = _error; \
86e30a6200SEnji Cooper 	} while(0)
87e30a6200SEnji Cooper 
88e30a6200SEnji Cooper #define	WRITE(s) do { 							\
89e30a6200SEnji Cooper 	ssize_t _size; 							\
90e30a6200SEnji Cooper 	if ((_size = write(desc[1], &buffer, s)) != s)			\
91e30a6200SEnji Cooper 		warn("short write; wrote %zd, expected %d", _size, s);	\
92e30a6200SEnji Cooper 	} while(0)
93e30a6200SEnji Cooper 
94e30a6200SEnji Cooper 	if (new_pid == 0) {
95e30a6200SEnji Cooper 
96e30a6200SEnji Cooper 		SYNC_R(0, go);
97e30a6200SEnji Cooper 		WRITE(145);
98e30a6200SEnji Cooper 		SYNC_W(0, go2);
99e30a6200SEnji Cooper 
100e30a6200SEnji Cooper 		SYNC_R(0, go);
101e30a6200SEnji Cooper 		WRITE(2048);
102e30a6200SEnji Cooper 		SYNC_W(0, go2);
103e30a6200SEnji Cooper 
104e30a6200SEnji Cooper 		SYNC_R(0, go);
105e30a6200SEnji Cooper 		WRITE(4096);
106e30a6200SEnji Cooper 		SYNC_W(0, go2);
107e30a6200SEnji Cooper 
108e30a6200SEnji Cooper 		SYNC_R(0, go);
109e30a6200SEnji Cooper 		WRITE(8191);
110e30a6200SEnji Cooper 		SYNC_W(0, go2);
111e30a6200SEnji Cooper 
112e30a6200SEnji Cooper 		SYNC_R(0, go);
113e30a6200SEnji Cooper 		SYNC_W(0, go2); /* XXX: why is this required? */
114e30a6200SEnji Cooper 		WRITE(8192);
115e30a6200SEnji Cooper 		SYNC_W(0, go2);
116e30a6200SEnji Cooper 
117e30a6200SEnji Cooper 		close(ipc_coord[0]);
118e30a6200SEnji Cooper 		close(ipc_coord[1]);
119e30a6200SEnji Cooper 
120e30a6200SEnji Cooper 		_exit(0);
121e30a6200SEnji Cooper 	}
122e30a6200SEnji Cooper 
123*21a4258dSRuslan Bukin 	kq = kqueue();
124*21a4258dSRuslan Bukin 	if (kq == -1)
125*21a4258dSRuslan Bukin 		_exit(1);
126*21a4258dSRuslan Bukin 
127*21a4258dSRuslan Bukin 	EV_SET(&ke, desc[0], EVFILT_READ, EV_ADD, 0, 0, NULL);
128*21a4258dSRuslan Bukin 
129*21a4258dSRuslan Bukin 	/* Attach event to the kqueue. */
130*21a4258dSRuslan Bukin 	if (kevent(kq, &ke, 1, NULL, 0, NULL) != 0)
131*21a4258dSRuslan Bukin 		_exit(2);
132*21a4258dSRuslan Bukin 
133e30a6200SEnji Cooper 	while (successes < 5) {
134e30a6200SEnji Cooper 		SYNC_W(1, go);
135e30a6200SEnji Cooper 		SYNC_R(1, go2);
136*21a4258dSRuslan Bukin 
137*21a4258dSRuslan Bukin 		/* Ensure data is available to read */
138*21a4258dSRuslan Bukin 		if (kevent(kq, NULL, 0, &event, 1, NULL) != 1)
139*21a4258dSRuslan Bukin 			_exit(3);
140*21a4258dSRuslan Bukin 
141e30a6200SEnji Cooper 		fstat(desc[0], &status);
142e30a6200SEnji Cooper 		error = read(desc[0], &buffer2, sizeof(buffer2));
143e30a6200SEnji Cooper 
144e30a6200SEnji Cooper 		if (status.st_size != error)
145e30a6200SEnji Cooper 			err(1, "FAILURE: stat size %jd read size %zd",
146e30a6200SEnji Cooper 			    (intmax_t)status.st_size, error);
147e30a6200SEnji Cooper 		if (error > 0) {
148e30a6200SEnji Cooper 			printf("SUCCESS at stat size %jd read size %zd\n",
149e30a6200SEnji Cooper 			    (intmax_t)status.st_size, error);
150e30a6200SEnji Cooper 			successes++;
151e30a6200SEnji Cooper 		}
152e30a6200SEnji Cooper 	}
153e30a6200SEnji Cooper 
154e30a6200SEnji Cooper 	exit(0);
155e30a6200SEnji Cooper }
156