1132524Ssilby/* 2132524SsilbyCopyright (C) 2004 Michael J. Silbersack. All rights reserved. 3132524Ssilby 4132524SsilbyRedistribution and use in source and binary forms, with or without 5132524Ssilbymodification, are permitted provided that the following conditions 6132524Ssilbyare met: 7132524Ssilby1. Redistributions of source code must retain the above copyright 8132524Ssilby notice, this list of conditions and the following disclaimer. 9132524Ssilby2. Redistributions in binary form must reproduce the above copyright 10132524Ssilby notice, this list of conditions and the following disclaimer in the 11132524Ssilby documentation and/or other materials provided with the distribution. 12132524Ssilby 13132524SsilbyTHIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14132524SsilbyANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15132524SsilbyIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16132524SsilbyARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 17132524SsilbyFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18132524SsilbyDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19132524SsilbyOR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20132524SsilbyHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21132524SsilbyLIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22132524SsilbyOUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23132524SsilbySUCH DAMAGE. 24132524Ssilby*/ 25132524Ssilby 26290914Sngie#include <sys/types.h> 27290914Sngie#include <sys/stat.h> 28290914Sngie#include <sys/wait.h> 29290914Sngie#include <assert.h> 30290914Sngie#include <err.h> 31290914Sngie#include <errno.h> 32132524Ssilby#include <stdio.h> 33290914Sngie#include <stdlib.h> 34290914Sngie#include <string.h> 35132524Ssilby#include <unistd.h> 36132524Ssilby 37132524Ssilby/* 38132524Ssilby * $FreeBSD$ 39132524Ssilby * This program tests to make sure that wraparound writes and reads 40132524Ssilby * are working, assuming that 16K socket buffers are used. In order 41132524Ssilby * to really stress the pipe code with this test, kernel modifications 42132524Ssilby * nay be necessary. 43132524Ssilby */ 44132524Ssilby 45132524Ssilbyint main (void) 46132524Ssilby{ 47290914Sngie char buffer[32768], buffer2[32768], go[] = "go", go2[] = "go2"; 48290914Sngie int desc[2], ipc_coord[2]; 49290914Sngie ssize_t error, total; 50290914Sngie int buggy, i; 51290914Sngie pid_t new_pid; 52132524Ssilby 53290914Sngie buggy = 0; 54290914Sngie total = 0; 55132524Ssilby 56290914Sngie error = pipe(desc); 57290914Sngie if (error == -1) 58290914Sngie err(1, "Couldn't allocate data pipe"); 59132524Ssilby 60290914Sngie error = pipe(ipc_coord); 61290914Sngie if (error == -1) 62290914Sngie err(1, "Couldn't allocate IPC coordination pipe"); 63132524Ssilby 64290914Sngie buffer[0] = 'A'; 65132524Ssilby 66290914Sngie for (i = 1; i < (int)sizeof(buffer); i++) { 67290914Sngie buffer[i] = buffer[i - 1] + 1; 68290914Sngie if (buffer[i] > 'Z') 69290914Sngie buffer[i] = 'A'; 70132524Ssilby } 71132524Ssilby 72290914Sngie new_pid = fork(); 73290914Sngie assert(new_pid != -1); 74132524Ssilby 75290914Sngie#define SYNC_R(i, _buf) do { \ 76290914Sngie int _error = errno; \ 77290914Sngie warnx("%d: waiting for synchronization", __LINE__); \ 78290914Sngie if (read(ipc_coord[i], &_buf, sizeof(_buf)) != sizeof(_buf)) \ 79290914Sngie err(1, "failed to synchronize (%s)", (i == 0 ? "parent" : "child")); \ 80290914Sngie errno = _error; \ 81290914Sngie } while(0) 82290914Sngie 83290914Sngie#define SYNC_W(i, _buf) do { \ 84290914Sngie int _error = errno; \ 85290914Sngie warnx("%d: sending synchronization", __LINE__); \ 86290914Sngie if (write(ipc_coord[i], &_buf, sizeof(_buf)) != sizeof(_buf)) \ 87290914Sngie err(1, "failed to synchronize (%s)", (i == 0 ? "child" : "parent")); \ 88290914Sngie errno = _error; \ 89290914Sngie } while(0) 90290914Sngie 91290914Sngie#define WRITE(s) do { \ 92290914Sngie ssize_t _size; \ 93290914Sngie if ((_size = write(desc[1], &buffer[total], s)) != s) \ 94290914Sngie warn("short write; wrote %zd, expected %d", _size, s); \ 95290914Sngie total += _size; \ 96290914Sngie } while(0) 97290914Sngie 98290914Sngie if (new_pid == 0) { 99290914Sngie WRITE(4096); 100290914Sngie WRITE(4096); 101290914Sngie WRITE(4000); 102290914Sngie SYNC_W(0, go2); 103290914Sngie 104290914Sngie SYNC_R(0, go); 105290914Sngie WRITE(3000); 106290914Sngie WRITE(3000); 107290914Sngie SYNC_W(0, go2); 108290914Sngie 109290914Sngie _exit(0); 110290914Sngie } 111290914Sngie 112290914Sngie SYNC_R(1, go2); 113132524Ssilby error = read(desc[0], &buffer2, 8192); 114132524Ssilby total += error; 115290914Sngie printf("Read %zd bytes\n", error); 116290914Sngie SYNC_W(1, go); 117290914Sngie SYNC_R(1, go2); 118132524Ssilby error = read(desc[0], &buffer2[total], 16384); 119132524Ssilby total += error; 120290914Sngie printf("Read %zd bytes, done\n", error); 121132524Ssilby 122290914Sngie if (memcmp(buffer, buffer2, total) != 0) { 123290914Sngie for (i = 0; i < total; i++) { 124290914Sngie if (buffer[i] != buffer2[i]) { 125290914Sngie buggy = 1; 126290914Sngie printf("Location %d input: %hhx output: %hhx\n", 127290914Sngie i, buffer[i], buffer2[i]); 128290914Sngie } 129132524Ssilby } 130132524Ssilby } 131132524Ssilby 132290914Sngie waitpid(new_pid, NULL, 0); 133290914Sngie 134290914Sngie if (buggy) 135290914Sngie errx(1, "FAILURE"); 136290914Sngie 137132524Ssilby printf("SUCCESS\n"); 138132524Ssilby 139290914Sngie exit(0); 140132524Ssilby} 141