Jim,
> [to lurkers, I'm hoping finally to check in Andreas'
> ACL patches soon. http://www.suse.de/~agruen/coreutils/5.91/ ]
I'm taking the lurkers into CC now ;)
thank you very much for your feedback. Many of your comments relate only to
the xattr patch I've sent in addition to the acl patches. My focus is on the
acl patches first; let's do them before looking at the xattr patch, please.
I'll keep your other comments for later.
On Thursday 24 November 2005 14:31, Jim Meyering wrote:
> -------------
> Please make sure that `make distcheck' (make syntax-check,
> in particular) passes. There are a few minor snags.
A ``make syntax-check'' fails for me because there is no cvsu utility. I found
a Perl version from somewhere on the net. Could you please make it so that
``make syntax-check'' will also work with the tarballs, and make it so that
it only uses commonly available tools? This would make it a lot simpler for
me; a Google search reveals that others have asked for this before, too
(http://lists.gnu.org/archive/html/bug-coreutils/2004-01/msg00068.html).
I now get this:
> ./m4/gettext.m4: AC_REQUIRE([jm_AC_TYPE_LONG_LONG])dnl
> ./m4/gettext.m4: AC_REQUIRE([jm_AC_HEADER_INTTYPES_H])
> ./m4/gettext.m4: AC_REQUIRE([jm_AC_HEADER_STDINT_H])
> ./m4/gettext.m4: AC_REQUIRE([jm_GLIBC21])dnl
> ./m4/gettext.m4: AC_REQUIRE([jm_AC_TYPE_UINTMAX_T])dnl
> ./m4/glibc21.m4:AC_DEFUN([jm_GLIBC21],
> ./m4/inttypes_h.m4:AC_DEFUN([jm_AC_HEADER_INTTYPES_H],
> ./m4/longlong.m4:AC_DEFUN([jm_AC_TYPE_LONG_LONG],
> ./m4/stdint_h.m4:AC_DEFUN([jm_AC_HEADER_STDINT_H],
> ./m4/uintmax_t.m4:AC_DEFUN([jm_AC_TYPE_UINTMAX_T],
> ./m4/uintmax_t.m4: AC_REQUIRE([jm_AC_HEADER_INTTYPES_H])
> ./m4/uintmax_t.m4: AC_REQUIRE([jm_AC_HEADER_STDINT_H])
> ./m4/uintmax_t.m4: AC_REQUIRE([jm_AC_TYPE_UNSIGNED_LONG_LONG])
> ./m4/ulonglong.m4:AC_DEFUN([jm_AC_TYPE_UNSIGNED_LONG_LONG],
> Makefile.maint: do not use jm_ in m4 macro names
> make: *** [sc_prohibit_jm_in_m4] Error 1
``Make distcheck'' fails because my gzip doesn't have the ``--rsyncable''
option. After removing this option, it screws up in strftime-check:
> --- strftime-check-src 2005-12-04 20:21:30.000000000 +0000
> +++ strftime-check-info 2005-12-04 20:21:31.000000000 +0000
> @@ -1,42 +1 @@
> -%
> -A
> -B
> -C
> -D
> -F
> -G
> -H
> -I
> -M
> N
> -P
> -R
> -S
> -T
> -U
> -V
> -W
> -X
> -Y
> -Z
> -a
> -b
> -c
> -d
> -e
> -g
> -h
> -j
> -k
> -l
> -m
> -n
> -p
> -r
> -s
> -t
> -u
> -w
> -x
> -y
> -z
> make[2]: *** [strftime-check] Error 1
> make[2]: Leaving directory `/var/tmp/coreutils'
> make[1]: *** [distcheck-hook] Error 2
> make[1]: Leaving directory `/var/tmp/coreutils'
> make: *** [distcheck] Error 2
The acl tests pass when run by hand (see the minor attached fix though).
> -------------
> Some of your new functions (I'm looking at copy.c)
> lack comments describing what they do, and their inputs and outputs.
> Please add them.
>
> copy.c (copy_internal)
> s/dst_mode_valid/restore_dst_mode/
> declare it to be `bool', not int
Done.
> -------------
> In cp.c: why set new->mode when new->mode_valid is false?
>
> new->mode = stats.st_mode;
> new->mode_valid = 0;
Fixed. I've also renamed mode_valid to restore_mode like above.
> -------------
> In copy.c, #include "acl.h" in alphabetical order -- so
> before the other "*.h" headers.
Done.
> -------------
> In copy_internal, the new code adds a race condition:
> call mkdir (dir, ...
> lstat (dir, ... to see if we have S_IRWXU access,
> if not, call chmod (dir, ... to add those permissions.
Well, the same pattern exists in other places the code, e.g., mknod followed
by chown followed by chmod in copy_internal().
> Having just rewritten remove.c to be reentrant, I wondered
> if we could avoid the race using openat-style functions (lib/openat.c).
> Hmm... there seems to be no mkdirat-like function, even in Solaris --
> I expected openat to have an option to create directories, just as
> unlinkat has an option to make it work like rmdir.
> What we need is a mkdir-like function that returns a file descriptor
> open on the resulting directory. It's feasible on systems with
> O_NOFOLLOW support.
A function that atomically changes into the new directory would work as well,
as would setting the initial permissions to S_IRWXU only.
> Your change also removes the relatively new HAVE_FCHMOD code that
> uses fchmod to avoid a race condition. I do see how that conflicted
> with adding ACL support, but wonder... Do you know if there are any
> ACL interfaces (for doing things like acl_get_file and acl_set_file)
> that operate on file descriptors rather than on file names?
I have reworked that, and I'm now using file handle based acl operations where
I can, too.
> We can save rewriting copy.c for another day.
> For now, I'd like to get ACL support in.
That's a long standing wish of mine, too ;)
The following patches are attached (apply in this order):
copy_reg_cleanup.diff
Move some of the functionality duplicated in copy_reg and
copy_internal in separate functions, and clean up the logic in
copy_reg and copy_internal.
coreutils-acl.diff
Dummy acl support, remove umask_kill, fix the logic for acls.
coreutils-acl+posix.diff
POSIX 1003.1e draft 17 acl support. Now covers Linux and others
like FreeBSD. I cannot test the non-Linux stuff very well, so
there might be a few minor issues.
mv-acl-test.diff
A minor test case fix.
Cheers,
Andreas.
--
Andreas Gruenbacher <[EMAIL PROTECTED]>
SUSE Labs, SUSE LINUX PRODUCTS GMBH / Novell Inc.
Index: coreutils/src/copy.c
===================================================================
--- coreutils.orig/src/copy.c
+++ coreutils/src/copy.c
@@ -52,13 +52,6 @@
#include "xreadlink.h"
#include "yesno.h"
-#ifndef HAVE_FCHMOD
-# define HAVE_FCHMOD false
-#endif
-#ifndef HAVE_FCHOWN
-# define HAVE_FCHOWN false
-#endif
-
#define SAME_OWNER(A, B) ((A).st_uid == (B).st_uid)
#define SAME_GROUP(A, B) ((A).st_gid == (B).st_gid)
#define SAME_OWNER_AND_GROUP(A, B) (SAME_OWNER (A, B) && SAME_GROUP (A, B))
@@ -192,6 +185,69 @@ copy_dir (char const *src_name_in, char
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
+ if (dest_desc != -1)
+ {
+ if (fchown (dest_desc, uid, gid) == 0)
+ {
+ *chown_succeeded = true;
+ return true;
+ }
+ }
+ else
+#endif
+ {
+ 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 +519,18 @@ copy_reg (char const *src_name, char con
}
}
-#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 +539,20 @@ copy_reg (char const *src_name, char con
&& (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
+ if (fchmod (dest_desc, get_dest_mode (x, src_sb->st_mode)) == 0)
+ goto close_src_and_dst_desc;
+#else
+ if (chmod (dst_name, get_dest_mode (x, src_sb->st_mode)) == 0)
+ goto close_src_and_dst_desc;
+#endif
+ 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 +1704,9 @@ copy_internal (char const *src_name, cha
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 +1719,7 @@ copy_internal (char const *src_name, cha
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 +1734,15 @@ copy_internal (char const *src_name, cha
}
/* 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)))
Index: coreutils/tests/mv/acl
===================================================================
--- coreutils.orig/tests/mv/acl
+++ coreutils/tests/mv/acl
@@ -14,14 +14,15 @@ if test "$VERBOSE" = yes; then
setfacl --version
fi
+if test -z "$other_partition_tmpdir"; then
+ (exit 77); exit 77
+fi
+
pwd=`pwd`
t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$
trap 'status=$?; cd $pwd; chmod -R u+rwx $t0; rm -rf $t0 && exit $status' 0
trap '(exit $?); exit $?' 1 2 13 15
-if test -z "$other_partition_tmpdir"; then
- (exit 77); exit 77
-fi
t0="$t0 $other_partition_tmpdir"
framework_failure=0
Index: coreutils/src/copy.c
===================================================================
--- coreutils.orig/src/copy.c
+++ coreutils/src/copy.c
@@ -30,6 +30,7 @@
#endif
#include "system.h"
+#include "acl.h"
#include "backupfile.h"
#include "buffer-lcm.h"
#include "copy.h"
@@ -95,26 +96,6 @@ static char const *top_level_dst_name;
/* The invocation name of this program. */
extern char *program_name;
-/* Encapsulate selection of the file mode to be applied to
- new non-directories. */
-
-static mode_t
-get_dest_mode (const struct cp_options *option, mode_t mode)
-{
- /* In some applications (e.g., install), use precisely the
- specified mode. */
- if (option->set_mode)
- return option->mode;
-
- /* Honor the umask for `cp', but not for `mv' or `cp -p'.
- In addition, `cp' without -p must clear the set-user-ID and set-group-ID
- bits. POSIX requires it do that when creating new files. */
- if (!option->move_mode && !option->preserve_mode)
- mode &= (option->umask_kill & ~(S_ISUID | S_ISGID));
-
- return mode;
-}
-
/* FIXME: describe */
/* FIXME: rewrite this to use a hash table so we avoid the quadratic
performance hit that's probably noticeable only on trees deeper
@@ -193,25 +174,19 @@ copy_dir (char const *src_name_in, char
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)
+ uid_t uid, gid_t gid)
{
#if HAVE_FCHOWN
if (dest_desc != -1)
{
if (fchown (dest_desc, uid, gid) == 0)
- {
- *chown_succeeded = true;
- return true;
- }
+ return true;
}
else
#endif
{
if (chown (dst_name, uid, gid) == 0)
- {
- *chown_succeeded = true;
- return true;
- }
+ return true;
}
if (! chown_failure_ok (x))
{
@@ -261,7 +236,6 @@ preserve_author (const char *dst_name, i
static bool
copy_reg (char const *src_name, char const *dst_name,
const struct cp_options *x, mode_t dst_mode, bool *new_dst,
- bool *chown_succeeded,
struct stat const *src_sb)
{
char *buf;
@@ -521,8 +495,7 @@ copy_reg (char const *src_name, char con
if (x->preserve_ownership && ! SAME_OWNER_AND_GROUP (*src_sb, sb))
{
- if (! set_owner (x, dst_name, dest_desc, src_sb->st_uid, src_sb->st_gid,
- chown_succeeded))
+ if (! set_owner (x, dst_name, dest_desc, src_sb->st_uid, src_sb->st_gid))
{
return_val = false;
goto close_src_and_dst_desc;
@@ -531,27 +504,16 @@ copy_reg (char const *src_name, char con
preserve_author (dst_name, dest_desc, src_sb);
- /* 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. */
- if (!(*new_dst
- && !(*chown_succeeded && (src_sb->st_mode & ~S_IRWXUGO)))
- && (x->preserve_mode || *new_dst)
- && (x->copy_as_regular || S_ISREG (src_sb->st_mode)))
- {
-#if HAVE_FCHMOD
- if (fchmod (dest_desc, get_dest_mode (x, src_sb->st_mode)) == 0)
- goto close_src_and_dst_desc;
-#else
- if (chmod (dst_name, get_dest_mode (x, src_sb->st_mode)) == 0)
- goto close_src_and_dst_desc;
-#endif
- 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;
- }
+ if (x->preserve_mode || x->move_mode)
+ {
+ if (copy_acl (src_name, source_desc, dst_name, dest_desc,
+ src_sb->st_mode) != 0 && x->require_preserve)
+ return_val = false;
+ }
+ else if (x->set_mode)
+ {
+ if (set_acl (dst_name, dest_desc, x->mode) != 0)
+ return_val = false;
}
close_src_and_dst_desc:
@@ -989,12 +951,13 @@ copy_internal (char const *src_name, cha
struct stat dst_sb;
mode_t src_mode;
mode_t src_type;
+ mode_t dst_mode IF_LINT (= 0);
+ bool restore_dst_mode = false;
char *earlier_file = NULL;
char *dst_backup = NULL;
bool backup_succeeded = false;
bool delayed_ok;
bool copied_as_regular = false;
- bool chown_succeeded = false;
bool preserve_metadata;
if (x->move_mode && rename_succeeded)
@@ -1510,22 +1473,42 @@ copy_internal (char const *src_name, cha
if (new_dst || !S_ISDIR (dst_sb.st_mode))
{
- /* Create the new directory writable and searchable, so
- we can create new entries in it. */
-
- if (mkdir (dst_name, (src_mode & x->umask_kill) | S_IRWXU) != 0)
+ if (mkdir (dst_name, src_mode) != 0)
{
error (0, errno, _("cannot create directory %s"),
quote (dst_name));
goto un_backup;
}
+ /* We need search and write permissions to the new directory
+ for writing the directory's contents. Check if these
+ permissions are there. */
+
+ if (lstat (dst_name, &dst_sb) != 0)
+ {
+ error (0, errno, _("cannot stat %s"), quote (dst_name));
+ goto un_backup;
+ }
+ else if ((dst_sb.st_mode & S_IRWXU) != S_IRWXU)
+ {
+ /* Make the new directory searchable and writable. */
+
+ dst_mode = dst_sb.st_mode;
+ restore_dst_mode = true;
+
+ if (chmod (dst_name, dst_mode | S_IRWXU))
+ {
+ error (0, errno, _("setting permissions for %s"),
+ quote (dst_name));
+ goto un_backup;
+ }
+ }
+
/* Insert the created directory's inode and device
numbers into the search structure, so that we can
avoid copying it again. */
- if (! remember_created (dst_name))
- goto un_backup;
+ remember_copied (dst_name, dst_sb.st_ino, dst_sb.st_dev);
if (x->verbose)
printf ("%s -> %s\n", quote_n (0, src_name), quote_n (1, dst_name));
@@ -1602,16 +1585,14 @@ copy_internal (char const *src_name, cha
/* POSIX says the permission bits of the source file must be
used as the 3rd argument in the open call, but that's not consistent
with historical practice. */
- if (! copy_reg (src_name, dst_name, x,
- get_dest_mode (x, src_mode), &new_dst, &chown_succeeded,
- &src_sb))
+ if (! copy_reg (src_name, dst_name, x, src_mode, &new_dst, &src_sb))
goto un_backup;
}
else
#ifdef S_ISFIFO
if (S_ISFIFO (src_type))
{
- if (mkfifo (dst_name, get_dest_mode (x, src_mode)))
+ if (mkfifo (dst_name, src_mode))
{
error (0, errno, _("cannot create fifo %s"), quote (dst_name));
goto un_backup;
@@ -1622,7 +1603,7 @@ copy_internal (char const *src_name, cha
if (S_ISBLK (src_type) || S_ISCHR (src_type)
|| S_ISSOCK (src_type))
{
- if (mknod (dst_name, get_dest_mode (x, src_mode), src_sb.st_rdev))
+ if (mknod (dst_name, src_mode, src_sb.st_rdev))
{
error (0, errno, _("cannot create special file %s"),
quote (dst_name));
@@ -1737,20 +1718,30 @@ copy_internal (char const *src_name, cha
if (x->preserve_ownership
&& (new_dst || !SAME_OWNER_AND_GROUP (src_sb, dst_sb)))
{
- if (! set_owner (x, dst_name, -1, src_sb.st_uid, src_sb.st_gid,
- &chown_succeeded))
+ if (! set_owner (x, dst_name, -1, src_sb.st_uid, src_sb.st_gid))
return false;
}
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)))
+ if (x->preserve_mode || x->move_mode)
+ {
+ if (copy_acl (src_name, -1, dst_name, -1, src_mode) != 0
+ && x->require_preserve)
+ return false;
+ }
+ else if (x->set_mode)
{
- if (chmod (dst_name, get_dest_mode (x, src_mode)) != 0)
+ if (set_acl (dst_name, -1, x->mode) != 0)
+ return false;
+ }
+ else if (restore_dst_mode)
+ {
+ if (chmod (dst_name, dst_mode))
{
- error (0, errno, _("setting permissions for %s"), quote (dst_name));
- if (x->set_mode || x->require_preserve)
+ error (0, errno, _("preserving permissions for %s"),
+ quote (dst_name));
+ if (x->require_preserve)
return false;
}
}
Index: coreutils/doc/coreutils.texi
===================================================================
--- coreutils.orig/doc/coreutils.texi
+++ coreutils/doc/coreutils.texi
@@ -5688,9 +5688,14 @@ Otherwise.
@end table
Following the permission bits is a single character that specifies
-whether an alternate access method applies to the file. When that
-character is a space, there is no alternate access method. When it
-is a printing character (e.g., @samp{+}), then there is such a method.
+whether an alternate access method such as an access control list
+applies to the file. When the character following the permissions is a
+space, there is no alternate access method. When it is a printing
+character, then there is such a method.
+
+For a file with an extended access control list, a @samp{+} character is
+listed. Basic access control lists are equivalent to the permissions
+listed, and are not considered an alternate access method.
@item -n
@itemx --numeric-uid-gid
@@ -6527,7 +6532,7 @@ of one or more of the following strings:
@table @samp
@itemx mode
-Preserve the permission attributes.
+Preserve the permission attributes, including access control lists.
@itemx ownership
Preserve the owner and group. On most modern systems,
only the super-user may change the owner of a file, and regular users
@@ -6543,7 +6548,6 @@ any links between corresponding source f
@itemx all
Preserve all file attributes.
Equivalent to specifying all of the above.
[EMAIL PROTECTED] Mention ACLs here.
@end table
Using @option{--preserve} with no @var{attribute_list} is equivalent
Index: coreutils/lib/acl.c
===================================================================
--- coreutils.orig/lib/acl.c
+++ coreutils/lib/acl.c
@@ -22,6 +22,7 @@
# include <config.h>
#endif
+#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifndef S_ISLNK
@@ -29,21 +30,31 @@
#endif
#include "acl.h"
+#include "error.h"
+#include "quote.h"
#include <errno.h>
#ifndef ENOSYS
# define ENOSYS (-1)
#endif
+#if ENABLE_NLS
+# include <libintl.h>
+# define _(Text) gettext (Text)
+#else
+# define _(Text) Text
+#endif
+
#ifndef MIN_ACL_ENTRIES
# define MIN_ACL_ENTRIES 4
#endif
-/* Return 1 if FILE has a nontrivial access control list, 0 if not,
- and -1 (setting errno) if an error is encountered. */
+/* Return 1 if NAME has a nontrivial access control list, 0 if
+ NAME only has no or a base access control list, and -1 on
+ error. SB must be set to the stat buffer of FILE. */
int
-file_has_acl (char const *file, struct stat const *filestat)
+file_has_acl (char const *name, struct stat const *sb)
{
/* FIXME: This implementation should work on recent-enough versions
of HP-UX, Solaris, and Unixware, but it simply returns 0 with
@@ -52,12 +63,57 @@ file_has_acl (char const *file, struct s
fix-related ideas. */
#if HAVE_ACL && defined GETACLCNT
- if (! S_ISLNK (filestat->st_mode))
+ if (! S_ISLNK (sb->st_mode))
{
- int n = acl (file, GETACLCNT, 0, NULL);
+ int n = acl (name, GETACLCNT, 0, NULL);
return n < 0 ? (errno == ENOSYS ? 0 : -1) : (MIN_ACL_ENTRIES < n);
}
#endif
return 0;
}
+
+/* Copy the access control list of (SOURCE_DESC or SRC_NAME) to
+ (DEST_DESC or DEST_NAME). Use file handle operations if SOURCE_DESC
+ or DEST_DESC are unequal to -1, and name based operations otherwise.
+ If access control lists are not available, fchmod DEST_DESC (or
+ chmod DEST_NAME) to MODE. Also sets the non-permission bits of the
+ destination file (S_ISUID, S_ISGID, S_ISVTX) to those from MODE if
+ they are set. System call return value semantics. */
+
+int
+copy_acl (const char *src_name, int source_desc, const char *dst_name,
+ int dest_desc, mode_t mode)
+{
+ int ret;
+#ifdef HAVE_FCHMOD
+ if (dest_desc != -1)
+ ret = fchmod (dest_desc, mode);
+ else
+#else
+ ret = chmod (dst_name, mode);
+#endif
+ if (ret)
+ error (0, errno, _("preserving permissions for %s"), quote (dst_name));
+ return ret;
+}
+
+/* Set the access control list of (DESC or NAME) to the equivalent of MODE.
+ Use file handle operations if DESC is unequal to -1, and name based
+ operations otherwise. Also sets the non-permission bits of the
+ destination file (S_ISUID, S_ISGID, S_ISVTX) to those from MODE if
+ they are set. System call return value semantics. */
+
+int
+set_acl (char const *name, int desc, mode_t mode)
+{
+ int ret;
+#ifdef HAVE_FCHMOD
+ ret = fchmod (desc, mode);
+#else
+ ret = chmod (name, mode);
+#endif
+ if (ret)
+ error (0, errno, _("setting permissions for %s"), quote (name));
+ return ret;
+}
Index: coreutils/lib/acl.h
===================================================================
--- coreutils.orig/lib/acl.h
+++ coreutils/lib/acl.h
@@ -18,11 +18,13 @@
Written by Paul Eggert. */
-#if HAVE_SYS_ACL_H && HAVE_ACL
+#if HAVE_SYS_ACL_H
# include <sys/acl.h>
#endif
-#if ! defined GETACLCNT && defined ACL_CNT
+#if defined HAVE_ACL && ! defined GETACLCNT && defined ACL_CNT
# define GETACLCNT ACL_CNT
#endif
int file_has_acl (char const *, struct stat const *);
+int copy_acl(char const *, int, char const *, int, mode_t);
+int set_acl(char const *, int, mode_t);
Index: coreutils/src/copy.h
===================================================================
--- coreutils.orig/src/copy.h
+++ coreutils/src/copy.h
@@ -165,9 +165,6 @@ struct cp_options
Create destination directories as usual. */
bool symbolic_link;
- /* The bits to preserve in created files' modes. */
- mode_t umask_kill;
-
/* If true, do not copy a nondirectory that has an existing destination
with the same or newer modification time. */
bool update;
Index: coreutils/src/cp.c
===================================================================
--- coreutils.orig/src/cp.c
+++ coreutils/src/cp.c
@@ -35,6 +35,7 @@
#include "quotearg.h"
#include "stat-time.h"
#include "utimens.h"
+#include "acl.h"
#define ASSIGN_BASENAME_STRDUPA(Dest, File_name) \
do \
@@ -56,7 +57,8 @@
need to be fixed after copying. */
struct dir_attr
{
- bool is_new_dir;
+ mode_t mode;
+ bool restore_mode;
size_t slash_offset;
struct dir_attr *next;
};
@@ -327,9 +329,14 @@ re_protect (char const *const_dst_name,
}
}
- if (x->preserve_mode | p->is_new_dir)
+ if (x->preserve_mode)
{
- if (chmod (dst_name, src_sb.st_mode & x->umask_kill))
+ if (copy_acl (src_name, -1, dst_name, -1, src_sb.st_mode))
+ return false;
+ }
+ else if (p->restore_mode)
+ {
+ if (chmod (dst_name, p->mode))
{
error (0, errno, _("failed to preserve permissions for %s"),
quote (dst_name));
@@ -347,8 +354,7 @@ re_protect (char const *const_dst_name,
SRC_OFFSET is the index in CONST_DIR (which is a destination
directory) of the beginning of the source directory name.
- Create any leading directories that don't already exist,
- giving them permissions MODE.
+ Create any leading directories that don't already exist.
If VERBOSE_FMT_STRING is nonzero, use it as a printf format
string for printing a message after successfully making a directory.
The format should take two string arguments: the names of the
@@ -364,9 +370,9 @@ re_protect (char const *const_dst_name,
static bool
make_dir_parents_private (char const *const_dir, size_t src_offset,
- mode_t mode, char const *verbose_fmt_string,
+ char const *verbose_fmt_string,
struct dir_attr **attr_list, bool *new_dst,
- int (*xstat) ())
+ const struct cp_options *x)
{
struct stat stats;
char *dir; /* A copy of CONST_DIR we can change. */
@@ -385,7 +391,7 @@ make_dir_parents_private (char const *co
*attr_list = NULL;
- if ((*xstat) (dst_dir, &stats))
+ if (XSTAT (x, dst_dir, &stats))
{
/* A parent of CONST_DIR does not exist.
Make all missing intermediate directories. */
@@ -400,20 +406,30 @@ make_dir_parents_private (char const *co
fixing later. */
struct dir_attr *new = xmalloc (sizeof *new);
new->slash_offset = slash - dir;
+ new->restore_mode = false;
new->next = *attr_list;
*attr_list = new;
*slash = '\0';
- if ((*xstat) (dir, &stats))
+ if (XSTAT (x, dir, &stats))
{
+ mode_t src_mode;
+
/* This component does not exist. We must set
- *new_dst and new->is_new_dir inside this loop because,
+ *new_dst and new->mode inside this loop because,
for example, in the command `cp --parents ../a/../b/c e_dir',
make_dir_parents_private creates only e_dir/../a if
./b already exists. */
*new_dst = true;
- new->is_new_dir = true;
- if (mkdir (dir, mode))
+ if (XSTAT (x, src, &stats))
+ {
+ error (0, errno, _("failed to get attributes of %s"),
+ quote (src));
+ return false;
+ }
+ src_mode = stats.st_mode;
+
+ if (mkdir (dir, src_mode))
{
error (0, errno, _("cannot make directory %s"),
quote (dir));
@@ -424,6 +440,41 @@ make_dir_parents_private (char const *co
if (verbose_fmt_string != NULL)
printf (verbose_fmt_string, src, dir);
}
+
+ /* We need search and write permissions to the new directory
+ for writing the directory's contents. Check if these
+ permissions are there. */
+
+ if (lstat (dir, &stats))
+ {
+ error (0, errno, _("failed to get attributes of %s"),
+ quote (dir));
+ return false;
+ }
+ else
+ {
+ if (x->preserve_mode)
+ {
+ new->mode = src_mode;
+ new->restore_mode = (src_mode != stats.st_mode);
+ }
+
+ if ((stats.st_mode & S_IRWXU) != S_IRWXU)
+ {
+ /* Make the new directory searchable and writable. The
+ original permissions will be restored later. */
+
+ new->mode = stats.st_mode;
+ new->restore_mode = true;
+
+ if (chmod (dir, stats.st_mode | S_IRWXU))
+ {
+ error (0, errno, _("setting permissions for %s"),
+ quote (dir));
+ return false;
+ }
+ }
+ }
}
else if (!S_ISDIR (stats.st_mode))
{
@@ -432,10 +483,7 @@ make_dir_parents_private (char const *co
return false;
}
else
- {
- new->is_new_dir = false;
- *new_dst = false;
- }
+ *new_dst = false;
*slash++ = '/';
/* Avoid unnecessary calls to `stat' when given
@@ -536,10 +584,6 @@ do_copy (int n_files, char **file, const
Copy the files `file1' through `filen'
to the existing directory `edir'. */
int i;
- int (*xstat)() = (x->dereference == DEREF_COMMAND_LINE_ARGUMENTS
- || x->dereference == DEREF_ALWAYS
- ? stat
- : lstat);
/* Initialize these hash tables only if we'll need them.
The problems they're used to detect can arise only if
@@ -585,9 +629,9 @@ do_copy (int n_files, char **file, const
leading directories. */
parent_exists =
(make_dir_parents_private
- (dst_name, arg_in_concat - dst_name, S_IRWXU,
+ (dst_name, arg_in_concat - dst_name,
(x->verbose ? "%s -> %s\n" : NULL),
- &attr_list, &new_dst, xstat));
+ &attr_list, &new_dst, x));
}
else
{
@@ -697,12 +741,6 @@ cp_option_init (struct cp_options *x)
/* Not used. */
x->stdin_tty = false;
- /* Find out the current file creation mask, to knock the right bits
- when using chmod. The creation mask is set to be liberal, so
- that created directories can be written, even if it would not
- have been allowed with the mask this process was started with. */
- x->umask_kill = ~ umask (0);
-
x->update = false;
x->verbose = false;
x->dest_info = NULL;
@@ -987,9 +1025,6 @@ main (int argc, char **argv)
version_control_string)
: no_backups);
- if (x.preserve_mode)
- x.umask_kill = ~ (mode_t) 0;
-
if (x.dereference == DEREF_UNDEFINED)
{
if (x.recursive)
Index: coreutils/src/install.c
===================================================================
--- coreutils.orig/src/install.c
+++ coreutils/src/install.c
@@ -153,7 +153,6 @@ cp_option_init (struct cp_options *x)
x->mode = S_IRUSR | S_IWUSR;
x->stdin_tty = false;
- x->umask_kill = 0;
x->update = false;
x->verbose = false;
x->dest_info = NULL;
Index: coreutils/src/ls.c
===================================================================
--- coreutils.orig/src/ls.c
+++ coreutils/src/ls.c
@@ -193,13 +193,13 @@ struct fileinfo
enum filetype filetype;
-#if HAVE_ACL
+#if USE_ACL
/* For long listings, true if the file has an access control list. */
bool have_acl;
#endif
};
-#if HAVE_ACL
+#if USE_ACL
# define FILE_HAS_ACL(F) ((F)->have_acl)
#else
# define FILE_HAS_ACL(F) 0
@@ -334,7 +334,7 @@ static int current_time_ns = -1;
/* Whether any of the files has an ACL. This affects the width of the
mode column. */
-#if HAVE_ACL
+#if USE_ACL
static bool any_has_acl;
#else
enum { any_has_acl = false };
@@ -2477,7 +2477,7 @@ clear_files (void)
}
files_index = 0;
-#if HAVE_ACL
+#if USE_ACL
any_has_acl = false;
#endif
inode_number_width = 0;
@@ -2588,7 +2588,7 @@ gobble_file (char const *name, enum file
return 0;
}
-#if HAVE_ACL
+#if USE_ACL
if (format == long_format)
{
int n = file_has_acl (absolute_name, &f->stat);
Index: coreutils/src/mv.c
===================================================================
--- coreutils.orig/src/mv.c
+++ coreutils/src/mv.c
@@ -134,12 +134,6 @@ cp_option_init (struct cp_options *x)
x->mode = 0;
x->stdin_tty = isatty (STDIN_FILENO);
- /* Find out the current file creation mask, to knock the right bits
- when using chmod. The creation mask is set to be liberal, so
- that created directories can be written, even if it would not
- have been allowed with the mask this process was started with. */
- x->umask_kill = ~ umask (0);
-
x->update = false;
x->verbose = false;
x->dest_info = NULL;
Index: coreutils/po/POTFILES.in
===================================================================
--- coreutils.orig/po/POTFILES.in
+++ coreutils/po/POTFILES.in
@@ -2,6 +2,7 @@
# Copyright (C) 1996-2005 Free Software Foundation, Inc.
# These are nominally temporary...
+lib/acl.c
lib/argmatch.c
lib/closeout.c
lib/error.c
Index: coreutils/lib/acl.c
===================================================================
--- coreutils.orig/lib/acl.c
+++ coreutils/lib/acl.c
@@ -23,12 +23,17 @@
#endif
#include <stdlib.h>
+#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifndef S_ISLNK
# define S_ISLNK(Mode) 0
#endif
+#ifdef HAVE_ACL_LIBACL_H
+# include <acl/libacl.h>
+#endif
+
#include "acl.h"
#include "error.h"
#include "quote.h"
@@ -37,6 +42,9 @@
#ifndef ENOSYS
# define ENOSYS (-1)
#endif
+#ifndef ENOTSUP
+# define ENOTSUP (-1)
+#endif
#if ENABLE_NLS
# include <libintl.h>
@@ -45,8 +53,38 @@
# define _(Text) Text
#endif
-#ifndef MIN_ACL_ENTRIES
-# define MIN_ACL_ENTRIES 4
+/* If DESC is a valid file handle (not -1), fchown it to MODE.
+ Otherwise, chown NAME to MODE. System call return value
+ semantics. */
+
+static int
+chmod_or_fchmod (const char *name, int desc, mode_t mode)
+{
+#if HAVE_FCHMOD
+ if (desc != -1)
+ return fchmod (desc, mode);
+ else
+#endif
+ return chmod (name, mode);
+}
+
+/* Return the number of entries of ACL. On error, return -1. */
+
+#if USE_ACL && HAVE_ACL_TO_TEXT && !HAVE_ACL_ENTRIES
+static int
+acl_entries (acl_t acl)
+{
+ char *text = acl_to_text (acl, NULL), *t;
+ int entries;
+ if (text == NULL)
+ return -1;
+ for (entries = 0, t = text; ; t++, entries++) {
+ if ((t = strchr (t, '\n')) == NULL)
+ break;
+ }
+ acl_free (text);
+ return entries;
+}
#endif
/* Return 1 if NAME has a nontrivial access control list, 0 if
@@ -56,20 +94,59 @@
int
file_has_acl (char const *name, struct stat const *sb)
{
- /* FIXME: This implementation should work on recent-enough versions
- of HP-UX, Solaris, and Unixware, but it simply returns 0 with
- POSIX 1003.1e (draft 17 -- abandoned), AIX, GNU/Linux, Irix, and
- Tru64. Please see Samba's source/lib/sysacls.c file for
- fix-related ideas. */
+#if USE_ACL && HAVE_ACL && defined GETACLCNT
+ /* This implementation should work on recent-enough versions of HP-UX,
+ Solaris, and Unixware. */
+
+# ifndef MIN_ACL_ENTRIES
+# define MIN_ACL_ENTRIES 4
+# endif
-#if HAVE_ACL && defined GETACLCNT
if (! S_ISLNK (sb->st_mode))
{
int n = acl (name, GETACLCNT, 0, NULL);
return n < 0 ? (errno == ENOSYS ? 0 : -1) : (MIN_ACL_ENTRIES < n);
}
+#elif USE_ACL
+ if (! S_ISLNK (sb->st_mode))
+ {
+ int ret;
+# if HAVE_ACL_EXTENDED_FILE
+ /* Linux-specific version. */
+
+ ret = acl_extended_file (name);
+# else
+ /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */
+
+ acl_t acl = acl_get_file (name, ACL_TYPE_ACCESS);
+ if (acl)
+ {
+ ret = (3 < acl_entries (acl));
+ acl_free (acl);
+ if (ret == 0 && S_ISDIR (sb->st_mode))
+ {
+ acl = acl_get_file (name, ACL_TYPE_DEFAULT);
+ if (acl)
+ {
+ ret = (0 < acl_entries (acl));
+ acl_free (acl);
+ }
+ else
+ ret = -1;
+ }
+ }
+ else
+ ret = -1;
+# endif
+ if (ret < 0)
+ return (errno == ENOSYS || errno == ENOTSUP) ? 0 : -1;
+ return ret;
+ }
#endif
+ /* FIXME: Add support for AIX, Irix, and Tru64. Please see Samba's
+ source/lib/sysacls.c file for fix-related ideas. */
+
return 0;
}
@@ -86,16 +163,105 @@ copy_acl (const char *src_name, int sour
int dest_desc, mode_t mode)
{
int ret;
-#ifdef HAVE_FCHMOD
+
+#if USE_ACL && HAVE_ACL_GET_FILE && HAVE_ACL_SET_FILE && \
+ HAVE_ACL_FREE && HAVE_ACL_ENTRIES
+ /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */
+
+ acl_t acl;
+#if HAVE_ACL_GET_FD
+ if (source_desc != -1)
+ acl = acl_get_fd (source_desc);
+ else
+#endif
+ acl = acl_get_file (src_name, ACL_TYPE_ACCESS);
+ if (acl == NULL)
+ {
+ if (errno == ENOSYS || errno == ENOTSUP)
+ return set_acl (dst_name, dest_desc, mode);
+ else
+ {
+ error (0, errno, "%s", quote (src_name));
+ return -1;
+ }
+ }
+
+#if HAVE_ACL_SET_FD
if (dest_desc != -1)
- ret = fchmod (dest_desc, mode);
+ ret = acl_set_fd (dest_desc, acl);
else
-#else
- ret = chmod (dst_name, mode);
#endif
- if (ret)
+ ret = acl_set_file (dst_name, ACL_TYPE_ACCESS, acl);
+ if (ret != 0)
+ {
+ int saved_errno = errno;
+
+ if (errno == ENOSYS || errno == ENOTSUP)
+ {
+ int n = acl_entries (acl);
+
+ acl_free (acl);
+ if (n == 3)
+ {
+ if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0)
+ saved_errno = errno;
+ else
+ return 0;
+ }
+ else
+ chmod_or_fchmod (dst_name, dest_desc, mode);
+ }
+ else
+ {
+ acl_free (acl);
+ chmod_or_fchmod (dst_name, dest_desc, mode);
+ }
+ error (0, saved_errno, _("preserving permissions for %s"),
+ quote (dst_name));
+ return -1;
+ }
+ else
+ acl_free (acl);
+
+ if (mode & (S_ISUID | S_ISGID | S_ISVTX))
+ {
+ /* We did not call chmod so far, so the special bits have not yet
+ been set. */
+
+ if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0)
+ {
+ error (0, errno, _("preserving permissions for %s"),
+ quote (dst_name));
+ return -1;
+ }
+ }
+
+ if (S_ISDIR (mode))
+ {
+ acl = acl_get_file (src_name, ACL_TYPE_DEFAULT);
+ if (acl == NULL)
+ {
+ error (0, errno, "%s", quote (src_name));
+ return -1;
+ }
+
+ if (acl_set_file (dst_name, ACL_TYPE_DEFAULT, acl))
+ {
+ error (0, errno, _("preserving permissions for %s"),
+ quote (dst_name));
+ acl_free (acl);
+ return -1;
+ }
+ else
+ acl_free (acl);
+ }
+ return 0;
+#else
+ ret = chmod_or_fchmod (dst_name, dest_desc, mode);
+ if (ret != 0)
error (0, errno, _("preserving permissions for %s"), quote (dst_name));
return ret;
+#endif
}
/* Set the access control list of (DESC or NAME) to the equivalent of MODE.
@@ -107,13 +273,90 @@ copy_acl (const char *src_name, int sour
int
set_acl (char const *name, int desc, mode_t mode)
{
+#if USE_ACL && HAVE_ACL_FROM_TEXT && HAVE_ACL_SET_FILE && HAVE_ACL_FREE && \
+ HAVE_ACL_DELETE_DEF_FILE
+ acl_t acl;
int ret;
-#ifdef HAVE_FCHMOD
- ret = fchmod (desc, mode);
+# if HAVE_ACL_FROM_MODE
+ /* Linux-specific version. */
+
+ acl = acl_from_mode (mode);
+ if (!acl)
+ {
+ error (0, errno, "%s", quote (name));
+ return -1;
+ }
+
+# elif HAVE_ACL_FROM_TEXT
+ /* POSIX 1003.1e draft 17 (abandoned) specific version. */
+
+ char acl_text[] = "u::---,g::---,o::---";
+
+ if (mode & S_IRUSR) acl_text[ 3] = 'r';
+ if (mode & S_IWUSR) acl_text[ 4] = 'w';
+ if (mode & S_IXUSR) acl_text[ 5] = 'x';
+ if (mode & S_IRGRP) acl_text[10] = 'r';
+ if (mode & S_IWGRP) acl_text[11] = 'w';
+ if (mode & S_IXGRP) acl_text[12] = 'x';
+ if (mode & S_IROTH) acl_text[17] = 'r';
+ if (mode & S_IWOTH) acl_text[18] = 'w';
+ if (mode & S_IXOTH) acl_text[19] = 'x';
+
+ acl = acl_from_text (acl_text);
+ if (!acl)
+ {
+ error (0, errno, "%s", quote (name));
+ return -1;
+ }
#else
- ret = chmod (name, mode);
+# error Need either acl_from_mode or acl_from_test
+#endif
+#if HAVE_ACL_SET_FD
+ if (desc != -1)
+ ret = acl_set_fd (desc, acl);
+ else
+#endif
+ ret = acl_set_file (name, ACL_TYPE_ACCESS, acl);
+ if (ret != 0)
+ {
+ int saved_errno = errno;
+ acl_free (acl);
+
+ if (errno == ENOTSUP || errno == ENOSYS)
+ {
+ if (chmod_or_fchmod (name, desc, mode) != 0)
+ saved_errno = errno;
+ else
+ return 0;
+ }
+ error (0, saved_errno, _("setting permissions for %s"), quote (name));
+ return -1;
+ }
+ else
+ acl_free (acl);
+
+ if (S_ISDIR (mode) && acl_delete_def_file (name))
+ {
+ error (0, errno, _("setting permissions for %s"), quote (name));
+ return -1;
+ }
+
+ if (mode & (S_ISUID | S_ISGID | S_ISVTX))
+ {
+ /* We did not call chmod so far, so the special bits have not yet
+ been set. */
+
+ if (chmod_or_fchmod (name, desc, mode))
+ {
+ error (0, errno, _("preserving permissions for %s"), quote (name));
+ return -1;
+ }
+ }
+ return 0;
+#else
+ int ret = chmod_or_fchmod (name, desc, mode);
+ if (ret)
+ error (0, errno, _("setting permissions for %s"), quote (name));
+ return ret;
#endif
- if (ret)
- error (0, errno, _("setting permissions for %s"), quote (name));
- return ret;
}
Index: coreutils/m4/acl.m4
===================================================================
--- coreutils.orig/m4/acl.m4
+++ coreutils/m4/acl.m4
@@ -14,5 +14,22 @@ AC_DEFUN([AC_FUNC_ACL],
dnl Prerequisites of lib/acl.c.
AC_CHECK_HEADERS(sys/acl.h)
+ if test "$ac_cv_header_sys_acl_h" = yes; then
+ use_acl=1
+ else
+ use_acl=0
+ fi
+ AC_DEFINE_UNQUOTED(USE_ACL, $use_acl,
+ [Define if you want access control list support.])
AC_CHECK_FUNCS(acl)
+ ac_save_LIBS="$LIBS"
+ AC_SEARCH_LIBS(acl_get_file, acl,
+ [test "$ac_cv_search_acl_get_file" = "none required" ||
+ LIB_ACL=$ac_cv_search_acl_get_file])
+ AC_SUBST(LIB_ACL)
+ AC_CHECK_HEADERS(acl/libacl.h)
+ AC_CHECK_FUNCS(acl_get_file acl_get_fd acl_set_file acl_set_fd \
+ acl_free acl_from_mode acl_from_text acl_to_text \
+ acl_delete_def_file acl_entries acl_extended_file)
+ LIBS="$ac_save_LIBS"
])
Index: coreutils/src/Makefile.am
===================================================================
--- coreutils.orig/src/Makefile.am
+++ coreutils/src/Makefile.am
@@ -93,6 +93,13 @@ uptime_LDADD = $(LDADD) $(GETLOADAVG_LIB
su_LDADD = $(LDADD) $(LIB_CRYPT)
+dir_LDADD += $(LIB_ACL)
+ls_LDADD += $(LIB_ACL)
+vdir_LDADD += $(LIB_ACL)
+cp_LDADD += $(LIB_ACL)
+mv_LDADD += $(LIB_ACL)
+ginstall_LDADD += $(LIB_ACL)
+
$(PROGRAMS): ../lib/libcoreutils.a
SUFFIXES = .sh
Index: coreutils/ChangeLog
===================================================================
--- coreutils.orig/ChangeLog
+++ coreutils/ChangeLog
@@ -1,3 +1,18 @@
+2005-12-04 Andreas Gruenbacher <[EMAIL PROTECTED]>
+
+ * lib/acl.h: Add copy_acl() and set_acl(). Fix for POSIX/Linux ACLs.
+ * lib/acl.c: Add copy_acl() and set_acl() implementations in versions
+ for Linux and other POSIX 1003.1e draft 17. Fix file_has_acl for
+ those platforms.
+ * src/copy.[hc]: Remove umask_kill; this makes no sense with POSIX
+ ACLs. Use copy_acl() instead of chmod(). Fix the logic for
+ POSIX ACLs.
+ * src/ls.c: Switch back from HAVE_ACL to USE_ACL: The acl() syscall
+ is no requirement for ACL support.
+ * src/cp.c: Remove umask_kill. Fix logic in make_path_private() for
+ POSIX ACLs.
+ * src/cp.c, src/mv.c, src/install.c: Remove umask_kill.
+
2005-12-04 Jim Meyering <[EMAIL PROTECTED]>
* Version 6.0-cvs.
_______________________________________________
Bug-coreutils mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/bug-coreutils