1*e30a6200SEnji Cooper /*
2*e30a6200SEnji Cooper Copyright (C) 2004 Michael J. Silbersack. All rights reserved.
3*e30a6200SEnji Cooper
4*e30a6200SEnji Cooper Redistribution and use in source and binary forms, with or without
5*e30a6200SEnji Cooper modification, are permitted provided that the following conditions
6*e30a6200SEnji Cooper are met:
7*e30a6200SEnji Cooper 1. Redistributions of source code must retain the above copyright
8*e30a6200SEnji Cooper notice, this list of conditions and the following disclaimer.
9*e30a6200SEnji Cooper 2. Redistributions in binary form must reproduce the above copyright
10*e30a6200SEnji Cooper notice, this list of conditions and the following disclaimer in the
11*e30a6200SEnji Cooper documentation and/or other materials provided with the distribution.
12*e30a6200SEnji Cooper
13*e30a6200SEnji Cooper THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14*e30a6200SEnji Cooper ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15*e30a6200SEnji Cooper IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16*e30a6200SEnji Cooper ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17*e30a6200SEnji Cooper FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18*e30a6200SEnji Cooper DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19*e30a6200SEnji Cooper OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20*e30a6200SEnji Cooper HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21*e30a6200SEnji Cooper LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22*e30a6200SEnji Cooper OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23*e30a6200SEnji Cooper SUCH DAMAGE.
24*e30a6200SEnji Cooper */
25*e30a6200SEnji Cooper
26*e30a6200SEnji Cooper #include <sys/types.h>
27*e30a6200SEnji Cooper #include <sys/stat.h>
28*e30a6200SEnji Cooper #include <sys/wait.h>
29*e30a6200SEnji Cooper #include <assert.h>
30*e30a6200SEnji Cooper #include <err.h>
31*e30a6200SEnji Cooper #include <errno.h>
32*e30a6200SEnji Cooper #include <stdio.h>
33*e30a6200SEnji Cooper #include <stdlib.h>
34*e30a6200SEnji Cooper #include <string.h>
35*e30a6200SEnji Cooper #include <unistd.h>
36*e30a6200SEnji Cooper
37*e30a6200SEnji Cooper /*
38*e30a6200SEnji Cooper * This program tests to make sure that wraparound writes and reads
39*e30a6200SEnji Cooper * are working, assuming that 16K socket buffers are used. In order
40*e30a6200SEnji Cooper * to really stress the pipe code with this test, kernel modifications
41*e30a6200SEnji Cooper * nay be necessary.
42*e30a6200SEnji Cooper */
43*e30a6200SEnji Cooper
main(void)44*e30a6200SEnji Cooper int main (void)
45*e30a6200SEnji Cooper {
46*e30a6200SEnji Cooper char buffer[32768], buffer2[32768], go[] = "go", go2[] = "go2";
47*e30a6200SEnji Cooper int desc[2], ipc_coord[2];
48*e30a6200SEnji Cooper ssize_t error, total;
49*e30a6200SEnji Cooper int buggy, i;
50*e30a6200SEnji Cooper pid_t new_pid;
51*e30a6200SEnji Cooper
52*e30a6200SEnji Cooper buggy = 0;
53*e30a6200SEnji Cooper total = 0;
54*e30a6200SEnji Cooper
55*e30a6200SEnji Cooper error = pipe(desc);
56*e30a6200SEnji Cooper if (error == -1)
57*e30a6200SEnji Cooper err(1, "Couldn't allocate data pipe");
58*e30a6200SEnji Cooper
59*e30a6200SEnji Cooper error = pipe(ipc_coord);
60*e30a6200SEnji Cooper if (error == -1)
61*e30a6200SEnji Cooper err(1, "Couldn't allocate IPC coordination pipe");
62*e30a6200SEnji Cooper
63*e30a6200SEnji Cooper buffer[0] = 'A';
64*e30a6200SEnji Cooper
65*e30a6200SEnji Cooper for (i = 1; i < (int)sizeof(buffer); i++) {
66*e30a6200SEnji Cooper buffer[i] = buffer[i - 1] + 1;
67*e30a6200SEnji Cooper if (buffer[i] > 'Z')
68*e30a6200SEnji Cooper buffer[i] = 'A';
69*e30a6200SEnji Cooper }
70*e30a6200SEnji Cooper
71*e30a6200SEnji Cooper new_pid = fork();
72*e30a6200SEnji Cooper assert(new_pid != -1);
73*e30a6200SEnji Cooper
74*e30a6200SEnji Cooper #define SYNC_R(i, _buf) do { \
75*e30a6200SEnji Cooper int _error = errno; \
76*e30a6200SEnji Cooper warnx("%d: waiting for synchronization", __LINE__); \
77*e30a6200SEnji Cooper if (read(ipc_coord[i], &_buf, sizeof(_buf)) != sizeof(_buf)) \
78*e30a6200SEnji Cooper err(1, "failed to synchronize (%s)", (i == 0 ? "parent" : "child")); \
79*e30a6200SEnji Cooper errno = _error; \
80*e30a6200SEnji Cooper } while(0)
81*e30a6200SEnji Cooper
82*e30a6200SEnji Cooper #define SYNC_W(i, _buf) do { \
83*e30a6200SEnji Cooper int _error = errno; \
84*e30a6200SEnji Cooper warnx("%d: sending synchronization", __LINE__); \
85*e30a6200SEnji Cooper if (write(ipc_coord[i], &_buf, sizeof(_buf)) != sizeof(_buf)) \
86*e30a6200SEnji Cooper err(1, "failed to synchronize (%s)", (i == 0 ? "child" : "parent")); \
87*e30a6200SEnji Cooper errno = _error; \
88*e30a6200SEnji Cooper } while(0)
89*e30a6200SEnji Cooper
90*e30a6200SEnji Cooper #define WRITE(s) do { \
91*e30a6200SEnji Cooper ssize_t _size; \
92*e30a6200SEnji Cooper if ((_size = write(desc[1], &buffer[total], s)) != s) \
93*e30a6200SEnji Cooper warn("short write; wrote %zd, expected %d", _size, s); \
94*e30a6200SEnji Cooper total += _size; \
95*e30a6200SEnji Cooper } while(0)
96*e30a6200SEnji Cooper
97*e30a6200SEnji Cooper if (new_pid == 0) {
98*e30a6200SEnji Cooper WRITE(4096);
99*e30a6200SEnji Cooper WRITE(4096);
100*e30a6200SEnji Cooper WRITE(4000);
101*e30a6200SEnji Cooper SYNC_W(0, go2);
102*e30a6200SEnji Cooper
103*e30a6200SEnji Cooper SYNC_R(0, go);
104*e30a6200SEnji Cooper WRITE(3000);
105*e30a6200SEnji Cooper WRITE(3000);
106*e30a6200SEnji Cooper SYNC_W(0, go2);
107*e30a6200SEnji Cooper
108*e30a6200SEnji Cooper _exit(0);
109*e30a6200SEnji Cooper }
110*e30a6200SEnji Cooper
111*e30a6200SEnji Cooper SYNC_R(1, go2);
112*e30a6200SEnji Cooper error = read(desc[0], &buffer2, 8192);
113*e30a6200SEnji Cooper total += error;
114*e30a6200SEnji Cooper printf("Read %zd bytes\n", error);
115*e30a6200SEnji Cooper SYNC_W(1, go);
116*e30a6200SEnji Cooper SYNC_R(1, go2);
117*e30a6200SEnji Cooper error = read(desc[0], &buffer2[total], 16384);
118*e30a6200SEnji Cooper total += error;
119*e30a6200SEnji Cooper printf("Read %zd bytes, done\n", error);
120*e30a6200SEnji Cooper
121*e30a6200SEnji Cooper if (memcmp(buffer, buffer2, total) != 0) {
122*e30a6200SEnji Cooper for (i = 0; i < total; i++) {
123*e30a6200SEnji Cooper if (buffer[i] != buffer2[i]) {
124*e30a6200SEnji Cooper buggy = 1;
125*e30a6200SEnji Cooper printf("Location %d input: %hhx output: %hhx\n",
126*e30a6200SEnji Cooper i, buffer[i], buffer2[i]);
127*e30a6200SEnji Cooper }
128*e30a6200SEnji Cooper }
129*e30a6200SEnji Cooper }
130*e30a6200SEnji Cooper
131*e30a6200SEnji Cooper waitpid(new_pid, NULL, 0);
132*e30a6200SEnji Cooper
133*e30a6200SEnji Cooper if (buggy)
134*e30a6200SEnji Cooper errx(1, "FAILURE");
135*e30a6200SEnji Cooper
136*e30a6200SEnji Cooper printf("SUCCESS\n");
137*e30a6200SEnji Cooper
138*e30a6200SEnji Cooper exit(0);
139*e30a6200SEnji Cooper }
140