diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2014-11-07 11:37:33 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2014-11-07 11:43:42 +0200 |
commit | 45af1632aa64a5ba1b108e248920e67c180e8485 (patch) | |
tree | 7155302a54ddc140882612178fde753000c5e60b | |
parent | 02e1fb17d864f2658ab14353e0bd026949c9f8a4 (diff) | |
download | paxutils-45af1632aa64a5ba1b108e248920e67c180e8485.tar.gz |
genfile: improve sparse mode
* tests/genfile.c (generate_sparse_file): Handle '-' argument
(read from stdin);
If content strings starts with '=', treat it as fragment size and
use default pattern to fill it.
* doc/genfile.texi: Document changes to genfile.
-rw-r--r-- | doc/genfile.texi | 33 | ||||
-rw-r--r-- | tests/genfile.c | 79 |
2 files changed, 92 insertions, 20 deletions
diff --git a/doc/genfile.texi b/doc/genfile.texi index e0f4e35..bd2e505 100644 --- a/doc/genfile.texi +++ b/doc/genfile.texi @@ -124,9 +124,8 @@ the rest of the command line specifies a so-called @dfn{file map}. descriptors}. Each descriptor is composed of two values: a number, specifying fragment offset from the end of the previous fragment or, for the very first fragment, from the beginning of the file, and -@dfn{contents string}, i.e., a string of characters, specifying the -pattern to fill the fragment with. File offset can be suffixed with -the following quantifiers: +@dfn{contents string}, that specifies the pattern to fill the fragment +with. File offset can be suffixed with the following quantifiers: @table @samp @item k @@ -140,17 +139,29 @@ The number is expressed in megabytes. The number is expressed in gigabytes. @end table - For each letter in contents string @command{genfile} will generate -a @dfn{block} of data, filled with this letter and will write it to -the fragment. The size of block is given by @option{--block-size} -option. It defaults to 512. Thus, if the string consists of @var{n} -characters, the resulting file fragment will contain -@code{@var{n}*@var{block-size}} of data. - - Last fragment descriptor can have only file offset part. In this + Contents string can be either a fragment size or a pattern. +Fragment size is a decimal number, prefixed with an equals sign. It +can be suffixed with a quantifier, as discussed above. If fragment +size is given, the fragment of that size will be filled with the +currently selected pattern (@pxref{Generate Mode, --pattern}) and +written to the file. + + A pattern is a string of arbitrary ASCII characters. For each +of them, @command{genfile} will generate a @dfn{block} of data, +filled with that character and will write it to the fragment. The size +of block is given by @option{--block-size} option. It defaults to 512. +Thus, if pattern consists of @var{n} characters, the resulting file +fragment will contain @code{@var{n}*@var{block-size}} bytes of data. + + The last fragment descriptor can have only file offset part. In this case @command{genfile} will create a hole at the end of the file up to the given offset. + A dash appearing as a fragment descriptor instructs +@command{genfile} to read file map from the standard input. Each line +of input should consist of fragment offset and contents string, +separated by any amount of whitespace. + For example, consider the following invocation: @smallexample diff --git a/tests/genfile.c b/tests/genfile.c index fa480ef..d41336b 100644 --- a/tests/genfile.c +++ b/tests/genfile.c @@ -32,6 +32,7 @@ #include <inttostr.h> #include <fcntl.h> #include <sys/stat.h> +#include <c-ctype.h> #define obstack_chunk_alloc malloc #define obstack_chunk_free free #include <obstack.h> @@ -506,6 +507,53 @@ mksparse (int fd, off_t displ, char *marks) } } +static int +make_fragment (int fd, char *offstr, char *mapstr) +{ + int i; + off_t displ = get_size (offstr, 1); + + file_length += displ; + + if (!mapstr || !*mapstr) + { + mkhole (fd, displ); + return 1; + } + else if (*mapstr == '=') + { + off_t n = get_size (mapstr + 1, 1); + + switch (pattern) + { + case DEFAULT_PATTERN: + for (i = 0; i < block_size; i++) + buffer[i] = i & 255; + break; + + case ZEROS_PATTERN: + memset (buffer, 0, block_size); + break; + } + + if (lseek (fd, displ, SEEK_CUR) == -1) + error (EXIT_FAILURE, errno, "lseek"); + + for (; n; n--) + { + if (write (fd, buffer, block_size) != block_size) + error (EXIT_FAILURE, errno, "write"); + file_length += block_size; + } + } + else + { + file_length += block_size * strlen (mapstr); + mksparse (fd, displ, mapstr); + } + return 0; +} + static void generate_sparse_file (int argc, char **argv) { @@ -526,20 +574,33 @@ generate_sparse_file (int argc, char **argv) file_length = 0; - for (i = 0; i < argc; i += 2) + while (argc) { - off_t displ = get_size (argv[i], 1); - file_length += displ; - - if (i == argc-1) + if (argv[0][0] == '-' && argv[0][1] == 0) { - mkhole (fd, displ); - break; + char buf[256]; + while (fgets (buf, sizeof (buf), stdin)) + { + size_t n = strlen (buf); + + while (n > 0 && c_isspace (buf[n-1])) + buf[--n] = 0; + + n = strcspn (buf, " \t"); + buf[n++] = 0; + while (buf[n] && c_isblank (buf[n])) + ++n; + make_fragment (fd, buf, buf + n); + } + ++argv; + --argc; } else { - file_length += block_size * strlen (argv[i+1]); - mksparse (fd, displ, argv[i+1]); + if (make_fragment (fd, argv[0], argv[1])) + break; + argc -= 2; + argv += 2; } } |