xref: /freebsd/tools/test/stress2/tools/flip.c (revision 273a89bb)
18a272653SPeter Holm /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
38a272653SPeter Holm  *
48a272653SPeter Holm  * Copyright (c) 2020 Peter Holm <pho@FreeBSD.org>
58a272653SPeter Holm  * All rights reserved.
68a272653SPeter Holm  *
78a272653SPeter Holm  * Redistribution and use in source and binary forms, with or without
88a272653SPeter Holm  * modification, are permitted provided that the following conditions
98a272653SPeter Holm  * are met:
108a272653SPeter Holm  * 1. Redistributions of source code must retain the above copyright
118a272653SPeter Holm  *    notice, this list of conditions and the following disclaimer.
128a272653SPeter Holm  * 2. Redistributions in binary form must reproduce the above copyright
138a272653SPeter Holm  *    notice, this list of conditions and the following disclaimer in the
148a272653SPeter Holm  *    documentation and/or other materials provided with the distribution.
158a272653SPeter Holm  *
168a272653SPeter Holm  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
178a272653SPeter Holm  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
188a272653SPeter Holm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
198a272653SPeter Holm  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
208a272653SPeter Holm  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
218a272653SPeter Holm  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
228a272653SPeter Holm  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
238a272653SPeter Holm  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
248a272653SPeter Holm  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
258a272653SPeter Holm  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
268a272653SPeter Holm  * SUCH DAMAGE.
278a272653SPeter Holm  */
288a272653SPeter Holm 
298a272653SPeter Holm /*
308a272653SPeter Holm  * Flip one or more bits in a file.
318a272653SPeter Holm  */
328a272653SPeter Holm 
338a272653SPeter Holm #include <sys/types.h>
348a272653SPeter Holm #include <sys/stat.h>
358a272653SPeter Holm 
368a272653SPeter Holm #include <err.h>
378a272653SPeter Holm #include <fcntl.h>
388a272653SPeter Holm #include <stdio.h>
398a272653SPeter Holm #include <stdlib.h>
408a272653SPeter Holm #include <string.h>
418a272653SPeter Holm #include <unistd.h>
428a272653SPeter Holm 
438a272653SPeter Holm extern char *optarg;
448a272653SPeter Holm extern int optind;
458a272653SPeter Holm 
468a272653SPeter Holm static long
random_long(long mi,long ma)478a272653SPeter Holm random_long(long mi, long ma)
488a272653SPeter Holm {
498a272653SPeter Holm         return (arc4random()  % (ma - mi + 1) + mi);
508a272653SPeter Holm }
518a272653SPeter Holm 
528a272653SPeter Holm static void
flip(void * ap,size_t len)538a272653SPeter Holm flip(void *ap, size_t len)
548a272653SPeter Holm {
558a272653SPeter Holm 	unsigned char *cp;
568a272653SPeter Holm 	int byte;
57171e56c1SPeter Holm 	unsigned char bit, buf, mask, old __unused;
588a272653SPeter Holm 
598a272653SPeter Holm 	cp = (unsigned char *)ap;
60ee10c61dSPeter Holm 	byte = random_long(0, len - 1);
618a272653SPeter Holm 	bit = random_long(0,7);
628a272653SPeter Holm 	mask = ~(1 << bit);
638a272653SPeter Holm 	buf = cp[byte];
648a272653SPeter Holm 	old = cp[byte];
658a272653SPeter Holm 	buf = (buf & mask) | (~buf & ~mask);
668a272653SPeter Holm 	cp[byte] = buf;
678a272653SPeter Holm #if defined(DEBUG)
688a272653SPeter Holm 	printf("Change %2x to %2x at %d by flipping bit %d\n",
698a272653SPeter Holm 	    old, buf, byte, bit);
708a272653SPeter Holm #endif
718a272653SPeter Holm }
728a272653SPeter Holm 
73ca0088aeSPeter Holm static void
trash(char * c)74ca0088aeSPeter Holm trash(char *c)
75ca0088aeSPeter Holm {
76ca0088aeSPeter Holm 	if (arc4random() % 2 == 1)
77ca0088aeSPeter Holm 		*c = 0;
78ca0088aeSPeter Holm 	else
79ca0088aeSPeter Holm 		arc4random_buf(c, sizeof(c));
80ca0088aeSPeter Holm }
81ca0088aeSPeter Holm 
828a272653SPeter Holm int
main(int argc,char * argv[])838a272653SPeter Holm main(int argc, char *argv[])
848a272653SPeter Holm {
858a272653SPeter Holm 	struct stat st;
868a272653SPeter Holm 	off_t pos;
87171e56c1SPeter Holm 	size_t size;
888a272653SPeter Holm 	int fd, i, times;
898a272653SPeter Holm 	char c;
908a272653SPeter Holm 
918a272653SPeter Holm 	times = 1;
92171e56c1SPeter Holm 	size = 0;
93171e56c1SPeter Holm 	while ((c = getopt(argc, argv, "n:s:")) != -1) {
948a272653SPeter Holm 		switch (c) {
958a272653SPeter Holm 			case 'n':
968a272653SPeter Holm 				times = atoi(optarg);
978a272653SPeter Holm 				break;
98171e56c1SPeter Holm 			case 's':
99171e56c1SPeter Holm 				size = atol(optarg);
100171e56c1SPeter Holm 				break;
1018a272653SPeter Holm 			case '?':
1028a272653SPeter Holm 			default:
1038a272653SPeter Holm 				fprintf(stderr,
1048a272653SPeter Holm 				    "Usage: %s [ -n <num> <file>]\n",
1058a272653SPeter Holm 				    argv[0]);
1068a272653SPeter Holm 				exit(1);
1078a272653SPeter Holm 		}
1088a272653SPeter Holm 	}
1098a272653SPeter Holm 	argc -= optind;
1108a272653SPeter Holm 	argv += optind;
1118a272653SPeter Holm 
1128a272653SPeter Holm 	if (argc != 1) {
1138a272653SPeter Holm 		fprintf(stderr, "Missing file name\n");
1148a272653SPeter Holm 		exit(1);
1158a272653SPeter Holm 	}
1168a272653SPeter Holm 
1178a272653SPeter Holm 	if ((fd = open(argv[0], O_RDWR)) == -1)
1188a272653SPeter Holm 		err(1, "open(%s)", argv[0]);
1198a272653SPeter Holm 
120171e56c1SPeter Holm 	if (size == 0) {
1218a272653SPeter Holm 		if (fstat(fd, &st) == -1)
1228a272653SPeter Holm 			err(1, "stat %s", argv[0]);
123ee10c61dSPeter Holm 		if ((st.st_mode & S_IFREG) == 0)
124ee10c61dSPeter Holm 			errx(1, "%s must be a regular file\n", argv[0]);
125171e56c1SPeter Holm 		size = st.st_size;
126171e56c1SPeter Holm 	}
1278a272653SPeter Holm 
1288a272653SPeter Holm 	for (i = 0; i < times; i++) {
129171e56c1SPeter Holm 		pos = arc4random() % size;
1308a272653SPeter Holm 		if (lseek(fd, pos, SEEK_SET) == -1)
1318a272653SPeter Holm 			err(1, "lseek()");
132171e56c1SPeter Holm 		if (read(fd, &c, 1) != 1)
133171e56c1SPeter Holm 			err(1, "read()");
134273a89bbSPeter Holm 		if (arc4random() % 100 < 98)
1358a272653SPeter Holm 			flip(&c, 1);
136ca0088aeSPeter Holm 		else
137ca0088aeSPeter Holm 			trash(&c);
1388a272653SPeter Holm 		if (lseek(fd, pos, SEEK_SET) == -1)
1398a272653SPeter Holm 			err(1, "lseek()");
140171e56c1SPeter Holm 		if (write(fd, &c, 1) != 1)
141171e56c1SPeter Holm 			err(1, "write()");
1428a272653SPeter Holm 	}
1438a272653SPeter Holm 
1448a272653SPeter Holm 	return (0);
1458a272653SPeter Holm }
146