1#!/bin/sh 2 3# 4# SPDX-License-Identifier: BSD-2-Clause 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 48newfs_flags="" 49newfs $newfs_flags -n md$mdstart > /dev/null 50mount /dev/md$mdstart $mntpoint 51set +e 52 53cd $mntpoint 54dd if=/dev/random of=input bs=4k count=100 status=none 55 56n=1 57start=` date +%s` 58while [ $((` date +%s` - start)) -lt 180 ]; do 59 rm -f output 60 umount $mntpoint 2>/dev/null # busy umount 61 $dir/socketpair4 62 s=$? 63 [ $s -ne 0 ] && { echo "Loop #$n"; ls -l; s=1; break; } 64 cmp -s input output || break 65 [ `stat -f '%z' input` -ne ` stat -f '%z' output` ] && break 66 n=$((n + 1)) 67done 68while pgrep -q swap; do 69 pkill swap 70done 71cmp -s input output || { echo "Loop #$n"; ls -l; s=1; } 72[ -f socketpair4.core -a $s -eq 0 ] && 73 { ls -l socketpair4.core; mv socketpair4.core $dir; s=1; } 74cd $odir 75 76for i in `jot 6`; do 77 mount | grep -q "on $mntpoint " || break 78 umount $mntpoint && break || sleep 10 79 [ $i -eq 6 ] && 80 { echo FATAL; fstat -mf $mntpoint; exit 1; } 81done 82mdconfig -d -u $mdstart 83rm -rf $dir/socketpair4 84exit $s 85 86EOF 87#include <sys/param.h> 88#include <sys/fcntl.h> 89#include <sys/socket.h> 90#include <sys/stat.h> 91#include <sys/uio.h> 92#include <sys/wait.h> 93 94#include <err.h> 95#include <errno.h> 96#include <fcntl.h> 97#include <stdio.h> 98#include <stdlib.h> 99#include <unistd.h> 100 101static void 102test(void) 103{ 104 struct stat st; 105 off_t rd, written; 106 pid_t pid; 107 int error, from, n, status, sv[2], to; 108 char buf[4086]; 109 const char *from_name, *to_name; 110 111 from_name = "input"; 112 to_name = "output"; 113 114 if ((error = socketpair(AF_UNIX, SOCK_STREAM, 0, sv)) == -1) 115 err(1, "socketpair"); 116 117 if ((from = open(from_name, O_RDONLY)) == -1) 118 err(1, "open read %s", from_name); 119 120 if ((error = fstat(from, &st)) == -1) 121 err(1, "stat %s", from_name); 122 123 pid = fork(); 124 if (pid == -1) 125 err(1, "fork"); 126 else if (pid != 0) { 127 setproctitle("parent"); 128 close(sv[1]); 129 130 written = 0; 131 for (;;) { 132 n = read(from, buf, sizeof(buf)); 133 if (n == -1) 134 err(1, "read(from)"); 135 else if (n == 0) 136 break; 137 written += n; 138 if (write(sv[0], buf, n) != n) 139 err(1, "write()"); 140 if (error == -1) 141 err(1, "write"); 142 } 143 if (written != st.st_size) 144 fprintf(stderr, "%d written, expected %d\n", 145 (int)written, (int)st.st_size); 146 close(from); 147 close(sv[0]); 148 if (waitpid(pid, &status, 0) != pid) 149 err(1, "waitpid(%d)", pid); 150 _exit(WEXITSTATUS(status)); 151 } else { 152 setproctitle("child"); 153 sleep(1); 154 close(from); 155 close(sv[0]); 156 157 if ((to = open(to_name, O_RDWR | O_CREAT, DEFFILEMODE)) == -1) 158 err(1, "open write %s", to_name); 159 160 rd = 0; 161 for (;;) { 162 n = read(sv[1], buf, sizeof(buf)); 163 if (n == -1) { 164 if (rd == st.st_size) { 165 err(1, "Expected EOF on read(socket)"); 166 break; 167 } 168 err(1, "read(socket), n=%d, rd=%d", n, 169 (int)rd); 170 } 171 if (n == 0) 172 break; 173 rd += n; 174 if (write(to, buf, n) != n) 175 err(1, "write()"); 176 } 177 close(to); 178 close(sv[1]); 179 if (rd != st.st_size) 180 fprintf(stderr, "Short read %d, expected %d\n", 181 (int)rd, (int)st.st_size); 182 _exit(0); 183 } 184} 185 186int 187main(void) 188{ 189 pid_t pid; 190 int status; 191 192 if ((pid = fork()) == 0) 193 test(); 194 if (pid == -1) 195 err(1, "fork()"); 196 if (waitpid(pid, &status, 0) == -1) 197 err(1, "waitpid(%d)", pid); 198 if (status != 0) { 199 if (WIFSIGNALED(status)) 200 fprintf(stderr, 201 "pid %d exit signal %d\n", 202 pid, WTERMSIG(status)); 203 } 204 205 return (WEXITSTATUS(status)); 206} 207