From 17fb5e805f79b94e6b2fad7585d14785f2358a54 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Tue, 7 Sep 2004 13:23:28 +0000 Subject: New file --- tests/DISTFILES | 1 + tests/genfile.c | 301 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 302 insertions(+) create mode 100644 tests/DISTFILES create mode 100644 tests/genfile.c (limited to 'tests') 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 , 1995. + Sergey Poznyakoff , 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 +#include +#include +#include + +#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); +} -- cgit v1.2.1