libarchive-static 1.0.6 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/extconf.rb +2 -9
- data/ext/libarchive-0.1.1/ext/archive_read_support_compression.c +6 -6
- data/ext/libarchive-0.1.1/ext/archive_read_support_compression.o +0 -0
- data/ext/libarchive-0.1.1/ext/archive_read_support_format.o +0 -0
- data/ext/libarchive-0.1.1/ext/archive_write_open_rb_str.c +1 -1
- data/ext/libarchive-0.1.1/ext/archive_write_open_rb_str.o +0 -0
- data/ext/libarchive-0.1.1/ext/archive_write_set_compression.c +5 -5
- data/ext/libarchive-0.1.1/ext/archive_write_set_compression.o +0 -0
- data/ext/libarchive-0.1.1/ext/config.h +23 -0
- data/ext/libarchive-0.1.1/ext/config.log +230 -0
- data/ext/libarchive-0.1.1/ext/config.status +671 -0
- data/ext/libarchive-0.1.1/ext/libarchive.c +1 -1
- data/ext/libarchive-0.1.1/ext/libarchive.o +0 -0
- data/ext/libarchive-0.1.1/ext/libarchive_archive.c +7 -7
- data/ext/libarchive-0.1.1/ext/libarchive_archive.o +0 -0
- data/ext/libarchive-0.1.1/ext/libarchive_entry.c +6 -0
- data/ext/libarchive-0.1.1/ext/libarchive_entry.o +0 -0
- data/ext/libarchive-0.1.1/ext/libarchive_reader.c +6 -4
- data/ext/libarchive-0.1.1/ext/libarchive_reader.o +0 -0
- data/ext/libarchive-0.1.1/ext/libarchive_ruby.so +0 -0
- data/ext/libarchive-0.1.1/ext/libarchive_win32.h +1 -1
- data/ext/libarchive-0.1.1/ext/libarchive_writer.c +2 -2
- data/ext/libarchive-0.1.1/ext/libarchive_writer.o +0 -0
- data/ext/libarchive-3.6.2/Makefile.in +16892 -0
- data/ext/libarchive-3.6.2/build/autoconf/ax_append_compile_flags.m4 +67 -0
- data/ext/libarchive-3.6.2/build/autoconf/ax_append_flag.m4 +71 -0
- data/ext/libarchive-3.6.2/build/autoconf/ax_check_compile_flag.m4 +74 -0
- data/ext/libarchive-3.6.2/build/autoconf/ax_require_defined.m4 +37 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/build/autoconf/check_stdcall_func.m4 +0 -0
- data/ext/libarchive-3.6.2/build/autoconf/compile +348 -0
- data/ext/libarchive-3.6.2/build/autoconf/config.guess +1754 -0
- data/ext/libarchive-3.6.2/build/autoconf/config.rpath +696 -0
- data/ext/libarchive-3.6.2/build/autoconf/config.sub +1890 -0
- data/ext/libarchive-3.6.2/build/autoconf/depcomp +791 -0
- data/ext/libarchive-3.6.2/build/autoconf/iconv.m4 +271 -0
- data/ext/libarchive-3.6.2/build/autoconf/install-sh +541 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/build/autoconf/la_uid_t.m4 +0 -0
- data/ext/libarchive-3.6.2/build/autoconf/lib-ld.m4 +109 -0
- data/ext/libarchive-3.6.2/build/autoconf/lib-link.m4 +777 -0
- data/ext/libarchive-3.6.2/build/autoconf/lib-prefix.m4 +224 -0
- data/ext/libarchive-3.6.2/build/autoconf/ltmain.sh +11251 -0
- data/ext/libarchive-3.6.2/build/autoconf/m4_ax_compile_check_sizeof.m4 +115 -0
- data/ext/libarchive-3.6.2/build/autoconf/missing +215 -0
- data/ext/libarchive-3.6.2/build/autoconf/test-driver +153 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/build/pkgconfig/libarchive.pc.in +4 -1
- data/ext/libarchive-3.6.2/config.h.in +1504 -0
- data/ext/libarchive-3.6.2/configure +25558 -0
- data/ext/libarchive-3.6.2/libarchive/archive.h +1212 -0
- data/ext/libarchive-3.6.2/libarchive/archive_acl.c +2097 -0
- data/ext/libarchive-3.6.2/libarchive/archive_acl_private.h +83 -0
- data/ext/libarchive-3.6.2/libarchive/archive_blake2.h +197 -0
- data/ext/libarchive-3.6.2/libarchive/archive_blake2_impl.h +161 -0
- data/ext/libarchive-3.6.2/libarchive/archive_blake2s_ref.c +369 -0
- data/ext/libarchive-3.6.2/libarchive/archive_blake2sp_ref.c +361 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_check_magic.c +63 -22
- data/ext/libarchive-3.6.2/libarchive/archive_cmdline.c +227 -0
- data/ext/libarchive-3.6.2/libarchive/archive_cmdline_private.h +47 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_crc32.h +17 -0
- data/ext/libarchive-3.6.2/libarchive/archive_cryptor.c +534 -0
- data/ext/libarchive-3.6.2/libarchive/archive_cryptor_private.h +188 -0
- data/ext/libarchive-3.6.2/libarchive/archive_digest.c +1505 -0
- data/ext/libarchive-3.6.2/libarchive/archive_digest_private.h +416 -0
- data/ext/libarchive-3.6.2/libarchive/archive_disk_acl_darwin.c +559 -0
- data/ext/libarchive-3.6.2/libarchive/archive_disk_acl_freebsd.c +712 -0
- data/ext/libarchive-3.6.2/libarchive/archive_disk_acl_linux.c +760 -0
- data/ext/libarchive-3.6.2/libarchive/archive_disk_acl_sunos.c +824 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_endian.h +48 -15
- data/ext/libarchive-3.6.2/libarchive/archive_entry.c +2149 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry.h +305 -106
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_copy_bhfi.c +5 -4
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_copy_stat.c +9 -3
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_link_resolver.c +104 -62
- data/ext/libarchive-3.6.2/libarchive/archive_entry_locale.h +92 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_private.h +65 -49
- data/ext/libarchive-3.6.2/libarchive/archive_entry_sparse.c +156 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_stat.c +6 -6
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_strmode.c +1 -1
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_xattr.c +4 -6
- data/ext/libarchive-3.6.2/libarchive/archive_getdate.c +1165 -0
- data/ext/libarchive-3.6.2/libarchive/archive_getdate.h +39 -0
- data/ext/libarchive-3.6.2/libarchive/archive_hmac.c +334 -0
- data/ext/libarchive-3.6.2/libarchive/archive_hmac_private.h +117 -0
- data/ext/libarchive-3.6.2/libarchive/archive_match.c +1875 -0
- data/ext/libarchive-3.6.2/libarchive/archive_openssl_evp_private.h +53 -0
- data/ext/libarchive-3.6.2/libarchive/archive_openssl_hmac_private.h +54 -0
- data/ext/libarchive-3.6.2/libarchive/archive_options.c +218 -0
- data/ext/libarchive-3.6.2/libarchive/archive_options_private.h +51 -0
- data/ext/libarchive-3.6.2/libarchive/archive_pack_dev.c +337 -0
- data/ext/libarchive-3.6.2/libarchive/archive_pack_dev.h +49 -0
- data/ext/libarchive-3.6.2/libarchive/archive_pathmatch.c +463 -0
- data/ext/libarchive-3.6.2/libarchive/archive_pathmatch.h +52 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_platform.h +77 -9
- data/ext/libarchive-3.6.2/libarchive/archive_platform_acl.h +55 -0
- data/ext/libarchive-3.6.2/libarchive/archive_platform_xattr.h +47 -0
- data/ext/libarchive-3.6.2/libarchive/archive_ppmd7.c +1168 -0
- data/ext/libarchive-3.6.2/libarchive/archive_ppmd7_private.h +119 -0
- data/ext/libarchive-3.6.2/libarchive/archive_ppmd8.c +1287 -0
- data/ext/libarchive-3.6.2/libarchive/archive_ppmd8_private.h +148 -0
- data/ext/libarchive-3.6.2/libarchive/archive_ppmd_private.h +151 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_private.h +74 -18
- data/ext/libarchive-3.6.2/libarchive/archive_random.c +272 -0
- data/ext/libarchive-3.6.2/libarchive/archive_random_private.h +36 -0
- data/ext/libarchive-3.6.2/libarchive/archive_rb.c +709 -0
- data/ext/libarchive-3.6.2/libarchive/archive_rb.h +113 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read.c +1756 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_add_passphrase.c +190 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_append_filter.c +204 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_data_into_fd.c +64 -18
- data/ext/libarchive-3.6.2/libarchive/archive_read_disk_entry_from_file.c +1086 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_disk_posix.c +2732 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_disk_private.h +40 -4
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_disk_set_standard_lookup.c +21 -11
- data/ext/libarchive-3.6.2/libarchive/archive_read_disk_windows.c +2479 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_extract.c +60 -0
- data/ext/{libarchive-2.8.4/libarchive/archive_read_extract.c → libarchive-3.6.2/libarchive/archive_read_extract2.c} +34 -61
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_open_fd.c +70 -49
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_open_file.c +38 -23
- data/ext/libarchive-3.6.2/libarchive/archive_read_open_filename.c +586 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_open_memory.c +58 -28
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_private.h +127 -59
- data/ext/libarchive-3.6.2/libarchive/archive_read_set_format.c +117 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_set_options.c +133 -0
- data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_all.c → libarchive-3.6.2/libarchive/archive_read_support_filter_all.c} +35 -10
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_by_code.c +83 -0
- data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_bzip2.c → libarchive-3.6.2/libarchive/archive_read_support_filter_bzip2.c} +38 -26
- data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_compress.c → libarchive-3.6.2/libarchive/archive_read_support_filter_compress.c} +52 -44
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_grzip.c +112 -0
- data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_gzip.c → libarchive-3.6.2/libarchive/archive_read_support_filter_gzip.c} +108 -37
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_lrzip.c +122 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_lz4.c +742 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_lzop.c +499 -0
- data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_none.c → libarchive-3.6.2/libarchive/archive_read_support_filter_none.c} +15 -3
- data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_program.c → libarchive-3.6.2/libarchive/archive_read_support_filter_program.c} +114 -77
- data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_rpm.c → libarchive-3.6.2/libarchive/archive_read_support_filter_rpm.c} +31 -31
- data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_uu.c → libarchive-3.6.2/libarchive/archive_read_support_filter_uu.c} +141 -85
- data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_xz.c → libarchive-3.6.2/libarchive/archive_read_support_filter_xz.c} +369 -284
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_zstd.c +297 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_7zip.c +3900 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_all.c +89 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_ar.c +126 -72
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_by_code.c +92 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_cab.c +3228 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_cpio.c +1104 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_empty.c +14 -11
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_iso9660.c +990 -541
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_lha.c +2916 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_mtree.c +2150 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_rar.c +3797 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_rar5.c +4251 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_raw.c +38 -31
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_tar.c +1157 -629
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_warc.c +848 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_xar.c +439 -258
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_zip.c +4270 -0
- data/ext/libarchive-3.6.2/libarchive/archive_string.c +4240 -0
- data/ext/libarchive-3.6.2/libarchive/archive_string.h +243 -0
- data/ext/libarchive-3.6.2/libarchive/archive_string_composition.h +2292 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_string_sprintf.c +44 -16
- data/ext/libarchive-3.6.2/libarchive/archive_util.c +655 -0
- data/ext/libarchive-3.6.2/libarchive/archive_version_details.c +151 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_virtual.c +85 -16
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_windows.c +214 -541
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_windows.h +74 -106
- data/ext/libarchive-3.6.2/libarchive/archive_write.c +828 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter.c +72 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_b64encode.c +304 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_by_name.c +77 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_bzip2.c +401 -0
- data/ext/{libarchive-2.8.4/libarchive/archive_write_set_compression_compress.c → libarchive-3.6.2/libarchive/archive_write_add_filter_compress.c} +86 -131
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_grzip.c +135 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_gzip.c +442 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_lrzip.c +197 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_lz4.c +700 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_lzop.c +478 -0
- data/ext/{libarchive-2.8.4/libarchive/archive_read_support_format_all.c → libarchive-3.6.2/libarchive/archive_write_add_filter_none.c} +11 -11
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_program.c +391 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_uuencode.c +295 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_xz.c +545 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_zstd.c +418 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_disk_posix.c +4711 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_disk_private.h +9 -2
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_disk_set_standard_lookup.c +30 -29
- data/ext/libarchive-3.6.2/libarchive/archive_write_disk_windows.c +2842 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_open_fd.c +15 -10
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_open_file.c +15 -9
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_open_filename.c +128 -20
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_open_memory.c +7 -18
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_private.h +72 -29
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format.c +56 -3
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_7zip.c +2322 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_ar.c +54 -34
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_by_name.c +20 -2
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_cpio.c +11 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_cpio_binary.c +610 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_cpio_newc.c +457 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_cpio_odc.c +500 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_filter_by_ext.c +142 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_gnutar.c +755 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_iso9660.c +8165 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_mtree.c +2217 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_pax.c +1049 -387
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_private.h +42 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_raw.c +125 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_shar.c +62 -47
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_ustar.c +279 -108
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_v7tar.c +638 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_warc.c +453 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_xar.c +3259 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_zip.c +1704 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_options.c +130 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_passphrase.c +95 -0
- data/ext/libarchive-3.6.2/libarchive/archive_xxhash.h +48 -0
- data/ext/libarchive-3.6.2/libarchive/config_freebsd.h +271 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/filter_fork.h +10 -5
- data/ext/{libarchive-2.8.4/libarchive/filter_fork.c → libarchive-3.6.2/libarchive/filter_fork_posix.c} +98 -19
- data/ext/libarchive-3.6.2/libarchive/filter_fork_windows.c +236 -0
- data/ext/libarchive-3.6.2/libarchive/xxhash.c +525 -0
- data/ext/libarchive-static-makefile +144 -80
- data/ext/libarchive-static-wrapper-makefile +1 -1
- data/ext/zlib-1.2.13/Makefile.in +404 -0
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/adler32.c +51 -34
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/compress.c +27 -21
- data/ext/zlib-1.2.13/configure +922 -0
- data/ext/zlib-1.2.13/crc32.c +1125 -0
- data/ext/zlib-1.2.13/crc32.h +9446 -0
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/deflate.c +842 -459
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/deflate.h +37 -33
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/gzclose.c +0 -0
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/gzguts.h +103 -16
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/gzlib.c +155 -53
- data/ext/zlib-1.2.13/gzread.c +650 -0
- data/ext/zlib-1.2.13/gzwrite.c +677 -0
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/infback.c +24 -12
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/inffast.c +49 -66
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/inffast.h +0 -0
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/inffixed.h +3 -3
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/inflate.c +209 -94
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/inflate.h +9 -5
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/inftrees.c +24 -50
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/inftrees.h +1 -1
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/trees.c +135 -198
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/trees.h +0 -0
- data/ext/zlib-1.2.13/uncompr.c +93 -0
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/zconf.h +182 -63
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/zlib.h +617 -295
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/zutil.c +50 -41
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/zutil.h +83 -82
- metadata +241 -133
- data/ext/libarchive-0.1.1/libarchive.c +0 -1762
- data/ext/libarchive-2.8.4/Makefile.in +0 -7076
- data/ext/libarchive-2.8.4/build/autoconf/compile +0 -143
- data/ext/libarchive-2.8.4/build/autoconf/config.guess +0 -1502
- data/ext/libarchive-2.8.4/build/autoconf/config.sub +0 -1708
- data/ext/libarchive-2.8.4/build/autoconf/depcomp +0 -630
- data/ext/libarchive-2.8.4/build/autoconf/install-sh +0 -291
- data/ext/libarchive-2.8.4/build/autoconf/ltmain.sh +0 -8406
- data/ext/libarchive-2.8.4/build/autoconf/missing +0 -376
- data/ext/libarchive-2.8.4/config.h.in +0 -772
- data/ext/libarchive-2.8.4/configure +0 -17916
- data/ext/libarchive-2.8.4/libarchive/archive.h +0 -741
- data/ext/libarchive-2.8.4/libarchive/archive_entry.c +0 -2202
- data/ext/libarchive-2.8.4/libarchive/archive_hash.h +0 -281
- data/ext/libarchive-2.8.4/libarchive/archive_read.c +0 -1249
- data/ext/libarchive-2.8.4/libarchive/archive_read_disk.c +0 -198
- data/ext/libarchive-2.8.4/libarchive/archive_read_disk_entry_from_file.c +0 -570
- data/ext/libarchive-2.8.4/libarchive/archive_read_open_filename.c +0 -272
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_cpio.c +0 -777
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_mtree.c +0 -1304
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_zip.c +0 -903
- data/ext/libarchive-2.8.4/libarchive/archive_string.c +0 -453
- data/ext/libarchive-2.8.4/libarchive/archive_string.h +0 -148
- data/ext/libarchive-2.8.4/libarchive/archive_util.c +0 -391
- data/ext/libarchive-2.8.4/libarchive/archive_write.c +0 -466
- data/ext/libarchive-2.8.4/libarchive/archive_write_disk.c +0 -2628
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_bzip2.c +0 -408
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_gzip.c +0 -477
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_none.c +0 -257
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_program.c +0 -347
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_xz.c +0 -438
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_cpio.c +0 -344
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_cpio_newc.c +0 -295
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_mtree.c +0 -1050
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_zip.c +0 -667
- data/ext/libarchive-2.8.4/libarchive/config_freebsd.h +0 -154
- data/ext/libarchive-2.8.4/libarchive/filter_fork_windows.c +0 -113
- data/ext/zlib-1.2.5/Makefile.in +0 -257
- data/ext/zlib-1.2.5/configure +0 -596
- data/ext/zlib-1.2.5/crc32.c +0 -442
- data/ext/zlib-1.2.5/crc32.h +0 -441
- data/ext/zlib-1.2.5/example.c +0 -565
- data/ext/zlib-1.2.5/gzread.c +0 -653
- data/ext/zlib-1.2.5/gzwrite.c +0 -531
- data/ext/zlib-1.2.5/minigzip.c +0 -440
- data/ext/zlib-1.2.5/uncompr.c +0 -59
|
@@ -0,0 +1,2097 @@
|
|
|
1
|
+
/*-
|
|
2
|
+
* Copyright (c) 2003-2010 Tim Kientzle
|
|
3
|
+
* Copyright (c) 2016 Martin Matuska
|
|
4
|
+
* All rights reserved.
|
|
5
|
+
*
|
|
6
|
+
* Redistribution and use in source and binary forms, with or without
|
|
7
|
+
* modification, are permitted provided that the following conditions
|
|
8
|
+
* are met:
|
|
9
|
+
* 1. Redistributions of source code must retain the above copyright
|
|
10
|
+
* notice, this list of conditions and the following disclaimer.
|
|
11
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
|
12
|
+
* notice, this list of conditions and the following disclaimer in the
|
|
13
|
+
* documentation and/or other materials provided with the distribution.
|
|
14
|
+
*
|
|
15
|
+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
|
16
|
+
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
17
|
+
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
18
|
+
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
19
|
+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
20
|
+
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
21
|
+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
22
|
+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
23
|
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
24
|
+
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
#include "archive_platform.h"
|
|
28
|
+
__FBSDID("$FreeBSD$");
|
|
29
|
+
|
|
30
|
+
#ifdef HAVE_ERRNO_H
|
|
31
|
+
#include <errno.h>
|
|
32
|
+
#endif
|
|
33
|
+
#ifdef HAVE_LIMITS_H
|
|
34
|
+
#include <limits.h>
|
|
35
|
+
#endif
|
|
36
|
+
#ifdef HAVE_WCHAR_H
|
|
37
|
+
#include <wchar.h>
|
|
38
|
+
#endif
|
|
39
|
+
|
|
40
|
+
#include "archive_acl_private.h"
|
|
41
|
+
#include "archive_entry.h"
|
|
42
|
+
#include "archive_private.h"
|
|
43
|
+
|
|
44
|
+
#undef max
|
|
45
|
+
#define max(a, b) ((a)>(b)?(a):(b))
|
|
46
|
+
|
|
47
|
+
#ifndef HAVE_WMEMCMP
|
|
48
|
+
/* Good enough for simple equality testing, but not for sorting. */
|
|
49
|
+
#define wmemcmp(a,b,i) memcmp((a), (b), (i) * sizeof(wchar_t))
|
|
50
|
+
#endif
|
|
51
|
+
|
|
52
|
+
static int acl_special(struct archive_acl *acl,
|
|
53
|
+
int type, int permset, int tag);
|
|
54
|
+
static struct archive_acl_entry *acl_new_entry(struct archive_acl *acl,
|
|
55
|
+
int type, int permset, int tag, int id);
|
|
56
|
+
static int archive_acl_add_entry_len_l(struct archive_acl *acl,
|
|
57
|
+
int type, int permset, int tag, int id, const char *name,
|
|
58
|
+
size_t len, struct archive_string_conv *sc);
|
|
59
|
+
static int archive_acl_text_want_type(struct archive_acl *acl, int flags);
|
|
60
|
+
static ssize_t archive_acl_text_len(struct archive_acl *acl, int want_type,
|
|
61
|
+
int flags, int wide, struct archive *a,
|
|
62
|
+
struct archive_string_conv *sc);
|
|
63
|
+
static int isint_w(const wchar_t *start, const wchar_t *end, int *result);
|
|
64
|
+
static int ismode_w(const wchar_t *start, const wchar_t *end, int *result);
|
|
65
|
+
static int is_nfs4_flags_w(const wchar_t *start, const wchar_t *end,
|
|
66
|
+
int *result);
|
|
67
|
+
static int is_nfs4_perms_w(const wchar_t *start, const wchar_t *end,
|
|
68
|
+
int *result);
|
|
69
|
+
static void next_field_w(const wchar_t **wp, const wchar_t **start,
|
|
70
|
+
const wchar_t **end, wchar_t *sep);
|
|
71
|
+
static void append_entry_w(wchar_t **wp, const wchar_t *prefix, int type,
|
|
72
|
+
int tag, int flags, const wchar_t *wname, int perm, int id);
|
|
73
|
+
static void append_id_w(wchar_t **wp, int id);
|
|
74
|
+
static int isint(const char *start, const char *end, int *result);
|
|
75
|
+
static int ismode(const char *start, const char *end, int *result);
|
|
76
|
+
static int is_nfs4_flags(const char *start, const char *end,
|
|
77
|
+
int *result);
|
|
78
|
+
static int is_nfs4_perms(const char *start, const char *end,
|
|
79
|
+
int *result);
|
|
80
|
+
static void next_field(const char **p, const char **start,
|
|
81
|
+
const char **end, char *sep);
|
|
82
|
+
static void append_entry(char **p, const char *prefix, int type,
|
|
83
|
+
int tag, int flags, const char *name, int perm, int id);
|
|
84
|
+
static void append_id(char **p, int id);
|
|
85
|
+
|
|
86
|
+
static const struct {
|
|
87
|
+
const int perm;
|
|
88
|
+
const char c;
|
|
89
|
+
const wchar_t wc;
|
|
90
|
+
} nfsv4_acl_perm_map[] = {
|
|
91
|
+
{ ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, 'r',
|
|
92
|
+
L'r' },
|
|
93
|
+
{ ARCHIVE_ENTRY_ACL_WRITE_DATA | ARCHIVE_ENTRY_ACL_ADD_FILE, 'w',
|
|
94
|
+
L'w' },
|
|
95
|
+
{ ARCHIVE_ENTRY_ACL_EXECUTE, 'x', L'x' },
|
|
96
|
+
{ ARCHIVE_ENTRY_ACL_APPEND_DATA | ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY,
|
|
97
|
+
'p', L'p' },
|
|
98
|
+
{ ARCHIVE_ENTRY_ACL_DELETE, 'd', L'd' },
|
|
99
|
+
{ ARCHIVE_ENTRY_ACL_DELETE_CHILD, 'D', L'D' },
|
|
100
|
+
{ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, 'a', L'a' },
|
|
101
|
+
{ ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, 'A', L'A' },
|
|
102
|
+
{ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, 'R', L'R' },
|
|
103
|
+
{ ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, 'W', L'W' },
|
|
104
|
+
{ ARCHIVE_ENTRY_ACL_READ_ACL, 'c', L'c' },
|
|
105
|
+
{ ARCHIVE_ENTRY_ACL_WRITE_ACL, 'C', L'C' },
|
|
106
|
+
{ ARCHIVE_ENTRY_ACL_WRITE_OWNER, 'o', L'o' },
|
|
107
|
+
{ ARCHIVE_ENTRY_ACL_SYNCHRONIZE, 's', L's' }
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
static const int nfsv4_acl_perm_map_size = (int)(sizeof(nfsv4_acl_perm_map) /
|
|
111
|
+
sizeof(nfsv4_acl_perm_map[0]));
|
|
112
|
+
|
|
113
|
+
static const struct {
|
|
114
|
+
const int perm;
|
|
115
|
+
const char c;
|
|
116
|
+
const wchar_t wc;
|
|
117
|
+
} nfsv4_acl_flag_map[] = {
|
|
118
|
+
{ ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, 'f', L'f' },
|
|
119
|
+
{ ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, 'd', L'd' },
|
|
120
|
+
{ ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, 'i', L'i' },
|
|
121
|
+
{ ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, 'n', L'n' },
|
|
122
|
+
{ ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, 'S', L'S' },
|
|
123
|
+
{ ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, 'F', L'F' },
|
|
124
|
+
{ ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, 'I', L'I' }
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
static const int nfsv4_acl_flag_map_size = (int)(sizeof(nfsv4_acl_flag_map) /
|
|
128
|
+
sizeof(nfsv4_acl_flag_map[0]));
|
|
129
|
+
|
|
130
|
+
void
|
|
131
|
+
archive_acl_clear(struct archive_acl *acl)
|
|
132
|
+
{
|
|
133
|
+
struct archive_acl_entry *ap;
|
|
134
|
+
|
|
135
|
+
while (acl->acl_head != NULL) {
|
|
136
|
+
ap = acl->acl_head->next;
|
|
137
|
+
archive_mstring_clean(&acl->acl_head->name);
|
|
138
|
+
free(acl->acl_head);
|
|
139
|
+
acl->acl_head = ap;
|
|
140
|
+
}
|
|
141
|
+
free(acl->acl_text_w);
|
|
142
|
+
acl->acl_text_w = NULL;
|
|
143
|
+
free(acl->acl_text);
|
|
144
|
+
acl->acl_text = NULL;
|
|
145
|
+
acl->acl_p = NULL;
|
|
146
|
+
acl->acl_types = 0;
|
|
147
|
+
acl->acl_state = 0; /* Not counting. */
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
void
|
|
151
|
+
archive_acl_copy(struct archive_acl *dest, struct archive_acl *src)
|
|
152
|
+
{
|
|
153
|
+
struct archive_acl_entry *ap, *ap2;
|
|
154
|
+
|
|
155
|
+
archive_acl_clear(dest);
|
|
156
|
+
|
|
157
|
+
dest->mode = src->mode;
|
|
158
|
+
ap = src->acl_head;
|
|
159
|
+
while (ap != NULL) {
|
|
160
|
+
ap2 = acl_new_entry(dest,
|
|
161
|
+
ap->type, ap->permset, ap->tag, ap->id);
|
|
162
|
+
if (ap2 != NULL)
|
|
163
|
+
archive_mstring_copy(&ap2->name, &ap->name);
|
|
164
|
+
ap = ap->next;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
int
|
|
169
|
+
archive_acl_add_entry(struct archive_acl *acl,
|
|
170
|
+
int type, int permset, int tag, int id, const char *name)
|
|
171
|
+
{
|
|
172
|
+
struct archive_acl_entry *ap;
|
|
173
|
+
|
|
174
|
+
if (acl_special(acl, type, permset, tag) == 0)
|
|
175
|
+
return ARCHIVE_OK;
|
|
176
|
+
ap = acl_new_entry(acl, type, permset, tag, id);
|
|
177
|
+
if (ap == NULL) {
|
|
178
|
+
/* XXX Error XXX */
|
|
179
|
+
return ARCHIVE_FAILED;
|
|
180
|
+
}
|
|
181
|
+
if (name != NULL && *name != '\0')
|
|
182
|
+
archive_mstring_copy_mbs(&ap->name, name);
|
|
183
|
+
else
|
|
184
|
+
archive_mstring_clean(&ap->name);
|
|
185
|
+
return ARCHIVE_OK;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
int
|
|
189
|
+
archive_acl_add_entry_w_len(struct archive_acl *acl,
|
|
190
|
+
int type, int permset, int tag, int id, const wchar_t *name, size_t len)
|
|
191
|
+
{
|
|
192
|
+
struct archive_acl_entry *ap;
|
|
193
|
+
|
|
194
|
+
if (acl_special(acl, type, permset, tag) == 0)
|
|
195
|
+
return ARCHIVE_OK;
|
|
196
|
+
ap = acl_new_entry(acl, type, permset, tag, id);
|
|
197
|
+
if (ap == NULL) {
|
|
198
|
+
/* XXX Error XXX */
|
|
199
|
+
return ARCHIVE_FAILED;
|
|
200
|
+
}
|
|
201
|
+
if (name != NULL && *name != L'\0' && len > 0)
|
|
202
|
+
archive_mstring_copy_wcs_len(&ap->name, name, len);
|
|
203
|
+
else
|
|
204
|
+
archive_mstring_clean(&ap->name);
|
|
205
|
+
return ARCHIVE_OK;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
static int
|
|
209
|
+
archive_acl_add_entry_len_l(struct archive_acl *acl,
|
|
210
|
+
int type, int permset, int tag, int id, const char *name, size_t len,
|
|
211
|
+
struct archive_string_conv *sc)
|
|
212
|
+
{
|
|
213
|
+
struct archive_acl_entry *ap;
|
|
214
|
+
int r;
|
|
215
|
+
|
|
216
|
+
if (acl_special(acl, type, permset, tag) == 0)
|
|
217
|
+
return ARCHIVE_OK;
|
|
218
|
+
ap = acl_new_entry(acl, type, permset, tag, id);
|
|
219
|
+
if (ap == NULL) {
|
|
220
|
+
/* XXX Error XXX */
|
|
221
|
+
return ARCHIVE_FAILED;
|
|
222
|
+
}
|
|
223
|
+
if (name != NULL && *name != '\0' && len > 0) {
|
|
224
|
+
r = archive_mstring_copy_mbs_len_l(&ap->name, name, len, sc);
|
|
225
|
+
} else {
|
|
226
|
+
r = 0;
|
|
227
|
+
archive_mstring_clean(&ap->name);
|
|
228
|
+
}
|
|
229
|
+
if (r == 0)
|
|
230
|
+
return (ARCHIVE_OK);
|
|
231
|
+
else if (errno == ENOMEM)
|
|
232
|
+
return (ARCHIVE_FATAL);
|
|
233
|
+
else
|
|
234
|
+
return (ARCHIVE_WARN);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/*
|
|
238
|
+
* If this ACL entry is part of the standard POSIX permissions set,
|
|
239
|
+
* store the permissions in the stat structure and return zero.
|
|
240
|
+
*/
|
|
241
|
+
static int
|
|
242
|
+
acl_special(struct archive_acl *acl, int type, int permset, int tag)
|
|
243
|
+
{
|
|
244
|
+
if (type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS
|
|
245
|
+
&& ((permset & ~007) == 0)) {
|
|
246
|
+
switch (tag) {
|
|
247
|
+
case ARCHIVE_ENTRY_ACL_USER_OBJ:
|
|
248
|
+
acl->mode &= ~0700;
|
|
249
|
+
acl->mode |= (permset & 7) << 6;
|
|
250
|
+
return (0);
|
|
251
|
+
case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
|
|
252
|
+
acl->mode &= ~0070;
|
|
253
|
+
acl->mode |= (permset & 7) << 3;
|
|
254
|
+
return (0);
|
|
255
|
+
case ARCHIVE_ENTRY_ACL_OTHER:
|
|
256
|
+
acl->mode &= ~0007;
|
|
257
|
+
acl->mode |= permset & 7;
|
|
258
|
+
return (0);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return (1);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/*
|
|
265
|
+
* Allocate and populate a new ACL entry with everything but the
|
|
266
|
+
* name.
|
|
267
|
+
*/
|
|
268
|
+
static struct archive_acl_entry *
|
|
269
|
+
acl_new_entry(struct archive_acl *acl,
|
|
270
|
+
int type, int permset, int tag, int id)
|
|
271
|
+
{
|
|
272
|
+
struct archive_acl_entry *ap, *aq;
|
|
273
|
+
|
|
274
|
+
/* Type argument must be a valid NFS4 or POSIX.1e type.
|
|
275
|
+
* The type must agree with anything already set and
|
|
276
|
+
* the permset must be compatible. */
|
|
277
|
+
if (type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
|
|
278
|
+
if (acl->acl_types & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
|
|
279
|
+
return (NULL);
|
|
280
|
+
}
|
|
281
|
+
if (permset &
|
|
282
|
+
~(ARCHIVE_ENTRY_ACL_PERMS_NFS4
|
|
283
|
+
| ARCHIVE_ENTRY_ACL_INHERITANCE_NFS4)) {
|
|
284
|
+
return (NULL);
|
|
285
|
+
}
|
|
286
|
+
} else if (type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) {
|
|
287
|
+
if (acl->acl_types & ~ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) {
|
|
288
|
+
return (NULL);
|
|
289
|
+
}
|
|
290
|
+
if (permset & ~ARCHIVE_ENTRY_ACL_PERMS_POSIX1E) {
|
|
291
|
+
return (NULL);
|
|
292
|
+
}
|
|
293
|
+
} else {
|
|
294
|
+
return (NULL);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/* Verify the tag is valid and compatible with NFS4 or POSIX.1e. */
|
|
298
|
+
switch (tag) {
|
|
299
|
+
case ARCHIVE_ENTRY_ACL_USER:
|
|
300
|
+
case ARCHIVE_ENTRY_ACL_USER_OBJ:
|
|
301
|
+
case ARCHIVE_ENTRY_ACL_GROUP:
|
|
302
|
+
case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
|
|
303
|
+
/* Tags valid in both NFS4 and POSIX.1e */
|
|
304
|
+
break;
|
|
305
|
+
case ARCHIVE_ENTRY_ACL_MASK:
|
|
306
|
+
case ARCHIVE_ENTRY_ACL_OTHER:
|
|
307
|
+
/* Tags valid only in POSIX.1e. */
|
|
308
|
+
if (type & ~ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) {
|
|
309
|
+
return (NULL);
|
|
310
|
+
}
|
|
311
|
+
break;
|
|
312
|
+
case ARCHIVE_ENTRY_ACL_EVERYONE:
|
|
313
|
+
/* Tags valid only in NFS4. */
|
|
314
|
+
if (type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
|
|
315
|
+
return (NULL);
|
|
316
|
+
}
|
|
317
|
+
break;
|
|
318
|
+
default:
|
|
319
|
+
/* No other values are valid. */
|
|
320
|
+
return (NULL);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
free(acl->acl_text_w);
|
|
324
|
+
acl->acl_text_w = NULL;
|
|
325
|
+
free(acl->acl_text);
|
|
326
|
+
acl->acl_text = NULL;
|
|
327
|
+
|
|
328
|
+
/*
|
|
329
|
+
* If there's a matching entry already in the list, overwrite it.
|
|
330
|
+
* NFSv4 entries may be repeated and are not overwritten.
|
|
331
|
+
*
|
|
332
|
+
* TODO: compare names of no id is provided (needs more rework)
|
|
333
|
+
*/
|
|
334
|
+
ap = acl->acl_head;
|
|
335
|
+
aq = NULL;
|
|
336
|
+
while (ap != NULL) {
|
|
337
|
+
if (((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0) &&
|
|
338
|
+
ap->type == type && ap->tag == tag && ap->id == id) {
|
|
339
|
+
if (id != -1 || (tag != ARCHIVE_ENTRY_ACL_USER &&
|
|
340
|
+
tag != ARCHIVE_ENTRY_ACL_GROUP)) {
|
|
341
|
+
ap->permset = permset;
|
|
342
|
+
return (ap);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
aq = ap;
|
|
346
|
+
ap = ap->next;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/* Add a new entry to the end of the list. */
|
|
350
|
+
ap = (struct archive_acl_entry *)calloc(1, sizeof(*ap));
|
|
351
|
+
if (ap == NULL)
|
|
352
|
+
return (NULL);
|
|
353
|
+
if (aq == NULL)
|
|
354
|
+
acl->acl_head = ap;
|
|
355
|
+
else
|
|
356
|
+
aq->next = ap;
|
|
357
|
+
ap->type = type;
|
|
358
|
+
ap->tag = tag;
|
|
359
|
+
ap->id = id;
|
|
360
|
+
ap->permset = permset;
|
|
361
|
+
acl->acl_types |= type;
|
|
362
|
+
return (ap);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/*
|
|
366
|
+
* Return a count of entries matching "want_type".
|
|
367
|
+
*/
|
|
368
|
+
int
|
|
369
|
+
archive_acl_count(struct archive_acl *acl, int want_type)
|
|
370
|
+
{
|
|
371
|
+
int count;
|
|
372
|
+
struct archive_acl_entry *ap;
|
|
373
|
+
|
|
374
|
+
count = 0;
|
|
375
|
+
ap = acl->acl_head;
|
|
376
|
+
while (ap != NULL) {
|
|
377
|
+
if ((ap->type & want_type) != 0)
|
|
378
|
+
count++;
|
|
379
|
+
ap = ap->next;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (count > 0 && ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0))
|
|
383
|
+
count += 3;
|
|
384
|
+
return (count);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/*
|
|
388
|
+
* Return a bitmask of stored ACL types in an ACL list
|
|
389
|
+
*/
|
|
390
|
+
int
|
|
391
|
+
archive_acl_types(struct archive_acl *acl)
|
|
392
|
+
{
|
|
393
|
+
return (acl->acl_types);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/*
|
|
397
|
+
* Prepare for reading entries from the ACL data. Returns a count
|
|
398
|
+
* of entries matching "want_type", or zero if there are no
|
|
399
|
+
* non-extended ACL entries of that type.
|
|
400
|
+
*/
|
|
401
|
+
int
|
|
402
|
+
archive_acl_reset(struct archive_acl *acl, int want_type)
|
|
403
|
+
{
|
|
404
|
+
int count, cutoff;
|
|
405
|
+
|
|
406
|
+
count = archive_acl_count(acl, want_type);
|
|
407
|
+
|
|
408
|
+
/*
|
|
409
|
+
* If the only entries are the three standard ones,
|
|
410
|
+
* then don't return any ACL data. (In this case,
|
|
411
|
+
* client can just use chmod(2) to set permissions.)
|
|
412
|
+
*/
|
|
413
|
+
if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)
|
|
414
|
+
cutoff = 3;
|
|
415
|
+
else
|
|
416
|
+
cutoff = 0;
|
|
417
|
+
|
|
418
|
+
if (count > cutoff)
|
|
419
|
+
acl->acl_state = ARCHIVE_ENTRY_ACL_USER_OBJ;
|
|
420
|
+
else
|
|
421
|
+
acl->acl_state = 0;
|
|
422
|
+
acl->acl_p = acl->acl_head;
|
|
423
|
+
return (count);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
/*
|
|
428
|
+
* Return the next ACL entry in the list. Fake entries for the
|
|
429
|
+
* standard permissions and include them in the returned list.
|
|
430
|
+
*/
|
|
431
|
+
int
|
|
432
|
+
archive_acl_next(struct archive *a, struct archive_acl *acl, int want_type,
|
|
433
|
+
int *type, int *permset, int *tag, int *id, const char **name)
|
|
434
|
+
{
|
|
435
|
+
*name = NULL;
|
|
436
|
+
*id = -1;
|
|
437
|
+
|
|
438
|
+
/*
|
|
439
|
+
* The acl_state is either zero (no entries available), -1
|
|
440
|
+
* (reading from list), or an entry type (retrieve that type
|
|
441
|
+
* from ae_stat.aest_mode).
|
|
442
|
+
*/
|
|
443
|
+
if (acl->acl_state == 0)
|
|
444
|
+
return (ARCHIVE_WARN);
|
|
445
|
+
|
|
446
|
+
/* The first three access entries are special. */
|
|
447
|
+
if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
|
|
448
|
+
switch (acl->acl_state) {
|
|
449
|
+
case ARCHIVE_ENTRY_ACL_USER_OBJ:
|
|
450
|
+
*permset = (acl->mode >> 6) & 7;
|
|
451
|
+
*type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
|
|
452
|
+
*tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
|
|
453
|
+
acl->acl_state = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
|
|
454
|
+
return (ARCHIVE_OK);
|
|
455
|
+
case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
|
|
456
|
+
*permset = (acl->mode >> 3) & 7;
|
|
457
|
+
*type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
|
|
458
|
+
*tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
|
|
459
|
+
acl->acl_state = ARCHIVE_ENTRY_ACL_OTHER;
|
|
460
|
+
return (ARCHIVE_OK);
|
|
461
|
+
case ARCHIVE_ENTRY_ACL_OTHER:
|
|
462
|
+
*permset = acl->mode & 7;
|
|
463
|
+
*type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
|
|
464
|
+
*tag = ARCHIVE_ENTRY_ACL_OTHER;
|
|
465
|
+
acl->acl_state = -1;
|
|
466
|
+
acl->acl_p = acl->acl_head;
|
|
467
|
+
return (ARCHIVE_OK);
|
|
468
|
+
default:
|
|
469
|
+
break;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
while (acl->acl_p != NULL && (acl->acl_p->type & want_type) == 0)
|
|
474
|
+
acl->acl_p = acl->acl_p->next;
|
|
475
|
+
if (acl->acl_p == NULL) {
|
|
476
|
+
acl->acl_state = 0;
|
|
477
|
+
*type = 0;
|
|
478
|
+
*permset = 0;
|
|
479
|
+
*tag = 0;
|
|
480
|
+
*id = -1;
|
|
481
|
+
*name = NULL;
|
|
482
|
+
return (ARCHIVE_EOF); /* End of ACL entries. */
|
|
483
|
+
}
|
|
484
|
+
*type = acl->acl_p->type;
|
|
485
|
+
*permset = acl->acl_p->permset;
|
|
486
|
+
*tag = acl->acl_p->tag;
|
|
487
|
+
*id = acl->acl_p->id;
|
|
488
|
+
if (archive_mstring_get_mbs(a, &acl->acl_p->name, name) != 0) {
|
|
489
|
+
if (errno == ENOMEM)
|
|
490
|
+
return (ARCHIVE_FATAL);
|
|
491
|
+
*name = NULL;
|
|
492
|
+
}
|
|
493
|
+
acl->acl_p = acl->acl_p->next;
|
|
494
|
+
return (ARCHIVE_OK);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/*
|
|
498
|
+
* Determine what type of ACL do we want
|
|
499
|
+
*/
|
|
500
|
+
static int
|
|
501
|
+
archive_acl_text_want_type(struct archive_acl *acl, int flags)
|
|
502
|
+
{
|
|
503
|
+
int want_type;
|
|
504
|
+
|
|
505
|
+
/* Check if ACL is NFSv4 */
|
|
506
|
+
if ((acl->acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
|
|
507
|
+
/* NFSv4 should never mix with POSIX.1e */
|
|
508
|
+
if ((acl->acl_types & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0)
|
|
509
|
+
return (0);
|
|
510
|
+
else
|
|
511
|
+
return (ARCHIVE_ENTRY_ACL_TYPE_NFS4);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/* Now deal with POSIX.1e ACLs */
|
|
515
|
+
|
|
516
|
+
want_type = 0;
|
|
517
|
+
if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)
|
|
518
|
+
want_type |= ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
|
|
519
|
+
if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
|
|
520
|
+
want_type |= ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
|
|
521
|
+
|
|
522
|
+
/* By default we want both access and default ACLs */
|
|
523
|
+
if (want_type == 0)
|
|
524
|
+
return (ARCHIVE_ENTRY_ACL_TYPE_POSIX1E);
|
|
525
|
+
|
|
526
|
+
return (want_type);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/*
|
|
530
|
+
* Calculate ACL text string length
|
|
531
|
+
*/
|
|
532
|
+
static ssize_t
|
|
533
|
+
archive_acl_text_len(struct archive_acl *acl, int want_type, int flags,
|
|
534
|
+
int wide, struct archive *a, struct archive_string_conv *sc) {
|
|
535
|
+
struct archive_acl_entry *ap;
|
|
536
|
+
const char *name;
|
|
537
|
+
const wchar_t *wname;
|
|
538
|
+
int count, idlen, tmp, r;
|
|
539
|
+
ssize_t length;
|
|
540
|
+
size_t len;
|
|
541
|
+
|
|
542
|
+
count = 0;
|
|
543
|
+
length = 0;
|
|
544
|
+
for (ap = acl->acl_head; ap != NULL; ap = ap->next) {
|
|
545
|
+
if ((ap->type & want_type) == 0)
|
|
546
|
+
continue;
|
|
547
|
+
/*
|
|
548
|
+
* Filemode-mapping ACL entries are stored exclusively in
|
|
549
|
+
* ap->mode so they should not be in the list
|
|
550
|
+
*/
|
|
551
|
+
if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS)
|
|
552
|
+
&& (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ
|
|
553
|
+
|| ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ
|
|
554
|
+
|| ap->tag == ARCHIVE_ENTRY_ACL_OTHER))
|
|
555
|
+
continue;
|
|
556
|
+
count++;
|
|
557
|
+
if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0
|
|
558
|
+
&& (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
|
|
559
|
+
length += 8; /* "default:" */
|
|
560
|
+
switch (ap->tag) {
|
|
561
|
+
case ARCHIVE_ENTRY_ACL_USER_OBJ:
|
|
562
|
+
if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
|
|
563
|
+
length += 6; /* "owner@" */
|
|
564
|
+
break;
|
|
565
|
+
}
|
|
566
|
+
/* FALLTHROUGH */
|
|
567
|
+
case ARCHIVE_ENTRY_ACL_USER:
|
|
568
|
+
case ARCHIVE_ENTRY_ACL_MASK:
|
|
569
|
+
length += 4; /* "user", "mask" */
|
|
570
|
+
break;
|
|
571
|
+
case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
|
|
572
|
+
if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
|
|
573
|
+
length += 6; /* "group@" */
|
|
574
|
+
break;
|
|
575
|
+
}
|
|
576
|
+
/* FALLTHROUGH */
|
|
577
|
+
case ARCHIVE_ENTRY_ACL_GROUP:
|
|
578
|
+
case ARCHIVE_ENTRY_ACL_OTHER:
|
|
579
|
+
length += 5; /* "group", "other" */
|
|
580
|
+
break;
|
|
581
|
+
case ARCHIVE_ENTRY_ACL_EVERYONE:
|
|
582
|
+
length += 9; /* "everyone@" */
|
|
583
|
+
break;
|
|
584
|
+
}
|
|
585
|
+
length += 1; /* colon after tag */
|
|
586
|
+
if (ap->tag == ARCHIVE_ENTRY_ACL_USER ||
|
|
587
|
+
ap->tag == ARCHIVE_ENTRY_ACL_GROUP) {
|
|
588
|
+
if (wide) {
|
|
589
|
+
r = archive_mstring_get_wcs(a, &ap->name,
|
|
590
|
+
&wname);
|
|
591
|
+
if (r == 0 && wname != NULL)
|
|
592
|
+
length += wcslen(wname);
|
|
593
|
+
else if (r < 0 && errno == ENOMEM)
|
|
594
|
+
return (0);
|
|
595
|
+
else
|
|
596
|
+
length += sizeof(uid_t) * 3 + 1;
|
|
597
|
+
} else {
|
|
598
|
+
r = archive_mstring_get_mbs_l(a, &ap->name, &name,
|
|
599
|
+
&len, sc);
|
|
600
|
+
if (r != 0)
|
|
601
|
+
return (0);
|
|
602
|
+
if (len > 0 && name != NULL)
|
|
603
|
+
length += len;
|
|
604
|
+
else
|
|
605
|
+
length += sizeof(uid_t) * 3 + 1;
|
|
606
|
+
}
|
|
607
|
+
length += 1; /* colon after user or group name */
|
|
608
|
+
} else if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4)
|
|
609
|
+
length += 1; /* 2nd colon empty user,group or other */
|
|
610
|
+
|
|
611
|
+
if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0)
|
|
612
|
+
&& ((want_type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0)
|
|
613
|
+
&& (ap->tag == ARCHIVE_ENTRY_ACL_OTHER
|
|
614
|
+
|| ap->tag == ARCHIVE_ENTRY_ACL_MASK)) {
|
|
615
|
+
/* Solaris has no colon after other: and mask: */
|
|
616
|
+
length = length - 1;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
|
|
620
|
+
/* rwxpdDaARWcCos:fdinSFI:deny */
|
|
621
|
+
length += 27;
|
|
622
|
+
if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DENY) == 0)
|
|
623
|
+
length += 1; /* allow, alarm, audit */
|
|
624
|
+
} else
|
|
625
|
+
length += 3; /* rwx */
|
|
626
|
+
|
|
627
|
+
if ((ap->tag == ARCHIVE_ENTRY_ACL_USER ||
|
|
628
|
+
ap->tag == ARCHIVE_ENTRY_ACL_GROUP) &&
|
|
629
|
+
(flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0) {
|
|
630
|
+
length += 1; /* colon */
|
|
631
|
+
/* ID digit count */
|
|
632
|
+
idlen = 1;
|
|
633
|
+
tmp = ap->id;
|
|
634
|
+
while (tmp > 9) {
|
|
635
|
+
tmp = tmp / 10;
|
|
636
|
+
idlen++;
|
|
637
|
+
}
|
|
638
|
+
length += idlen;
|
|
639
|
+
}
|
|
640
|
+
length ++; /* entry separator */
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/* Add filemode-mapping access entries to the length */
|
|
644
|
+
if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
|
|
645
|
+
if ((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0) {
|
|
646
|
+
/* "user::rwx\ngroup::rwx\nother:rwx\n" */
|
|
647
|
+
length += 31;
|
|
648
|
+
} else {
|
|
649
|
+
/* "user::rwx\ngroup::rwx\nother::rwx\n" */
|
|
650
|
+
length += 32;
|
|
651
|
+
}
|
|
652
|
+
} else if (count == 0)
|
|
653
|
+
return (0);
|
|
654
|
+
|
|
655
|
+
/* The terminating character is included in count */
|
|
656
|
+
return (length);
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/*
|
|
660
|
+
* Generate a wide text version of the ACL. The flags parameter controls
|
|
661
|
+
* the type and style of the generated ACL.
|
|
662
|
+
*/
|
|
663
|
+
wchar_t *
|
|
664
|
+
archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags,
|
|
665
|
+
struct archive *a)
|
|
666
|
+
{
|
|
667
|
+
int count;
|
|
668
|
+
ssize_t length;
|
|
669
|
+
size_t len;
|
|
670
|
+
const wchar_t *wname;
|
|
671
|
+
const wchar_t *prefix;
|
|
672
|
+
wchar_t separator;
|
|
673
|
+
struct archive_acl_entry *ap;
|
|
674
|
+
int id, r, want_type;
|
|
675
|
+
wchar_t *wp, *ws;
|
|
676
|
+
|
|
677
|
+
want_type = archive_acl_text_want_type(acl, flags);
|
|
678
|
+
|
|
679
|
+
/* Both NFSv4 and POSIX.1 types found */
|
|
680
|
+
if (want_type == 0)
|
|
681
|
+
return (NULL);
|
|
682
|
+
|
|
683
|
+
if (want_type == ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)
|
|
684
|
+
flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT;
|
|
685
|
+
|
|
686
|
+
length = archive_acl_text_len(acl, want_type, flags, 1, a, NULL);
|
|
687
|
+
|
|
688
|
+
if (length == 0)
|
|
689
|
+
return (NULL);
|
|
690
|
+
|
|
691
|
+
if (flags & ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA)
|
|
692
|
+
separator = L',';
|
|
693
|
+
else
|
|
694
|
+
separator = L'\n';
|
|
695
|
+
|
|
696
|
+
/* Now, allocate the string and actually populate it. */
|
|
697
|
+
wp = ws = (wchar_t *)malloc(length * sizeof(wchar_t));
|
|
698
|
+
if (wp == NULL) {
|
|
699
|
+
if (errno == ENOMEM)
|
|
700
|
+
__archive_errx(1, "No memory");
|
|
701
|
+
return (NULL);
|
|
702
|
+
}
|
|
703
|
+
count = 0;
|
|
704
|
+
|
|
705
|
+
if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
|
|
706
|
+
append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
|
|
707
|
+
ARCHIVE_ENTRY_ACL_USER_OBJ, flags, NULL,
|
|
708
|
+
acl->mode & 0700, -1);
|
|
709
|
+
*wp++ = separator;
|
|
710
|
+
append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
|
|
711
|
+
ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL,
|
|
712
|
+
acl->mode & 0070, -1);
|
|
713
|
+
*wp++ = separator;
|
|
714
|
+
append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
|
|
715
|
+
ARCHIVE_ENTRY_ACL_OTHER, flags, NULL,
|
|
716
|
+
acl->mode & 0007, -1);
|
|
717
|
+
count += 3;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
for (ap = acl->acl_head; ap != NULL; ap = ap->next) {
|
|
721
|
+
if ((ap->type & want_type) == 0)
|
|
722
|
+
continue;
|
|
723
|
+
/*
|
|
724
|
+
* Filemode-mapping ACL entries are stored exclusively in
|
|
725
|
+
* ap->mode so they should not be in the list
|
|
726
|
+
*/
|
|
727
|
+
if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS)
|
|
728
|
+
&& (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ
|
|
729
|
+
|| ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ
|
|
730
|
+
|| ap->tag == ARCHIVE_ENTRY_ACL_OTHER))
|
|
731
|
+
continue;
|
|
732
|
+
if (ap->type == ARCHIVE_ENTRY_ACL_TYPE_DEFAULT &&
|
|
733
|
+
(flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0)
|
|
734
|
+
prefix = L"default:";
|
|
735
|
+
else
|
|
736
|
+
prefix = NULL;
|
|
737
|
+
r = archive_mstring_get_wcs(a, &ap->name, &wname);
|
|
738
|
+
if (r == 0) {
|
|
739
|
+
if (count > 0)
|
|
740
|
+
*wp++ = separator;
|
|
741
|
+
if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
|
|
742
|
+
id = ap->id;
|
|
743
|
+
else
|
|
744
|
+
id = -1;
|
|
745
|
+
append_entry_w(&wp, prefix, ap->type, ap->tag, flags,
|
|
746
|
+
wname, ap->permset, id);
|
|
747
|
+
count++;
|
|
748
|
+
} else if (r < 0 && errno == ENOMEM) {
|
|
749
|
+
free(ws);
|
|
750
|
+
return (NULL);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
/* Add terminating character */
|
|
755
|
+
*wp++ = L'\0';
|
|
756
|
+
|
|
757
|
+
len = wcslen(ws);
|
|
758
|
+
|
|
759
|
+
if ((ssize_t)len > (length - 1))
|
|
760
|
+
__archive_errx(1, "Buffer overrun");
|
|
761
|
+
|
|
762
|
+
if (text_len != NULL)
|
|
763
|
+
*text_len = len;
|
|
764
|
+
|
|
765
|
+
return (ws);
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
static void
|
|
769
|
+
append_id_w(wchar_t **wp, int id)
|
|
770
|
+
{
|
|
771
|
+
if (id < 0)
|
|
772
|
+
id = 0;
|
|
773
|
+
if (id > 9)
|
|
774
|
+
append_id_w(wp, id / 10);
|
|
775
|
+
*(*wp)++ = L"0123456789"[id % 10];
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
static void
|
|
779
|
+
append_entry_w(wchar_t **wp, const wchar_t *prefix, int type,
|
|
780
|
+
int tag, int flags, const wchar_t *wname, int perm, int id)
|
|
781
|
+
{
|
|
782
|
+
int i;
|
|
783
|
+
|
|
784
|
+
if (prefix != NULL) {
|
|
785
|
+
wcscpy(*wp, prefix);
|
|
786
|
+
*wp += wcslen(*wp);
|
|
787
|
+
}
|
|
788
|
+
switch (tag) {
|
|
789
|
+
case ARCHIVE_ENTRY_ACL_USER_OBJ:
|
|
790
|
+
wname = NULL;
|
|
791
|
+
id = -1;
|
|
792
|
+
if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
|
|
793
|
+
wcscpy(*wp, L"owner@");
|
|
794
|
+
break;
|
|
795
|
+
}
|
|
796
|
+
/* FALLTHROUGH */
|
|
797
|
+
case ARCHIVE_ENTRY_ACL_USER:
|
|
798
|
+
wcscpy(*wp, L"user");
|
|
799
|
+
break;
|
|
800
|
+
case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
|
|
801
|
+
wname = NULL;
|
|
802
|
+
id = -1;
|
|
803
|
+
if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
|
|
804
|
+
wcscpy(*wp, L"group@");
|
|
805
|
+
break;
|
|
806
|
+
}
|
|
807
|
+
/* FALLTHROUGH */
|
|
808
|
+
case ARCHIVE_ENTRY_ACL_GROUP:
|
|
809
|
+
wcscpy(*wp, L"group");
|
|
810
|
+
break;
|
|
811
|
+
case ARCHIVE_ENTRY_ACL_MASK:
|
|
812
|
+
wcscpy(*wp, L"mask");
|
|
813
|
+
wname = NULL;
|
|
814
|
+
id = -1;
|
|
815
|
+
break;
|
|
816
|
+
case ARCHIVE_ENTRY_ACL_OTHER:
|
|
817
|
+
wcscpy(*wp, L"other");
|
|
818
|
+
wname = NULL;
|
|
819
|
+
id = -1;
|
|
820
|
+
break;
|
|
821
|
+
case ARCHIVE_ENTRY_ACL_EVERYONE:
|
|
822
|
+
wcscpy(*wp, L"everyone@");
|
|
823
|
+
wname = NULL;
|
|
824
|
+
id = -1;
|
|
825
|
+
break;
|
|
826
|
+
}
|
|
827
|
+
*wp += wcslen(*wp);
|
|
828
|
+
*(*wp)++ = L':';
|
|
829
|
+
if (((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) ||
|
|
830
|
+
tag == ARCHIVE_ENTRY_ACL_USER ||
|
|
831
|
+
tag == ARCHIVE_ENTRY_ACL_GROUP) {
|
|
832
|
+
if (wname != NULL) {
|
|
833
|
+
wcscpy(*wp, wname);
|
|
834
|
+
*wp += wcslen(*wp);
|
|
835
|
+
} else if (tag == ARCHIVE_ENTRY_ACL_USER
|
|
836
|
+
|| tag == ARCHIVE_ENTRY_ACL_GROUP) {
|
|
837
|
+
append_id_w(wp, id);
|
|
838
|
+
if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0)
|
|
839
|
+
id = -1;
|
|
840
|
+
}
|
|
841
|
+
/* Solaris style has no second colon after other and mask */
|
|
842
|
+
if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) == 0)
|
|
843
|
+
|| (tag != ARCHIVE_ENTRY_ACL_OTHER
|
|
844
|
+
&& tag != ARCHIVE_ENTRY_ACL_MASK))
|
|
845
|
+
*(*wp)++ = L':';
|
|
846
|
+
}
|
|
847
|
+
if ((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
|
|
848
|
+
/* POSIX.1e ACL perms */
|
|
849
|
+
*(*wp)++ = (perm & 0444) ? L'r' : L'-';
|
|
850
|
+
*(*wp)++ = (perm & 0222) ? L'w' : L'-';
|
|
851
|
+
*(*wp)++ = (perm & 0111) ? L'x' : L'-';
|
|
852
|
+
} else {
|
|
853
|
+
/* NFSv4 ACL perms */
|
|
854
|
+
for (i = 0; i < nfsv4_acl_perm_map_size; i++) {
|
|
855
|
+
if (perm & nfsv4_acl_perm_map[i].perm)
|
|
856
|
+
*(*wp)++ = nfsv4_acl_perm_map[i].wc;
|
|
857
|
+
else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
|
|
858
|
+
*(*wp)++ = L'-';
|
|
859
|
+
}
|
|
860
|
+
*(*wp)++ = L':';
|
|
861
|
+
for (i = 0; i < nfsv4_acl_flag_map_size; i++) {
|
|
862
|
+
if (perm & nfsv4_acl_flag_map[i].perm)
|
|
863
|
+
*(*wp)++ = nfsv4_acl_flag_map[i].wc;
|
|
864
|
+
else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
|
|
865
|
+
*(*wp)++ = L'-';
|
|
866
|
+
}
|
|
867
|
+
*(*wp)++ = L':';
|
|
868
|
+
switch (type) {
|
|
869
|
+
case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
|
|
870
|
+
wcscpy(*wp, L"allow");
|
|
871
|
+
break;
|
|
872
|
+
case ARCHIVE_ENTRY_ACL_TYPE_DENY:
|
|
873
|
+
wcscpy(*wp, L"deny");
|
|
874
|
+
break;
|
|
875
|
+
case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
|
|
876
|
+
wcscpy(*wp, L"audit");
|
|
877
|
+
break;
|
|
878
|
+
case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
|
|
879
|
+
wcscpy(*wp, L"alarm");
|
|
880
|
+
break;
|
|
881
|
+
default:
|
|
882
|
+
break;
|
|
883
|
+
}
|
|
884
|
+
*wp += wcslen(*wp);
|
|
885
|
+
}
|
|
886
|
+
if (id != -1) {
|
|
887
|
+
*(*wp)++ = L':';
|
|
888
|
+
append_id_w(wp, id);
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
/*
|
|
893
|
+
* Generate a text version of the ACL. The flags parameter controls
|
|
894
|
+
* the type and style of the generated ACL.
|
|
895
|
+
*/
|
|
896
|
+
char *
|
|
897
|
+
archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags,
|
|
898
|
+
struct archive_string_conv *sc)
|
|
899
|
+
{
|
|
900
|
+
int count;
|
|
901
|
+
ssize_t length;
|
|
902
|
+
size_t len;
|
|
903
|
+
const char *name;
|
|
904
|
+
const char *prefix;
|
|
905
|
+
char separator;
|
|
906
|
+
struct archive_acl_entry *ap;
|
|
907
|
+
int id, r, want_type;
|
|
908
|
+
char *p, *s;
|
|
909
|
+
|
|
910
|
+
want_type = archive_acl_text_want_type(acl, flags);
|
|
911
|
+
|
|
912
|
+
/* Both NFSv4 and POSIX.1 types found */
|
|
913
|
+
if (want_type == 0)
|
|
914
|
+
return (NULL);
|
|
915
|
+
|
|
916
|
+
if (want_type == ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)
|
|
917
|
+
flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT;
|
|
918
|
+
|
|
919
|
+
length = archive_acl_text_len(acl, want_type, flags, 0, NULL, sc);
|
|
920
|
+
|
|
921
|
+
if (length == 0)
|
|
922
|
+
return (NULL);
|
|
923
|
+
|
|
924
|
+
if (flags & ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA)
|
|
925
|
+
separator = ',';
|
|
926
|
+
else
|
|
927
|
+
separator = '\n';
|
|
928
|
+
|
|
929
|
+
/* Now, allocate the string and actually populate it. */
|
|
930
|
+
p = s = (char *)malloc(length * sizeof(char));
|
|
931
|
+
if (p == NULL) {
|
|
932
|
+
if (errno == ENOMEM)
|
|
933
|
+
__archive_errx(1, "No memory");
|
|
934
|
+
return (NULL);
|
|
935
|
+
}
|
|
936
|
+
count = 0;
|
|
937
|
+
|
|
938
|
+
if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
|
|
939
|
+
append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
|
|
940
|
+
ARCHIVE_ENTRY_ACL_USER_OBJ, flags, NULL,
|
|
941
|
+
acl->mode & 0700, -1);
|
|
942
|
+
*p++ = separator;
|
|
943
|
+
append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
|
|
944
|
+
ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL,
|
|
945
|
+
acl->mode & 0070, -1);
|
|
946
|
+
*p++ = separator;
|
|
947
|
+
append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
|
|
948
|
+
ARCHIVE_ENTRY_ACL_OTHER, flags, NULL,
|
|
949
|
+
acl->mode & 0007, -1);
|
|
950
|
+
count += 3;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
for (ap = acl->acl_head; ap != NULL; ap = ap->next) {
|
|
954
|
+
if ((ap->type & want_type) == 0)
|
|
955
|
+
continue;
|
|
956
|
+
/*
|
|
957
|
+
* Filemode-mapping ACL entries are stored exclusively in
|
|
958
|
+
* ap->mode so they should not be in the list
|
|
959
|
+
*/
|
|
960
|
+
if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS)
|
|
961
|
+
&& (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ
|
|
962
|
+
|| ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ
|
|
963
|
+
|| ap->tag == ARCHIVE_ENTRY_ACL_OTHER))
|
|
964
|
+
continue;
|
|
965
|
+
if (ap->type == ARCHIVE_ENTRY_ACL_TYPE_DEFAULT &&
|
|
966
|
+
(flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0)
|
|
967
|
+
prefix = "default:";
|
|
968
|
+
else
|
|
969
|
+
prefix = NULL;
|
|
970
|
+
r = archive_mstring_get_mbs_l(
|
|
971
|
+
NULL, &ap->name, &name, &len, sc);
|
|
972
|
+
if (r != 0) {
|
|
973
|
+
free(s);
|
|
974
|
+
return (NULL);
|
|
975
|
+
}
|
|
976
|
+
if (count > 0)
|
|
977
|
+
*p++ = separator;
|
|
978
|
+
if (name == NULL ||
|
|
979
|
+
(flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)) {
|
|
980
|
+
id = ap->id;
|
|
981
|
+
} else {
|
|
982
|
+
id = -1;
|
|
983
|
+
}
|
|
984
|
+
append_entry(&p, prefix, ap->type, ap->tag, flags, name,
|
|
985
|
+
ap->permset, id);
|
|
986
|
+
count++;
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
/* Add terminating character */
|
|
990
|
+
*p++ = '\0';
|
|
991
|
+
|
|
992
|
+
len = strlen(s);
|
|
993
|
+
|
|
994
|
+
if ((ssize_t)len > (length - 1))
|
|
995
|
+
__archive_errx(1, "Buffer overrun");
|
|
996
|
+
|
|
997
|
+
if (text_len != NULL)
|
|
998
|
+
*text_len = len;
|
|
999
|
+
|
|
1000
|
+
return (s);
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
static void
|
|
1004
|
+
append_id(char **p, int id)
|
|
1005
|
+
{
|
|
1006
|
+
if (id < 0)
|
|
1007
|
+
id = 0;
|
|
1008
|
+
if (id > 9)
|
|
1009
|
+
append_id(p, id / 10);
|
|
1010
|
+
*(*p)++ = "0123456789"[id % 10];
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
static void
|
|
1014
|
+
append_entry(char **p, const char *prefix, int type,
|
|
1015
|
+
int tag, int flags, const char *name, int perm, int id)
|
|
1016
|
+
{
|
|
1017
|
+
int i;
|
|
1018
|
+
|
|
1019
|
+
if (prefix != NULL) {
|
|
1020
|
+
strcpy(*p, prefix);
|
|
1021
|
+
*p += strlen(*p);
|
|
1022
|
+
}
|
|
1023
|
+
switch (tag) {
|
|
1024
|
+
case ARCHIVE_ENTRY_ACL_USER_OBJ:
|
|
1025
|
+
name = NULL;
|
|
1026
|
+
id = -1;
|
|
1027
|
+
if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
|
|
1028
|
+
strcpy(*p, "owner@");
|
|
1029
|
+
break;
|
|
1030
|
+
}
|
|
1031
|
+
/* FALLTHROUGH */
|
|
1032
|
+
case ARCHIVE_ENTRY_ACL_USER:
|
|
1033
|
+
strcpy(*p, "user");
|
|
1034
|
+
break;
|
|
1035
|
+
case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
|
|
1036
|
+
name = NULL;
|
|
1037
|
+
id = -1;
|
|
1038
|
+
if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
|
|
1039
|
+
strcpy(*p, "group@");
|
|
1040
|
+
break;
|
|
1041
|
+
}
|
|
1042
|
+
/* FALLTHROUGH */
|
|
1043
|
+
case ARCHIVE_ENTRY_ACL_GROUP:
|
|
1044
|
+
strcpy(*p, "group");
|
|
1045
|
+
break;
|
|
1046
|
+
case ARCHIVE_ENTRY_ACL_MASK:
|
|
1047
|
+
strcpy(*p, "mask");
|
|
1048
|
+
name = NULL;
|
|
1049
|
+
id = -1;
|
|
1050
|
+
break;
|
|
1051
|
+
case ARCHIVE_ENTRY_ACL_OTHER:
|
|
1052
|
+
strcpy(*p, "other");
|
|
1053
|
+
name = NULL;
|
|
1054
|
+
id = -1;
|
|
1055
|
+
break;
|
|
1056
|
+
case ARCHIVE_ENTRY_ACL_EVERYONE:
|
|
1057
|
+
strcpy(*p, "everyone@");
|
|
1058
|
+
name = NULL;
|
|
1059
|
+
id = -1;
|
|
1060
|
+
break;
|
|
1061
|
+
}
|
|
1062
|
+
*p += strlen(*p);
|
|
1063
|
+
*(*p)++ = ':';
|
|
1064
|
+
if (((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) ||
|
|
1065
|
+
tag == ARCHIVE_ENTRY_ACL_USER ||
|
|
1066
|
+
tag == ARCHIVE_ENTRY_ACL_GROUP) {
|
|
1067
|
+
if (name != NULL) {
|
|
1068
|
+
strcpy(*p, name);
|
|
1069
|
+
*p += strlen(*p);
|
|
1070
|
+
} else if (tag == ARCHIVE_ENTRY_ACL_USER
|
|
1071
|
+
|| tag == ARCHIVE_ENTRY_ACL_GROUP) {
|
|
1072
|
+
append_id(p, id);
|
|
1073
|
+
if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0)
|
|
1074
|
+
id = -1;
|
|
1075
|
+
}
|
|
1076
|
+
/* Solaris style has no second colon after other and mask */
|
|
1077
|
+
if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) == 0)
|
|
1078
|
+
|| (tag != ARCHIVE_ENTRY_ACL_OTHER
|
|
1079
|
+
&& tag != ARCHIVE_ENTRY_ACL_MASK))
|
|
1080
|
+
*(*p)++ = ':';
|
|
1081
|
+
}
|
|
1082
|
+
if ((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
|
|
1083
|
+
/* POSIX.1e ACL perms */
|
|
1084
|
+
*(*p)++ = (perm & 0444) ? 'r' : '-';
|
|
1085
|
+
*(*p)++ = (perm & 0222) ? 'w' : '-';
|
|
1086
|
+
*(*p)++ = (perm & 0111) ? 'x' : '-';
|
|
1087
|
+
} else {
|
|
1088
|
+
/* NFSv4 ACL perms */
|
|
1089
|
+
for (i = 0; i < nfsv4_acl_perm_map_size; i++) {
|
|
1090
|
+
if (perm & nfsv4_acl_perm_map[i].perm)
|
|
1091
|
+
*(*p)++ = nfsv4_acl_perm_map[i].c;
|
|
1092
|
+
else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
|
|
1093
|
+
*(*p)++ = '-';
|
|
1094
|
+
}
|
|
1095
|
+
*(*p)++ = ':';
|
|
1096
|
+
for (i = 0; i < nfsv4_acl_flag_map_size; i++) {
|
|
1097
|
+
if (perm & nfsv4_acl_flag_map[i].perm)
|
|
1098
|
+
*(*p)++ = nfsv4_acl_flag_map[i].c;
|
|
1099
|
+
else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
|
|
1100
|
+
*(*p)++ = '-';
|
|
1101
|
+
}
|
|
1102
|
+
*(*p)++ = ':';
|
|
1103
|
+
switch (type) {
|
|
1104
|
+
case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
|
|
1105
|
+
strcpy(*p, "allow");
|
|
1106
|
+
break;
|
|
1107
|
+
case ARCHIVE_ENTRY_ACL_TYPE_DENY:
|
|
1108
|
+
strcpy(*p, "deny");
|
|
1109
|
+
break;
|
|
1110
|
+
case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
|
|
1111
|
+
strcpy(*p, "audit");
|
|
1112
|
+
break;
|
|
1113
|
+
case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
|
|
1114
|
+
strcpy(*p, "alarm");
|
|
1115
|
+
break;
|
|
1116
|
+
}
|
|
1117
|
+
*p += strlen(*p);
|
|
1118
|
+
}
|
|
1119
|
+
if (id != -1) {
|
|
1120
|
+
*(*p)++ = ':';
|
|
1121
|
+
append_id(p, id);
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
/*
|
|
1126
|
+
* Parse a wide ACL text string.
|
|
1127
|
+
*
|
|
1128
|
+
* The want_type argument may be one of the following:
|
|
1129
|
+
* ARCHIVE_ENTRY_ACL_TYPE_ACCESS - text is a POSIX.1e ACL of type ACCESS
|
|
1130
|
+
* ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - text is a POSIX.1e ACL of type DEFAULT
|
|
1131
|
+
* ARCHIVE_ENTRY_ACL_TYPE_NFS4 - text is as a NFSv4 ACL
|
|
1132
|
+
*
|
|
1133
|
+
* POSIX.1e ACL entries prefixed with "default:" are treated as
|
|
1134
|
+
* ARCHIVE_ENTRY_ACL_TYPE_DEFAULT unless type is ARCHIVE_ENTRY_ACL_TYPE_NFS4
|
|
1135
|
+
*/
|
|
1136
|
+
int
|
|
1137
|
+
archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text,
|
|
1138
|
+
int want_type)
|
|
1139
|
+
{
|
|
1140
|
+
struct {
|
|
1141
|
+
const wchar_t *start;
|
|
1142
|
+
const wchar_t *end;
|
|
1143
|
+
} field[6], name;
|
|
1144
|
+
|
|
1145
|
+
const wchar_t *s, *st;
|
|
1146
|
+
|
|
1147
|
+
int numfields, fields, n, r, sol, ret;
|
|
1148
|
+
int type, types, tag, permset, id;
|
|
1149
|
+
size_t len;
|
|
1150
|
+
wchar_t sep;
|
|
1151
|
+
|
|
1152
|
+
ret = ARCHIVE_OK;
|
|
1153
|
+
types = 0;
|
|
1154
|
+
|
|
1155
|
+
switch (want_type) {
|
|
1156
|
+
case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
|
|
1157
|
+
want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
|
|
1158
|
+
__LA_FALLTHROUGH;
|
|
1159
|
+
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
|
|
1160
|
+
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
|
|
1161
|
+
numfields = 5;
|
|
1162
|
+
break;
|
|
1163
|
+
case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
|
|
1164
|
+
numfields = 6;
|
|
1165
|
+
break;
|
|
1166
|
+
default:
|
|
1167
|
+
return (ARCHIVE_FATAL);
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
while (text != NULL && *text != L'\0') {
|
|
1171
|
+
/*
|
|
1172
|
+
* Parse the fields out of the next entry,
|
|
1173
|
+
* advance 'text' to start of next entry.
|
|
1174
|
+
*/
|
|
1175
|
+
fields = 0;
|
|
1176
|
+
do {
|
|
1177
|
+
const wchar_t *start, *end;
|
|
1178
|
+
next_field_w(&text, &start, &end, &sep);
|
|
1179
|
+
if (fields < numfields) {
|
|
1180
|
+
field[fields].start = start;
|
|
1181
|
+
field[fields].end = end;
|
|
1182
|
+
}
|
|
1183
|
+
++fields;
|
|
1184
|
+
} while (sep == L':');
|
|
1185
|
+
|
|
1186
|
+
/* Set remaining fields to blank. */
|
|
1187
|
+
for (n = fields; n < numfields; ++n)
|
|
1188
|
+
field[n].start = field[n].end = NULL;
|
|
1189
|
+
|
|
1190
|
+
if (field[0].start != NULL && *(field[0].start) == L'#') {
|
|
1191
|
+
/* Comment, skip entry */
|
|
1192
|
+
continue;
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
n = 0;
|
|
1196
|
+
sol = 0;
|
|
1197
|
+
id = -1;
|
|
1198
|
+
permset = 0;
|
|
1199
|
+
name.start = name.end = NULL;
|
|
1200
|
+
|
|
1201
|
+
if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
|
|
1202
|
+
/* POSIX.1e ACLs */
|
|
1203
|
+
/*
|
|
1204
|
+
* Default keyword "default:user::rwx"
|
|
1205
|
+
* if found, we have one more field
|
|
1206
|
+
*
|
|
1207
|
+
* We also support old Solaris extension:
|
|
1208
|
+
* "defaultuser::rwx" is the default ACL corresponding
|
|
1209
|
+
* to "user::rwx", etc. valid only for first field
|
|
1210
|
+
*/
|
|
1211
|
+
s = field[0].start;
|
|
1212
|
+
len = field[0].end - field[0].start;
|
|
1213
|
+
if (*s == L'd' && (len == 1 || (len >= 7
|
|
1214
|
+
&& wmemcmp((s + 1), L"efault", 6) == 0))) {
|
|
1215
|
+
type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
|
|
1216
|
+
if (len > 7)
|
|
1217
|
+
field[0].start += 7;
|
|
1218
|
+
else
|
|
1219
|
+
n = 1;
|
|
1220
|
+
} else
|
|
1221
|
+
type = want_type;
|
|
1222
|
+
|
|
1223
|
+
/* Check for a numeric ID in field n+1 or n+3. */
|
|
1224
|
+
isint_w(field[n + 1].start, field[n + 1].end, &id);
|
|
1225
|
+
/* Field n+3 is optional. */
|
|
1226
|
+
if (id == -1 && fields > n+3)
|
|
1227
|
+
isint_w(field[n + 3].start, field[n + 3].end,
|
|
1228
|
+
&id);
|
|
1229
|
+
|
|
1230
|
+
tag = 0;
|
|
1231
|
+
s = field[n].start;
|
|
1232
|
+
st = field[n].start + 1;
|
|
1233
|
+
len = field[n].end - field[n].start;
|
|
1234
|
+
|
|
1235
|
+
switch (*s) {
|
|
1236
|
+
case L'u':
|
|
1237
|
+
if (len == 1 || (len == 4
|
|
1238
|
+
&& wmemcmp(st, L"ser", 3) == 0))
|
|
1239
|
+
tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
|
|
1240
|
+
break;
|
|
1241
|
+
case L'g':
|
|
1242
|
+
if (len == 1 || (len == 5
|
|
1243
|
+
&& wmemcmp(st, L"roup", 4) == 0))
|
|
1244
|
+
tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
|
|
1245
|
+
break;
|
|
1246
|
+
case L'o':
|
|
1247
|
+
if (len == 1 || (len == 5
|
|
1248
|
+
&& wmemcmp(st, L"ther", 4) == 0))
|
|
1249
|
+
tag = ARCHIVE_ENTRY_ACL_OTHER;
|
|
1250
|
+
break;
|
|
1251
|
+
case L'm':
|
|
1252
|
+
if (len == 1 || (len == 4
|
|
1253
|
+
&& wmemcmp(st, L"ask", 3) == 0))
|
|
1254
|
+
tag = ARCHIVE_ENTRY_ACL_MASK;
|
|
1255
|
+
break;
|
|
1256
|
+
default:
|
|
1257
|
+
break;
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
switch (tag) {
|
|
1261
|
+
case ARCHIVE_ENTRY_ACL_OTHER:
|
|
1262
|
+
case ARCHIVE_ENTRY_ACL_MASK:
|
|
1263
|
+
if (fields == (n + 2)
|
|
1264
|
+
&& field[n + 1].start < field[n + 1].end
|
|
1265
|
+
&& ismode_w(field[n + 1].start,
|
|
1266
|
+
field[n + 1].end, &permset)) {
|
|
1267
|
+
/* This is Solaris-style "other:rwx" */
|
|
1268
|
+
sol = 1;
|
|
1269
|
+
} else if (fields == (n + 3) &&
|
|
1270
|
+
field[n + 1].start < field[n + 1].end) {
|
|
1271
|
+
/* Invalid mask or other field */
|
|
1272
|
+
ret = ARCHIVE_WARN;
|
|
1273
|
+
continue;
|
|
1274
|
+
}
|
|
1275
|
+
break;
|
|
1276
|
+
case ARCHIVE_ENTRY_ACL_USER_OBJ:
|
|
1277
|
+
case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
|
|
1278
|
+
if (id != -1 ||
|
|
1279
|
+
field[n + 1].start < field[n + 1].end) {
|
|
1280
|
+
name = field[n + 1];
|
|
1281
|
+
if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ)
|
|
1282
|
+
tag = ARCHIVE_ENTRY_ACL_USER;
|
|
1283
|
+
else
|
|
1284
|
+
tag = ARCHIVE_ENTRY_ACL_GROUP;
|
|
1285
|
+
}
|
|
1286
|
+
break;
|
|
1287
|
+
default:
|
|
1288
|
+
/* Invalid tag, skip entry */
|
|
1289
|
+
ret = ARCHIVE_WARN;
|
|
1290
|
+
continue;
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
/*
|
|
1294
|
+
* Without "default:" we expect mode in field 2
|
|
1295
|
+
* Exception: Solaris other and mask fields
|
|
1296
|
+
*/
|
|
1297
|
+
if (permset == 0 && !ismode_w(field[n + 2 - sol].start,
|
|
1298
|
+
field[n + 2 - sol].end, &permset)) {
|
|
1299
|
+
/* Invalid mode, skip entry */
|
|
1300
|
+
ret = ARCHIVE_WARN;
|
|
1301
|
+
continue;
|
|
1302
|
+
}
|
|
1303
|
+
} else {
|
|
1304
|
+
/* NFS4 ACLs */
|
|
1305
|
+
s = field[0].start;
|
|
1306
|
+
len = field[0].end - field[0].start;
|
|
1307
|
+
tag = 0;
|
|
1308
|
+
|
|
1309
|
+
switch (len) {
|
|
1310
|
+
case 4:
|
|
1311
|
+
if (wmemcmp(s, L"user", 4) == 0)
|
|
1312
|
+
tag = ARCHIVE_ENTRY_ACL_USER;
|
|
1313
|
+
break;
|
|
1314
|
+
case 5:
|
|
1315
|
+
if (wmemcmp(s, L"group", 5) == 0)
|
|
1316
|
+
tag = ARCHIVE_ENTRY_ACL_GROUP;
|
|
1317
|
+
break;
|
|
1318
|
+
case 6:
|
|
1319
|
+
if (wmemcmp(s, L"owner@", 6) == 0)
|
|
1320
|
+
tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
|
|
1321
|
+
else if (wmemcmp(s, L"group@", len) == 0)
|
|
1322
|
+
tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
|
|
1323
|
+
break;
|
|
1324
|
+
case 9:
|
|
1325
|
+
if (wmemcmp(s, L"everyone@", 9) == 0)
|
|
1326
|
+
tag = ARCHIVE_ENTRY_ACL_EVERYONE;
|
|
1327
|
+
default:
|
|
1328
|
+
break;
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
if (tag == 0) {
|
|
1332
|
+
/* Invalid tag, skip entry */
|
|
1333
|
+
ret = ARCHIVE_WARN;
|
|
1334
|
+
continue;
|
|
1335
|
+
} else if (tag == ARCHIVE_ENTRY_ACL_USER ||
|
|
1336
|
+
tag == ARCHIVE_ENTRY_ACL_GROUP) {
|
|
1337
|
+
n = 1;
|
|
1338
|
+
name = field[1];
|
|
1339
|
+
isint_w(name.start, name.end, &id);
|
|
1340
|
+
} else
|
|
1341
|
+
n = 0;
|
|
1342
|
+
|
|
1343
|
+
if (!is_nfs4_perms_w(field[1 + n].start,
|
|
1344
|
+
field[1 + n].end, &permset)) {
|
|
1345
|
+
/* Invalid NFSv4 perms, skip entry */
|
|
1346
|
+
ret = ARCHIVE_WARN;
|
|
1347
|
+
continue;
|
|
1348
|
+
}
|
|
1349
|
+
if (!is_nfs4_flags_w(field[2 + n].start,
|
|
1350
|
+
field[2 + n].end, &permset)) {
|
|
1351
|
+
/* Invalid NFSv4 flags, skip entry */
|
|
1352
|
+
ret = ARCHIVE_WARN;
|
|
1353
|
+
continue;
|
|
1354
|
+
}
|
|
1355
|
+
s = field[3 + n].start;
|
|
1356
|
+
len = field[3 + n].end - field[3 + n].start;
|
|
1357
|
+
type = 0;
|
|
1358
|
+
if (len == 4) {
|
|
1359
|
+
if (wmemcmp(s, L"deny", 4) == 0)
|
|
1360
|
+
type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
|
|
1361
|
+
} else if (len == 5) {
|
|
1362
|
+
if (wmemcmp(s, L"allow", 5) == 0)
|
|
1363
|
+
type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
|
|
1364
|
+
else if (wmemcmp(s, L"audit", 5) == 0)
|
|
1365
|
+
type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
|
|
1366
|
+
else if (wmemcmp(s, L"alarm", 5) == 0)
|
|
1367
|
+
type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
|
|
1368
|
+
}
|
|
1369
|
+
if (type == 0) {
|
|
1370
|
+
/* Invalid entry type, skip entry */
|
|
1371
|
+
ret = ARCHIVE_WARN;
|
|
1372
|
+
continue;
|
|
1373
|
+
}
|
|
1374
|
+
isint_w(field[4 + n].start, field[4 + n].end, &id);
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
/* Add entry to the internal list. */
|
|
1378
|
+
r = archive_acl_add_entry_w_len(acl, type, permset,
|
|
1379
|
+
tag, id, name.start, name.end - name.start);
|
|
1380
|
+
if (r < ARCHIVE_WARN)
|
|
1381
|
+
return (r);
|
|
1382
|
+
if (r != ARCHIVE_OK)
|
|
1383
|
+
ret = ARCHIVE_WARN;
|
|
1384
|
+
types |= type;
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
/* Reset ACL */
|
|
1388
|
+
archive_acl_reset(acl, types);
|
|
1389
|
+
|
|
1390
|
+
return (ret);
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
/*
|
|
1394
|
+
* Parse a string to a positive decimal integer. Returns true if
|
|
1395
|
+
* the string is non-empty and consists only of decimal digits,
|
|
1396
|
+
* false otherwise.
|
|
1397
|
+
*/
|
|
1398
|
+
static int
|
|
1399
|
+
isint_w(const wchar_t *start, const wchar_t *end, int *result)
|
|
1400
|
+
{
|
|
1401
|
+
int n = 0;
|
|
1402
|
+
if (start >= end)
|
|
1403
|
+
return (0);
|
|
1404
|
+
while (start < end) {
|
|
1405
|
+
if (*start < L'0' || *start > L'9')
|
|
1406
|
+
return (0);
|
|
1407
|
+
if (n > (INT_MAX / 10) ||
|
|
1408
|
+
(n == INT_MAX / 10 && (*start - L'0') > INT_MAX % 10)) {
|
|
1409
|
+
n = INT_MAX;
|
|
1410
|
+
} else {
|
|
1411
|
+
n *= 10;
|
|
1412
|
+
n += *start - L'0';
|
|
1413
|
+
}
|
|
1414
|
+
start++;
|
|
1415
|
+
}
|
|
1416
|
+
*result = n;
|
|
1417
|
+
return (1);
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
/*
|
|
1421
|
+
* Parse a string as a mode field. Returns true if
|
|
1422
|
+
* the string is non-empty and consists only of mode characters,
|
|
1423
|
+
* false otherwise.
|
|
1424
|
+
*/
|
|
1425
|
+
static int
|
|
1426
|
+
ismode_w(const wchar_t *start, const wchar_t *end, int *permset)
|
|
1427
|
+
{
|
|
1428
|
+
const wchar_t *p;
|
|
1429
|
+
|
|
1430
|
+
if (start >= end)
|
|
1431
|
+
return (0);
|
|
1432
|
+
p = start;
|
|
1433
|
+
*permset = 0;
|
|
1434
|
+
while (p < end) {
|
|
1435
|
+
switch (*p++) {
|
|
1436
|
+
case L'r': case L'R':
|
|
1437
|
+
*permset |= ARCHIVE_ENTRY_ACL_READ;
|
|
1438
|
+
break;
|
|
1439
|
+
case L'w': case L'W':
|
|
1440
|
+
*permset |= ARCHIVE_ENTRY_ACL_WRITE;
|
|
1441
|
+
break;
|
|
1442
|
+
case L'x': case L'X':
|
|
1443
|
+
*permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
|
|
1444
|
+
break;
|
|
1445
|
+
case L'-':
|
|
1446
|
+
break;
|
|
1447
|
+
default:
|
|
1448
|
+
return (0);
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
return (1);
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
/*
|
|
1455
|
+
* Parse a string as a NFS4 ACL permission field.
|
|
1456
|
+
* Returns true if the string is non-empty and consists only of NFS4 ACL
|
|
1457
|
+
* permission characters, false otherwise
|
|
1458
|
+
*/
|
|
1459
|
+
static int
|
|
1460
|
+
is_nfs4_perms_w(const wchar_t *start, const wchar_t *end, int *permset)
|
|
1461
|
+
{
|
|
1462
|
+
const wchar_t *p = start;
|
|
1463
|
+
|
|
1464
|
+
while (p < end) {
|
|
1465
|
+
switch (*p++) {
|
|
1466
|
+
case L'r':
|
|
1467
|
+
*permset |= ARCHIVE_ENTRY_ACL_READ_DATA;
|
|
1468
|
+
break;
|
|
1469
|
+
case L'w':
|
|
1470
|
+
*permset |= ARCHIVE_ENTRY_ACL_WRITE_DATA;
|
|
1471
|
+
break;
|
|
1472
|
+
case L'x':
|
|
1473
|
+
*permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
|
|
1474
|
+
break;
|
|
1475
|
+
case L'p':
|
|
1476
|
+
*permset |= ARCHIVE_ENTRY_ACL_APPEND_DATA;
|
|
1477
|
+
break;
|
|
1478
|
+
case L'D':
|
|
1479
|
+
*permset |= ARCHIVE_ENTRY_ACL_DELETE_CHILD;
|
|
1480
|
+
break;
|
|
1481
|
+
case L'd':
|
|
1482
|
+
*permset |= ARCHIVE_ENTRY_ACL_DELETE;
|
|
1483
|
+
break;
|
|
1484
|
+
case L'a':
|
|
1485
|
+
*permset |= ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES;
|
|
1486
|
+
break;
|
|
1487
|
+
case L'A':
|
|
1488
|
+
*permset |= ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES;
|
|
1489
|
+
break;
|
|
1490
|
+
case L'R':
|
|
1491
|
+
*permset |= ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS;
|
|
1492
|
+
break;
|
|
1493
|
+
case L'W':
|
|
1494
|
+
*permset |= ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS;
|
|
1495
|
+
break;
|
|
1496
|
+
case L'c':
|
|
1497
|
+
*permset |= ARCHIVE_ENTRY_ACL_READ_ACL;
|
|
1498
|
+
break;
|
|
1499
|
+
case L'C':
|
|
1500
|
+
*permset |= ARCHIVE_ENTRY_ACL_WRITE_ACL;
|
|
1501
|
+
break;
|
|
1502
|
+
case L'o':
|
|
1503
|
+
*permset |= ARCHIVE_ENTRY_ACL_WRITE_OWNER;
|
|
1504
|
+
break;
|
|
1505
|
+
case L's':
|
|
1506
|
+
*permset |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
|
|
1507
|
+
break;
|
|
1508
|
+
case L'-':
|
|
1509
|
+
break;
|
|
1510
|
+
default:
|
|
1511
|
+
return(0);
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
return (1);
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
/*
|
|
1518
|
+
* Parse a string as a NFS4 ACL flags field.
|
|
1519
|
+
* Returns true if the string is non-empty and consists only of NFS4 ACL
|
|
1520
|
+
* flag characters, false otherwise
|
|
1521
|
+
*/
|
|
1522
|
+
static int
|
|
1523
|
+
is_nfs4_flags_w(const wchar_t *start, const wchar_t *end, int *permset)
|
|
1524
|
+
{
|
|
1525
|
+
const wchar_t *p = start;
|
|
1526
|
+
|
|
1527
|
+
while (p < end) {
|
|
1528
|
+
switch(*p++) {
|
|
1529
|
+
case L'f':
|
|
1530
|
+
*permset |= ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT;
|
|
1531
|
+
break;
|
|
1532
|
+
case L'd':
|
|
1533
|
+
*permset |= ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT;
|
|
1534
|
+
break;
|
|
1535
|
+
case L'i':
|
|
1536
|
+
*permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY;
|
|
1537
|
+
break;
|
|
1538
|
+
case L'n':
|
|
1539
|
+
*permset |=
|
|
1540
|
+
ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT;
|
|
1541
|
+
break;
|
|
1542
|
+
case L'S':
|
|
1543
|
+
*permset |= ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS;
|
|
1544
|
+
break;
|
|
1545
|
+
case L'F':
|
|
1546
|
+
*permset |= ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS;
|
|
1547
|
+
break;
|
|
1548
|
+
case L'I':
|
|
1549
|
+
*permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERITED;
|
|
1550
|
+
break;
|
|
1551
|
+
case L'-':
|
|
1552
|
+
break;
|
|
1553
|
+
default:
|
|
1554
|
+
return (0);
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
return (1);
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
/*
|
|
1561
|
+
* Match "[:whitespace:]*(.*)[:whitespace:]*[:,\n]". *wp is updated
|
|
1562
|
+
* to point to just after the separator. *start points to the first
|
|
1563
|
+
* character of the matched text and *end just after the last
|
|
1564
|
+
* character of the matched identifier. In particular *end - *start
|
|
1565
|
+
* is the length of the field body, not including leading or trailing
|
|
1566
|
+
* whitespace.
|
|
1567
|
+
*/
|
|
1568
|
+
static void
|
|
1569
|
+
next_field_w(const wchar_t **wp, const wchar_t **start,
|
|
1570
|
+
const wchar_t **end, wchar_t *sep)
|
|
1571
|
+
{
|
|
1572
|
+
/* Skip leading whitespace to find start of field. */
|
|
1573
|
+
while (**wp == L' ' || **wp == L'\t' || **wp == L'\n') {
|
|
1574
|
+
(*wp)++;
|
|
1575
|
+
}
|
|
1576
|
+
*start = *wp;
|
|
1577
|
+
|
|
1578
|
+
/* Scan for the separator. */
|
|
1579
|
+
while (**wp != L'\0' && **wp != L',' && **wp != L':' &&
|
|
1580
|
+
**wp != L'\n' && **wp != L'#') {
|
|
1581
|
+
(*wp)++;
|
|
1582
|
+
}
|
|
1583
|
+
*sep = **wp;
|
|
1584
|
+
|
|
1585
|
+
/* Locate end of field, trim trailing whitespace if necessary */
|
|
1586
|
+
if (*wp == *start) {
|
|
1587
|
+
*end = *wp;
|
|
1588
|
+
} else {
|
|
1589
|
+
*end = *wp - 1;
|
|
1590
|
+
while (**end == L' ' || **end == L'\t' || **end == L'\n') {
|
|
1591
|
+
(*end)--;
|
|
1592
|
+
}
|
|
1593
|
+
(*end)++;
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
/* Handle in-field comments */
|
|
1597
|
+
if (*sep == L'#') {
|
|
1598
|
+
while (**wp != L'\0' && **wp != L',' && **wp != L'\n') {
|
|
1599
|
+
(*wp)++;
|
|
1600
|
+
}
|
|
1601
|
+
*sep = **wp;
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1604
|
+
/* Adjust scanner location. */
|
|
1605
|
+
if (**wp != L'\0')
|
|
1606
|
+
(*wp)++;
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
/*
|
|
1610
|
+
* Parse an ACL text string.
|
|
1611
|
+
*
|
|
1612
|
+
* The want_type argument may be one of the following:
|
|
1613
|
+
* ARCHIVE_ENTRY_ACL_TYPE_ACCESS - text is a POSIX.1e ACL of type ACCESS
|
|
1614
|
+
* ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - text is a POSIX.1e ACL of type DEFAULT
|
|
1615
|
+
* ARCHIVE_ENTRY_ACL_TYPE_NFS4 - text is as a NFSv4 ACL
|
|
1616
|
+
*
|
|
1617
|
+
* POSIX.1e ACL entries prefixed with "default:" are treated as
|
|
1618
|
+
* ARCHIVE_ENTRY_ACL_TYPE_DEFAULT unless type is ARCHIVE_ENTRY_ACL_TYPE_NFS4
|
|
1619
|
+
*/
|
|
1620
|
+
int
|
|
1621
|
+
archive_acl_from_text_l(struct archive_acl *acl, const char *text,
|
|
1622
|
+
int want_type, struct archive_string_conv *sc)
|
|
1623
|
+
{
|
|
1624
|
+
struct {
|
|
1625
|
+
const char *start;
|
|
1626
|
+
const char *end;
|
|
1627
|
+
} field[6], name;
|
|
1628
|
+
|
|
1629
|
+
const char *s, *st;
|
|
1630
|
+
int numfields, fields, n, r, sol, ret;
|
|
1631
|
+
int type, types, tag, permset, id;
|
|
1632
|
+
size_t len;
|
|
1633
|
+
char sep;
|
|
1634
|
+
|
|
1635
|
+
switch (want_type) {
|
|
1636
|
+
case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
|
|
1637
|
+
want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
|
|
1638
|
+
__LA_FALLTHROUGH;
|
|
1639
|
+
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
|
|
1640
|
+
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
|
|
1641
|
+
numfields = 5;
|
|
1642
|
+
break;
|
|
1643
|
+
case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
|
|
1644
|
+
numfields = 6;
|
|
1645
|
+
break;
|
|
1646
|
+
default:
|
|
1647
|
+
return (ARCHIVE_FATAL);
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1650
|
+
ret = ARCHIVE_OK;
|
|
1651
|
+
types = 0;
|
|
1652
|
+
|
|
1653
|
+
while (text != NULL && *text != '\0') {
|
|
1654
|
+
/*
|
|
1655
|
+
* Parse the fields out of the next entry,
|
|
1656
|
+
* advance 'text' to start of next entry.
|
|
1657
|
+
*/
|
|
1658
|
+
fields = 0;
|
|
1659
|
+
do {
|
|
1660
|
+
const char *start, *end;
|
|
1661
|
+
next_field(&text, &start, &end, &sep);
|
|
1662
|
+
if (fields < numfields) {
|
|
1663
|
+
field[fields].start = start;
|
|
1664
|
+
field[fields].end = end;
|
|
1665
|
+
}
|
|
1666
|
+
++fields;
|
|
1667
|
+
} while (sep == ':');
|
|
1668
|
+
|
|
1669
|
+
/* Set remaining fields to blank. */
|
|
1670
|
+
for (n = fields; n < numfields; ++n)
|
|
1671
|
+
field[n].start = field[n].end = NULL;
|
|
1672
|
+
|
|
1673
|
+
if (field[0].start != NULL && *(field[0].start) == '#') {
|
|
1674
|
+
/* Comment, skip entry */
|
|
1675
|
+
continue;
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1678
|
+
n = 0;
|
|
1679
|
+
sol = 0;
|
|
1680
|
+
id = -1;
|
|
1681
|
+
permset = 0;
|
|
1682
|
+
name.start = name.end = NULL;
|
|
1683
|
+
|
|
1684
|
+
if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
|
|
1685
|
+
/* POSIX.1e ACLs */
|
|
1686
|
+
/*
|
|
1687
|
+
* Default keyword "default:user::rwx"
|
|
1688
|
+
* if found, we have one more field
|
|
1689
|
+
*
|
|
1690
|
+
* We also support old Solaris extension:
|
|
1691
|
+
* "defaultuser::rwx" is the default ACL corresponding
|
|
1692
|
+
* to "user::rwx", etc. valid only for first field
|
|
1693
|
+
*/
|
|
1694
|
+
s = field[0].start;
|
|
1695
|
+
len = field[0].end - field[0].start;
|
|
1696
|
+
if (*s == 'd' && (len == 1 || (len >= 7
|
|
1697
|
+
&& memcmp((s + 1), "efault", 6) == 0))) {
|
|
1698
|
+
type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
|
|
1699
|
+
if (len > 7)
|
|
1700
|
+
field[0].start += 7;
|
|
1701
|
+
else
|
|
1702
|
+
n = 1;
|
|
1703
|
+
} else
|
|
1704
|
+
type = want_type;
|
|
1705
|
+
|
|
1706
|
+
/* Check for a numeric ID in field n+1 or n+3. */
|
|
1707
|
+
isint(field[n + 1].start, field[n + 1].end, &id);
|
|
1708
|
+
/* Field n+3 is optional. */
|
|
1709
|
+
if (id == -1 && fields > (n + 3))
|
|
1710
|
+
isint(field[n + 3].start, field[n + 3].end,
|
|
1711
|
+
&id);
|
|
1712
|
+
|
|
1713
|
+
tag = 0;
|
|
1714
|
+
s = field[n].start;
|
|
1715
|
+
st = field[n].start + 1;
|
|
1716
|
+
len = field[n].end - field[n].start;
|
|
1717
|
+
|
|
1718
|
+
if (len == 0) {
|
|
1719
|
+
ret = ARCHIVE_WARN;
|
|
1720
|
+
continue;
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
switch (*s) {
|
|
1724
|
+
case 'u':
|
|
1725
|
+
if (len == 1 || (len == 4
|
|
1726
|
+
&& memcmp(st, "ser", 3) == 0))
|
|
1727
|
+
tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
|
|
1728
|
+
break;
|
|
1729
|
+
case 'g':
|
|
1730
|
+
if (len == 1 || (len == 5
|
|
1731
|
+
&& memcmp(st, "roup", 4) == 0))
|
|
1732
|
+
tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
|
|
1733
|
+
break;
|
|
1734
|
+
case 'o':
|
|
1735
|
+
if (len == 1 || (len == 5
|
|
1736
|
+
&& memcmp(st, "ther", 4) == 0))
|
|
1737
|
+
tag = ARCHIVE_ENTRY_ACL_OTHER;
|
|
1738
|
+
break;
|
|
1739
|
+
case 'm':
|
|
1740
|
+
if (len == 1 || (len == 4
|
|
1741
|
+
&& memcmp(st, "ask", 3) == 0))
|
|
1742
|
+
tag = ARCHIVE_ENTRY_ACL_MASK;
|
|
1743
|
+
break;
|
|
1744
|
+
default:
|
|
1745
|
+
break;
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
switch (tag) {
|
|
1749
|
+
case ARCHIVE_ENTRY_ACL_OTHER:
|
|
1750
|
+
case ARCHIVE_ENTRY_ACL_MASK:
|
|
1751
|
+
if (fields == (n + 2)
|
|
1752
|
+
&& field[n + 1].start < field[n + 1].end
|
|
1753
|
+
&& ismode(field[n + 1].start,
|
|
1754
|
+
field[n + 1].end, &permset)) {
|
|
1755
|
+
/* This is Solaris-style "other:rwx" */
|
|
1756
|
+
sol = 1;
|
|
1757
|
+
} else if (fields == (n + 3) &&
|
|
1758
|
+
field[n + 1].start < field[n + 1].end) {
|
|
1759
|
+
/* Invalid mask or other field */
|
|
1760
|
+
ret = ARCHIVE_WARN;
|
|
1761
|
+
continue;
|
|
1762
|
+
}
|
|
1763
|
+
break;
|
|
1764
|
+
case ARCHIVE_ENTRY_ACL_USER_OBJ:
|
|
1765
|
+
case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
|
|
1766
|
+
if (id != -1 ||
|
|
1767
|
+
field[n + 1].start < field[n + 1].end) {
|
|
1768
|
+
name = field[n + 1];
|
|
1769
|
+
if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ)
|
|
1770
|
+
tag = ARCHIVE_ENTRY_ACL_USER;
|
|
1771
|
+
else
|
|
1772
|
+
tag = ARCHIVE_ENTRY_ACL_GROUP;
|
|
1773
|
+
}
|
|
1774
|
+
break;
|
|
1775
|
+
default:
|
|
1776
|
+
/* Invalid tag, skip entry */
|
|
1777
|
+
ret = ARCHIVE_WARN;
|
|
1778
|
+
continue;
|
|
1779
|
+
}
|
|
1780
|
+
|
|
1781
|
+
/*
|
|
1782
|
+
* Without "default:" we expect mode in field 3
|
|
1783
|
+
* Exception: Solaris other and mask fields
|
|
1784
|
+
*/
|
|
1785
|
+
if (permset == 0 && !ismode(field[n + 2 - sol].start,
|
|
1786
|
+
field[n + 2 - sol].end, &permset)) {
|
|
1787
|
+
/* Invalid mode, skip entry */
|
|
1788
|
+
ret = ARCHIVE_WARN;
|
|
1789
|
+
continue;
|
|
1790
|
+
}
|
|
1791
|
+
} else {
|
|
1792
|
+
/* NFS4 ACLs */
|
|
1793
|
+
s = field[0].start;
|
|
1794
|
+
len = field[0].end - field[0].start;
|
|
1795
|
+
tag = 0;
|
|
1796
|
+
|
|
1797
|
+
switch (len) {
|
|
1798
|
+
case 4:
|
|
1799
|
+
if (memcmp(s, "user", 4) == 0)
|
|
1800
|
+
tag = ARCHIVE_ENTRY_ACL_USER;
|
|
1801
|
+
break;
|
|
1802
|
+
case 5:
|
|
1803
|
+
if (memcmp(s, "group", 5) == 0)
|
|
1804
|
+
tag = ARCHIVE_ENTRY_ACL_GROUP;
|
|
1805
|
+
break;
|
|
1806
|
+
case 6:
|
|
1807
|
+
if (memcmp(s, "owner@", 6) == 0)
|
|
1808
|
+
tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
|
|
1809
|
+
else if (memcmp(s, "group@", 6) == 0)
|
|
1810
|
+
tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
|
|
1811
|
+
break;
|
|
1812
|
+
case 9:
|
|
1813
|
+
if (memcmp(s, "everyone@", 9) == 0)
|
|
1814
|
+
tag = ARCHIVE_ENTRY_ACL_EVERYONE;
|
|
1815
|
+
break;
|
|
1816
|
+
default:
|
|
1817
|
+
break;
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1820
|
+
if (tag == 0) {
|
|
1821
|
+
/* Invalid tag, skip entry */
|
|
1822
|
+
ret = ARCHIVE_WARN;
|
|
1823
|
+
continue;
|
|
1824
|
+
} else if (tag == ARCHIVE_ENTRY_ACL_USER ||
|
|
1825
|
+
tag == ARCHIVE_ENTRY_ACL_GROUP) {
|
|
1826
|
+
n = 1;
|
|
1827
|
+
name = field[1];
|
|
1828
|
+
isint(name.start, name.end, &id);
|
|
1829
|
+
} else
|
|
1830
|
+
n = 0;
|
|
1831
|
+
|
|
1832
|
+
if (!is_nfs4_perms(field[1 + n].start,
|
|
1833
|
+
field[1 + n].end, &permset)) {
|
|
1834
|
+
/* Invalid NFSv4 perms, skip entry */
|
|
1835
|
+
ret = ARCHIVE_WARN;
|
|
1836
|
+
continue;
|
|
1837
|
+
}
|
|
1838
|
+
if (!is_nfs4_flags(field[2 + n].start,
|
|
1839
|
+
field[2 + n].end, &permset)) {
|
|
1840
|
+
/* Invalid NFSv4 flags, skip entry */
|
|
1841
|
+
ret = ARCHIVE_WARN;
|
|
1842
|
+
continue;
|
|
1843
|
+
}
|
|
1844
|
+
s = field[3 + n].start;
|
|
1845
|
+
len = field[3 + n].end - field[3 + n].start;
|
|
1846
|
+
type = 0;
|
|
1847
|
+
if (len == 4) {
|
|
1848
|
+
if (memcmp(s, "deny", 4) == 0)
|
|
1849
|
+
type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
|
|
1850
|
+
} else if (len == 5) {
|
|
1851
|
+
if (memcmp(s, "allow", 5) == 0)
|
|
1852
|
+
type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
|
|
1853
|
+
else if (memcmp(s, "audit", 5) == 0)
|
|
1854
|
+
type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
|
|
1855
|
+
else if (memcmp(s, "alarm", 5) == 0)
|
|
1856
|
+
type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
|
|
1857
|
+
}
|
|
1858
|
+
if (type == 0) {
|
|
1859
|
+
/* Invalid entry type, skip entry */
|
|
1860
|
+
ret = ARCHIVE_WARN;
|
|
1861
|
+
continue;
|
|
1862
|
+
}
|
|
1863
|
+
isint(field[4 + n].start, field[4 + n].end,
|
|
1864
|
+
&id);
|
|
1865
|
+
}
|
|
1866
|
+
|
|
1867
|
+
/* Add entry to the internal list. */
|
|
1868
|
+
r = archive_acl_add_entry_len_l(acl, type, permset,
|
|
1869
|
+
tag, id, name.start, name.end - name.start, sc);
|
|
1870
|
+
if (r < ARCHIVE_WARN)
|
|
1871
|
+
return (r);
|
|
1872
|
+
if (r != ARCHIVE_OK)
|
|
1873
|
+
ret = ARCHIVE_WARN;
|
|
1874
|
+
types |= type;
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
/* Reset ACL */
|
|
1878
|
+
archive_acl_reset(acl, types);
|
|
1879
|
+
|
|
1880
|
+
return (ret);
|
|
1881
|
+
}
|
|
1882
|
+
|
|
1883
|
+
/*
|
|
1884
|
+
* Parse a string to a positive decimal integer. Returns true if
|
|
1885
|
+
* the string is non-empty and consists only of decimal digits,
|
|
1886
|
+
* false otherwise.
|
|
1887
|
+
*/
|
|
1888
|
+
static int
|
|
1889
|
+
isint(const char *start, const char *end, int *result)
|
|
1890
|
+
{
|
|
1891
|
+
int n = 0;
|
|
1892
|
+
if (start >= end)
|
|
1893
|
+
return (0);
|
|
1894
|
+
while (start < end) {
|
|
1895
|
+
if (*start < '0' || *start > '9')
|
|
1896
|
+
return (0);
|
|
1897
|
+
if (n > (INT_MAX / 10) ||
|
|
1898
|
+
(n == INT_MAX / 10 && (*start - '0') > INT_MAX % 10)) {
|
|
1899
|
+
n = INT_MAX;
|
|
1900
|
+
} else {
|
|
1901
|
+
n *= 10;
|
|
1902
|
+
n += *start - '0';
|
|
1903
|
+
}
|
|
1904
|
+
start++;
|
|
1905
|
+
}
|
|
1906
|
+
*result = n;
|
|
1907
|
+
return (1);
|
|
1908
|
+
}
|
|
1909
|
+
|
|
1910
|
+
/*
|
|
1911
|
+
* Parse a string as a mode field. Returns true if
|
|
1912
|
+
* the string is non-empty and consists only of mode characters,
|
|
1913
|
+
* false otherwise.
|
|
1914
|
+
*/
|
|
1915
|
+
static int
|
|
1916
|
+
ismode(const char *start, const char *end, int *permset)
|
|
1917
|
+
{
|
|
1918
|
+
const char *p;
|
|
1919
|
+
|
|
1920
|
+
if (start >= end)
|
|
1921
|
+
return (0);
|
|
1922
|
+
p = start;
|
|
1923
|
+
*permset = 0;
|
|
1924
|
+
while (p < end) {
|
|
1925
|
+
switch (*p++) {
|
|
1926
|
+
case 'r': case 'R':
|
|
1927
|
+
*permset |= ARCHIVE_ENTRY_ACL_READ;
|
|
1928
|
+
break;
|
|
1929
|
+
case 'w': case 'W':
|
|
1930
|
+
*permset |= ARCHIVE_ENTRY_ACL_WRITE;
|
|
1931
|
+
break;
|
|
1932
|
+
case 'x': case 'X':
|
|
1933
|
+
*permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
|
|
1934
|
+
break;
|
|
1935
|
+
case '-':
|
|
1936
|
+
break;
|
|
1937
|
+
default:
|
|
1938
|
+
return (0);
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
return (1);
|
|
1942
|
+
}
|
|
1943
|
+
|
|
1944
|
+
/*
|
|
1945
|
+
* Parse a string as a NFS4 ACL permission field.
|
|
1946
|
+
* Returns true if the string is non-empty and consists only of NFS4 ACL
|
|
1947
|
+
* permission characters, false otherwise
|
|
1948
|
+
*/
|
|
1949
|
+
static int
|
|
1950
|
+
is_nfs4_perms(const char *start, const char *end, int *permset)
|
|
1951
|
+
{
|
|
1952
|
+
const char *p = start;
|
|
1953
|
+
|
|
1954
|
+
while (p < end) {
|
|
1955
|
+
switch (*p++) {
|
|
1956
|
+
case 'r':
|
|
1957
|
+
*permset |= ARCHIVE_ENTRY_ACL_READ_DATA;
|
|
1958
|
+
break;
|
|
1959
|
+
case 'w':
|
|
1960
|
+
*permset |= ARCHIVE_ENTRY_ACL_WRITE_DATA;
|
|
1961
|
+
break;
|
|
1962
|
+
case 'x':
|
|
1963
|
+
*permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
|
|
1964
|
+
break;
|
|
1965
|
+
case 'p':
|
|
1966
|
+
*permset |= ARCHIVE_ENTRY_ACL_APPEND_DATA;
|
|
1967
|
+
break;
|
|
1968
|
+
case 'D':
|
|
1969
|
+
*permset |= ARCHIVE_ENTRY_ACL_DELETE_CHILD;
|
|
1970
|
+
break;
|
|
1971
|
+
case 'd':
|
|
1972
|
+
*permset |= ARCHIVE_ENTRY_ACL_DELETE;
|
|
1973
|
+
break;
|
|
1974
|
+
case 'a':
|
|
1975
|
+
*permset |= ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES;
|
|
1976
|
+
break;
|
|
1977
|
+
case 'A':
|
|
1978
|
+
*permset |= ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES;
|
|
1979
|
+
break;
|
|
1980
|
+
case 'R':
|
|
1981
|
+
*permset |= ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS;
|
|
1982
|
+
break;
|
|
1983
|
+
case 'W':
|
|
1984
|
+
*permset |= ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS;
|
|
1985
|
+
break;
|
|
1986
|
+
case 'c':
|
|
1987
|
+
*permset |= ARCHIVE_ENTRY_ACL_READ_ACL;
|
|
1988
|
+
break;
|
|
1989
|
+
case 'C':
|
|
1990
|
+
*permset |= ARCHIVE_ENTRY_ACL_WRITE_ACL;
|
|
1991
|
+
break;
|
|
1992
|
+
case 'o':
|
|
1993
|
+
*permset |= ARCHIVE_ENTRY_ACL_WRITE_OWNER;
|
|
1994
|
+
break;
|
|
1995
|
+
case 's':
|
|
1996
|
+
*permset |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
|
|
1997
|
+
break;
|
|
1998
|
+
case '-':
|
|
1999
|
+
break;
|
|
2000
|
+
default:
|
|
2001
|
+
return(0);
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
2004
|
+
return (1);
|
|
2005
|
+
}
|
|
2006
|
+
|
|
2007
|
+
/*
|
|
2008
|
+
* Parse a string as a NFS4 ACL flags field.
|
|
2009
|
+
* Returns true if the string is non-empty and consists only of NFS4 ACL
|
|
2010
|
+
* flag characters, false otherwise
|
|
2011
|
+
*/
|
|
2012
|
+
static int
|
|
2013
|
+
is_nfs4_flags(const char *start, const char *end, int *permset)
|
|
2014
|
+
{
|
|
2015
|
+
const char *p = start;
|
|
2016
|
+
|
|
2017
|
+
while (p < end) {
|
|
2018
|
+
switch(*p++) {
|
|
2019
|
+
case 'f':
|
|
2020
|
+
*permset |= ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT;
|
|
2021
|
+
break;
|
|
2022
|
+
case 'd':
|
|
2023
|
+
*permset |= ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT;
|
|
2024
|
+
break;
|
|
2025
|
+
case 'i':
|
|
2026
|
+
*permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY;
|
|
2027
|
+
break;
|
|
2028
|
+
case 'n':
|
|
2029
|
+
*permset |=
|
|
2030
|
+
ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT;
|
|
2031
|
+
break;
|
|
2032
|
+
case 'S':
|
|
2033
|
+
*permset |= ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS;
|
|
2034
|
+
break;
|
|
2035
|
+
case 'F':
|
|
2036
|
+
*permset |= ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS;
|
|
2037
|
+
break;
|
|
2038
|
+
case 'I':
|
|
2039
|
+
*permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERITED;
|
|
2040
|
+
break;
|
|
2041
|
+
case '-':
|
|
2042
|
+
break;
|
|
2043
|
+
default:
|
|
2044
|
+
return (0);
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
return (1);
|
|
2048
|
+
}
|
|
2049
|
+
|
|
2050
|
+
/*
|
|
2051
|
+
* Match "[:whitespace:]*(.*)[:whitespace:]*[:,\n]". *wp is updated
|
|
2052
|
+
* to point to just after the separator. *start points to the first
|
|
2053
|
+
* character of the matched text and *end just after the last
|
|
2054
|
+
* character of the matched identifier. In particular *end - *start
|
|
2055
|
+
* is the length of the field body, not including leading or trailing
|
|
2056
|
+
* whitespace.
|
|
2057
|
+
*/
|
|
2058
|
+
static void
|
|
2059
|
+
next_field(const char **p, const char **start,
|
|
2060
|
+
const char **end, char *sep)
|
|
2061
|
+
{
|
|
2062
|
+
/* Skip leading whitespace to find start of field. */
|
|
2063
|
+
while (**p == ' ' || **p == '\t' || **p == '\n') {
|
|
2064
|
+
(*p)++;
|
|
2065
|
+
}
|
|
2066
|
+
*start = *p;
|
|
2067
|
+
|
|
2068
|
+
/* Scan for the separator. */
|
|
2069
|
+
while (**p != '\0' && **p != ',' && **p != ':' && **p != '\n' &&
|
|
2070
|
+
**p != '#') {
|
|
2071
|
+
(*p)++;
|
|
2072
|
+
}
|
|
2073
|
+
*sep = **p;
|
|
2074
|
+
|
|
2075
|
+
/* Locate end of field, trim trailing whitespace if necessary */
|
|
2076
|
+
if (*p == *start) {
|
|
2077
|
+
*end = *p;
|
|
2078
|
+
} else {
|
|
2079
|
+
*end = *p - 1;
|
|
2080
|
+
while (**end == ' ' || **end == '\t' || **end == '\n') {
|
|
2081
|
+
(*end)--;
|
|
2082
|
+
}
|
|
2083
|
+
(*end)++;
|
|
2084
|
+
}
|
|
2085
|
+
|
|
2086
|
+
/* Handle in-field comments */
|
|
2087
|
+
if (*sep == '#') {
|
|
2088
|
+
while (**p != '\0' && **p != ',' && **p != '\n') {
|
|
2089
|
+
(*p)++;
|
|
2090
|
+
}
|
|
2091
|
+
*sep = **p;
|
|
2092
|
+
}
|
|
2093
|
+
|
|
2094
|
+
/* Adjust scanner location. */
|
|
2095
|
+
if (**p != '\0')
|
|
2096
|
+
(*p)++;
|
|
2097
|
+
}
|