diff options
author | Lasse Collin <lasse.collin@tukaani.org> | 2007-11-10 01:07:37 +0200 |
---|---|---|
committer | Jim Meyering <meyering@redhat.com> | 2007-11-24 15:06:43 +0100 |
commit | cbc06bb6390c1ad4a227723078ecd7f7689251cc (patch) | |
tree | e15224e4c5e1cdbb6817b2ae74e22587b6882099 /src/copy.c | |
parent | ad8fbe0dd2c77fe41457311f91bfcf49b0bf7616 (diff) | |
download | coreutils-cbc06bb6390c1ad4a227723078ecd7f7689251cc.tar.xz |
"cp -p" tries to preserve GID even if preserving the UID fails.
* NEWS: Mention this new feature.
* src/copy.c (set_owner): Try to preserve just the GID,
when initial fchown/lchown fails.
* src/cp.c (re_protect): Likewise.
Diffstat (limited to 'src/copy.c')
-rw-r--r-- | src/copy.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/src/copy.c b/src/copy.c index 280fbf8d9..4dec5166e 100644 --- a/src/copy.c +++ b/src/copy.c @@ -172,7 +172,8 @@ copy_dir (char const *src_name_in, char const *dst_name_in, bool new_dst, safety prefer lchown if the system supports it since no symbolic links should be involved. DEST_DESC must refer to the same file as DEST_NAME if defined. - Return 1 if the syscall succeeds, 0 if it fails but it's OK + Upon failure to set both UID and GID, try to set only the GID. + Return 1 if the initial syscall succeeds, 0 if it fails but it's OK not to preserve ownership, -1 otherwise. */ static int @@ -183,11 +184,27 @@ set_owner (const struct cp_options *x, char const *dst_name, int dest_desc, { if (fchown (dest_desc, uid, gid) == 0) return 1; + if (errno == EPERM || errno == EINVAL) + { + /* We've failed to set *both*. Now, try to set just the group + ID, but ignore any failure here, and don't change errno. */ + int saved_errno = errno; + (void) fchown (dest_desc, -1, gid); + errno = saved_errno; + } } else { if (lchown (dst_name, uid, gid) == 0) return 1; + if (errno == EPERM || errno == EINVAL) + { + /* We've failed to set *both*. Now, try to set just the group + ID, but ignore any failure here, and don't change errno. */ + int saved_errno = errno; + (void) lchown (dst_name, -1, gid); + errno = saved_errno; + } } if (! chown_failure_ok (x)) |