mirror of the now-defunct rocklinux.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1143 lines
32 KiB

  1. # --- ROCK-COPYRIGHT-NOTE-BEGIN ---
  2. #
  3. # This copyright note is auto-generated by ./scripts/Create-CopyPatch.
  4. # Please add additional copyright information _after_ the line containing
  5. # the ROCK-COPYRIGHT-NOTE-END tag. Otherwise it might get removed by
  6. # the ./scripts/Create-CopyPatch script. Do not edit this copyright text!
  7. #
  8. # ROCK Linux: rock-src/package/base/coreutils/acl-xattr.diff
  9. # ROCK Linux is Copyright (C) 1998 - 2006 Clifford Wolf
  10. #
  11. # This patch file is dual-licensed. It is available under the license the
  12. # patched project is licensed under, as long as it is an OpenSource license
  13. # as defined at http://www.opensource.org/ (e.g. BSD, X11) or under the terms
  14. # of the GNU General Public License as published by the Free Software
  15. # Foundation; either version 2 of the License, or (at your option) any later
  16. # version.
  17. #
  18. # --- ROCK-COPYRIGHT-NOTE-END ---
  19. Andreas Gruenbacher patches for ACL and XATTR support in coreutils.
  20. http://www.suse.de/~agruen/coreutils/5.91/coreutils-acl.diff
  21. http://www.suse.de/~agruen/coreutils/5.91/coreutils-acl+posix.diff
  22. http://www.suse.de/~agruen/coreutils/5.91/coreutils-xattr.diff
  23. (merged using combinediff)
  24. ------------------------------------------------------------------------------
  25. --- coreutils-5.91/doc/coreutils.texi
  26. +++ coreutils-5.91/doc/coreutils.texi
  27. @@ -5610,9 +5610,14 @@
  28. @end table
  29. Following the permission bits is a single character that specifies
  30. -whether an alternate access method applies to the file. When that
  31. -character is a space, there is no alternate access method. When it
  32. -is a printing character (e.g., @samp{+}), then there is such a method.
  33. +whether an alternate access method such as an access control list
  34. +applies to the file. When the character following the permissions is a
  35. +space, there is no alternate access method. When it is a printing
  36. +character, then there is such a method.
  37. +
  38. +For a file with an extended access control list, a @samp{+} character is
  39. +listed. Basic access control lists are equivalent to the permissions
  40. +listed, and are not considered an alternate access method.
  41. @item -n
  42. @itemx --numeric-uid-gid
  43. @@ -6345,6 +6350,18 @@
  44. directory in a different order).
  45. Equivalent to @option{-dpPR}.
  46. +@itemx @w{@kbd{--attributes}=@var{regex}}
  47. +@opindex --attributes
  48. +Preserve extended attributes whose names match the specified regular
  49. +expression. The default behavior or @command{cp} if no
  50. +@option{--attributes} option is given is to preserve all extended
  51. +attributes except file permissions. If @var{regex} is ``@samp{-}'', no
  52. +extended attributes are preserved.
  53. +
  54. +This option does not affect the preservation of file permissions.
  55. +File permission preservation is controlled by the @option{-p} or
  56. +@option{--preserve=mode} options.
  57. +
  58. @item -b
  59. @itemx @w{@kbd{--backup}[=@var{method}]}
  60. @opindex -b
  61. @@ -6448,7 +6465,7 @@
  62. @table @samp
  63. @itemx mode
  64. -Preserve the permission attributes.
  65. +Preserve the permission attributes, including access control lists.
  66. @itemx ownership
  67. Preserve the owner and group. On most modern systems,
  68. only the super-user may change the owner of a file, and regular users
  69. @@ -6464,7 +6481,6 @@
  70. @itemx all
  71. Preserve all file attributes.
  72. Equivalent to specifying all of the above.
  73. -@c Mention ACLs here.
  74. @end table
  75. Using @option{--preserve} with no @var{attribute_list} is equivalent
  76. --- coreutils-5.91/lib/acl.c
  77. +++ coreutils-5.91/lib/acl.c
  78. @@ -22,18 +22,35 @@
  79. # include <config.h>
  80. #endif
  81. +#include <stdlib.h>
  82. #include <sys/types.h>
  83. #include <sys/stat.h>
  84. #ifndef S_ISLNK
  85. # define S_ISLNK(Mode) 0
  86. #endif
  87. +#include "error.h"
  88. +#include "quote.h"
  89. #include "acl.h"
  90. +#ifdef HAVE_ACL_LIBACL_H
  91. +# include <acl/libacl.h>
  92. +#endif
  93. +
  94. #include <errno.h>
  95. #ifndef ENOSYS
  96. # define ENOSYS (-1)
  97. #endif
  98. +#ifndef ENOTSUP
  99. +# define ENOTSUP (-1)
  100. +#endif
  101. +
  102. +#if ENABLE_NLS
  103. +# include <libintl.h>
  104. +# define _(Text) gettext (Text)
  105. +#else
  106. +# define _(Text) Text
  107. +#endif
  108. #ifndef MIN_ACL_ENTRIES
  109. # define MIN_ACL_ENTRIES 4
  110. @@ -47,17 +64,196 @@
  111. {
  112. - /* FIXME: This implementation should work on recent-enough versions
  113. - of HP-UX, Solaris, and Unixware, but it simply returns 0 with
  114. - POSIX 1003.1e (draft 17 -- abandoned), AIX, GNU/Linux, Irix, and
  115. - Tru64. Please see Samba's source/lib/sysacls.c file for
  116. - fix-related ideas. */
  117. +#if USE_ACL && HAVE_ACL && defined GETACLCNT
  118. + /* This implementation should work on recent-enough versions of HP-UX,
  119. + Solaris, and Unixware. */
  120. -#if HAVE_ACL && defined GETACLCNT
  121. if (! S_ISLNK (filestat->st_mode))
  122. {
  123. int n = acl (file, GETACLCNT, 0, NULL);
  124. return n < 0 ? (errno == ENOSYS ? 0 : -1) : (MIN_ACL_ENTRIES < n);
  125. }
  126. +#elif USE_ACL && HAVE_ACL_EXTENDED_FILE
  127. + /* Linux specific version. */
  128. +
  129. + if (! S_ISLNK (filestat->st_mode))
  130. + {
  131. + int ret = acl_extended_file (file);
  132. + if (ret < 0)
  133. + return (errno == ENOSYS || errno == ENOTSUP) ? 0 : -1;
  134. + return ret;
  135. + }
  136. +#endif
  137. +
  138. + /* FIXME: Add support for POSIX 1003.1e (draft 17 -- abandoned), AIX, Irix,
  139. + and Tru64. Please see Samba's source/lib/sysacls.c file for fix-related
  140. + ideas. */
  141. +
  142. + return 0;
  143. +}
  144. +
  145. +/* Copy the access control list of src_file to dst_file. Fall back to
  146. + src_st.st_mode if access control lists are not supported for either
  147. + file. */
  148. +int
  149. +copy_acl (char const *src_file, char const *dst_file, mode_t mode)
  150. +{
  151. +#if USE_ACL && HAVE_ACL_GET_FILE && HAVE_ACL_SET_FILE && \
  152. + HAVE_ACL_FREE && HAVE_ACL_ENTRIES
  153. + /* Linux specific. Will work on all POSIX 1003.1e draft 17 (abandoned)
  154. + systems if the Linux specific acl_entries() function is substituted. */
  155. +
  156. + acl_t acl = acl_get_file (src_file, ACL_TYPE_ACCESS);
  157. + if (acl == NULL)
  158. + {
  159. + if (errno == ENOSYS || errno == ENOTSUP)
  160. + return set_acl (dst_file, mode);
  161. + else
  162. + {
  163. + error (0, errno, "%s", quote (src_file));
  164. + return -1;
  165. + }
  166. + }
  167. +
  168. + if (acl_set_file (dst_file, ACL_TYPE_ACCESS, acl))
  169. + {
  170. + int saved_errno = errno;
  171. +
  172. + if (errno == ENOSYS || errno == ENOTSUP)
  173. + {
  174. + int n = acl_entries (acl);
  175. +
  176. + acl_free (acl);
  177. + if (n == 3)
  178. + {
  179. + if (chmod (dst_file, mode))
  180. + saved_errno = errno;
  181. + else
  182. + return 0;
  183. + }
  184. + else
  185. + chmod (dst_file, mode);
  186. + }
  187. + else
  188. + {
  189. + acl_free (acl);
  190. + chmod (dst_file, mode);
  191. + }
  192. + error (0, saved_errno, _("preserving permissions for %s"),
  193. + quote (dst_file));
  194. + return -1;
  195. + }
  196. + else
  197. + acl_free (acl);
  198. +
  199. + if (mode & (S_ISUID | S_ISGID | S_ISVTX))
  200. + {
  201. + /* We did not call chmod so far, so the special bits have not yet
  202. + been set. */
  203. +
  204. + if (chmod (dst_file, mode))
  205. + {
  206. + error (0, errno, _("preserving permissions for %s"),
  207. + quote (dst_file));
  208. + return -1;
  209. + }
  210. + }
  211. +
  212. + if (S_ISDIR (mode))
  213. + {
  214. + acl = acl_get_file (src_file, ACL_TYPE_DEFAULT);
  215. + if (acl == NULL)
  216. + {
  217. + error (0, errno, "%s", quote (src_file));
  218. + return -1;
  219. + }
  220. +
  221. + if (acl_set_file (dst_file, ACL_TYPE_DEFAULT, acl))
  222. + {
  223. + error (0, errno, _("preserving permissions for %s"),
  224. + quote (dst_file));
  225. + acl_free(acl);
  226. + return -1;
  227. + }
  228. + else
  229. + acl_free(acl);
  230. + }
  231. + return 0;
  232. +#else
  233. + int ret = chmod (dst_file, mode);
  234. + if (ret)
  235. + error (0, errno, _("preserving permissions for %s"), quote (dst_file));
  236. + return ret;
  237. #endif
  238. +}
  239. +
  240. +/* Set the access control list of path to the permissions defined by mode. */
  241. +int
  242. +set_acl (char const *path, mode_t mode)
  243. +{
  244. +#if USE_ACL && HAVE_ACL_FROM_TEXT && HAVE_ACL_SET_FILE && HAVE_ACL_FREE && \
  245. + HAVE_ACL_DELETE_DEF_FILE
  246. + /* POSIX 1003.1e draft 17 (abandoned) specific version. */
  247. +
  248. + char acl_text[] = "u::---,g::---,o::---";
  249. + acl_t acl;
  250. +
  251. + if (mode & S_IRUSR) acl_text[ 3] = 'r';
  252. + if (mode & S_IWUSR) acl_text[ 4] = 'w';
  253. + if (mode & S_IXUSR) acl_text[ 5] = 'x';
  254. + if (mode & S_IRGRP) acl_text[10] = 'r';
  255. + if (mode & S_IWGRP) acl_text[11] = 'w';
  256. + if (mode & S_IXGRP) acl_text[12] = 'x';
  257. + if (mode & S_IROTH) acl_text[17] = 'r';
  258. + if (mode & S_IWOTH) acl_text[18] = 'w';
  259. + if (mode & S_IXOTH) acl_text[19] = 'x';
  260. + acl = acl_from_text(acl_text);
  261. + if (!acl)
  262. + {
  263. + error (0, errno, "%s", quote (path));
  264. + return -1;
  265. + }
  266. +
  267. + if (acl_set_file(path, ACL_TYPE_ACCESS, acl))
  268. + {
  269. + int saved_errno = errno;
  270. + acl_free (acl);
  271. +
  272. + if (errno == ENOTSUP || errno == ENOSYS)
  273. + {
  274. + if (chmod (path, mode))
  275. + saved_errno = errno;
  276. + else
  277. + return 0;
  278. + }
  279. + error (0, saved_errno, _("setting permissions for %s"), quote (path));
  280. + return -1;
  281. + }
  282. + else
  283. + acl_free (acl);
  284. +
  285. + if (mode & (S_ISUID | S_ISGID | S_ISVTX))
  286. + {
  287. + /* We did not call chmod so far, so the special bits have not yet
  288. + been set. */
  289. +
  290. + if (chmod (path, mode))
  291. + {
  292. + error (0, errno, _("preserving permissions for %s"),
  293. + quote (path));
  294. + return -1;
  295. + }
  296. + }
  297. +
  298. + if (S_ISDIR (mode) && acl_delete_def_file (path))
  299. + {
  300. + error (0, errno, _("setting permissions for %s"), quote (path));
  301. + return -1;
  302. + }
  303. return 0;
  304. +#else
  305. + int ret = chmod (path, mode);
  306. + if (ret)
  307. + error (0, errno, _("setting permissions for %s"), quote (path));
  308. + return ret;
  309. +#endif
  310. }
  311. --- coreutils-5.91/lib/acl.h
  312. +++ coreutils-5.91/lib/acl.h
  313. @@ -18,11 +18,13 @@
  314. Written by Paul Eggert. */
  315. -#if HAVE_SYS_ACL_H && HAVE_ACL
  316. +#if HAVE_SYS_ACL_H
  317. # include <sys/acl.h>
  318. #endif
  319. -#if ! defined GETACLCNT && defined ACL_CNT
  320. +#if defined HAVE_ACL && ! defined GETACLCNT && defined ACL_CNT
  321. # define GETACLCNT ACL_CNT
  322. #endif
  323. int file_has_acl (char const *, struct stat const *);
  324. +int copy_acl(char const *, char const *, mode_t);
  325. +int set_acl(char const *, mode_t);
  326. --- coreutils-5.91/src/copy.c
  327. +++ coreutils-5.91/src/copy.c
  328. @@ -50,6 +50,14 @@
  329. #include "utimens.h"
  330. #include "xreadlink.h"
  331. #include "yesno.h"
  332. +#include "acl.h"
  333. +
  334. +#if USE_XATTR
  335. +# include "regex.h"
  336. +# include <stdarg.h>
  337. +# include <attr/error_context.h>
  338. +# include <attr/libattr.h>
  339. +#endif
  340. #ifndef HAVE_FCHMOD
  341. # define HAVE_FCHMOD false
  342. @@ -101,26 +109,6 @@
  343. /* The invocation name of this program. */
  344. extern char *program_name;
  345. -/* Encapsulate selection of the file mode to be applied to
  346. - new non-directories. */
  347. -
  348. -static mode_t
  349. -get_dest_mode (const struct cp_options *option, mode_t mode)
  350. -{
  351. - /* In some applications (e.g., install), use precisely the
  352. - specified mode. */
  353. - if (option->set_mode)
  354. - return option->mode;
  355. -
  356. - /* Honor the umask for `cp', but not for `mv' or `cp -p'.
  357. - In addition, `cp' without -p must clear the set-user-ID and set-group-ID
  358. - bits. POSIX requires it do that when creating new files. */
  359. - if (!option->move_mode && !option->preserve_mode)
  360. - mode &= (option->umask_kill & ~(S_ISUID | S_ISGID));
  361. -
  362. - return mode;
  363. -}
  364. -
  365. /* FIXME: describe */
  366. /* FIXME: rewrite this to use a hash table so we avoid the quadratic
  367. performance hit that's probably noticeable only on trees deeper
  368. @@ -138,6 +126,104 @@
  369. return false;
  370. }
  371. +#if USE_XATTR
  372. +static void
  373. +copy_attr_error (struct error_context *ctx, const char *fmt, ...)
  374. +{
  375. + int err = errno;
  376. + va_list ap;
  377. + int len;
  378. + char *buffer;
  379. +
  380. + /* There is no error function that takes a va_list argument,
  381. + so we print the message in a buffer first. */
  382. +
  383. + va_start (ap, fmt);
  384. + len = vsnprintf (NULL, 0, fmt, ap);
  385. + if (len > 0)
  386. + {
  387. + buffer = xmalloc (len + 1);
  388. + vsnprintf (buffer, len + 1, fmt, ap);
  389. + error (0, err, "%s", buffer);
  390. + free (buffer);
  391. + }
  392. + va_end (ap);
  393. +}
  394. +
  395. +static const char *
  396. +copy_attr_quote (struct error_context *ctx, const char *str)
  397. +{
  398. + return xstrdup (quote (str));
  399. +}
  400. +
  401. +static void
  402. +copy_attr_free (struct error_context *ctx, const char *str)
  403. +{
  404. + free ((void *) str);
  405. +}
  406. +
  407. +struct copy_attr_context
  408. + {
  409. + struct error_context ctx;
  410. + const char *re_pattern;
  411. + struct re_pattern_buffer re_compiled;
  412. + } copy_attr_ctx = {
  413. + { copy_attr_error,
  414. + copy_attr_quote,
  415. + copy_attr_free }
  416. + };
  417. +
  418. +static int
  419. +copy_attr_filter (const char *name, struct error_context *ctx)
  420. +{
  421. + struct copy_attr_context *copy_ctx = (struct copy_attr_context *) ctx;
  422. +
  423. + return (attr_copy_check_permissions (name, ctx)
  424. + && copy_ctx->re_pattern != NULL
  425. + && re_search (&copy_ctx->re_compiled, name, strlen (name), 0,
  426. + strlen (name), NULL) >= 0);
  427. +}
  428. +#endif /* USE_XATTR */
  429. +
  430. +static bool
  431. +copy_extended_attributes (const char *src_path, const char *dst_path,
  432. + const struct cp_options *x)
  433. +{
  434. +#if USE_XATTR
  435. + if (x->attr_pattern == NULL)
  436. + return true;
  437. +
  438. + if (copy_attr_ctx.re_pattern != x->attr_pattern)
  439. + {
  440. + struct re_pattern_buffer *c = &copy_attr_ctx.re_compiled;
  441. + size_t len = strlen (x->attr_pattern);
  442. + const char *err;
  443. +
  444. + free (c->fastmap);
  445. + free (c->buffer);
  446. +
  447. + copy_attr_ctx.re_pattern = x->attr_pattern;
  448. + c->allocated = 2 * len;
  449. + c->buffer = xmalloc (c->allocated);
  450. + c->fastmap = xmalloc (256);
  451. + c->translate = 0;
  452. + err = re_compile_pattern (x->attr_pattern, len, c);
  453. + if (err)
  454. + {
  455. + free (c->fastmap);
  456. + free (c->buffer);
  457. + copy_attr_ctx.re_pattern = NULL;
  458. + error (EXIT_FAILURE, 0, _("%s: invalid regular expression: %s"),
  459. + x->attr_pattern, err);
  460. + }
  461. + }
  462. + return attr_copy_file (src_path, dst_path,
  463. + copy_attr_filter, &copy_attr_ctx.ctx) == 0;
  464. +#else /* USE_XATTR */
  465. + return true;
  466. +#endif /* USE_XATTR */
  467. +}
  468. +
  469. /* Read the contents of the directory SRC_NAME_IN, and recursively
  470. copy the contents to DST_NAME_IN. NEW_DST is true if
  471. DST_NAME_IN is a directory that was created previously in the
  472. @@ -205,7 +291,6 @@
  473. static bool
  474. copy_reg (char const *src_name, char const *dst_name,
  475. const struct cp_options *x, mode_t dst_mode, bool *new_dst,
  476. - bool *chown_succeeded,
  477. struct stat const *src_sb,
  478. struct stat const *dst_sb)
  479. {
  480. @@ -435,9 +520,8 @@
  481. if (x->preserve_ownership
  482. && (*new_dst || !SAME_OWNER_AND_GROUP (*src_sb, *dst_sb)))
  483. {
  484. - if (fchown (dest_desc, src_sb->st_uid, src_sb->st_gid) == 0)
  485. - *chown_succeeded = true;
  486. - else if (! chown_failure_ok (x))
  487. + if (! fchown (dest_desc, src_sb->st_uid, src_sb->st_gid) == 0 &&
  488. + ! chown_failure_ok (x))
  489. {
  490. error (0, errno, _("failed to preserve ownership for %s"),
  491. quote (dst_name));
  492. @@ -454,27 +538,6 @@
  493. /* FIXME: Preserve the st_author field via the file descriptor dest_desc. */
  494. #endif
  495. -#if HAVE_FCHMOD
  496. - /* Permissions of newly-created regular files were set upon `open'.
  497. - But don't return early if there were any special bits and chown
  498. - succeeded, because the chown must have reset those bits. */
  499. - if (!(*new_dst
  500. - && !(*chown_succeeded && (src_sb->st_mode & ~S_IRWXUGO)))
  501. - && (x->preserve_mode || *new_dst)
  502. - && (x->copy_as_regular || S_ISREG (src_sb->st_mode)))
  503. - {
  504. - if (fchmod (dest_desc, get_dest_mode (x, src_sb->st_mode)) != 0)
  505. - {
  506. - error (0, errno, _("setting permissions for %s"), quote (dst_name));
  507. - if (x->set_mode || x->require_preserve)
  508. - {
  509. - return_val = false;
  510. - goto close_src_and_dst_desc;
  511. - }
  512. - }
  513. - }
  514. -#endif
  515. -
  516. close_src_and_dst_desc:
  517. if (close (dest_desc) < 0)
  518. {
  519. @@ -909,12 +972,13 @@
  520. struct stat dst_sb;
  521. mode_t src_mode;
  522. mode_t src_type;
  523. + mode_t dst_mode IF_LINT (= 0);
  524. + int dst_mode_valid = 0;
  525. char *earlier_file = NULL;
  526. char *dst_backup = NULL;
  527. bool backup_succeeded = false;
  528. bool delayed_ok;
  529. bool copied_as_regular = false;
  530. - bool chown_succeeded = false;
  531. bool preserve_metadata;
  532. if (x->move_mode && rename_succeeded)
  533. @@ -1430,22 +1494,43 @@
  534. if (new_dst || !S_ISDIR (dst_sb.st_mode))
  535. {
  536. - /* Create the new directory writable and searchable, so
  537. - we can create new entries in it. */
  538. -
  539. - if (mkdir (dst_name, (src_mode & x->umask_kill) | S_IRWXU) != 0)
  540. + if (mkdir (dst_name, src_mode) != 0)
  541. {
  542. error (0, errno, _("cannot create directory %s"),
  543. quote (dst_name));
  544. goto un_backup;
  545. }
  546. + /* We need search and write permissions to the new directory
  547. + for writing the directory's contents. Check if these
  548. + permissions are there. */
  549. +
  550. + if (lstat (dst_name, &dst_sb))
  551. + {
  552. + error (0, errno, _("cannot stat %s"), quote (dst_name));
  553. + goto un_backup;
  554. + }
  555. + else if ((dst_sb.st_mode & S_IRWXU) != S_IRWXU)
  556. + {
  557. + /* Make the new directory searchable and writable. The
  558. + original permissions will be restored later. */
  559. +
  560. + dst_mode = dst_sb.st_mode;
  561. + dst_mode_valid = 1;
  562. +
  563. + if (chmod (dst_name, dst_mode | S_IRWXU))
  564. + {
  565. + error (0, errno, _("setting permissions for %s"),
  566. + quote (dst_name));
  567. + goto un_backup;
  568. + }
  569. + }
  570. +
  571. /* Insert the created directory's inode and device
  572. numbers into the search structure, so that we can
  573. avoid copying it again. */
  574. - if (! remember_created (dst_name))
  575. - goto un_backup;
  576. + remember_copied (dst_name, dst_sb.st_ino, dst_sb.st_dev);
  577. if (x->verbose)
  578. printf ("%s -> %s\n", quote_n (0, src_name), quote_n (1, dst_name));
  579. @@ -1522,8 +1607,7 @@
  580. /* POSIX says the permission bits of the source file must be
  581. used as the 3rd argument in the open call, but that's not consistent
  582. with historical practice. */
  583. - if (! copy_reg (src_name, dst_name, x,
  584. - get_dest_mode (x, src_mode), &new_dst, &chown_succeeded,
  585. + if (! copy_reg (src_name, dst_name, x, src_mode, &new_dst,
  586. &src_sb, &dst_sb))
  587. goto un_backup;
  588. }
  589. @@ -1531,7 +1615,7 @@
  590. #ifdef S_ISFIFO
  591. if (S_ISFIFO (src_type))
  592. {
  593. - if (mkfifo (dst_name, get_dest_mode (x, src_mode)))
  594. + if (mkfifo (dst_name, src_mode))
  595. {
  596. error (0, errno, _("cannot create fifo %s"), quote (dst_name));
  597. goto un_backup;
  598. @@ -1542,7 +1626,7 @@
  599. if (S_ISBLK (src_type) || S_ISCHR (src_type)
  600. || S_ISSOCK (src_type))
  601. {
  602. - if (mknod (dst_name, get_dest_mode (x, src_mode), src_sb.st_rdev))
  603. + if (mknod (dst_name, src_mode, src_sb.st_rdev))
  604. {
  605. error (0, errno, _("cannot create special file %s"),
  606. quote (dst_name));
  607. @@ -1654,9 +1738,8 @@
  608. if (!(copied_as_regular && HAVE_FCHOWN) && x->preserve_ownership
  609. && (new_dst || !SAME_OWNER_AND_GROUP (src_sb, dst_sb)))
  610. {
  611. - if (chown (dst_name, src_sb.st_uid, src_sb.st_gid) == 0)
  612. - chown_succeeded = true;
  613. - else if (! chown_failure_ok (x))
  614. + if (! chown (dst_name, src_sb.st_uid, src_sb.st_gid) == 0 &&
  615. + ! chown_failure_ok (x))
  616. {
  617. error (0, errno, _("failed to preserve ownership for %s"),
  618. quote (dst_name));
  619. @@ -1682,21 +1765,30 @@
  620. }
  621. #endif
  622. - /* Permissions of newly-created regular files are set by open and/or fchmod
  623. - in copy_reg. But don't return early if there were any special bits and
  624. - chown succeeded, because the chown must have reset those bits. */
  625. - if (copied_as_regular
  626. - && (HAVE_FCHMOD
  627. - || (new_dst && !(chown_succeeded && (src_mode & ~S_IRWXUGO)))))
  628. - return delayed_ok;
  629. + if (! copy_extended_attributes (src_name, dst_name, x))
  630. + delayed_ok = false;
  631. - if ((x->preserve_mode || new_dst)
  632. - && (x->copy_as_regular || S_ISREG (src_type) || S_ISDIR (src_type)))
  633. + if (x->preserve_mode || x->move_mode)
  634. {
  635. - if (chmod (dst_name, get_dest_mode (x, src_mode)) != 0)
  636. + if (copy_acl (src_name, dst_name, src_mode) && x->require_preserve)
  637. + return false;
  638. + }
  639. + else if (x->set_mode)
  640. + {
  641. + if (chmod (dst_name, x->mode))
  642. {
  643. - error (0, errno, _("setting permissions for %s"), quote (dst_name));
  644. - if (x->set_mode || x->require_preserve)
  645. + error (0, errno, _("setting permissions for %s"),
  646. + quote (dst_name));
  647. + return false;
  648. + }
  649. + }
  650. + else if (dst_mode_valid)
  651. + {
  652. + if (chmod (dst_name, dst_mode))
  653. + {
  654. + error (0, errno, _("preserving permissions for %s"),
  655. + quote (dst_name));
  656. + if (x->require_preserve)
  657. return false;
  658. }
  659. }
  660. --- coreutils-5.91/src/copy.h
  661. +++ coreutils-5.91/src/copy.h
  662. @@ -128,6 +128,10 @@
  663. bool preserve_mode;
  664. bool preserve_timestamps;
  665. + /* Regular expression pattern that specifies which extended attributes to
  666. + copy. NULL stands for copying no extended attributes. */
  667. + const char *attr_pattern;
  668. +
  669. /* Enabled for mv, and for cp by the --preserve=links option.
  670. If true, attempt to preserve in the destination files any
  671. logical hard links between the source files. If used with cp's
  672. @@ -165,9 +169,6 @@
  673. Create destination directories as usual. */
  674. bool symbolic_link;
  675. - /* The bits to preserve in created files' modes. */
  676. - mode_t umask_kill;
  677. -
  678. /* If true, do not copy a nondirectory that has an existing destination
  679. with the same or newer modification time. */
  680. bool update;
  681. --- coreutils-5.91/src/cp.c
  682. +++ coreutils-5.91/src/cp.c
  683. @@ -35,6 +35,7 @@
  684. #include "quotearg.h"
  685. #include "stat-time.h"
  686. #include "utimens.h"
  687. +#include "acl.h"
  688. #define ASSIGN_BASENAME_STRDUPA(Dest, File_name) \
  689. do \
  690. @@ -56,7 +57,8 @@
  691. need to be fixed after copying. */
  692. struct dir_attr
  693. {
  694. - bool is_new_dir;
  695. + mode_t mode;
  696. + bool mode_valid;
  697. size_t slash_offset;
  698. struct dir_attr *next;
  699. };
  700. @@ -72,7 +74,8 @@
  701. REPLY_OPTION,
  702. SPARSE_OPTION,
  703. STRIP_TRAILING_SLASHES_OPTION,
  704. - UNLINK_DEST_BEFORE_OPENING
  705. + UNLINK_DEST_BEFORE_OPENING,
  706. + PRESERVE_XATTRS_OPTION
  707. };
  708. /* Initial number of entries in each hash table entry's table of inodes. */
  709. @@ -129,6 +132,7 @@
  710. {"parents", no_argument, NULL, PARENTS_OPTION},
  711. {"path", no_argument, NULL, PARENTS_OPTION}, /* Deprecated. */
  712. {"preserve", optional_argument, NULL, PRESERVE_ATTRIBUTES_OPTION},
  713. + {"attributes", required_argument, NULL, PRESERVE_XATTRS_OPTION},
  714. {"recursive", no_argument, NULL, 'R'},
  715. {"remove-destination", no_argument, NULL, UNLINK_DEST_BEFORE_OPENING},
  716. {"reply", required_argument, NULL, REPLY_OPTION}, /* Deprecated 2005-07-03,
  717. @@ -219,6 +223,13 @@
  718. -v, --verbose explain what is being done\n\
  719. -x, --one-file-system stay on this file system\n\
  720. "), stdout);
  721. + fputs(_("\n\
  722. + --attributes=regex preserve extended attributes whose name\n\
  723. + matches the specified regular expression\n\
  724. + (defaults to preserving all extended\n\
  725. + attributes except file permissions;\n\
  726. + regex=`-' preserves no extended attributes).\n\
  727. +"), stdout);
  728. fputs (HELP_OPTION_DESCRIPTION, stdout);
  729. fputs (VERSION_OPTION_DESCRIPTION, stdout);
  730. fputs (_("\
  731. @@ -327,9 +338,14 @@
  732. }
  733. }
  734. - if (x->preserve_mode | p->is_new_dir)
  735. + if (x->preserve_mode)
  736. + {
  737. + if (copy_acl (src_name, dst_name, src_sb.st_mode))
  738. + return false;
  739. + }
  740. + else if (p->mode_valid)
  741. {
  742. - if (chmod (dst_name, src_sb.st_mode & x->umask_kill))
  743. + if (chmod (dst_name, p->mode))
  744. {
  745. error (0, errno, _("failed to preserve permissions for %s"),
  746. quote (dst_name));
  747. @@ -347,8 +363,7 @@
  748. SRC_OFFSET is the index in CONST_DIR (which is a destination
  749. directory) of the beginning of the source directory name.
  750. - Create any leading directories that don't already exist,
  751. - giving them permissions MODE.
  752. + Create any leading directories that don't already exist.
  753. If VERBOSE_FMT_STRING is nonzero, use it as a printf format
  754. string for printing a message after successfully making a directory.
  755. The format should take two string arguments: the names of the
  756. @@ -364,9 +379,9 @@
  757. static bool
  758. make_dir_parents_private (char const *const_dir, size_t src_offset,
  759. - mode_t mode, char const *verbose_fmt_string,
  760. + char const *verbose_fmt_string,
  761. struct dir_attr **attr_list, bool *new_dst,
  762. - int (*xstat) ())
  763. + const struct cp_options *x)
  764. {
  765. struct stat stats;
  766. char *dir; /* A copy of CONST_DIR we can change. */
  767. @@ -385,7 +400,7 @@
  768. *attr_list = NULL;
  769. - if ((*xstat) (dst_dir, &stats))
  770. + if (XSTAT (x, dst_dir, &stats))
  771. {
  772. /* A parent of CONST_DIR does not exist.
  773. Make all missing intermediate directories. */
  774. @@ -404,16 +419,25 @@
  775. *attr_list = new;
  776. *slash = '\0';
  777. - if ((*xstat) (dir, &stats))
  778. + if (XSTAT (x, dir, &stats))
  779. {
  780. + mode_t src_mode;
  781. +
  782. /* This component does not exist. We must set
  783. - *new_dst and new->is_new_dir inside this loop because,
  784. + *new_dst and new->mode inside this loop because,
  785. for example, in the command `cp --parents ../a/../b/c e_dir',
  786. make_dir_parents_private creates only e_dir/../a if
  787. ./b already exists. */
  788. *new_dst = true;
  789. - new->is_new_dir = true;
  790. - if (mkdir (dir, mode))
  791. + if (XSTAT (x, src, &stats))
  792. + {
  793. + error (0, errno, _("failed to get attributes of %s"),
  794. + quote (src));
  795. + return false;
  796. + }
  797. + src_mode = stats.st_mode;
  798. +
  799. + if (mkdir (dir, src_mode))
  800. {
  801. error (0, errno, _("cannot make directory %s"),
  802. quote (dir));
  803. @@ -424,6 +448,45 @@
  804. if (verbose_fmt_string != NULL)
  805. printf (verbose_fmt_string, src, dir);
  806. }
  807. +
  808. + /* We need search and write permissions to the new directory
  809. + for writing the directory's contents. Check if these
  810. + permissions are there. */
  811. +
  812. + if (lstat (dir, &stats))
  813. + {
  814. + error (0, errno, _("failed to get attributes of %s"),
  815. + quote (dir));
  816. + return false;
  817. + }
  818. + else
  819. + {
  820. + if (x->preserve_mode)
  821. + {
  822. + new->mode = src_mode;
  823. + new->mode_valid = (src_mode != stats.st_mode);
  824. + }
  825. + else
  826. + {
  827. + new->mode = stats.st_mode;
  828. + new->mode_valid = false;
  829. + }
  830. +
  831. + if ((stats.st_mode & S_IRWXU) != S_IRWXU)
  832. + {
  833. + /* Make the new directory searchable and writable. The
  834. + original permissions will be restored later. */
  835. +
  836. + new->mode_valid = true;
  837. +
  838. + if (chmod (dir, stats.st_mode | S_IRWXU))
  839. + {
  840. + error (0, errno, _("setting permissions for %s"),
  841. + quote (dir));
  842. + return false;
  843. + }
  844. + }
  845. + }
  846. }
  847. else if (!S_ISDIR (stats.st_mode))
  848. {
  849. @@ -433,7 +496,7 @@
  850. }
  851. else
  852. {
  853. - new->is_new_dir = false;
  854. + new->mode_valid = false;
  855. *new_dst = false;
  856. }
  857. *slash++ = '/';
  858. @@ -536,10 +599,6 @@
  859. Copy the files `file1' through `filen'
  860. to the existing directory `edir'. */
  861. int i;
  862. - int (*xstat)() = (x->dereference == DEREF_COMMAND_LINE_ARGUMENTS
  863. - || x->dereference == DEREF_ALWAYS
  864. - ? stat
  865. - : lstat);
  866. /* Initialize these hash tables only if we'll need them.
  867. The problems they're used to detect can arise only if
  868. @@ -585,9 +644,9 @@
  869. leading directories. */
  870. parent_exists =
  871. (make_dir_parents_private
  872. - (dst_name, arg_in_concat - dst_name, S_IRWXU,
  873. + (dst_name, arg_in_concat - dst_name,
  874. (x->verbose ? "%s -> %s\n" : NULL),
  875. - &attr_list, &new_dst, xstat));
  876. + &attr_list, &new_dst, x));
  877. }
  878. else
  879. {
  880. @@ -697,16 +756,12 @@
  881. /* Not used. */
  882. x->stdin_tty = false;
  883. - /* Find out the current file creation mask, to knock the right bits
  884. - when using chmod. The creation mask is set to be liberal, so
  885. - that created directories can be written, even if it would not
  886. - have been allowed with the mask this process was started with. */
  887. - x->umask_kill = ~ umask (0);
  888. -
  889. x->update = false;
  890. x->verbose = false;
  891. x->dest_info = NULL;
  892. x->src_info = NULL;
  893. +
  894. + x->attr_pattern = ""; /* all extended attributes */
  895. }
  896. /* Given a string, ARG, containing a comma-separated list of arguments
  897. @@ -894,6 +949,13 @@
  898. x.require_preserve = true;
  899. break;
  900. + case PRESERVE_XATTRS_OPTION:
  901. + if (strcmp (optarg, "-") == 0)
  902. + x.attr_pattern = NULL;
  903. + else
  904. + x.attr_pattern = optarg;
  905. + break;
  906. +
  907. case PARENTS_OPTION:
  908. parents_option = true;
  909. break;
  910. @@ -987,9 +1049,6 @@
  911. version_control_string)
  912. : no_backups);
  913. - if (x.preserve_mode)
  914. - x.umask_kill = ~ (mode_t) 0;
  915. -
  916. if (x.dereference == DEREF_UNDEFINED)
  917. {
  918. if (x.recursive)
  919. --- coreutils-5.91/src/install.c
  920. +++ coreutils-5.91/src/install.c
  921. @@ -153,11 +153,12 @@
  922. x->mode = S_IRUSR | S_IWUSR;
  923. x->stdin_tty = false;
  924. - x->umask_kill = 0;
  925. x->update = false;
  926. x->verbose = false;
  927. x->dest_info = NULL;
  928. x->src_info = NULL;
  929. +
  930. + x->attr_pattern = NULL; /* no extended attributes */
  931. }
  932. /* FILE is the last operand of this command. Return true if FILE is a
  933. --- coreutils-5.91/src/ls.c
  934. +++ coreutils-5.91/src/ls.c
  935. @@ -193,13 +193,13 @@ struct fileinfo
  936. enum filetype filetype;
  937. -#if HAVE_ACL
  938. +#if USE_ACL
  939. /* For long listings, true if the file has an access control list. */
  940. bool have_acl;
  941. #endif
  942. };
  943. -#if HAVE_ACL
  944. +#if USE_ACL
  945. # define FILE_HAS_ACL(F) ((F)->have_acl)
  946. #else
  947. # define FILE_HAS_ACL(F) 0
  948. @@ -334,7 +334,7 @@ static int current_time_ns = -1;
  949. /* Whether any of the files has an ACL. This affects the width of the
  950. mode column. */
  951. -#if HAVE_ACL
  952. +#if USE_ACL
  953. static bool any_has_acl;
  954. #else
  955. enum { any_has_acl = false };
  956. @@ -2469,7 +2469,7 @@ clear_files (void)
  957. }
  958. files_index = 0;
  959. -#if HAVE_ACL
  960. +#if USE_ACL
  961. any_has_acl = false;
  962. #endif
  963. inode_number_width = 0;
  964. @@ -2580,7 +2580,7 @@ gobble_file (char const *name, enum file
  965. return 0;
  966. }
  967. -#if HAVE_ACL
  968. +#if USE_ACL
  969. if (format == long_format)
  970. {
  971. int n = file_has_acl (absolute_name, &f->stat);
  972. --- coreutils-5.91/src/mv.c
  973. +++ coreutils-5.91/src/mv.c
  974. @@ -135,16 +135,12 @@
  975. x->mode = 0;
  976. x->stdin_tty = isatty (STDIN_FILENO);
  977. - /* Find out the current file creation mask, to knock the right bits
  978. - when using chmod. The creation mask is set to be liberal, so
  979. - that created directories can be written, even if it would not
  980. - have been allowed with the mask this process was started with. */
  981. - x->umask_kill = ~ umask (0);
  982. -
  983. x->update = false;
  984. x->verbose = false;
  985. x->dest_info = NULL;
  986. x->src_info = NULL;
  987. +
  988. + x->attr_pattern = ""; /* all extended attributes */
  989. }
  990. /* FILE is the last operand of this command. Return true if FILE is a
  991. --- coreutils-5.91/m4/acl.m4
  992. +++ coreutils-5.91/m4/acl.m4
  993. @@ -14,5 +14,22 @@ AC_DEFUN([AC_FUNC_ACL],
  994. dnl Prerequisites of lib/acl.c.
  995. AC_CHECK_HEADERS(sys/acl.h)
  996. + if test "$ac_cv_header_sys_acl_h" = yes; then
  997. + use_acl=1
  998. + else
  999. + use_acl=0
  1000. + fi
  1001. + AC_DEFINE_UNQUOTED(USE_ACL, $use_acl,
  1002. + [Define if you want access control list support.])
  1003. AC_CHECK_FUNCS(acl)
  1004. + ac_save_LIBS="$LIBS"
  1005. + AC_SEARCH_LIBS(acl_get_file, acl,
  1006. + [test "$ac_cv_search_acl_get_file" = "none required" ||
  1007. + LIB_ACL=$ac_cv_search_acl_get_file])
  1008. + AC_SUBST(LIB_ACL)
  1009. + AC_CHECK_HEADERS(acl/libacl.h)
  1010. + AC_CHECK_FUNCS(acl_get_file acl_set_file acl_free acl_to_text \
  1011. + acl_from_text acl_delete_def_file \
  1012. + acl_entries acl_extended_file)
  1013. + LIBS="$ac_save_LIBS"
  1014. ])
  1015. --- coreutils-5.91/src/Makefile.am
  1016. +++ coreutils-5.91/src/Makefile.am
  1017. @@ -92,6 +92,17 @@
  1018. su_LDADD = $(LDADD) $(LIB_CRYPT)
  1019. +dir_LDADD += $(LIB_ACL)
  1020. +ls_LDADD += $(LIB_ACL)
  1021. +vdir_LDADD += $(LIB_ACL)
  1022. +cp_LDADD += $(LIB_ACL)
  1023. +mv_LDADD += $(LIB_ACL)
  1024. +ginstall_LDADD += $(LIB_ACL)
  1025. +
  1026. +cp_LDADD += $(LIB_XATTR)
  1027. +mv_LDADD += $(LIB_XATTR)
  1028. +ginstall_LDADD += $(LIB_XATTR)
  1029. +
  1030. $(PROGRAMS): ../lib/libcoreutils.a
  1031. SUFFIXES = .sh
  1032. --- coreutils-5.91/configure.ac
  1033. +++ coreutils-5.91/configure.ac
  1034. @@ -248,6 +248,9 @@ AC_CHECK_DECLS([strtoimax, strtoumax])
  1035. cu_LIB_CHECK
  1036. +# Extended attribute copying.
  1037. +AC_FUNC_XATTR
  1038. +
  1039. AM_GNU_GETTEXT([external], [need-ngettext])
  1040. AM_GNU_GETTEXT_VERSION(0.13.1)
  1041. --- coreutils-5.91/m4/xattr.m4
  1042. +++ coreutils-5.91/m4/xattr.m4
  1043. @@ -0,0 +1,38 @@
  1044. +# xattr.m4 - check for Extended Attributes (Linux)
  1045. +
  1046. +# Copyright (C) 2003 Free Software Foundation, Inc.
  1047. +
  1048. +# This program is free software; you can redistribute it and/or modify
  1049. +# it under the terms of the GNU General Public License as published by
  1050. +# the Free Software Foundation; either version 2, or (at your option)
  1051. +# any later version.
  1052. +
  1053. +# This program is distributed in the hope that it will be useful,
  1054. +# but WITHOUT ANY WARRANTY; without even the implied warranty of
  1055. +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1056. +# GNU General Public License for more details.
  1057. +
  1058. +# You should have received a copy of the GNU General Public License
  1059. +# along with this program; if not, write to the Free Software Foundation,
  1060. +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  1061. +
  1062. +# Written by Andreas Gruenbacher.
  1063. +
  1064. +AC_DEFUN([AC_FUNC_XATTR],
  1065. +[
  1066. + AC_CHECK_HEADERS(attr/error_context.h attr/libattr.h)
  1067. + if test "$ac_cv_header_attr_libattr_h" = yes \
  1068. + && test "$ac_cv_header_attr_error_context_h" = yes; then
  1069. + use_xattr=1
  1070. + else
  1071. + use_xattr=0
  1072. + fi
  1073. + AC_DEFINE_UNQUOTED(USE_XATTR, $use_xattr,
  1074. + [Define if you want extended attribute support.])
  1075. + xattr_saved_LIBS=$LIBS
  1076. + AC_SEARCH_LIBS(attr_copy_file, attr,
  1077. + [test "$ac_cv_search_attr_copy_file" = "none required" || LIB_XATTR=$ac_cv_search_attr_copy_file])
  1078. + AC_SUBST(LIB_XATTR)
  1079. + AC_CHECK_FUNCS(attr_copy_file)
  1080. + LIBS=$xattr_saved_LIBS
  1081. +])