1#!/bin/sh 2 3# 4# Copyright (c) 2010 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# Test scenario for sendfile corruption of read only input file 30 31# Scenario by Ming Fu <Ming Fu watchguard com> 32 33. ../default.cfg 34 35odir=`pwd` 36 37cd /tmp 38sed '1,/^EOF/d' < $odir/$0 > sendfile2.c 39mycc -o sendfile2 -Wall sendfile2.c 40rm -f sendfile2.c 41[ -d "$RUNDIR" ] || mkdir -p $RUNDIR 42cd $RUNDIR 43 44dd if=/dev/random of=large bs=1m count=3 status=none 45md1=`md5 large` 46 47nc -l 7000 > lf & 48sleep 0.1 49/tmp/sendfile2 50kill $! 2>/dev/null 51wait 52 53md2=`md5 large` 54[ "$md1" != "$md2" ] && printf "%s\n%s\n" "$md1" "$md2" 55 56rm -f /tmp/sendfile2 large lf 57exit 58EOF 59#include <sys/types.h> 60#include <arpa/inet.h> 61#include <err.h> 62#include <fcntl.h> 63#include <netdb.h> 64#include <netinet/in.h> 65#include <stdio.h> 66#include <string.h> 67#include <strings.h> 68#include <sys/select.h> 69#include <sys/socket.h> 70#include <sys/stat.h> 71#include <sys/types.h> 72#include <sys/uio.h> 73#include <unistd.h> 74 75int 76main () { 77 int s, f; 78 struct sockaddr_in addr; 79 struct hostent *hostent; 80 int flags; 81 char str[32]="\r\n800\r\n"; 82 char *p = str; 83 struct stat sb; 84 int n; 85 fd_set wset; 86 int64_t size; 87 off_t sbytes; 88 off_t sent = 0; 89 int chunk; 90 91 alarm(120); 92 s = socket(AF_INET, SOCK_STREAM, 0); 93 bzero(&addr, sizeof(addr)); 94 addr.sin_family = AF_INET; 95 addr.sin_port = htons(7000); 96 hostent = gethostbyname ("localhost"); 97 memcpy (&addr.sin_addr.s_addr, hostent->h_addr, 98 sizeof (struct in_addr)); 99 100 n = connect(s, (struct sockaddr *)&addr, sizeof (addr)); 101 if (n < 0) 102 warn ("fail to connect"); 103 flags = fcntl(s, F_GETFL); 104 flags |= O_NONBLOCK; 105 fcntl(s, F_SETFL); 106 107 f = open("large", O_RDONLY); 108 if (f < 0) 109 warn("fail to open file"); 110 n = fstat(f, &sb); 111 if (n < 0) 112 warn("fstat failed"); 113 114 size = sb.st_size; 115 chunk = 0; 116 while (size > 0) { 117 FD_ZERO(&wset); 118 FD_SET(s, &wset); 119 n = select(f+1, NULL, &wset, NULL, NULL); 120 if (n < 0) 121 continue; 122 if (chunk > 0) { 123 sbytes = 0; 124 n = sendfile(f, s, sent, chunk, NULL, &sbytes, 0); 125 if (n < 0) 126 continue; 127 chunk -= sbytes; 128 size -= sbytes; 129 sent += sbytes; 130 continue; 131 } 132 if (size > 2048) 133 chunk = 2048; 134 else 135 chunk = size; 136 n = sprintf(str, "\r\n%x\r\n", 2048); 137 p = str; 138 write(s, p, n); 139 } 140 141 return (0); 142} 143