aboutsummaryrefslogtreecommitdiff
path: root/tests/sys/cddl/zfs/bin/mkfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/sys/cddl/zfs/bin/mkfile.c')
-rw-r--r--tests/sys/cddl/zfs/bin/mkfile.c209
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;
+}