Subject: bin/37018: cp(1) verbose flag stops working after error
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: None <dieter.NetBSD@pandora.be>
List: netbsd-bugs
Date: 09/22/2007 21:35:00
>Number:         37018
>Category:       bin
>Synopsis:       cp(1) verbose flag stops working after error
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Sep 22 21:35:00 +0000 2007
>Originator:     dieter roelants
>Release:        NetBSD 4.99.22
>Organization:
>Environment:
System: NetBSD simult.amelgem.be 4.99.22 NetBSD 4.99.22 (SIMULT) #23: Mon Jul 2 19:30:03 CEST 2007 dieter@simult.amelgem.be:/build/obj.i386.current/sys/arch/i386/compile/SIMULT i386
Architecture: i386
Machine: i386
>Description:
	The verbose flag of cp(1) should show all files being
	successfully copied. However, after an error is encountered,
	later successful copies aren't shown.
>How-To-Repeat:

simult:p5:/tmp/p$ ls -l
total 8
-rw-r--r--  1 dieter  wheel    0 Sep 22 21:25 a
----------  1 dieter  wheel    0 Sep 22 21:25 b
-rw-r--r--  1 dieter  wheel    0 Sep 22 21:25 c
drwxr-xr-x  2 dieter  wheel  512 Sep 22 21:25 dest
simult:p5:/tmp/p$ cp -v ? dest/
c -> dest/c
cp: b: Permission denied
simult:p5:/tmp/p$ ls dest
a c

>Fix:

Index: cp.c
===================================================================
RCS file: /cvsroot/src/bin/cp/cp.c,v
retrieving revision 1.48
diff -u -r1.48 cp.c
--- cp.c	26 Dec 2006 00:13:24 -0000	1.48
+++ cp.c	22 Sep 2007 19:15:11 -0000
@@ -286,7 +286,7 @@
 	struct stat to_stat;
 	FTS *ftsp;
 	FTSENT *curr;
-	int base, dne, rval, sval;
+	int base, dne, rval, sval, tval;
 	size_t nlen;
 	char *p, *target_mid;
 
@@ -296,18 +296,18 @@
 	if ((ftsp = fts_open(argv, fts_options, mastercmp)) == NULL)
 		err(EXIT_FAILURE, "%s", argv[0]);
 		/* NOTREACHED */
-	for (rval = 0; (curr = fts_read(ftsp)) != NULL;) {
+	for (rval = 0; (curr = fts_read(ftsp)) != NULL; tval = 0) {
 		switch (curr->fts_info) {
 		case FTS_NS:
 		case FTS_DNR:
 		case FTS_ERR:
 			warnx("%s: %s", curr->fts_path,
 					strerror(curr->fts_errno));
-			rval = 1;
+			tval = 1;
 			continue;
 		case FTS_DC:			/* Warn, continue. */
 			warnx("%s: directory causes a cycle", curr->fts_path);
-			rval = 1;
+			tval = 1;
 			continue;
 		}
 
@@ -320,7 +320,7 @@
 			    to.target_end - to.p_path + 1) > MAXPATHLEN) {
 				warnx("%s/%s: name too long (not copied)",
 						to.p_path, curr->fts_name);
-				rval = 1;
+				tval = 1;
 				continue;
 			}
 
@@ -366,7 +366,7 @@
 			if (target_mid - to.p_path + nlen >= PATH_MAX) {
 				warnx("%s%s: name too long (not copied)",
 				    to.p_path, p);
-				rval = 1;
+				tval = 1;
 				continue;
 			}
 			(void)strncat(target_mid, p, nlen);
@@ -384,7 +384,7 @@
 			    to_stat.st_ino == curr->fts_statp->st_ino) {
 				warnx("%s and %s are identical (not copied).",
 				    to.p_path, curr->fts_path);
-				rval = 1;
+				tval = 1;
 				if (S_ISDIR(curr->fts_statp->st_mode))
 					(void)fts_set(ftsp, curr, FTS_SKIP);
 				continue;
@@ -393,7 +393,7 @@
 			    S_ISDIR(to_stat.st_mode)) {
 		warnx("cannot overwrite directory %s with non-directory %s",
 				    to.p_path, curr->fts_path);
-				rval = 1;
+				tval = 1;
 				continue;
 			}
 			if (!S_ISDIR(curr->fts_statp->st_mode))
@@ -406,10 +406,10 @@
 			if((fts_options & FTS_LOGICAL) ||
 			   ((fts_options & FTS_COMFOLLOW) && curr->fts_level == 0)) {
 				if (copy_file(curr, dne))
-					rval = 1;
+					tval = 1;
 			} else {	
 				if (copy_link(curr, !dne))
-					rval = 1;
+					tval = 1;
 			}
 			break;
 		case S_IFDIR:
@@ -418,7 +418,7 @@
 					warnx("%s is a directory (not copied).",
 					    curr->fts_path);
 				(void)fts_set(ftsp, curr, FTS_SKIP);
-				rval = 1;
+				tval = 1;
 				break;
 			}
 
@@ -459,7 +459,7 @@
                         	 * forever.
 				 */
 				if (pflag && setfile(curr->fts_statp, 0))
-					rval = 1;
+					tval = 1;
 				else if (dne)
 					(void)chmod(to.p_path, 
 					    curr->fts_statp->st_mode);
@@ -475,7 +475,7 @@
 			{
 				warnx("directory %s encountered when not expected.",
 				    curr->fts_path);
-				rval = 1;
+				tval = 1;
 				break;
 			}
 
@@ -484,26 +484,27 @@
 		case S_IFCHR:
 			if (Rflag) {
 				if (copy_special(curr->fts_statp, !dne))
-					rval = 1;
+					tval = 1;
 			} else
 				if (copy_file(curr, dne))
-					rval = 1;
+					tval = 1;
 			break;
 		case S_IFIFO:
 			if (Rflag) {
 				if (copy_fifo(curr->fts_statp, !dne))
-					rval = 1;
+					tval = 1;
 			} else 
 				if (copy_file(curr, dne))
-					rval = 1;
+					tval = 1;
 			break;
 		default:
 			if (copy_file(curr, dne))
-				rval = 1;
+				tval = 1;
 			break;
 		}
-		if (vflag && !rval)
+		if (vflag && !tval)
 			(void)printf("%s -> %s\n", curr->fts_path, to.p_path);
+		rval |= tval;
 	}
 	if (errno) {
 		err(EXIT_FAILURE, "fts_read");