diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2023-03-04 13:40:28 -0800 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2023-03-04 14:49:46 -0800 |
commit | 8022874d1242f3b094b6bd001e83845e289d2bb1 (patch) | |
tree | 5cc1713dda09c25a301faff6d6af4fdb983ecd68 | |
parent | 788654dd82ec204ccdcb84cc20c7595d20a5e5a1 (diff) | |
download | coreutils-8022874d1242f3b094b6bd001e83845e289d2bb1.tar.gz |
split: tune for when creating output files
* src/split.c (create): Avoid fstat + ftruncate in the usual case
where the output file does not already exist, by trying
to create it with O_EXCL first. This costs a failed open
in the unusual case where the output file already exists,
but that’s OK.
-rw-r--r-- | src/split.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/src/split.c b/src/split.c index 8550ef442..cc581b6c6 100644 --- a/src/split.c +++ b/src/split.c @@ -459,7 +459,11 @@ create (char const *name) if (verbose) fprintf (stdout, _("creating file %s\n"), quoteaf (name)); - int fd = open (name, O_WRONLY | O_CREAT | O_BINARY, MODE_RW_UGO); + int oflags = O_WRONLY | O_CREAT | O_BINARY; + int fd = open (name, oflags | O_EXCL, MODE_RW_UGO); + if (0 <= fd || errno != EEXIST) + return fd; + fd = open (name, oflags, MODE_RW_UGO); if (fd < 0) return fd; struct stat out_stat_buf; @@ -468,8 +472,10 @@ create (char const *name) if (SAME_INODE (in_stat_buf, out_stat_buf)) die (EXIT_FAILURE, 0, _("%s would overwrite input; aborting"), quoteaf (name)); - if (ftruncate (fd, 0) != 0 - && (S_ISREG (out_stat_buf.st_mode) || S_TYPEISSHM (&out_stat_buf))) + bool regularish + = S_ISREG (out_stat_buf.st_mode) || S_TYPEISSHM (&out_stat_buf); + if (! (regularish && out_stat_buf.st_size == 0) + && ftruncate (fd, 0) < 0 && regularish) die (EXIT_FAILURE, errno, _("%s: error truncating"), quotef (name)); return fd; |