[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH]: ACL support
From: |
Arkadiusz Miskiewicz |
Subject: |
[PATCH]: ACL support |
Date: |
Mon, 7 Apr 2003 21:26:33 +0200 |
User-agent: |
Mutt/1.4.1i |
Hi,
Here is patch that adds ACL support to coreutils 5.0. Patch is based on
http://acl.bestbits.at/current/diff/fileutils-4.1.8acl-0.8.25.diff.gz.
Patch was tested a bit under Linux 2.4.20 with xfs patches.
diff -urN coreutils-4.5.10.org/configure.ac coreutils-4.5.10/configure.ac
--- coreutils-4.5.10.org/configure.ac Mon Mar 24 16:29:50 2003
+++ coreutils-4.5.10/configure.ac Mon Mar 24 16:31:35 2003
@@ -257,6 +257,8 @@
AM_GNU_GETTEXT([external], [need-ngettext])
AM_GNU_GETTEXT_VERSION(0.11.5)
+ag_POSIX_ACL
+
# just in case we want PAM
AC_SUBST(LIB_PAM)
# with PAM su doesn't need libcrypt
diff -urN coreutils-4.5.10.org/lib/acl.c coreutils-4.5.10/lib/acl.c
--- coreutils-4.5.10.org/lib/acl.c Mon Mar 24 16:29:46 2003
+++ coreutils-4.5.10/lib/acl.c Mon Mar 24 16:30:58 2003
@@ -22,6 +22,13 @@
# include <config.h>
#endif
+#if ENABLE_NLS
+# include <libintl.h>
+# define _(Text) gettext (Text)
+#else
+# define _(Text) Text
+#endif
+
#include <sys/stat.h>
#ifndef S_ISLNK
# define S_ISLNK(Mode) 0
@@ -33,6 +40,9 @@
#ifndef ENOSYS
# define ENOSYS (-1)
#endif
+#ifndef ENOTSUP
+# define ENOTSUP (-1)
+#endif
#ifndef MIN_ACL_ENTRIES
# define MIN_ACL_ENTRIES 4
@@ -44,19 +54,201 @@
int
file_has_acl (char const *path, struct stat const *pathstat)
{
- /* 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 HAVE_ACL && defined GETACLCNT
+ /* This implementation should work on recent-enough versions of HP-UX,
+ Solaris, and Unixware. */
+
if (! S_ISLNK (pathstat->st_mode))
{
int n = acl (path, GETACLCNT, 0, NULL);
return n < 0 ? (errno == ENOSYS ? 0 : -1) : (MIN_ACL_ENTRIES < n);
}
+#elif HAVE_ACL_EXTENDED_FILE
+
+ /* Linux specific. */
+
+ if (! S_ISLNK (pathstat->st_mode))
+ {
+ int ret = acl_extended_file (path);
+ if (ret < 0)
+ return (errno == ENOSYS || errno == ENOTSUP) ? 0 : -1;
+ return ret;
+ }
+#else
+ /* FIXME: Add support for AIX, Irix, and Tru64, FreeBSD, etc.
+ Please see Samba's source/lib/sysacls.c file for fix-related ideas. */
+#endif
+
+ return 0;
+}
+
+/* Copy the permissions from SRC_PATH to DST_PATH, including access control
+ lists on systems where this is supported. MODE is the file mode for
+ DST_PATH, including the file type.
+ Also sets special bits in MODE on DST_PATH. */
+
+int
+copy_acl (char const *src_path, char const *dst_path, mode_t mode)
+{
+#if HAVE_ACL_GET_FILE && HAVE_ACL_SET_FILE && HAVE_ACL_FREE && \
+ HAVE_ACL_ENTRIES
+
+ /* Linux specific. Will work on all POSIX 1003.1e draft 17 (abandoned)
+ compliant systems if the acl_entries() function is implemented. */
+
+ acl_t acl = acl_get_file (src_path, ACL_TYPE_ACCESS);
+ if (acl == NULL)
+ {
+ if (errno == ENOSYS || errno == ENOTSUP)
+ return set_acl (dst_path, mode);
+ else
+ {
+ error (0, errno, "%s", quote (src_path));
+ return -1;
+ }
+ }
+
+ if (acl_set_file (dst_path, ACL_TYPE_ACCESS, acl))
+ {
+ int saved_errno = errno;
+
+ if (errno == ENOSYS || errno == ENOTSUP)
+ {
+ int n = acl_entries (acl);
+
+ acl_free (acl);
+ if (n == 3)
+ {
+ if (chmod (dst_path, mode))
+ saved_errno = errno;
+ else
+ return 0;
+ }
+ else
+ chmod (dst_path, mode);
+ }
+ else
+ {
+ acl_free (acl);
+ chmod (dst_path, mode);
+ }
+ error (0, saved_errno, _("preserving permissions for %s"),
+ quote (dst_path));
+ return -1;
+ }
+ 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 (dst_path, mode))
+ {
+ error (0, errno, _("preserving permissions for %s"),
+ quote (dst_path));
+ return -1;
+ }
+ }
+
+ if (S_ISDIR (mode))
+ {
+ acl = acl_get_file (src_path, ACL_TYPE_DEFAULT);
+ if (acl == NULL)
+ {
+ error (0, errno, "%s", quote (src_path));
+ return -1;
+ }
+
+ if (acl_set_file (dst_path, ACL_TYPE_DEFAULT, acl))
+ {
+ error (0, errno, _("preserving permissions for %s"),
+ quote (dst_path));
+ acl_free(acl);
+ return -1;
+ }
+ else
+ acl_free(acl);
+ }
+ return 0;
+#else
+ int ret = chmod (dst_path, mode);
+ if (ret)
+ error (0, errno, _("preserving permissions for %s"), quote (dst_path));
+ return ret;
#endif
+}
+
+/* Set the permissions of PATH, overwriting access control lists, on systems
+ where this is supported. MODE is the file mode for PATH, including the
+ file type. Also sets special bits in MODE on PATH. */
+int
+set_acl (char const *path, mode_t mode)
+{
+#if HAVE_ACL_FROM_TEXT && HAVE_ACL_SET_FILE && HAVE_ACL_FREE && \
+ HAVE_ACL_DELETE_DEF_FILE
+ char acl_text[] = "u::---,g::---,o::---";
+ acl_t acl;
+
+ 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 (path));
+ return -1;
+ }
+
+ if (acl_set_file(path, ACL_TYPE_ACCESS, acl))
+ {
+ int saved_errno = errno;
+ acl_free (acl);
+
+ if (errno == ENOTSUP || errno == ENOSYS)
+ {
+ if (chmod (path, mode))
+ saved_errno = errno;
+ else
+ return 0;
+ }
+ error (0, saved_errno, _("setting permissions for %s"), quote (path));
+ return -1;
+ }
+ 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 (path, mode))
+ {
+ error (0, errno, _("preserving permissions for %s"),
+ quote (path));
+ return -1;
+ }
+ }
+
+ if (S_ISDIR (mode) && acl_delete_def_file (path))
+ {
+ error (0, errno, _("setting permissions for %s"), quote (path));
+ return -1;
+ }
return 0;
+#else
+ int ret = chmod (path, mode);
+ if (ret)
+ error (0, errno, _("setting permissions for %s"), quote (path));
+ return ret;
+#endif
}
+
diff -urN coreutils-4.5.10.org/lib/acl.h coreutils-4.5.10/lib/acl.h
--- coreutils-4.5.10.org/lib/acl.h Mon Mar 24 16:29:46 2003
+++ coreutils-4.5.10/lib/acl.h Mon Mar 24 16:30:58 2003
@@ -18,7 +18,7 @@
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
@@ -26,3 +26,5 @@
#endif
int file_has_acl (char const *, struct stat const *);
+int copy_acl (char const *, char const *, mode_t);
+int set_acl (char const *, mode_t);
diff -urN coreutils-4.5.10.org/m4/Makefile.am coreutils-4.5.10/m4/Makefile.am
--- coreutils-4.5.10.org/m4/Makefile.am Mon Mar 24 16:29:47 2003
+++ coreutils-4.5.10/m4/Makefile.am Mon Mar 24 16:30:58 2003
@@ -62,6 +62,7 @@
onceonly.m4 \
open-max.m4 \
perl.m4 \
+posix_acl.m4 \
prereq.m4 \
progtest.m4 \
putenv.m4 \
diff -urN coreutils-4.5.10.org/m4/posix_acl.m4 coreutils-4.5.10/m4/posix_acl.m4
--- coreutils-4.5.10.org/m4/posix_acl.m4 Thu Jan 1 01:00:00 1970
+++ coreutils-4.5.10/m4/posix_acl.m4 Mon Mar 24 16:30:58 2003
@@ -0,0 +1,19 @@
+#serial 1
+
+dnl Written by Andreas Gruenbacher <address@hidden>.
+
+dnl Posix 1003.1e draft standard 17 (abandoned) and similar
+dnl access control list support
+AC_DEFUN([ag_POSIX_ACL],
+[
+ AC_CHECK_HEADERS(sys/acl.h)
+ AC_CHECK_LIB(acl, main)
+ AC_CHECK_FUNCS(acl_get_file acl_set_file acl_free acl_to_text \
+ acl_from_text acl_delete_def_file)
+ # Linux specific extensions:
+ AC_CHECK_FUNCS(acl_entries acl_extended_file)
+
+ if test $ac_cv_header_sys_acl_h = yes; then
+ AC_DEFINE(USE_ACL, 1, [Define if you want access control list support.])
+ fi
+])
diff -urN coreutils-4.5.10.org/src/copy.c coreutils-4.5.10/src/copy.c
--- coreutils-4.5.10.org/src/copy.c Mon Mar 24 16:29:46 2003
+++ coreutils-4.5.10/src/copy.c Mon Mar 24 16:30:58 2003
@@ -99,26 +99,6 @@
/* 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
@@ -792,13 +772,13 @@
struct stat src_sb;
struct stat dst_sb;
mode_t src_mode;
- mode_t src_type;
+ mode_t dst_mode;
char *earlier_file = NULL;
char *dst_backup = NULL;
int backup_succeeded = 0;
int delayed_fail;
int copied_as_regular = 0;
- int ran_chown = 0;
+ int dst_mode_valid = 0;
int preserve_metadata;
if (x->move_mode && rename_succeeded)
@@ -811,11 +791,9 @@
return 1;
}
- src_type = src_sb.st_mode;
-
src_mode = src_sb.st_mode;
- if (S_ISDIR (src_type) && !x->recursive)
+ if (S_ISDIR (src_mode) && !x->recursive)
{
error (0, 0, _("omitting directory %s"), quote (src_path));
return 1;
@@ -870,7 +848,7 @@
if (!S_ISDIR (dst_sb.st_mode))
{
- if (S_ISDIR (src_type))
+ if (S_ISDIR (src_mode))
{
error (0, 0,
_("cannot overwrite non-directory %s with directory %s"),
@@ -896,7 +874,7 @@
}
}
- if (!S_ISDIR (src_type))
+ if (!S_ISDIR (src_mode))
{
if (S_ISDIR (dst_sb.st_mode))
{
@@ -924,7 +902,7 @@
This may be due to an interactive `negative' reply to the
prompt about the existing file. It may also be due to the
use of the --reply=no option. */
- if (!S_ISDIR (src_type))
+ if (!S_ISDIR (src_mode))
{
/* cp and mv treat -i and -f differently. */
if (x->move_mode)
@@ -1042,7 +1020,7 @@
/* If the source is a directory, we don't always create the destination
directory. So --verbose should not announce anything until we're
sure we'll create a directory. */
- if (x->verbose && !S_ISDIR (src_type))
+ if (x->verbose && !S_ISDIR (src_mode))
{
printf ("%s -> %s", quote_n (0, src_path), quote_n (1, dst_path));
if (backup_succeeded)
@@ -1077,7 +1055,7 @@
|| (command_line_arg
&& x->dereference == DEREF_COMMAND_LINE_ARGUMENTS)
|| x->dereference == DEREF_ALWAYS))
- || (x->recursive && S_ISDIR (src_type)))
+ || (x->recursive && S_ISDIR (src_mode)))
{
earlier_file = remember_copied (dst_path, src_sb.st_ino, src_sb.st_dev);
}
@@ -1090,7 +1068,7 @@
/* Avoid damaging the destination filesystem by refusing to preserve
hard-linked directories (which are found at least in Netapp snapshot
directories). */
- if (S_ISDIR (src_type))
+ if (S_ISDIR (src_mode))
{
/* If src_path and earlier_file refer to the same directory entry,
then warn about copying a directory into itself. */
@@ -1142,7 +1120,7 @@
{
if (rename (src_path, dst_path) == 0)
{
- if (x->verbose && S_ISDIR (src_type))
+ if (x->verbose && S_ISDIR (src_mode))
printf ("%s -> %s\n", quote_n (0, src_path), quote_n (1, dst_path));
if (rename_succeeded)
*rename_succeeded = 1;
@@ -1255,7 +1233,7 @@
In such cases, set this variable to zero. */
preserve_metadata = 1;
- if (S_ISDIR (src_type))
+ if (S_ISDIR (src_mode))
{
struct dir_list *dir;
@@ -1280,16 +1258,38 @@
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_path, (src_mode & x->umask_kill) | S_IRWXU))
+ if (mkdir (dst_path, src_mode))
{
error (0, errno, _("cannot create directory %s"),
quote (dst_path));
goto un_backup;
}
+ /* We need search and write permissions to the new directory
+ for adding the directory's contents. Check if these permissions
+ are already there. */
+
+ if (lstat (dst_path, &dst_sb))
+ {
+ error (0, errno, _("cannot stat %s"), quote (dst_path));
+ delayed_fail = 1;
+ }
+ else if ((dst_sb.st_mode & S_IRWXU) != S_IRWXU)
+ {
+ /* Make the new directory writable and searchable. The original
+ permissions will be restored later. */
+
+ dst_mode_valid = 1;
+ dst_mode = dst_sb.st_mode;
+
+ if (chmod (dst_path, dst_mode | S_IRWXU))
+ {
+ error (0, errno, _("setting permissions for %s"),
+ quote (dst_path));
+ goto un_backup;
+ }
+ }
+
/* Insert the created directory's inode and device
numbers into the search structure, so that we can
avoid copying it again. */
@@ -1365,10 +1365,10 @@
goto un_backup;
}
}
- else if (S_ISREG (src_type)
- || (x->copy_as_regular && !S_ISDIR (src_type)
+ else if (S_ISREG (src_mode)
+ || (x->copy_as_regular && !S_ISDIR (src_mode)
#ifdef S_ISLNK
- && !S_ISLNK (src_type)
+ && !S_ISLNK (src_mode)
#endif
))
{
@@ -1376,15 +1376,14 @@
/* 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_path, dst_path, x,
- get_dest_mode (x, src_mode), &new_dst, &src_sb))
+ if (copy_reg (src_path, dst_path, x, src_mode, &new_dst, &src_sb))
goto un_backup;
}
else
#ifdef S_ISFIFO
- if (S_ISFIFO (src_type))
+ if (S_ISFIFO (src_mode))
{
- if (mkfifo (dst_path, get_dest_mode (x, src_mode)))
+ if (mkfifo (dst_path, src_mode))
{
error (0, errno, _("cannot create fifo %s"), quote (dst_path));
goto un_backup;
@@ -1392,13 +1391,13 @@
}
else
#endif
- if (S_ISBLK (src_type) || S_ISCHR (src_type)
+ if (S_ISBLK (src_mode) || S_ISCHR (src_mode)
#ifdef S_ISSOCK
- || S_ISSOCK (src_type)
+ || S_ISSOCK (src_mode)
#endif
)
{
- if (mknod (dst_path, get_dest_mode (x, src_mode), src_sb.st_rdev))
+ if (mknod (dst_path, src_mode, src_sb.st_rdev))
{
error (0, errno, _("cannot create special file %s"),
quote (dst_path));
@@ -1407,7 +1406,7 @@
}
else
#ifdef S_ISLNK
- if (S_ISLNK (src_type))
+ if (S_ISLNK (src_mode))
{
char *src_link_val = xreadlink (src_path);
if (src_link_val == NULL)
@@ -1513,7 +1512,25 @@
if (x->preserve_ownership
&& (new_dst || !SAME_OWNER_AND_GROUP (src_sb, dst_sb)))
{
- ran_chown = 1;
+ /* The chown() system call may clear the SUID and SGID bits, so we
+ need to set them again later. (But we don't care if we will
+ overwrite the permissions of the destination file anyway.) */
+
+ if ((src_mode & (S_ISUID | S_ISGID))
+ && !x->preserve_mode && !x->move_mode && !x->set_mode)
+ {
+ if (lstat (dst_path, &dst_sb))
+ {
+ error (0, errno, _("cannot stat %s"), quote (dst_path));
+ delayed_fail = 1;
+ }
+ else
+ {
+ dst_mode_valid = 1;
+ dst_mode = dst_sb.st_mode;
+ }
+ }
+
if (DO_CHOWN (chown, dst_path, src_sb.st_uid, src_sb.st_gid))
{
error (0, errno, _("failed to preserve ownership for %s"),
@@ -1534,20 +1551,23 @@
}
#endif
- /* Permissions of newly-created regular files were set upon `open' in
- copy_reg. But don't return early if there were any special bits and
- we had to run chown, because the chown must have reset those bits. */
- if ((new_dst && copied_as_regular)
- && !(ran_chown && (src_mode & ~S_IRWXUGO)))
- return delayed_fail;
-
- 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 (chmod (dst_path, get_dest_mode (x, src_mode)))
- {
- error (0, errno, _("setting permissions for %s"), quote (dst_path));
- if (x->set_mode || x->require_preserve)
+ if (copy_acl (src_path, dst_path, src_mode) && x->require_preserve)
+ return 1;
+ }
+ else if (x->set_mode)
+ {
+ if (set_acl (dst_path, x->mode) && x->require_preserve)
+ return 1;
+ }
+ else if (dst_mode_valid)
+ {
+ if (chmod (dst_path, dst_mode))
+ {
+ error (0, errno, _("preserving permissions for %s"),
+ quote (dst_path));
+ if (x->require_preserve)
return 1;
}
}
diff -urN coreutils-4.5.10.org/src/copy.h coreutils-4.5.10/src/copy.h
--- coreutils-4.5.10.org/src/copy.h Mon Mar 24 16:29:46 2003
+++ coreutils-4.5.10/src/copy.h Mon Mar 24 16:30:58 2003
@@ -139,9 +139,6 @@
Create destination directories as usual. */
int symbolic_link;
- /* The bits to preserve in created files' modes. */
- mode_t umask_kill;
-
/* If nonzero, do not copy a nondirectory that has an existing destination
with the same or newer modification time. */
int update;
diff -urN coreutils-4.5.10.org/src/cp.c coreutils-4.5.10/src/cp.c
--- coreutils-4.5.10.org/src/cp.c Mon Mar 24 16:29:46 2003
+++ coreutils-4.5.10/src/cp.c Mon Mar 24 16:34:26 2003
@@ -61,7 +61,8 @@
need to be fixed after copying. */
struct dir_attr
{
- int is_new_dir;
+ int mode_valid;
+ mode_t mode;
int slash_offset;
struct dir_attr *next;
};
@@ -342,9 +343,14 @@
}
}
- if (x->preserve_mode || p->is_new_dir)
+ if (x->preserve_mode)
{
- if (chmod (dst_path, src_sb.st_mode & x->umask_kill))
+ if (copy_acl (src_path, dst_path, src_sb.st_mode))
+ return 1;
+ }
+ else if (p->mode_valid)
+ {
+ if (chmod (dst_path, p->mode))
{
error (0, errno, _("failed to preserve permissions for %s"),
quote (dst_path));
@@ -362,8 +368,7 @@
SRC_OFFSET is the index in CONST_DIRPATH (which is a destination
path) 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
@@ -378,15 +383,16 @@
/* FIXME: find a way to synch this function with the one in lib/makepath.c. */
static int
-make_path_private (const char *const_dirpath, int src_offset, int mode,
+make_path_private (const char *const_dirpath, int src_offset,
const char *verbose_fmt_string, struct dir_attr **attr_list,
- int *new_dst, int (*xstat)())
+ int *new_dst, const struct cp_options *x)
{
struct stat stats;
char *dirpath; /* A copy of CONST_DIRPATH we can change. */
char *src; /* Source name in `dirpath'. */
char *dst_dirname; /* Leading path of `dirpath'. */
size_t dirlen; /* Length of leading path of `dirpath'. */
+ mode_t mode;
dirpath = (char *) alloca (strlen (const_dirpath) + 1);
strcpy (dirpath, const_dirpath);
@@ -400,7 +406,7 @@
*attr_list = NULL;
- if ((*xstat) (dst_dirname, &stats))
+ if ((*x->xstat) (dst_dirname, &stats))
{
/* Parent of CONST_DIRNAME does not exist.
Make all missing intermediate directories. */
@@ -420,15 +426,23 @@
*attr_list = new;
*slash = '\0';
- if ((*xstat) (dirpath, &stats))
+ if ((*x->xstat) (dirpath, &stats))
{
/* This element of the path does not exist. We must set
- *new_dst and new->is_new_dir inside this loop because,
+ *new_dst inside this loop because,
for example, in the command `cp --parents ../a/../b/c e_dir',
make_path_private creates only e_dir/../a if ./b already
exists. */
*new_dst = 1;
- new->is_new_dir = 1;
+
+ if ((*x->xstat) (src, &stats))
+ {
+ error (0, errno, _("failed to get attributes of %s"),
+ quote (src));
+ return 1;
+ }
+ mode = stats.st_mode;
+
if (mkdir (dirpath, mode))
{
error (0, errno, _("cannot make directory %s"),
@@ -440,6 +454,46 @@
if (verbose_fmt_string != NULL)
printf (verbose_fmt_string, src, dirpath);
}
+
+ /* We need search and write permissions to the new directory
+ for adding the directory's contents. Check if these
+ permissions are already there. */
+
+ if (lstat (dirpath, &stats))
+ {
+ error (0, errno, _("failed to get attributes of %s"),
+ quote (dirpath));
+ return 1;
+ }
+ else
+ {
+ if (x->preserve_mode && mode != stats.st_mode)
+ {
+ new->mode = mode;
+ new->mode_valid = 1;
+ }
+ else
+ new->mode_valid = 0;
+
+ if ((stats.st_mode & S_IRWXU) != S_IRWXU)
+ {
+ /* Make the new directory writable and searchable. The
+ original permissions will be restored later. */
+
+ if (!new->mode_valid)
+ {
+ new->mode = stats.st_mode;
+ new->mode_valid = 1;
+ }
+
+ if (chmod (dirpath, stats.st_mode | S_IRWXU))
+ {
+ error (0, errno, _("setting permissions for %s"),
+ quote (dirpath));
+ return 1;
+ }
+ }
+ }
}
else if (!S_ISDIR (stats.st_mode))
{
@@ -449,7 +503,7 @@
}
else
{
- new->is_new_dir = 0;
+ new->mode_valid = 0;
*new_dst = 0;
}
*slash++ = '/';
@@ -600,11 +654,9 @@
leading directories. */
parent_exists = !make_path_private (dst_path,
arg_in_concat - dst_path,
- S_IRWXU,
(x->verbose
? "%s -> %s\n" : NULL),
- &attr_list, &new_dst,
- x->xstat);
+ &attr_list, &new_dst, x);
}
else
{
@@ -739,12 +791,6 @@
/* Not used. */
x->stdin_tty = 0;
- /* 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 = 0;
x->verbose = 0;
x->dest_info = NULL;
@@ -1017,9 +1063,6 @@
version_control_string)
: none);
- if (x.preserve_mode == 1)
- x.umask_kill = ~ (mode_t) 0;
-
if (x.dereference == DEREF_UNDEFINED)
{
if (x.recursive)
diff -urN coreutils-4.5.10.org/src/install.c coreutils-4.5.10/src/install.c
--- coreutils-4.5.10.org/src/install.c Mon Mar 24 16:29:46 2003
+++ coreutils-4.5.10/src/install.c Mon Mar 24 16:30:58 2003
@@ -245,7 +245,6 @@
x->mode = S_IRUSR | S_IWUSR;
x->stdin_tty = 0;
- x->umask_kill = 0;
x->update = 0;
x->verbose = 0;
x->xstat = stat;
diff -urN coreutils-4.5.10.org/src/ls.c coreutils-4.5.10/src/ls.c
--- coreutils-4.5.10.org/src/ls.c Mon Mar 24 16:29:46 2003
+++ coreutils-4.5.10/src/ls.c Mon Mar 24 16:30:58 2003
@@ -223,13 +223,13 @@
enum filetype filetype;
-#if HAVE_ACL
+#if HAVE_ACL || USE_ACL
/* For long listings, true if the file has an access control list. */
bool have_acl;
#endif
};
-#if HAVE_ACL
+#if HAVE_ACL || USE_ACL
# define FILE_HAS_ACL(F) ((F)->have_acl)
#else
# define FILE_HAS_ACL(F) 0
@@ -2400,7 +2400,7 @@
return 0;
}
-#if HAVE_ACL
+#if HAVE_ACL || USE_ACL
if (format == long_format)
{
int n = file_has_acl (path, &files[files_index].stat);
diff -urN coreutils-4.5.10.org/src/mv.c coreutils-4.5.10/src/mv.c
--- coreutils-4.5.10.org/src/mv.c Mon Mar 24 16:29:46 2003
+++ coreutils-4.5.10/src/mv.c Mon Mar 24 16:30:58 2003
@@ -137,12 +137,6 @@
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 = 0;
x->verbose = 0;
x->xstat = lstat;
diff -urN coreutils-4.5.10.org/tests/misc/README
coreutils-4.5.10/tests/misc/README
--- coreutils-4.5.10.org/tests/misc/README Thu Jan 1 01:00:00 1970
+++ coreutils-4.5.10/tests/misc/README Mon Mar 24 16:30:58 2003
@@ -0,0 +1,6 @@
+Use the run script to run any of the *.test scripts, e.g.,
+
+ run cp.test
+
+The cp.test script can be run as any user; the cp-root
+script requires root privileges.
diff -urN coreutils-4.5.10.org/tests/misc/acl coreutils-4.5.10/tests/misc/acl
--- coreutils-4.5.10.org/tests/misc/acl Thu Jan 1 01:00:00 1970
+++ coreutils-4.5.10/tests/misc/acl Mon Mar 24 16:30:58 2003
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+getfacl "$@" | sed -e 's/[ ]*#.*$//' -e '/^$/d'
diff -urN coreutils-4.5.10.org/tests/misc/cp-root.test
coreutils-4.5.10/tests/misc/cp-root.test
--- coreutils-4.5.10.org/tests/misc/cp-root.test Thu Jan 1 01:00:00 1970
+++ coreutils-4.5.10/tests/misc/cp-root.test Mon Mar 24 16:30:58 2003
@@ -0,0 +1,26 @@
+! Tests the access control list extensions to cp.
+! This script must be run as root.
+!
+$ rm -rf test
+$ mkdir test
+$ cd test
+$ umask 022
+$ touch f
+$ chmod u+xs,g+xs f
+$ mode f
+ -rwsr-sr-- f
+$ cp -p f g
+$ mode g
+ -rwsr-sr-- g
+$ cp f h
+$ mode h
+ -rwsr-sr-- h
+$ chown bin h
+$ cp h i
+$ mode i
+ -rwsr-sr-- i
+!
+! cleanup
+!
+$cd ..
+$ rm -rf test
diff -urN coreutils-4.5.10.org/tests/misc/cp.test
coreutils-4.5.10/tests/misc/cp.test
--- coreutils-4.5.10.org/tests/misc/cp.test Thu Jan 1 01:00:00 1970
+++ coreutils-4.5.10/tests/misc/cp.test Mon Mar 24 16:30:58 2003
@@ -0,0 +1,86 @@
+! Tests the access control list extensions to cp (and also of ls).
+! Requires a system with POSIX access control lists and the
+! getfacl and setfacl utilities.
+!
+$ rm -rf test
+$ mkdir test
+$ cd test
+$ umask 022
+$ touch f
+$ mode . f
+ drwxr-xr-x .
+ -rw-r--r-- f
+$ setfacl -m u:@OWNER@:rw- f
+$ mode f
+ -rw-rw-r--+ f
+$ acl f
+ user::rw-
+ user:@OWNER@:rw-
+ group::r--
+ mask::rw-
+ other::r--
+!
+! cp and cp -p
+!
+$ cp f g
+$ cp -p f h
+$ mode g h
+ -rw-r--r-- g
+ -rw-rw-r--+ h
+$ acl h
+ user::rw-
+ user:@OWNER@:rw-
+ group::r--
+ mask::rw-
+ other::r--
+$ mkdir d
+$ setfacl -d -m u::rwx,u:@OWNER@:r-x,g::---,m::r-x,o::--- d
+$ acl d
+ user::rwx
+ group::r-x
+ other::r-x
+ default:user::rwx
+ default:user:@OWNER@:r-x
+ default:group::---
+ default:mask::r-x
+ default:other::---
+$ touch d/i
+$ acl d/i
+ user::rw-
+ user:@OWNER@:r-x
+ group::---
+ mask::r--
+ other::---
+$ cp f d/f
+$ acl d/f
+ user::rw-
+ user:@OWNER@:r-x
+ group::---
+ mask::r--
+ other::---
+$ chmod go-rwx g
+$ cp g d/g
+$ acl d/g
+ user::rw-
+ user:@OWNER@:r-x
+ group::---
+ mask::---
+ other::---
+$ cp -p h d/h
+$ acl h
+ user::rw-
+ user:@OWNER@:rw-
+ group::r--
+ mask::rw-
+ other::r--
+$ touch j
+$ cp -p j d/j
+$ mode d/j
+ -rw-r--r-- d/j
+$
+! mv
+!
+! cleanup
+!
+$cd ..
+$ rm -rf test
diff -urN coreutils-4.5.10.org/tests/misc/mode coreutils-4.5.10/tests/misc/mode
--- coreutils-4.5.10.org/tests/misc/mode Thu Jan 1 01:00:00 1970
+++ coreutils-4.5.10/tests/misc/mode Mon Mar 24 16:30:58 2003
@@ -0,0 +1,2 @@
+#!/bin/sh
+ls -dl $* | awk -- '!/^total/ { print $1, $8; }'
diff -urN coreutils-4.5.10.org/tests/misc/run coreutils-4.5.10/tests/misc/run
--- coreutils-4.5.10.org/tests/misc/run Thu Jan 1 01:00:00 1970
+++ coreutils-4.5.10/tests/misc/run Mon Mar 24 16:30:58 2003
@@ -0,0 +1,164 @@
+#!/usr/bin/perl
+
+use strict;
+use FileHandle;
+use POSIX qw(geteuid getegid isatty);
+
+my $pwd = `pwd`;
+chomp $pwd;
+$ENV{'PATH'} = $pwd . ":../../src:" . $ENV{'PATH'};
+
+my $owner = getpwuid(geteuid());
+my $group = getgrgid(getegid());
+
+my ($OK, $FAILED) = ("ok", "failed");
+if (isatty(fileno(STDOUT))) {
+ $OK = "\033[32m" . $OK . "\033[m";
+ $FAILED = "\033[31m\033[1m" . $FAILED . "\033[m";
+}
+
+my ($prog, $in, $out) = ([], [], []);
+my $line = 0;
+my $prog_line;
+my ($tests, $failed);
+
+for (;;) {
+ my $script = <>; $line++;
+ $script =~ s/address@hidden@/$owner/g;
+ $script =~ s/address@hidden@/$group/g;
+ next if (defined($script) && $script =~ /^!/);
+ if (!defined($script) || $script =~ s/^\$ ?//) {
+ if (@$prog) {
+ #print "[$prog_line] \$ ", join(' ', @$prog), " -- ";
+ my $p = [ @$prog ];
+ print "[$prog_line] \$ ", join(' ',
+ map { s/\s/\\$&/g; $_ } @$p), " -- ";
+ my $result = exec_test($prog, $in);
+ my $good = 1;
+ my $nmax = (@$out > @$result) ? @$out : @$result;
+ for (my $n=0; $n < $nmax; $n++) {
+ if (!defined($out->[$n]) || !defined($result->[$n]) ||
+ $out->[$n] ne $result->[$n]) {
+ $good = 0;
+ #chomp $out->[$n];
+ #chomp $result->[$n];
+ #print "$out->[$n] != $result->[$n]";
+ }
+ }
+ $tests++;
+ $failed++ unless $good;
+ print $good ? $OK : $FAILED, "\n";
+ if (!$good) {
+ for (my $n=0; $n < $nmax; $n++) {
+ my $l = defined($out->[$n]) ? $out->[$n] : "~";
+ chomp $l;
+ my $r = defined($result->[$n]) ? $result->[$n] : "~";
+ chomp $r;
+ print sprintf("%-37s | %-39s\n", $l, $r);
+ }
+ }
+ }
+ #$prog = [ split /\s+/, $script ] if $script;
+ $prog = [ map { s/\\(.)/$1/g; $_ } split /(?<!\\)\s+/, $script ] if
$script;
+ $prog_line = $line;
+ $in = [];
+ $out = [];
+ } elsif ($script =~ s/^> ?//) {
+ push @$in, $script;
+ } else {
+ $script =~ s/^[ \t]*//; # ignore leading whitespace
+ push @$out, $script;
+ }
+ last unless defined($script);
+}
+my $status = sprintf("%d commands (%d passed, %d failed)",
+ $tests, $tests-$failed, $failed);
+if (isatty(fileno(STDOUT))) {
+ if ($failed) {
+ $status = "\033[31m\033[1m" . $status . "\033[m";
+ } else {
+ $status = "\033[32m" . $status . "\033[m";
+ }
+}
+print $status, "\n";
+
+sub exec_test($$) {
+ my ($prog, $in) = @_;
+ local (*IN, *IN_DUP, *IN2, *OUT_DUP, *OUT, *OUT2);
+
+ if ($prog->[0] eq "umask") {
+ umask oct $prog->[1];
+ return [];
+ } elsif ($prog->[0] eq "cd") {
+ if (!chdir $prog->[1]) {
+ return [ "chdir: $prog->[1]: $!\n" ];
+ }
+ return [];
+ }
+
+ pipe *IN2, *OUT
+ or die "Can't create pipe for reading: $!";
+ open *IN_DUP, "<&STDIN"
+ or *IN_DUP = undef;
+ open *STDIN, "<&IN2"
+ or die "Can't duplicate pipe for reading: $!";
+ close *IN2;
+
+ open *OUT_DUP, ">&STDOUT"
+ or die "Can't duplicate STDOUT: $!";
+ pipe *IN, *OUT2
+ or die "Can't create pipe for writing: $!";
+ open *STDOUT, ">&OUT2"
+ or die "Can't duplicate pipe for writing: $!";
+ close *OUT2;
+
+ *STDOUT->autoflush();
+ *OUT->autoflush();
+
+ if (fork()) {
+ # Server
+ if (*IN_DUP) {
+ open *STDIN, "<&IN_DUP"
+ or die "Can't duplicate STDIN: $!";
+ close *IN_DUP
+ or die "Can't close STDIN duplicate: $!";
+ }
+ open *STDOUT, ">&OUT_DUP"
+ or die "Can't duplicate STDOUT: $!";
+ close *OUT_DUP
+ or die "Can't close STDOUT duplicate: $!";
+
+ foreach my $line (@$in) {
+ #print "> $line";
+ print OUT $line;
+ }
+ close *OUT
+ or die "Can't close pipe for writing: $!";
+
+ my $result = [];
+ while (<IN>) {
+ #print "< $_";
+ push @$result, $_;
+ }
+ return $result;
+ } else {
+ # Client
+ close IN
+ or die "Can't close read end for input pipe: $!";
+ close OUT
+ or die "Can't close write end for output pipe: $!";
+ close OUT_DUP
+ or die "Can't close STDOUT duplicate: $!";
+ local *ERR_DUP;
+ open ERR_DUP, ">&STDERR"
+ or die "Can't duplicate STDERR: $!";
+ open STDERR, ">&STDOUT"
+ or die "Can't join STDOUT and STDERR: $!";
+
+ #print ERR_DUP "<", join(' ', @$prog), ">\n";
+ exec @$prog;
+ print ERR_DUP $prog->[0], ": $!\n";
+ exit;
+ }
+}
+
--
Arkadiusz MiĆkiewicz CS at FoE, Wroclaw University of Technology
address@hidden AM2-6BONE, 1024/3DB19BBD, arekm(at)ircnet, PLD/Linux
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [PATCH]: ACL support,
Arkadiusz Miskiewicz <=