xref: /freebsd/tools/test/stress2/misc/sendfile2.sh (revision 22d7dd834bc5cd189810e414701e3ad1e98102e4)
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, flags);
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