diff options
author | Jim Meyering <jim@meyering.net> | 2005-12-04 23:34:14 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 2005-12-04 23:34:14 +0000 |
commit | c837e0038da8d90cabce96bffe05f23f6b398d8e (patch) | |
tree | 8a13cbb1241b3dc3d4f9455e82ecb6c547ada6cb /src | |
parent | 5e36a5a28f2020920fe06187311d7aee1b1c118a (diff) | |
download | coreutils-c837e0038da8d90cabce96bffe05f23f6b398d8e.tar.xz |
(fchown) [!HAVE_FCHOWN]: Define fchown(...) to -1.
(set_owner, preserve_author): New functions, factored out of copy_reg.
(copy_reg): Use them.
(copy_internal): Use them here, too.
From Andreas Gruenbacher.
Diffstat (limited to 'src')
-rw-r--r-- | src/copy.c | 146 |
1 files changed, 86 insertions, 60 deletions
diff --git a/src/copy.c b/src/copy.c index cc775eb26..729530bac 100644 --- a/src/copy.c +++ b/src/copy.c @@ -57,6 +57,7 @@ #endif #ifndef HAVE_FCHOWN # define HAVE_FCHOWN false +# define fchown(fd, uid, gid) (-1) #endif #define SAME_OWNER(A, B) ((A).st_uid == (B).st_uid) @@ -192,6 +193,67 @@ copy_dir (char const *src_name_in, char const *dst_name_in, bool new_dst, return ok; } +/* Set the owner and owning group of DEST_DESC to the st_uid and + st_gid fields of SRC_SB. If DEST_DESC is undefined (-1), set + the owner and owning group of DST_NAME instead. DEST_DESC must + refer to the same file as DEST_NAME if defined. + Return true if successful. */ + +static bool +set_owner (const struct cp_options *x, char const *dst_name, int dest_desc, + uid_t uid, gid_t gid, bool *chown_succeeded) +{ + if (HAVE_FCHOWN && dest_desc != -1) + { + if (fchown (dest_desc, uid, gid) == 0) + { + *chown_succeeded = true; + return true; + } + } + else + { + if (chown (dst_name, uid, gid) == 0) + { + *chown_succeeded = true; + return true; + } + } + if (! chown_failure_ok (x)) + { + error (0, errno, _("failed to preserve ownership for %s"), + quote (dst_name)); + if (x->require_preserve) + return false; + } + return true; +} + +/* Set the st_author field of DEST_DESC to the st_author field of + SRC_SB. If DEST_DESC is undefined (-1), set the st_author field + of DST_NAME instead. DEST_DESC must refer to the same file as + DEST_NAME if defined. */ + +static void +preserve_author (const char *dst_name, int dest_desc, const struct stat *src_sb) +{ + /* FIXME: Preserve the st_author field via the file descriptor dest_desc. */ +#if HAVE_STRUCT_STAT_ST_AUTHOR + /* Preserve the st_author field. */ + file_t file = file_name_lookup (dst_name, 0, 0); + if (file == MACH_PORT_NULL) + error (0, errno, _("failed to lookup file %s"), quote (dst_name)); + else + { + error_t err = file_chauthor (file, src_sb.st_author); + if (err) + error (0, err, _("failed to preserve authorship for %s"), + quote (dst_name)); + mach_port_deallocate (mach_task_self (), file); + } +#endif +} + /* Copy a regular file from SRC_NAME to DST_NAME. If the source file contains holes, copies holes and blocks of zeros in the source file as holes in the destination file. @@ -463,29 +525,18 @@ copy_reg (char const *src_name, char const *dst_name, } } -#if HAVE_FCHOWN if (x->preserve_ownership && ! SAME_OWNER_AND_GROUP (*src_sb, sb)) { - if (fchown (dest_desc, src_sb->st_uid, src_sb->st_gid) == 0) - *chown_succeeded = true; - else if (! chown_failure_ok (x)) - { - error (0, errno, _("failed to preserve ownership for %s"), - quote (dst_name)); - if (x->require_preserve) - { - return_val = false; - goto close_src_and_dst_desc; - } + if (! set_owner (x, dst_name, dest_desc, src_sb->st_uid, src_sb->st_gid, + chown_succeeded)) + { + return_val = false; + goto close_src_and_dst_desc; } } -#endif -#if HAVE_STRUCT_STAT_ST_AUTHOR - /* FIXME: Preserve the st_author field via the file descriptor dest_desc. */ -#endif + preserve_author (dst_name, dest_desc, src_sb); -#if HAVE_FCHMOD /* Permissions of newly-created regular files were set upon `open'. But don't return early if there were any special bits and chown succeeded, because the chown must have reset those bits. */ @@ -494,17 +545,18 @@ copy_reg (char const *src_name, char const *dst_name, && (x->preserve_mode || *new_dst) && (x->copy_as_regular || S_ISREG (src_sb->st_mode))) { - if (fchmod (dest_desc, get_dest_mode (x, src_sb->st_mode)) != 0) + if ((HAVE_FCHMOD + ? fchmod (dest_desc, get_dest_mode (x, src_sb->st_mode)) + : chmod (dst_name, get_dest_mode (x, src_sb->st_mode))) == 0) + goto close_src_and_dst_desc; + + error (0, errno, _("setting permissions for %s"), quote (dst_name)); + if (x->set_mode || x->require_preserve) { - error (0, errno, _("setting permissions for %s"), quote (dst_name)); - if (x->set_mode || x->require_preserve) - { - return_val = false; - goto close_src_and_dst_desc; - } + return_val = false; + goto close_src_and_dst_desc; } } -#endif close_src_and_dst_desc: if (close (dest_desc) < 0) @@ -1656,6 +1708,9 @@ copy_internal (char const *src_name, char const *dst_name, if ( ! preserve_metadata) return true; + if (copied_as_regular) + return delayed_ok; + /* POSIX says that `cp -p' must restore the following: - permission bits - setuid, setgid bits @@ -1668,7 +1723,7 @@ copy_internal (char const *src_name, char const *dst_name, chown turns off set[ug]id bits for non-root, so do the chmod last. */ - if (!copied_as_regular && x->preserve_timestamps) + if (x->preserve_timestamps) { struct timespec timespec[2]; timespec[0] = get_stat_atime (&src_sb); @@ -1683,44 +1738,15 @@ copy_internal (char const *src_name, char const *dst_name, } /* Avoid calling chown if we know it's not necessary. */ - if (!(copied_as_regular && HAVE_FCHOWN) && x->preserve_ownership + if (x->preserve_ownership && (new_dst || !SAME_OWNER_AND_GROUP (src_sb, dst_sb))) { - if (chown (dst_name, src_sb.st_uid, src_sb.st_gid) == 0) - chown_succeeded = true; - else if (! chown_failure_ok (x)) - { - error (0, errno, _("failed to preserve ownership for %s"), - quote (dst_name)); - if (x->require_preserve) - return false; - } + if (! set_owner (x, dst_name, -1, src_sb.st_uid, src_sb.st_gid, + &chown_succeeded)) + return false; } -#if HAVE_STRUCT_STAT_ST_AUTHOR - /* Preserve the st_author field. */ - { - file_t file = file_name_lookup (dst_name, 0, 0); - if (file == MACH_PORT_NULL) - error (0, errno, _("failed to lookup file %s"), quote (dst_name)); - else - { - error_t err = file_chauthor (file, src_sb.st_author); - if (err) - error (0, err, _("failed to preserve authorship for %s"), - quote (dst_name)); - mach_port_deallocate (mach_task_self (), file); - } - } -#endif - - /* Permissions of newly-created regular files are set by open and/or fchmod - in copy_reg. But don't return early if there were any special bits and - chown succeeded, because the chown must have reset those bits. */ - if (copied_as_regular - && (HAVE_FCHMOD - || (new_dst && !(chown_succeeded && (src_mode & ~S_IRWXUGO))))) - return delayed_ok; + preserve_author (dst_name, -1, &src_sb); if ((x->preserve_mode || new_dst) && (x->copy_as_regular || S_ISREG (src_type) || S_ISDIR (src_type))) |