xref: /freebsd/tests/sys/cddl/zfs/bin/mkfile.c (revision ef8abddf103d9dfd5660d50d15e6dbfbb2f47f62)
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 #ifndef	lint
282fae26bdSAlan Somers static char rcsid[] = "$Id: mkfile.c,v 1.5 2013-10-26 10:11:34+09 hatanou Exp $";
292fae26bdSAlan Somers #endif	/* !lint */
302fae26bdSAlan Somers 
312fae26bdSAlan Somers #include <stdio.h>
322fae26bdSAlan Somers #include <stdlib.h>
332fae26bdSAlan Somers #include <string.h>
342fae26bdSAlan Somers #include <strings.h>
352fae26bdSAlan Somers #include <fcntl.h>
362fae26bdSAlan Somers #include <limits.h>
372fae26bdSAlan Somers #include <sys/stat.h>
382fae26bdSAlan Somers #include <sys/types.h>
392fae26bdSAlan Somers #include <sys/uio.h>
402fae26bdSAlan Somers #include <unistd.h>
412fae26bdSAlan Somers #include <ctype.h>
422fae26bdSAlan Somers #include <errno.h>
432fae26bdSAlan Somers 
442fae26bdSAlan Somers #define	MKFILE_WBUF	((size_t)(1048576))	/* Is 1M a reasonable value? */
452fae26bdSAlan Somers 
462fae26bdSAlan Somers /* SunOS's mkfile(8) sets "sticky bit." */
472fae26bdSAlan Somers #define	MKFILE_FLAG	(O_WRONLY | O_CREAT | O_TRUNC)
482fae26bdSAlan Somers #define	MKFILE_MODE	(S_IRUSR | S_IWUSR | S_ISVTX)
492fae26bdSAlan Somers 
502fae26bdSAlan Somers static char	buf[MKFILE_WBUF];
512fae26bdSAlan Somers static int	nofill = 0;
522fae26bdSAlan Somers static int	verbose = 0;
532fae26bdSAlan Somers 
542fae26bdSAlan Somers static void
552fae26bdSAlan Somers usage()
562fae26bdSAlan Somers {
572fae26bdSAlan Somers 	fprintf(stderr,
582fae26bdSAlan Somers 	    "Usage: mkfile [-nv] <size>[e|p|t|g|m|k|b] <filename> ...\n");
592fae26bdSAlan Somers }
602fae26bdSAlan Somers 
612fae26bdSAlan Somers static unsigned long long
622fae26bdSAlan Somers getsize(char *s)
632fae26bdSAlan Somers {
642fae26bdSAlan Somers 	int sh;
652fae26bdSAlan Somers 	unsigned long long length;
662fae26bdSAlan Somers 	char *suffix;
672fae26bdSAlan Somers 
682fae26bdSAlan Somers 	/*
692fae26bdSAlan Somers 	 * NOTE: We don't handle 'Z' (zetta) or 'Y' (yotta) suffixes yet.
702fae26bdSAlan Somers 	 * These are too large to store in unsigned long long (64bits).
712fae26bdSAlan Somers 	 * In the future, we'll have to use larger type,
722fae26bdSAlan Somers 	 * something like uint128_t.
732fae26bdSAlan Somers 	 */
742fae26bdSAlan Somers 	length = strtoull(s, &suffix, 10);
752fae26bdSAlan Somers 	sh = 0;
762fae26bdSAlan Somers 	switch (tolower(*suffix)) {
772fae26bdSAlan Somers 	case 'e':	/* Exabytes. */
782fae26bdSAlan Somers 		sh = 60;
792fae26bdSAlan Somers 		break;
802fae26bdSAlan Somers 	case 'p':	/* Petabytes. */
812fae26bdSAlan Somers 		sh = 50;
822fae26bdSAlan Somers 		break;
832fae26bdSAlan Somers 	case 't':	/* Terabytes. */
842fae26bdSAlan Somers 		sh = 40;
852fae26bdSAlan Somers 		break;
862fae26bdSAlan Somers 	case 'g':	/* Gigabytes. */
872fae26bdSAlan Somers 		sh = 30;
882fae26bdSAlan Somers 		break;
892fae26bdSAlan Somers 	case 'm':	/* Megabytes. */
902fae26bdSAlan Somers 		sh = 20;
912fae26bdSAlan Somers 		break;
922fae26bdSAlan Somers 	case 'k':	/* Kilobytes. */
932fae26bdSAlan Somers 		sh = 10;
942fae26bdSAlan Somers 		break;
952fae26bdSAlan Somers 	case 'b':	/* Blocks. */
962fae26bdSAlan Somers 		sh = 9;
972fae26bdSAlan Somers 		break;
982fae26bdSAlan Somers 	case '\0':	/* Bytes. */
992fae26bdSAlan Somers 		break;
1002fae26bdSAlan Somers 	default:	/* Unknown... */
1012fae26bdSAlan Somers 		errno = EINVAL;
1022fae26bdSAlan Somers 		return 0;
1032fae26bdSAlan Somers 	}
1042fae26bdSAlan Somers 	if (sh) {
1052fae26bdSAlan Somers 		unsigned long long l;
1062fae26bdSAlan Somers 
1072fae26bdSAlan Somers 		l = length;
1082fae26bdSAlan Somers 		length <<= sh;
1092fae26bdSAlan Somers 		/* Check overflow. */
1102fae26bdSAlan Somers 		if ((length >> sh) != l) {
1112fae26bdSAlan Somers 			errno = ERANGE;
1122fae26bdSAlan Somers 			return 0;
1132fae26bdSAlan Somers 		}
1142fae26bdSAlan Somers 	}
1152fae26bdSAlan Somers 
1162fae26bdSAlan Somers 	return length;
1172fae26bdSAlan Somers }
1182fae26bdSAlan Somers 
1192fae26bdSAlan Somers static int
1202fae26bdSAlan Somers create_file(char *f, unsigned long long s)
1212fae26bdSAlan Somers {
1222fae26bdSAlan Somers 	int fd;
1232fae26bdSAlan Somers 	size_t w;
1242fae26bdSAlan Somers 	ssize_t ws;
1252fae26bdSAlan Somers 
1262fae26bdSAlan Somers 	if (verbose) {
1272fae26bdSAlan Somers 		fprintf(stdout, "%s %llu bytes\n", f, s);
1282fae26bdSAlan Somers 		fflush(stdout);
1292fae26bdSAlan Somers 	}
1302fae26bdSAlan Somers 
1312fae26bdSAlan Somers 	/* Open file to create. */
1322fae26bdSAlan Somers 	if ((fd = open(f, MKFILE_FLAG, MKFILE_MODE)) < 0) {
1332fae26bdSAlan Somers 		return -1;
1342fae26bdSAlan Somers 	}
1352fae26bdSAlan Somers 
1362fae26bdSAlan Somers 	/* Seek to the end and write 1 byte. */
1372fae26bdSAlan Somers 	if ((lseek(fd, (off_t)(s - 1LL), SEEK_SET) == (off_t)-1) ||
1382fae26bdSAlan Somers 	    (write(fd, buf, (size_t)1) == (ssize_t)-1)) {
1392fae26bdSAlan Somers 		/*
1402fae26bdSAlan Somers 		 * We don't close(fd) here to avoid overwriting errno.
1412fae26bdSAlan Somers 		 * This is fd-leak, but is not harmful
1422fae26bdSAlan Somers 		 * because returning error causes mkfile(8) to exit.
1432fae26bdSAlan Somers 		 */
1442fae26bdSAlan Somers 		return -1;
1452fae26bdSAlan Somers 	}
1462fae26bdSAlan Somers 
1472fae26bdSAlan Somers 	/* Fill. */
1482fae26bdSAlan Somers 	if (!nofill) {
1492fae26bdSAlan Somers 		if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) {
1502fae26bdSAlan Somers 			/* Same as above. */
1512fae26bdSAlan Somers 			return -1;
1522fae26bdSAlan Somers 		}
1532fae26bdSAlan Somers 		while (s) {
1542fae26bdSAlan Somers 			w = (s > MKFILE_WBUF) ? MKFILE_WBUF : s;
1552fae26bdSAlan Somers 			if ((ws = write(fd, buf, w)) == (ssize_t)-1) {
1562fae26bdSAlan Somers 				/* Same as above. */
1572fae26bdSAlan Somers 				return -1;
1582fae26bdSAlan Somers 			}
1592fae26bdSAlan Somers 			s -= ws;
1602fae26bdSAlan Somers 		}
1612fae26bdSAlan Somers 	}
1622fae26bdSAlan Somers 	close(fd);
1632fae26bdSAlan Somers 
1642fae26bdSAlan Somers 	return 0;
1652fae26bdSAlan Somers }
1662fae26bdSAlan Somers 
1672fae26bdSAlan Somers int
1682fae26bdSAlan Somers main(int argc, char *argv[])
1692fae26bdSAlan Somers {
1702fae26bdSAlan Somers 	unsigned long long fsize;
171*ef8abddfSDag-Erling Smørgrav 	int ch;
1722fae26bdSAlan Somers 
1732fae26bdSAlan Somers 	/* We have at least 2 arguments. */
1742fae26bdSAlan Somers 	if (argc < 3) {
1752fae26bdSAlan Somers 		usage();
1762fae26bdSAlan Somers 		return EXIT_FAILURE;
1772fae26bdSAlan Somers 	}
1782fae26bdSAlan Somers 
1792fae26bdSAlan Somers 	/* Options. */
1802fae26bdSAlan Somers 	while ((ch = getopt(argc, argv, "nv")) != -1) {
1812fae26bdSAlan Somers 		switch (ch) {
1822fae26bdSAlan Somers 		case 'n':
1832fae26bdSAlan Somers 			nofill = 1;
1842fae26bdSAlan Somers 			break;
1852fae26bdSAlan Somers 		case 'v':
1862fae26bdSAlan Somers 			verbose = 1;
1872fae26bdSAlan Somers 			break;
1882fae26bdSAlan Somers 		default:
1892fae26bdSAlan Somers 			usage();
1902fae26bdSAlan Somers 			return EXIT_FAILURE;
1912fae26bdSAlan Somers 		}
1922fae26bdSAlan Somers 	}
1932fae26bdSAlan Somers 	argc -= optind;
1942fae26bdSAlan Somers 	argv += optind;
1952fae26bdSAlan Somers 
1962fae26bdSAlan Somers 	/* File size to create. */
1972fae26bdSAlan Somers 	if ((fsize = getsize(*argv)) == 0) {
1982fae26bdSAlan Somers 		perror(*argv);
1992fae26bdSAlan Somers 		return EXIT_FAILURE;
2002fae26bdSAlan Somers 	}
2012fae26bdSAlan Somers 
2022fae26bdSAlan Somers 	/* Filenames to create. */
2032fae26bdSAlan Somers 	bzero(buf, MKFILE_WBUF);
2042fae26bdSAlan Somers 	while (++argv, --argc) {
2052fae26bdSAlan Somers 		if (create_file(*argv, fsize) == -1) {
2062fae26bdSAlan Somers 			perror(*argv);
2072fae26bdSAlan Somers 			return EXIT_FAILURE;
2082fae26bdSAlan Somers 		}
2092fae26bdSAlan Somers 	}
2102fae26bdSAlan Somers 
2112fae26bdSAlan Somers 	return EXIT_SUCCESS;
2122fae26bdSAlan Somers }
213