1#!/bin/sh 2 3# 4# SPDX-License-Identifier: BSD-2-Clause-FreeBSD 5# 6# Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> 7# 8# Redistribution and use in source and binary forms, with or without 9# modification, are permitted provided that the following conditions 10# are met: 11# 1. Redistributions of source code must retain the above copyright 12# notice, this list of conditions and the following disclaimer. 13# 2. Redistributions in binary form must reproduce the above copyright 14# notice, this list of conditions and the following disclaimer in the 15# documentation and/or other materials provided with the distribution. 16# 17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27# SUCH DAMAGE. 28# 29 30# A socketpair() test scenario illustrating issues with a missing EOF 31# Fixed by r361037 + r361056 32 33. ../default.cfg 34[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1 35 36dir=/tmp 37odir=`pwd` 38cd $dir 39sed '1,/^EOF/d' < $odir/$0 > $dir/socketpair4.c 40mycc -o socketpair4 -Wall -Wextra -O0 -g socketpair4.c || exit 1 41rm -f socketpair4.c 42cd $odir 43 44set -e 45mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint 46[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart 47mdconfig -a -t swap -s 1g -u $mdstart 48bsdlabel -w md$mdstart auto 49newfs_flags="" 50newfs $newfs_flags -n md$mdstart > /dev/null 51mount /dev/md$mdstart $mntpoint 52set +e 53 54cd $mntpoint 55dd if=/dev/random of=input bs=4k count=100 status=none 56 57n=1 58start=` date +%s` 59while [ $((` date +%s` - start)) -lt 180 ]; do 60 rm -f output 61 umount $mntpoint 2>/dev/null # busy umount 62 $dir/socketpair4 63 s=$? 64 [ $s -ne 0 ] && { echo "Loop #$n"; ls -l; s=1; break; } 65 cmp -s input output || break 66 [ `stat -f '%z' input` -ne ` stat -f '%z' output` ] && break 67 n=$((n + 1)) 68done 69while pgrep -q swap; do 70 pkill swap 71done 72cmp -s input output || { echo "Loop #$n"; ls -l; s=1; } 73[ -f socketpair4.core -a $s -eq 0 ] && 74 { ls -l socketpair4.core; mv socketpair4.core $dir; s=1; } 75cd $odir 76 77for i in `jot 6`; do 78 mount | grep -q "on $mntpoint " || break 79 umount $mntpoint && break || sleep 10 80 [ $i -eq 6 ] && 81 { echo FATAL; fstat -mf $mntpoint; exit 1; } 82done 83mdconfig -d -u $mdstart 84rm -rf $dir/socketpair4 85exit $s 86 87EOF 88#include <sys/param.h> 89#include <sys/fcntl.h> 90#include <sys/socket.h> 91#include <sys/stat.h> 92#include <sys/uio.h> 93#include <sys/wait.h> 94 95#include <err.h> 96#include <errno.h> 97#include <fcntl.h> 98#include <stdio.h> 99#include <stdlib.h> 100#include <unistd.h> 101 102static void 103test(void) 104{ 105 struct stat st; 106 off_t rd, written; 107 pid_t pid; 108 int error, from, n, status, sv[2], to; 109 char buf[4086]; 110 const char *from_name, *to_name; 111 112 from_name = "input"; 113 to_name = "output"; 114 115 if ((error = socketpair(AF_UNIX, SOCK_STREAM, 0, sv)) == -1) 116 err(1, "socketpair"); 117 118 if ((from = open(from_name, O_RDONLY)) == -1) 119 err(1, "open read %s", from_name); 120 121 if ((error = fstat(from, &st)) == -1) 122 err(1, "stat %s", from_name); 123 124 pid = fork(); 125 if (pid == -1) 126 err(1, "fork"); 127 else if (pid != 0) { 128 setproctitle("parent"); 129 close(sv[1]); 130 131 written = 0; 132 for (;;) { 133 n = read(from, buf, sizeof(buf)); 134 if (n == -1) 135 err(1, "read(from)"); 136 else if (n == 0) 137 break; 138 written += n; 139 if (write(sv[0], buf, n) != n) 140 err(1, "write()"); 141 if (error == -1) 142 err(1, "write"); 143 } 144 if (written != st.st_size) 145 fprintf(stderr, "%d written, expected %d\n", 146 (int)written, (int)st.st_size); 147 close(from); 148 close(sv[0]); 149 if (waitpid(pid, &status, 0) != pid) 150 err(1, "waitpid(%d)", pid); 151 _exit(WEXITSTATUS(status)); 152 } else { 153 setproctitle("child"); 154 sleep(1); 155 close(from); 156 close(sv[0]); 157 158 if ((to = open(to_name, O_RDWR | O_CREAT, DEFFILEMODE)) == -1) 159 err(1, "open write %s", to_name); 160 161 rd = 0; 162 for (;;) { 163 n = read(sv[1], buf, sizeof(buf)); 164 if (n == -1) { 165 if (rd == st.st_size) { 166 err(1, "Expected EOF on read(socket)"); 167 break; 168 } 169 err(1, "read(socket), n=%d, rd=%d", n, 170 (int)rd); 171 } 172 if (n == 0) 173 break; 174 rd += n; 175 if (write(to, buf, n) != n) 176 err(1, "write()"); 177 } 178 close(to); 179 close(sv[1]); 180 if (rd != st.st_size) 181 fprintf(stderr, "Short read %d, expected %d\n", 182 (int)rd, (int)st.st_size); 183 _exit(0); 184 } 185} 186 187int 188main(void) 189{ 190 pid_t pid; 191 int status; 192 193 if ((pid = fork()) == 0) 194 test(); 195 if (pid == -1) 196 err(1, "fork()"); 197 if (waitpid(pid, &status, 0) == -1) 198 err(1, "waitpid(%d)", pid); 199 if (status != 0) { 200 if (WIFSIGNALED(status)) 201 fprintf(stderr, 202 "pid %d exit signal %d\n", 203 pid, WTERMSIG(status)); 204 } 205 206 return (WEXITSTATUS(status)); 207} 208