xref: /freebsd/tests/sys/kern/pipe/pipe_reverse_test.c (revision 42b388439bd3795e09258c57a74ce9eec3651c7b)
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 simply tests writing through the reverse direction of
39*e30a6200SEnji Cooper  * a pipe.  Nothing too fancy, it's only needed because most pipe-using
40*e30a6200SEnji Cooper  * programs never touch the reverse direction (it doesn't exist on
41*e30a6200SEnji Cooper  * Linux.)
42*e30a6200SEnji Cooper  */
43*e30a6200SEnji Cooper 
44*e30a6200SEnji Cooper int
main(void)45*e30a6200SEnji Cooper main(void)
46*e30a6200SEnji Cooper {
47*e30a6200SEnji Cooper 	char buffer[65535], buffer2[65535], go[] = "go", go2[] = "go2";
48*e30a6200SEnji Cooper 	int desc[2], ipc_coord[2];
49*e30a6200SEnji Cooper 	size_t i;
50*e30a6200SEnji Cooper 	ssize_t total;
51*e30a6200SEnji Cooper 	int buggy, error;
52*e30a6200SEnji Cooper 	pid_t new_pid;
53*e30a6200SEnji Cooper 
54*e30a6200SEnji Cooper 	buggy = 0;
55*e30a6200SEnji Cooper 	total = 0;
56*e30a6200SEnji Cooper 
57*e30a6200SEnji Cooper 	error = pipe(desc);
58*e30a6200SEnji Cooper 	if (error == -1)
59*e30a6200SEnji Cooper 		err(1, "Couldn't allocate data pipe");
60*e30a6200SEnji Cooper 
61*e30a6200SEnji Cooper 	error = pipe(ipc_coord);
62*e30a6200SEnji Cooper 	if (error == -1)
63*e30a6200SEnji Cooper 		err(1, "Couldn't allocate IPC coordination pipe");
64*e30a6200SEnji Cooper 
65*e30a6200SEnji Cooper 	buffer[0] = 'A';
66*e30a6200SEnji Cooper 
67*e30a6200SEnji Cooper 	for (i = 1; i < (int)sizeof(buffer); i++) {
68*e30a6200SEnji Cooper 		buffer[i] = buffer[i - 1] + 1;
69*e30a6200SEnji Cooper 		if (buffer[i] > 'Z')
70*e30a6200SEnji Cooper 			buffer[i] = 'A';
71*e30a6200SEnji Cooper 	}
72*e30a6200SEnji Cooper 
73*e30a6200SEnji Cooper 	new_pid = fork();
74*e30a6200SEnji Cooper 	assert(new_pid != -1);
75*e30a6200SEnji Cooper 
76*e30a6200SEnji Cooper #define	SYNC_R(i, _buf) do {	\
77*e30a6200SEnji Cooper 	int _error = errno; \
78*e30a6200SEnji Cooper 	warnx("%d: waiting for synchronization", __LINE__); \
79*e30a6200SEnji Cooper 	if (read(ipc_coord[i], &_buf, sizeof(_buf)) != sizeof(_buf)) \
80*e30a6200SEnji Cooper 		err(1, "failed to synchronize (%s)", (i == 0 ? "parent" : "child")); \
81*e30a6200SEnji Cooper 	errno = _error; \
82*e30a6200SEnji Cooper 	} while(0)
83*e30a6200SEnji Cooper 
84*e30a6200SEnji Cooper #define	SYNC_W(i, _buf) do {	\
85*e30a6200SEnji Cooper 	int _error = errno; \
86*e30a6200SEnji Cooper 	warnx("%d: sending synchronization", __LINE__); \
87*e30a6200SEnji Cooper 	if (write(ipc_coord[i], &_buf, sizeof(_buf)) != sizeof(_buf)) \
88*e30a6200SEnji Cooper 		err(1, "failed to synchronize (%s)", (i == 0 ? "child" : "parent")); \
89*e30a6200SEnji Cooper 	errno = _error; \
90*e30a6200SEnji Cooper 	} while(0)
91*e30a6200SEnji Cooper 
92*e30a6200SEnji Cooper #define	WRITE(s) do { 							\
93*e30a6200SEnji Cooper 	ssize_t _size; 							\
94*e30a6200SEnji Cooper 	if ((_size = write(desc[1], &buffer[total], s)) != s)		\
95*e30a6200SEnji Cooper 		warn("short write; wrote %zd, expected %d", _size, s);	\
96*e30a6200SEnji Cooper 	total += _size;							\
97*e30a6200SEnji Cooper 	} while(0)
98*e30a6200SEnji Cooper 
99*e30a6200SEnji Cooper 	if (new_pid == 0) {
100*e30a6200SEnji Cooper 		SYNC_R(0, go);
101*e30a6200SEnji Cooper 		for (i = 0; i < 8; i++)
102*e30a6200SEnji Cooper 			WRITE(4096);
103*e30a6200SEnji Cooper 
104*e30a6200SEnji Cooper 		SYNC_W(0, go2);
105*e30a6200SEnji Cooper 		SYNC_R(0, go);
106*e30a6200SEnji Cooper 
107*e30a6200SEnji Cooper 		for (i = 0; i < 2; i++)
108*e30a6200SEnji Cooper 			WRITE(4096);
109*e30a6200SEnji Cooper 
110*e30a6200SEnji Cooper 		SYNC_W(0, go2);
111*e30a6200SEnji Cooper 
112*e30a6200SEnji Cooper 		_exit(0);
113*e30a6200SEnji Cooper 	}
114*e30a6200SEnji Cooper 
115*e30a6200SEnji Cooper 	SYNC_W(1, go);
116*e30a6200SEnji Cooper 	SYNC_R(1, go2);
117*e30a6200SEnji Cooper 
118*e30a6200SEnji Cooper 	error = read(desc[0], &buffer2, 8 * 4096);
119*e30a6200SEnji Cooper 	total += error;
120*e30a6200SEnji Cooper 	printf("Read %d bytes\n", error);
121*e30a6200SEnji Cooper 
122*e30a6200SEnji Cooper 	SYNC_W(1, go);
123*e30a6200SEnji Cooper 	SYNC_R(1, go2);
124*e30a6200SEnji Cooper 
125*e30a6200SEnji Cooper 	error = read(desc[0], &buffer2[total], 2 * 4096);
126*e30a6200SEnji Cooper 	total += error;
127*e30a6200SEnji Cooper 	printf("Read %d bytes, done\n", error);
128*e30a6200SEnji Cooper 
129*e30a6200SEnji Cooper 	if (memcmp(buffer, buffer2, total) != 0) {
130*e30a6200SEnji Cooper 		for (i = 0; i < (size_t)total; i++) {
131*e30a6200SEnji Cooper 			if (buffer[i] != buffer2[i]) {
132*e30a6200SEnji Cooper 				buggy = 1;
133*e30a6200SEnji Cooper 				printf("Location %zu input: %hhx "
134*e30a6200SEnji Cooper 				    "output: %hhx\n",
135*e30a6200SEnji Cooper 				    i, buffer[i], buffer2[i]);
136*e30a6200SEnji Cooper 			}
137*e30a6200SEnji Cooper 		}
138*e30a6200SEnji Cooper 	}
139*e30a6200SEnji Cooper 
140*e30a6200SEnji Cooper 	waitpid(new_pid, NULL, 0);
141*e30a6200SEnji Cooper 
142*e30a6200SEnji Cooper 	if ((buggy == 1) || (total != 10 * 4096))
143*e30a6200SEnji Cooper 		errx(1, "FAILED");
144*e30a6200SEnji Cooper 	else
145*e30a6200SEnji Cooper 		printf("SUCCESS\n");
146*e30a6200SEnji Cooper 
147*e30a6200SEnji Cooper 	exit(0);
148*e30a6200SEnji Cooper }
149