From: Jakub Bogusz Date: Wed, 28 Apr 2004 10:37:01 +0000 (+0000) Subject: - based on patch from Fedora, replaces old acl-0.8.25 patch X-Git-Tag: auto/ac/coreutils-5_2_1-0_5~6 X-Git-Url: http://git.pld-linux.org/?a=commitdiff_plain;h=96776da5cc72fd50d17ba0e758ac9794e6c0b793;p=packages%2Fcoreutils.git - based on patch from Fedora, replaces old acl-0.8.25 patch Changed files: coreutils-acl.patch -> 1.1 --- diff --git a/coreutils-acl.patch b/coreutils-acl.patch new file mode 100644 index 0000000..b13f3a5 --- /dev/null +++ b/coreutils-acl.patch @@ -0,0 +1,1320 @@ +--- /dev/null 2004-02-23 21:02:56.000000000 +0000 ++++ coreutils-5.2.1/m4/posix_acl.m4 2004-03-13 11:50:03.000000000 +0000 +@@ -0,0 +1,28 @@ ++#serial 1 ++ ++dnl Written by Andreas Gruenbacher . ++ ++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, cu_cv_lacl=yes, cu_cv_lacl=no) ++ if test "$cu_cv_lacl" = yes; then ++ LIBACL=-lacl ++ else ++ LIBACL= ++ fi ++ AC_SUBST(LIBACL) ++ OLDLIBS="$LIBS" ++ LIBS="$LIBS $LIBACL" ++ 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) ++ LIBS="$OLDLIBS" ++ ++ if test $ac_cv_header_sys_acl_h = yes; then ++ AC_DEFINE(USE_ACL, 1, [Define if you want access control list support.]) ++ fi ++]) +--- coreutils-5.2.1/m4/Makefile.am.acl 2004-03-08 09:56:31.000000000 +0000 ++++ coreutils-5.2.1/m4/Makefile.am 2004-03-13 11:50:03.000000000 +0000 +@@ -108,6 +108,7 @@ + EXTRA_DIST += path-concat.m4 + EXTRA_DIST += pathmax.m4 + EXTRA_DIST += perl.m4 ++EXTRA_DIST += posix_acl.m4 + EXTRA_DIST += physmem.m4 + EXTRA_DIST += po.m4 + EXTRA_DIST += posixtm.m4 +--- coreutils-5.2.1/lib/acl.h.acl 2004-02-02 08:13:21.000000000 +0000 ++++ coreutils-5.2.1/lib/acl.h 2004-03-13 11:50:03.000000000 +0000 +@@ -18,11 +18,16 @@ + + Written by Paul Eggert. */ + +-#if HAVE_SYS_ACL_H && HAVE_ACL ++#if HAVE_SYS_ACL_H + # include + #endif ++#if HAVE_SYS_TYPES_H ++# include ++#endif + #if ! defined GETACLCNT && defined ACL_CNT + # define GETACLCNT ACL_CNT + #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); +--- coreutils-5.2.1/lib/acl.c.acl 2004-02-02 08:13:21.000000000 +0000 ++++ coreutils-5.2.1/lib/acl.c 2004-03-13 11:50:03.000000000 +0000 +@@ -22,18 +22,30 @@ + # include + #endif + ++#if ENABLE_NLS ++# include ++# define _(Text) gettext (Text) ++#else ++# define _(Text) Text ++#endif ++ + #include + #include + #ifndef S_ISLNK + # define S_ISLNK(Mode) 0 + #endif + ++#include ++ + #include "acl.h" + + #include + #ifndef ENOSYS + # define ENOSYS (-1) + #endif ++#ifndef ENOTSUP ++# define ENOTSUP (-1) ++#endif + + #ifndef MIN_ACL_ENTRIES + # define MIN_ACL_ENTRIES 4 +@@ -45,19 +57,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 ++} ++ +--- coreutils-5.2.1/src/mv.c.acl 2004-02-07 15:41:02.000000000 +0000 ++++ coreutils-5.2.1/src/mv.c 2004-03-13 11:50:03.000000000 +0000 +@@ -132,12 +132,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->dest_info = NULL; +--- coreutils-5.2.1/src/ls.c.acl 2004-03-13 11:50:03.000000000 +0000 ++++ coreutils-5.2.1/src/ls.c 2004-03-13 11:50:03.000000000 +0000 +@@ -188,13 +188,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 +@@ -2409,7 +2409,7 @@ + return 0; + } + +-#if HAVE_ACL ++#if HAVE_ACL || USE_ACL + if (format == long_format) + { + int n = file_has_acl (path, &f->stat); +--- coreutils-5.2.1/src/install.c.acl 2004-03-13 11:50:03.000000000 +0000 ++++ coreutils-5.2.1/src/install.c 2004-03-13 11:50:03.000000000 +0000 +@@ -242,7 +242,6 @@ + x->mode = S_IRUSR | S_IWUSR; + x->stdin_tty = 0; + +- x->umask_kill = 0; + x->update = 0; + x->verbose = 0; + x->dest_info = NULL; +--- coreutils-5.2.1/src/cp.c.acl 2004-02-07 15:55:09.000000000 +0000 ++++ coreutils-5.2.1/src/cp.c 2004-03-13 11:50:03.000000000 +0000 +@@ -58,7 +58,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; + }; +@@ -333,9 +334,14 @@ + } + } + +- if (x->preserve_mode || p->is_new_dir) +- { +- if (chmod (dst_path, src_sb.st_mode & x->umask_kill)) ++ if (x->preserve_mode) ++ { ++ 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)); +@@ -353,8 +359,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 +@@ -369,15 +374,20 @@ + /* 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; ++ int (*xstat)() = (x->dereference == DEREF_COMMAND_LINE_ARGUMENTS ++ || x->dereference == DEREF_ALWAYS ++ ? stat ++ : lstat); + + ASSIGN_STRDUPA (dirpath, const_dirpath); + +@@ -412,12 +422,20 @@ + if ((*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 ((*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"), +@@ -429,6 +447,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)) + { +@@ -438,7 +496,7 @@ + } + else + { +- new->is_new_dir = 0; ++ new->mode_valid = 0; + *new_dst = 0; + } + *slash++ = '/'; +@@ -552,10 +610,6 @@ + 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); + + for (i = 0; i < n_files; i++) + { +@@ -593,11 +647,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, +- xstat); ++ &attr_list, &new_dst, x); + } + else + { +@@ -731,12 +783,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; +@@ -1011,9 +1057,6 @@ + version_control_string) + : none); + +- if (x.preserve_mode == 1) +- x.umask_kill = ~ (mode_t) 0; +- + if (x.dereference == DEREF_UNDEFINED) + { + if (x.recursive) +--- coreutils-5.2.1/src/copy.h.acl 2004-02-07 16:00:59.000000000 +0000 ++++ coreutils-5.2.1/src/copy.h 2004-03-13 11:50:03.000000000 +0000 +@@ -143,9 +143,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; +--- coreutils-5.2.1/src/copy.c.acl 2004-03-12 11:48:59.000000000 +0000 ++++ coreutils-5.2.1/src/copy.c 2004-03-13 11:50:43.000000000 +0000 +@@ -95,26 +95,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 +@@ -817,13 +797,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) +@@ -837,11 +817,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; +@@ -909,7 +887,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"), +@@ -935,7 +913,7 @@ + } + } + +- if (!S_ISDIR (src_type)) ++ if (!S_ISDIR (src_mode)) + { + if (S_ISDIR (dst_sb.st_mode)) + { +@@ -963,7 +941,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) +@@ -1084,7 +1062,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) +@@ -1132,7 +1110,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); + } +@@ -1145,7 +1123,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. */ +@@ -1197,7 +1175,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; +@@ -1310,7 +1288,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; + +@@ -1335,16 +1313,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. */ +@@ -1420,23 +1420,22 @@ + goto un_backup; + } + } +- else if (S_ISREG (src_type) +- || (x->copy_as_regular && !S_ISDIR (src_type) +- && !S_ISLNK (src_type))) ++ else if (S_ISREG (src_mode) ++ || (x->copy_as_regular && !S_ISDIR (src_mode) ++ && !S_ISLNK (src_mode))) + { + copied_as_regular = 1; + /* 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; +@@ -1444,10 +1443,10 @@ + } + else + #endif +- if (S_ISBLK (src_type) || S_ISCHR (src_type) +- || S_ISSOCK (src_type)) ++ if (S_ISBLK (src_mode) || S_ISCHR (src_mode) ++ || S_ISSOCK (src_mode)) + { +- 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)); +@@ -1456,7 +1455,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) +@@ -1560,7 +1559,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"), +@@ -1587,20 +1604,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; + } + } +--- coreutils-5.2.1/src/Makefile.am.acl 2004-02-02 08:12:57.000000000 +0000 ++++ coreutils-5.2.1/src/Makefile.am 2004-03-13 11:50:03.000000000 +0000 +@@ -32,10 +32,13 @@ + # replacement functions defined in libfetish.a. + LDADD = ../lib/libfetish.a $(LIBINTL) ../lib/libfetish.a + +-dir_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) +-ls_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) ++dir_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) @LIBACL@ ++ls_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) @LIBACL@ + shred_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) +-vdir_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) ++vdir_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) @LIBACL@ ++cp_LDADD = $(LDADD) @LIBACL@ ++ginstall_LDADD = $(LDADD) @LIBACL@ ++mv_LDADD = $(LDADD) @LIBACL@ + + ## If necessary, add -lm to resolve use of pow in lib/strtod.c. + sort_LDADD = $(LDADD) $(POW_LIB) +--- coreutils-5.2.1/configure.ac.acl 2004-03-02 22:47:31.000000000 +0000 ++++ coreutils-5.2.1/configure.ac 2004-03-13 11:50:03.000000000 +0000 +@@ -16,6 +16,9 @@ + AC_PROG_RANLIB + AC_PROG_LN_S + AC_CANONICAL_HOST ++AM_C_PROTOTYPES ++AC_PROG_YACC ++AC_SUBST(YACC) + + + AC_CHECK_FUNCS(uname, +@@ -235,6 +238,8 @@ + AM_GNU_GETTEXT([external], [need-ngettext]) + AM_GNU_GETTEXT_VERSION(0.13.1) + ++ag_POSIX_ACL ++ + AC_CONFIG_FILES( + Makefile + doc/Makefile +--- coreutils-5.2.1/config.hin.acl 2004-03-11 08:59:16.000000000 +0000 ++++ coreutils-5.2.1/config.hin 2004-03-13 11:50:03.000000000 +0000 +@@ -96,6 +96,30 @@ + /* Define to 1 if you have the `acl' function. */ + #undef HAVE_ACL + ++/* Define to 1 if you have the `acl_delete_def_file' function. */ ++#undef HAVE_ACL_DELETE_DEF_FILE ++ ++/* Define to 1 if you have the `acl_entries' function. */ ++#undef HAVE_ACL_ENTRIES ++ ++/* Define to 1 if you have the `acl_extended_file' function. */ ++#undef HAVE_ACL_EXTENDED_FILE ++ ++/* Define to 1 if you have the `acl_free' function. */ ++#undef HAVE_ACL_FREE ++ ++/* Define to 1 if you have the `acl_from_text' function. */ ++#undef HAVE_ACL_FROM_TEXT ++ ++/* Define to 1 if you have the `acl_get_file' function. */ ++#undef HAVE_ACL_GET_FILE ++ ++/* Define to 1 if you have the `acl_set_file' function. */ ++#undef HAVE_ACL_SET_FILE ++ ++/* Define to 1 if you have the `acl_to_text' function. */ ++#undef HAVE_ACL_TO_TEXT ++ + /* Define to 1 if you have the `alarm' function. */ + #undef HAVE_ALARM + +@@ -489,6 +513,9 @@ + /* Define to 1 if you have the `lchown' function. */ + #undef HAVE_LCHOWN + ++/* Define to 1 if you have the `acl' library (-lacl). */ ++#undef HAVE_LIBACL ++ + /* Define to 1 if you have the `dgc' library (-ldgc). */ + #undef HAVE_LIBDGC + +@@ -1335,6 +1362,9 @@ + . */ + #undef UMAX4_3 + ++/* Define if you want access control list support. */ ++#undef USE_ACL ++ + /* Version number of package */ + #undef VERSION + +--- coreutils-5.2.1/NEWS.acl 2004-03-12 19:04:30.000000000 +0000 ++++ coreutils-5.2.1/NEWS 2004-03-13 11:50:03.000000000 +0000 +@@ -1,3 +1,6 @@ ++[4.5.3acl] ++* ACL framework and Linux ACL support. ++* `cp -p' and `mv' now preserve ACLs + GNU coreutils NEWS -*- outline -*- + * Major changes in release 5.2.1 (2004-03-12) [stable] + +--- coreutils-5.2.1/ChangeLog.acl 2004-03-12 19:03:44.000000000 +0000 ++++ coreutils-5.2.1/ChangeLog 2004-03-13 11:50:03.000000000 +0000 +@@ -0,0 +1,45 @@ ++2002-07-01 Bernhard Rosenkraenzer ++ * Port the following patch to 4.1.9: ++ ++2002-04-10 Andreas Gruenbacher ++ ++ * Version 4.1.8acl. ++ ++ * src/copy.c (get_dest_mode): Remove. ++ * src/copy.c (copy_internal): Merge src_mode and src_type. ++ * src/copy.c (copy_internal): Add dst_mode and dst_mode_valid, ++ which are set when the destination file mode is changed temporarily. ++ * src/copy.c (copy_internal): Check effective permissions after ++ mkdir(). Add S_IRWXU only after saving the default permissions, so ++ the default permissions can be restored. This is needed with ++ default ACLs on some systems. ++ * src/copy.c (copy_internal): Use dst_mode and dst_mode_valid for ++ ran_chown. Save the current permissions if needed before chown(). ++ * src/copy.c (copy_internal): Clean up the final permission setting ++ code and prepare for copy/set ACL support. ++ * src/cp.c, src/install.c, src/mv.c, src/copy.h: Remove umask_kill, ++ and never change the startup umask. The functions creating files need ++ the original umask to be active to create the correct permissions ++ inside directories with default ACLs; umask_kill no longer works. ++ * src/cp.c (struct dir_attr, re_protect, make_path_private): Remove ++ is_new_dir and add mode and mode_valid instead. ++ * src/cp.c (make_path_private): Remove the mode parameter. Pass in ++ cp_options, instead of cp_options->xstat only. Stat the source dir, ++ and create the destination dir with the source dir's mode as create ++ mode (see analog change to src/copy.c (copy_internal)). Check if the ++ effective permissions include S_IRWXU. Remember the original code only ++ if needed later. ++ * lib/acl.h, lib/acl.c (copy_acl, set_acl): Add these functions, ++ initially with the bare non-ACL functionality. ++ * src/copy.c (copy_internal): Use copy_acl and set_acl instead of chmod. ++ * src/cp.c (re_protect): Use copy_acl instead of chmod. ++ * m4/posix_acl.m4, configure.ac (ag_POSIX_ACL): Add POSIX ACL tests. ++ * lib/acl.h: Remove HAVE_ACL symbol; is needed for POSIX ++ ACLs even if there is no acl system call. ++ * lib/acl.c (ENOTSUP): Provide default value. ++ * lib/acl.c (file_has_acl, copy_acl, set_acl): Add Linux ACL ++ implementations. ++ * src/ls.c: change `HAVE_ACL' to `HAVE_ACL || USE_ACL' for POSIX ACLs: ++ there is no acl system call for POSIX ACLs. ++ * tests/misc: Add my own small test suite so it doesn't get lost. ++ +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/\@OWNER\@/$owner/g; ++ $script =~ s/\@GROUP\@/$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 /(? ?//) { ++ 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 () { ++ #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; ++ } ++} ++ +--- coreutils-5.2.1/po/pl.po.orig 2003-12-28 23:21:11.000000000 +0100 ++++ coreutils-5.2.1/po/pl.po 2003-12-28 23:43:19.632649608 +0100 +@@ -1011,6 +1011,11 @@ + msgid "setting permissions for %s" + msgstr "nie mo¿na ustawiæ uprawnieñ do %s" + ++#: src/copy.c:1568 ++#, c-format ++msgid "preserving permissions for %s" ++msgstr "nie mo¿na zachowaæ uprawnieñ do %s" ++ + #: src/copy.c:1624 src/ln.c:332 + #, c-format + msgid "cannot un-backup %s"