summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2004-09-07 13:23:28 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2004-09-07 13:23:28 +0000
commit17fb5e805f79b94e6b2fad7585d14785f2358a54 (patch)
treef73086e53f69a93e0a57246c09dc0a6e3449a61f /tests
parentb5a31c71f54e75856c9a8d94dbf9bfb4346f4f5a (diff)
downloadpaxutils-17fb5e805f79b94e6b2fad7585d14785f2358a54.tar.gz
New file
Diffstat (limited to 'tests')
-rw-r--r--tests/DISTFILES1
-rw-r--r--tests/genfile.c301
2 files changed, 302 insertions, 0 deletions
diff --git a/tests/DISTFILES b/tests/DISTFILES
new file mode 100644
index 0000000..b8d3d25
--- /dev/null
+++ b/tests/DISTFILES
@@ -0,0 +1 @@
+genfile.c
diff --git a/tests/genfile.c b/tests/genfile.c
new file mode 100644
index 0000000..f67fa4d
--- /dev/null
+++ b/tests/genfile.c
@@ -0,0 +1,301 @@
+/* Generate a file containing some preset patterns.
+
+ Copyright (C) 1995, 1996, 1997, 2001, 2003, 2004 Free Software
+ Foundation, Inc.
+
+ François Pinard <pinard@iro.umontreal.ca>, 1995.
+ Sergey Poznyakoff <gray@mirddin.farlep.net>, 2004.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include <system.h>
+#include <stdarg.h>
+#include <argmatch.h>
+#include <argp.h>
+
+#ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+#endif
+#ifndef EXIT_FAILURE
+# define EXIT_FAILURE 1
+#endif
+
+enum pattern
+{
+ DEFAULT_PATTERN,
+ ZEROS_PATTERN
+};
+
+/* The name this program was run with. */
+const char *program_name;
+
+/* Name of file to generate */
+static char *file_name;
+
+/* Length of file to generate. */
+static int file_length = 0;
+
+/* Pattern to generate. */
+static enum pattern pattern = DEFAULT_PATTERN;
+
+/* Generate sparse file */
+static int sparse_file;
+
+/* Size of a block for sparse file */
+size_t block_size = 512;
+
+/* Block buffer for sparse file */
+char *buffer;
+
+static const char *argp_program_version = "genfile (" PACKAGE ") " VERSION;
+static const char *argp_program_bug_address = "<" PACKAGE_BUGREPORT ">";
+static char doc[] = N_("genfile generates data files for GNU paxutils test suite");
+
+static struct argp_option options[] = {
+ {"length", 'l', N_("SIZE"), 0,
+ N_("Create file of the given SIZE"), 0 },
+ {"file", 'f', N_("NAME"), 0,
+ N_("Write to file NAME, instead of standard output"), 0},
+ {"pattern", 'p', N_("PATTERN"), 0,
+ N_("Fill the file with the given PATTERN. PATTERN is 'default' or 'zeros'"),
+ 0 },
+ {"block-size", 'b', N_("SIZE"), 0,
+ N_("Size of a block for sparse file"), 0},
+ {"sparse", 's', NULL, 0,
+ N_("Generate sparse file. The rest of the command line gives the file map"),
+ 0 },
+ { NULL, }
+};
+
+static char const * const pattern_args[] = { "default", "zeros", 0 };
+static enum pattern const pattern_types[] = {DEFAULT_PATTERN, ZEROS_PATTERN};
+
+static void
+die (char const *fmt, ...)
+{
+ va_list ap;
+
+ fprintf (stderr, "%s: ", program_name);
+ va_start (ap, fmt);
+ vfprintf (stderr, fmt, ap);
+ va_end (ap);
+ fprintf (stderr, "\n");
+ exit (EXIT_FAILURE);
+}
+
+static int
+xlat_suffix (off_t *vp, char *p)
+{
+ if (p[1])
+ return 1;
+ switch (p[0])
+ {
+ case 'g':
+ case 'G':
+ *vp *= 1024;
+
+ case 'm':
+ case 'M':
+ *vp *= 1024;
+
+ case 'k':
+ case 'K':
+ *vp *= 1024;
+ break;
+
+ default:
+ return 1;
+ }
+ return 0;
+}
+
+static off_t
+get_size (const char *str, int allow_zero)
+{
+ char *p;
+ off_t n;
+
+ n = strtoul (str, &p, 0);
+ if (n < 0 || (!allow_zero && n == 0) || (*p && xlat_suffix (&n, p)))
+ die (_("Invalid size: %s"), str);
+ return n;
+}
+
+
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+ switch (key)
+ {
+ case 'f':
+ file_name = arg;
+ break;
+
+ case 'l':
+ file_length = get_size (arg, 0);
+ break;
+
+ case 'p':
+ pattern = XARGMATCH ("--pattern", arg, pattern_args, pattern_types);
+ break;
+
+ case 'b':
+ block_size = get_size (arg, 0);
+ break;
+
+ case 's':
+ sparse_file = 1;
+ break;
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+ return 0;
+}
+
+static struct argp argp = {
+ options,
+ parse_opt,
+ N_("[disp letters [disp letters...] [disp]...]"),
+ doc,
+ NULL,
+ NULL,
+ NULL
+};
+
+static void
+generate_simple_file (int argc, char **argv)
+{
+ int i;
+ FILE *fp;
+
+ if (argc)
+ die (_("too many arguments"));
+
+ if (file_name)
+ {
+ fp = fopen (file_name, "w");
+ if (!fp)
+ die (_("cannot open `%s'"), file_name);
+ }
+ else
+ fp = stdout;
+
+ switch (pattern)
+ {
+ case DEFAULT_PATTERN:
+ for (i = 0; i < file_length; i++)
+ fputc (i & 255, fp);
+ break;
+
+ case ZEROS_PATTERN:
+ for (i = 0; i < file_length; i++)
+ fputc (0, fp);
+ break;
+ }
+ fclose (fp);
+}
+
+
+
+static void
+mkhole (int fd, off_t displ)
+{
+ if (lseek (fd, displ, SEEK_CUR) == -1)
+ {
+ perror ("lseek");
+ exit (EXIT_FAILURE);
+ }
+ ftruncate (fd, lseek (fd, 0, SEEK_CUR));
+}
+
+static void
+mksparse (int fd, off_t displ, char *marks)
+{
+ for (; *marks; marks++)
+ {
+ memset (buffer, *marks, block_size);
+ if (write (fd, buffer, block_size) != block_size)
+ {
+ perror ("write");
+ exit (EXIT_FAILURE);
+ }
+
+ if (lseek (fd, displ, SEEK_CUR) == -1)
+ {
+ perror ("lseek");
+ exit (EXIT_FAILURE);
+ }
+ }
+}
+
+static void
+generate_sparse_file (int argc, char **argv)
+{
+ int i;
+ int fd;
+
+ if (!file_name)
+ die (_("cannot generate sparse files on standard output, use --file option"));
+ fd = open (file_name, O_CREAT|O_TRUNC|O_RDWR, 0644);
+ if (fd < 0)
+ die (_("cannot open `%s'"), file_name);
+
+ buffer = malloc (block_size);
+ if (!buffer)
+ die (_("Not enough memory"));
+
+ for (i = 0; i < argc; i += 2)
+ {
+ off_t displ = get_size (argv[i], 1);
+
+ if (i == argc-1)
+ {
+ mkhole (fd, displ);
+ break;
+ }
+ else
+ mksparse (fd, displ, argv[i+1]);
+ }
+
+ close (fd);
+}
+
+
+int
+main (int argc, char **argv)
+{
+ int index;
+
+ program_name = argv[0];
+ setlocale (LC_ALL, "");
+
+ /* Decode command options. */
+
+ if (argp_parse (&argp, argc, argv, 0, &index, NULL))
+ exit (EXIT_FAILURE);
+
+ argc -= index;
+ argv += index;
+
+ /* Generate file. */
+ if (sparse_file)
+ generate_sparse_file (argc, argv);
+ else
+ generate_simple_file (argc, argv);
+
+ exit (EXIT_SUCCESS);
+}