summaryrefslogtreecommitdiff
path: root/util/trunc.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/trunc.c')
-rw-r--r--util/trunc.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/util/trunc.c b/util/trunc.c
new file mode 100644
index 0000000..55cb19d
--- /dev/null
+++ b/util/trunc.c
@@ -0,0 +1,132 @@
+/* trunc.c: Set the size of an existing file, or create a file of a
+ * specified size.
+ *
+ * Copyright (C) 2008 Micah J. Cowan
+ *
+ * Copying and distribution of this file, with or without modification,
+ * are permitted in any medium without royalty provided the copyright
+ * notice and this notice are preserved. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define PROGRAM_NAME "trunc"
+
+void
+usage (FILE *f)
+{
+ fputs (
+PROGRAM_NAME " [-c] file sz\n\
+\n\
+Set the filesize of FILE to SIZE.\n\
+\n\
+ -c: create FILE if it doesn't exist.\n\
+\n\
+ Multiplier suffixes for SIZE (case-insensitive):\n\
+ k: SIZE * 1024\n\
+ m: SIZE * 1024 * 1024\n", f);
+}
+
+off_t
+get_size (const char str[])
+{
+ unsigned long val;
+ int suffix;
+ char *end;
+
+ errno = 0;
+ val = strtoul(str, &end, 10);
+ if (end == str)
+ {
+ fputs (PROGRAM_NAME ": size is not a number.\n", stderr);
+ usage (stderr);
+ exit (EXIT_FAILURE);
+ }
+ else if (errno == ERANGE
+ || (unsigned long)(off_t)val != val)
+ {
+ fputs (PROGRAM_NAME ": size is out of range.\n", stderr);
+ exit (EXIT_FAILURE);
+ }
+
+ suffix = tolower ((unsigned char) end[0]);
+ if (suffix == 'k')
+ {
+ val *= 1024;
+ }
+ else if (suffix == 'm')
+ {
+ val *= 1024 * 1024;
+ }
+
+ return val;
+}
+
+int
+main (int argc, char *argv[])
+{
+ const char *fname;
+ const char *szstr;
+ off_t sz;
+ int create = 0;
+ int option;
+ int fd;
+
+ /* Parse options. */
+ while ((option = getopt (argc, argv, "c")) != -1)
+ {
+ switch (option) {
+ case 'c':
+ create = 1;
+ break;
+ case '?':
+ fprintf (stderr, PROGRAM_NAME ": Unrecognized option `%c'.\n\n",
+ optopt);
+ usage (stderr);
+ exit (EXIT_FAILURE);
+ default:
+ /* We shouldn't reach here. */
+ abort();
+ }
+ }
+
+ if (argv[optind] == NULL
+ || argv[optind+1] == NULL
+ || argv[optind+2] != NULL)
+ {
+ usage (stderr);
+ exit (EXIT_FAILURE);
+ }
+
+ fname = argv[optind];
+ szstr = argv[optind+1];
+
+ sz = get_size(szstr);
+ if (create)
+ {
+ mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+ fd = open(fname, O_WRONLY | O_CREAT, mode);
+ }
+ else
+ {
+ fd = open(fname, O_WRONLY);
+ }
+
+ if (fd == -1)
+ {
+ perror (PROGRAM_NAME ": open");
+ exit (EXIT_FAILURE);
+ }
+
+ if (ftruncate(fd, sz) == -1)
+ {
+ perror (PROGRAM_NAME ": truncate");
+ exit (EXIT_FAILURE);
+ }
+
+ return 0;
+}