1#!/bin/sh 2 3# 4# Copyright (c) 2011 Peter Holm <pho@FreeBSD.org> 5# All rights reserved. 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 1. Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26# SUCH DAMAGE. 27# 28 29# sendfile(2) test by kib@ 30# Both processes will sit in the sbwait state forever: 31 32. ../default.cfg 33 34here=`pwd` 35cd /tmp 36sed '1,/^EOF/d' < $here/$0 > sendfile4.c 37mycc -o sendfile4 -Wall -Wextra -O2 sendfile4.c || exit 38rm -f sendfile4.c 39cd $here 40 41dd if=/dev/zero of=$diskimage bs=1m count=6 status=none 42/tmp/sendfile4 $diskimage || echo FAIL 43 44rm -f /tmp/sendfile4 $diskimage 45exit 46EOF 47#include <sys/types.h> 48#include <sys/fcntl.h> 49#include <sys/socket.h> 50#include <sys/stat.h> 51#include <sys/uio.h> 52#include <sys/wait.h> 53#include <err.h> 54#include <errno.h> 55#include <signal.h> 56#include <stdlib.h> 57#include <unistd.h> 58 59static void 60handler(int i __unused) { 61 _exit(1); 62} 63 64int 65main(int argc, char *argv[]) 66{ 67 const char *from_name; 68 char *buf; 69 int sv[2]; 70 struct stat st; 71 off_t written, pos; 72 int child, error, from, status; 73 74 if (argc != 2) 75 errx(1, "Usage: %s from", argv[0]); 76 from_name = argv[1]; 77 78 from = open(from_name, O_RDONLY); 79 if (from == -1) 80 err(1, "open read %s", from_name); 81 82 error = fstat(from, &st); 83 if (error == -1) 84 err(1, "stat %s", from_name); 85 86 error = socketpair(AF_UNIX, SOCK_STREAM, 0, sv); 87 if (error == -1) 88 err(1, "socketpair"); 89 90 signal(SIGALRM, handler); 91 alarm(120); 92 child = fork(); 93 if (child == -1) 94 err(1, "fork"); 95 else if (child != 0) { 96 close(sv[1]); 97 pos = 0; 98 for (;;) { 99 error = sendfile(from, sv[0], pos, st.st_size - pos, 100 NULL, &written, 0); 101 if (error == -1) { 102 if (errno != EAGAIN) 103 err(1, "sendfile"); 104 } 105 pos += written; 106 if (pos == st.st_size) 107 break; 108 } 109 close(sv[0]); 110 waitpid(child, &status, 0); 111 } else { 112 close(sv[0]); 113 buf = malloc(st.st_size); 114 if (buf == NULL) 115 err(1, "malloc %jd", st.st_size); 116 pos = 0; 117 for (;;) { 118 written = 413; 119 if (written > st.st_size - pos) 120 written = st.st_size - pos; 121#if 0 122 written = st.st_size - pos; 123 if (written > 1000) 124 written = 1000; 125 written = arc4random_uniform(written) + 1; 126#endif 127 error = read(sv[1], buf + pos, written); 128 if (error == -1) 129 err(1, "read"); 130 else if (error == 0) 131 errx(1, "short read"); 132 pos += error; 133 if (pos == st.st_size) 134 break; 135 } 136 close(sv[1]); 137 _exit(0); 138 } 139 140 return (0); 141} 142