/* split.c -- split a file into pieces. This is the split utility
Copyright (C) 1988-2018 Free Software Foundation, Inc.
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 3 of the License, 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, see <https://www.gnu.org/licenses/>. */ The GNUv3 license
/* By tege@sics.se, with rms.
TODO:
* support -p REGEX as in BSD's split.
* support --suppress-matched as in csplit. */
#include <config.h> Provides system specific information
#include <assert.h> ...!includes auto-comment...
#include <stdio.h> Provides standard I/O capability
#include <getopt.h> ...!includes auto-comment...
#include <signal.h> ...!includes auto-comment...
#include <sys/types.h> Provides system data types
#include <sys/wait.h> ...!includes auto-comment...
#include "system.h" ...!includes auto-comment...
#include "die.h" ...!includes auto-comment...
#include "error.h" ...!includes auto-comment...
#include "fd-reopen.h" ...!includes auto-comment...
#include "fcntl--.h" ...!includes auto-comment...
#include "full-write.h" ...!includes auto-comment...
#include "ioblksize.h" ...!includes auto-comment...
#include "quote.h" ...!includes auto-comment...
#include "safe-read.h" ...!includes auto-comment...
#include "sig2str.h" ...!includes auto-comment...
#include "xbinary-io.h" ...!includes auto-comment...
#include "xdectoint.h" ...!includes auto-comment...
#include "xstrtol.h" ...!includes auto-comment...
/* The official name of this program (e.g., no 'g' prefix). */
#define PROGRAM_NAME "split" Line 46
#define AUTHORS \ Line 48
proper_name ("Torbjorn Granlund"), \ Line 49
proper_name ("Richard M. Stallman") Line 50
/* Shell command to filter through, instead of creating files. */
static char const *filter_command; Line 53
/* Process ID of the filter. */
static int filter_pid; Line 56
/* Array of open pipes. */
static int *open_pipes; Line 59
static size_t open_pipes_alloc; Line 60
static size_t n_open_pipes; Line 61
/* Blocked signals. */
static sigset_t oldblocked; Line 64
static sigset_t newblocked; Line 65
/* Base name of output files. */
static char const *outbase; Line 68
/* Name of output files. */
static char *outfile; Line 71
/* Pointer to the end of the prefix in OUTFILE.
Suffixes are inserted here. */
static char *outfile_mid; Line 75
/* Generate new suffix when suffixes are exhausted. */
static bool suffix_auto = true; Line 78
/* Length of OUTFILE's suffix. */
static size_t suffix_length; Line 81
/* Alphabet of characters to use in suffix. */
static char const *suffix_alphabet = "abcdefghijklmnopqrstuvwxyz"; Line 84
/* Numerical suffix start value. */
static const char *numeric_suffix_start; Line 87
/* Additional suffix to append to output file names. */
static char const *additional_suffix; Line 90
/* Name of input file. May be "-". */
static char *infile; Line 93
/* stat buf for input file. */
static struct stat in_stat_buf; Line 96
/* Descriptor on which output file is open. */
static int output_desc = -1; Line 99
/* If true, print a diagnostic on standard error just before each
output file is opened. */
static bool verbose; Line 103
/* If true, don't generate zero length output files. */
static bool elide_empty_files; Line 106
/* If true, in round robin mode, immediately copy
input to output, which is much slower, so disabled by default. */
static bool unbuffered; Line 110
/* The character marking end of line. Defaults to \n below. */
static int eolchar = -1; Line 113
/* The split mode to use. */
enum Split_type Line 116
{
type_undef, type_bytes, type_byteslines, type_lines, type_digits, Line 118
type_chunk_bytes, type_chunk_lines, type_rr Line 119
}; Block 1
/* For long options that have no equivalent short option, use a
non-character as a pseudo short option, starting with CHAR_MAX + 1. */
enum Line 124
{
VERBOSE_OPTION = CHAR_MAX + 1, Line 126
FILTER_OPTION, Line 127
IO_BLKSIZE_OPTION, Line 128
ADDITIONAL_SUFFIX_OPTION Line 129
}; Block 2
static struct option const longopts[] = Line 132
{
{"bytes", required_argument, NULL, 'b'}, Line 134
{"lines", required_argument, NULL, 'l'}, Line 135
{"line-bytes", required_argument, NULL, 'C'}, Line 136
{"number", required_argument, NULL, 'n'}, Line 137
{"elide-empty-files", no_argument, NULL, 'e'}, Line 138
{"unbuffered", no_argument, NULL, 'u'}, Line 139
{"suffix-length", required_argument, NULL, 'a'}, Line 140
{"additional-suffix", required_argument, NULL, Line 141
ADDITIONAL_SUFFIX_OPTION}, Line 142
{"numeric-suffixes", optional_argument, NULL, 'd'}, Line 143
{"hex-suffixes", optional_argument, NULL, 'x'}, Line 144
{"filter", required_argument, NULL, FILTER_OPTION}, Line 145
{"verbose", no_argument, NULL, VERBOSE_OPTION}, Line 146
{"separator", required_argument, NULL, 't'}, Line 147
{"-io-blksize", required_argument, NULL, Line 148
IO_BLKSIZE_OPTION}, /* do not document */ Line 149
{GETOPT_HELP_OPTION_DECL}, Line 150
{GETOPT_VERSION_OPTION_DECL}, Line 151
{NULL, 0, NULL, 0} Line 152
}; Block 3
/* Return true if the errno value, ERR, is ignorable. */
static inline bool Line 156
ignorable (int err) Line 157
{
return filter_command && err == EPIPE; Line 159
} Block 4
static void Line 162
set_suffix_length (uintmax_t n_units, enum Split_type split_type) Line 163
{
#define DEFAULT_SUFFIX_LENGTH 2 Line 165
uintmax_t suffix_needed = 0; Line 167
/* The suffix auto length feature is incompatible with
a user specified start value as the generated suffixes
are not all consecutive. */
if (numeric_suffix_start) Line 172
suffix_auto = false; Line 173
/* Auto-calculate the suffix length if the number of files is given. */
if (split_type == type_chunk_bytes || split_type == type_chunk_lines Line 176
|| split_type == type_rr) Line 177
{
uintmax_t n_units_end = n_units; Line 179
if (numeric_suffix_start) Line 180
{
uintmax_t n_start; Line 182
strtol_error e = xstrtoumax (numeric_suffix_start, NULL, 10, Line 183
&n_start, ""); Line 184
if (e == LONGINT_OK && n_start <= UINTMAX_MAX - n_units) Line 185
{
/* Restrict auto adjustment so we don't keep
incrementing a suffix size arbitrarily,
as that would break sort order for files
generated from multiple split runs. */
if (n_start < n_units) Line 191
n_units_end += n_start; Line 192
}
}
size_t alphabet_len = strlen (suffix_alphabet); Line 196
bool alphabet_slop = (n_units_end % alphabet_len) != 0; Line 197
while (n_units_end /= alphabet_len) Line 198
suffix_needed++; Line 199
suffix_needed += alphabet_slop; Line 200
suffix_auto = false; Line 201
}
if (suffix_length) /* set by user */ Line 204
{
if (suffix_length < suffix_needed) Line 206
{
die (EXIT_FAILURE, 0, Line 208
_("the suffix length needs to be at least %"PRIuMAX), Line 209
suffix_needed); Line 210
}
suffix_auto = false; Line 212
return; Line 213
}
else Line 215
suffix_length = MAX (DEFAULT_SUFFIX_LENGTH, suffix_needed); Line 216
} Block 5
void Line 219
usage (int status) Line 220
{
if (status != EXIT_SUCCESS) Line 222
emit_try_help (); ...!common auto-comment...
else Line 224
{
printf (_("\ Line 226
Usage: %s [OPTION]... [FILE [PREFIX]]\n\ Line 227
"), Line 228
program_name); Line 229
fputs (_("\ Line 230
Output pieces of FILE to PREFIXaa, PREFIXab, ...;\n\ Line 231
default size is 1000 lines, and default PREFIX is 'x'.\n\ Line 232
"), stdout); Line 233
emit_stdin_note (); ...!common auto-comment...
emit_mandatory_arg_note (); ...!common auto-comment...
fprintf (stdout, _("\ Line 238
-a, --suffix-length=N generate suffixes of length N (default %d)\n\ Line 239
--additional-suffix=SUFFIX append an additional SUFFIX to file names\n\ Line 240
-b, --bytes=SIZE put SIZE bytes per output file\n\ Line 241
-C, --line-bytes=SIZE put at most SIZE bytes of records per output file\n\ Line 242
-d use numeric suffixes starting at 0, not alphabetic\n\ Line 243
--numeric-suffixes[=FROM] same as -d, but allow setting the start value\ Line 244
\n\
-x use hex suffixes starting at 0, not alphabetic\n\ Line 246
--hex-suffixes[=FROM] same as -x, but allow setting the start value\n\ Line 247
-e, --elide-empty-files do not generate empty output files with '-n'\n\ Line 248
--filter=COMMAND write to shell COMMAND; file name is $FILE\n\ Line 249
-l, --lines=NUMBER put NUMBER lines/records per output file\n\ Line 250
-n, --number=CHUNKS generate CHUNKS output files; see explanation below\n\Line 251
-t, --separator=SEP use SEP instead of newline as the record separator;\n\Line 252
'\\0' (zero) specifies the NUL character\n\ Line 253
-u, --unbuffered immediately copy input to output with '-n r/...'\n\ Line 254
"), DEFAULT_SUFFIX_LENGTH); Line 255
fputs (_("\ Line 256
--verbose print a diagnostic just before each\n\ Line 257
output file is opened\n\ Line 258
"), stdout); Line 259
fputs (HELP_OPTION_DESCRIPTION, stdout); Line 260
fputs (VERSION_OPTION_DESCRIPTION, stdout); Line 261
emit_size_note (); Line 262
fputs (_("\n\ Line 263
CHUNKS may be:\n\ Line 264
N split into N files based on size of input\n\ Line 265
K/N output Kth of N to stdout\n\ Line 266
l/N split into N files without splitting lines/records\n\ Line 267
l/K/N output Kth of N to stdout without splitting lines/records\n\ Line 268
r/N like 'l' but use round robin distribution\n\ Line 269
r/K/N likewise but only output Kth of N to stdout\n\ Line 270
"), stdout); Line 271
emit_ancillary_info (PROGRAM_NAME); Line 272
}
exit (status); Line 274
} Block 6
/* Return the number of bytes that can be read from FD with status ST.
Store up to the first BUFSIZE bytes of the file's data into BUF,
and advance the file position by the number of bytes read. On
input error, set errno and return -1. */
static off_t Line 282
input_file_size (int fd, struct stat const *st, char *buf, size_t bufsize) Line 283
{
off_t cur = lseek (fd, 0, SEEK_CUR); Line 285
if (cur < 0) Line 286
{
if (errno == ESPIPE) Line 288
errno = 0; /* Suppress confusing seek error. */ Line 289
return -1; Line 290
}
off_t size = 0; Line 293
do
{
size_t n_read = safe_read (fd, buf + size, bufsize - size); Line 296...!syscalls auto-comment...
if (n_read == 0) Line 297
return size; Line 298
if (n_read == SAFE_READ_ERROR) Line 299
return -1; Line 300
size += n_read; Line 301
}
while (size < bufsize); Line 303
/* Note we check st_size _after_ the read() above
because /proc files on GNU/Linux are seekable
but have st_size == 0. */
if (st->st_size == 0) Line 308
{
/* We've filled the buffer, from a seekable file,
which has an st_size==0, E.g., /dev/zero on GNU/Linux.
Assume there is no limit to file size. */
errno = EOVERFLOW; Line 313
return -1; Line 314
}
cur += size; Line 317
off_t end; Line 318
if (usable_st_size (st) && cur <= st->st_size) Line 319
end = st->st_size; Line 320
else Line 321
{
end = lseek (fd, 0, SEEK_END); Line 323
if (end < 0) Line 324
return -1; Line 325
if (end != cur) Line 326
{
if (lseek (fd, cur, SEEK_SET) < 0) Line 328
return -1; Line 329
if (end < cur) Line 330
end = cur; Line 331
}
}
size += end - cur; Line 335
if (size == OFF_T_MAX) Line 336
{
/* E.g., /dev/zero on GNU/Hurd. */
errno = EOVERFLOW; Line 339
return -1; Line 340
}
return size; Line 343
} Block 7
/* Compute the next sequential output file name and store it into the
string 'outfile'. */
static void Line 349
next_file_name (void) Line 350
{
/* Index in suffix_alphabet of each character in the suffix. */
static size_t *sufindex; Line 353
static size_t outbase_length; Line 354
static size_t outfile_length; Line 355
static size_t addsuf_length; Line 356
if (! outfile) Line 358
{
bool widen; Line 360
new_name: Line 362
widen = !! outfile_length; Line 363
if (! widen) Line 365
{
/* Allocate and initialize the first file name. */
outbase_length = strlen (outbase); Line 369
addsuf_length = additional_suffix ? strlen (additional_suffix) : 0; Line 370
outfile_length = outbase_length + suffix_length + addsuf_length; Line 371
}
else Line 373
{
/* Reallocate and initialize a new wider file name.
We do this by subsuming the unchanging part of
the generated suffix into the prefix (base), and
reinitializing the now one longer suffix. */
outfile_length += 2; Line 380
suffix_length++; Line 381
}
if (outfile_length + 1 < outbase_length) Line 384
xalloc_die (); ...!common auto-comment...
outfile = xrealloc (outfile, outfile_length + 1); Line 386
if (! widen) Line 388
memcpy (outfile, outbase, outbase_length); Line 389
else Line 390
{
/* Append the last alphabet character to the file name prefix. */
outfile[outbase_length] = suffix_alphabet[sufindex[0]]; Line 393
outbase_length++; Line 394
}
outfile_mid = outfile + outbase_length; Line 397
memset (outfile_mid, suffix_alphabet[0], suffix_length); Line 398
if (additional_suffix) Line 399
memcpy (outfile_mid + suffix_length, additional_suffix, addsuf_length); Line 400
outfile[outfile_length] = 0; Line 401
free (sufindex); Line 403
sufindex = xcalloc (suffix_length, sizeof *sufindex); Line 404
if (numeric_suffix_start) Line 406
{
assert (! widen); Line 408
/* Update the output file name. */
size_t i = strlen (numeric_suffix_start); Line 411
memcpy (outfile_mid + suffix_length - i, numeric_suffix_start, i); Line 412
/* Update the suffix index. */
size_t *sufindex_end = sufindex + suffix_length; Line 415
while (i-- != 0) Line 416
*--sufindex_end = numeric_suffix_start[i] - '0'; Line 417
}
#if ! _POSIX_NO_TRUNC && HAVE_PATHCONF && defined _PC_NAME_MAX Line 420
/* 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); Line 426
long name_max = pathconf (dir, _PC_NAME_MAX); Line 427
if (0 <= name_max && name_max < base_len (last_component (outfile))) Line 428
die (EXIT_FAILURE, ENAMETOOLONG, "%s", quotef (outfile)); Line 429
free (dir); Line 430
}
#endif Line 432
}
else Line 434
{
/* Increment the suffix in place, if possible. */
size_t i = suffix_length; Line 438
while (i-- != 0) Line 439
{
sufindex[i]++; Line 441
if (suffix_auto && i == 0 && ! suffix_alphabet[sufindex[0] + 1]) Line 442
goto new_name; Line 443
outfile_mid[i] = suffix_alphabet[sufindex[i]]; Line 444
if (outfile_mid[i]) Line 445
return; Line 446
sufindex[i] = 0; Line 447
outfile_mid[i] = suffix_alphabet[sufindex[i]]; Line 448
}
die (EXIT_FAILURE, 0, _("output file suffixes exhausted")); Line 450
}
}
/* Create or truncate a file. */
static int Line 456
create (const char *name) Line 457
{
if (!filter_command) Line 459
{
if (verbose) Line 461
fprintf (stdout, _("creating file %s\n"), quoteaf (name)); Line 462
int fd = open (name, O_WRONLY | O_CREAT | O_BINARY, MODE_RW_UGO); Line 464...!syscalls auto-comment...
if (fd < 0) Line 465
return fd; Line 466
struct stat out_stat_buf; Line 467
if (fstat (fd, &out_stat_buf) != 0) Line 468...!syscalls auto-comment......!syscalls auto-comment...
die (EXIT_FAILURE, errno, _("failed to stat %s"), quoteaf (name)); Line 469
if (SAME_INODE (in_stat_buf, out_stat_buf)) Line 470
die (EXIT_FAILURE, 0, _("%s would overwrite input; aborting"), ...!common auto-comment...
quoteaf (name)); Line 472
if (ftruncate (fd, 0) != 0) Line 473...!syscalls auto-comment...
die (EXIT_FAILURE, errno, _("%s: error truncating"), quotef (name)); Line 474
return fd; Line 476
}
else Line 478
{
int fd_pair[2]; Line 480
pid_t child_pid; Line 481
char const *shell_prog = getenv ("SHELL"); Line 482
if (shell_prog == NULL) Line 483
shell_prog = "/bin/sh"; Line 484
if (setenv ("FILE", name, 1) != 0) Line 485
die (EXIT_FAILURE, errno, Line 486
_("failed to set FILE environment variable")); Line 487
if (verbose) Line 488
fprintf (stdout, _("executing with FILE=%s\n"), quotef (name)); Line 489
if (pipe (fd_pair) != 0) Line 490
die (EXIT_FAILURE, errno, _("failed to create pipe")); Line 491
child_pid = fork (); Line 492...!syscalls auto-comment...
if (child_pid == 0) Line 493
{
/* This is the child process. If an error occurs here, the
parent will eventually learn about it after doing a wait,
at which time it will emit its own error message. */
int j; Line 498
/* We have to close any pipes that were opened during an
earlier call, otherwise this process will be holding a
write-pipe that will prevent the earlier process from
reading an EOF on the corresponding read-pipe. */
for (j = 0; j < n_open_pipes; ++j) Line 503
if (close (open_pipes[j]) != 0) Line 504...!syscalls auto-comment...
die (EXIT_FAILURE, errno, _("closing prior pipe")); Line 505
if (close (fd_pair[1])) Line 506...!syscalls auto-comment...
die (EXIT_FAILURE, errno, _("closing output pipe")); Line 507
if (fd_pair[0] != STDIN_FILENO) Line 508
{
if (dup2 (fd_pair[0], STDIN_FILENO) != STDIN_FILENO) Line 510
die (EXIT_FAILURE, errno, _("moving input pipe")); Line 511
if (close (fd_pair[0]) != 0) Line 512...!syscalls auto-comment...
die (EXIT_FAILURE, errno, _("closing input pipe")); Line 513
}
sigprocmask (SIG_SETMASK, &oldblocked, NULL); Line 515
execl (shell_prog, last_component (shell_prog), "-c", Line 516
filter_command, (char *) NULL); Line 517
die (EXIT_FAILURE, errno, _("failed to run command: \"%s -c %s\""), Line 518
shell_prog, filter_command); Line 519
}
if (child_pid == -1) Line 521
die (EXIT_FAILURE, errno, _("fork system call failed")); Line 522
if (close (fd_pair[0]) != 0) Line 523...!syscalls auto-comment...
die (EXIT_FAILURE, errno, _("failed to close input pipe")); Line 524
filter_pid = child_pid; Line 525
if (n_open_pipes == open_pipes_alloc) Line 526
open_pipes = x2nrealloc (open_pipes, &open_pipes_alloc, Line 527
sizeof *open_pipes); Line 528
open_pipes[n_open_pipes++] = fd_pair[1]; Line 529
return fd_pair[1]; Line 530
}
} Block 9
/* Close the output file, and do any associated cleanup.
If FP and FD are both specified, they refer to the same open file;
in this case FP is closed, but FD is still used in cleanup. */
static void Line 537
closeout (FILE *fp, int fd, pid_t pid, char const *name) Line 538
{
if (fp != NULL && fclose (fp) != 0 && ! ignorable (errno)) Line 540...!syscalls auto-comment...
die (EXIT_FAILURE, errno, "%s", quotef (name)); Line 541
if (fd >= 0) Line 542
{
if (fp == NULL && close (fd) < 0) Line 544...!syscalls auto-comment...
die (EXIT_FAILURE, errno, "%s", quotef (name)); Line 545
int j; Line 546
for (j = 0; j < n_open_pipes; ++j) Line 547
{
if (open_pipes[j] == fd) Line 549
{
open_pipes[j] = open_pipes[--n_open_pipes]; Line 551
break; Line 552
}
}
}
if (pid > 0) Line 556
{
int wstatus = 0; Line 558
if (waitpid (pid, &wstatus, 0) == -1 && errno != ECHILD) Line 559
die (EXIT_FAILURE, errno, _("waiting for child process")); Line 560
if (WIFSIGNALED (wstatus)) Line 561
{
int sig = WTERMSIG (wstatus); Line 563
if (sig != SIGPIPE) Line 564
{
char signame[MAX (SIG2STR_MAX, INT_BUFSIZE_BOUND (int))]; Line 566
if (sig2str (sig, signame) != 0) Line 567
sprintf (signame, "%d", sig); Line 568
error (sig + 128, 0, Line 569
_("with FILE=%s, signal %s from command: %s"), Line 570
quotef (name), signame, filter_command); Line 571
}
}
else if (WIFEXITED (wstatus)) Line 574
{
int ex = WEXITSTATUS (wstatus); Line 576
if (ex != 0) Line 577
error (ex, 0, _("with FILE=%s, exit %d from command: %s"), Line 578
quotef (name), ex, filter_command); Line 579
}
else Line 581
{
/* shouldn't happen. */
die (EXIT_FAILURE, 0, Line 584
_("unknown status from command (0x%X)"), wstatus + 0u); Line 585
}
}
} Block 10
/* Write BYTES bytes at BP to an output file.
If NEW_FILE_FLAG is true, open the next output file.
Otherwise add to the same output file already in use.
Return true if successful. */
static bool Line 595
cwrite (bool new_file_flag, const char *bp, size_t bytes) Line 596...!syscalls auto-comment...
{
if (new_file_flag) Line 598
{
if (!bp && bytes == 0 && elide_empty_files) Line 600
return true; Line 601
closeout (NULL, output_desc, filter_pid, outfile); Line 602
next_file_name (); Line 603
output_desc = create (outfile); Line 604
if (output_desc < 0) Line 605
die (EXIT_FAILURE, errno, "%s", quotef (outfile)); Line 606
}
if (full_write (output_desc, bp, bytes) == bytes) Line 609...!syscalls auto-comment...
return true; Line 610
else Line 611
{
if (! ignorable (errno)) Line 613
die (EXIT_FAILURE, errno, "%s", quotef (outfile)); Line 614
return false; Line 615
}
} Block 11
/* Split into pieces of exactly N_BYTES bytes.
Use buffer BUF, whose size is BUFSIZE.
BUF contains the first INITIAL_READ input bytes. */
static void Line 623
bytes_split (uintmax_t n_bytes, char *buf, size_t bufsize, size_t initial_read, Line 624
uintmax_t max_files) Line 625
{
size_t n_read; Line 627
bool new_file_flag = true; Line 628
bool filter_ok = true; Line 629
uintmax_t to_write = n_bytes; Line 630
uintmax_t opened = 0; Line 631
bool eof; Line 632
do
{
if (initial_read != SIZE_MAX) Line 636
{
n_read = initial_read; Line 638
initial_read = SIZE_MAX; Line 639
eof = n_read < bufsize; Line 640
}
else Line 642
{
if (! filter_ok Line 644
&& lseek (STDIN_FILENO, to_write, SEEK_CUR) != -1) Line 645
{
to_write = n_bytes; Line 647
new_file_flag = true; Line 648
}
n_read = safe_read (STDIN_FILENO, buf, bufsize); Line 651...!syscalls auto-comment...
if (n_read == SAFE_READ_ERROR) Line 652
die (EXIT_FAILURE, errno, "%s", quotef (infile)); Line 653
eof = n_read == 0; Line 654
}
char *bp_out = buf; Line 656
while (to_write <= n_read) Line 657
{
if (filter_ok || new_file_flag) Line 659
filter_ok = cwrite (new_file_flag, bp_out, to_write); Line 660...!syscalls auto-comment...
opened += new_file_flag; Line 661
new_file_flag = !max_files || (opened < max_files); Line 662
if (! filter_ok && ! new_file_flag) Line 663
{
/* If filters no longer accepting input, stop reading. */
n_read = 0; Line 666
eof = true; Line 667
break; Line 668
}
bp_out += to_write; Line 670
n_read -= to_write; Line 671
to_write = n_bytes; Line 672
}
if (n_read != 0) Line 674
{
if (filter_ok || new_file_flag) Line 676
filter_ok = cwrite (new_file_flag, bp_out, n_read); Line 677...!syscalls auto-comment...
opened += new_file_flag; Line 678
new_file_flag = false; Line 679
if (! filter_ok && opened == max_files) Line 680
{
/* If filters no longer accepting input, stop reading. */
break; Line 683
}
to_write -= n_read; Line 685
}
}
while (! eof); Line 688
/* Ensure NUMBER files are created, which truncates
any existing files or notifies any consumers on fifos.
FIXME: Should we do this before EXIT_FAILURE? */
while (opened++ < max_files) Line 693
cwrite (true, NULL, 0); Line 694...!syscalls auto-comment...
} Block 12
/* Split into pieces of exactly N_LINES lines.
Use buffer BUF, whose size is BUFSIZE. */
static void Line 700
lines_split (uintmax_t n_lines, char *buf, size_t bufsize) Line 701
{
size_t n_read; Line 703
char *bp, *bp_out, *eob; Line 704
bool new_file_flag = true; Line 705
uintmax_t n = 0; Line 706
do
{
n_read = safe_read (STDIN_FILENO, buf, bufsize); Line 710...!syscalls auto-comment...
if (n_read == SAFE_READ_ERROR) Line 711
die (EXIT_FAILURE, errno, "%s", quotef (infile)); Line 712
bp = bp_out = buf; Line 713
eob = bp + n_read; Line 714
*eob = eolchar; Line 715
while (true) Line 716
{
bp = memchr (bp, eolchar, eob - bp + 1); Line 718
if (bp == eob) Line 719
{
if (eob != bp_out) /* do not write 0 bytes! */ Line 721
{
size_t len = eob - bp_out; Line 723
cwrite (new_file_flag, bp_out, len); Line 724...!syscalls auto-comment...
new_file_flag = false; Line 725
}
break; Line 727
}
++bp; Line 730
if (++n >= n_lines) Line 731
{
cwrite (new_file_flag, bp_out, bp - bp_out); Line 733...!syscalls auto-comment...
bp_out = bp; Line 734
new_file_flag = true; Line 735
n = 0; Line 736
}
}
}
while (n_read); Line 740
} Block 13
/* Split into pieces that are as large as possible while still not more
than N_BYTES bytes, and are split on line boundaries except
where lines longer than N_BYTES bytes occur. */
static void Line 747
line_bytes_split (uintmax_t n_bytes, char *buf, size_t bufsize) Line 748
{
size_t n_read; Line 750
uintmax_t n_out = 0; /* for each split. */ Line 751
size_t n_hold = 0; Line 752
char *hold = NULL; /* for lines > bufsize. */ Line 753
size_t hold_size = 0; Line 754
bool split_line = false; /* Whether a \n was output in a split. */ Line 755
do
{
n_read = safe_read (STDIN_FILENO, buf, bufsize); Line 759...!syscalls auto-comment...
if (n_read == SAFE_READ_ERROR) Line 760
die (EXIT_FAILURE, errno, "%s", quotef (infile)); Line 761
size_t n_left = n_read; Line 762
char *sob = buf; Line 763
while (n_left) Line 764
{
size_t split_rest = 0; Line 766
char *eoc = NULL; Line 767
char *eol; Line 768
/* Determine End Of Chunk and/or End of Line,
which are used below to select what to write or buffer. */
if (n_bytes - n_out - n_hold <= n_left) Line 772
{
/* Have enough for split. */
split_rest = n_bytes - n_out - n_hold; Line 775
eoc = sob + split_rest - 1; Line 776
eol = memrchr (sob, eolchar, split_rest); Line 777
}
else Line 779
eol = memrchr (sob, eolchar, n_left); Line 780
/* Output hold space if possible. */
if (n_hold && !(!eol && n_out)) Line 783
{
cwrite (n_out == 0, hold, n_hold); Line 785...!syscalls auto-comment...
n_out += n_hold; Line 786
if (n_hold > bufsize) Line 787
hold = xrealloc (hold, bufsize); Line 788
n_hold = 0; Line 789
hold_size = bufsize; Line 790
}
/* Output to eol if present. */
if (eol) Line 794
{
split_line = true; Line 796
size_t n_write = eol - sob + 1; Line 797
cwrite (n_out == 0, sob, n_write); Line 798...!syscalls auto-comment...
n_out += n_write; Line 799
n_left -= n_write; Line 800
sob += n_write; Line 801
if (eoc) Line 802
split_rest -= n_write; Line 803
}
/* Output to eoc or eob if possible. */
if (n_left && !split_line) Line 807
{
size_t n_write = eoc ? split_rest : n_left; Line 809
cwrite (n_out == 0, sob, n_write); Line 810...!syscalls auto-comment...
n_out += n_write; Line 811
n_left -= n_write; Line 812
sob += n_write; Line 813
if (eoc) Line 814
split_rest -= n_write; Line 815
}
/* Update hold if needed. */
if ((eoc && split_rest) || (!eoc && n_left)) Line 819
{
size_t n_buf = eoc ? split_rest : n_left; Line 821
if (hold_size - n_hold < n_buf) Line 822
{
if (hold_size <= SIZE_MAX - bufsize) Line 824
hold_size += bufsize; Line 825
else Line 826
xalloc_die (); ...!common auto-comment...
hold = xrealloc (hold, hold_size); Line 828
}
memcpy (hold + n_hold, sob, n_buf); Line 830
n_hold += n_buf; Line 831
n_left -= n_buf; Line 832
sob += n_buf; Line 833
}
/* Reset for new split. */
if (eoc) Line 837
{
n_out = 0; Line 839
split_line = false; Line 840
}
}
}
while (n_read); Line 844
/* Handle no eol at end of file. */
if (n_hold) Line 847
cwrite (n_out == 0, hold, n_hold); Line 848...!syscalls auto-comment...
free (hold); Line 850
} Block 14
/* -n l/[K/]N: Write lines to files of approximately file size / N.
The file is partitioned into file size / N sized portions, with the
last assigned any excess. If a line _starts_ within a partition
it is written completely to the corresponding file. Since lines
are not split even if they overlap a partition, the files written
can be larger or smaller than the partition size, and even empty
if a line is so long as to completely overlap the partition. */
static void Line 861
lines_chunk_split (uintmax_t k, uintmax_t n, char *buf, size_t bufsize, Line 862
size_t initial_read, off_t file_size) Line 863
{
assert (n && k <= n && n <= file_size); Line 865
const off_t chunk_size = file_size / n; Line 867
uintmax_t chunk_no = 1; Line 868
off_t chunk_end = chunk_size - 1; Line 869
off_t n_written = 0; Line 870
bool new_file_flag = true; Line 871
bool chunk_truncated = false; Line 872
if (k > 1) Line 874
{
/* Start reading 1 byte before kth chunk of file. */
off_t start = (k - 1) * chunk_size - 1; Line 877
if (start < initial_read) Line 878
{
memmove (buf, buf + start, initial_read - start); Line 880
initial_read -= start; Line 881
}
else Line 883
{
if (lseek (STDIN_FILENO, start - initial_read, SEEK_CUR) < 0) Line 885
die (EXIT_FAILURE, errno, "%s", quotef (infile)); Line 886
initial_read = SIZE_MAX; Line 887
}
n_written = start; Line 889
chunk_no = k - 1; Line 890
chunk_end = chunk_no * chunk_size - 1; Line 891
}
while (n_written < file_size) Line 894
{
char *bp = buf, *eob; Line 896
size_t n_read; Line 897
if (initial_read != SIZE_MAX) Line 898
{
n_read = initial_read; Line 900
initial_read = SIZE_MAX; Line 901
}
else Line 903
{
n_read = safe_read (STDIN_FILENO, buf, bufsize); Line 905...!syscalls auto-comment...
if (n_read == SAFE_READ_ERROR) Line 906
die (EXIT_FAILURE, errno, "%s", quotef (infile)); Line 907
}
if (n_read == 0) Line 909
break; /* eof. */ Line 910
n_read = MIN (n_read, file_size - n_written); Line 911
chunk_truncated = false; Line 912
eob = buf + n_read; Line 913
while (bp != eob) Line 915
{
size_t to_write; Line 917
bool next = false; Line 918
/* Begin looking for '\n' at last byte of chunk. */
off_t skip = MIN (n_read, MAX (0, chunk_end - n_written)); Line 921
char *bp_out = memchr (bp + skip, eolchar, n_read - skip); Line 922
if (bp_out++) Line 923
next = true; Line 924
else Line 925
bp_out = eob; Line 926
to_write = bp_out - bp; Line 927
if (k == chunk_no) Line 929
{
/* We don't use the stdout buffer here since we're writing
large chunks from an existing file, so it's more efficient
to write out directly. */
if (full_write (STDOUT_FILENO, bp, to_write) != to_write) Line 934...!syscalls auto-comment...
die (EXIT_FAILURE, errno, "%s", _("write error")); Line 935
}
else if (! k) Line 937
cwrite (new_file_flag, bp, to_write); Line 938...!syscalls auto-comment...
n_written += to_write; Line 939
bp += to_write; Line 940
n_read -= to_write; Line 941
new_file_flag = next; Line 942
/* A line could have been so long that it skipped
entire chunks. So create empty files in that case. */
while (next || chunk_end <= n_written - 1) Line 946
{
if (!next && bp == eob) Line 948
{
/* replenish buf, before going to next chunk. */
chunk_truncated = true; Line 951
break; Line 952
}
chunk_no++; Line 954
if (k && chunk_no > k) Line 955
return; Line 956
if (chunk_no == n) Line 957
chunk_end = file_size - 1; /* >= chunk_size. */ Line 958
else Line 959
chunk_end += chunk_size; Line 960
if (chunk_end <= n_written - 1) Line 961
{
if (! k) Line 963
cwrite (true, NULL, 0); Line 964...!syscalls auto-comment...
}
else Line 966
next = false; Line 967
}
}
}
if (chunk_truncated) Line 972
chunk_no++; Line 973
/* Ensure NUMBER files are created, which truncates
any existing files or notifies any consumers on fifos.
FIXME: Should we do this before EXIT_FAILURE? */
while (!k && chunk_no++ <= n) Line 978
cwrite (true, NULL, 0); Line 979...!syscalls auto-comment...
} Block 15
/* -n K/N: Extract Kth of N chunks. */
static void Line 984
bytes_chunk_extract (uintmax_t k, uintmax_t n, char *buf, size_t bufsize, Line 985
size_t initial_read, off_t file_size) Line 986
{
off_t start; Line 988
off_t end; Line 989
assert (k && n && k <= n && n <= file_size); Line 991
start = (k - 1) * (file_size / n); Line 993
end = (k == n) ? file_size : k * (file_size / n); Line 994
if (start < initial_read) Line 996
{
memmove (buf, buf + start, initial_read - start); Line 998
initial_read -= start; Line 999
}
else Line 1001
{
if (lseek (STDIN_FILENO, start, SEEK_CUR) < 0) Line 1003
die (EXIT_FAILURE, errno, "%s", quotef (infile)); Line 1004
initial_read = SIZE_MAX; Line 1005
}
while (start < end) Line 1008
{
size_t n_read; Line 1010
if (initial_read != SIZE_MAX) Line 1011
{
n_read = initial_read; Line 1013
initial_read = SIZE_MAX; Line 1014
}
else Line 1016
{
n_read = safe_read (STDIN_FILENO, buf, bufsize); Line 1018...!syscalls auto-comment...
if (n_read == SAFE_READ_ERROR) Line 1019
die (EXIT_FAILURE, errno, "%s", quotef (infile)); Line 1020
}
if (n_read == 0) Line 1022
break; /* eof. */ Line 1023
n_read = MIN (n_read, end - start); Line 1024
if (full_write (STDOUT_FILENO, buf, n_read) != n_read Line 1025...!syscalls auto-comment...
&& ! ignorable (errno)) Line 1026
die (EXIT_FAILURE, errno, "%s", quotef ("-")); Line 1027
start += n_read; Line 1028
}
} Block 16
typedef struct of_info Line 1032
{
char *of_name; Line 1034
int ofd; Line 1035
FILE *ofile; Line 1036
int opid; Line 1037
} of_t; Line 1038Block 17
enum Line 1040
{
OFD_NEW = -1, Line 1042
OFD_APPEND = -2 Line 1043
}; Block 18
/* Rotate file descriptors when we're writing to more output files than we
have available file descriptors.
Return whether we came under file resource pressure.
If so, it's probably best to close each file when finished with it. */
static bool Line 1051
ofile_open (of_t *files, size_t i_check, size_t nfiles) Line 1052...!syscalls auto-comment...
{
bool file_limit = false; Line 1054
if (files[i_check].ofd <= OFD_NEW) Line 1056
{
int fd; Line 1058
size_t i_reopen = i_check ? i_check - 1 : nfiles - 1; Line 1059
/* Another process could have opened a file in between the calls to
close and open, so we should keep trying until open succeeds or
we've closed all of our files. */
while (true) Line 1064
{
if (files[i_check].ofd == OFD_NEW) Line 1066
fd = create (files[i_check].of_name); Line 1067
else /* OFD_APPEND */ Line 1068
{
/* Attempt to append to previously opened file.
We use O_NONBLOCK to support writing to fifos,
where the other end has closed because of our
previous close. In that case we'll immediately
get an error, rather than waiting indefinitely.
In specialised cases the consumer can keep reading
from the fifo, terminating on conditions in the data
itself, or perhaps never in the case of 'tail -f'.
I.e., for fifos it is valid to attempt this reopen.
We don't handle the filter_command case here, as create()
will exit if there are not enough files in that case.
I.e., we don't support restarting filters, as that would
put too much burden on users specifying --filter commands. */
fd = open (files[i_check].of_name, Line 1084...!syscalls auto-comment...
O_WRONLY | O_BINARY | O_APPEND | O_NONBLOCK); Line 1085
}
if (-1 < fd) Line 1088
break; Line 1089
if (!(errno == EMFILE || errno == ENFILE)) Line 1091
die (EXIT_FAILURE, errno, "%s", quotef (files[i_check].of_name)); Line 1092
file_limit = true; Line 1094
/* Search backwards for an open file to close. */
while (files[i_reopen].ofd < 0) Line 1097
{
i_reopen = i_reopen ? i_reopen - 1 : nfiles - 1; Line 1099
/* No more open files to close, exit with E[NM]FILE. */
if (i_reopen == i_check) Line 1101
die (EXIT_FAILURE, errno, "%s", Line 1102
quotef (files[i_check].of_name)); Line 1103
}
if (fclose (files[i_reopen].ofile) != 0) Line 1106...!syscalls auto-comment...
die (EXIT_FAILURE, errno, "%s", quotef (files[i_reopen].of_name)); Line 1107
files[i_reopen].ofile = NULL; Line 1108
files[i_reopen].ofd = OFD_APPEND; Line 1109
}
files[i_check].ofd = fd; Line 1112
if (!(files[i_check].ofile = fdopen (fd, "a"))) Line 1113...!syscalls auto-comment...
die (EXIT_FAILURE, errno, "%s", quotef (files[i_check].of_name)); Line 1114
files[i_check].opid = filter_pid; Line 1115
filter_pid = 0; Line 1116
}
return file_limit; Line 1119
} Block 19
/* -n r/[K/]N: Divide file into N chunks in round robin fashion.
When K == 0, we try to keep the files open in parallel.
If we run out of file resources, then we revert
to opening and closing each file for each line. */
static void Line 1127
lines_rr (uintmax_t k, uintmax_t n, char *buf, size_t bufsize) Line 1128
{
bool wrapped = false; Line 1130
bool wrote = false; Line 1131
bool file_limit; Line 1132
size_t i_file; Line 1133
of_t *files IF_LINT (= NULL); Line 1134
uintmax_t line_no; Line 1135
if (k) Line 1137
line_no = 1; Line 1138
else Line 1139
{
if (SIZE_MAX < n) Line 1141
xalloc_die (); ...!common auto-comment...
files = xnmalloc (n, sizeof *files); Line 1143
/* Generate output file names. */
for (i_file = 0; i_file < n; i_file++) Line 1146
{
next_file_name (); Line 1148
files[i_file].of_name = xstrdup (outfile); Line 1149
files[i_file].ofd = OFD_NEW; Line 1150
files[i_file].ofile = NULL; Line 1151
files[i_file].opid = 0; Line 1152
}
i_file = 0; Line 1154
file_limit = false; Line 1155
}
while (true) Line 1158
{
char *bp = buf, *eob; Line 1160
size_t n_read = safe_read (STDIN_FILENO, buf, bufsize); Line 1161...!syscalls auto-comment...
if (n_read == SAFE_READ_ERROR) Line 1162
die (EXIT_FAILURE, errno, "%s", quotef (infile)); Line 1163
else if (n_read == 0) Line 1164
break; /* eof. */ Line 1165
eob = buf + n_read; Line 1166
while (bp != eob) Line 1168
{
size_t to_write; Line 1170
bool next = false; Line 1171
/* Find end of line. */
char *bp_out = memchr (bp, eolchar, eob - bp); Line 1174
if (bp_out) Line 1175
{
bp_out++; Line 1177
next = true; Line 1178
}
else Line 1180
bp_out = eob; Line 1181
to_write = bp_out - bp; Line 1182
if (k) Line 1184
{
if (line_no == k && unbuffered) Line 1186
{
if (full_write (STDOUT_FILENO, bp, to_write) != to_write) Line 1188...!syscalls auto-comment...
die (EXIT_FAILURE, errno, "%s", _("write error")); Line 1189
}
else if (line_no == k && fwrite (bp, to_write, 1, stdout) != 1) Line 1191...!syscalls auto-comment...
{
clearerr (stdout); /* To silence close_stdout(). */ Line 1193
die (EXIT_FAILURE, errno, "%s", _("write error")); Line 1194
}
if (next) Line 1196
line_no = (line_no == n) ? 1 : line_no + 1; Line 1197
}
else Line 1199
{
/* Secure file descriptor. */
file_limit |= ofile_open (files, i_file, n); Line 1202...!syscalls auto-comment...
if (unbuffered) Line 1203
{
/* Note writing to fd, rather than flushing the FILE gives
an 8% performance benefit, due to reduced data copying. */
if (full_write (files[i_file].ofd, bp, to_write) != to_write Line 1207...!syscalls auto-comment...
&& ! ignorable (errno)) Line 1208
{
die (EXIT_FAILURE, errno, "%s", Line 1210
quotef (files[i_file].of_name)); Line 1211
}
}
else if (fwrite (bp, to_write, 1, files[i_file].ofile) != 1 Line 1214...!syscalls auto-comment...
&& ! ignorable (errno)) Line 1215
{
die (EXIT_FAILURE, errno, "%s", Line 1217
quotef (files[i_file].of_name)); Line 1218
}
if (! ignorable (errno)) Line 1221
wrote = true; Line 1222
if (file_limit) Line 1224
{
if (fclose (files[i_file].ofile) != 0) Line 1226...!syscalls auto-comment...
{
die (EXIT_FAILURE, errno, "%s", Line 1228
quotef (files[i_file].of_name)); Line 1229
}
files[i_file].ofile = NULL; Line 1231
files[i_file].ofd = OFD_APPEND; Line 1232
}
if (next && ++i_file == n) Line 1234
{
wrapped = true; Line 1236
/* If no filters are accepting input, stop reading. */
if (! wrote) Line 1238
goto no_filters; Line 1239
wrote = false; Line 1240
i_file = 0; Line 1241
}
}
bp = bp_out; Line 1245
}
}
no_filters: Line 1249
/* Ensure all files created, so that any existing files are truncated,
and to signal any waiting fifo consumers.
Also, close any open file descriptors.
FIXME: Should we do this before EXIT_FAILURE? */
if (!k) Line 1254
{
int ceiling = (wrapped ? n : i_file); Line 1256
for (i_file = 0; i_file < n; i_file++) Line 1257
{
if (i_file >= ceiling && !elide_empty_files) Line 1259
file_limit |= ofile_open (files, i_file, n); Line 1260...!syscalls auto-comment...
if (files[i_file].ofd >= 0) Line 1261
closeout (files[i_file].ofile, files[i_file].ofd, Line 1262
files[i_file].opid, files[i_file].of_name); Line 1263
files[i_file].ofd = OFD_APPEND; Line 1264
}
}
IF_LINT (free (files)); Line 1267
} Block 20
#define FAIL_ONLY_ONE_WAY() \ Line 1270
do \ Line 1271
{ \ Line 1272
error (0, 0, _("cannot split in more than one way")); \ Line 1273
usage (EXIT_FAILURE); \ Line 1274
} \ Line 1275Block 21
while (0) Line 1276
/* Parse K/N syntax of chunk options. */
static void Line 1281
parse_chunk (uintmax_t *k_units, uintmax_t *n_units, char *slash) Line 1282
{
*n_units = xdectoumax (slash + 1, 1, UINTMAX_MAX, "", Line 1284
_("invalid number of chunks"), 0); Line 1285
if (slash != optarg) /* a leading number is specified. */ Line 1286
{
*slash = '\0'; Line 1288
*k_units = xdectoumax (optarg, 1, *n_units, "", Line 1289
_("invalid chunk number"), 0); Line 1290
}
} Block 22
int
main (int argc, char **argv) Line 1296
{
enum Split_type split_type = type_undef; Line 1298
size_t in_blk_size = 0; /* optimal block size of input file device */ Line 1299
size_t page_size = getpagesize (); Line 1300
uintmax_t k_units = 0; Line 1301
uintmax_t n_units = 0; Line 1302
static char const multipliers[] = "bEGKkMmPTYZ0"; Line 1304
int c; Line 1305
int digits_optind = 0; Line 1306
off_t file_size = OFF_T_MAX; Line 1307
initialize_main (&argc, &argv); VMS-specific entry point handling wildcard expansion
set_program_name (argv[0]); Retains program name and discards path
setlocale (LC_ALL, ""); Sets up internationalization (i18n)
bindtextdomain (PACKAGE, LOCALEDIR); Assigns i18n directorySets text domain for _() [gettext()] function
textdomain (PACKAGE); Sets text domain for _() [gettext()] function
atexit (close_stdout); Close stdout on exit (see gnulib)
/* Parse command line options. */
infile = bad_cast ("-"); Line 1319
outbase = bad_cast ("x"); Line 1320
while (true) Line 1322
{
/* This is the argv-index of the option we will read next. */
int this_optind = optind ? optind : 1; Line 1325
char *slash; Line 1326
c = getopt_long (argc, argv, "0123456789C:a:b:del:n:t:ux", Line 1328
longopts, NULL); Line 1329
if (c == -1) Line 1330
break; Line 1331
switch (c) Line 1333
{
case 'a': Line 1335
suffix_length = xdectoumax (optarg, 0, SIZE_MAX / sizeof (size_t), Line 1336
"", _("invalid suffix length"), 0); Line 1337
break; Line 1338
case ADDITIONAL_SUFFIX_OPTION: Line 1340
if (last_component (optarg) != optarg) Line 1341
{
error (0, 0, Line 1343
_("invalid suffix %s, contains directory separator"), Line 1344
quote (optarg)); Line 1345
usage (EXIT_FAILURE); Line 1346
}
additional_suffix = optarg; Line 1348
break; Line 1349
case 'b': Line 1351
if (split_type != type_undef) Line 1352
FAIL_ONLY_ONE_WAY (); Line 1353
split_type = type_bytes; Line 1354
/* Limit to OFF_T_MAX, because if input is a pipe, we could get more
data than is possible to write to a single file, so indicate that
immediately rather than having possibly future invocations fail. */
n_units = xdectoumax (optarg, 1, OFF_T_MAX, multipliers, Line 1358
_("invalid number of bytes"), 0); Line 1359
break; Line 1360
case 'l': Line 1362
if (split_type != type_undef) Line 1363
FAIL_ONLY_ONE_WAY (); Line 1364
split_type = type_lines; Line 1365
n_units = xdectoumax (optarg, 1, UINTMAX_MAX, "", Line 1366
_("invalid number of lines"), 0); Line 1367
break; Line 1368
case 'C': Line 1370
if (split_type != type_undef) Line 1371
FAIL_ONLY_ONE_WAY (); Line 1372
split_type = type_byteslines; Line 1373
n_units = xdectoumax (optarg, 1, MIN (SIZE_MAX, OFF_T_MAX), Line 1374
multipliers, _("invalid number of bytes"), 0); Line 1375
break; Line 1376
case 'n': Line 1378
if (split_type != type_undef) Line 1379
FAIL_ONLY_ONE_WAY (); Line 1380
/* skip any whitespace */
while (isspace (to_uchar (*optarg))) Line 1382
optarg++; Line 1383
if (STRNCMP_LIT (optarg, "r/") == 0) Line 1384
{
split_type = type_rr; Line 1386
optarg += 2; Line 1387
}
else if (STRNCMP_LIT (optarg, "l/") == 0) Line 1389
{
split_type = type_chunk_lines; Line 1391
optarg += 2; Line 1392
}
else Line 1394
split_type = type_chunk_bytes; Line 1395
if ((slash = strchr (optarg, '/'))) Line 1396
parse_chunk (&k_units, &n_units, slash); Line 1397
else Line 1398
n_units = xdectoumax (optarg, 1, UINTMAX_MAX, "", Line 1399
_("invalid number of chunks"), 0); Line 1400
break; Line 1401
case 'u': Line 1403
unbuffered = true; Line 1404
break; Line 1405
case 't': Line 1407
{
char neweol = optarg[0]; Line 1409
if (! neweol) Line 1410
die (EXIT_FAILURE, 0, _("empty record separator")); Line 1411
if (optarg[1]) Line 1412
{
if (STREQ (optarg, "\\0")) Line 1414
neweol = '\0'; Line 1415
else Line 1416
{
/* Provoke with 'split -txx'. Complain about
"multi-character tab" instead of "multibyte tab", so
that the diagnostic's wording does not need to be
changed once multibyte characters are supported. */
die (EXIT_FAILURE, 0, _("multi-character separator %s"), Line 1422
quote (optarg)); Line 1423
}
}
/* Make it explicit we don't support multiple separators. */
if (0 <= eolchar && neweol != eolchar) Line 1427
{
die (EXIT_FAILURE, 0, Line 1429
_("multiple separator characters specified")); Line 1430
}
eolchar = neweol; Line 1433
}
break; Line 1435
case '0': Line 1437
case '1': Line 1438
case '2': Line 1439
case '3': Line 1440
case '4': Line 1441
case '5': Line 1442
case '6': Line 1443
case '7': Line 1444
case '8': Line 1445
case '9': Line 1446
if (split_type == type_undef) Line 1447
{
split_type = type_digits; Line 1449
n_units = 0; Line 1450
}
if (split_type != type_undef && split_type != type_digits) Line 1452
FAIL_ONLY_ONE_WAY (); Line 1453
if (digits_optind != 0 && digits_optind != this_optind) Line 1454
n_units = 0; /* More than one number given; ignore other. */ Line 1455
digits_optind = this_optind; Line 1456
if (!DECIMAL_DIGIT_ACCUMULATE (n_units, c - '0', uintmax_t)) Line 1457
{
char buffer[INT_BUFSIZE_BOUND (uintmax_t)]; Line 1459
die (EXIT_FAILURE, 0, Line 1460
_("line count option -%s%c... is too large"), Line 1461
umaxtostr (n_units, buffer), c); Line 1462
}
break; Line 1464
case 'd': Line 1466
case 'x': Line 1467
if (c == 'd') Line 1468
suffix_alphabet = "0123456789"; Line 1469
else Line 1470
suffix_alphabet = "0123456789abcdef"; Line 1471
if (optarg) Line 1472
{
if (strlen (optarg) != strspn (optarg, suffix_alphabet)) Line 1474
{
error (0, 0, Line 1476
(c == 'd') ? Line 1477
_("%s: invalid start value for numerical suffix") : Line 1478
_("%s: invalid start value for hexadecimal suffix"), Line 1479
quote (optarg)); Line 1480
usage (EXIT_FAILURE); Line 1481
}
else Line 1483
{
/* Skip any leading zero. */
while (*optarg == '0' && *(optarg + 1) != '\0') Line 1486
optarg++; Line 1487
numeric_suffix_start = optarg; Line 1488
}
}
break; Line 1491
case 'e': Line 1493
elide_empty_files = true; Line 1494
break; Line 1495
case FILTER_OPTION: Line 1497
filter_command = optarg; Line 1498
break; Line 1499
case IO_BLKSIZE_OPTION: Line 1501
in_blk_size = xdectoumax (optarg, 1, SIZE_MAX - page_size, Line 1502
multipliers, _("invalid IO block size"), 0);Line 1503
break; Line 1504
case VERBOSE_OPTION: Line 1506
verbose = true; Line 1507
break; Line 1508
case_GETOPT_HELP_CHAR; Line 1510
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); Line 1512
default: Line 1514
usage (EXIT_FAILURE); Line 1515
}
}
if (k_units != 0 && filter_command) Line 1519
{
error (0, 0, _("--filter does not process a chunk extracted to stdout")); Line 1521
usage (EXIT_FAILURE); Line 1522
}
/* Handle default case. */
if (split_type == type_undef) Line 1526
{
split_type = type_lines; Line 1528
n_units = 1000; Line 1529
}
if (n_units == 0) Line 1532
{
error (0, 0, "%s: %s", _("invalid number of lines"), quote ("0")); Line 1534
usage (EXIT_FAILURE); Line 1535
}
if (eolchar < 0) Line 1538
eolchar = '\n'; Line 1539
set_suffix_length (n_units, split_type); Line 1541
/* Get out the filename arguments. */
if (optind < argc) Line 1545
infile = argv[optind++]; Line 1546
if (optind < argc) Line 1548
outbase = argv[optind++]; Line 1549
if (optind < argc) Line 1551
{
error (0, 0, _("extra operand %s"), quote (argv[optind])); Line 1553
usage (EXIT_FAILURE); Line 1554
}
/* Check that the suffix length is large enough for the numerical
suffix start value. */
if (numeric_suffix_start && strlen (numeric_suffix_start) > suffix_length) Line 1559
{
error (0, 0, _("numerical suffix start value is too large " Line 1561
"for the suffix length")); Line 1562
usage (EXIT_FAILURE); Line 1563
}
/* Open the input file. */
if (! STREQ (infile, "-") Line 1567
&& fd_reopen (STDIN_FILENO, infile, O_RDONLY, 0) < 0) Line 1568...!syscalls auto-comment...
die (EXIT_FAILURE, errno, _("cannot open %s for reading"), Line 1569
quoteaf (infile)); Line 1570
/* Binary I/O is safer when byte counts are used. */
xset_binary_mode (STDIN_FILENO, O_BINARY); Line 1573
/* Get the optimal block size of input device and make a buffer. */
if (fstat (STDIN_FILENO, &in_stat_buf) != 0) Line 1577...!syscalls auto-comment......!syscalls auto-comment...
die (EXIT_FAILURE, errno, "%s", quotef (infile)); Line 1578
bool specified_buf_size = !! in_blk_size; Line 1580
if (! specified_buf_size) Line 1581
in_blk_size = io_blksize (in_stat_buf); Line 1582
void *b = xmalloc (in_blk_size + 1 + page_size - 1); Line 1584
char *buf = ptr_align (b, page_size); Line 1585
size_t initial_read = SIZE_MAX; Line 1586
if (split_type == type_chunk_bytes || split_type == type_chunk_lines) Line 1588
{
file_size = input_file_size (STDIN_FILENO, &in_stat_buf, Line 1590
buf, in_blk_size); Line 1591
if (file_size < 0) Line 1592
die (EXIT_FAILURE, errno, _("%s: cannot determine file size"), Line 1593
quotef (infile)); Line 1594
initial_read = MIN (file_size, in_blk_size); Line 1595
/* Overflow, and sanity checking. */
if (OFF_T_MAX < n_units) Line 1597
{
char buffer[INT_BUFSIZE_BOUND (uintmax_t)]; Line 1599
die (EXIT_FAILURE, EOVERFLOW, "%s: %s", Line 1600
_("invalid number of chunks"), Line 1601
quote (umaxtostr (n_units, buffer))); Line 1602
}
/* increase file_size to n_units here, so that we still process
any input data, and create empty files for the rest. */
file_size = MAX (file_size, n_units); Line 1606
}
/* When filtering, closure of one pipe must not terminate the process,
as there may still be other streams expecting input from us. */
if (filter_command) Line 1611
{
struct sigaction act; Line 1613
sigemptyset (&newblocked); Line 1614
sigaction (SIGPIPE, NULL, &act); Line 1615
if (act.sa_handler != SIG_IGN) Line 1616
sigaddset (&newblocked, SIGPIPE); Line 1617
sigprocmask (SIG_BLOCK, &newblocked, &oldblocked); Line 1618
}
switch (split_type) Line 1621
{
case type_digits: Line 1623
case type_lines: Line 1624
lines_split (n_units, buf, in_blk_size); Line 1625
break; Line 1626
case type_bytes: Line 1628
bytes_split (n_units, buf, in_blk_size, SIZE_MAX, 0); Line 1629
break; Line 1630
case type_byteslines: Line 1632
line_bytes_split (n_units, buf, in_blk_size); Line 1633
break; Line 1634
case type_chunk_bytes: Line 1636
if (k_units == 0) Line 1637
bytes_split (file_size / n_units, buf, in_blk_size, initial_read, Line 1638
n_units); Line 1639
else Line 1640
bytes_chunk_extract (k_units, n_units, buf, in_blk_size, initial_read, Line 1641
file_size); Line 1642
break; Line 1643
case type_chunk_lines: Line 1645
lines_chunk_split (k_units, n_units, buf, in_blk_size, initial_read, Line 1646
file_size); Line 1647
break; Line 1648
case type_rr: Line 1650
/* Note, this is like 'sed -n ${k}~${n}p' when k > 0,
but the functionality is provided for symmetry. */
lines_rr (k_units, n_units, buf, in_blk_size); Line 1653
break; Line 1654
default: Line 1656
abort (); ...!common auto-comment...
}
IF_LINT (free (b)); Line 1660
if (close (STDIN_FILENO) != 0) Line 1662...!syscalls auto-comment...
die (EXIT_FAILURE, errno, "%s", quotef (infile)); Line 1663
closeout (NULL, output_desc, filter_pid, outfile); Line 1664
return EXIT_SUCCESS; Line 1666
} Block 23