xref: /openbsd/regress/sys/fileops/fileops.c (revision 5b36a749)
1*5b36a749Sbluhm /* $OpenBSD: fileops.c,v 1.2 2017/05/29 13:49:40 bluhm Exp $ */
28b1dbb2aSsf /*
38b1dbb2aSsf  * Copyright (c) 2017 Stefan Fritsch <sf@sfritsch.de>
48b1dbb2aSsf  *
58b1dbb2aSsf  * Permission to use, copy, modify, and distribute this software for any
68b1dbb2aSsf  * purpose with or without fee is hereby granted, provided that the above
78b1dbb2aSsf  * copyright notice and this permission notice appear in all copies.
88b1dbb2aSsf  *
98b1dbb2aSsf  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
108b1dbb2aSsf  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
118b1dbb2aSsf  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
128b1dbb2aSsf  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
138b1dbb2aSsf  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
148b1dbb2aSsf  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
158b1dbb2aSsf  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
168b1dbb2aSsf  */
178b1dbb2aSsf #include <assert.h>
188b1dbb2aSsf #include <err.h>
198b1dbb2aSsf #include <fcntl.h>
208b1dbb2aSsf #include <stdint.h>
218b1dbb2aSsf #include <stdio.h>
228b1dbb2aSsf #include <stdlib.h>
238b1dbb2aSsf #include <string.h>
248b1dbb2aSsf #include <sys/mman.h>
258b1dbb2aSsf #include <sys/stat.h>
268b1dbb2aSsf #include <unistd.h>
278b1dbb2aSsf 
288b1dbb2aSsf #define BUFSIZE (16 * 1024)
298b1dbb2aSsf #define HOLESIZE (16 * BUFSIZE)
308b1dbb2aSsf 
318b1dbb2aSsf static int	 debug = 0;
328b1dbb2aSsf static int	 fd = -1;
338b1dbb2aSsf static off_t	 curpos = 0;
348b1dbb2aSsf static char	*fname;
358b1dbb2aSsf static char	*gbuf;
368b1dbb2aSsf static char	*mbuf;
378b1dbb2aSsf 
388b1dbb2aSsf void
gen_data(void * buf,size_t size,uint32_t seed)398b1dbb2aSsf gen_data(void *buf, size_t size, uint32_t seed)
408b1dbb2aSsf {
418b1dbb2aSsf 	assert(size % 4 == 0);
428b1dbb2aSsf 	if (debug)
438b1dbb2aSsf 		printf("%s: size %zd seed %#08x\n", __func__, size, seed);
448b1dbb2aSsf 	uint32_t *ibuf = buf;
458b1dbb2aSsf 	for (size_t i = 0; i < size / 4; i++)
468b1dbb2aSsf 		ibuf[i] = seed + i;
478b1dbb2aSsf }
488b1dbb2aSsf 
498b1dbb2aSsf void
check_data(const void * buf,size_t size,uint32_t seed)508b1dbb2aSsf check_data(const void *buf, size_t size, uint32_t seed)
518b1dbb2aSsf {
528b1dbb2aSsf 	assert(size % 4 == 0);
538b1dbb2aSsf 	const uint32_t *ibuf = buf;
548b1dbb2aSsf 	for (size_t i = 0; i < size / 4; i++) {
558b1dbb2aSsf 		if (ibuf[i] != seed + i) {
56*5b36a749Sbluhm 			errx(3, "%s: pos %zd/%zd: expected %#08zx got %#08x",
57*5b36a749Sbluhm 			    __func__, 4 * i, size, seed + i, ibuf[i]);
588b1dbb2aSsf 		}
598b1dbb2aSsf 	}
608b1dbb2aSsf }
618b1dbb2aSsf 
628b1dbb2aSsf void
check_zero(const void * buf,size_t size)638b1dbb2aSsf check_zero(const void *buf, size_t size)
648b1dbb2aSsf {
658b1dbb2aSsf 	assert(size % 4 == 0);
668b1dbb2aSsf 	const uint32_t *ibuf = buf;
678b1dbb2aSsf 	for (size_t i = 0; i < size / 4; i++) {
688b1dbb2aSsf 		if (ibuf[i] != 0) {
69*5b36a749Sbluhm 			errx(3, "%s: pos %zd/%zd: expected 0 got %#08x",
70*5b36a749Sbluhm 			    __func__, 4 * i, size, ibuf[i]);
718b1dbb2aSsf 		}
728b1dbb2aSsf 	}
738b1dbb2aSsf }
748b1dbb2aSsf 
758b1dbb2aSsf void
check(const char * what,int64_t have,int64_t want)768b1dbb2aSsf check(const char *what, int64_t have, int64_t want)
778b1dbb2aSsf {
788b1dbb2aSsf 	if (have != want) {
798b1dbb2aSsf 		if (have == -1)
80*5b36a749Sbluhm 			err(2, "%s returned %lld, expected %lld",
81*5b36a749Sbluhm 			    what, have, want);
828b1dbb2aSsf 		else
83*5b36a749Sbluhm 			errx(2, "%s returned %lld, expected %lld",
84*5b36a749Sbluhm 			    what, have, want);
858b1dbb2aSsf 	}
868b1dbb2aSsf 
878b1dbb2aSsf 	if (debug)
888b1dbb2aSsf 		printf("%s returned %lld\n", what, have);
898b1dbb2aSsf }
908b1dbb2aSsf 
918b1dbb2aSsf void
c_write(void * buf,size_t size)928b1dbb2aSsf c_write(void *buf, size_t size)
938b1dbb2aSsf {
948b1dbb2aSsf 	ssize_t ret = write(fd, buf, size);
958b1dbb2aSsf 	check("write", ret, size);
968b1dbb2aSsf 	curpos += ret;
978b1dbb2aSsf }
988b1dbb2aSsf 
998b1dbb2aSsf void
c_read(void * buf,size_t size)1008b1dbb2aSsf c_read(void *buf, size_t size)
1018b1dbb2aSsf {
1028b1dbb2aSsf 	ssize_t ret = read(fd, buf, size);
1038b1dbb2aSsf 	check("read", ret, size);
1048b1dbb2aSsf 	curpos += ret;
1058b1dbb2aSsf }
1068b1dbb2aSsf 
1078b1dbb2aSsf void
c_fsync(void)1088b1dbb2aSsf c_fsync(void)
1098b1dbb2aSsf {
1108b1dbb2aSsf 	int ret = fsync(fd);
1118b1dbb2aSsf 	check("fsync", ret, 0);
1128b1dbb2aSsf }
1138b1dbb2aSsf 
1148b1dbb2aSsf void
c_lseek(off_t offset,int whence)1158b1dbb2aSsf c_lseek(off_t offset, int whence)
1168b1dbb2aSsf {
1178b1dbb2aSsf 	off_t ret = lseek(fd, offset, whence);
1188b1dbb2aSsf 	switch (whence) {
1198b1dbb2aSsf 		case SEEK_SET:
1208b1dbb2aSsf 			curpos = offset;
1218b1dbb2aSsf 			break;
1228b1dbb2aSsf 		case SEEK_CUR:
1238b1dbb2aSsf 			curpos += offset;
1248b1dbb2aSsf 			break;
1258b1dbb2aSsf 		default:
126*5b36a749Sbluhm 			errx(1, "c_lseek not supported");
1278b1dbb2aSsf 	}
1288b1dbb2aSsf 	check("lseek", ret, curpos);
1298b1dbb2aSsf 	if (debug)
1308b1dbb2aSsf 		printf("curpos: %lld\n", (long long int)curpos);
1318b1dbb2aSsf }
1328b1dbb2aSsf 
1338b1dbb2aSsf void
c_mmap(size_t size)1348b1dbb2aSsf c_mmap(size_t size)
1358b1dbb2aSsf {
1368b1dbb2aSsf 	mbuf = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, curpos);
1378b1dbb2aSsf 	if (mbuf == MAP_FAILED)
138*5b36a749Sbluhm 		err(2, "mmap %zd pos %lld failed", size, (long long)curpos);
1398b1dbb2aSsf 	curpos += size;
1408b1dbb2aSsf 	if (debug)
1418b1dbb2aSsf 		printf("mmap: %p\n", mbuf);
1428b1dbb2aSsf }
1438b1dbb2aSsf 
1448b1dbb2aSsf void
c_munmap(size_t size)1458b1dbb2aSsf c_munmap(size_t size)
1468b1dbb2aSsf {
1478b1dbb2aSsf 	int ret = munmap(mbuf, size);
1488b1dbb2aSsf 	if (ret != 0)
149*5b36a749Sbluhm 		err(2, "munmap");
1508b1dbb2aSsf }
1518b1dbb2aSsf 
1528b1dbb2aSsf void
c_open(int flags)1538b1dbb2aSsf c_open(int flags)
1548b1dbb2aSsf {
1558b1dbb2aSsf 	fd = open(fname, flags, S_IRUSR|S_IWUSR);
1568b1dbb2aSsf 	if (fd == -1)
157*5b36a749Sbluhm 		err(1, "open");
1588b1dbb2aSsf }
1598b1dbb2aSsf 
1608b1dbb2aSsf void
check_read(size_t size,int hole)1618b1dbb2aSsf check_read(size_t size, int hole)
1628b1dbb2aSsf {
1638b1dbb2aSsf 	size_t pos = 0;
1648b1dbb2aSsf 	while (pos < size) {
1658b1dbb2aSsf 		size_t to_read = size - pos;
1668b1dbb2aSsf 		uint32_t seed = curpos;
1678b1dbb2aSsf 		if (to_read > BUFSIZE)
1688b1dbb2aSsf 			to_read = BUFSIZE;
1698b1dbb2aSsf 		c_read(gbuf, to_read);
1708b1dbb2aSsf 		if (hole)
1718b1dbb2aSsf 			check_zero(gbuf, to_read);
1728b1dbb2aSsf 		else
1738b1dbb2aSsf 			check_data(gbuf, to_read, seed);
1748b1dbb2aSsf 		pos += to_read;
1758b1dbb2aSsf 	}
1768b1dbb2aSsf }
1778b1dbb2aSsf 
1788b1dbb2aSsf /* XXX this assumes size is a multiple of the page size */
1798b1dbb2aSsf void
check_mmap(size_t size,int hole)1808b1dbb2aSsf check_mmap(size_t size, int hole)
1818b1dbb2aSsf {
1828b1dbb2aSsf 	size_t pos = 0;
1838b1dbb2aSsf 	while (pos < size) {
1848b1dbb2aSsf 		size_t to_read = size - pos;
1858b1dbb2aSsf 		uint32_t seed = curpos;
1868b1dbb2aSsf 		if (to_read > BUFSIZE)
1878b1dbb2aSsf 			to_read = BUFSIZE;
1888b1dbb2aSsf 		c_mmap(to_read);
1898b1dbb2aSsf 		if (hole)
1908b1dbb2aSsf 			check_zero(mbuf, to_read);
1918b1dbb2aSsf 		else
1928b1dbb2aSsf 			check_data(mbuf, to_read, seed);
1938b1dbb2aSsf 		c_munmap(to_read);
1948b1dbb2aSsf 		pos += to_read;
1958b1dbb2aSsf 	}
1968b1dbb2aSsf }
1978b1dbb2aSsf 
1988b1dbb2aSsf void
do_create(void)1998b1dbb2aSsf do_create(void)
2008b1dbb2aSsf {
2018b1dbb2aSsf 	unlink(fname);
2028b1dbb2aSsf 	c_open(O_EXCL|O_CREAT|O_RDWR);
2038b1dbb2aSsf 
2048b1dbb2aSsf 	gen_data(gbuf, BUFSIZE, curpos);
2058b1dbb2aSsf 	c_write(gbuf, BUFSIZE);
2068b1dbb2aSsf 
2078b1dbb2aSsf 	c_lseek(HOLESIZE, SEEK_CUR);
2088b1dbb2aSsf 
2098b1dbb2aSsf 	gen_data(gbuf, BUFSIZE, curpos);
2108b1dbb2aSsf 	c_write(gbuf, BUFSIZE);
2118b1dbb2aSsf 	c_fsync();
2128b1dbb2aSsf }
2138b1dbb2aSsf 
2148b1dbb2aSsf void
do_read(void)2158b1dbb2aSsf do_read(void)
2168b1dbb2aSsf {
2178b1dbb2aSsf 	c_open(O_RDWR);
2188b1dbb2aSsf 	check_read(BUFSIZE, 0);
2198b1dbb2aSsf 	check_read(HOLESIZE, 1);
2208b1dbb2aSsf 	check_read(BUFSIZE, 0);
2218b1dbb2aSsf }
2228b1dbb2aSsf 
2238b1dbb2aSsf void
do_mmap(void)2248b1dbb2aSsf do_mmap(void)
2258b1dbb2aSsf {
2268b1dbb2aSsf 	c_open(O_RDWR);
2278b1dbb2aSsf 	check_mmap(BUFSIZE, 0);
2288b1dbb2aSsf 	check_mmap(HOLESIZE, 1);
2298b1dbb2aSsf 	check_mmap(BUFSIZE, 0);
2308b1dbb2aSsf }
2318b1dbb2aSsf 
2328b1dbb2aSsf void
usage(void)2338b1dbb2aSsf usage(void)
2348b1dbb2aSsf {
235*5b36a749Sbluhm 	errx(1, "usage: fileops (create|read|mmap) filename");
2368b1dbb2aSsf }
2378b1dbb2aSsf 
main(int argc,char ** argv)2388b1dbb2aSsf int main(int argc, char **argv)
2398b1dbb2aSsf {
2408b1dbb2aSsf 	if (argc != 3)
2418b1dbb2aSsf 		usage();
2428b1dbb2aSsf 
2438b1dbb2aSsf 	fname = argv[2];
2448b1dbb2aSsf 	gbuf = malloc(BUFSIZE);
2458b1dbb2aSsf 	if (gbuf == NULL)
246*5b36a749Sbluhm 		err(1, "malloc");
2478b1dbb2aSsf 
2488b1dbb2aSsf 	if (strcmp(argv[1], "create") == 0) {
2498b1dbb2aSsf 		do_create();
2508b1dbb2aSsf 	} else if (strcmp(argv[1], "read") == 0) {
2518b1dbb2aSsf 		do_read();
2528b1dbb2aSsf 	} else if (strcmp(argv[1], "mmap") == 0) {
2538b1dbb2aSsf 		do_mmap();
2548b1dbb2aSsf 	} else {
2558b1dbb2aSsf 		usage();
2568b1dbb2aSsf 	}
2578b1dbb2aSsf 
258*5b36a749Sbluhm 	printf("pass\n");
2598b1dbb2aSsf 	return 0;
2608b1dbb2aSsf }
261