Mercurial > hg > octave-nkf > gnulib-hg
view lib/copy-acl.c @ 14152:c5273d4d49b3
Update to Unicode 5.2.0.
* lib/gen-uni-tables.c (output_predicate, output_category,
output_combclass, output_bidi_category, output_decimal_digit_test,
output_decimal_digit, output_digit_test, output_digit,
output_numeric_test, output_numeric, output_mirror, output_scripts,
output_scripts_byname, output_blocks, output_ident_category): Fix
comment header.
(is_WBP_MIDNUMLET, is_WBP_MIDLETTER): New functions, extracted from
get_wbp.
(PROP_CASED, PROP_CASE_IGNORABLE, PROP_CHANGES_WHEN_*): New enumeration
items.
(fill_properties): Also fill the peoperties Cased, Case_Ignorable,
Changes_When_Lowercased, Changes_When_Uppercased,
Changes_When_Titlecased, Changes_When_Casefolded,
Changes_When_Casemapped.
(is_property_alphabetic, is_property_default_ignorable_code_point):
Update for Unicode 5.2.0.
(is_property_cased, is_property_case_ignorable,
is_property_changes_when_lowercased,
is_property_changes_when_uppercased,
is_property_changes_when_titlecased,
is_property_changes_when_casefolded,
is_property_changes_when_casemapped): New functions.
(output_properties): Output also the properties cased, case_ignorable,
changes_when_lowercased, changes_when_uppercased,
changes_when_titlecased, changes_when_casefolded,
changes_when_casemapped.
(symbolic_width): Update for Unicode 5.2.0, incorporating changes from
Unicode TR#11 revision 17 -> 19.
(LBP_CP): New enumeration value.
(LBP_*): Adjust values accordingly.
(get_lbp): Update for Unicode 5.2.0, incorporating changes from Unicode
TR#14 revision 22 -> 24.
(debug_output_lbp): Allow for LBP_* bits >= 32. Support LBP_CP.
(fill_org_lbp, debug_output_org_lbp, output_lbp): Support LBP_CP.
(get_wbp): Update for Unicode 5.2.0, incorporating changes from Unicode
TR#29 revision 13 -> 15. Use functions is_WBP_MIDNUMLET,
is_WBP_MIDLETTER.
(output_composition_tables): Allow for 24 bits instead of 16 bits in
the code1 and code2 of each composition rule.
* lib/unicase/cased.h: Regenerated for Unicode 5.2.0.
* lib/unicase/ignorable.h: Likewise.
* lib/unicase/tocasefold.h: Likewise.
* lib/unicase/tolower.h: Likewise.
* lib/unicase/totitle.h: Likewise.
* lib/unicase/toupper.h: Likewise.
* lib/unictype/bidi_of.h: Likewise.
* lib/unictype/blocks.h: Likewise.
* lib/unictype/categ_C.h: Likewise.
* lib/unictype/categ_Cf.h: Likewise.
* lib/unictype/categ_Cn.h: Likewise.
* lib/unictype/categ_L.h: Likewise.
* lib/unictype/categ_Ll.h: Likewise.
* lib/unictype/categ_Lm.h: Likewise.
* lib/unictype/categ_Lo.h: Likewise.
* lib/unictype/categ_Lu.h: Likewise.
* lib/unictype/categ_M.h: Likewise.
* lib/unictype/categ_Mc.h: Likewise.
* lib/unictype/categ_Mn.h: Likewise.
* lib/unictype/categ_N.h: Likewise.
* lib/unictype/categ_Nd.h: Likewise.
* lib/unictype/categ_Nl.h: Likewise.
* lib/unictype/categ_No.h: Likewise.
* lib/unictype/categ_P.h: Likewise.
* lib/unictype/categ_Pd.h: Likewise.
* lib/unictype/categ_Po.h: Likewise.
* lib/unictype/categ_S.h: Likewise.
* lib/unictype/categ_Sc.h: Likewise.
* lib/unictype/categ_So.h: Likewise.
* lib/unictype/categ_of.h: Likewise.
* lib/unictype/combining.h: Likewise.
* lib/unictype/ctype_alnum.h: Likewise.
* lib/unictype/ctype_alpha.h: Likewise.
* lib/unictype/ctype_graph.h: Likewise.
* lib/unictype/ctype_lower.h: Likewise.
* lib/unictype/ctype_print.h: Likewise.
* lib/unictype/ctype_punct.h: Likewise.
* lib/unictype/ctype_upper.h: Likewise.
* lib/unictype/decdigit.h: Likewise.
* lib/unictype/digit.h: Likewise.
* lib/unictype/numeric.h: Likewise.
* lib/unictype/pr_alphabetic.h: Likewise.
* lib/unictype/pr_bidi_arabic_digit.h: Likewise.
* lib/unictype/pr_bidi_eur_num_terminator.h: Likewise.
* lib/unictype/pr_bidi_european_digit.h: Likewise.
* lib/unictype/pr_bidi_hebrew_right_to_left.h: Likewise.
* lib/unictype/pr_bidi_left_to_right.h: Likewise.
* lib/unictype/pr_bidi_non_spacing_mark.h: Likewise.
* lib/unictype/pr_bidi_other_neutral.h: Likewise.
* lib/unictype/pr_combining.h: Likewise.
* lib/unictype/pr_composite.h: Likewise.
* lib/unictype/pr_currency_symbol.h: Likewise.
* lib/unictype/pr_dash.h: Likewise.
* lib/unictype/pr_decimal_digit.h: Likewise.
* lib/unictype/pr_deprecated.h: Likewise.
* lib/unictype/pr_diacritic.h: Likewise.
* lib/unictype/pr_extender.h: Likewise.
* lib/unictype/pr_grapheme_base.h: Likewise.
* lib/unictype/pr_grapheme_extend.h: Likewise.
* lib/unictype/pr_grapheme_link.h: Likewise.
* lib/unictype/pr_id_continue.h: Likewise.
* lib/unictype/pr_id_start.h: Likewise.
* lib/unictype/pr_ideographic.h: Likewise.
* lib/unictype/pr_ignorable_control.h: Likewise.
* lib/unictype/pr_logical_order_exception.h: Likewise.
* lib/unictype/pr_lowercase.h: Likewise.
* lib/unictype/pr_numeric.h: Likewise.
* lib/unictype/pr_other_alphabetic.h: Likewise.
* lib/unictype/pr_punctuation.h: Likewise.
* lib/unictype/pr_sentence_terminal.h: Likewise.
* lib/unictype/pr_terminal_punctuation.h: Likewise.
* lib/unictype/pr_unassigned_code_value.h: Likewise.
* lib/unictype/pr_unified_ideograph.h: Likewise.
* lib/unictype/pr_uppercase.h: Likewise.
* lib/unictype/pr_xid_continue.h: Likewise.
* lib/unictype/pr_xid_start.h: Likewise.
* lib/unictype/pr_zero_width.h: Likewise.
* lib/unictype/scripts.h: Likewise.
* lib/unictype/scripts_byname.gperf: Likewise.
* lib/unictype/sy_java_ident.h: Likewise.
* lib/unigbrk/gbrkprop.h: Likewise.
* lib/unilbrk/lbrkprop1.h: Likewise.
* lib/unilbrk/lbrkprop2.h: Likewise.
* lib/unilbrk/lbrktables.h: Likewise.
* lib/unilbrk/lbrktables.c (unilbrk_table): Add a row and column for
LBP_CP. Implement rule LB30.
* lib/uniwidth/width.c (nonspacing_table_data): Add U+0816..U+0819,
U+081B..U+0823, U+0825..U+0827, U+0829..U+082D, U+0900, U+0955, U+109D,
U+1A56, U+1A58..U+1A5E, U+1A60, U+1A62, U+1A65..U+1A6C, U+1A73..U+1A7C,
U+1A7F, U+1CD0..U+1CD2, U+1CD4..U+1CE0, U+1CE2..U+1CE8, U+1CED, U+1DFD,
U+2CEF..U+2CF1, U+A6F0..U+A6F1, U+A8E0..U+A8F1, U+A980..U+A982, U+A9B3,
U+A9B6..U+A9B9, U+A9BC, U+AAB0, U+AAB2..U+AAB4, U+AAB7..U+AAB8,
U+AABE..U+AABF, U+AAC1, U+ABE5, U+ABE8, U+ABED, U+11080..U+11081,
U+110B3..U+110B6, U+110B9..U+110BA, U+110BD.
(uc_width): Return 2 also for unassigned code points of planes 2 and 3.
* lib/uninorm/composition-table.gperf: Regenerated for Unicode 5.2.0.
* lib/uninorm/composition.c (struct composition_rule): Allow for 24
bits instead of 16 bits in the code1 and code2 of each composition
rule.
(uc_composition): Update for Unicode 5.2.0.
* lib/uninorm/decomposition-table1.h: Regenerated for Unicode 5.2.0.
* lib/uninorm/decomposition-table2.h: Likewise.
* lib/uniwbrk/wbrkprop.h: Likewise.
* tests/unicase/test-cased.c: Likewise.
* tests/unicase/test-ignorable.c: Likewise.
* tests/unicase/test-uc_tolower.c: Likewise.
* tests/unicase/test-uc_totitle.c: Likewise.
* tests/unicase/test-uc_toupper.c: Likewise.
* tests/unictype/test-categ_C.c: Likewise.
* tests/unictype/test-categ_Cf.c: Likewise.
* tests/unictype/test-categ_Cn.c: Likewise.
* tests/unictype/test-categ_L.c: Likewise.
* tests/unictype/test-categ_Ll.c: Likewise.
* tests/unictype/test-categ_Lm.c: Likewise.
* tests/unictype/test-categ_Lo.c: Likewise.
* tests/unictype/test-categ_Lu.c: Likewise.
* tests/unictype/test-categ_M.c: Likewise.
* tests/unictype/test-categ_Mc.c: Likewise.
* tests/unictype/test-categ_Mn.c: Likewise.
* tests/unictype/test-categ_N.c: Likewise.
* tests/unictype/test-categ_Nd.c: Likewise.
* tests/unictype/test-categ_Nl.c: Likewise.
* tests/unictype/test-categ_No.c: Likewise.
* tests/unictype/test-categ_P.c: Likewise.
* tests/unictype/test-categ_Pd.c: Likewise.
* tests/unictype/test-categ_Po.c: Likewise.
* tests/unictype/test-categ_S.c: Likewise.
* tests/unictype/test-categ_Sc.c: Likewise.
* tests/unictype/test-categ_So.c: Likewise.
* tests/unictype/test-ctype_alnum.c: Likewise.
* tests/unictype/test-ctype_alpha.c: Likewise.
* tests/unictype/test-ctype_graph.c: Likewise.
* tests/unictype/test-ctype_lower.c: Likewise.
* tests/unictype/test-ctype_print.c: Likewise.
* tests/unictype/test-ctype_punct.c: Likewise.
* tests/unictype/test-ctype_upper.c: Likewise.
* tests/unictype/test-decdigit.h: Likewise.
* tests/unictype/test-digit.h: Likewise.
* tests/unictype/test-numeric.h: Likewise.
* tests/unictype/test-pr_alphabetic.c: Likewise.
* tests/unictype/test-pr_bidi_arabic_digit.c: Likewise.
* tests/unictype/test-pr_bidi_eur_num_terminator.c: Likewise.
* tests/unictype/test-pr_bidi_european_digit.c: Likewise.
* tests/unictype/test-pr_bidi_hebrew_right_to_left.c: Likewise.
* tests/unictype/test-pr_bidi_left_to_right.c: Likewise.
* tests/unictype/test-pr_bidi_non_spacing_mark.c: Likewise.
* tests/unictype/test-pr_bidi_other_neutral.c: Likewise.
* tests/unictype/test-pr_combining.c: Likewise.
* tests/unictype/test-pr_composite.c: Likewise.
* tests/unictype/test-pr_currency_symbol.c: Likewise.
* tests/unictype/test-pr_dash.c: Likewise.
* tests/unictype/test-pr_decimal_digit.c: Likewise.
* tests/unictype/test-pr_deprecated.c: Likewise.
* tests/unictype/test-pr_diacritic.c: Likewise.
* tests/unictype/test-pr_extender.c: Likewise.
* tests/unictype/test-pr_grapheme_base.c: Likewise.
* tests/unictype/test-pr_grapheme_extend.c: Likewise.
* tests/unictype/test-pr_grapheme_link.c: Likewise.
* tests/unictype/test-pr_id_continue.c: Likewise.
* tests/unictype/test-pr_id_start.c: Likewise.
* tests/unictype/test-pr_ideographic.c: Likewise.
* tests/unictype/test-pr_ignorable_control.c: Likewise.
* tests/unictype/test-pr_logical_order_exception.c: Likewise.
* tests/unictype/test-pr_lowercase.c: Likewise.
* tests/unictype/test-pr_numeric.c: Likewise.
* tests/unictype/test-pr_other_alphabetic.c: Likewise.
* tests/unictype/test-pr_punctuation.c: Likewise.
* tests/unictype/test-pr_sentence_terminal.c: Likewise.
* tests/unictype/test-pr_terminal_punctuation.c: Likewise.
* tests/unictype/test-pr_unassigned_code_value.c: Likewise.
* tests/unictype/test-pr_unified_ideograph.c: Likewise.
* tests/unictype/test-pr_uppercase.c: Likewise.
* tests/unictype/test-pr_xid_continue.c: Likewise.
* tests/unictype/test-pr_xid_start.c: Likewise.
* tests/unictype/test-pr_zero_width.c: Likewise.
* tests/unigbrk/test-uc-gbrk-prop.h: Likewise.
* tests/unilbrk/test-u8-possible-linebreaks.c (main): Update for
changed behaviour: line breaking is now disallowed between a letter
or '=' and '('.
* tests/unilbrk/test-u16-possible-linebreaks.c (main): Likewise.
* tests/unilbrk/test-u32-possible-linebreaks.c (main): Likewise.
* tests/unilbrk/test-ulc-possible-linebreaks.c (main): Likewise.
* tests/unilbrk/test-ulc-width-linebreaks.c (main): Likewise.
* tests/uniwidth/test-uc_width2.sh: Same updates as in
lib/uniwidth/width.c.
* tests/uninorm/NormalizationTest.txt: Update from Unicode 5.2.0,
without comments, but with the original copyright notice.
* lib/unicase/special-casing-table.gperf: Regenerated; only comment
changes.
* lib/unictype/categ_Cc.h: Likewise.
* lib/unictype/categ_Co.h: Likewise.
* lib/unictype/categ_Cs.h: Likewise.
* lib/unictype/categ_Lt.h: Likewise.
* lib/unictype/categ_Me.h: Likewise.
* lib/unictype/categ_Pc.h: Likewise.
* lib/unictype/categ_Pe.h: Likewise.
* lib/unictype/categ_Pf.h: Likewise.
* lib/unictype/categ_Pi.h: Likewise.
* lib/unictype/categ_Ps.h: Likewise.
* lib/unictype/categ_Sk.h: Likewise.
* lib/unictype/categ_Sm.h: Likewise.
* lib/unictype/categ_Z.h: Likewise.
* lib/unictype/categ_Zl.h: Likewise.
* lib/unictype/categ_Zp.h: Likewise.
* lib/unictype/categ_Zs.h: Likewise.
* lib/unictype/ctype_blank.h: Likewise.
* lib/unictype/ctype_cntrl.h: Likewise.
* lib/unictype/ctype_digit.h: Likewise.
* lib/unictype/ctype_space.h: Likewise.
* lib/unictype/ctype_xdigit.h: Likewise.
* lib/unictype/mirror.h: Likewise.
* lib/unictype/pr_ascii_hex_digit.h: Likewise.
* lib/unictype/pr_bidi_arabic_right_to_left.h: Likewise.
* lib/unictype/pr_bidi_block_separator.h: Likewise.
* lib/unictype/pr_bidi_boundary_neutral.h: Likewise.
* lib/unictype/pr_bidi_common_separator.h: Likewise.
* lib/unictype/pr_bidi_control.h: Likewise.
* lib/unictype/pr_bidi_embedding_or_override.h: Likewise.
* lib/unictype/pr_bidi_eur_num_separator.h: Likewise.
* lib/unictype/pr_bidi_pdf.h: Likewise.
* lib/unictype/pr_bidi_segment_separator.h: Likewise.
* lib/unictype/pr_bidi_whitespace.h: Likewise.
* lib/unictype/pr_default_ignorable_code_point.h: Likewise.
* lib/unictype/pr_format_control.h: Likewise.
* lib/unictype/pr_hex_digit.h: Likewise.
* lib/unictype/pr_hyphen.h: Likewise.
* lib/unictype/pr_ids_binary_operator.h: Likewise.
* lib/unictype/pr_ids_trinary_operator.h: Likewise.
* lib/unictype/pr_iso_control.h: Likewise.
* lib/unictype/pr_join_control.h: Likewise.
* lib/unictype/pr_left_of_pair.h: Likewise.
* lib/unictype/pr_line_separator.h: Likewise.
* lib/unictype/pr_math.h: Likewise.
* lib/unictype/pr_non_break.h: Likewise.
* lib/unictype/pr_not_a_character.h: Likewise.
* lib/unictype/pr_other_default_ignorable_code_point.h: Likewise.
* lib/unictype/pr_other_grapheme_extend.h: Likewise.
* lib/unictype/pr_other_id_continue.h: Likewise.
* lib/unictype/pr_other_id_start.h: Likewise.
* lib/unictype/pr_other_lowercase.h: Likewise.
* lib/unictype/pr_other_math.h: Likewise.
* lib/unictype/pr_other_uppercase.h: Likewise.
* lib/unictype/pr_paired_punctuation.h: Likewise.
* lib/unictype/pr_paragraph_separator.h: Likewise.
* lib/unictype/pr_pattern_syntax.h: Likewise.
* lib/unictype/pr_pattern_white_space.h: Likewise.
* lib/unictype/pr_private_use.h: Likewise.
* lib/unictype/pr_quotation_mark.h: Likewise.
* lib/unictype/pr_radical.h: Likewise.
* lib/unictype/pr_soft_dotted.h: Likewise.
* lib/unictype/pr_space.h: Likewise.
* lib/unictype/pr_titlecase.h: Likewise.
* lib/unictype/pr_variation_selector.h: Likewise.
* lib/unictype/pr_white_space.h: Likewise.
* lib/unictype/sy_c_ident.h: Likewise.
* lib/unictype/sy_c_whitespace.h: Likewise.
* lib/unictype/sy_java_whitespace.h: Likewise.
* modules/uni*/*: Bump version number of expected libunistring version.
Reported by Simon Josefsson.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Sun, 09 Jan 2011 11:09:25 +0100 |
parents | 97fc9a21a8fb |
children | 812be65b0e8b |
line wrap: on
line source
/* copy-acl.c - copy access control list from one file to another file Copyright (C) 2002-2003, 2005-2011 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */ #include <config.h> #include "acl.h" #include "acl-internal.h" #include "gettext.h" #define _(msgid) gettext (msgid) /* Copy access control lists from one file to another. If SOURCE_DESC is a valid file descriptor, use file descriptor operations, else use filename based operations on SRC_NAME. Likewise for DEST_DESC and DST_NAME. If access control lists are not available, fchmod the target file to MODE. Also sets the non-permission bits of the destination file (S_ISUID, S_ISGID, S_ISVTX) to those from MODE if any are set. Return 0 if successful. Return -2 and set errno for an error relating to the source file. Return -1 and set errno for an error relating to the destination file. */ static int qcopy_acl (const char *src_name, int source_desc, const char *dst_name, int dest_desc, mode_t mode) { #if USE_ACL && HAVE_ACL_GET_FILE /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */ /* Linux, FreeBSD, MacOS X, IRIX, Tru64 */ # if MODE_INSIDE_ACL /* Linux, FreeBSD, IRIX, Tru64 */ acl_t acl; int ret; if (HAVE_ACL_GET_FD && source_desc != -1) acl = acl_get_fd (source_desc); else acl = acl_get_file (src_name, ACL_TYPE_ACCESS); if (acl == NULL) { if (ACL_NOT_WELL_SUPPORTED (errno)) return qset_acl (dst_name, dest_desc, mode); else return -2; } if (HAVE_ACL_SET_FD && dest_desc != -1) ret = acl_set_fd (dest_desc, acl); else ret = acl_set_file (dst_name, ACL_TYPE_ACCESS, acl); if (ret != 0) { int saved_errno = errno; if (ACL_NOT_WELL_SUPPORTED (errno) && !acl_access_nontrivial (acl)) { acl_free (acl); return chmod_or_fchmod (dst_name, dest_desc, mode); } else { acl_free (acl); chmod_or_fchmod (dst_name, dest_desc, mode); errno = saved_errno; return -1; } } else acl_free (acl); if (mode & (S_ISUID | S_ISGID | S_ISVTX)) { /* We did not call chmod so far, and either the mode and the ACL are separate or special bits are to be set which don't fit into ACLs. */ if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0) return -1; } if (S_ISDIR (mode)) { acl = acl_get_file (src_name, ACL_TYPE_DEFAULT); if (acl == NULL) return -2; if (acl_set_file (dst_name, ACL_TYPE_DEFAULT, acl)) { int saved_errno = errno; acl_free (acl); errno = saved_errno; return -1; } else acl_free (acl); } return 0; # else /* !MODE_INSIDE_ACL */ /* MacOS X */ # if !HAVE_ACL_TYPE_EXTENDED # error Must have ACL_TYPE_EXTENDED # endif /* On MacOS X, acl_get_file (name, ACL_TYPE_ACCESS) and acl_get_file (name, ACL_TYPE_DEFAULT) always return NULL / EINVAL. You have to use acl_get_file (name, ACL_TYPE_EXTENDED) or acl_get_fd (open (name, ...)) to retrieve an ACL. On the other hand, acl_set_file (name, ACL_TYPE_ACCESS, acl) and acl_set_file (name, ACL_TYPE_DEFAULT, acl) have the same effect as acl_set_file (name, ACL_TYPE_EXTENDED, acl): Each of these calls sets the file's ACL. */ acl_t acl; int ret; if (HAVE_ACL_GET_FD && source_desc != -1) acl = acl_get_fd (source_desc); else acl = acl_get_file (src_name, ACL_TYPE_EXTENDED); if (acl == NULL) { if (ACL_NOT_WELL_SUPPORTED (errno)) return qset_acl (dst_name, dest_desc, mode); else return -2; } if (HAVE_ACL_SET_FD && dest_desc != -1) ret = acl_set_fd (dest_desc, acl); else ret = acl_set_file (dst_name, ACL_TYPE_EXTENDED, acl); if (ret != 0) { int saved_errno = errno; if (ACL_NOT_WELL_SUPPORTED (errno) && !acl_extended_nontrivial (acl)) { acl_free (acl); return chmod_or_fchmod (dst_name, dest_desc, mode); } else { acl_free (acl); chmod_or_fchmod (dst_name, dest_desc, mode); errno = saved_errno; return -1; } } else acl_free (acl); /* Since !MODE_INSIDE_ACL, we have to call chmod explicitly. */ return chmod_or_fchmod (dst_name, dest_desc, mode); # endif #elif USE_ACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ # if defined ACL_NO_TRIVIAL /* Solaris 10 (newer version), which has additional API declared in <sys/acl.h> (acl_t) and implemented in libsec (acl_set, acl_trivial, acl_fromtext, ...). */ int ret; acl_t *aclp = NULL; ret = (source_desc < 0 ? acl_get (src_name, ACL_NO_TRIVIAL, &aclp) : facl_get (source_desc, ACL_NO_TRIVIAL, &aclp)); if (ret != 0 && errno != ENOSYS) return -2; ret = qset_acl (dst_name, dest_desc, mode); if (ret != 0) return -1; if (aclp) { ret = (dest_desc < 0 ? acl_set (dst_name, aclp) : facl_set (dest_desc, aclp)); if (ret != 0) { int saved_errno = errno; acl_free (aclp); errno = saved_errno; return -1; } acl_free (aclp); } return 0; # else /* Solaris, Cygwin, general case */ /* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions of Unixware. The acl() call returns the access and default ACL both at once. */ # ifdef ACE_GETACL int ace_count; ace_t *ace_entries; # endif int count; aclent_t *entries; int did_chmod; int saved_errno; int ret; # ifdef ACE_GETACL /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4 file systems (whereas the other ones are used in UFS file systems). There is an API pathconf (name, _PC_ACL_ENABLED) fpathconf (desc, _PC_ACL_ENABLED) that allows to determine which of the two kinds of ACLs is supported for the given file. But some file systems may implement this call incorrectly, so better not use it. When fetching the source ACL, we simply fetch both ACL types. When setting the destination ACL, we try either ACL types, assuming that the kernel will translate the ACL from one form to the other. (See in <http://docs.sun.com/app/docs/doc/819-2241/6n4huc7ia?l=en&a=view> the description of ENOTSUP.) */ for (;;) { ace_count = (source_desc != -1 ? facl (source_desc, ACE_GETACLCNT, 0, NULL) : acl (src_name, ACE_GETACLCNT, 0, NULL)); if (ace_count < 0) { if (errno == ENOSYS || errno == EINVAL) { ace_count = 0; ace_entries = NULL; break; } else return -2; } if (ace_count == 0) { ace_entries = NULL; break; } ace_entries = (ace_t *) malloc (ace_count * sizeof (ace_t)); if (ace_entries == NULL) { errno = ENOMEM; return -2; } if ((source_desc != -1 ? facl (source_desc, ACE_GETACL, ace_count, ace_entries) : acl (src_name, ACE_GETACL, ace_count, ace_entries)) == ace_count) break; /* Huh? The number of ACL entries changed since the last call. Repeat. */ } # endif for (;;) { count = (source_desc != -1 ? facl (source_desc, GETACLCNT, 0, NULL) : acl (src_name, GETACLCNT, 0, NULL)); if (count < 0) { if (errno == ENOSYS || errno == ENOTSUP || errno == EOPNOTSUPP) { count = 0; entries = NULL; break; } else return -2; } if (count == 0) { entries = NULL; break; } entries = (aclent_t *) malloc (count * sizeof (aclent_t)); if (entries == NULL) { errno = ENOMEM; return -2; } if ((source_desc != -1 ? facl (source_desc, GETACL, count, entries) : acl (src_name, GETACL, count, entries)) == count) break; /* Huh? The number of ACL entries changed since the last call. Repeat. */ } /* Is there an ACL of either kind? */ # ifdef ACE_GETACL if (ace_count == 0) # endif if (count == 0) return qset_acl (dst_name, dest_desc, mode); did_chmod = 0; /* set to 1 once the mode bits in 0777 have been set */ saved_errno = 0; /* the first non-ignorable error code */ if (!MODE_INSIDE_ACL) { /* On Cygwin, it is necessary to call chmod before acl, because chmod can change the contents of the ACL (in ways that don't change the allowed accesses, but still visible). */ if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0) saved_errno = errno; did_chmod = 1; } /* If both ace_entries and entries are available, try SETACL before ACE_SETACL, because SETACL cannot fail with ENOTSUP whereas ACE_SETACL can. */ if (count > 0) { ret = (dest_desc != -1 ? facl (dest_desc, SETACL, count, entries) : acl (dst_name, SETACL, count, entries)); if (ret < 0 && saved_errno == 0) { saved_errno = errno; if ((errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL) && !acl_nontrivial (count, entries)) saved_errno = 0; } else did_chmod = 1; } free (entries); # ifdef ACE_GETACL if (ace_count > 0) { ret = (dest_desc != -1 ? facl (dest_desc, ACE_SETACL, ace_count, ace_entries) : acl (dst_name, ACE_SETACL, ace_count, ace_entries)); if (ret < 0 && saved_errno == 0) { saved_errno = errno; if ((errno == ENOSYS || errno == EINVAL || errno == ENOTSUP) && !acl_ace_nontrivial (ace_count, ace_entries)) saved_errno = 0; } } free (ace_entries); # endif if (MODE_INSIDE_ACL && did_chmod <= ((mode & (S_ISUID | S_ISGID | S_ISVTX)) ? 1 : 0)) { /* We did not call chmod so far, and either the mode and the ACL are separate or special bits are to be set which don't fit into ACLs. */ if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0) { if (saved_errno == 0) saved_errno = errno; } } if (saved_errno) { errno = saved_errno; return -1; } return 0; # endif #elif USE_ACL && HAVE_GETACL /* HP-UX */ int count; struct acl_entry entries[NACLENTRIES]; int ret; for (;;) { count = (source_desc != -1 ? fgetacl (source_desc, 0, NULL) : getacl (src_name, 0, NULL)); if (count < 0) { if (ACL_NOT_WELL_SUPPORTED (errno)) { count = 0; break; } else return -2; } if (count == 0) break; if (count > NACLENTRIES) /* If NACLENTRIES cannot be trusted, use dynamic memory allocation. */ abort (); if ((source_desc != -1 ? fgetacl (source_desc, count, entries) : getacl (src_name, count, entries)) == count) break; /* Huh? The number of ACL entries changed since the last call. Repeat. */ } if (count == 0) return qset_acl (dst_name, dest_desc, mode); ret = (dest_desc != -1 ? fsetacl (dest_desc, count, entries) : setacl (dst_name, count, entries)); if (ret < 0) { int saved_errno = errno; if (ACL_NOT_WELL_SUPPORTED (errno)) { struct stat source_statbuf; if ((source_desc != -1 ? fstat (source_desc, &source_statbuf) : stat (src_name, &source_statbuf)) == 0) { if (!acl_nontrivial (count, entries, &source_statbuf)) return chmod_or_fchmod (dst_name, dest_desc, mode); } else saved_errno = errno; } chmod_or_fchmod (dst_name, dest_desc, mode); errno = saved_errno; return -1; } if (mode & (S_ISUID | S_ISGID | S_ISVTX)) { /* We did not call chmod so far, and either the mode and the ACL are separate or special bits are to be set which don't fit into ACLs. */ return chmod_or_fchmod (dst_name, dest_desc, mode); } return 0; #elif USE_ACL && HAVE_ACLX_GET && 0 /* AIX */ /* TODO */ #elif USE_ACL && HAVE_STATACL /* older AIX */ union { struct acl a; char room[4096]; } u; int ret; if ((source_desc != -1 ? fstatacl (source_desc, STX_NORMAL, &u.a, sizeof (u)) : statacl (src_name, STX_NORMAL, &u.a, sizeof (u))) < 0) return -2; ret = (dest_desc != -1 ? fchacl (dest_desc, &u.a, u.a.acl_len) : chacl (dst_name, &u.a, u.a.acl_len)); if (ret < 0) { int saved_errno = errno; chmod_or_fchmod (dst_name, dest_desc, mode); errno = saved_errno; return -1; } /* No need to call chmod_or_fchmod at this point, since the mode bits S_ISUID, S_ISGID, S_ISVTX are also stored in the ACL. */ return 0; #elif USE_ACL && HAVE_ACLSORT /* NonStop Kernel */ int count; struct acl entries[NACLENTRIES]; int ret; for (;;) { count = acl ((char *) src_name, ACL_CNT, NACLENTRIES, NULL); if (count < 0) { if (0) { count = 0; break; } else return -2; } if (count == 0) break; if (count > NACLENTRIES) /* If NACLENTRIES cannot be trusted, use dynamic memory allocation. */ abort (); if (acl ((char *) src_name, ACL_GET, count, entries) == count) break; /* Huh? The number of ACL entries changed since the last call. Repeat. */ } if (count == 0) return qset_acl (dst_name, dest_desc, mode); ret = acl ((char *) dst_name, ACL_SET, count, entries); if (ret < 0) { int saved_errno = errno; if (0) { if (!acl_nontrivial (count, entries)) return chmod_or_fchmod (dst_name, dest_desc, mode); } chmod_or_fchmod (dst_name, dest_desc, mode); errno = saved_errno; return -1; } if (mode & (S_ISUID | S_ISGID | S_ISVTX)) { /* We did not call chmod so far, and either the mode and the ACL are separate or special bits are to be set which don't fit into ACLs. */ return chmod_or_fchmod (dst_name, dest_desc, mode); } return 0; #else return qset_acl (dst_name, dest_desc, mode); #endif } /* Copy access control lists from one file to another. If SOURCE_DESC is a valid file descriptor, use file descriptor operations, else use filename based operations on SRC_NAME. Likewise for DEST_DESC and DST_NAME. If access control lists are not available, fchmod the target file to MODE. Also sets the non-permission bits of the destination file (S_ISUID, S_ISGID, S_ISVTX) to those from MODE if any are set. Return 0 if successful, otherwise output a diagnostic and return -1. */ int copy_acl (const char *src_name, int source_desc, const char *dst_name, int dest_desc, mode_t mode) { int ret = qcopy_acl (src_name, source_desc, dst_name, dest_desc, mode); switch (ret) { case -2: error (0, errno, "%s", quote (src_name)); return -1; case -1: error (0, errno, _("preserving permissions for %s"), quote (dst_name)); return -1; default: return 0; } }