xref: /freebsd/tests/sys/cddl/zfs/bin/mkfile.c (revision ac00d4d59b18a76c6148ca5d7439bb446d38da5c)
12fae26bdSAlan Somers /*-
22fae26bdSAlan Somers  * Copyright (c) 2001-2013
32fae26bdSAlan Somers  *	HATANO Tomomi.  All rights reserved.
42fae26bdSAlan Somers  *
52fae26bdSAlan Somers  * Redistribution and use in source and binary forms, with or without
62fae26bdSAlan Somers  * modification, are permitted provided that the following conditions
72fae26bdSAlan Somers  * are met:
82fae26bdSAlan Somers  * 1. Redistributions of source code must retain the above copyright
92fae26bdSAlan Somers  *    notice, this list of conditions and the following disclaimer.
102fae26bdSAlan Somers  * 2. Redistributions in binary form must reproduce the above copyright
112fae26bdSAlan Somers  *    notice, this list of conditions and the following disclaimer in the
122fae26bdSAlan Somers  *    documentation and/or other materials provided with the distribution.
132fae26bdSAlan Somers  *
142fae26bdSAlan Somers  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
152fae26bdSAlan Somers  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
162fae26bdSAlan Somers  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
172fae26bdSAlan Somers  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
182fae26bdSAlan Somers  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
192fae26bdSAlan Somers  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
202fae26bdSAlan Somers  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
212fae26bdSAlan Somers  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
222fae26bdSAlan Somers  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
232fae26bdSAlan Somers  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
242fae26bdSAlan Somers  * SUCH DAMAGE.
252fae26bdSAlan Somers  */
262fae26bdSAlan Somers 
272fae26bdSAlan Somers 
282fae26bdSAlan Somers #include <stdio.h>
292fae26bdSAlan Somers #include <stdlib.h>
302fae26bdSAlan Somers #include <string.h>
312fae26bdSAlan Somers #include <strings.h>
322fae26bdSAlan Somers #include <fcntl.h>
332fae26bdSAlan Somers #include <limits.h>
342fae26bdSAlan Somers #include <sys/stat.h>
352fae26bdSAlan Somers #include <sys/types.h>
362fae26bdSAlan Somers #include <sys/uio.h>
372fae26bdSAlan Somers #include <unistd.h>
382fae26bdSAlan Somers #include <ctype.h>
392fae26bdSAlan Somers #include <errno.h>
402fae26bdSAlan Somers 
412fae26bdSAlan Somers #define	MKFILE_WBUF	((size_t)(1048576))	/* Is 1M a reasonable value? */
422fae26bdSAlan Somers 
432fae26bdSAlan Somers /* SunOS's mkfile(8) sets "sticky bit." */
442fae26bdSAlan Somers #define	MKFILE_FLAG	(O_WRONLY | O_CREAT | O_TRUNC)
452fae26bdSAlan Somers #define	MKFILE_MODE	(S_IRUSR | S_IWUSR | S_ISVTX)
462fae26bdSAlan Somers 
472fae26bdSAlan Somers static char	buf[MKFILE_WBUF];
482fae26bdSAlan Somers static int	nofill = 0;
492fae26bdSAlan Somers static int	verbose = 0;
502fae26bdSAlan Somers 
512fae26bdSAlan Somers static void
usage()522fae26bdSAlan Somers usage()
532fae26bdSAlan Somers {
542fae26bdSAlan Somers 	fprintf(stderr,
552fae26bdSAlan Somers 	    "Usage: mkfile [-nv] <size>[e|p|t|g|m|k|b] <filename> ...\n");
562fae26bdSAlan Somers }
572fae26bdSAlan Somers 
582fae26bdSAlan Somers static unsigned long long
getsize(char * s)592fae26bdSAlan Somers getsize(char *s)
602fae26bdSAlan Somers {
612fae26bdSAlan Somers 	int sh;
622fae26bdSAlan Somers 	unsigned long long length;
632fae26bdSAlan Somers 	char *suffix;
642fae26bdSAlan Somers 
652fae26bdSAlan Somers 	/*
662fae26bdSAlan Somers 	 * NOTE: We don't handle 'Z' (zetta) or 'Y' (yotta) suffixes yet.
672fae26bdSAlan Somers 	 * These are too large to store in unsigned long long (64bits).
682fae26bdSAlan Somers 	 * In the future, we'll have to use larger type,
692fae26bdSAlan Somers 	 * something like uint128_t.
702fae26bdSAlan Somers 	 */
712fae26bdSAlan Somers 	length = strtoull(s, &suffix, 10);
722fae26bdSAlan Somers 	sh = 0;
732fae26bdSAlan Somers 	switch (tolower(*suffix)) {
742fae26bdSAlan Somers 	case 'e':	/* Exabytes. */
752fae26bdSAlan Somers 		sh = 60;
762fae26bdSAlan Somers 		break;
772fae26bdSAlan Somers 	case 'p':	/* Petabytes. */
782fae26bdSAlan Somers 		sh = 50;
792fae26bdSAlan Somers 		break;
802fae26bdSAlan Somers 	case 't':	/* Terabytes. */
812fae26bdSAlan Somers 		sh = 40;
822fae26bdSAlan Somers 		break;
832fae26bdSAlan Somers 	case 'g':	/* Gigabytes. */
842fae26bdSAlan Somers 		sh = 30;
852fae26bdSAlan Somers 		break;
862fae26bdSAlan Somers 	case 'm':	/* Megabytes. */
872fae26bdSAlan Somers 		sh = 20;
882fae26bdSAlan Somers 		break;
892fae26bdSAlan Somers 	case 'k':	/* Kilobytes. */
902fae26bdSAlan Somers 		sh = 10;
912fae26bdSAlan Somers 		break;
922fae26bdSAlan Somers 	case 'b':	/* Blocks. */
932fae26bdSAlan Somers 		sh = 9;
942fae26bdSAlan Somers 		break;
952fae26bdSAlan Somers 	case '\0':	/* Bytes. */
962fae26bdSAlan Somers 		break;
972fae26bdSAlan Somers 	default:	/* Unknown... */
982fae26bdSAlan Somers 		errno = EINVAL;
992fae26bdSAlan Somers 		return 0;
1002fae26bdSAlan Somers 	}
1012fae26bdSAlan Somers 	if (sh) {
1022fae26bdSAlan Somers 		unsigned long long l;
1032fae26bdSAlan Somers 
1042fae26bdSAlan Somers 		l = length;
1052fae26bdSAlan Somers 		length <<= sh;
1062fae26bdSAlan Somers 		/* Check overflow. */
1072fae26bdSAlan Somers 		if ((length >> sh) != l) {
1082fae26bdSAlan Somers 			errno = ERANGE;
1092fae26bdSAlan Somers 			return 0;
1102fae26bdSAlan Somers 		}
1112fae26bdSAlan Somers 	}
1122fae26bdSAlan Somers 
1132fae26bdSAlan Somers 	return length;
1142fae26bdSAlan Somers }
1152fae26bdSAlan Somers 
1162fae26bdSAlan Somers static int
create_file(char * f,unsigned long long s)1172fae26bdSAlan Somers create_file(char *f, unsigned long long s)
1182fae26bdSAlan Somers {
1192fae26bdSAlan Somers 	int fd;
1202fae26bdSAlan Somers 	size_t w;
1212fae26bdSAlan Somers 	ssize_t ws;
1222fae26bdSAlan Somers 
1232fae26bdSAlan Somers 	if (verbose) {
1242fae26bdSAlan Somers 		fprintf(stdout, "%s %llu bytes\n", f, s);
1252fae26bdSAlan Somers 		fflush(stdout);
1262fae26bdSAlan Somers 	}
1272fae26bdSAlan Somers 
1282fae26bdSAlan Somers 	/* Open file to create. */
1292fae26bdSAlan Somers 	if ((fd = open(f, MKFILE_FLAG, MKFILE_MODE)) < 0) {
1302fae26bdSAlan Somers 		return -1;
1312fae26bdSAlan Somers 	}
1322fae26bdSAlan Somers 
1332fae26bdSAlan Somers 	/* Seek to the end and write 1 byte. */
1342fae26bdSAlan Somers 	if ((lseek(fd, (off_t)(s - 1LL), SEEK_SET) == (off_t)-1) ||
1352fae26bdSAlan Somers 	    (write(fd, buf, (size_t)1) == (ssize_t)-1)) {
1362fae26bdSAlan Somers 		/*
1372fae26bdSAlan Somers 		 * We don't close(fd) here to avoid overwriting errno.
1382fae26bdSAlan Somers 		 * This is fd-leak, but is not harmful
1392fae26bdSAlan Somers 		 * because returning error causes mkfile(8) to exit.
1402fae26bdSAlan Somers 		 */
1412fae26bdSAlan Somers 		return -1;
1422fae26bdSAlan Somers 	}
1432fae26bdSAlan Somers 
1442fae26bdSAlan Somers 	/* Fill. */
1452fae26bdSAlan Somers 	if (!nofill) {
1462fae26bdSAlan Somers 		if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) {
1472fae26bdSAlan Somers 			/* Same as above. */
1482fae26bdSAlan Somers 			return -1;
1492fae26bdSAlan Somers 		}
1502fae26bdSAlan Somers 		while (s) {
1512fae26bdSAlan Somers 			w = (s > MKFILE_WBUF) ? MKFILE_WBUF : s;
1522fae26bdSAlan Somers 			if ((ws = write(fd, buf, w)) == (ssize_t)-1) {
1532fae26bdSAlan Somers 				/* Same as above. */
1542fae26bdSAlan Somers 				return -1;
1552fae26bdSAlan Somers 			}
1562fae26bdSAlan Somers 			s -= ws;
1572fae26bdSAlan Somers 		}
1582fae26bdSAlan Somers 	}
1592fae26bdSAlan Somers 	close(fd);
1602fae26bdSAlan Somers 
1612fae26bdSAlan Somers 	return 0;
1622fae26bdSAlan Somers }
1632fae26bdSAlan Somers 
1642fae26bdSAlan Somers int
main(int argc,char * argv[])1652fae26bdSAlan Somers main(int argc, char *argv[])
1662fae26bdSAlan Somers {
1672fae26bdSAlan Somers 	unsigned long long fsize;
168*ef8abddfSDag-Erling Smørgrav 	int ch;
1692fae26bdSAlan Somers 
1702fae26bdSAlan Somers 	/* We have at least 2 arguments. */
1712fae26bdSAlan Somers 	if (argc < 3) {
1722fae26bdSAlan Somers 		usage();
1732fae26bdSAlan Somers 		return EXIT_FAILURE;
1742fae26bdSAlan Somers 	}
1752fae26bdSAlan Somers 
1762fae26bdSAlan Somers 	/* Options. */
1772fae26bdSAlan Somers 	while ((ch = getopt(argc, argv, "nv")) != -1) {
1782fae26bdSAlan Somers 		switch (ch) {
1792fae26bdSAlan Somers 		case 'n':
1802fae26bdSAlan Somers 			nofill = 1;
1812fae26bdSAlan Somers 			break;
1822fae26bdSAlan Somers 		case 'v':
1832fae26bdSAlan Somers 			verbose = 1;
1842fae26bdSAlan Somers 			break;
1852fae26bdSAlan Somers 		default:
1862fae26bdSAlan Somers 			usage();
1872fae26bdSAlan Somers 			return EXIT_FAILURE;
1882fae26bdSAlan Somers 		}
1892fae26bdSAlan Somers 	}
1902fae26bdSAlan Somers 	argc -= optind;
1912fae26bdSAlan Somers 	argv += optind;
1922fae26bdSAlan Somers 
1932fae26bdSAlan Somers 	/* File size to create. */
1942fae26bdSAlan Somers 	if ((fsize = getsize(*argv)) == 0) {
1952fae26bdSAlan Somers 		perror(*argv);
1962fae26bdSAlan Somers 		return EXIT_FAILURE;
1972fae26bdSAlan Somers 	}
1982fae26bdSAlan Somers 
1992fae26bdSAlan Somers 	/* Filenames to create. */
2002fae26bdSAlan Somers 	bzero(buf, MKFILE_WBUF);
2012fae26bdSAlan Somers 	while (++argv, --argc) {
2022fae26bdSAlan Somers 		if (create_file(*argv, fsize) == -1) {
2032fae26bdSAlan Somers 			perror(*argv);
2042fae26bdSAlan Somers 			return EXIT_FAILURE;
2052fae26bdSAlan Somers 		}
2062fae26bdSAlan Somers 	}
2072fae26bdSAlan Somers 
2082fae26bdSAlan Somers 	return EXIT_SUCCESS;
2092fae26bdSAlan Somers }
210