The attached patch adds a new -q option to cp that allows ignoring file flags whilst copying with the existing -p, (preserve), option. Without -p, the new -q option does nothing.
Rationale: File flags are not widely used, but we use them on copies of local data that is not expected to change, (and is archived elsewhere as immutable). When copying data from such locations, it is often preferable to preserve the original file ownership and timestamp, but currently using the -p option also causes the file flags to be set on the new copy. This is inconvenient if done by a regular user, as the uchg flag has to be manually removed afterwards. If done by root, the schg flag can only be removed by booting into single-user mode. The following patch avoids this inconvenience by allowing the user invoking cp to skip copying of flags altogether whilst preserving the other file attributes. --- cp.1.dist Mon Sep 2 18:18:41 2019 +++ cp.1 Thu Dec 22 08:56:17 2022 @@ -128,6 +128,10 @@ and either the user ID or group ID cannot be preserved, neither the set-user-ID nor set-group-ID bits are preserved in the copy's permissions. +.It Fl q +Modify the behaviour of the +.Fl p +option such that file flags are not preserved. .It Fl R If .Ar source --- cp.c.dist Fri Jun 28 10:34:58 2019 +++ cp.c Thu Dec 22 08:47:01 2022 @@ -71,7 +71,7 @@ PATH_T to = { to.p_path, "" }; uid_t myuid; -int Rflag, fflag, iflag, pflag, rflag, vflag; +int Rflag, fflag, iflag, pflag, qflag, rflag, vflag; mode_t myumask; enum op { FILE_TO_FILE, FILE_TO_DIR, DIR_TO_DNE }; @@ -88,7 +88,7 @@ char *target; Hflag = Lflag = Pflag = Rflag = 0; - while ((ch = getopt(argc, argv, "HLPRafiprv")) != -1) + while ((ch = getopt(argc, argv, "HLPRafipqrv")) != -1) switch (ch) { case 'H': Hflag = 1; @@ -121,6 +121,9 @@ break; case 'p': pflag = 1; + break; + case 'q': + qflag = 1; break; case 'r': rflag = 1; --- extern.h.dist Sat Dec 26 15:11:43 2015 +++ extern.h Thu Dec 22 08:47:22 2022 @@ -40,7 +40,7 @@ extern PATH_T to; extern uid_t myuid; -extern int fflag, iflag, pflag; +extern int fflag, iflag, pflag, qflag; extern mode_t myumask; extern char *__progname; --- utils.c.dist Sun Nov 28 16:28:41 2021 +++ utils.c Thu Dec 22 08:51:25 2022 @@ -314,12 +314,14 @@ * 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.) */ - errno = 0; - if (fd >= 0 ? fchflags(fd, fs->st_flags) : - chflagsat(AT_FDCWD, to.p_path, fs->st_flags, AT_SYMLINK_NOFOLLOW)) - if (errno != EOPNOTSUPP || fs->st_flags != 0) { - warn("chflags: %s", to.p_path); - rval = 1; + if (qflag == 0) { + errno = 0; + if (fd >= 0 ? fchflags(fd, fs->st_flags) : + chflagsat(AT_FDCWD, to.p_path, fs->st_flags, AT_SYMLINK_NOFOLLOW)) + if (errno != EOPNOTSUPP || fs->st_flags != 0) { + warn("chflags: %s", to.p_path); + rval = 1; + } } return (rval); }