tech-userlevel archive

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

Re: cp -i might violate POSIX



On Sat, Mar 05, 2016 at 03:03:36AM +0100, Dmitrij D. Czarkoff wrote:
> So the goal of the diff is to replace something like
> 
>   $ for src in ${files}; do [ -r "$src" ] && cp ${src} dst/; done
> 
> with
> 
>   $ yes n | cp -i ${files} dst/
> 
> ?
Or alternatively, to state in the manual that -i will be ignored
if stdin is not a tty, ideally with some rationale on why we deviate
from POSIX there.


> Well, I guess you can save some performance this way, but it is just
> too ugly to make sense.
I'd argue that
>   $ yes n | cp -i ${files} dst/
even if ugly, is more straightforward a solution to arrive at from
the manual alone than
>   $ for src in ${files}; do [ -r "$src" ] && cp ${src} dst/; done
unless one is already familiar with the (undocumented) twist.


> I'd rather add "-n" flag.
I agree that -n would be nice (below a FreeBSD-inspired patch),
but I think -i should be fixed (or the behavior documented) regardless.


----8<-----------------------------------------------------------------

--- bin/cp/cp.1.orig
+++ bin/cp/cp.1
@@ -44,7 +44,7 @@
 .Fl R
 .Op Fl H | Fl L | Fl P
 .Oc
-.Op Fl f | i
+.Op Fl f | i | n
 .Op Fl alNpv
 .Ar source_file target_file
 .Nm cp
@@ -52,7 +52,7 @@
 .Fl R
 .Op Fl H | Fl L | Fl P
 .Oc
-.Op Fl f | i
+.Op Fl f | i | n
 .Op Fl alNpv
 .Ar source_file ... target_directory
 .Sh DESCRIPTION
@@ -82,11 +82,14 @@ Same as
 For each existing destination pathname, attempt to overwrite it.
 If permissions do not allow copy to succeed, remove it and create a new
 file, without prompting for confirmation.
+.br
 (The
-.Fl i
-option is ignored if the
 .Fl f
-option is specified.)
+option overrides any previous
+.Fl i
+or
+.Fl n
+options.)
 .It Fl H
 If the
 .Fl R
@@ -100,6 +103,24 @@ that would overwrite an existing file.
 If the response from the standard input begins with the character
 .Sq Li y ,
 the file copy is attempted.
+.br
+(The
+.Fl i
+option overrides any previous
+.Fl f
+or
+.Fl n
+options.)
+.It Fl n
+Do not overwrite existing files.
+.br
+(The
+.Fl n
+option overrides any previous
+.Fl i
+or
+.Fl f
+options.)
 .It Fl L
 If the
 .Fl R
--- bin/cp/cp.c.orig
+++ bin/cp/cp.c
@@ -87,7 +87,7 @@ static char empty[] = "";
 PATH_T to = { .p_end = to.p_path, .target_end = empty  };
 
 uid_t myuid;
-int Hflag, Lflag, Rflag, Pflag, fflag, iflag, lflag, pflag, rflag, vflag, Nflag;
+int Hflag, Lflag, Rflag, Pflag, fflag, iflag, lflag, nflag, pflag, rflag, vflag, Nflag;
 mode_t myumask;
 sig_atomic_t pinfo;
 
@@ -114,7 +114,7 @@ main(int argc, char *argv[])
 	(void)setlocale(LC_ALL, "");
 
 	Hflag = Lflag = Pflag = Rflag = 0;
-	while ((ch = getopt(argc, argv, "HLNPRfailprv")) != -1) 
+	while ((ch = getopt(argc, argv, "HLNPRfailnprv")) != -1)
 		switch (ch) {
 		case 'H':
 			Hflag = 1;
@@ -142,11 +142,15 @@ main(int argc, char *argv[])
 			break;
 		case 'f':
 			fflag = 1;
-			iflag = 0;
+			nflag = iflag = 0;
 			break;
 		case 'i':
 			iflag = isatty(fileno(stdin));
-			fflag = 0;
+			fflag = nflag = 0;
+			break;
+		case 'n':
+			nflag = 1;
+			fflag = iflag = 0;
 			break;
 		case 'l':
 			lflag = 1;
--- bin/cp/extern.h.orig
+++ bin/cp/extern.h
@@ -42,7 +42,7 @@ typedef struct {
 
 extern PATH_T to;
 extern uid_t myuid;
-extern int Rflag, rflag, Hflag, Lflag, Pflag, fflag, iflag, lflag, pflag, Nflag;
+extern int Rflag, rflag, Hflag, Lflag, Pflag, fflag, iflag, lflag, nflag, pflag, Nflag;
 extern mode_t myumask;
 extern sig_atomic_t pinfo;
 
--- bin/cp/utils.c.orig
+++ bin/cp/utils.c
@@ -120,7 +120,10 @@ copy_file(FTSENT *entp, int dne)
 		struct stat sb;
 		int sval;
 
-		if (iflag) {
+		if (nflag) {
+			(void)close(from_fd);
+			return (0);
+		} else if (iflag) {
 			(void)fprintf(stderr, "overwrite %s? ", to.p_path);
 			checkch = ch = getchar();
 			while (ch != '\n' && ch != EOF)
@@ -412,8 +415,8 @@ void
 usage(void)
 {
 	(void)fprintf(stderr,
-	    "usage: %s [-R [-H | -L | -P]] [-f | -i] [-alNpv] src target\n"
-	    "       %s [-R [-H | -L | -P]] [-f | -i] [-alNpv] src1 ... srcN directory\n",
+	    "usage: %s [-R [-H | -L | -P]] [-f | -i | -n] [-alNpv] src target\n"
+	    "       %s [-R [-H | -L | -P]] [-f | -i | -n] [-alNpv] src1 ... srcN directory\n",
 	    getprogname(), getprogname());
 	exit(1);
 	/* NOTREACHED */


Home | Main Index | Thread Index | Old Index