1132438Ssilby/* 2132438SsilbyCopyright (C) 2004 Michael J. Silbersack. All rights reserved. 3132438Ssilby 4132438SsilbyRedistribution and use in source and binary forms, with or without 5132438Ssilbymodification, are permitted provided that the following conditions 6132438Ssilbyare met: 7132438Ssilby1. Redistributions of source code must retain the above copyright 8132438Ssilby notice, this list of conditions and the following disclaimer. 9132438Ssilby2. Redistributions in binary form must reproduce the above copyright 10132438Ssilby notice, this list of conditions and the following disclaimer in the 11132438Ssilby documentation and/or other materials provided with the distribution. 12132438Ssilby 13132438SsilbyTHIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14132438SsilbyANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15132438SsilbyIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16132438SsilbyARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 17132438SsilbyFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18132438SsilbyDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19132438SsilbyOR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20132438SsilbyHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21132438SsilbyLIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22132438SsilbyOUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23132438SsilbySUCH DAMAGE. 24132438Ssilby*/ 25132438Ssilby 26290914Sngie#include <sys/types.h> 27290914Sngie#include <sys/stat.h> 28290914Sngie#include <sys/wait.h> 29309662Sngie#include <sys/event.h> 30290914Sngie#include <assert.h> 31290914Sngie#include <err.h> 32290914Sngie#include <errno.h> 33290914Sngie#include <inttypes.h> 34132438Ssilby#include <stdio.h> 35290914Sngie#include <stdlib.h> 36132438Ssilby#include <unistd.h> 37132438Ssilby 38132438Ssilby/* 39132438Ssilby * $FreeBSD: stable/10/tests/sys/kern/pipe/pipe_fstat_bug_test.c 309662 2016-12-07 00:57:15Z ngie $ 40132438Ssilby * The goal of this program is to see if fstat reports the correct 41132438Ssilby * data count for a pipe. Prior to revision 1.172 of sys_pipe.c, 42132438Ssilby * 0 would be returned once the pipe entered direct write mode. 43132438Ssilby * 44132438Ssilby * Linux (2.6) always returns zero, so it's not a valuable platform 45132438Ssilby * for comparison. 46132438Ssilby */ 47132438Ssilby 48290914Sngieint 49290914Sngiemain(void) 50132438Ssilby{ 51290914Sngie char buffer[32768], buffer2[32768], go[] = "go", go2[] = "go2"; 52290914Sngie int desc[2], ipc_coord[2]; 53309662Sngie struct kevent event, ke; 54290914Sngie ssize_t error; 55290914Sngie int successes = 0; 56290914Sngie struct stat status; 57290914Sngie pid_t new_pid; 58309662Sngie int kq; 59132438Ssilby 60290914Sngie error = pipe(desc); 61290914Sngie if (error == -1) 62290914Sngie err(1, "Couldn't allocate data pipe"); 63132438Ssilby 64290914Sngie error = pipe(ipc_coord); 65290914Sngie if (error == -1) 66290914Sngie err(1, "Couldn't allocate IPC coordination pipe"); 67132438Ssilby 68290914Sngie new_pid = fork(); 69290914Sngie assert(new_pid != -1); 70132438Ssilby 71290914Sngie close(new_pid == 0 ? desc[0] : desc[1]); 72290914Sngie 73290914Sngie#define SYNC_R(i, _buf) do { \ 74290914Sngie int _error = errno; \ 75290914Sngie warnx("%d: waiting for synchronization", __LINE__); \ 76290914Sngie if (read(ipc_coord[i], &_buf, sizeof(_buf)) != sizeof(_buf)) \ 77290914Sngie err(1, "failed to synchronize (%s)", (i == 0 ? "parent" : "child")); \ 78290914Sngie errno = _error; \ 79290914Sngie } while(0) 80290914Sngie 81290914Sngie#define SYNC_W(i, _buf) do { \ 82290914Sngie int _error = errno; \ 83290914Sngie warnx("%d: sending synchronization", __LINE__); \ 84290914Sngie if (write(ipc_coord[i], &_buf, sizeof(_buf)) != sizeof(_buf)) \ 85290914Sngie err(1, "failed to synchronize (%s)", (i == 0 ? "child" : "parent")); \ 86290914Sngie errno = _error; \ 87290914Sngie } while(0) 88290914Sngie 89290914Sngie#define WRITE(s) do { \ 90290914Sngie ssize_t _size; \ 91290914Sngie if ((_size = write(desc[1], &buffer, s)) != s) \ 92290914Sngie warn("short write; wrote %zd, expected %d", _size, s); \ 93290914Sngie } while(0) 94290914Sngie 95290914Sngie if (new_pid == 0) { 96290914Sngie 97290914Sngie SYNC_R(0, go); 98290914Sngie WRITE(145); 99290914Sngie SYNC_W(0, go2); 100290914Sngie 101290914Sngie SYNC_R(0, go); 102290914Sngie WRITE(2048); 103290914Sngie SYNC_W(0, go2); 104290914Sngie 105290914Sngie SYNC_R(0, go); 106290914Sngie WRITE(4096); 107290914Sngie SYNC_W(0, go2); 108290914Sngie 109290914Sngie SYNC_R(0, go); 110290914Sngie WRITE(8191); 111290914Sngie SYNC_W(0, go2); 112290914Sngie 113290914Sngie SYNC_R(0, go); 114290914Sngie SYNC_W(0, go2); /* XXX: why is this required? */ 115290914Sngie WRITE(8192); 116290914Sngie SYNC_W(0, go2); 117290914Sngie 118290914Sngie close(ipc_coord[0]); 119290914Sngie close(ipc_coord[1]); 120290914Sngie 121290914Sngie _exit(0); 122290914Sngie } 123290914Sngie 124309662Sngie kq = kqueue(); 125309662Sngie if (kq == -1) 126309662Sngie _exit(1); 127309662Sngie 128309662Sngie EV_SET(&ke, desc[0], EVFILT_READ, EV_ADD, 0, 0, NULL); 129309662Sngie 130309662Sngie /* Attach event to the kqueue. */ 131309662Sngie if (kevent(kq, &ke, 1, NULL, 0, NULL) != 0) 132309662Sngie _exit(2); 133309662Sngie 134132438Ssilby while (successes < 5) { 135290914Sngie SYNC_W(1, go); 136290914Sngie SYNC_R(1, go2); 137309662Sngie 138309662Sngie /* Ensure data is available to read */ 139309662Sngie if (kevent(kq, NULL, 0, &event, 1, NULL) != 1) 140309662Sngie _exit(3); 141309662Sngie 142132438Ssilby fstat(desc[0], &status); 143290914Sngie error = read(desc[0], &buffer2, sizeof(buffer2)); 144290914Sngie 145132438Ssilby if (status.st_size != error) 146290914Sngie err(1, "FAILURE: stat size %jd read size %zd", 147290914Sngie (intmax_t)status.st_size, error); 148132438Ssilby if (error > 0) { 149290914Sngie printf("SUCCESS at stat size %jd read size %zd\n", 150290914Sngie (intmax_t)status.st_size, error); 151132438Ssilby successes++; 152132438Ssilby } 153132438Ssilby } 154132438Ssilby 155290914Sngie exit(0); 156132438Ssilby} 157