xref: /freebsd/tools/test/stress2/misc/msdos18.sh (revision 59c8e88e72633afbc47a4ace0d2170d00d51f7dc)
1#!/bin/sh
2
3#
4# SPDX-License-Identifier: BSD-2-Clause
5#
6# Copyright (c) 2023 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# D38549: msdosfs deextend: validate pages of the partial buffer
31
32# https://people.freebsd.org/~pho/stress/log/log0420.txt
33
34[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
35
36. ../default.cfg
37
38set -eu
39prog=$(basename "$0" .sh)
40mkdir -p $mntpoint
41mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint
42[ -c /dev/md$mdstart ] &&  mdconfig -d -u $mdstart
43mdconfig -a -t swap -s 1g -u $mdstart
44newfs_msdos /dev/md$mdstart > /dev/null 2>&1
45mount -t msdosfs /dev/md$mdstart $mntpoint
46mount | grep $mntpoint
47set +e
48
49odir=`pwd`
50
51cd /tmp
52sed '1,/^EOF/d' < $odir/$0 > $prog.c
53cc -o $prog -Wall -O0 $prog.c -pthread || exit 1
54rm -f $prog.c
55cd $mntpoint
56
57in=inputFile
58out=outputFile
59
60/tmp/$prog $in $out 12345
61ls -al
62
63cd $odir
64umount $mntpoint
65mdconfig -d -u $mdstart
66rm -f /tmp/$prog
67exit
68EOF
69#include <sys/param.h>
70#include <sys/socket.h>
71#include <sys/stat.h>
72#include <sys/wait.h>
73
74#include <err.h>
75#include <fcntl.h>
76#include <netdb.h>
77#include <netinet/in.h>
78#include <pthread.h>
79#include <pthread_np.h>
80#include <signal.h>
81#include <stdio.h>
82#include <stdlib.h>
83#include <string.h>
84#include <time.h>
85#include <unistd.h>
86
87int fd, port;
88volatile int go;
89char *inputFile;
90char *outputFile;
91
92#define FSIZE 936374
93char buf[FSIZE];
94
95static void
96reader(void) {
97	struct sockaddr_in inetaddr, inetpeer;
98	socklen_t len;
99	int on, n, tcpsock, msgsock;
100
101	on = 1;
102	if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
103		err(1, "socket(), %s:%d", __FILE__, __LINE__);
104
105	if (setsockopt(tcpsock,
106	    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
107		err(1, "setsockopt(), %s:%d", __FILE__, __LINE__);
108
109	inetaddr.sin_family = AF_INET;
110	inetaddr.sin_addr.s_addr = INADDR_ANY;
111	inetaddr.sin_port = htons(port);
112	inetaddr.sin_len = sizeof(inetaddr);
113
114	if (bind(tcpsock,
115	    (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0)
116		err(1, "bind(), %s:%d", __FILE__, __LINE__);
117
118	if (listen(tcpsock, 5) < 0)
119		err(1, "listen(), %s:%d", __FILE__, __LINE__);
120
121	len = sizeof(inetpeer);
122	if ((msgsock = accept(tcpsock,
123	    (struct sockaddr *)&inetpeer, &len)) < 0)
124		err(1, "accept(), %s:%d", __FILE__, __LINE__);
125
126	if ((fd = open(outputFile, O_RDWR | O_CREAT | O_TRUNC, 0640)) == -1)
127		err(1, "open(%s)", outputFile);
128
129	usleep(arc4random() % 1000);
130	for (;;) {
131		if ((n = read(msgsock, buf, FSIZE)) < 0)
132			err(1, "read(), %s:%d", __FILE__, __LINE__);
133		if (n == 0)
134			break;
135
136	}
137	close(msgsock);
138	close(tcpsock);
139	close(fd);
140	return;
141}
142
143static void *
144thr(void *data __unused)
145{
146	pthread_set_name_np(pthread_self(), __func__);
147	go = 1;
148	while (go == 1) {
149		ftruncate(fd, FSIZE / 2);
150		ftruncate(fd, FSIZE);
151	}
152
153	return (NULL);
154}
155
156static void
157writer(void) {
158	struct hostent *hostent;
159	struct sockaddr_in inetaddr;
160	pthread_t tid;
161	off_t off = 0;
162	size_t size;
163	int i, on, r, tcpsock;
164
165	on = 1;
166	for (i = 1; i < 5; i++) {
167		if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
168			err(1, "socket(), %s:%d", __FILE__, __LINE__);
169
170		if (setsockopt(tcpsock,
171		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
172			err(1, "setsockopt(), %s:%d", __FILE__, __LINE__);
173
174		size = getpagesize();
175		if (setsockopt(tcpsock, SOL_SOCKET, SO_SNDBUF, (void *)&size,
176		    sizeof(size)) < 0)
177			err(1, "setsockopt(SO_SNDBUF), %s:%d",
178			    __FILE__, __LINE__);
179
180		hostent = gethostbyname ("localhost");
181		memcpy (&inetaddr.sin_addr.s_addr, hostent->h_addr,
182			sizeof (struct in_addr));
183
184		inetaddr.sin_family = AF_INET;
185		inetaddr.sin_port = htons(port);
186		inetaddr.sin_len = sizeof(inetaddr);
187
188		r = connect(tcpsock, (struct sockaddr *) &inetaddr,
189			sizeof(inetaddr));
190		if (r == 0)
191			break;
192		sleep(1);
193		close(tcpsock);
194	}
195	if (r < 0)
196		err(1, "connect(), %s:%d", __FILE__, __LINE__);
197
198	if ((fd = open(inputFile, O_RDWR | O_CREAT | O_TRUNC, 0640)) == -1)
199		err(1, "open(%s)", inputFile);
200
201	if (write(fd, buf, sizeof(buf)) != sizeof(buf))
202		err(1, "write()");
203
204	r = pthread_create(&tid, NULL, thr, NULL);
205	if (r)
206		errc(1, r, "pthread_create");
207
208	usleep(5000);
209	if (sendfile(fd, tcpsock, 0, FSIZE, NULL, &off, 0) == -1)
210		err(1, "sendfile");
211
212	usleep(arc4random() % 20000);
213	go = 0;
214	if ((r = pthread_join(tid, NULL)) != 0)
215		errc(1, r, "pthread_join");
216
217	_exit(0);
218}
219
220int
221main(int argc, char **argv)
222{
223	pid_t pid;
224	time_t start;
225
226	if (argc != 4) {
227		fprintf(stderr, "Usage: %s <inputFile outputFile portNumber\n",
228		    argv[0]);
229		return (1);
230	}
231	inputFile = argv[1];
232	outputFile = argv[2];
233	port = atoi(argv[3]);
234	pthread_set_name_np(pthread_self(), __func__);
235
236	start = time(NULL);
237	while (time(NULL) - start < 120) {
238		if ((pid = fork()) == 0) {
239			writer();
240		} else if (pid > 0) {
241			reader();
242			kill(pid, SIGINT);
243			if (waitpid(pid, NULL, 0) != pid)
244				err(1, "waitpid()");
245		} else
246			err(1, "fork(), %s:%d",  __FILE__, __LINE__);
247	}
248
249	return (0);
250}
251