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