tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: split(1): add '-c' to continue creating files



Jan Schaumann <jschauma%netmeister.org@localhost> wrote:

> The attached diff adds a flag "-c" (mnemonic "create,
> don't overwrite" or "continue where you left off"):

Ugh, and once more without a race condition.

-Jan
Index: split.1
===================================================================
RCS file: /cvsroot/src/usr.bin/split/split.1,v
retrieving revision 1.16
diff -u -p -r1.16 split.1
--- split.1	30 Jan 2023 15:22:02 -0000	1.16
+++ split.1	12 Feb 2023 21:18:10 -0000
@@ -29,7 +29,7 @@
 .\"
 .\"	@(#)split.1	8.3 (Berkeley) 4/16/94
 .\"
-.Dd January 28, 2023
+.Dd February 12, 2023
 .Dt SPLIT 1
 .Os
 .Sh NAME
@@ -37,6 +37,7 @@
 .Nd split a file into pieces
 .Sh SYNOPSIS
 .Nm
+.Op Fl c
 .Op Fl a Ar suffix_length
 .Oo
 .Fl b Ar byte_count Ns Oo Li k|m Oc |
@@ -78,6 +79,9 @@ If
 is appended to the number, the file is split into
 .Ar byte_count
 megabyte pieces.
+.It Fl c
+Continue creating files and do not overwrite existing
+output files.
 .It Fl l
 Create smaller files
 .Ar line_count
@@ -111,6 +115,16 @@ If the
 argument is not specified,
 .Ql x
 is used.
+.Pp
+By default,
+.Nm
+will overwrite any existing output files.
+If the
+.Fl c
+flag is specified,
+.Nm
+will instead continue to generate output file names
+until it finds one that does not already exist.
 .Sh STANDARDS
 The
 .Nm
Index: split.c
===================================================================
RCS file: /cvsroot/src/usr.bin/split/split.c,v
retrieving revision 1.30
diff -u -p -r1.30 split.c
--- split.c	12 Feb 2023 20:43:21 -0000	1.30
+++ split.c	12 Feb 2023 21:18:11 -0000
@@ -56,6 +56,7 @@ __RCSID("$NetBSD: split.c,v 1.30 2023/02
 
 #define DEFLINE	1000		/* Default num lines per file. */
 
+static int clobber = 1;         /* Whether to overwrite existing output files. */
 static int file_open;		/* If a file is open. */
 static int ifd = STDIN_FILENO, ofd = -1; /* Input/output file descriptors. */
 static char *fname;		/* File name prefix. */
@@ -79,7 +80,7 @@ main(int argc, char *argv[])
 	off_t numlines = 0;	/* Line count to split on. */
 	off_t chunks = 0;	/* Number of chunks to split into. */
 
-	while ((ch = getopt(argc, argv, "0123456789b:l:a:n:")) != -1)
+	while ((ch = getopt(argc, argv, "0123456789b:cl:a:n:")) != -1)
 		switch (ch) {
 		case '0': case '1': case '2': case '3': case '4':
 		case '5': case '6': case '7': case '8': case '9':
@@ -115,6 +116,9 @@ main(int argc, char *argv[])
 			else if (*ep == 'm')
 				bytecnt *= 1024 * 1024;
 			break;
+		case 'c':               /* Continue, don't overwrite output files. */
+			clobber = 0;
+			break;
 		case 'l':		/* Line count. */
 			if (numlines != 0)
 				usage();
@@ -317,6 +321,11 @@ newfile(void)
 	static int fnum;
 	static char *fpnt;
 	int quot, i;
+	int flags = O_WRONLY | O_CREAT | O_TRUNC;
+
+	if (!clobber) {
+		flags |= O_EXCL;
+	}
 
 	if (ofd == -1) {
 		fpnt = fname + strlen(fname);
@@ -324,6 +333,7 @@ newfile(void)
 	} else if (close(ofd) != 0)
 		err(1, "%s", fname);
 
+again:
 	quot = fnum;
 
 	/* If '-a' is not specified, then we automatically expand the
@@ -364,8 +374,13 @@ newfile(void)
 	if (quot > 0)
 		errx(1, "too many files.");
 	++fnum;
-	if ((ofd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, DEFFILEMODE)) < 0)
+
+	if ((ofd = open(fname, flags, DEFFILEMODE)) < 0) {
+		if (!clobber && errno == EEXIST) {
+			goto again;
+		}
 		err(1, "%s", fname);
+	}
 }
 
 static size_t


Home | Main Index | Thread Index | Old Index