From: Paul Eggert Date: Sat, 4 Mar 2023 21:40:28 +0000 (-0800) Subject: split: tune for when creating output files X-Git-Tag: v9.2~23 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8022874d1242f3b094b6bd001e83845e289d2bb1;p=thirdparty%2Fcoreutils.git 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. --- diff --git a/src/split.c b/src/split.c index 8550ef4420..cc581b6c65 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;