git: a64518b35f6e - stable/13 - cp: Add -N flag, inspired by NetBSD's similar flag

From: Dag-Erling Smørgrav <des_at_FreeBSD.org>
Date: Wed, 17 Jan 2024 18:28:34 UTC
The branch stable/13 has been updated by des:

URL: https://cgit.FreeBSD.org/src/commit/?id=a64518b35f6e0c1aaf3c4f8f1efadf2273b9d981

commit a64518b35f6e0c1aaf3c4f8f1efadf2273b9d981
Author:     Warner Losh <imp@FreeBSD.org>
AuthorDate: 2023-12-07 19:32:27 +0000
Commit:     Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2024-01-17 16:15:57 +0000

    cp: Add -N flag, inspired by NetBSD's similar flag
    
    Add -N to supress copying of file flags when -p is specified (explicitly
    or implicitly). Often times we don't care about the flags or wish to be
    able to copy to NFS, and this comes in handy for that. FreeBSD's and
    NetBSD's cp are somewhat different, so I had to reimplement all but one
    of the patch hunks...
    
    Obtained from:          NetBSD (cp.1 1.25, cp.c 1.37, utils.c 1.28 by elad)
    Sponsored by:           Netflix
    
    Differential Revision:  https://reviews.freebsd.org/D42673
    
    (cherry picked from commit 5a52e3d00dd5e0209f6fcb1e41b5985191e6f4e7)
    
    cp: Don't warn for chflags() failing with EOPNOTSUPP if flags == 0
    
    From NetBSD's utils.c 1.5 importing importing BSDI change, with light
    formatting changes:
        Author: cgd <cgd@NetBSD.org>
        Date:   Wed Feb 26 14:40:51 1997 +0000
    
        Patch from BSDI (via Keith Bostic):
        >NFS doesn't support chflags; ignore errors unless there's reason
        >to believe we're losing bits.  (Note, this still won't be right
        >if the server supports flags and we were trying to *remove* flags
        >on a file that we copied, i.e., that we didn't create.)
    
        CVS Info: utils.c 1.6
    
    Obtained from:          NetBSD
    Sponsored by:           Netflix
    
    Differential Revision:  https://reviews.freebsd.org/D42674
    
    (cherry picked from commit 3e7e3b5bdf902a375decc11b95179fd2fbc0da2a)
---
 bin/cp/cp.1     | 14 +++++++++-----
 bin/cp/cp.c     |  7 +++++--
 bin/cp/extern.h |  2 +-
 bin/cp/utils.c  | 15 ++++++++++++---
 4 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/bin/cp/cp.1 b/bin/cp/cp.1
index b67718bd39b1..3862babafe7f 100644
--- a/bin/cp/cp.1
+++ b/bin/cp/cp.1
@@ -31,7 +31,7 @@
 .\"
 .\"	@(#)cp.1	8.3 (Berkeley) 4/18/94
 .\"
-.Dd February 23, 2022
+.Dd December 7, 2023
 .Dt CP 1
 .Os
 .Sh NAME
@@ -44,7 +44,7 @@
 .Op Fl H | Fl L | Fl P
 .Oc
 .Op Fl f | i | n
-.Op Fl alpsvx
+.Op Fl alNpsvx
 .Ar source_file target_file
 .Nm
 .Oo
@@ -52,15 +52,15 @@
 .Op Fl H | Fl L | Fl P
 .Oc
 .Op Fl f | i | n
-.Op Fl alpsvx
+.Op Fl alNpsvx
 .Ar source_file ... target_directory
 .Nm
 .Op Fl f | i | n
-.Op Fl alPpsvx
+.Op Fl alNPpsvx
 .Ar source_file target_file
 .Nm
 .Op Fl f | i | n
-.Op Fl alPpsvx
+.Op Fl alNPpsvx
 .Ar source_file ... target_directory
 .Sh DESCRIPTION
 In the first synopsis form, the
@@ -90,6 +90,10 @@ option is specified, symbolic links on the command line are followed.
 If the
 .Fl R
 option is specified, all symbolic links are followed.
+.It Fl N
+When used with
+.Fl p ,
+suppress copying file flags.
 .It Fl P
 No symbolic links are followed.
 This is the default if the
diff --git a/bin/cp/cp.c b/bin/cp/cp.c
index 24156e4b4a0b..8217a1e5d3c9 100644
--- a/bin/cp/cp.c
+++ b/bin/cp/cp.c
@@ -84,7 +84,7 @@ static char emptystring[] = "";
 
 PATH_T to = { to.p_path, emptystring, "" };
 
-int fflag, iflag, lflag, nflag, pflag, sflag, vflag;
+int Nflag, fflag, iflag, lflag, nflag, pflag, sflag, vflag;
 static int Hflag, Lflag, Rflag, rflag;
 volatile sig_atomic_t info;
 
@@ -103,7 +103,7 @@ main(int argc, char *argv[])
 
 	fts_options = FTS_NOCHDIR | FTS_PHYSICAL;
 	Pflag = 0;
-	while ((ch = getopt(argc, argv, "HLPRafilnprsvx")) != -1)
+	while ((ch = getopt(argc, argv, "HLNPRafilnprsvx")) != -1)
 		switch (ch) {
 		case 'H':
 			Hflag = 1;
@@ -113,6 +113,9 @@ main(int argc, char *argv[])
 			Lflag = 1;
 			Hflag = Pflag = 0;
 			break;
+		case 'N':
+			Nflag = 1;
+			break;
 		case 'P':
 			Pflag = 1;
 			Hflag = Lflag = 0;
diff --git a/bin/cp/extern.h b/bin/cp/extern.h
index 314cfc086ecb..f242d11cd418 100644
--- a/bin/cp/extern.h
+++ b/bin/cp/extern.h
@@ -38,7 +38,7 @@ typedef struct {
 } PATH_T;
 
 extern PATH_T to;
-extern int fflag, iflag, lflag, nflag, pflag, sflag, vflag;
+extern int Nflag, fflag, iflag, lflag, nflag, pflag, sflag, vflag;
 extern volatile sig_atomic_t info;
 
 __BEGIN_DECLS
diff --git a/bin/cp/utils.c b/bin/cp/utils.c
index 02d78350067c..f43902eab3e6 100644
--- a/bin/cp/utils.c
+++ b/bin/cp/utils.c
@@ -355,13 +355,22 @@ setfile(struct stat *fs, int fd)
 			rval = 1;
 		}
 
-	if (!gotstat || fs->st_flags != ts.st_flags)
+	if (!Nflag && (!gotstat || fs->st_flags != ts.st_flags))
 		if (fdval ?
 		    fchflags(fd, fs->st_flags) :
 		    (islink ? lchflags(to.p_path, fs->st_flags) :
 		    chflags(to.p_path, fs->st_flags))) {
-			warn("chflags: %s", to.p_path);
-			rval = 1;
+			/*
+			 * NFS doesn't support chflags; ignore errors unless
+			 * there's reason to believe we're losing bits.  (Note,
+			 * this still won't be right if the server supports
+			 * flags and we were trying to *remove* flags on a file
+			 * that we copied, i.e., that we didn't create.)
+			 */
+			if (errno != EOPNOTSUPP || fs->st_flags != 0) {
+				warn("chflags: %s", to.p_path);
+				rval = 1;
+			}
 		}
 
 	return (rval);