summaryrefslogtreecommitdiff
path: root/src/split.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2002-02-12 15:44:16 +0000
committerJim Meyering <jim@meyering.net>2002-02-12 15:44:16 +0000
commit65cbf7d1fdb6a3db9299d66cca495cc5efc74b44 (patch)
tree3cdef4e0714904f4b8c6509dce0040665fbaa771 /src/split.c
parentedcef6055020b768c4eb98f62ee4cf15c8facf8a (diff)
downloadcoreutils-65cbf7d1fdb6a3db9299d66cca495cc5efc74b44.tar.xz
Include "dirname.h".
(outbase): Now a global var. (outfile_end): Remove. (suffix_length): New var. (shortopts, longopts, main): Add -a or --suffix-length. (next_file_name): Implement -a. Do not extend the suffix length. Check for file names that are too long. (main): Move outfile initialization to next_file_name. (shortopts): Remove -v (a typo).
Diffstat (limited to 'src/split.c')
-rw-r--r--src/split.c94
1 files changed, 56 insertions, 38 deletions
diff --git a/src/split.c b/src/split.c
index 1b803977e..ae8f4a92f 100644
--- a/src/split.c
+++ b/src/split.c
@@ -29,6 +29,7 @@
#include "system.h"
#include "closeout.h"
+#include "dirname.h"
#include "error.h"
#include "full-write.h"
#include "safe-read.h"
@@ -43,14 +44,17 @@
char *program_name;
/* Base name of output files. */
-static char *outfile;
+static char const *outbase;
+/* Name of output files. */
+static char *outfile;
+
/* Pointer to the end of the prefix in OUTFILE.
Suffixes are inserted here. */
static char *outfile_mid;
-/* Pointer to the end of OUTFILE. */
-static char *outfile_end;
+/* Length of OUTFILE's suffix. */
+static size_t suffix_length = 2;
/* Name of input file. May be "-". */
static char *infile;
@@ -65,7 +69,7 @@ static int output_desc;
output file is opened. */
static int verbose;
-static char const shortopts[] = "vb:l:C:"
+static char const shortopts[] = "a:b:l:C:"
#if POSIX2_VERSION < 200112
"0123456789"
#endif
@@ -76,6 +80,7 @@ static struct option const longopts[] =
{"bytes", required_argument, NULL, 'b'},
{"lines", required_argument, NULL, 'l'},
{"line-bytes", required_argument, NULL, 'C'},
+ {"suffix-length", required_argument, NULL, 'a'},
{"verbose", no_argument, NULL, 2},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
@@ -103,6 +108,7 @@ PREFIX is `x'. With no INPUT, or when INPUT is -, read standard input.\n\
Mandatory arguments to long options are mandatory for short options too.\n\
"), stdout);
fputs (_("\
+ -a, --suffix-length=N use suffixes of length N (default 2)\n\
-b, --bytes=SIZE put SIZE bytes per output file\n\
-C, --line-bytes=SIZE put at most SIZE bytes of lines per output file\n\
-l, --lines=NUMBER put NUMBER lines per output file\n\
@@ -126,35 +132,49 @@ SIZE may have a multiplier suffix: b for 512, k for 1K, m for 1 Meg.\n\
exit (status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
-/* Compute the next sequential output file name suffix and store it
- into the string `outfile' at the position pointed to by `outfile_mid'. */
+/* Compute the next sequential output file name and store it into the
+ string `outfile'. */
static void
next_file_name (void)
{
- static unsigned n_digits = 2;
- char *p;
-
- /* Change any suffix of `z's to `a's. */
- for (p = outfile_end - 1; *p == 'z'; p--)
+ if (! outfile)
{
- *p = 'a';
+ /* Allocate and initialize the first file name. */
+
+ size_t outbase_length = strlen (outbase);
+ size_t outfile_length = outbase_length + suffix_length;
+ if (outfile_length + 1 < outbase_length)
+ xalloc_die ();
+ outfile = xmalloc (outfile_length + 1);
+ outfile_mid = outfile + outbase_length;
+ memcpy (outfile, outbase, outbase_length);
+ memset (outfile_mid, 'a', suffix_length);
+ outfile[outfile_length] = 0;
+
+#if ! _POSIX_NO_TRUNC && HAVE_PATHCONF && defined _PC_NAME_MAX
+ /* POSIX requires that if the output file name is too long for
+ its directory, `split' must fail without creating any files.
+ This must be checked for explicitly on operating systems that
+ silently truncate file names. */
+ {
+ char *dir = dir_name (outfile);
+ long name_max = pathconf (dir, _PC_NAME_MAX);
+ if (0 <= name_max && name_max < base_len (base_name (outfile)))
+ error (EXIT_FAILURE, ENAMETOOLONG, "%s", outfile);
+ free (dir);
+ }
+#endif
}
-
- /* Increment the rightmost non-`z' character that was present before the
- above z/a substitutions. There is guaranteed to be such a character. */
- ++(*p);
-
- /* If the result of that increment operation yielded a `z' and there
- are only `z's to the left of it, then append two more `a' characters
- to the end and add 1 (-1 + 2) to the number of digits (we're taking
- out this `z' and adding two `a's). */
- if (*p == 'z' && p == outfile_mid)
+ else
{
- ++n_digits;
- ++outfile_mid;
- *outfile_end++ = 'a';
- *outfile_end++ = 'a';
+ /* Increment the suffix in place, if possible. */
+
+ char *p;
+ for (p = outfile_mid + suffix_length; outfile_mid < p; *--p = 'a')
+ if (p[-1]++ != 'z')
+ return;
+ error (EXIT_FAILURE, 0, _("Output file suffixes exhausted"));
}
}
@@ -357,7 +377,6 @@ main (int argc, char **argv)
int in_blk_size; /* optimal block size of input file device */
char *buf; /* file i/o buffer */
int accum = 0;
- char *outbase;
int c;
int digits_optind = 0;
@@ -388,6 +407,16 @@ main (int argc, char **argv)
case 0:
break;
+ case 'a':
+ if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
+ || tmp_long < 0 || tmp_long > SIZE_MAX)
+ {
+ error (0, 0, _("%s: invalid suffix length"), optarg);
+ usage (EXIT_FAILURE);
+ }
+ suffix_length = tmp_long;
+ break;
+
case 'b':
if (split_type != type_undef)
{
@@ -522,17 +551,6 @@ main (int argc, char **argv)
/* No output file is open now. */
output_desc = -1;
- /* Copy the output file prefix so we can add suffixes to it.
- 26**29 is certainly enough output files! */
-
- outfile = xmalloc (strlen (outbase) + 30);
- strcpy (outfile, outbase);
- outfile_mid = outfile + strlen (outfile);
- outfile_end = outfile_mid + 2;
- memset (outfile_mid, 0, 30);
- outfile_mid[0] = 'a';
- outfile_mid[1] = 'a' - 1; /* first call to next_file_name makes it an 'a' */
-
/* Get the optimal block size of input device and make a buffer. */
if (fstat (input_desc, &stat_buf) < 0)