diff options
Diffstat (limited to 'tests/sys/cddl/zfs/bin/mkfile.c')
| -rw-r--r-- | tests/sys/cddl/zfs/bin/mkfile.c | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/tests/sys/cddl/zfs/bin/mkfile.c b/tests/sys/cddl/zfs/bin/mkfile.c new file mode 100644 index 000000000000..0b7f43c8f42f --- /dev/null +++ b/tests/sys/cddl/zfs/bin/mkfile.c @@ -0,0 +1,209 @@ +/*- + * Copyright (c) 2001-2013 + * HATANO Tomomi. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <fcntl.h> +#include <limits.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <unistd.h> +#include <ctype.h> +#include <errno.h> + +#define MKFILE_WBUF ((size_t)(1048576)) /* Is 1M a reasonable value? */ + +/* SunOS's mkfile(8) sets "sticky bit." */ +#define MKFILE_FLAG (O_WRONLY | O_CREAT | O_TRUNC) +#define MKFILE_MODE (S_IRUSR | S_IWUSR | S_ISVTX) + +static char buf[MKFILE_WBUF]; +static int nofill = 0; +static int verbose = 0; + +static void +usage() +{ + fprintf(stderr, + "Usage: mkfile [-nv] <size>[e|p|t|g|m|k|b] <filename> ...\n"); +} + +static unsigned long long +getsize(char *s) +{ + int sh; + unsigned long long length; + char *suffix; + + /* + * NOTE: We don't handle 'Z' (zetta) or 'Y' (yotta) suffixes yet. + * These are too large to store in unsigned long long (64bits). + * In the future, we'll have to use larger type, + * something like uint128_t. + */ + length = strtoull(s, &suffix, 10); + sh = 0; + switch (tolower(*suffix)) { + case 'e': /* Exabytes. */ + sh = 60; + break; + case 'p': /* Petabytes. */ + sh = 50; + break; + case 't': /* Terabytes. */ + sh = 40; + break; + case 'g': /* Gigabytes. */ + sh = 30; + break; + case 'm': /* Megabytes. */ + sh = 20; + break; + case 'k': /* Kilobytes. */ + sh = 10; + break; + case 'b': /* Blocks. */ + sh = 9; + break; + case '\0': /* Bytes. */ + break; + default: /* Unknown... */ + errno = EINVAL; + return 0; + } + if (sh) { + unsigned long long l; + + l = length; + length <<= sh; + /* Check overflow. */ + if ((length >> sh) != l) { + errno = ERANGE; + return 0; + } + } + + return length; +} + +static int +create_file(char *f, unsigned long long s) +{ + int fd; + size_t w; + ssize_t ws; + + if (verbose) { + fprintf(stdout, "%s %llu bytes\n", f, s); + fflush(stdout); + } + + /* Open file to create. */ + if ((fd = open(f, MKFILE_FLAG, MKFILE_MODE)) < 0) { + return -1; + } + + /* Seek to the end and write 1 byte. */ + if ((lseek(fd, (off_t)(s - 1LL), SEEK_SET) == (off_t)-1) || + (write(fd, buf, (size_t)1) == (ssize_t)-1)) { + /* + * We don't close(fd) here to avoid overwriting errno. + * This is fd-leak, but is not harmful + * because returning error causes mkfile(8) to exit. + */ + return -1; + } + + /* Fill. */ + if (!nofill) { + if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) { + /* Same as above. */ + return -1; + } + while (s) { + w = (s > MKFILE_WBUF) ? MKFILE_WBUF : s; + if ((ws = write(fd, buf, w)) == (ssize_t)-1) { + /* Same as above. */ + return -1; + } + s -= ws; + } + } + close(fd); + + return 0; +} + +int +main(int argc, char *argv[]) +{ + unsigned long long fsize; + int ch; + + /* We have at least 2 arguments. */ + if (argc < 3) { + usage(); + return EXIT_FAILURE; + } + + /* Options. */ + while ((ch = getopt(argc, argv, "nv")) != -1) { + switch (ch) { + case 'n': + nofill = 1; + break; + case 'v': + verbose = 1; + break; + default: + usage(); + return EXIT_FAILURE; + } + } + argc -= optind; + argv += optind; + + /* File size to create. */ + if ((fsize = getsize(*argv)) == 0) { + perror(*argv); + return EXIT_FAILURE; + } + + /* Filenames to create. */ + bzero(buf, MKFILE_WBUF); + while (++argv, --argc) { + if (create_file(*argv, fsize) == -1) { + perror(*argv); + return EXIT_FAILURE; + } + } + + return EXIT_SUCCESS; +} |
