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