1
0
mirror of git://git.sv.gnu.org/coreutils.git synced 2026-07-29 03:50:45 +02:00

(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.
This commit is contained in:
Jim Meyering
2005-12-04 23:34:14 +00:00
parent 5e36a5a28f
commit c837e0038d
+86 -60
View File
@@ -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)))