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