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.
Files changed (295) hide show
  1. checksums.yaml +4 -4
  2. data/ext/extconf.rb +2 -9
  3. data/ext/libarchive-0.1.1/ext/archive_read_support_compression.c +6 -6
  4. data/ext/libarchive-0.1.1/ext/archive_read_support_compression.o +0 -0
  5. data/ext/libarchive-0.1.1/ext/archive_read_support_format.o +0 -0
  6. data/ext/libarchive-0.1.1/ext/archive_write_open_rb_str.c +1 -1
  7. data/ext/libarchive-0.1.1/ext/archive_write_open_rb_str.o +0 -0
  8. data/ext/libarchive-0.1.1/ext/archive_write_set_compression.c +5 -5
  9. data/ext/libarchive-0.1.1/ext/archive_write_set_compression.o +0 -0
  10. data/ext/libarchive-0.1.1/ext/config.h +23 -0
  11. data/ext/libarchive-0.1.1/ext/config.log +230 -0
  12. data/ext/libarchive-0.1.1/ext/config.status +671 -0
  13. data/ext/libarchive-0.1.1/ext/libarchive.c +1 -1
  14. data/ext/libarchive-0.1.1/ext/libarchive.o +0 -0
  15. data/ext/libarchive-0.1.1/ext/libarchive_archive.c +7 -7
  16. data/ext/libarchive-0.1.1/ext/libarchive_archive.o +0 -0
  17. data/ext/libarchive-0.1.1/ext/libarchive_entry.c +6 -0
  18. data/ext/libarchive-0.1.1/ext/libarchive_entry.o +0 -0
  19. data/ext/libarchive-0.1.1/ext/libarchive_reader.c +6 -4
  20. data/ext/libarchive-0.1.1/ext/libarchive_reader.o +0 -0
  21. data/ext/libarchive-0.1.1/ext/libarchive_ruby.so +0 -0
  22. data/ext/libarchive-0.1.1/ext/libarchive_win32.h +1 -1
  23. data/ext/libarchive-0.1.1/ext/libarchive_writer.c +2 -2
  24. data/ext/libarchive-0.1.1/ext/libarchive_writer.o +0 -0
  25. data/ext/libarchive-3.6.2/Makefile.in +16892 -0
  26. data/ext/libarchive-3.6.2/build/autoconf/ax_append_compile_flags.m4 +67 -0
  27. data/ext/libarchive-3.6.2/build/autoconf/ax_append_flag.m4 +71 -0
  28. data/ext/libarchive-3.6.2/build/autoconf/ax_check_compile_flag.m4 +74 -0
  29. data/ext/libarchive-3.6.2/build/autoconf/ax_require_defined.m4 +37 -0
  30. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/build/autoconf/check_stdcall_func.m4 +0 -0
  31. data/ext/libarchive-3.6.2/build/autoconf/compile +348 -0
  32. data/ext/libarchive-3.6.2/build/autoconf/config.guess +1754 -0
  33. data/ext/libarchive-3.6.2/build/autoconf/config.rpath +696 -0
  34. data/ext/libarchive-3.6.2/build/autoconf/config.sub +1890 -0
  35. data/ext/libarchive-3.6.2/build/autoconf/depcomp +791 -0
  36. data/ext/libarchive-3.6.2/build/autoconf/iconv.m4 +271 -0
  37. data/ext/libarchive-3.6.2/build/autoconf/install-sh +541 -0
  38. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/build/autoconf/la_uid_t.m4 +0 -0
  39. data/ext/libarchive-3.6.2/build/autoconf/lib-ld.m4 +109 -0
  40. data/ext/libarchive-3.6.2/build/autoconf/lib-link.m4 +777 -0
  41. data/ext/libarchive-3.6.2/build/autoconf/lib-prefix.m4 +224 -0
  42. data/ext/libarchive-3.6.2/build/autoconf/ltmain.sh +11251 -0
  43. data/ext/libarchive-3.6.2/build/autoconf/m4_ax_compile_check_sizeof.m4 +115 -0
  44. data/ext/libarchive-3.6.2/build/autoconf/missing +215 -0
  45. data/ext/libarchive-3.6.2/build/autoconf/test-driver +153 -0
  46. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/build/pkgconfig/libarchive.pc.in +4 -1
  47. data/ext/libarchive-3.6.2/config.h.in +1504 -0
  48. data/ext/libarchive-3.6.2/configure +25558 -0
  49. data/ext/libarchive-3.6.2/libarchive/archive.h +1212 -0
  50. data/ext/libarchive-3.6.2/libarchive/archive_acl.c +2097 -0
  51. data/ext/libarchive-3.6.2/libarchive/archive_acl_private.h +83 -0
  52. data/ext/libarchive-3.6.2/libarchive/archive_blake2.h +197 -0
  53. data/ext/libarchive-3.6.2/libarchive/archive_blake2_impl.h +161 -0
  54. data/ext/libarchive-3.6.2/libarchive/archive_blake2s_ref.c +369 -0
  55. data/ext/libarchive-3.6.2/libarchive/archive_blake2sp_ref.c +361 -0
  56. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_check_magic.c +63 -22
  57. data/ext/libarchive-3.6.2/libarchive/archive_cmdline.c +227 -0
  58. data/ext/libarchive-3.6.2/libarchive/archive_cmdline_private.h +47 -0
  59. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_crc32.h +17 -0
  60. data/ext/libarchive-3.6.2/libarchive/archive_cryptor.c +534 -0
  61. data/ext/libarchive-3.6.2/libarchive/archive_cryptor_private.h +188 -0
  62. data/ext/libarchive-3.6.2/libarchive/archive_digest.c +1505 -0
  63. data/ext/libarchive-3.6.2/libarchive/archive_digest_private.h +416 -0
  64. data/ext/libarchive-3.6.2/libarchive/archive_disk_acl_darwin.c +559 -0
  65. data/ext/libarchive-3.6.2/libarchive/archive_disk_acl_freebsd.c +712 -0
  66. data/ext/libarchive-3.6.2/libarchive/archive_disk_acl_linux.c +760 -0
  67. data/ext/libarchive-3.6.2/libarchive/archive_disk_acl_sunos.c +824 -0
  68. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_endian.h +48 -15
  69. data/ext/libarchive-3.6.2/libarchive/archive_entry.c +2149 -0
  70. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry.h +305 -106
  71. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_copy_bhfi.c +5 -4
  72. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_copy_stat.c +9 -3
  73. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_link_resolver.c +104 -62
  74. data/ext/libarchive-3.6.2/libarchive/archive_entry_locale.h +92 -0
  75. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_private.h +65 -49
  76. data/ext/libarchive-3.6.2/libarchive/archive_entry_sparse.c +156 -0
  77. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_stat.c +6 -6
  78. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_strmode.c +1 -1
  79. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_xattr.c +4 -6
  80. data/ext/libarchive-3.6.2/libarchive/archive_getdate.c +1165 -0
  81. data/ext/libarchive-3.6.2/libarchive/archive_getdate.h +39 -0
  82. data/ext/libarchive-3.6.2/libarchive/archive_hmac.c +334 -0
  83. data/ext/libarchive-3.6.2/libarchive/archive_hmac_private.h +117 -0
  84. data/ext/libarchive-3.6.2/libarchive/archive_match.c +1875 -0
  85. data/ext/libarchive-3.6.2/libarchive/archive_openssl_evp_private.h +53 -0
  86. data/ext/libarchive-3.6.2/libarchive/archive_openssl_hmac_private.h +54 -0
  87. data/ext/libarchive-3.6.2/libarchive/archive_options.c +218 -0
  88. data/ext/libarchive-3.6.2/libarchive/archive_options_private.h +51 -0
  89. data/ext/libarchive-3.6.2/libarchive/archive_pack_dev.c +337 -0
  90. data/ext/libarchive-3.6.2/libarchive/archive_pack_dev.h +49 -0
  91. data/ext/libarchive-3.6.2/libarchive/archive_pathmatch.c +463 -0
  92. data/ext/libarchive-3.6.2/libarchive/archive_pathmatch.h +52 -0
  93. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_platform.h +77 -9
  94. data/ext/libarchive-3.6.2/libarchive/archive_platform_acl.h +55 -0
  95. data/ext/libarchive-3.6.2/libarchive/archive_platform_xattr.h +47 -0
  96. data/ext/libarchive-3.6.2/libarchive/archive_ppmd7.c +1168 -0
  97. data/ext/libarchive-3.6.2/libarchive/archive_ppmd7_private.h +119 -0
  98. data/ext/libarchive-3.6.2/libarchive/archive_ppmd8.c +1287 -0
  99. data/ext/libarchive-3.6.2/libarchive/archive_ppmd8_private.h +148 -0
  100. data/ext/libarchive-3.6.2/libarchive/archive_ppmd_private.h +151 -0
  101. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_private.h +74 -18
  102. data/ext/libarchive-3.6.2/libarchive/archive_random.c +272 -0
  103. data/ext/libarchive-3.6.2/libarchive/archive_random_private.h +36 -0
  104. data/ext/libarchive-3.6.2/libarchive/archive_rb.c +709 -0
  105. data/ext/libarchive-3.6.2/libarchive/archive_rb.h +113 -0
  106. data/ext/libarchive-3.6.2/libarchive/archive_read.c +1756 -0
  107. data/ext/libarchive-3.6.2/libarchive/archive_read_add_passphrase.c +190 -0
  108. data/ext/libarchive-3.6.2/libarchive/archive_read_append_filter.c +204 -0
  109. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_data_into_fd.c +64 -18
  110. data/ext/libarchive-3.6.2/libarchive/archive_read_disk_entry_from_file.c +1086 -0
  111. data/ext/libarchive-3.6.2/libarchive/archive_read_disk_posix.c +2732 -0
  112. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_disk_private.h +40 -4
  113. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_disk_set_standard_lookup.c +21 -11
  114. data/ext/libarchive-3.6.2/libarchive/archive_read_disk_windows.c +2479 -0
  115. data/ext/libarchive-3.6.2/libarchive/archive_read_extract.c +60 -0
  116. data/ext/{libarchive-2.8.4/libarchive/archive_read_extract.c → libarchive-3.6.2/libarchive/archive_read_extract2.c} +34 -61
  117. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_open_fd.c +70 -49
  118. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_open_file.c +38 -23
  119. data/ext/libarchive-3.6.2/libarchive/archive_read_open_filename.c +586 -0
  120. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_open_memory.c +58 -28
  121. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_private.h +127 -59
  122. data/ext/libarchive-3.6.2/libarchive/archive_read_set_format.c +117 -0
  123. data/ext/libarchive-3.6.2/libarchive/archive_read_set_options.c +133 -0
  124. 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
  125. data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_by_code.c +83 -0
  126. 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
  127. 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
  128. data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_grzip.c +112 -0
  129. 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
  130. data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_lrzip.c +122 -0
  131. data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_lz4.c +742 -0
  132. data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_lzop.c +499 -0
  133. 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
  134. 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
  135. 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
  136. 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
  137. 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
  138. data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_zstd.c +297 -0
  139. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_7zip.c +3900 -0
  140. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_all.c +89 -0
  141. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_ar.c +126 -72
  142. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_by_code.c +92 -0
  143. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_cab.c +3228 -0
  144. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_cpio.c +1104 -0
  145. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_empty.c +14 -11
  146. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_iso9660.c +990 -541
  147. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_lha.c +2916 -0
  148. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_mtree.c +2150 -0
  149. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_rar.c +3797 -0
  150. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_rar5.c +4251 -0
  151. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_raw.c +38 -31
  152. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_tar.c +1157 -629
  153. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_warc.c +848 -0
  154. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_xar.c +439 -258
  155. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_zip.c +4270 -0
  156. data/ext/libarchive-3.6.2/libarchive/archive_string.c +4240 -0
  157. data/ext/libarchive-3.6.2/libarchive/archive_string.h +243 -0
  158. data/ext/libarchive-3.6.2/libarchive/archive_string_composition.h +2292 -0
  159. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_string_sprintf.c +44 -16
  160. data/ext/libarchive-3.6.2/libarchive/archive_util.c +655 -0
  161. data/ext/libarchive-3.6.2/libarchive/archive_version_details.c +151 -0
  162. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_virtual.c +85 -16
  163. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_windows.c +214 -541
  164. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_windows.h +74 -106
  165. data/ext/libarchive-3.6.2/libarchive/archive_write.c +828 -0
  166. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter.c +72 -0
  167. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_b64encode.c +304 -0
  168. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_by_name.c +77 -0
  169. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_bzip2.c +401 -0
  170. 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
  171. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_grzip.c +135 -0
  172. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_gzip.c +442 -0
  173. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_lrzip.c +197 -0
  174. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_lz4.c +700 -0
  175. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_lzop.c +478 -0
  176. 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
  177. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_program.c +391 -0
  178. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_uuencode.c +295 -0
  179. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_xz.c +545 -0
  180. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_zstd.c +418 -0
  181. data/ext/libarchive-3.6.2/libarchive/archive_write_disk_posix.c +4711 -0
  182. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_disk_private.h +9 -2
  183. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_disk_set_standard_lookup.c +30 -29
  184. data/ext/libarchive-3.6.2/libarchive/archive_write_disk_windows.c +2842 -0
  185. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_open_fd.c +15 -10
  186. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_open_file.c +15 -9
  187. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_open_filename.c +128 -20
  188. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_open_memory.c +7 -18
  189. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_private.h +72 -29
  190. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format.c +56 -3
  191. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_7zip.c +2322 -0
  192. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_ar.c +54 -34
  193. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_by_name.c +20 -2
  194. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_cpio.c +11 -0
  195. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_cpio_binary.c +610 -0
  196. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_cpio_newc.c +457 -0
  197. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_cpio_odc.c +500 -0
  198. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_filter_by_ext.c +142 -0
  199. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_gnutar.c +755 -0
  200. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_iso9660.c +8165 -0
  201. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_mtree.c +2217 -0
  202. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_pax.c +1049 -387
  203. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_private.h +42 -0
  204. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_raw.c +125 -0
  205. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_shar.c +62 -47
  206. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_ustar.c +279 -108
  207. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_v7tar.c +638 -0
  208. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_warc.c +453 -0
  209. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_xar.c +3259 -0
  210. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_zip.c +1704 -0
  211. data/ext/libarchive-3.6.2/libarchive/archive_write_set_options.c +130 -0
  212. data/ext/libarchive-3.6.2/libarchive/archive_write_set_passphrase.c +95 -0
  213. data/ext/libarchive-3.6.2/libarchive/archive_xxhash.h +48 -0
  214. data/ext/libarchive-3.6.2/libarchive/config_freebsd.h +271 -0
  215. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/filter_fork.h +10 -5
  216. data/ext/{libarchive-2.8.4/libarchive/filter_fork.c → libarchive-3.6.2/libarchive/filter_fork_posix.c} +98 -19
  217. data/ext/libarchive-3.6.2/libarchive/filter_fork_windows.c +236 -0
  218. data/ext/libarchive-3.6.2/libarchive/xxhash.c +525 -0
  219. data/ext/libarchive-static-makefile +144 -80
  220. data/ext/libarchive-static-wrapper-makefile +1 -1
  221. data/ext/zlib-1.2.13/Makefile.in +404 -0
  222. data/ext/{zlib-1.2.5 → zlib-1.2.13}/adler32.c +51 -34
  223. data/ext/{zlib-1.2.5 → zlib-1.2.13}/compress.c +27 -21
  224. data/ext/zlib-1.2.13/configure +922 -0
  225. data/ext/zlib-1.2.13/crc32.c +1125 -0
  226. data/ext/zlib-1.2.13/crc32.h +9446 -0
  227. data/ext/{zlib-1.2.5 → zlib-1.2.13}/deflate.c +842 -459
  228. data/ext/{zlib-1.2.5 → zlib-1.2.13}/deflate.h +37 -33
  229. data/ext/{zlib-1.2.5 → zlib-1.2.13}/gzclose.c +0 -0
  230. data/ext/{zlib-1.2.5 → zlib-1.2.13}/gzguts.h +103 -16
  231. data/ext/{zlib-1.2.5 → zlib-1.2.13}/gzlib.c +155 -53
  232. data/ext/zlib-1.2.13/gzread.c +650 -0
  233. data/ext/zlib-1.2.13/gzwrite.c +677 -0
  234. data/ext/{zlib-1.2.5 → zlib-1.2.13}/infback.c +24 -12
  235. data/ext/{zlib-1.2.5 → zlib-1.2.13}/inffast.c +49 -66
  236. data/ext/{zlib-1.2.5 → zlib-1.2.13}/inffast.h +0 -0
  237. data/ext/{zlib-1.2.5 → zlib-1.2.13}/inffixed.h +3 -3
  238. data/ext/{zlib-1.2.5 → zlib-1.2.13}/inflate.c +209 -94
  239. data/ext/{zlib-1.2.5 → zlib-1.2.13}/inflate.h +9 -5
  240. data/ext/{zlib-1.2.5 → zlib-1.2.13}/inftrees.c +24 -50
  241. data/ext/{zlib-1.2.5 → zlib-1.2.13}/inftrees.h +1 -1
  242. data/ext/{zlib-1.2.5 → zlib-1.2.13}/trees.c +135 -198
  243. data/ext/{zlib-1.2.5 → zlib-1.2.13}/trees.h +0 -0
  244. data/ext/zlib-1.2.13/uncompr.c +93 -0
  245. data/ext/{zlib-1.2.5 → zlib-1.2.13}/zconf.h +182 -63
  246. data/ext/{zlib-1.2.5 → zlib-1.2.13}/zlib.h +617 -295
  247. data/ext/{zlib-1.2.5 → zlib-1.2.13}/zutil.c +50 -41
  248. data/ext/{zlib-1.2.5 → zlib-1.2.13}/zutil.h +83 -82
  249. metadata +241 -133
  250. data/ext/libarchive-0.1.1/libarchive.c +0 -1762
  251. data/ext/libarchive-2.8.4/Makefile.in +0 -7076
  252. data/ext/libarchive-2.8.4/build/autoconf/compile +0 -143
  253. data/ext/libarchive-2.8.4/build/autoconf/config.guess +0 -1502
  254. data/ext/libarchive-2.8.4/build/autoconf/config.sub +0 -1708
  255. data/ext/libarchive-2.8.4/build/autoconf/depcomp +0 -630
  256. data/ext/libarchive-2.8.4/build/autoconf/install-sh +0 -291
  257. data/ext/libarchive-2.8.4/build/autoconf/ltmain.sh +0 -8406
  258. data/ext/libarchive-2.8.4/build/autoconf/missing +0 -376
  259. data/ext/libarchive-2.8.4/config.h.in +0 -772
  260. data/ext/libarchive-2.8.4/configure +0 -17916
  261. data/ext/libarchive-2.8.4/libarchive/archive.h +0 -741
  262. data/ext/libarchive-2.8.4/libarchive/archive_entry.c +0 -2202
  263. data/ext/libarchive-2.8.4/libarchive/archive_hash.h +0 -281
  264. data/ext/libarchive-2.8.4/libarchive/archive_read.c +0 -1249
  265. data/ext/libarchive-2.8.4/libarchive/archive_read_disk.c +0 -198
  266. data/ext/libarchive-2.8.4/libarchive/archive_read_disk_entry_from_file.c +0 -570
  267. data/ext/libarchive-2.8.4/libarchive/archive_read_open_filename.c +0 -272
  268. data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_cpio.c +0 -777
  269. data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_mtree.c +0 -1304
  270. data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_zip.c +0 -903
  271. data/ext/libarchive-2.8.4/libarchive/archive_string.c +0 -453
  272. data/ext/libarchive-2.8.4/libarchive/archive_string.h +0 -148
  273. data/ext/libarchive-2.8.4/libarchive/archive_util.c +0 -391
  274. data/ext/libarchive-2.8.4/libarchive/archive_write.c +0 -466
  275. data/ext/libarchive-2.8.4/libarchive/archive_write_disk.c +0 -2628
  276. data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_bzip2.c +0 -408
  277. data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_gzip.c +0 -477
  278. data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_none.c +0 -257
  279. data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_program.c +0 -347
  280. data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_xz.c +0 -438
  281. data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_cpio.c +0 -344
  282. data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_cpio_newc.c +0 -295
  283. data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_mtree.c +0 -1050
  284. data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_zip.c +0 -667
  285. data/ext/libarchive-2.8.4/libarchive/config_freebsd.h +0 -154
  286. data/ext/libarchive-2.8.4/libarchive/filter_fork_windows.c +0 -113
  287. data/ext/zlib-1.2.5/Makefile.in +0 -257
  288. data/ext/zlib-1.2.5/configure +0 -596
  289. data/ext/zlib-1.2.5/crc32.c +0 -442
  290. data/ext/zlib-1.2.5/crc32.h +0 -441
  291. data/ext/zlib-1.2.5/example.c +0 -565
  292. data/ext/zlib-1.2.5/gzread.c +0 -653
  293. data/ext/zlib-1.2.5/gzwrite.c +0 -531
  294. data/ext/zlib-1.2.5/minigzip.c +0 -440
  295. data/ext/zlib-1.2.5/uncompr.c +0 -59
@@ -0,0 +1,4711 @@
1
+ /*-
2
+ * Copyright (c) 2003-2010 Tim Kientzle
3
+ * Copyright (c) 2012 Michihiro NAKAJIMA
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
+ * in this position and unchanged.
12
+ * 2. Redistributions in binary form must reproduce the above copyright
13
+ * notice, this list of conditions and the following disclaimer in the
14
+ * documentation and/or other materials provided with the distribution.
15
+ *
16
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
17
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
20
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
+ */
27
+
28
+ #include "archive_platform.h"
29
+ __FBSDID("$FreeBSD$");
30
+
31
+ #if !defined(_WIN32) || defined(__CYGWIN__)
32
+
33
+ #ifdef HAVE_SYS_TYPES_H
34
+ #include <sys/types.h>
35
+ #endif
36
+ #ifdef HAVE_SYS_ACL_H
37
+ #include <sys/acl.h>
38
+ #endif
39
+ #ifdef HAVE_SYS_EXTATTR_H
40
+ #include <sys/extattr.h>
41
+ #endif
42
+ #if HAVE_SYS_XATTR_H
43
+ #include <sys/xattr.h>
44
+ #elif HAVE_ATTR_XATTR_H
45
+ #include <attr/xattr.h>
46
+ #endif
47
+ #ifdef HAVE_SYS_EA_H
48
+ #include <sys/ea.h>
49
+ #endif
50
+ #ifdef HAVE_SYS_IOCTL_H
51
+ #include <sys/ioctl.h>
52
+ #endif
53
+ #ifdef HAVE_SYS_STAT_H
54
+ #include <sys/stat.h>
55
+ #endif
56
+ #ifdef HAVE_SYS_TIME_H
57
+ #include <sys/time.h>
58
+ #endif
59
+ #ifdef HAVE_SYS_UTIME_H
60
+ #include <sys/utime.h>
61
+ #endif
62
+ #ifdef HAVE_COPYFILE_H
63
+ #include <copyfile.h>
64
+ #endif
65
+ #ifdef HAVE_ERRNO_H
66
+ #include <errno.h>
67
+ #endif
68
+ #ifdef HAVE_FCNTL_H
69
+ #include <fcntl.h>
70
+ #endif
71
+ #ifdef HAVE_GRP_H
72
+ #include <grp.h>
73
+ #endif
74
+ #ifdef HAVE_LANGINFO_H
75
+ #include <langinfo.h>
76
+ #endif
77
+ #ifdef HAVE_LINUX_FS_H
78
+ #include <linux/fs.h> /* for Linux file flags */
79
+ #endif
80
+ /*
81
+ * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
82
+ * As the include guards don't agree, the order of include is important.
83
+ */
84
+ #ifdef HAVE_LINUX_EXT2_FS_H
85
+ #include <linux/ext2_fs.h> /* for Linux file flags */
86
+ #endif
87
+ #if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
88
+ #include <ext2fs/ext2_fs.h> /* Linux file flags, broken on Cygwin */
89
+ #endif
90
+ #ifdef HAVE_LIMITS_H
91
+ #include <limits.h>
92
+ #endif
93
+ #ifdef HAVE_PWD_H
94
+ #include <pwd.h>
95
+ #endif
96
+ #include <stdio.h>
97
+ #ifdef HAVE_STDLIB_H
98
+ #include <stdlib.h>
99
+ #endif
100
+ #ifdef HAVE_STRING_H
101
+ #include <string.h>
102
+ #endif
103
+ #ifdef HAVE_UNISTD_H
104
+ #include <unistd.h>
105
+ #endif
106
+ #ifdef HAVE_UTIME_H
107
+ #include <utime.h>
108
+ #endif
109
+ #ifdef F_GETTIMES /* Tru64 specific */
110
+ #include <sys/fcntl1.h>
111
+ #endif
112
+
113
+ /*
114
+ * Macro to cast st_mtime and time_t to an int64 so that 2 numbers can reliably be compared.
115
+ *
116
+ * It assumes that the input is an integer type of no more than 64 bits.
117
+ * If the number is less than zero, t must be a signed type, so it fits in
118
+ * int64_t. Otherwise, it's a nonnegative value so we can cast it to uint64_t
119
+ * without loss. But it could be a large unsigned value, so we have to clip it
120
+ * to INT64_MAX.*
121
+ */
122
+ #define to_int64_time(t) \
123
+ ((t) < 0 ? (int64_t)(t) : (uint64_t)(t) > (uint64_t)INT64_MAX ? INT64_MAX : (int64_t)(t))
124
+
125
+ #if __APPLE__
126
+ #include <TargetConditionals.h>
127
+ #if TARGET_OS_MAC && !TARGET_OS_EMBEDDED && HAVE_QUARANTINE_H
128
+ #include <quarantine.h>
129
+ #define HAVE_QUARANTINE 1
130
+ #endif
131
+ #endif
132
+
133
+ #ifdef HAVE_ZLIB_H
134
+ #include <zlib.h>
135
+ #endif
136
+
137
+ /* TODO: Support Mac OS 'quarantine' feature. This is really just a
138
+ * standard tag to mark files that have been downloaded as "tainted".
139
+ * On Mac OS, we should mark the extracted files as tainted if the
140
+ * archive being read was tainted. Windows has a similar feature; we
141
+ * should investigate ways to support this generically. */
142
+
143
+ #include "archive.h"
144
+ #include "archive_acl_private.h"
145
+ #include "archive_string.h"
146
+ #include "archive_endian.h"
147
+ #include "archive_entry.h"
148
+ #include "archive_private.h"
149
+ #include "archive_write_disk_private.h"
150
+
151
+ #ifndef O_BINARY
152
+ #define O_BINARY 0
153
+ #endif
154
+ #ifndef O_CLOEXEC
155
+ #define O_CLOEXEC 0
156
+ #endif
157
+
158
+ /* Ignore non-int O_NOFOLLOW constant. */
159
+ /* gnulib's fcntl.h does this on AIX, but it seems practical everywhere */
160
+ #if defined O_NOFOLLOW && !(INT_MIN <= O_NOFOLLOW && O_NOFOLLOW <= INT_MAX)
161
+ #undef O_NOFOLLOW
162
+ #endif
163
+
164
+ #ifndef O_NOFOLLOW
165
+ #define O_NOFOLLOW 0
166
+ #endif
167
+
168
+ #ifndef AT_FDCWD
169
+ #define AT_FDCWD -100
170
+ #endif
171
+
172
+ struct fixup_entry {
173
+ struct fixup_entry *next;
174
+ struct archive_acl acl;
175
+ mode_t mode;
176
+ __LA_MODE_T filetype;
177
+ int64_t atime;
178
+ int64_t birthtime;
179
+ int64_t mtime;
180
+ int64_t ctime;
181
+ unsigned long atime_nanos;
182
+ unsigned long birthtime_nanos;
183
+ unsigned long mtime_nanos;
184
+ unsigned long ctime_nanos;
185
+ unsigned long fflags_set;
186
+ size_t mac_metadata_size;
187
+ void *mac_metadata;
188
+ int fixup; /* bitmask of what needs fixing */
189
+ char *name;
190
+ };
191
+
192
+ /*
193
+ * We use a bitmask to track which operations remain to be done for
194
+ * this file. In particular, this helps us avoid unnecessary
195
+ * operations when it's possible to take care of one step as a
196
+ * side-effect of another. For example, mkdir() can specify the mode
197
+ * for the newly-created object but symlink() cannot. This means we
198
+ * can skip chmod() if mkdir() succeeded, but we must explicitly
199
+ * chmod() if we're trying to create a directory that already exists
200
+ * (mkdir() failed) or if we're restoring a symlink. Similarly, we
201
+ * need to verify UID/GID before trying to restore SUID/SGID bits;
202
+ * that verification can occur explicitly through a stat() call or
203
+ * implicitly because of a successful chown() call.
204
+ */
205
+ #define TODO_MODE_FORCE 0x40000000
206
+ #define TODO_MODE_BASE 0x20000000
207
+ #define TODO_SUID 0x10000000
208
+ #define TODO_SUID_CHECK 0x08000000
209
+ #define TODO_SGID 0x04000000
210
+ #define TODO_SGID_CHECK 0x02000000
211
+ #define TODO_APPLEDOUBLE 0x01000000
212
+ #define TODO_MODE (TODO_MODE_BASE|TODO_SUID|TODO_SGID)
213
+ #define TODO_TIMES ARCHIVE_EXTRACT_TIME
214
+ #define TODO_OWNER ARCHIVE_EXTRACT_OWNER
215
+ #define TODO_FFLAGS ARCHIVE_EXTRACT_FFLAGS
216
+ #define TODO_ACLS ARCHIVE_EXTRACT_ACL
217
+ #define TODO_XATTR ARCHIVE_EXTRACT_XATTR
218
+ #define TODO_MAC_METADATA ARCHIVE_EXTRACT_MAC_METADATA
219
+ #define TODO_HFS_COMPRESSION ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED
220
+
221
+ struct archive_write_disk {
222
+ struct archive archive;
223
+
224
+ mode_t user_umask;
225
+ struct fixup_entry *fixup_list;
226
+ struct fixup_entry *current_fixup;
227
+ int64_t user_uid;
228
+ int skip_file_set;
229
+ int64_t skip_file_dev;
230
+ int64_t skip_file_ino;
231
+ time_t start_time;
232
+
233
+ int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid);
234
+ void (*cleanup_gid)(void *private);
235
+ void *lookup_gid_data;
236
+ int64_t (*lookup_uid)(void *private, const char *uname, int64_t uid);
237
+ void (*cleanup_uid)(void *private);
238
+ void *lookup_uid_data;
239
+
240
+ /*
241
+ * Full path of last file to satisfy symlink checks.
242
+ */
243
+ struct archive_string path_safe;
244
+
245
+ /*
246
+ * Cached stat data from disk for the current entry.
247
+ * If this is valid, pst points to st. Otherwise,
248
+ * pst is null.
249
+ */
250
+ struct stat st;
251
+ struct stat *pst;
252
+
253
+ /* Information about the object being restored right now. */
254
+ struct archive_entry *entry; /* Entry being extracted. */
255
+ char *name; /* Name of entry, possibly edited. */
256
+ struct archive_string _name_data; /* backing store for 'name' */
257
+ char *tmpname; /* Temporary name * */
258
+ struct archive_string _tmpname_data; /* backing store for 'tmpname' */
259
+ /* Tasks remaining for this object. */
260
+ int todo;
261
+ /* Tasks deferred until end-of-archive. */
262
+ int deferred;
263
+ /* Options requested by the client. */
264
+ int flags;
265
+ /* Handle for the file we're restoring. */
266
+ int fd;
267
+ /* Current offset for writing data to the file. */
268
+ int64_t offset;
269
+ /* Last offset actually written to disk. */
270
+ int64_t fd_offset;
271
+ /* Total bytes actually written to files. */
272
+ int64_t total_bytes_written;
273
+ /* Maximum size of file, -1 if unknown. */
274
+ int64_t filesize;
275
+ /* Dir we were in before this restore; only for deep paths. */
276
+ int restore_pwd;
277
+ /* Mode we should use for this entry; affected by _PERM and umask. */
278
+ mode_t mode;
279
+ /* UID/GID to use in restoring this entry. */
280
+ int64_t uid;
281
+ int64_t gid;
282
+ /*
283
+ * HFS+ Compression.
284
+ */
285
+ /* Xattr "com.apple.decmpfs". */
286
+ uint32_t decmpfs_attr_size;
287
+ unsigned char *decmpfs_header_p;
288
+ /* ResourceFork set options used for fsetxattr. */
289
+ int rsrc_xattr_options;
290
+ /* Xattr "com.apple.ResourceFork". */
291
+ unsigned char *resource_fork;
292
+ size_t resource_fork_allocated_size;
293
+ unsigned int decmpfs_block_count;
294
+ uint32_t *decmpfs_block_info;
295
+ /* Buffer for compressed data. */
296
+ unsigned char *compressed_buffer;
297
+ size_t compressed_buffer_size;
298
+ size_t compressed_buffer_remaining;
299
+ /* The offset of the ResourceFork where compressed data will
300
+ * be placed. */
301
+ uint32_t compressed_rsrc_position;
302
+ uint32_t compressed_rsrc_position_v;
303
+ /* Buffer for uncompressed data. */
304
+ char *uncompressed_buffer;
305
+ size_t block_remaining_bytes;
306
+ size_t file_remaining_bytes;
307
+ #ifdef HAVE_ZLIB_H
308
+ z_stream stream;
309
+ int stream_valid;
310
+ int decmpfs_compression_level;
311
+ #endif
312
+ };
313
+
314
+ /*
315
+ * Default mode for dirs created automatically (will be modified by umask).
316
+ * Note that POSIX specifies 0777 for implicitly-created dirs, "modified
317
+ * by the process' file creation mask."
318
+ */
319
+ #define DEFAULT_DIR_MODE 0777
320
+ /*
321
+ * Dir modes are restored in two steps: During the extraction, the permissions
322
+ * in the archive are modified to match the following limits. During
323
+ * the post-extract fixup pass, the permissions from the archive are
324
+ * applied.
325
+ */
326
+ #define MINIMUM_DIR_MODE 0700
327
+ #define MAXIMUM_DIR_MODE 0775
328
+
329
+ /*
330
+ * Maximum uncompressed size of a decmpfs block.
331
+ */
332
+ #define MAX_DECMPFS_BLOCK_SIZE (64 * 1024)
333
+ /*
334
+ * HFS+ compression type.
335
+ */
336
+ #define CMP_XATTR 3/* Compressed data in xattr. */
337
+ #define CMP_RESOURCE_FORK 4/* Compressed data in resource fork. */
338
+ /*
339
+ * HFS+ compression resource fork.
340
+ */
341
+ #define RSRC_H_SIZE 260 /* Base size of Resource fork header. */
342
+ #define RSRC_F_SIZE 50 /* Size of Resource fork footer. */
343
+ /* Size to write compressed data to resource fork. */
344
+ #define COMPRESSED_W_SIZE (64 * 1024)
345
+ /* decmpfs definitions. */
346
+ #define MAX_DECMPFS_XATTR_SIZE 3802
347
+ #ifndef DECMPFS_XATTR_NAME
348
+ #define DECMPFS_XATTR_NAME "com.apple.decmpfs"
349
+ #endif
350
+ #define DECMPFS_MAGIC 0x636d7066
351
+ #define DECMPFS_COMPRESSION_MAGIC 0
352
+ #define DECMPFS_COMPRESSION_TYPE 4
353
+ #define DECMPFS_UNCOMPRESSED_SIZE 8
354
+ #define DECMPFS_HEADER_SIZE 16
355
+
356
+ #define HFS_BLOCKS(s) ((s) >> 12)
357
+
358
+
359
+ static int la_opendirat(int, const char *);
360
+ static int la_mktemp(struct archive_write_disk *);
361
+ static int la_verify_filetype(mode_t, __LA_MODE_T);
362
+ static void fsobj_error(int *, struct archive_string *, int, const char *,
363
+ const char *);
364
+ static int check_symlinks_fsobj(char *, int *, struct archive_string *,
365
+ int, int);
366
+ static int check_symlinks(struct archive_write_disk *);
367
+ static int create_filesystem_object(struct archive_write_disk *);
368
+ static struct fixup_entry *current_fixup(struct archive_write_disk *,
369
+ const char *pathname);
370
+ #if defined(HAVE_FCHDIR) && defined(PATH_MAX)
371
+ static void edit_deep_directories(struct archive_write_disk *ad);
372
+ #endif
373
+ static int cleanup_pathname_fsobj(char *, int *, struct archive_string *,
374
+ int);
375
+ static int cleanup_pathname(struct archive_write_disk *);
376
+ static int create_dir(struct archive_write_disk *, char *);
377
+ static int create_parent_dir(struct archive_write_disk *, char *);
378
+ static ssize_t hfs_write_data_block(struct archive_write_disk *,
379
+ const char *, size_t);
380
+ static int fixup_appledouble(struct archive_write_disk *, const char *);
381
+ static int older(struct stat *, struct archive_entry *);
382
+ static int restore_entry(struct archive_write_disk *);
383
+ static int set_mac_metadata(struct archive_write_disk *, const char *,
384
+ const void *, size_t);
385
+ static int set_xattrs(struct archive_write_disk *);
386
+ static int clear_nochange_fflags(struct archive_write_disk *);
387
+ static int set_fflags(struct archive_write_disk *);
388
+ static int set_fflags_platform(struct archive_write_disk *, int fd,
389
+ const char *name, mode_t mode,
390
+ unsigned long fflags_set, unsigned long fflags_clear);
391
+ static int set_ownership(struct archive_write_disk *);
392
+ static int set_mode(struct archive_write_disk *, int mode);
393
+ static int set_time(int, int, const char *, time_t, long, time_t, long);
394
+ static int set_times(struct archive_write_disk *, int, int, const char *,
395
+ time_t, long, time_t, long, time_t, long, time_t, long);
396
+ static int set_times_from_entry(struct archive_write_disk *);
397
+ static struct fixup_entry *sort_dir_list(struct fixup_entry *p);
398
+ static ssize_t write_data_block(struct archive_write_disk *,
399
+ const char *, size_t);
400
+
401
+ static int _archive_write_disk_close(struct archive *);
402
+ static int _archive_write_disk_free(struct archive *);
403
+ static int _archive_write_disk_header(struct archive *,
404
+ struct archive_entry *);
405
+ static int64_t _archive_write_disk_filter_bytes(struct archive *, int);
406
+ static int _archive_write_disk_finish_entry(struct archive *);
407
+ static ssize_t _archive_write_disk_data(struct archive *, const void *,
408
+ size_t);
409
+ static ssize_t _archive_write_disk_data_block(struct archive *, const void *,
410
+ size_t, int64_t);
411
+
412
+ static int
413
+ la_mktemp(struct archive_write_disk *a)
414
+ {
415
+ int oerrno, fd;
416
+ mode_t mode;
417
+
418
+ archive_string_empty(&a->_tmpname_data);
419
+ archive_string_sprintf(&a->_tmpname_data, "%s.XXXXXX", a->name);
420
+ a->tmpname = a->_tmpname_data.s;
421
+
422
+ fd = __archive_mkstemp(a->tmpname);
423
+ if (fd == -1)
424
+ return -1;
425
+
426
+ mode = a->mode & 0777 & ~a->user_umask;
427
+ if (fchmod(fd, mode) == -1) {
428
+ oerrno = errno;
429
+ close(fd);
430
+ errno = oerrno;
431
+ return -1;
432
+ }
433
+ return fd;
434
+ }
435
+
436
+ static int
437
+ la_opendirat(int fd, const char *path) {
438
+ const int flags = O_CLOEXEC
439
+ #if defined(O_BINARY)
440
+ | O_BINARY
441
+ #endif
442
+ #if defined(O_DIRECTORY)
443
+ | O_DIRECTORY
444
+ #endif
445
+ #if defined(O_PATH)
446
+ | O_PATH
447
+ #elif defined(O_SEARCH)
448
+ | O_SEARCH
449
+ #elif defined(__FreeBSD__) && defined(O_EXEC)
450
+ | O_EXEC
451
+ #else
452
+ | O_RDONLY
453
+ #endif
454
+ ;
455
+
456
+ #if !defined(HAVE_OPENAT)
457
+ if (fd != AT_FDCWD) {
458
+ errno = ENOTSUP;
459
+ return (-1);
460
+ } else
461
+ return (open(path, flags));
462
+ #else
463
+ return (openat(fd, path, flags));
464
+ #endif
465
+ }
466
+
467
+ static int
468
+ la_verify_filetype(mode_t mode, __LA_MODE_T filetype) {
469
+ int ret = 0;
470
+
471
+ switch (filetype) {
472
+ case AE_IFREG:
473
+ ret = (S_ISREG(mode));
474
+ break;
475
+ case AE_IFDIR:
476
+ ret = (S_ISDIR(mode));
477
+ break;
478
+ case AE_IFLNK:
479
+ ret = (S_ISLNK(mode));
480
+ break;
481
+ case AE_IFSOCK:
482
+ ret = (S_ISSOCK(mode));
483
+ break;
484
+ case AE_IFCHR:
485
+ ret = (S_ISCHR(mode));
486
+ break;
487
+ case AE_IFBLK:
488
+ ret = (S_ISBLK(mode));
489
+ break;
490
+ case AE_IFIFO:
491
+ ret = (S_ISFIFO(mode));
492
+ break;
493
+ default:
494
+ break;
495
+ }
496
+
497
+ return (ret);
498
+ }
499
+
500
+ static int
501
+ lazy_stat(struct archive_write_disk *a)
502
+ {
503
+ if (a->pst != NULL) {
504
+ /* Already have stat() data available. */
505
+ return (ARCHIVE_OK);
506
+ }
507
+ #ifdef HAVE_FSTAT
508
+ if (a->fd >= 0 && fstat(a->fd, &a->st) == 0) {
509
+ a->pst = &a->st;
510
+ return (ARCHIVE_OK);
511
+ }
512
+ #endif
513
+ /*
514
+ * XXX At this point, symlinks should not be hit, otherwise
515
+ * XXX a race occurred. Do we want to check explicitly for that?
516
+ */
517
+ if (lstat(a->name, &a->st) == 0) {
518
+ a->pst = &a->st;
519
+ return (ARCHIVE_OK);
520
+ }
521
+ archive_set_error(&a->archive, errno, "Couldn't stat file");
522
+ return (ARCHIVE_WARN);
523
+ }
524
+
525
+ static const struct archive_vtable
526
+ archive_write_disk_vtable = {
527
+ .archive_close = _archive_write_disk_close,
528
+ .archive_filter_bytes = _archive_write_disk_filter_bytes,
529
+ .archive_free = _archive_write_disk_free,
530
+ .archive_write_header = _archive_write_disk_header,
531
+ .archive_write_finish_entry = _archive_write_disk_finish_entry,
532
+ .archive_write_data = _archive_write_disk_data,
533
+ .archive_write_data_block = _archive_write_disk_data_block,
534
+ };
535
+
536
+ static int64_t
537
+ _archive_write_disk_filter_bytes(struct archive *_a, int n)
538
+ {
539
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
540
+ (void)n; /* UNUSED */
541
+ if (n == -1 || n == 0)
542
+ return (a->total_bytes_written);
543
+ return (-1);
544
+ }
545
+
546
+
547
+ int
548
+ archive_write_disk_set_options(struct archive *_a, int flags)
549
+ {
550
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
551
+
552
+ a->flags = flags;
553
+ return (ARCHIVE_OK);
554
+ }
555
+
556
+
557
+ /*
558
+ * Extract this entry to disk.
559
+ *
560
+ * TODO: Validate hardlinks. According to the standards, we're
561
+ * supposed to check each extracted hardlink and squawk if it refers
562
+ * to a file that we didn't restore. I'm not entirely convinced this
563
+ * is a good idea, but more importantly: Is there any way to validate
564
+ * hardlinks without keeping a complete list of filenames from the
565
+ * entire archive?? Ugh.
566
+ *
567
+ */
568
+ static int
569
+ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
570
+ {
571
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
572
+ struct fixup_entry *fe;
573
+ const char *linkname;
574
+ int ret, r;
575
+
576
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
577
+ ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
578
+ "archive_write_disk_header");
579
+ archive_clear_error(&a->archive);
580
+ if (a->archive.state & ARCHIVE_STATE_DATA) {
581
+ r = _archive_write_disk_finish_entry(&a->archive);
582
+ if (r == ARCHIVE_FATAL)
583
+ return (r);
584
+ }
585
+
586
+ /* Set up for this particular entry. */
587
+ a->pst = NULL;
588
+ a->current_fixup = NULL;
589
+ a->deferred = 0;
590
+ if (a->entry) {
591
+ archive_entry_free(a->entry);
592
+ a->entry = NULL;
593
+ }
594
+ a->entry = archive_entry_clone(entry);
595
+ a->fd = -1;
596
+ a->fd_offset = 0;
597
+ a->offset = 0;
598
+ a->restore_pwd = -1;
599
+ a->uid = a->user_uid;
600
+ a->mode = archive_entry_mode(a->entry);
601
+ if (archive_entry_size_is_set(a->entry))
602
+ a->filesize = archive_entry_size(a->entry);
603
+ else
604
+ a->filesize = -1;
605
+ archive_strcpy(&(a->_name_data), archive_entry_pathname(a->entry));
606
+ a->name = a->_name_data.s;
607
+ archive_clear_error(&a->archive);
608
+
609
+ /*
610
+ * Clean up the requested path. This is necessary for correct
611
+ * dir restores; the dir restore logic otherwise gets messed
612
+ * up by nonsense like "dir/.".
613
+ */
614
+ ret = cleanup_pathname(a);
615
+ if (ret != ARCHIVE_OK)
616
+ return (ret);
617
+
618
+ /*
619
+ * Check if we have a hardlink that points to itself.
620
+ */
621
+ linkname = archive_entry_hardlink(a->entry);
622
+ if (linkname != NULL && strcmp(a->name, linkname) == 0) {
623
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
624
+ "Skipping hardlink pointing to itself: %s",
625
+ a->name);
626
+ return (ARCHIVE_WARN);
627
+ }
628
+
629
+ /*
630
+ * Query the umask so we get predictable mode settings.
631
+ * This gets done on every call to _write_header in case the
632
+ * user edits their umask during the extraction for some
633
+ * reason.
634
+ */
635
+ umask(a->user_umask = umask(0));
636
+
637
+ /* Figure out what we need to do for this entry. */
638
+ a->todo = TODO_MODE_BASE;
639
+ if (a->flags & ARCHIVE_EXTRACT_PERM) {
640
+ a->todo |= TODO_MODE_FORCE; /* Be pushy about permissions. */
641
+ /*
642
+ * SGID requires an extra "check" step because we
643
+ * cannot easily predict the GID that the system will
644
+ * assign. (Different systems assign GIDs to files
645
+ * based on a variety of criteria, including process
646
+ * credentials and the gid of the enclosing
647
+ * directory.) We can only restore the SGID bit if
648
+ * the file has the right GID, and we only know the
649
+ * GID if we either set it (see set_ownership) or if
650
+ * we've actually called stat() on the file after it
651
+ * was restored. Since there are several places at
652
+ * which we might verify the GID, we need a TODO bit
653
+ * to keep track.
654
+ */
655
+ if (a->mode & S_ISGID)
656
+ a->todo |= TODO_SGID | TODO_SGID_CHECK;
657
+ /*
658
+ * Verifying the SUID is simpler, but can still be
659
+ * done in multiple ways, hence the separate "check" bit.
660
+ */
661
+ if (a->mode & S_ISUID)
662
+ a->todo |= TODO_SUID | TODO_SUID_CHECK;
663
+ } else {
664
+ /*
665
+ * User didn't request full permissions, so don't
666
+ * restore SUID, SGID bits and obey umask.
667
+ */
668
+ a->mode &= ~S_ISUID;
669
+ a->mode &= ~S_ISGID;
670
+ a->mode &= ~S_ISVTX;
671
+ a->mode &= ~a->user_umask;
672
+ }
673
+ if (a->flags & ARCHIVE_EXTRACT_OWNER)
674
+ a->todo |= TODO_OWNER;
675
+ if (a->flags & ARCHIVE_EXTRACT_TIME)
676
+ a->todo |= TODO_TIMES;
677
+ if (a->flags & ARCHIVE_EXTRACT_ACL) {
678
+ #if ARCHIVE_ACL_DARWIN
679
+ /*
680
+ * On MacOS, platform ACLs get stored in mac_metadata, too.
681
+ * If we intend to extract mac_metadata and it is present
682
+ * we skip extracting libarchive NFSv4 ACLs.
683
+ */
684
+ size_t metadata_size;
685
+
686
+ if ((a->flags & ARCHIVE_EXTRACT_MAC_METADATA) == 0 ||
687
+ archive_entry_mac_metadata(a->entry,
688
+ &metadata_size) == NULL || metadata_size == 0)
689
+ #endif
690
+ #if ARCHIVE_ACL_LIBRICHACL
691
+ /*
692
+ * RichACLs are stored in an extended attribute.
693
+ * If we intend to extract extended attributes and have this
694
+ * attribute we skip extracting libarchive NFSv4 ACLs.
695
+ */
696
+ short extract_acls = 1;
697
+ if (a->flags & ARCHIVE_EXTRACT_XATTR && (
698
+ archive_entry_acl_types(a->entry) &
699
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4)) {
700
+ const char *attr_name;
701
+ const void *attr_value;
702
+ size_t attr_size;
703
+ int i = archive_entry_xattr_reset(a->entry);
704
+ while (i--) {
705
+ archive_entry_xattr_next(a->entry, &attr_name,
706
+ &attr_value, &attr_size);
707
+ if (attr_name != NULL && attr_value != NULL &&
708
+ attr_size > 0 && strcmp(attr_name,
709
+ "trusted.richacl") == 0) {
710
+ extract_acls = 0;
711
+ break;
712
+ }
713
+ }
714
+ }
715
+ if (extract_acls)
716
+ #endif
717
+ #if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL
718
+ {
719
+ #endif
720
+ if (archive_entry_filetype(a->entry) == AE_IFDIR)
721
+ a->deferred |= TODO_ACLS;
722
+ else
723
+ a->todo |= TODO_ACLS;
724
+ #if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL
725
+ }
726
+ #endif
727
+ }
728
+ if (a->flags & ARCHIVE_EXTRACT_MAC_METADATA) {
729
+ if (archive_entry_filetype(a->entry) == AE_IFDIR)
730
+ a->deferred |= TODO_MAC_METADATA;
731
+ else
732
+ a->todo |= TODO_MAC_METADATA;
733
+ }
734
+ #if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H)
735
+ if ((a->flags & ARCHIVE_EXTRACT_NO_HFS_COMPRESSION) == 0) {
736
+ unsigned long set, clear;
737
+ archive_entry_fflags(a->entry, &set, &clear);
738
+ if ((set & ~clear) & UF_COMPRESSED) {
739
+ a->todo |= TODO_HFS_COMPRESSION;
740
+ a->decmpfs_block_count = (unsigned)-1;
741
+ }
742
+ }
743
+ if ((a->flags & ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED) != 0 &&
744
+ (a->mode & AE_IFMT) == AE_IFREG && a->filesize > 0) {
745
+ a->todo |= TODO_HFS_COMPRESSION;
746
+ a->decmpfs_block_count = (unsigned)-1;
747
+ }
748
+ {
749
+ const char *p;
750
+
751
+ /* Check if the current file name is a type of the
752
+ * resource fork file. */
753
+ p = strrchr(a->name, '/');
754
+ if (p == NULL)
755
+ p = a->name;
756
+ else
757
+ p++;
758
+ if (p[0] == '.' && p[1] == '_') {
759
+ /* Do not compress "._XXX" files. */
760
+ a->todo &= ~TODO_HFS_COMPRESSION;
761
+ if (a->filesize > 0)
762
+ a->todo |= TODO_APPLEDOUBLE;
763
+ }
764
+ }
765
+ #endif
766
+
767
+ if (a->flags & ARCHIVE_EXTRACT_XATTR) {
768
+ #if ARCHIVE_XATTR_DARWIN
769
+ /*
770
+ * On MacOS, extended attributes get stored in mac_metadata,
771
+ * too. If we intend to extract mac_metadata and it is present
772
+ * we skip extracting extended attributes.
773
+ */
774
+ size_t metadata_size;
775
+
776
+ if ((a->flags & ARCHIVE_EXTRACT_MAC_METADATA) == 0 ||
777
+ archive_entry_mac_metadata(a->entry,
778
+ &metadata_size) == NULL || metadata_size == 0)
779
+ #endif
780
+ a->todo |= TODO_XATTR;
781
+ }
782
+ if (a->flags & ARCHIVE_EXTRACT_FFLAGS)
783
+ a->todo |= TODO_FFLAGS;
784
+ if (a->flags & ARCHIVE_EXTRACT_SECURE_SYMLINKS) {
785
+ ret = check_symlinks(a);
786
+ if (ret != ARCHIVE_OK)
787
+ return (ret);
788
+ }
789
+ #if defined(HAVE_FCHDIR) && defined(PATH_MAX)
790
+ /* If path exceeds PATH_MAX, shorten the path. */
791
+ edit_deep_directories(a);
792
+ #endif
793
+
794
+ ret = restore_entry(a);
795
+
796
+ #if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H)
797
+ /*
798
+ * Check if the filesystem the file is restoring on supports
799
+ * HFS+ Compression. If not, cancel HFS+ Compression.
800
+ */
801
+ if (a->todo | TODO_HFS_COMPRESSION) {
802
+ /*
803
+ * NOTE: UF_COMPRESSED is ignored even if the filesystem
804
+ * supports HFS+ Compression because the file should
805
+ * have at least an extended attribute "com.apple.decmpfs"
806
+ * before the flag is set to indicate that the file have
807
+ * been compressed. If the filesystem does not support
808
+ * HFS+ Compression the system call will fail.
809
+ */
810
+ if (a->fd < 0 || fchflags(a->fd, UF_COMPRESSED) != 0)
811
+ a->todo &= ~TODO_HFS_COMPRESSION;
812
+ }
813
+ #endif
814
+
815
+ /*
816
+ * TODO: There are rumours that some extended attributes must
817
+ * be restored before file data is written. If this is true,
818
+ * then we either need to write all extended attributes both
819
+ * before and after restoring the data, or find some rule for
820
+ * determining which must go first and which last. Due to the
821
+ * many ways people are using xattrs, this may prove to be an
822
+ * intractable problem.
823
+ */
824
+
825
+ #ifdef HAVE_FCHDIR
826
+ /* If we changed directory above, restore it here. */
827
+ if (a->restore_pwd >= 0) {
828
+ r = fchdir(a->restore_pwd);
829
+ if (r != 0) {
830
+ archive_set_error(&a->archive, errno,
831
+ "chdir() failure");
832
+ ret = ARCHIVE_FATAL;
833
+ }
834
+ close(a->restore_pwd);
835
+ a->restore_pwd = -1;
836
+ }
837
+ #endif
838
+
839
+ /*
840
+ * Fixup uses the unedited pathname from archive_entry_pathname(),
841
+ * because it is relative to the base dir and the edited path
842
+ * might be relative to some intermediate dir as a result of the
843
+ * deep restore logic.
844
+ */
845
+ if (a->deferred & TODO_MODE) {
846
+ fe = current_fixup(a, archive_entry_pathname(entry));
847
+ if (fe == NULL)
848
+ return (ARCHIVE_FATAL);
849
+ fe->filetype = archive_entry_filetype(entry);
850
+ fe->fixup |= TODO_MODE_BASE;
851
+ fe->mode = a->mode;
852
+ }
853
+
854
+ if ((a->deferred & TODO_TIMES)
855
+ && (archive_entry_mtime_is_set(entry)
856
+ || archive_entry_atime_is_set(entry))) {
857
+ fe = current_fixup(a, archive_entry_pathname(entry));
858
+ if (fe == NULL)
859
+ return (ARCHIVE_FATAL);
860
+ fe->filetype = archive_entry_filetype(entry);
861
+ fe->mode = a->mode;
862
+ fe->fixup |= TODO_TIMES;
863
+ if (archive_entry_atime_is_set(entry)) {
864
+ fe->atime = archive_entry_atime(entry);
865
+ fe->atime_nanos = archive_entry_atime_nsec(entry);
866
+ } else {
867
+ /* If atime is unset, use start time. */
868
+ fe->atime = a->start_time;
869
+ fe->atime_nanos = 0;
870
+ }
871
+ if (archive_entry_mtime_is_set(entry)) {
872
+ fe->mtime = archive_entry_mtime(entry);
873
+ fe->mtime_nanos = archive_entry_mtime_nsec(entry);
874
+ } else {
875
+ /* If mtime is unset, use start time. */
876
+ fe->mtime = a->start_time;
877
+ fe->mtime_nanos = 0;
878
+ }
879
+ if (archive_entry_birthtime_is_set(entry)) {
880
+ fe->birthtime = archive_entry_birthtime(entry);
881
+ fe->birthtime_nanos = archive_entry_birthtime_nsec(
882
+ entry);
883
+ } else {
884
+ /* If birthtime is unset, use mtime. */
885
+ fe->birthtime = fe->mtime;
886
+ fe->birthtime_nanos = fe->mtime_nanos;
887
+ }
888
+ }
889
+
890
+ if (a->deferred & TODO_ACLS) {
891
+ fe = current_fixup(a, archive_entry_pathname(entry));
892
+ if (fe == NULL)
893
+ return (ARCHIVE_FATAL);
894
+ fe->filetype = archive_entry_filetype(entry);
895
+ fe->fixup |= TODO_ACLS;
896
+ archive_acl_copy(&fe->acl, archive_entry_acl(entry));
897
+ }
898
+
899
+ if (a->deferred & TODO_MAC_METADATA) {
900
+ const void *metadata;
901
+ size_t metadata_size;
902
+ metadata = archive_entry_mac_metadata(a->entry, &metadata_size);
903
+ if (metadata != NULL && metadata_size > 0) {
904
+ fe = current_fixup(a, archive_entry_pathname(entry));
905
+ if (fe == NULL)
906
+ return (ARCHIVE_FATAL);
907
+ fe->filetype = archive_entry_filetype(entry);
908
+ fe->mac_metadata = malloc(metadata_size);
909
+ if (fe->mac_metadata != NULL) {
910
+ memcpy(fe->mac_metadata, metadata,
911
+ metadata_size);
912
+ fe->mac_metadata_size = metadata_size;
913
+ fe->fixup |= TODO_MAC_METADATA;
914
+ }
915
+ }
916
+ }
917
+
918
+ if (a->deferred & TODO_FFLAGS) {
919
+ fe = current_fixup(a, archive_entry_pathname(entry));
920
+ if (fe == NULL)
921
+ return (ARCHIVE_FATAL);
922
+ fe->filetype = archive_entry_filetype(entry);
923
+ fe->fixup |= TODO_FFLAGS;
924
+ /* TODO: Complete this.. defer fflags from below. */
925
+ }
926
+
927
+ /* We've created the object and are ready to pour data into it. */
928
+ if (ret >= ARCHIVE_WARN)
929
+ a->archive.state = ARCHIVE_STATE_DATA;
930
+ /*
931
+ * If it's not open, tell our client not to try writing.
932
+ * In particular, dirs, links, etc, don't get written to.
933
+ */
934
+ if (a->fd < 0) {
935
+ archive_entry_set_size(entry, 0);
936
+ a->filesize = 0;
937
+ }
938
+
939
+ return (ret);
940
+ }
941
+
942
+ int
943
+ archive_write_disk_set_skip_file(struct archive *_a, la_int64_t d, la_int64_t i)
944
+ {
945
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
946
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
947
+ ARCHIVE_STATE_ANY, "archive_write_disk_set_skip_file");
948
+ a->skip_file_set = 1;
949
+ a->skip_file_dev = d;
950
+ a->skip_file_ino = i;
951
+ return (ARCHIVE_OK);
952
+ }
953
+
954
+ static ssize_t
955
+ write_data_block(struct archive_write_disk *a, const char *buff, size_t size)
956
+ {
957
+ uint64_t start_size = size;
958
+ ssize_t bytes_written = 0;
959
+ ssize_t block_size = 0, bytes_to_write;
960
+
961
+ if (size == 0)
962
+ return (ARCHIVE_OK);
963
+
964
+ if (a->filesize == 0 || a->fd < 0) {
965
+ archive_set_error(&a->archive, 0,
966
+ "Attempt to write to an empty file");
967
+ return (ARCHIVE_WARN);
968
+ }
969
+
970
+ if (a->flags & ARCHIVE_EXTRACT_SPARSE) {
971
+ #if HAVE_STRUCT_STAT_ST_BLKSIZE
972
+ int r;
973
+ if ((r = lazy_stat(a)) != ARCHIVE_OK)
974
+ return (r);
975
+ block_size = a->pst->st_blksize;
976
+ #else
977
+ /* XXX TODO XXX Is there a more appropriate choice here ? */
978
+ /* This needn't match the filesystem allocation size. */
979
+ block_size = 16*1024;
980
+ #endif
981
+ }
982
+
983
+ /* If this write would run beyond the file size, truncate it. */
984
+ if (a->filesize >= 0 && (int64_t)(a->offset + size) > a->filesize)
985
+ start_size = size = (size_t)(a->filesize - a->offset);
986
+
987
+ /* Write the data. */
988
+ while (size > 0) {
989
+ if (block_size == 0) {
990
+ bytes_to_write = size;
991
+ } else {
992
+ /* We're sparsifying the file. */
993
+ const char *p, *end;
994
+ int64_t block_end;
995
+
996
+ /* Skip leading zero bytes. */
997
+ for (p = buff, end = buff + size; p < end; ++p) {
998
+ if (*p != '\0')
999
+ break;
1000
+ }
1001
+ a->offset += p - buff;
1002
+ size -= p - buff;
1003
+ buff = p;
1004
+ if (size == 0)
1005
+ break;
1006
+
1007
+ /* Calculate next block boundary after offset. */
1008
+ block_end
1009
+ = (a->offset / block_size + 1) * block_size;
1010
+
1011
+ /* If the adjusted write would cross block boundary,
1012
+ * truncate it to the block boundary. */
1013
+ bytes_to_write = size;
1014
+ if (a->offset + bytes_to_write > block_end)
1015
+ bytes_to_write = block_end - a->offset;
1016
+ }
1017
+ /* Seek if necessary to the specified offset. */
1018
+ if (a->offset != a->fd_offset) {
1019
+ if (lseek(a->fd, a->offset, SEEK_SET) < 0) {
1020
+ archive_set_error(&a->archive, errno,
1021
+ "Seek failed");
1022
+ return (ARCHIVE_FATAL);
1023
+ }
1024
+ a->fd_offset = a->offset;
1025
+ }
1026
+ bytes_written = write(a->fd, buff, bytes_to_write);
1027
+ if (bytes_written < 0) {
1028
+ archive_set_error(&a->archive, errno, "Write failed");
1029
+ return (ARCHIVE_WARN);
1030
+ }
1031
+ buff += bytes_written;
1032
+ size -= bytes_written;
1033
+ a->total_bytes_written += bytes_written;
1034
+ a->offset += bytes_written;
1035
+ a->fd_offset = a->offset;
1036
+ }
1037
+ return (start_size - size);
1038
+ }
1039
+
1040
+ #if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_SYS_XATTR_H)\
1041
+ && defined(HAVE_ZLIB_H)
1042
+
1043
+ /*
1044
+ * Set UF_COMPRESSED file flag.
1045
+ * This have to be called after hfs_write_decmpfs() because if the
1046
+ * file does not have "com.apple.decmpfs" xattr the flag is ignored.
1047
+ */
1048
+ static int
1049
+ hfs_set_compressed_fflag(struct archive_write_disk *a)
1050
+ {
1051
+ int r;
1052
+
1053
+ if ((r = lazy_stat(a)) != ARCHIVE_OK)
1054
+ return (r);
1055
+
1056
+ a->st.st_flags |= UF_COMPRESSED;
1057
+ if (fchflags(a->fd, a->st.st_flags) != 0) {
1058
+ archive_set_error(&a->archive, errno,
1059
+ "Failed to set UF_COMPRESSED file flag");
1060
+ return (ARCHIVE_WARN);
1061
+ }
1062
+ return (ARCHIVE_OK);
1063
+ }
1064
+
1065
+ /*
1066
+ * HFS+ Compression decmpfs
1067
+ *
1068
+ * +------------------------------+ +0
1069
+ * | Magic(LE 4 bytes) |
1070
+ * +------------------------------+
1071
+ * | Type(LE 4 bytes) |
1072
+ * +------------------------------+
1073
+ * | Uncompressed size(LE 8 bytes)|
1074
+ * +------------------------------+ +16
1075
+ * | |
1076
+ * | Compressed data |
1077
+ * | (Placed only if Type == 3) |
1078
+ * | |
1079
+ * +------------------------------+ +3802 = MAX_DECMPFS_XATTR_SIZE
1080
+ *
1081
+ * Type is 3: decmpfs has compressed data.
1082
+ * Type is 4: Resource Fork has compressed data.
1083
+ */
1084
+ /*
1085
+ * Write "com.apple.decmpfs"
1086
+ */
1087
+ static int
1088
+ hfs_write_decmpfs(struct archive_write_disk *a)
1089
+ {
1090
+ int r;
1091
+ uint32_t compression_type;
1092
+
1093
+ r = fsetxattr(a->fd, DECMPFS_XATTR_NAME, a->decmpfs_header_p,
1094
+ a->decmpfs_attr_size, 0, 0);
1095
+ if (r < 0) {
1096
+ archive_set_error(&a->archive, errno,
1097
+ "Cannot restore xattr:%s", DECMPFS_XATTR_NAME);
1098
+ compression_type = archive_le32dec(
1099
+ &a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE]);
1100
+ if (compression_type == CMP_RESOURCE_FORK)
1101
+ fremovexattr(a->fd, XATTR_RESOURCEFORK_NAME,
1102
+ XATTR_SHOWCOMPRESSION);
1103
+ return (ARCHIVE_WARN);
1104
+ }
1105
+ return (ARCHIVE_OK);
1106
+ }
1107
+
1108
+ /*
1109
+ * HFS+ Compression Resource Fork
1110
+ *
1111
+ * +-----------------------------+
1112
+ * | Header(260 bytes) |
1113
+ * +-----------------------------+
1114
+ * | Block count(LE 4 bytes) |
1115
+ * +-----------------------------+ --+
1116
+ * +-- | Offset (LE 4 bytes) | |
1117
+ * | | [distance from Block count] | | Block 0
1118
+ * | +-----------------------------+ |
1119
+ * | | Compressed size(LE 4 bytes) | |
1120
+ * | +-----------------------------+ --+
1121
+ * | | |
1122
+ * | | .................. |
1123
+ * | | |
1124
+ * | +-----------------------------+ --+
1125
+ * | | Offset (LE 4 bytes) | |
1126
+ * | +-----------------------------+ | Block (Block count -1)
1127
+ * | | Compressed size(LE 4 bytes) | |
1128
+ * +-> +-----------------------------+ --+
1129
+ * | Compressed data(n bytes) | Block 0
1130
+ * +-----------------------------+
1131
+ * | |
1132
+ * | .................. |
1133
+ * | |
1134
+ * +-----------------------------+
1135
+ * | Compressed data(n bytes) | Block (Block count -1)
1136
+ * +-----------------------------+
1137
+ * | Footer(50 bytes) |
1138
+ * +-----------------------------+
1139
+ *
1140
+ */
1141
+ /*
1142
+ * Write the header of "com.apple.ResourceFork"
1143
+ */
1144
+ static int
1145
+ hfs_write_resource_fork(struct archive_write_disk *a, unsigned char *buff,
1146
+ size_t bytes, uint32_t position)
1147
+ {
1148
+ int ret;
1149
+
1150
+ ret = fsetxattr(a->fd, XATTR_RESOURCEFORK_NAME, buff, bytes,
1151
+ position, a->rsrc_xattr_options);
1152
+ if (ret < 0) {
1153
+ archive_set_error(&a->archive, errno,
1154
+ "Cannot restore xattr: %s at %u pos %u bytes",
1155
+ XATTR_RESOURCEFORK_NAME,
1156
+ (unsigned)position,
1157
+ (unsigned)bytes);
1158
+ return (ARCHIVE_WARN);
1159
+ }
1160
+ a->rsrc_xattr_options &= ~XATTR_CREATE;
1161
+ return (ARCHIVE_OK);
1162
+ }
1163
+
1164
+ static int
1165
+ hfs_write_compressed_data(struct archive_write_disk *a, size_t bytes_compressed)
1166
+ {
1167
+ int ret;
1168
+
1169
+ ret = hfs_write_resource_fork(a, a->compressed_buffer,
1170
+ bytes_compressed, a->compressed_rsrc_position);
1171
+ if (ret == ARCHIVE_OK)
1172
+ a->compressed_rsrc_position += bytes_compressed;
1173
+ return (ret);
1174
+ }
1175
+
1176
+ static int
1177
+ hfs_write_resource_fork_header(struct archive_write_disk *a)
1178
+ {
1179
+ unsigned char *buff;
1180
+ uint32_t rsrc_bytes;
1181
+ uint32_t rsrc_header_bytes;
1182
+
1183
+ /*
1184
+ * Write resource fork header + block info.
1185
+ */
1186
+ buff = a->resource_fork;
1187
+ rsrc_bytes = a->compressed_rsrc_position - RSRC_F_SIZE;
1188
+ rsrc_header_bytes =
1189
+ RSRC_H_SIZE + /* Header base size. */
1190
+ 4 + /* Block count. */
1191
+ (a->decmpfs_block_count * 8);/* Block info */
1192
+ archive_be32enc(buff, 0x100);
1193
+ archive_be32enc(buff + 4, rsrc_bytes);
1194
+ archive_be32enc(buff + 8, rsrc_bytes - 256);
1195
+ archive_be32enc(buff + 12, 0x32);
1196
+ memset(buff + 16, 0, 240);
1197
+ archive_be32enc(buff + 256, rsrc_bytes - 260);
1198
+ return hfs_write_resource_fork(a, buff, rsrc_header_bytes, 0);
1199
+ }
1200
+
1201
+ static size_t
1202
+ hfs_set_resource_fork_footer(unsigned char *buff, size_t buff_size)
1203
+ {
1204
+ static const char rsrc_footer[RSRC_F_SIZE] = {
1205
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1206
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1207
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1208
+ 0x00, 0x1c, 0x00, 0x32, 0x00, 0x00, 'c', 'm',
1209
+ 'p', 'f', 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01,
1210
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1211
+ 0x00, 0x00
1212
+ };
1213
+ if (buff_size < sizeof(rsrc_footer))
1214
+ return (0);
1215
+ memcpy(buff, rsrc_footer, sizeof(rsrc_footer));
1216
+ return (sizeof(rsrc_footer));
1217
+ }
1218
+
1219
+ static int
1220
+ hfs_reset_compressor(struct archive_write_disk *a)
1221
+ {
1222
+ int ret;
1223
+
1224
+ if (a->stream_valid)
1225
+ ret = deflateReset(&a->stream);
1226
+ else
1227
+ ret = deflateInit(&a->stream, a->decmpfs_compression_level);
1228
+
1229
+ if (ret != Z_OK) {
1230
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1231
+ "Failed to initialize compressor");
1232
+ return (ARCHIVE_FATAL);
1233
+ } else
1234
+ a->stream_valid = 1;
1235
+
1236
+ return (ARCHIVE_OK);
1237
+ }
1238
+
1239
+ static int
1240
+ hfs_decompress(struct archive_write_disk *a)
1241
+ {
1242
+ uint32_t *block_info;
1243
+ unsigned int block_count;
1244
+ uint32_t data_pos, data_size;
1245
+ ssize_t r;
1246
+ ssize_t bytes_written, bytes_to_write;
1247
+ unsigned char *b;
1248
+
1249
+ block_info = (uint32_t *)(a->resource_fork + RSRC_H_SIZE);
1250
+ block_count = archive_le32dec(block_info++);
1251
+ while (block_count--) {
1252
+ data_pos = RSRC_H_SIZE + archive_le32dec(block_info++);
1253
+ data_size = archive_le32dec(block_info++);
1254
+ r = fgetxattr(a->fd, XATTR_RESOURCEFORK_NAME,
1255
+ a->compressed_buffer, data_size, data_pos, 0);
1256
+ if (r != data_size) {
1257
+ archive_set_error(&a->archive,
1258
+ (r < 0)?errno:ARCHIVE_ERRNO_MISC,
1259
+ "Failed to read resource fork");
1260
+ return (ARCHIVE_WARN);
1261
+ }
1262
+ if (a->compressed_buffer[0] == 0xff) {
1263
+ bytes_to_write = data_size -1;
1264
+ b = a->compressed_buffer + 1;
1265
+ } else {
1266
+ uLong dest_len = MAX_DECMPFS_BLOCK_SIZE;
1267
+ int zr;
1268
+
1269
+ zr = uncompress((Bytef *)a->uncompressed_buffer,
1270
+ &dest_len, a->compressed_buffer, data_size);
1271
+ if (zr != Z_OK) {
1272
+ archive_set_error(&a->archive,
1273
+ ARCHIVE_ERRNO_MISC,
1274
+ "Failed to decompress resource fork");
1275
+ return (ARCHIVE_WARN);
1276
+ }
1277
+ bytes_to_write = dest_len;
1278
+ b = (unsigned char *)a->uncompressed_buffer;
1279
+ }
1280
+ do {
1281
+ bytes_written = write(a->fd, b, bytes_to_write);
1282
+ if (bytes_written < 0) {
1283
+ archive_set_error(&a->archive, errno,
1284
+ "Write failed");
1285
+ return (ARCHIVE_WARN);
1286
+ }
1287
+ bytes_to_write -= bytes_written;
1288
+ b += bytes_written;
1289
+ } while (bytes_to_write > 0);
1290
+ }
1291
+ r = fremovexattr(a->fd, XATTR_RESOURCEFORK_NAME, 0);
1292
+ if (r == -1) {
1293
+ archive_set_error(&a->archive, errno,
1294
+ "Failed to remove resource fork");
1295
+ return (ARCHIVE_WARN);
1296
+ }
1297
+ return (ARCHIVE_OK);
1298
+ }
1299
+
1300
+ static int
1301
+ hfs_drive_compressor(struct archive_write_disk *a, const char *buff,
1302
+ size_t size)
1303
+ {
1304
+ unsigned char *buffer_compressed;
1305
+ size_t bytes_compressed;
1306
+ size_t bytes_used;
1307
+ int ret;
1308
+
1309
+ ret = hfs_reset_compressor(a);
1310
+ if (ret != ARCHIVE_OK)
1311
+ return (ret);
1312
+
1313
+ if (a->compressed_buffer == NULL) {
1314
+ size_t block_size;
1315
+
1316
+ block_size = COMPRESSED_W_SIZE + RSRC_F_SIZE +
1317
+ + compressBound(MAX_DECMPFS_BLOCK_SIZE);
1318
+ a->compressed_buffer = malloc(block_size);
1319
+ if (a->compressed_buffer == NULL) {
1320
+ archive_set_error(&a->archive, ENOMEM,
1321
+ "Can't allocate memory for Resource Fork");
1322
+ return (ARCHIVE_FATAL);
1323
+ }
1324
+ a->compressed_buffer_size = block_size;
1325
+ a->compressed_buffer_remaining = block_size;
1326
+ }
1327
+
1328
+ buffer_compressed = a->compressed_buffer +
1329
+ a->compressed_buffer_size - a->compressed_buffer_remaining;
1330
+ a->stream.next_in = (Bytef *)(uintptr_t)(const void *)buff;
1331
+ a->stream.avail_in = size;
1332
+ a->stream.next_out = buffer_compressed;
1333
+ a->stream.avail_out = a->compressed_buffer_remaining;
1334
+ do {
1335
+ ret = deflate(&a->stream, Z_FINISH);
1336
+ switch (ret) {
1337
+ case Z_OK:
1338
+ case Z_STREAM_END:
1339
+ break;
1340
+ default:
1341
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1342
+ "Failed to compress data");
1343
+ return (ARCHIVE_FAILED);
1344
+ }
1345
+ } while (ret == Z_OK);
1346
+ bytes_compressed = a->compressed_buffer_remaining - a->stream.avail_out;
1347
+
1348
+ /*
1349
+ * If the compressed size is larger than the original size,
1350
+ * throw away compressed data, use uncompressed data instead.
1351
+ */
1352
+ if (bytes_compressed > size) {
1353
+ buffer_compressed[0] = 0xFF;/* uncompressed marker. */
1354
+ memcpy(buffer_compressed + 1, buff, size);
1355
+ bytes_compressed = size + 1;
1356
+ }
1357
+ a->compressed_buffer_remaining -= bytes_compressed;
1358
+
1359
+ /*
1360
+ * If the compressed size is smaller than MAX_DECMPFS_XATTR_SIZE
1361
+ * and the block count in the file is only one, store compressed
1362
+ * data to decmpfs xattr instead of the resource fork.
1363
+ */
1364
+ if (a->decmpfs_block_count == 1 &&
1365
+ (a->decmpfs_attr_size + bytes_compressed)
1366
+ <= MAX_DECMPFS_XATTR_SIZE) {
1367
+ archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE],
1368
+ CMP_XATTR);
1369
+ memcpy(a->decmpfs_header_p + DECMPFS_HEADER_SIZE,
1370
+ buffer_compressed, bytes_compressed);
1371
+ a->decmpfs_attr_size += bytes_compressed;
1372
+ a->compressed_buffer_remaining = a->compressed_buffer_size;
1373
+ /*
1374
+ * Finish HFS+ Compression.
1375
+ * - Write the decmpfs xattr.
1376
+ * - Set the UF_COMPRESSED file flag.
1377
+ */
1378
+ ret = hfs_write_decmpfs(a);
1379
+ if (ret == ARCHIVE_OK)
1380
+ ret = hfs_set_compressed_fflag(a);
1381
+ return (ret);
1382
+ }
1383
+
1384
+ /* Update block info. */
1385
+ archive_le32enc(a->decmpfs_block_info++,
1386
+ a->compressed_rsrc_position_v - RSRC_H_SIZE);
1387
+ archive_le32enc(a->decmpfs_block_info++, bytes_compressed);
1388
+ a->compressed_rsrc_position_v += bytes_compressed;
1389
+
1390
+ /*
1391
+ * Write the compressed data to the resource fork.
1392
+ */
1393
+ bytes_used = a->compressed_buffer_size - a->compressed_buffer_remaining;
1394
+ while (bytes_used >= COMPRESSED_W_SIZE) {
1395
+ ret = hfs_write_compressed_data(a, COMPRESSED_W_SIZE);
1396
+ if (ret != ARCHIVE_OK)
1397
+ return (ret);
1398
+ bytes_used -= COMPRESSED_W_SIZE;
1399
+ if (bytes_used > COMPRESSED_W_SIZE)
1400
+ memmove(a->compressed_buffer,
1401
+ a->compressed_buffer + COMPRESSED_W_SIZE,
1402
+ bytes_used);
1403
+ else
1404
+ memcpy(a->compressed_buffer,
1405
+ a->compressed_buffer + COMPRESSED_W_SIZE,
1406
+ bytes_used);
1407
+ }
1408
+ a->compressed_buffer_remaining = a->compressed_buffer_size - bytes_used;
1409
+
1410
+ /*
1411
+ * If the current block is the last block, write the remaining
1412
+ * compressed data and the resource fork footer.
1413
+ */
1414
+ if (a->file_remaining_bytes == 0) {
1415
+ size_t rsrc_size;
1416
+ int64_t bk;
1417
+
1418
+ /* Append the resource footer. */
1419
+ rsrc_size = hfs_set_resource_fork_footer(
1420
+ a->compressed_buffer + bytes_used,
1421
+ a->compressed_buffer_remaining);
1422
+ ret = hfs_write_compressed_data(a, bytes_used + rsrc_size);
1423
+ a->compressed_buffer_remaining = a->compressed_buffer_size;
1424
+
1425
+ /* If the compressed size is not enough smaller than
1426
+ * the uncompressed size. cancel HFS+ compression.
1427
+ * TODO: study a behavior of ditto utility and improve
1428
+ * the condition to fall back into no HFS+ compression. */
1429
+ bk = HFS_BLOCKS(a->compressed_rsrc_position);
1430
+ bk += bk >> 7;
1431
+ if (bk > HFS_BLOCKS(a->filesize))
1432
+ return hfs_decompress(a);
1433
+ /*
1434
+ * Write the resourcefork header.
1435
+ */
1436
+ if (ret == ARCHIVE_OK)
1437
+ ret = hfs_write_resource_fork_header(a);
1438
+ /*
1439
+ * Finish HFS+ Compression.
1440
+ * - Write the decmpfs xattr.
1441
+ * - Set the UF_COMPRESSED file flag.
1442
+ */
1443
+ if (ret == ARCHIVE_OK)
1444
+ ret = hfs_write_decmpfs(a);
1445
+ if (ret == ARCHIVE_OK)
1446
+ ret = hfs_set_compressed_fflag(a);
1447
+ }
1448
+ return (ret);
1449
+ }
1450
+
1451
+ static ssize_t
1452
+ hfs_write_decmpfs_block(struct archive_write_disk *a, const char *buff,
1453
+ size_t size)
1454
+ {
1455
+ const char *buffer_to_write;
1456
+ size_t bytes_to_write;
1457
+ int ret;
1458
+
1459
+ if (a->decmpfs_block_count == (unsigned)-1) {
1460
+ void *new_block;
1461
+ size_t new_size;
1462
+ unsigned int block_count;
1463
+
1464
+ if (a->decmpfs_header_p == NULL) {
1465
+ new_block = malloc(MAX_DECMPFS_XATTR_SIZE
1466
+ + sizeof(uint32_t));
1467
+ if (new_block == NULL) {
1468
+ archive_set_error(&a->archive, ENOMEM,
1469
+ "Can't allocate memory for decmpfs");
1470
+ return (ARCHIVE_FATAL);
1471
+ }
1472
+ a->decmpfs_header_p = new_block;
1473
+ }
1474
+ a->decmpfs_attr_size = DECMPFS_HEADER_SIZE;
1475
+ archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_MAGIC],
1476
+ DECMPFS_MAGIC);
1477
+ archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE],
1478
+ CMP_RESOURCE_FORK);
1479
+ archive_le64enc(&a->decmpfs_header_p[DECMPFS_UNCOMPRESSED_SIZE],
1480
+ a->filesize);
1481
+
1482
+ /* Calculate a block count of the file. */
1483
+ block_count =
1484
+ (a->filesize + MAX_DECMPFS_BLOCK_SIZE -1) /
1485
+ MAX_DECMPFS_BLOCK_SIZE;
1486
+ /*
1487
+ * Allocate buffer for resource fork.
1488
+ * Set up related pointers;
1489
+ */
1490
+ new_size =
1491
+ RSRC_H_SIZE + /* header */
1492
+ 4 + /* Block count */
1493
+ (block_count * sizeof(uint32_t) * 2) +
1494
+ RSRC_F_SIZE; /* footer */
1495
+ if (new_size > a->resource_fork_allocated_size) {
1496
+ new_block = realloc(a->resource_fork, new_size);
1497
+ if (new_block == NULL) {
1498
+ archive_set_error(&a->archive, ENOMEM,
1499
+ "Can't allocate memory for ResourceFork");
1500
+ return (ARCHIVE_FATAL);
1501
+ }
1502
+ a->resource_fork_allocated_size = new_size;
1503
+ a->resource_fork = new_block;
1504
+ }
1505
+
1506
+ /* Allocate uncompressed buffer */
1507
+ if (a->uncompressed_buffer == NULL) {
1508
+ new_block = malloc(MAX_DECMPFS_BLOCK_SIZE);
1509
+ if (new_block == NULL) {
1510
+ archive_set_error(&a->archive, ENOMEM,
1511
+ "Can't allocate memory for decmpfs");
1512
+ return (ARCHIVE_FATAL);
1513
+ }
1514
+ a->uncompressed_buffer = new_block;
1515
+ }
1516
+ a->block_remaining_bytes = MAX_DECMPFS_BLOCK_SIZE;
1517
+ a->file_remaining_bytes = a->filesize;
1518
+ a->compressed_buffer_remaining = a->compressed_buffer_size;
1519
+
1520
+ /*
1521
+ * Set up a resource fork.
1522
+ */
1523
+ a->rsrc_xattr_options = XATTR_CREATE;
1524
+ /* Get the position where we are going to set a bunch
1525
+ * of block info. */
1526
+ a->decmpfs_block_info =
1527
+ (uint32_t *)(a->resource_fork + RSRC_H_SIZE);
1528
+ /* Set the block count to the resource fork. */
1529
+ archive_le32enc(a->decmpfs_block_info++, block_count);
1530
+ /* Get the position where we are going to set compressed
1531
+ * data. */
1532
+ a->compressed_rsrc_position =
1533
+ RSRC_H_SIZE + 4 + (block_count * 8);
1534
+ a->compressed_rsrc_position_v = a->compressed_rsrc_position;
1535
+ a->decmpfs_block_count = block_count;
1536
+ }
1537
+
1538
+ /* Ignore redundant bytes. */
1539
+ if (a->file_remaining_bytes == 0)
1540
+ return ((ssize_t)size);
1541
+
1542
+ /* Do not overrun a block size. */
1543
+ if (size > a->block_remaining_bytes)
1544
+ bytes_to_write = a->block_remaining_bytes;
1545
+ else
1546
+ bytes_to_write = size;
1547
+ /* Do not overrun the file size. */
1548
+ if (bytes_to_write > a->file_remaining_bytes)
1549
+ bytes_to_write = a->file_remaining_bytes;
1550
+
1551
+ /* For efficiency, if a copy length is full of the uncompressed
1552
+ * buffer size, do not copy writing data to it. */
1553
+ if (bytes_to_write == MAX_DECMPFS_BLOCK_SIZE)
1554
+ buffer_to_write = buff;
1555
+ else {
1556
+ memcpy(a->uncompressed_buffer +
1557
+ MAX_DECMPFS_BLOCK_SIZE - a->block_remaining_bytes,
1558
+ buff, bytes_to_write);
1559
+ buffer_to_write = a->uncompressed_buffer;
1560
+ }
1561
+ a->block_remaining_bytes -= bytes_to_write;
1562
+ a->file_remaining_bytes -= bytes_to_write;
1563
+
1564
+ if (a->block_remaining_bytes == 0 || a->file_remaining_bytes == 0) {
1565
+ ret = hfs_drive_compressor(a, buffer_to_write,
1566
+ MAX_DECMPFS_BLOCK_SIZE - a->block_remaining_bytes);
1567
+ if (ret < 0)
1568
+ return (ret);
1569
+ a->block_remaining_bytes = MAX_DECMPFS_BLOCK_SIZE;
1570
+ }
1571
+ /* Ignore redundant bytes. */
1572
+ if (a->file_remaining_bytes == 0)
1573
+ return ((ssize_t)size);
1574
+ return (bytes_to_write);
1575
+ }
1576
+
1577
+ static ssize_t
1578
+ hfs_write_data_block(struct archive_write_disk *a, const char *buff,
1579
+ size_t size)
1580
+ {
1581
+ uint64_t start_size = size;
1582
+ ssize_t bytes_written = 0;
1583
+ ssize_t bytes_to_write;
1584
+
1585
+ if (size == 0)
1586
+ return (ARCHIVE_OK);
1587
+
1588
+ if (a->filesize == 0 || a->fd < 0) {
1589
+ archive_set_error(&a->archive, 0,
1590
+ "Attempt to write to an empty file");
1591
+ return (ARCHIVE_WARN);
1592
+ }
1593
+
1594
+ /* If this write would run beyond the file size, truncate it. */
1595
+ if (a->filesize >= 0 && (int64_t)(a->offset + size) > a->filesize)
1596
+ start_size = size = (size_t)(a->filesize - a->offset);
1597
+
1598
+ /* Write the data. */
1599
+ while (size > 0) {
1600
+ bytes_to_write = size;
1601
+ /* Seek if necessary to the specified offset. */
1602
+ if (a->offset < a->fd_offset) {
1603
+ /* Can't support backward move. */
1604
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1605
+ "Seek failed");
1606
+ return (ARCHIVE_FATAL);
1607
+ } else if (a->offset > a->fd_offset) {
1608
+ int64_t skip = a->offset - a->fd_offset;
1609
+ char nullblock[1024];
1610
+
1611
+ memset(nullblock, 0, sizeof(nullblock));
1612
+ while (skip > 0) {
1613
+ if (skip > (int64_t)sizeof(nullblock))
1614
+ bytes_written = hfs_write_decmpfs_block(
1615
+ a, nullblock, sizeof(nullblock));
1616
+ else
1617
+ bytes_written = hfs_write_decmpfs_block(
1618
+ a, nullblock, skip);
1619
+ if (bytes_written < 0) {
1620
+ archive_set_error(&a->archive, errno,
1621
+ "Write failed");
1622
+ return (ARCHIVE_WARN);
1623
+ }
1624
+ skip -= bytes_written;
1625
+ }
1626
+
1627
+ a->fd_offset = a->offset;
1628
+ }
1629
+ bytes_written =
1630
+ hfs_write_decmpfs_block(a, buff, bytes_to_write);
1631
+ if (bytes_written < 0)
1632
+ return (bytes_written);
1633
+ buff += bytes_written;
1634
+ size -= bytes_written;
1635
+ a->total_bytes_written += bytes_written;
1636
+ a->offset += bytes_written;
1637
+ a->fd_offset = a->offset;
1638
+ }
1639
+ return (start_size - size);
1640
+ }
1641
+ #else
1642
+ static ssize_t
1643
+ hfs_write_data_block(struct archive_write_disk *a, const char *buff,
1644
+ size_t size)
1645
+ {
1646
+ return (write_data_block(a, buff, size));
1647
+ }
1648
+ #endif
1649
+
1650
+ static ssize_t
1651
+ _archive_write_disk_data_block(struct archive *_a,
1652
+ const void *buff, size_t size, int64_t offset)
1653
+ {
1654
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
1655
+ ssize_t r;
1656
+
1657
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
1658
+ ARCHIVE_STATE_DATA, "archive_write_data_block");
1659
+
1660
+ a->offset = offset;
1661
+ if (a->todo & TODO_HFS_COMPRESSION)
1662
+ r = hfs_write_data_block(a, buff, size);
1663
+ else
1664
+ r = write_data_block(a, buff, size);
1665
+ if (r < ARCHIVE_OK)
1666
+ return (r);
1667
+ if ((size_t)r < size) {
1668
+ archive_set_error(&a->archive, 0,
1669
+ "Too much data: Truncating file at %ju bytes",
1670
+ (uintmax_t)a->filesize);
1671
+ return (ARCHIVE_WARN);
1672
+ }
1673
+ #if ARCHIVE_VERSION_NUMBER < 3999000
1674
+ return (ARCHIVE_OK);
1675
+ #else
1676
+ return (size);
1677
+ #endif
1678
+ }
1679
+
1680
+ static ssize_t
1681
+ _archive_write_disk_data(struct archive *_a, const void *buff, size_t size)
1682
+ {
1683
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
1684
+
1685
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
1686
+ ARCHIVE_STATE_DATA, "archive_write_data");
1687
+
1688
+ if (a->todo & TODO_HFS_COMPRESSION)
1689
+ return (hfs_write_data_block(a, buff, size));
1690
+ return (write_data_block(a, buff, size));
1691
+ }
1692
+
1693
+ static int
1694
+ _archive_write_disk_finish_entry(struct archive *_a)
1695
+ {
1696
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
1697
+ int ret = ARCHIVE_OK;
1698
+
1699
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
1700
+ ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
1701
+ "archive_write_finish_entry");
1702
+ if (a->archive.state & ARCHIVE_STATE_HEADER)
1703
+ return (ARCHIVE_OK);
1704
+ archive_clear_error(&a->archive);
1705
+
1706
+ /* Pad or truncate file to the right size. */
1707
+ if (a->fd < 0) {
1708
+ /* There's no file. */
1709
+ } else if (a->filesize < 0) {
1710
+ /* File size is unknown, so we can't set the size. */
1711
+ } else if (a->fd_offset == a->filesize) {
1712
+ /* Last write ended at exactly the filesize; we're done. */
1713
+ /* Hopefully, this is the common case. */
1714
+ #if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H)
1715
+ } else if (a->todo & TODO_HFS_COMPRESSION) {
1716
+ char null_d[1024];
1717
+ ssize_t r;
1718
+
1719
+ if (a->file_remaining_bytes)
1720
+ memset(null_d, 0, sizeof(null_d));
1721
+ while (a->file_remaining_bytes) {
1722
+ if (a->file_remaining_bytes > sizeof(null_d))
1723
+ r = hfs_write_data_block(
1724
+ a, null_d, sizeof(null_d));
1725
+ else
1726
+ r = hfs_write_data_block(
1727
+ a, null_d, a->file_remaining_bytes);
1728
+ if (r < 0)
1729
+ return ((int)r);
1730
+ }
1731
+ #endif
1732
+ } else {
1733
+ #if HAVE_FTRUNCATE
1734
+ if (ftruncate(a->fd, a->filesize) == -1 &&
1735
+ a->filesize == 0) {
1736
+ archive_set_error(&a->archive, errno,
1737
+ "File size could not be restored");
1738
+ return (ARCHIVE_FAILED);
1739
+ }
1740
+ #endif
1741
+ /*
1742
+ * Not all platforms implement the XSI option to
1743
+ * extend files via ftruncate. Stat() the file again
1744
+ * to see what happened.
1745
+ */
1746
+ a->pst = NULL;
1747
+ if ((ret = lazy_stat(a)) != ARCHIVE_OK)
1748
+ return (ret);
1749
+ /* We can use lseek()/write() to extend the file if
1750
+ * ftruncate didn't work or isn't available. */
1751
+ if (a->st.st_size < a->filesize) {
1752
+ const char nul = '\0';
1753
+ if (lseek(a->fd, a->filesize - 1, SEEK_SET) < 0) {
1754
+ archive_set_error(&a->archive, errno,
1755
+ "Seek failed");
1756
+ return (ARCHIVE_FATAL);
1757
+ }
1758
+ if (write(a->fd, &nul, 1) < 0) {
1759
+ archive_set_error(&a->archive, errno,
1760
+ "Write to restore size failed");
1761
+ return (ARCHIVE_FATAL);
1762
+ }
1763
+ a->pst = NULL;
1764
+ }
1765
+ }
1766
+
1767
+ /* Restore metadata. */
1768
+
1769
+ /*
1770
+ * This is specific to Mac OS X.
1771
+ * If the current file is an AppleDouble file, it should be
1772
+ * linked with the data fork file and remove it.
1773
+ */
1774
+ if (a->todo & TODO_APPLEDOUBLE) {
1775
+ int r2 = fixup_appledouble(a, a->name);
1776
+ if (r2 == ARCHIVE_EOF) {
1777
+ /* The current file has been successfully linked
1778
+ * with the data fork file and removed. So there
1779
+ * is nothing to do on the current file. */
1780
+ goto finish_metadata;
1781
+ }
1782
+ if (r2 < ret) ret = r2;
1783
+ }
1784
+
1785
+ /*
1786
+ * Look up the "real" UID only if we're going to need it.
1787
+ * TODO: the TODO_SGID condition can be dropped here, can't it?
1788
+ */
1789
+ if (a->todo & (TODO_OWNER | TODO_SUID | TODO_SGID)) {
1790
+ a->uid = archive_write_disk_uid(&a->archive,
1791
+ archive_entry_uname(a->entry),
1792
+ archive_entry_uid(a->entry));
1793
+ }
1794
+ /* Look up the "real" GID only if we're going to need it. */
1795
+ /* TODO: the TODO_SUID condition can be dropped here, can't it? */
1796
+ if (a->todo & (TODO_OWNER | TODO_SGID | TODO_SUID)) {
1797
+ a->gid = archive_write_disk_gid(&a->archive,
1798
+ archive_entry_gname(a->entry),
1799
+ archive_entry_gid(a->entry));
1800
+ }
1801
+
1802
+ /*
1803
+ * Restore ownership before set_mode tries to restore suid/sgid
1804
+ * bits. If we set the owner, we know what it is and can skip
1805
+ * a stat() call to examine the ownership of the file on disk.
1806
+ */
1807
+ if (a->todo & TODO_OWNER) {
1808
+ int r2 = set_ownership(a);
1809
+ if (r2 < ret) ret = r2;
1810
+ }
1811
+
1812
+ /*
1813
+ * HYPOTHESIS:
1814
+ * If we're not root, we won't be setting any security
1815
+ * attributes that may be wiped by the set_mode() routine
1816
+ * below. We also can't set xattr on non-owner-writable files,
1817
+ * which may be the state after set_mode(). Perform
1818
+ * set_xattrs() first based on these constraints.
1819
+ */
1820
+ if (a->user_uid != 0 &&
1821
+ (a->todo & TODO_XATTR)) {
1822
+ int r2 = set_xattrs(a);
1823
+ if (r2 < ret) ret = r2;
1824
+ }
1825
+
1826
+ /*
1827
+ * set_mode must precede ACLs on systems such as Solaris and
1828
+ * FreeBSD where setting the mode implicitly clears extended ACLs
1829
+ */
1830
+ if (a->todo & TODO_MODE) {
1831
+ int r2 = set_mode(a, a->mode);
1832
+ if (r2 < ret) ret = r2;
1833
+ }
1834
+
1835
+ /*
1836
+ * Security-related extended attributes (such as
1837
+ * security.capability on Linux) have to be restored last,
1838
+ * since they're implicitly removed by other file changes.
1839
+ * We do this last only when root.
1840
+ */
1841
+ if (a->user_uid == 0 &&
1842
+ (a->todo & TODO_XATTR)) {
1843
+ int r2 = set_xattrs(a);
1844
+ if (r2 < ret) ret = r2;
1845
+ }
1846
+
1847
+ /*
1848
+ * Some flags prevent file modification; they must be restored after
1849
+ * file contents are written.
1850
+ */
1851
+ if (a->todo & TODO_FFLAGS) {
1852
+ int r2 = set_fflags(a);
1853
+ if (r2 < ret) ret = r2;
1854
+ }
1855
+
1856
+ /*
1857
+ * Time must follow most other metadata;
1858
+ * otherwise atime will get changed.
1859
+ */
1860
+ if (a->todo & TODO_TIMES) {
1861
+ int r2 = set_times_from_entry(a);
1862
+ if (r2 < ret) ret = r2;
1863
+ }
1864
+
1865
+ /*
1866
+ * Mac extended metadata includes ACLs.
1867
+ */
1868
+ if (a->todo & TODO_MAC_METADATA) {
1869
+ const void *metadata;
1870
+ size_t metadata_size;
1871
+ metadata = archive_entry_mac_metadata(a->entry, &metadata_size);
1872
+ if (metadata != NULL && metadata_size > 0) {
1873
+ int r2 = set_mac_metadata(a, archive_entry_pathname(
1874
+ a->entry), metadata, metadata_size);
1875
+ if (r2 < ret) ret = r2;
1876
+ }
1877
+ }
1878
+
1879
+ /*
1880
+ * ACLs must be restored after timestamps because there are
1881
+ * ACLs that prevent attribute changes (including time).
1882
+ */
1883
+ if (a->todo & TODO_ACLS) {
1884
+ int r2;
1885
+ r2 = archive_write_disk_set_acls(&a->archive, a->fd,
1886
+ archive_entry_pathname(a->entry),
1887
+ archive_entry_acl(a->entry),
1888
+ archive_entry_mode(a->entry));
1889
+ if (r2 < ret) ret = r2;
1890
+ }
1891
+
1892
+ finish_metadata:
1893
+ /* If there's an fd, we can close it now. */
1894
+ if (a->fd >= 0) {
1895
+ close(a->fd);
1896
+ a->fd = -1;
1897
+ if (a->tmpname) {
1898
+ if (rename(a->tmpname, a->name) == -1) {
1899
+ archive_set_error(&a->archive, errno,
1900
+ "Failed to rename temporary file");
1901
+ ret = ARCHIVE_FAILED;
1902
+ unlink(a->tmpname);
1903
+ }
1904
+ a->tmpname = NULL;
1905
+ }
1906
+ }
1907
+ /* If there's an entry, we can release it now. */
1908
+ archive_entry_free(a->entry);
1909
+ a->entry = NULL;
1910
+ a->archive.state = ARCHIVE_STATE_HEADER;
1911
+ return (ret);
1912
+ }
1913
+
1914
+ int
1915
+ archive_write_disk_set_group_lookup(struct archive *_a,
1916
+ void *private_data,
1917
+ la_int64_t (*lookup_gid)(void *private, const char *gname, la_int64_t gid),
1918
+ void (*cleanup_gid)(void *private))
1919
+ {
1920
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
1921
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
1922
+ ARCHIVE_STATE_ANY, "archive_write_disk_set_group_lookup");
1923
+
1924
+ if (a->cleanup_gid != NULL && a->lookup_gid_data != NULL)
1925
+ (a->cleanup_gid)(a->lookup_gid_data);
1926
+
1927
+ a->lookup_gid = lookup_gid;
1928
+ a->cleanup_gid = cleanup_gid;
1929
+ a->lookup_gid_data = private_data;
1930
+ return (ARCHIVE_OK);
1931
+ }
1932
+
1933
+ int
1934
+ archive_write_disk_set_user_lookup(struct archive *_a,
1935
+ void *private_data,
1936
+ int64_t (*lookup_uid)(void *private, const char *uname, int64_t uid),
1937
+ void (*cleanup_uid)(void *private))
1938
+ {
1939
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
1940
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
1941
+ ARCHIVE_STATE_ANY, "archive_write_disk_set_user_lookup");
1942
+
1943
+ if (a->cleanup_uid != NULL && a->lookup_uid_data != NULL)
1944
+ (a->cleanup_uid)(a->lookup_uid_data);
1945
+
1946
+ a->lookup_uid = lookup_uid;
1947
+ a->cleanup_uid = cleanup_uid;
1948
+ a->lookup_uid_data = private_data;
1949
+ return (ARCHIVE_OK);
1950
+ }
1951
+
1952
+ int64_t
1953
+ archive_write_disk_gid(struct archive *_a, const char *name, la_int64_t id)
1954
+ {
1955
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
1956
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
1957
+ ARCHIVE_STATE_ANY, "archive_write_disk_gid");
1958
+ if (a->lookup_gid)
1959
+ return (a->lookup_gid)(a->lookup_gid_data, name, id);
1960
+ return (id);
1961
+ }
1962
+
1963
+ int64_t
1964
+ archive_write_disk_uid(struct archive *_a, const char *name, la_int64_t id)
1965
+ {
1966
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
1967
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
1968
+ ARCHIVE_STATE_ANY, "archive_write_disk_uid");
1969
+ if (a->lookup_uid)
1970
+ return (a->lookup_uid)(a->lookup_uid_data, name, id);
1971
+ return (id);
1972
+ }
1973
+
1974
+ /*
1975
+ * Create a new archive_write_disk object and initialize it with global state.
1976
+ */
1977
+ struct archive *
1978
+ archive_write_disk_new(void)
1979
+ {
1980
+ struct archive_write_disk *a;
1981
+
1982
+ a = (struct archive_write_disk *)calloc(1, sizeof(*a));
1983
+ if (a == NULL)
1984
+ return (NULL);
1985
+ a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC;
1986
+ /* We're ready to write a header immediately. */
1987
+ a->archive.state = ARCHIVE_STATE_HEADER;
1988
+ a->archive.vtable = &archive_write_disk_vtable;
1989
+ a->start_time = time(NULL);
1990
+ /* Query and restore the umask. */
1991
+ umask(a->user_umask = umask(0));
1992
+ #ifdef HAVE_GETEUID
1993
+ a->user_uid = geteuid();
1994
+ #endif /* HAVE_GETEUID */
1995
+ if (archive_string_ensure(&a->path_safe, 512) == NULL) {
1996
+ free(a);
1997
+ return (NULL);
1998
+ }
1999
+ a->path_safe.s[0] = 0;
2000
+
2001
+ #ifdef HAVE_ZLIB_H
2002
+ a->decmpfs_compression_level = 5;
2003
+ #endif
2004
+ return (&a->archive);
2005
+ }
2006
+
2007
+
2008
+ /*
2009
+ * If pathname is longer than PATH_MAX, chdir to a suitable
2010
+ * intermediate dir and edit the path down to a shorter suffix. Note
2011
+ * that this routine never returns an error; if the chdir() attempt
2012
+ * fails for any reason, we just go ahead with the long pathname. The
2013
+ * object creation is likely to fail, but any error will get handled
2014
+ * at that time.
2015
+ */
2016
+ #if defined(HAVE_FCHDIR) && defined(PATH_MAX)
2017
+ static void
2018
+ edit_deep_directories(struct archive_write_disk *a)
2019
+ {
2020
+ int ret;
2021
+ char *tail = a->name;
2022
+
2023
+ /* If path is short, avoid the open() below. */
2024
+ if (strlen(tail) < PATH_MAX)
2025
+ return;
2026
+
2027
+ /* Try to record our starting dir. */
2028
+ a->restore_pwd = la_opendirat(AT_FDCWD, ".");
2029
+ __archive_ensure_cloexec_flag(a->restore_pwd);
2030
+ if (a->restore_pwd < 0)
2031
+ return;
2032
+
2033
+ /* As long as the path is too long... */
2034
+ while (strlen(tail) >= PATH_MAX) {
2035
+ /* Locate a dir prefix shorter than PATH_MAX. */
2036
+ tail += PATH_MAX - 8;
2037
+ while (tail > a->name && *tail != '/')
2038
+ tail--;
2039
+ /* Exit if we find a too-long path component. */
2040
+ if (tail <= a->name)
2041
+ return;
2042
+ /* Create the intermediate dir and chdir to it. */
2043
+ *tail = '\0'; /* Terminate dir portion */
2044
+ ret = create_dir(a, a->name);
2045
+ if (ret == ARCHIVE_OK && chdir(a->name) != 0)
2046
+ ret = ARCHIVE_FAILED;
2047
+ *tail = '/'; /* Restore the / we removed. */
2048
+ if (ret != ARCHIVE_OK)
2049
+ return;
2050
+ tail++;
2051
+ /* The chdir() succeeded; we've now shortened the path. */
2052
+ a->name = tail;
2053
+ }
2054
+ return;
2055
+ }
2056
+ #endif
2057
+
2058
+ /*
2059
+ * The main restore function.
2060
+ */
2061
+ static int
2062
+ restore_entry(struct archive_write_disk *a)
2063
+ {
2064
+ int ret = ARCHIVE_OK, en;
2065
+
2066
+ if (a->flags & ARCHIVE_EXTRACT_UNLINK && !S_ISDIR(a->mode)) {
2067
+ /*
2068
+ * TODO: Fix this. Apparently, there are platforms
2069
+ * that still allow root to hose the entire filesystem
2070
+ * by unlinking a dir. The S_ISDIR() test above
2071
+ * prevents us from using unlink() here if the new
2072
+ * object is a dir, but that doesn't mean the old
2073
+ * object isn't a dir.
2074
+ */
2075
+ if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS)
2076
+ (void)clear_nochange_fflags(a);
2077
+ if (unlink(a->name) == 0) {
2078
+ /* We removed it, reset cached stat. */
2079
+ a->pst = NULL;
2080
+ } else if (errno == ENOENT) {
2081
+ /* File didn't exist, that's just as good. */
2082
+ } else if (rmdir(a->name) == 0) {
2083
+ /* It was a dir, but now it's gone. */
2084
+ a->pst = NULL;
2085
+ } else {
2086
+ /* We tried, but couldn't get rid of it. */
2087
+ archive_set_error(&a->archive, errno,
2088
+ "Could not unlink");
2089
+ return(ARCHIVE_FAILED);
2090
+ }
2091
+ }
2092
+
2093
+ /* Try creating it first; if this fails, we'll try to recover. */
2094
+ en = create_filesystem_object(a);
2095
+
2096
+ if ((en == ENOTDIR || en == ENOENT)
2097
+ && !(a->flags & ARCHIVE_EXTRACT_NO_AUTODIR)) {
2098
+ /* If the parent dir doesn't exist, try creating it. */
2099
+ create_parent_dir(a, a->name);
2100
+ /* Now try to create the object again. */
2101
+ en = create_filesystem_object(a);
2102
+ }
2103
+
2104
+ if ((en == ENOENT) && (archive_entry_hardlink(a->entry) != NULL)) {
2105
+ archive_set_error(&a->archive, en,
2106
+ "Hard-link target '%s' does not exist.",
2107
+ archive_entry_hardlink(a->entry));
2108
+ return (ARCHIVE_FAILED);
2109
+ }
2110
+
2111
+ if ((en == EISDIR || en == EEXIST)
2112
+ && (a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
2113
+ /* If we're not overwriting, we're done. */
2114
+ if (S_ISDIR(a->mode)) {
2115
+ /* Don't overwrite any settings on existing directories. */
2116
+ a->todo = 0;
2117
+ }
2118
+ archive_entry_unset_size(a->entry);
2119
+ return (ARCHIVE_OK);
2120
+ }
2121
+
2122
+ /*
2123
+ * Some platforms return EISDIR if you call
2124
+ * open(O_WRONLY | O_EXCL | O_CREAT) on a directory, some
2125
+ * return EEXIST. POSIX is ambiguous, requiring EISDIR
2126
+ * for open(O_WRONLY) on a dir and EEXIST for open(O_EXCL | O_CREAT)
2127
+ * on an existing item.
2128
+ */
2129
+ if (en == EISDIR) {
2130
+ /* A dir is in the way of a non-dir, rmdir it. */
2131
+ if (rmdir(a->name) != 0) {
2132
+ archive_set_error(&a->archive, errno,
2133
+ "Can't remove already-existing dir");
2134
+ return (ARCHIVE_FAILED);
2135
+ }
2136
+ a->pst = NULL;
2137
+ /* Try again. */
2138
+ en = create_filesystem_object(a);
2139
+ } else if (en == EEXIST) {
2140
+ /*
2141
+ * We know something is in the way, but we don't know what;
2142
+ * we need to find out before we go any further.
2143
+ */
2144
+ int r = 0;
2145
+ /*
2146
+ * The SECURE_SYMLINKS logic has already removed a
2147
+ * symlink to a dir if the client wants that. So
2148
+ * follow the symlink if we're creating a dir.
2149
+ */
2150
+ if (S_ISDIR(a->mode))
2151
+ r = la_stat(a->name, &a->st);
2152
+ /*
2153
+ * If it's not a dir (or it's a broken symlink),
2154
+ * then don't follow it.
2155
+ */
2156
+ if (r != 0 || !S_ISDIR(a->mode))
2157
+ r = lstat(a->name, &a->st);
2158
+ if (r != 0) {
2159
+ archive_set_error(&a->archive, errno,
2160
+ "Can't stat existing object");
2161
+ return (ARCHIVE_FAILED);
2162
+ }
2163
+
2164
+ /*
2165
+ * NO_OVERWRITE_NEWER doesn't apply to directories.
2166
+ */
2167
+ if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER)
2168
+ && !S_ISDIR(a->st.st_mode)) {
2169
+ if (!older(&(a->st), a->entry)) {
2170
+ archive_entry_unset_size(a->entry);
2171
+ return (ARCHIVE_OK);
2172
+ }
2173
+ }
2174
+
2175
+ /* If it's our archive, we're done. */
2176
+ if (a->skip_file_set &&
2177
+ a->st.st_dev == (dev_t)a->skip_file_dev &&
2178
+ a->st.st_ino == (ino_t)a->skip_file_ino) {
2179
+ archive_set_error(&a->archive, 0,
2180
+ "Refusing to overwrite archive");
2181
+ return (ARCHIVE_FAILED);
2182
+ }
2183
+
2184
+ if (!S_ISDIR(a->st.st_mode)) {
2185
+ if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS)
2186
+ (void)clear_nochange_fflags(a);
2187
+
2188
+ if ((a->flags & ARCHIVE_EXTRACT_SAFE_WRITES) &&
2189
+ S_ISREG(a->st.st_mode)) {
2190
+ /* Use a temporary file to extract */
2191
+ if ((a->fd = la_mktemp(a)) == -1) {
2192
+ archive_set_error(&a->archive, errno,
2193
+ "Can't create temporary file");
2194
+ return ARCHIVE_FAILED;
2195
+ }
2196
+ a->pst = NULL;
2197
+ en = 0;
2198
+ } else {
2199
+ /* A non-dir is in the way, unlink it. */
2200
+ if (unlink(a->name) != 0) {
2201
+ archive_set_error(&a->archive, errno,
2202
+ "Can't unlink already-existing "
2203
+ "object");
2204
+ return (ARCHIVE_FAILED);
2205
+ }
2206
+ a->pst = NULL;
2207
+ /* Try again. */
2208
+ en = create_filesystem_object(a);
2209
+ }
2210
+ } else if (!S_ISDIR(a->mode)) {
2211
+ /* A dir is in the way of a non-dir, rmdir it. */
2212
+ if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS)
2213
+ (void)clear_nochange_fflags(a);
2214
+ if (rmdir(a->name) != 0) {
2215
+ archive_set_error(&a->archive, errno,
2216
+ "Can't replace existing directory with non-directory");
2217
+ return (ARCHIVE_FAILED);
2218
+ }
2219
+ /* Try again. */
2220
+ en = create_filesystem_object(a);
2221
+ } else {
2222
+ /*
2223
+ * There's a dir in the way of a dir. Don't
2224
+ * waste time with rmdir()/mkdir(), just fix
2225
+ * up the permissions on the existing dir.
2226
+ * Note that we don't change perms on existing
2227
+ * dirs unless _EXTRACT_PERM is specified.
2228
+ */
2229
+ if ((a->mode != a->st.st_mode)
2230
+ && (a->todo & TODO_MODE_FORCE))
2231
+ a->deferred |= (a->todo & TODO_MODE);
2232
+ /* Ownership doesn't need deferred fixup. */
2233
+ en = 0; /* Forget the EEXIST. */
2234
+ }
2235
+ }
2236
+
2237
+ if (en) {
2238
+ /* Everything failed; give up here. */
2239
+ if ((&a->archive)->error == NULL)
2240
+ archive_set_error(&a->archive, en, "Can't create '%s'",
2241
+ a->name);
2242
+ return (ARCHIVE_FAILED);
2243
+ }
2244
+
2245
+ a->pst = NULL; /* Cached stat data no longer valid. */
2246
+ return (ret);
2247
+ }
2248
+
2249
+ /*
2250
+ * Returns 0 if creation succeeds, or else returns errno value from
2251
+ * the failed system call. Note: This function should only ever perform
2252
+ * a single system call.
2253
+ */
2254
+ static int
2255
+ create_filesystem_object(struct archive_write_disk *a)
2256
+ {
2257
+ /* Create the entry. */
2258
+ const char *linkname;
2259
+ mode_t final_mode, mode;
2260
+ int r;
2261
+ /* these for check_symlinks_fsobj */
2262
+ char *linkname_copy; /* non-const copy of linkname */
2263
+ struct stat st;
2264
+ struct archive_string error_string;
2265
+ int error_number;
2266
+
2267
+ /* We identify hard/symlinks according to the link names. */
2268
+ /* Since link(2) and symlink(2) don't handle modes, we're done here. */
2269
+ linkname = archive_entry_hardlink(a->entry);
2270
+ if (linkname != NULL) {
2271
+ #if !HAVE_LINK
2272
+ return (EPERM);
2273
+ #else
2274
+ archive_string_init(&error_string);
2275
+ linkname_copy = strdup(linkname);
2276
+ if (linkname_copy == NULL) {
2277
+ return (EPERM);
2278
+ }
2279
+ /*
2280
+ * TODO: consider using the cleaned-up path as the link
2281
+ * target?
2282
+ */
2283
+ r = cleanup_pathname_fsobj(linkname_copy, &error_number,
2284
+ &error_string, a->flags);
2285
+ if (r != ARCHIVE_OK) {
2286
+ archive_set_error(&a->archive, error_number, "%s",
2287
+ error_string.s);
2288
+ free(linkname_copy);
2289
+ archive_string_free(&error_string);
2290
+ /*
2291
+ * EPERM is more appropriate than error_number for our
2292
+ * callers
2293
+ */
2294
+ return (EPERM);
2295
+ }
2296
+ r = check_symlinks_fsobj(linkname_copy, &error_number,
2297
+ &error_string, a->flags, 1);
2298
+ if (r != ARCHIVE_OK) {
2299
+ archive_set_error(&a->archive, error_number, "%s",
2300
+ error_string.s);
2301
+ free(linkname_copy);
2302
+ archive_string_free(&error_string);
2303
+ /*
2304
+ * EPERM is more appropriate than error_number for our
2305
+ * callers
2306
+ */
2307
+ return (EPERM);
2308
+ }
2309
+ free(linkname_copy);
2310
+ archive_string_free(&error_string);
2311
+ /*
2312
+ * Unlinking and linking here is really not atomic,
2313
+ * but doing it right, would require us to construct
2314
+ * an mktemplink() function, and then use rename(2).
2315
+ */
2316
+ if (a->flags & ARCHIVE_EXTRACT_SAFE_WRITES)
2317
+ unlink(a->name);
2318
+ #ifdef HAVE_LINKAT
2319
+ r = linkat(AT_FDCWD, linkname, AT_FDCWD, a->name,
2320
+ 0) ? errno : 0;
2321
+ #else
2322
+ r = link(linkname, a->name) ? errno : 0;
2323
+ #endif
2324
+ /*
2325
+ * New cpio and pax formats allow hardlink entries
2326
+ * to carry data, so we may have to open the file
2327
+ * for hardlink entries.
2328
+ *
2329
+ * If the hardlink was successfully created and
2330
+ * the archive doesn't have carry data for it,
2331
+ * consider it to be non-authoritative for meta data.
2332
+ * This is consistent with GNU tar and BSD pax.
2333
+ * If the hardlink does carry data, let the last
2334
+ * archive entry decide ownership.
2335
+ */
2336
+ if (r == 0 && a->filesize <= 0) {
2337
+ a->todo = 0;
2338
+ a->deferred = 0;
2339
+ } else if (r == 0 && a->filesize > 0) {
2340
+ #ifdef HAVE_LSTAT
2341
+ r = lstat(a->name, &st);
2342
+ #else
2343
+ r = la_stat(a->name, &st);
2344
+ #endif
2345
+ if (r != 0)
2346
+ r = errno;
2347
+ else if ((st.st_mode & AE_IFMT) == AE_IFREG) {
2348
+ a->fd = open(a->name, O_WRONLY | O_TRUNC |
2349
+ O_BINARY | O_CLOEXEC | O_NOFOLLOW);
2350
+ __archive_ensure_cloexec_flag(a->fd);
2351
+ if (a->fd < 0)
2352
+ r = errno;
2353
+ }
2354
+ }
2355
+ return (r);
2356
+ #endif
2357
+ }
2358
+ linkname = archive_entry_symlink(a->entry);
2359
+ if (linkname != NULL) {
2360
+ #if HAVE_SYMLINK
2361
+ /*
2362
+ * Unlinking and linking here is really not atomic,
2363
+ * but doing it right, would require us to construct
2364
+ * an mktempsymlink() function, and then use rename(2).
2365
+ */
2366
+ if (a->flags & ARCHIVE_EXTRACT_SAFE_WRITES)
2367
+ unlink(a->name);
2368
+ return symlink(linkname, a->name) ? errno : 0;
2369
+ #else
2370
+ return (EPERM);
2371
+ #endif
2372
+ }
2373
+
2374
+ /*
2375
+ * The remaining system calls all set permissions, so let's
2376
+ * try to take advantage of that to avoid an extra chmod()
2377
+ * call. (Recall that umask is set to zero right now!)
2378
+ */
2379
+
2380
+ /* Mode we want for the final restored object (w/o file type bits). */
2381
+ final_mode = a->mode & 07777;
2382
+ /*
2383
+ * The mode that will actually be restored in this step. Note
2384
+ * that SUID, SGID, etc, require additional work to ensure
2385
+ * security, so we never restore them at this point.
2386
+ */
2387
+ mode = final_mode & 0777 & ~a->user_umask;
2388
+
2389
+ /*
2390
+ * Always create writable such that [f]setxattr() works if we're not
2391
+ * root.
2392
+ */
2393
+ if (a->user_uid != 0 &&
2394
+ a->todo & (TODO_HFS_COMPRESSION | TODO_XATTR)) {
2395
+ mode |= 0200;
2396
+ }
2397
+
2398
+ switch (a->mode & AE_IFMT) {
2399
+ default:
2400
+ /* POSIX requires that we fall through here. */
2401
+ /* FALLTHROUGH */
2402
+ case AE_IFREG:
2403
+ a->tmpname = NULL;
2404
+ a->fd = open(a->name,
2405
+ O_WRONLY | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, mode);
2406
+ __archive_ensure_cloexec_flag(a->fd);
2407
+ r = (a->fd < 0);
2408
+ break;
2409
+ case AE_IFCHR:
2410
+ #ifdef HAVE_MKNOD
2411
+ /* Note: we use AE_IFCHR for the case label, and
2412
+ * S_IFCHR for the mknod() call. This is correct. */
2413
+ r = mknod(a->name, mode | S_IFCHR,
2414
+ archive_entry_rdev(a->entry));
2415
+ break;
2416
+ #else
2417
+ /* TODO: Find a better way to warn about our inability
2418
+ * to restore a char device node. */
2419
+ return (EINVAL);
2420
+ #endif /* HAVE_MKNOD */
2421
+ case AE_IFBLK:
2422
+ #ifdef HAVE_MKNOD
2423
+ r = mknod(a->name, mode | S_IFBLK,
2424
+ archive_entry_rdev(a->entry));
2425
+ break;
2426
+ #else
2427
+ /* TODO: Find a better way to warn about our inability
2428
+ * to restore a block device node. */
2429
+ return (EINVAL);
2430
+ #endif /* HAVE_MKNOD */
2431
+ case AE_IFDIR:
2432
+ mode = (mode | MINIMUM_DIR_MODE) & MAXIMUM_DIR_MODE;
2433
+ r = mkdir(a->name, mode);
2434
+ if (r == 0) {
2435
+ /* Defer setting dir times. */
2436
+ a->deferred |= (a->todo & TODO_TIMES);
2437
+ a->todo &= ~TODO_TIMES;
2438
+ /* Never use an immediate chmod(). */
2439
+ /* We can't avoid the chmod() entirely if EXTRACT_PERM
2440
+ * because of SysV SGID inheritance. */
2441
+ if ((mode != final_mode)
2442
+ || (a->flags & ARCHIVE_EXTRACT_PERM))
2443
+ a->deferred |= (a->todo & TODO_MODE);
2444
+ a->todo &= ~TODO_MODE;
2445
+ }
2446
+ break;
2447
+ case AE_IFIFO:
2448
+ #ifdef HAVE_MKFIFO
2449
+ r = mkfifo(a->name, mode);
2450
+ break;
2451
+ #else
2452
+ /* TODO: Find a better way to warn about our inability
2453
+ * to restore a fifo. */
2454
+ return (EINVAL);
2455
+ #endif /* HAVE_MKFIFO */
2456
+ }
2457
+
2458
+ /* All the system calls above set errno on failure. */
2459
+ if (r)
2460
+ return (errno);
2461
+
2462
+ /* If we managed to set the final mode, we've avoided a chmod(). */
2463
+ if (mode == final_mode)
2464
+ a->todo &= ~TODO_MODE;
2465
+ return (0);
2466
+ }
2467
+
2468
+ /*
2469
+ * Cleanup function for archive_extract. Mostly, this involves processing
2470
+ * the fixup list, which is used to address a number of problems:
2471
+ * * Dir permissions might prevent us from restoring a file in that
2472
+ * dir, so we restore the dir with minimum 0700 permissions first,
2473
+ * then correct the mode at the end.
2474
+ * * Similarly, the act of restoring a file touches the directory
2475
+ * and changes the timestamp on the dir, so we have to touch-up dir
2476
+ * timestamps at the end as well.
2477
+ * * Some file flags can interfere with the restore by, for example,
2478
+ * preventing the creation of hardlinks to those files.
2479
+ * * Mac OS extended metadata includes ACLs, so must be deferred on dirs.
2480
+ *
2481
+ * Note that tar/cpio do not require that archives be in a particular
2482
+ * order; there is no way to know when the last file has been restored
2483
+ * within a directory, so there's no way to optimize the memory usage
2484
+ * here by fixing up the directory any earlier than the
2485
+ * end-of-archive.
2486
+ *
2487
+ * XXX TODO: Directory ACLs should be restored here, for the same
2488
+ * reason we set directory perms here. XXX
2489
+ */
2490
+ static int
2491
+ _archive_write_disk_close(struct archive *_a)
2492
+ {
2493
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
2494
+ struct fixup_entry *next, *p;
2495
+ struct stat st;
2496
+ char *c;
2497
+ int fd, ret, openflags;
2498
+
2499
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
2500
+ ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
2501
+ "archive_write_disk_close");
2502
+ ret = _archive_write_disk_finish_entry(&a->archive);
2503
+
2504
+ /* Sort dir list so directories are fixed up in depth-first order. */
2505
+ p = sort_dir_list(a->fixup_list);
2506
+
2507
+ while (p != NULL) {
2508
+ fd = -1;
2509
+ a->pst = NULL; /* Mark stat cache as out-of-date. */
2510
+
2511
+ /* We must strip trailing slashes from the path to avoid
2512
+ dereferencing symbolic links to directories */
2513
+ c = p->name;
2514
+ while (*c != '\0')
2515
+ c++;
2516
+ while (c != p->name && *(c - 1) == '/') {
2517
+ c--;
2518
+ *c = '\0';
2519
+ }
2520
+
2521
+ if (p->fixup == 0)
2522
+ goto skip_fixup_entry;
2523
+ else {
2524
+ /*
2525
+ * We need to verify if the type of the file
2526
+ * we are going to open matches the file type
2527
+ * of the fixup entry.
2528
+ */
2529
+ openflags = O_BINARY | O_NOFOLLOW | O_RDONLY
2530
+ | O_CLOEXEC;
2531
+ #if defined(O_DIRECTORY)
2532
+ if (p->filetype == AE_IFDIR)
2533
+ openflags |= O_DIRECTORY;
2534
+ #endif
2535
+ fd = open(p->name, openflags);
2536
+
2537
+ #if defined(O_DIRECTORY)
2538
+ /*
2539
+ * If we support O_DIRECTORY and open was
2540
+ * successful we can skip the file type check
2541
+ * for directories. For other file types
2542
+ * we need to verify via fstat() or lstat()
2543
+ */
2544
+ if (fd == -1 || p->filetype != AE_IFDIR) {
2545
+ #if HAVE_FSTAT
2546
+ if (fd > 0 && (
2547
+ fstat(fd, &st) != 0 ||
2548
+ la_verify_filetype(st.st_mode,
2549
+ p->filetype) == 0)) {
2550
+ goto skip_fixup_entry;
2551
+ } else
2552
+ #endif
2553
+ if (lstat(p->name, &st) != 0 ||
2554
+ la_verify_filetype(st.st_mode,
2555
+ p->filetype) == 0) {
2556
+ goto skip_fixup_entry;
2557
+ }
2558
+ }
2559
+ #else
2560
+ #if HAVE_FSTAT
2561
+ if (fd > 0 && (
2562
+ fstat(fd, &st) != 0 ||
2563
+ la_verify_filetype(st.st_mode,
2564
+ p->filetype) == 0)) {
2565
+ goto skip_fixup_entry;
2566
+ } else
2567
+ #endif
2568
+ if (lstat(p->name, &st) != 0 ||
2569
+ la_verify_filetype(st.st_mode,
2570
+ p->filetype) == 0) {
2571
+ goto skip_fixup_entry;
2572
+ }
2573
+ #endif
2574
+ }
2575
+ if (p->fixup & TODO_TIMES) {
2576
+ set_times(a, fd, p->mode, p->name,
2577
+ p->atime, p->atime_nanos,
2578
+ p->birthtime, p->birthtime_nanos,
2579
+ p->mtime, p->mtime_nanos,
2580
+ p->ctime, p->ctime_nanos);
2581
+ }
2582
+ if (p->fixup & TODO_MODE_BASE) {
2583
+ #ifdef HAVE_FCHMOD
2584
+ if (fd >= 0)
2585
+ fchmod(fd, p->mode & 07777);
2586
+ else
2587
+ #endif
2588
+ #ifdef HAVE_LCHMOD
2589
+ lchmod(p->name, p->mode & 07777);
2590
+ #else
2591
+ chmod(p->name, p->mode & 07777);
2592
+ #endif
2593
+ }
2594
+ if (p->fixup & TODO_ACLS)
2595
+ archive_write_disk_set_acls(&a->archive, fd,
2596
+ p->name, &p->acl, p->mode);
2597
+ if (p->fixup & TODO_FFLAGS)
2598
+ set_fflags_platform(a, fd, p->name,
2599
+ p->mode, p->fflags_set, 0);
2600
+ if (p->fixup & TODO_MAC_METADATA)
2601
+ set_mac_metadata(a, p->name, p->mac_metadata,
2602
+ p->mac_metadata_size);
2603
+ skip_fixup_entry:
2604
+ next = p->next;
2605
+ archive_acl_clear(&p->acl);
2606
+ free(p->mac_metadata);
2607
+ free(p->name);
2608
+ if (fd >= 0)
2609
+ close(fd);
2610
+ free(p);
2611
+ p = next;
2612
+ }
2613
+ a->fixup_list = NULL;
2614
+ return (ret);
2615
+ }
2616
+
2617
+ static int
2618
+ _archive_write_disk_free(struct archive *_a)
2619
+ {
2620
+ struct archive_write_disk *a;
2621
+ int ret;
2622
+ if (_a == NULL)
2623
+ return (ARCHIVE_OK);
2624
+ archive_check_magic(_a, ARCHIVE_WRITE_DISK_MAGIC,
2625
+ ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_write_disk_free");
2626
+ a = (struct archive_write_disk *)_a;
2627
+ ret = _archive_write_disk_close(&a->archive);
2628
+ archive_write_disk_set_group_lookup(&a->archive, NULL, NULL, NULL);
2629
+ archive_write_disk_set_user_lookup(&a->archive, NULL, NULL, NULL);
2630
+ archive_entry_free(a->entry);
2631
+ archive_string_free(&a->_name_data);
2632
+ archive_string_free(&a->_tmpname_data);
2633
+ archive_string_free(&a->archive.error_string);
2634
+ archive_string_free(&a->path_safe);
2635
+ a->archive.magic = 0;
2636
+ __archive_clean(&a->archive);
2637
+ free(a->decmpfs_header_p);
2638
+ free(a->resource_fork);
2639
+ free(a->compressed_buffer);
2640
+ free(a->uncompressed_buffer);
2641
+ #if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_SYS_XATTR_H)\
2642
+ && defined(HAVE_ZLIB_H)
2643
+ if (a->stream_valid) {
2644
+ switch (deflateEnd(&a->stream)) {
2645
+ case Z_OK:
2646
+ break;
2647
+ default:
2648
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2649
+ "Failed to clean up compressor");
2650
+ ret = ARCHIVE_FATAL;
2651
+ break;
2652
+ }
2653
+ }
2654
+ #endif
2655
+ free(a);
2656
+ return (ret);
2657
+ }
2658
+
2659
+ /*
2660
+ * Simple O(n log n) merge sort to order the fixup list. In
2661
+ * particular, we want to restore dir timestamps depth-first.
2662
+ */
2663
+ static struct fixup_entry *
2664
+ sort_dir_list(struct fixup_entry *p)
2665
+ {
2666
+ struct fixup_entry *a, *b, *t;
2667
+
2668
+ if (p == NULL)
2669
+ return (NULL);
2670
+ /* A one-item list is already sorted. */
2671
+ if (p->next == NULL)
2672
+ return (p);
2673
+
2674
+ /* Step 1: split the list. */
2675
+ t = p;
2676
+ a = p->next->next;
2677
+ while (a != NULL) {
2678
+ /* Step a twice, t once. */
2679
+ a = a->next;
2680
+ if (a != NULL)
2681
+ a = a->next;
2682
+ t = t->next;
2683
+ }
2684
+ /* Now, t is at the mid-point, so break the list here. */
2685
+ b = t->next;
2686
+ t->next = NULL;
2687
+ a = p;
2688
+
2689
+ /* Step 2: Recursively sort the two sub-lists. */
2690
+ a = sort_dir_list(a);
2691
+ b = sort_dir_list(b);
2692
+
2693
+ /* Step 3: Merge the returned lists. */
2694
+ /* Pick the first element for the merged list. */
2695
+ if (strcmp(a->name, b->name) > 0) {
2696
+ t = p = a;
2697
+ a = a->next;
2698
+ } else {
2699
+ t = p = b;
2700
+ b = b->next;
2701
+ }
2702
+
2703
+ /* Always put the later element on the list first. */
2704
+ while (a != NULL && b != NULL) {
2705
+ if (strcmp(a->name, b->name) > 0) {
2706
+ t->next = a;
2707
+ a = a->next;
2708
+ } else {
2709
+ t->next = b;
2710
+ b = b->next;
2711
+ }
2712
+ t = t->next;
2713
+ }
2714
+
2715
+ /* Only one list is non-empty, so just splice it on. */
2716
+ if (a != NULL)
2717
+ t->next = a;
2718
+ if (b != NULL)
2719
+ t->next = b;
2720
+
2721
+ return (p);
2722
+ }
2723
+
2724
+ /*
2725
+ * Returns a new, initialized fixup entry.
2726
+ *
2727
+ * TODO: Reduce the memory requirements for this list by using a tree
2728
+ * structure rather than a simple list of names.
2729
+ */
2730
+ static struct fixup_entry *
2731
+ new_fixup(struct archive_write_disk *a, const char *pathname)
2732
+ {
2733
+ struct fixup_entry *fe;
2734
+
2735
+ fe = (struct fixup_entry *)calloc(1, sizeof(struct fixup_entry));
2736
+ if (fe == NULL) {
2737
+ archive_set_error(&a->archive, ENOMEM,
2738
+ "Can't allocate memory for a fixup");
2739
+ return (NULL);
2740
+ }
2741
+ fe->next = a->fixup_list;
2742
+ a->fixup_list = fe;
2743
+ fe->fixup = 0;
2744
+ fe->filetype = 0;
2745
+ fe->name = strdup(pathname);
2746
+ return (fe);
2747
+ }
2748
+
2749
+ /*
2750
+ * Returns a fixup structure for the current entry.
2751
+ */
2752
+ static struct fixup_entry *
2753
+ current_fixup(struct archive_write_disk *a, const char *pathname)
2754
+ {
2755
+ if (a->current_fixup == NULL)
2756
+ a->current_fixup = new_fixup(a, pathname);
2757
+ return (a->current_fixup);
2758
+ }
2759
+
2760
+ /* Error helper for new *_fsobj functions */
2761
+ static void
2762
+ fsobj_error(int *a_eno, struct archive_string *a_estr,
2763
+ int err, const char *errstr, const char *path)
2764
+ {
2765
+ if (a_eno)
2766
+ *a_eno = err;
2767
+ if (a_estr)
2768
+ archive_string_sprintf(a_estr, "%s%s", errstr, path);
2769
+ }
2770
+
2771
+ /*
2772
+ * TODO: Someday, integrate this with the deep dir support; they both
2773
+ * scan the path and both can be optimized by comparing against other
2774
+ * recent paths.
2775
+ */
2776
+ /*
2777
+ * Checks the given path to see if any elements along it are symlinks. Returns
2778
+ * ARCHIVE_OK if there are none, otherwise puts an error in errmsg.
2779
+ */
2780
+ static int
2781
+ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
2782
+ int flags, int checking_linkname)
2783
+ {
2784
+ #if !defined(HAVE_LSTAT) && \
2785
+ !(defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT))
2786
+ /* Platform doesn't have lstat, so we can't look for symlinks. */
2787
+ (void)path; /* UNUSED */
2788
+ (void)error_number; /* UNUSED */
2789
+ (void)error_string; /* UNUSED */
2790
+ (void)flags; /* UNUSED */
2791
+ (void)checking_linkname; /* UNUSED */
2792
+ return (ARCHIVE_OK);
2793
+ #else
2794
+ int res = ARCHIVE_OK;
2795
+ char *tail;
2796
+ char *head;
2797
+ int last;
2798
+ char c = '\0';
2799
+ int r;
2800
+ struct stat st;
2801
+ int chdir_fd;
2802
+ #if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
2803
+ int fd;
2804
+ #endif
2805
+
2806
+ /* Nothing to do here if name is empty */
2807
+ if(path[0] == '\0')
2808
+ return (ARCHIVE_OK);
2809
+
2810
+ /*
2811
+ * Guard against symlink tricks. Reject any archive entry whose
2812
+ * destination would be altered by a symlink.
2813
+ *
2814
+ * Walk the filename in chunks separated by '/'. For each segment:
2815
+ * - if it doesn't exist, continue
2816
+ * - if it's symlink, abort or remove it
2817
+ * - if it's a directory and it's not the last chunk, cd into it
2818
+ * As we go:
2819
+ * head points to the current (relative) path
2820
+ * tail points to the temporary \0 terminating the segment we're
2821
+ * currently examining
2822
+ * c holds what used to be in *tail
2823
+ * last is 1 if this is the last tail
2824
+ */
2825
+ chdir_fd = la_opendirat(AT_FDCWD, ".");
2826
+ __archive_ensure_cloexec_flag(chdir_fd);
2827
+ if (chdir_fd < 0) {
2828
+ fsobj_error(a_eno, a_estr, errno,
2829
+ "Could not open ", path);
2830
+ return (ARCHIVE_FATAL);
2831
+ }
2832
+ head = path;
2833
+ tail = path;
2834
+ last = 0;
2835
+ /* TODO: reintroduce a safe cache here? */
2836
+ /* Skip the root directory if the path is absolute. */
2837
+ if(tail == path && tail[0] == '/')
2838
+ ++tail;
2839
+ /* Keep going until we've checked the entire name.
2840
+ * head, tail, path all alias the same string, which is
2841
+ * temporarily zeroed at tail, so be careful restoring the
2842
+ * stashed (c=tail[0]) for error messages.
2843
+ * Exiting the loop with break is okay; continue is not.
2844
+ */
2845
+ while (!last) {
2846
+ /*
2847
+ * Skip the separator we just consumed, plus any adjacent ones
2848
+ */
2849
+ while (*tail == '/')
2850
+ ++tail;
2851
+ /* Skip the next path element. */
2852
+ while (*tail != '\0' && *tail != '/')
2853
+ ++tail;
2854
+ /* is this the last path component? */
2855
+ last = (tail[0] == '\0') || (tail[0] == '/' && tail[1] == '\0');
2856
+ /* temporarily truncate the string here */
2857
+ c = tail[0];
2858
+ tail[0] = '\0';
2859
+ /* Check that we haven't hit a symlink. */
2860
+ #if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
2861
+ r = fstatat(chdir_fd, head, &st, AT_SYMLINK_NOFOLLOW);
2862
+ #else
2863
+ r = lstat(head, &st);
2864
+ #endif
2865
+ if (r != 0) {
2866
+ tail[0] = c;
2867
+ /* We've hit a dir that doesn't exist; stop now. */
2868
+ if (errno == ENOENT) {
2869
+ break;
2870
+ } else {
2871
+ /*
2872
+ * Treat any other error as fatal - best to be
2873
+ * paranoid here.
2874
+ * Note: This effectively disables deep
2875
+ * directory support when security checks are
2876
+ * enabled. Otherwise, very long pathnames that
2877
+ * trigger an error here could evade the
2878
+ * sandbox.
2879
+ * TODO: We could do better, but it would
2880
+ * probably require merging the symlink checks
2881
+ * with the deep-directory editing.
2882
+ */
2883
+ fsobj_error(a_eno, a_estr, errno,
2884
+ "Could not stat ", path);
2885
+ res = ARCHIVE_FAILED;
2886
+ break;
2887
+ }
2888
+ } else if (S_ISDIR(st.st_mode)) {
2889
+ if (!last) {
2890
+ #if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
2891
+ fd = la_opendirat(chdir_fd, head);
2892
+ if (fd < 0)
2893
+ r = -1;
2894
+ else {
2895
+ r = 0;
2896
+ close(chdir_fd);
2897
+ chdir_fd = fd;
2898
+ }
2899
+ #else
2900
+ r = chdir(head);
2901
+ #endif
2902
+ if (r != 0) {
2903
+ tail[0] = c;
2904
+ fsobj_error(a_eno, a_estr, errno,
2905
+ "Could not chdir ", path);
2906
+ res = (ARCHIVE_FATAL);
2907
+ break;
2908
+ }
2909
+ /* Our view is now from inside this dir: */
2910
+ head = tail + 1;
2911
+ }
2912
+ } else if (S_ISLNK(st.st_mode)) {
2913
+ if (last && checking_linkname) {
2914
+ #ifdef HAVE_LINKAT
2915
+ /*
2916
+ * Hardlinks to symlinks are safe to write
2917
+ * if linkat() is supported as it does not
2918
+ * follow symlinks.
2919
+ */
2920
+ res = ARCHIVE_OK;
2921
+ #else
2922
+ /*
2923
+ * We return ARCHIVE_FAILED here as we are
2924
+ * not able to safely write hardlinks
2925
+ * to symlinks.
2926
+ */
2927
+ tail[0] = c;
2928
+ fsobj_error(a_eno, a_estr, errno,
2929
+ "Cannot write hardlink to symlink ",
2930
+ path);
2931
+ res = ARCHIVE_FAILED;
2932
+ #endif
2933
+ break;
2934
+ } else
2935
+ if (last) {
2936
+ /*
2937
+ * Last element is symlink; remove it
2938
+ * so we can overwrite it with the
2939
+ * item being extracted.
2940
+ */
2941
+ #if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
2942
+ r = unlinkat(chdir_fd, head, 0);
2943
+ #else
2944
+ r = unlink(head);
2945
+ #endif
2946
+ if (r != 0) {
2947
+ tail[0] = c;
2948
+ fsobj_error(a_eno, a_estr, errno,
2949
+ "Could not remove symlink ",
2950
+ path);
2951
+ res = ARCHIVE_FAILED;
2952
+ break;
2953
+ }
2954
+ /*
2955
+ * Even if we did remove it, a warning
2956
+ * is in order. The warning is silly,
2957
+ * though, if we're just replacing one
2958
+ * symlink with another symlink.
2959
+ */
2960
+ tail[0] = c;
2961
+ /*
2962
+ * FIXME: not sure how important this is to
2963
+ * restore
2964
+ */
2965
+ /*
2966
+ if (!S_ISLNK(path)) {
2967
+ fsobj_error(a_eno, a_estr, 0,
2968
+ "Removing symlink ", path);
2969
+ }
2970
+ */
2971
+ /* Symlink gone. No more problem! */
2972
+ res = ARCHIVE_OK;
2973
+ break;
2974
+ } else if (flags & ARCHIVE_EXTRACT_UNLINK) {
2975
+ /* User asked us to remove problems. */
2976
+ #if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
2977
+ r = unlinkat(chdir_fd, head, 0);
2978
+ #else
2979
+ r = unlink(head);
2980
+ #endif
2981
+ if (r != 0) {
2982
+ tail[0] = c;
2983
+ fsobj_error(a_eno, a_estr, 0,
2984
+ "Cannot remove intervening "
2985
+ "symlink ", path);
2986
+ res = ARCHIVE_FAILED;
2987
+ break;
2988
+ }
2989
+ tail[0] = c;
2990
+ } else if ((flags &
2991
+ ARCHIVE_EXTRACT_SECURE_SYMLINKS) == 0) {
2992
+ /*
2993
+ * We are not the last element and we want to
2994
+ * follow symlinks if they are a directory.
2995
+ *
2996
+ * This is needed to extract hardlinks over
2997
+ * symlinks.
2998
+ */
2999
+ #if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
3000
+ r = fstatat(chdir_fd, head, &st, 0);
3001
+ #else
3002
+ r = la_stat(head, &st);
3003
+ #endif
3004
+ if (r != 0) {
3005
+ tail[0] = c;
3006
+ if (errno == ENOENT) {
3007
+ break;
3008
+ } else {
3009
+ fsobj_error(a_eno, a_estr,
3010
+ errno,
3011
+ "Could not stat ", path);
3012
+ res = (ARCHIVE_FAILED);
3013
+ break;
3014
+ }
3015
+ } else if (S_ISDIR(st.st_mode)) {
3016
+ #if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
3017
+ fd = la_opendirat(chdir_fd, head);
3018
+ if (fd < 0)
3019
+ r = -1;
3020
+ else {
3021
+ r = 0;
3022
+ close(chdir_fd);
3023
+ chdir_fd = fd;
3024
+ }
3025
+ #else
3026
+ r = chdir(head);
3027
+ #endif
3028
+ if (r != 0) {
3029
+ tail[0] = c;
3030
+ fsobj_error(a_eno, a_estr,
3031
+ errno,
3032
+ "Could not chdir ", path);
3033
+ res = (ARCHIVE_FATAL);
3034
+ break;
3035
+ }
3036
+ /*
3037
+ * Our view is now from inside
3038
+ * this dir:
3039
+ */
3040
+ head = tail + 1;
3041
+ } else {
3042
+ tail[0] = c;
3043
+ fsobj_error(a_eno, a_estr, 0,
3044
+ "Cannot extract through "
3045
+ "symlink ", path);
3046
+ res = ARCHIVE_FAILED;
3047
+ break;
3048
+ }
3049
+ } else {
3050
+ tail[0] = c;
3051
+ fsobj_error(a_eno, a_estr, 0,
3052
+ "Cannot extract through symlink ", path);
3053
+ res = ARCHIVE_FAILED;
3054
+ break;
3055
+ }
3056
+ }
3057
+ /* be sure to always maintain this */
3058
+ tail[0] = c;
3059
+ if (tail[0] != '\0')
3060
+ tail++; /* Advance to the next segment. */
3061
+ }
3062
+ /* Catches loop exits via break */
3063
+ tail[0] = c;
3064
+ #if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
3065
+ /* If we operate with openat(), fstatat() and unlinkat() there was
3066
+ * no chdir(), so just close the fd */
3067
+ if (chdir_fd >= 0)
3068
+ close(chdir_fd);
3069
+ #elif HAVE_FCHDIR
3070
+ /* If we changed directory above, restore it here. */
3071
+ if (chdir_fd >= 0) {
3072
+ r = fchdir(chdir_fd);
3073
+ if (r != 0) {
3074
+ fsobj_error(a_eno, a_estr, errno,
3075
+ "chdir() failure", "");
3076
+ }
3077
+ close(chdir_fd);
3078
+ chdir_fd = -1;
3079
+ if (r != 0) {
3080
+ res = (ARCHIVE_FATAL);
3081
+ }
3082
+ }
3083
+ #endif
3084
+ /* TODO: reintroduce a safe cache here? */
3085
+ return res;
3086
+ #endif
3087
+ }
3088
+
3089
+ /*
3090
+ * Check a->name for symlinks, returning ARCHIVE_OK if its clean, otherwise
3091
+ * calls archive_set_error and returns ARCHIVE_{FATAL,FAILED}
3092
+ */
3093
+ static int
3094
+ check_symlinks(struct archive_write_disk *a)
3095
+ {
3096
+ struct archive_string error_string;
3097
+ int error_number;
3098
+ int rc;
3099
+ archive_string_init(&error_string);
3100
+ rc = check_symlinks_fsobj(a->name, &error_number, &error_string,
3101
+ a->flags, 0);
3102
+ if (rc != ARCHIVE_OK) {
3103
+ archive_set_error(&a->archive, error_number, "%s",
3104
+ error_string.s);
3105
+ }
3106
+ archive_string_free(&error_string);
3107
+ a->pst = NULL; /* to be safe */
3108
+ return rc;
3109
+ }
3110
+
3111
+
3112
+ #if defined(__CYGWIN__)
3113
+ /*
3114
+ * 1. Convert a path separator from '\' to '/' .
3115
+ * We shouldn't check multibyte character directly because some
3116
+ * character-set have been using the '\' character for a part of
3117
+ * its multibyte character code.
3118
+ * 2. Replace unusable characters in Windows with underscore('_').
3119
+ * See also : http://msdn.microsoft.com/en-us/library/aa365247.aspx
3120
+ */
3121
+ static void
3122
+ cleanup_pathname_win(char *path)
3123
+ {
3124
+ wchar_t wc;
3125
+ char *p;
3126
+ size_t alen, l;
3127
+ int mb, complete, utf8;
3128
+
3129
+ alen = 0;
3130
+ mb = 0;
3131
+ complete = 1;
3132
+ utf8 = (strcmp(nl_langinfo(CODESET), "UTF-8") == 0)? 1: 0;
3133
+ for (p = path; *p != '\0'; p++) {
3134
+ ++alen;
3135
+ if (*p == '\\') {
3136
+ /* If previous byte is smaller than 128,
3137
+ * this is not second byte of multibyte characters,
3138
+ * so we can replace '\' with '/'. */
3139
+ if (utf8 || !mb)
3140
+ *p = '/';
3141
+ else
3142
+ complete = 0;/* uncompleted. */
3143
+ } else if (*(unsigned char *)p > 127)
3144
+ mb = 1;
3145
+ else
3146
+ mb = 0;
3147
+ /* Rewrite the path name if its next character is unusable. */
3148
+ if (*p == ':' || *p == '*' || *p == '?' || *p == '"' ||
3149
+ *p == '<' || *p == '>' || *p == '|')
3150
+ *p = '_';
3151
+ }
3152
+ if (complete)
3153
+ return;
3154
+
3155
+ /*
3156
+ * Convert path separator in wide-character.
3157
+ */
3158
+ p = path;
3159
+ while (*p != '\0' && alen) {
3160
+ l = mbtowc(&wc, p, alen);
3161
+ if (l == (size_t)-1) {
3162
+ while (*p != '\0') {
3163
+ if (*p == '\\')
3164
+ *p = '/';
3165
+ ++p;
3166
+ }
3167
+ break;
3168
+ }
3169
+ if (l == 1 && wc == L'\\')
3170
+ *p = '/';
3171
+ p += l;
3172
+ alen -= l;
3173
+ }
3174
+ }
3175
+ #endif
3176
+
3177
+ /*
3178
+ * Canonicalize the pathname. In particular, this strips duplicate
3179
+ * '/' characters, '.' elements, and trailing '/'. It also raises an
3180
+ * error for an empty path, a trailing '..', (if _SECURE_NODOTDOT is
3181
+ * set) any '..' in the path or (if ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS
3182
+ * is set) if the path is absolute.
3183
+ */
3184
+ static int
3185
+ cleanup_pathname_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
3186
+ int flags)
3187
+ {
3188
+ char *dest, *src;
3189
+ char separator = '\0';
3190
+
3191
+ dest = src = path;
3192
+ if (*src == '\0') {
3193
+ fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC,
3194
+ "Invalid empty ", "pathname");
3195
+ return (ARCHIVE_FAILED);
3196
+ }
3197
+
3198
+ #if defined(__CYGWIN__)
3199
+ cleanup_pathname_win(path);
3200
+ #endif
3201
+ /* Skip leading '/'. */
3202
+ if (*src == '/') {
3203
+ if (flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) {
3204
+ fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC,
3205
+ "Path is ", "absolute");
3206
+ return (ARCHIVE_FAILED);
3207
+ }
3208
+
3209
+ separator = *src++;
3210
+ }
3211
+
3212
+ /* Scan the pathname one element at a time. */
3213
+ for (;;) {
3214
+ /* src points to first char after '/' */
3215
+ if (src[0] == '\0') {
3216
+ break;
3217
+ } else if (src[0] == '/') {
3218
+ /* Found '//', ignore second one. */
3219
+ src++;
3220
+ continue;
3221
+ } else if (src[0] == '.') {
3222
+ if (src[1] == '\0') {
3223
+ /* Ignore trailing '.' */
3224
+ break;
3225
+ } else if (src[1] == '/') {
3226
+ /* Skip './'. */
3227
+ src += 2;
3228
+ continue;
3229
+ } else if (src[1] == '.') {
3230
+ if (src[2] == '/' || src[2] == '\0') {
3231
+ /* Conditionally warn about '..' */
3232
+ if (flags
3233
+ & ARCHIVE_EXTRACT_SECURE_NODOTDOT) {
3234
+ fsobj_error(a_eno, a_estr,
3235
+ ARCHIVE_ERRNO_MISC,
3236
+ "Path contains ", "'..'");
3237
+ return (ARCHIVE_FAILED);
3238
+ }
3239
+ }
3240
+ /*
3241
+ * Note: Under no circumstances do we
3242
+ * remove '..' elements. In
3243
+ * particular, restoring
3244
+ * '/foo/../bar/' should create the
3245
+ * 'foo' dir as a side-effect.
3246
+ */
3247
+ }
3248
+ }
3249
+
3250
+ /* Copy current element, including leading '/'. */
3251
+ if (separator)
3252
+ *dest++ = '/';
3253
+ while (*src != '\0' && *src != '/') {
3254
+ *dest++ = *src++;
3255
+ }
3256
+
3257
+ if (*src == '\0')
3258
+ break;
3259
+
3260
+ /* Skip '/' separator. */
3261
+ separator = *src++;
3262
+ }
3263
+ /*
3264
+ * We've just copied zero or more path elements, not including the
3265
+ * final '/'.
3266
+ */
3267
+ if (dest == path) {
3268
+ /*
3269
+ * Nothing got copied. The path must have been something
3270
+ * like '.' or '/' or './' or '/././././/./'.
3271
+ */
3272
+ if (separator)
3273
+ *dest++ = '/';
3274
+ else
3275
+ *dest++ = '.';
3276
+ }
3277
+ /* Terminate the result. */
3278
+ *dest = '\0';
3279
+ return (ARCHIVE_OK);
3280
+ }
3281
+
3282
+ static int
3283
+ cleanup_pathname(struct archive_write_disk *a)
3284
+ {
3285
+ struct archive_string error_string;
3286
+ int error_number;
3287
+ int rc;
3288
+ archive_string_init(&error_string);
3289
+ rc = cleanup_pathname_fsobj(a->name, &error_number, &error_string,
3290
+ a->flags);
3291
+ if (rc != ARCHIVE_OK) {
3292
+ archive_set_error(&a->archive, error_number, "%s",
3293
+ error_string.s);
3294
+ }
3295
+ archive_string_free(&error_string);
3296
+ return rc;
3297
+ }
3298
+
3299
+ /*
3300
+ * Create the parent directory of the specified path, assuming path
3301
+ * is already in mutable storage.
3302
+ */
3303
+ static int
3304
+ create_parent_dir(struct archive_write_disk *a, char *path)
3305
+ {
3306
+ char *slash;
3307
+ int r;
3308
+
3309
+ /* Remove tail element to obtain parent name. */
3310
+ slash = strrchr(path, '/');
3311
+ if (slash == NULL)
3312
+ return (ARCHIVE_OK);
3313
+ *slash = '\0';
3314
+ r = create_dir(a, path);
3315
+ *slash = '/';
3316
+ return (r);
3317
+ }
3318
+
3319
+ /*
3320
+ * Create the specified dir, recursing to create parents as necessary.
3321
+ *
3322
+ * Returns ARCHIVE_OK if the path exists when we're done here.
3323
+ * Otherwise, returns ARCHIVE_FAILED.
3324
+ * Assumes path is in mutable storage; path is unchanged on exit.
3325
+ */
3326
+ static int
3327
+ create_dir(struct archive_write_disk *a, char *path)
3328
+ {
3329
+ struct stat st;
3330
+ struct fixup_entry *le;
3331
+ char *slash, *base;
3332
+ mode_t mode_final, mode;
3333
+ int r;
3334
+
3335
+ /* Check for special names and just skip them. */
3336
+ slash = strrchr(path, '/');
3337
+ if (slash == NULL)
3338
+ base = path;
3339
+ else
3340
+ base = slash + 1;
3341
+
3342
+ if (base[0] == '\0' ||
3343
+ (base[0] == '.' && base[1] == '\0') ||
3344
+ (base[0] == '.' && base[1] == '.' && base[2] == '\0')) {
3345
+ /* Don't bother trying to create null path, '.', or '..'. */
3346
+ if (slash != NULL) {
3347
+ *slash = '\0';
3348
+ r = create_dir(a, path);
3349
+ *slash = '/';
3350
+ return (r);
3351
+ }
3352
+ return (ARCHIVE_OK);
3353
+ }
3354
+
3355
+ /*
3356
+ * Yes, this should be stat() and not lstat(). Using lstat()
3357
+ * here loses the ability to extract through symlinks. Also note
3358
+ * that this should not use the a->st cache.
3359
+ */
3360
+ if (la_stat(path, &st) == 0) {
3361
+ if (S_ISDIR(st.st_mode))
3362
+ return (ARCHIVE_OK);
3363
+ if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
3364
+ archive_set_error(&a->archive, EEXIST,
3365
+ "Can't create directory '%s'", path);
3366
+ return (ARCHIVE_FAILED);
3367
+ }
3368
+ if (unlink(path) != 0) {
3369
+ archive_set_error(&a->archive, errno,
3370
+ "Can't create directory '%s': "
3371
+ "Conflicting file cannot be removed",
3372
+ path);
3373
+ return (ARCHIVE_FAILED);
3374
+ }
3375
+ } else if (errno != ENOENT && errno != ENOTDIR) {
3376
+ /* Stat failed? */
3377
+ archive_set_error(&a->archive, errno,
3378
+ "Can't test directory '%s'", path);
3379
+ return (ARCHIVE_FAILED);
3380
+ } else if (slash != NULL) {
3381
+ *slash = '\0';
3382
+ r = create_dir(a, path);
3383
+ *slash = '/';
3384
+ if (r != ARCHIVE_OK)
3385
+ return (r);
3386
+ }
3387
+
3388
+ /*
3389
+ * Mode we want for the final restored directory. Per POSIX,
3390
+ * implicitly-created dirs must be created obeying the umask.
3391
+ * There's no mention whether this is different for privileged
3392
+ * restores (which the rest of this code handles by pretending
3393
+ * umask=0). I've chosen here to always obey the user's umask for
3394
+ * implicit dirs, even if _EXTRACT_PERM was specified.
3395
+ */
3396
+ mode_final = DEFAULT_DIR_MODE & ~a->user_umask;
3397
+ /* Mode we want on disk during the restore process. */
3398
+ mode = mode_final;
3399
+ mode |= MINIMUM_DIR_MODE;
3400
+ mode &= MAXIMUM_DIR_MODE;
3401
+ if (mkdir(path, mode) == 0) {
3402
+ if (mode != mode_final) {
3403
+ le = new_fixup(a, path);
3404
+ if (le == NULL)
3405
+ return (ARCHIVE_FATAL);
3406
+ le->fixup |=TODO_MODE_BASE;
3407
+ le->mode = mode_final;
3408
+ }
3409
+ return (ARCHIVE_OK);
3410
+ }
3411
+
3412
+ /*
3413
+ * Without the following check, a/b/../b/c/d fails at the
3414
+ * second visit to 'b', so 'd' can't be created. Note that we
3415
+ * don't add it to the fixup list here, as it's already been
3416
+ * added.
3417
+ */
3418
+ if (la_stat(path, &st) == 0 && S_ISDIR(st.st_mode))
3419
+ return (ARCHIVE_OK);
3420
+
3421
+ archive_set_error(&a->archive, errno, "Failed to create dir '%s'",
3422
+ path);
3423
+ return (ARCHIVE_FAILED);
3424
+ }
3425
+
3426
+ /*
3427
+ * Note: Although we can skip setting the user id if the desired user
3428
+ * id matches the current user, we cannot skip setting the group, as
3429
+ * many systems set the gid based on the containing directory. So
3430
+ * we have to perform a chown syscall if we want to set the SGID
3431
+ * bit. (The alternative is to stat() and then possibly chown(); it's
3432
+ * more efficient to skip the stat() and just always chown().) Note
3433
+ * that a successful chown() here clears the TODO_SGID_CHECK bit, which
3434
+ * allows set_mode to skip the stat() check for the GID.
3435
+ */
3436
+ static int
3437
+ set_ownership(struct archive_write_disk *a)
3438
+ {
3439
+ #if !defined(__CYGWIN__) && !defined(__linux__)
3440
+ /*
3441
+ * On Linux, a process may have the CAP_CHOWN capability.
3442
+ * On Windows there is no 'root' user with uid 0.
3443
+ * Elsewhere we can skip calling chown if we are not root and the desired
3444
+ * user id does not match the current user.
3445
+ */
3446
+ if (a->user_uid != 0 && a->user_uid != a->uid) {
3447
+ archive_set_error(&a->archive, errno,
3448
+ "Can't set UID=%jd", (intmax_t)a->uid);
3449
+ return (ARCHIVE_WARN);
3450
+ }
3451
+ #endif
3452
+
3453
+ #ifdef HAVE_FCHOWN
3454
+ /* If we have an fd, we can avoid a race. */
3455
+ if (a->fd >= 0 && fchown(a->fd, a->uid, a->gid) == 0) {
3456
+ /* We've set owner and know uid/gid are correct. */
3457
+ a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK);
3458
+ return (ARCHIVE_OK);
3459
+ }
3460
+ #endif
3461
+
3462
+ /* We prefer lchown() but will use chown() if that's all we have. */
3463
+ /* Of course, if we have neither, this will always fail. */
3464
+ #ifdef HAVE_LCHOWN
3465
+ if (lchown(a->name, a->uid, a->gid) == 0) {
3466
+ /* We've set owner and know uid/gid are correct. */
3467
+ a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK);
3468
+ return (ARCHIVE_OK);
3469
+ }
3470
+ #elif HAVE_CHOWN
3471
+ if (!S_ISLNK(a->mode) && chown(a->name, a->uid, a->gid) == 0) {
3472
+ /* We've set owner and know uid/gid are correct. */
3473
+ a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK);
3474
+ return (ARCHIVE_OK);
3475
+ }
3476
+ #endif
3477
+
3478
+ archive_set_error(&a->archive, errno,
3479
+ "Can't set user=%jd/group=%jd for %s",
3480
+ (intmax_t)a->uid, (intmax_t)a->gid, a->name);
3481
+ return (ARCHIVE_WARN);
3482
+ }
3483
+
3484
+ /*
3485
+ * Note: Returns 0 on success, non-zero on failure.
3486
+ */
3487
+ static int
3488
+ set_time(int fd, int mode, const char *name,
3489
+ time_t atime, long atime_nsec,
3490
+ time_t mtime, long mtime_nsec)
3491
+ {
3492
+ /* Select the best implementation for this platform. */
3493
+ #if defined(HAVE_UTIMENSAT) && defined(HAVE_FUTIMENS)
3494
+ /*
3495
+ * utimensat() and futimens() are defined in
3496
+ * POSIX.1-2008. They support ns resolution and setting times
3497
+ * on fds and symlinks.
3498
+ */
3499
+ struct timespec ts[2];
3500
+ (void)mode; /* UNUSED */
3501
+ ts[0].tv_sec = atime;
3502
+ ts[0].tv_nsec = atime_nsec;
3503
+ ts[1].tv_sec = mtime;
3504
+ ts[1].tv_nsec = mtime_nsec;
3505
+ if (fd >= 0)
3506
+ return futimens(fd, ts);
3507
+ return utimensat(AT_FDCWD, name, ts, AT_SYMLINK_NOFOLLOW);
3508
+
3509
+ #elif HAVE_UTIMES
3510
+ /*
3511
+ * The utimes()-family functions support µs-resolution and
3512
+ * setting times fds and symlinks. utimes() is documented as
3513
+ * LEGACY by POSIX, futimes() and lutimes() are not described
3514
+ * in POSIX.
3515
+ */
3516
+ struct timeval times[2];
3517
+
3518
+ times[0].tv_sec = atime;
3519
+ times[0].tv_usec = atime_nsec / 1000;
3520
+ times[1].tv_sec = mtime;
3521
+ times[1].tv_usec = mtime_nsec / 1000;
3522
+
3523
+ #ifdef HAVE_FUTIMES
3524
+ if (fd >= 0)
3525
+ return (futimes(fd, times));
3526
+ #else
3527
+ (void)fd; /* UNUSED */
3528
+ #endif
3529
+ #ifdef HAVE_LUTIMES
3530
+ (void)mode; /* UNUSED */
3531
+ return (lutimes(name, times));
3532
+ #else
3533
+ if (S_ISLNK(mode))
3534
+ return (0);
3535
+ return (utimes(name, times));
3536
+ #endif
3537
+
3538
+ #elif defined(HAVE_UTIME)
3539
+ /*
3540
+ * utime() is POSIX-standard but only supports 1s resolution and
3541
+ * does not support fds or symlinks.
3542
+ */
3543
+ struct utimbuf times;
3544
+ (void)fd; /* UNUSED */
3545
+ (void)name; /* UNUSED */
3546
+ (void)atime_nsec; /* UNUSED */
3547
+ (void)mtime_nsec; /* UNUSED */
3548
+ times.actime = atime;
3549
+ times.modtime = mtime;
3550
+ if (S_ISLNK(mode))
3551
+ return (ARCHIVE_OK);
3552
+ return (utime(name, &times));
3553
+
3554
+ #else
3555
+ /*
3556
+ * We don't know how to set the time on this platform.
3557
+ */
3558
+ (void)fd; /* UNUSED */
3559
+ (void)mode; /* UNUSED */
3560
+ (void)name; /* UNUSED */
3561
+ (void)atime_nsec; /* UNUSED */
3562
+ (void)mtime_nsec; /* UNUSED */
3563
+ return (ARCHIVE_WARN);
3564
+ #endif
3565
+ }
3566
+
3567
+ #ifdef F_SETTIMES
3568
+ static int
3569
+ set_time_tru64(int fd, int mode, const char *name,
3570
+ time_t atime, long atime_nsec,
3571
+ time_t mtime, long mtime_nsec,
3572
+ time_t ctime, long ctime_nsec)
3573
+ {
3574
+ struct attr_timbuf tstamp;
3575
+ tstamp.atime.tv_sec = atime;
3576
+ tstamp.mtime.tv_sec = mtime;
3577
+ tstamp.ctime.tv_sec = ctime;
3578
+ #if defined (__hpux) && defined (__ia64)
3579
+ tstamp.atime.tv_nsec = atime_nsec;
3580
+ tstamp.mtime.tv_nsec = mtime_nsec;
3581
+ tstamp.ctime.tv_nsec = ctime_nsec;
3582
+ #else
3583
+ tstamp.atime.tv_usec = atime_nsec / 1000;
3584
+ tstamp.mtime.tv_usec = mtime_nsec / 1000;
3585
+ tstamp.ctime.tv_usec = ctime_nsec / 1000;
3586
+ #endif
3587
+ return (fcntl(fd,F_SETTIMES,&tstamp));
3588
+ }
3589
+ #endif /* F_SETTIMES */
3590
+
3591
+ static int
3592
+ set_times(struct archive_write_disk *a,
3593
+ int fd, int mode, const char *name,
3594
+ time_t atime, long atime_nanos,
3595
+ time_t birthtime, long birthtime_nanos,
3596
+ time_t mtime, long mtime_nanos,
3597
+ time_t cctime, long ctime_nanos)
3598
+ {
3599
+ /* Note: set_time doesn't use libarchive return conventions!
3600
+ * It uses syscall conventions. So 0 here instead of ARCHIVE_OK. */
3601
+ int r1 = 0, r2 = 0;
3602
+
3603
+ #ifdef F_SETTIMES
3604
+ /*
3605
+ * on Tru64 try own fcntl first which can restore even the
3606
+ * ctime, fall back to default code path below if it fails
3607
+ * or if we are not running as root
3608
+ */
3609
+ if (a->user_uid == 0 &&
3610
+ set_time_tru64(fd, mode, name,
3611
+ atime, atime_nanos, mtime,
3612
+ mtime_nanos, cctime, ctime_nanos) == 0) {
3613
+ return (ARCHIVE_OK);
3614
+ }
3615
+ #else /* Tru64 */
3616
+ (void)cctime; /* UNUSED */
3617
+ (void)ctime_nanos; /* UNUSED */
3618
+ #endif /* Tru64 */
3619
+
3620
+ #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
3621
+ /*
3622
+ * If you have struct stat.st_birthtime, we assume BSD
3623
+ * birthtime semantics, in which {f,l,}utimes() updates
3624
+ * birthtime to earliest mtime. So we set the time twice,
3625
+ * first using the birthtime, then using the mtime. If
3626
+ * birthtime == mtime, this isn't necessary, so we skip it.
3627
+ * If birthtime > mtime, then this won't work, so we skip it.
3628
+ */
3629
+ if (birthtime < mtime
3630
+ || (birthtime == mtime && birthtime_nanos < mtime_nanos))
3631
+ r1 = set_time(fd, mode, name,
3632
+ atime, atime_nanos,
3633
+ birthtime, birthtime_nanos);
3634
+ #else
3635
+ (void)birthtime; /* UNUSED */
3636
+ (void)birthtime_nanos; /* UNUSED */
3637
+ #endif
3638
+ r2 = set_time(fd, mode, name,
3639
+ atime, atime_nanos,
3640
+ mtime, mtime_nanos);
3641
+ if (r1 != 0 || r2 != 0) {
3642
+ archive_set_error(&a->archive, errno,
3643
+ "Can't restore time");
3644
+ return (ARCHIVE_WARN);
3645
+ }
3646
+ return (ARCHIVE_OK);
3647
+ }
3648
+
3649
+ static int
3650
+ set_times_from_entry(struct archive_write_disk *a)
3651
+ {
3652
+ time_t atime, birthtime, mtime, cctime;
3653
+ long atime_nsec, birthtime_nsec, mtime_nsec, ctime_nsec;
3654
+
3655
+ /* Suitable defaults. */
3656
+ atime = birthtime = mtime = cctime = a->start_time;
3657
+ atime_nsec = birthtime_nsec = mtime_nsec = ctime_nsec = 0;
3658
+
3659
+ /* If no time was provided, we're done. */
3660
+ if (!archive_entry_atime_is_set(a->entry)
3661
+ #if HAVE_STRUCT_STAT_ST_BIRTHTIME
3662
+ && !archive_entry_birthtime_is_set(a->entry)
3663
+ #endif
3664
+ && !archive_entry_mtime_is_set(a->entry))
3665
+ return (ARCHIVE_OK);
3666
+
3667
+ if (archive_entry_atime_is_set(a->entry)) {
3668
+ atime = archive_entry_atime(a->entry);
3669
+ atime_nsec = archive_entry_atime_nsec(a->entry);
3670
+ }
3671
+ if (archive_entry_birthtime_is_set(a->entry)) {
3672
+ birthtime = archive_entry_birthtime(a->entry);
3673
+ birthtime_nsec = archive_entry_birthtime_nsec(a->entry);
3674
+ }
3675
+ if (archive_entry_mtime_is_set(a->entry)) {
3676
+ mtime = archive_entry_mtime(a->entry);
3677
+ mtime_nsec = archive_entry_mtime_nsec(a->entry);
3678
+ }
3679
+ if (archive_entry_ctime_is_set(a->entry)) {
3680
+ cctime = archive_entry_ctime(a->entry);
3681
+ ctime_nsec = archive_entry_ctime_nsec(a->entry);
3682
+ }
3683
+
3684
+ return set_times(a, a->fd, a->mode, a->name,
3685
+ atime, atime_nsec,
3686
+ birthtime, birthtime_nsec,
3687
+ mtime, mtime_nsec,
3688
+ cctime, ctime_nsec);
3689
+ }
3690
+
3691
+ static int
3692
+ set_mode(struct archive_write_disk *a, int mode)
3693
+ {
3694
+ int r = ARCHIVE_OK;
3695
+ int r2;
3696
+ mode &= 07777; /* Strip off file type bits. */
3697
+
3698
+ if (a->todo & TODO_SGID_CHECK) {
3699
+ /*
3700
+ * If we don't know the GID is right, we must stat()
3701
+ * to verify it. We can't just check the GID of this
3702
+ * process, since systems sometimes set GID from
3703
+ * the enclosing dir or based on ACLs.
3704
+ */
3705
+ if ((r = lazy_stat(a)) != ARCHIVE_OK)
3706
+ return (r);
3707
+ if (a->pst->st_gid != a->gid) {
3708
+ mode &= ~ S_ISGID;
3709
+ if (a->flags & ARCHIVE_EXTRACT_OWNER) {
3710
+ /*
3711
+ * This is only an error if you
3712
+ * requested owner restore. If you
3713
+ * didn't, we'll try to restore
3714
+ * sgid/suid, but won't consider it a
3715
+ * problem if we can't.
3716
+ */
3717
+ archive_set_error(&a->archive, -1,
3718
+ "Can't restore SGID bit");
3719
+ r = ARCHIVE_WARN;
3720
+ }
3721
+ }
3722
+ /* While we're here, double-check the UID. */
3723
+ if (a->pst->st_uid != a->uid
3724
+ && (a->todo & TODO_SUID)) {
3725
+ mode &= ~ S_ISUID;
3726
+ if (a->flags & ARCHIVE_EXTRACT_OWNER) {
3727
+ archive_set_error(&a->archive, -1,
3728
+ "Can't restore SUID bit");
3729
+ r = ARCHIVE_WARN;
3730
+ }
3731
+ }
3732
+ a->todo &= ~TODO_SGID_CHECK;
3733
+ a->todo &= ~TODO_SUID_CHECK;
3734
+ } else if (a->todo & TODO_SUID_CHECK) {
3735
+ /*
3736
+ * If we don't know the UID is right, we can just check
3737
+ * the user, since all systems set the file UID from
3738
+ * the process UID.
3739
+ */
3740
+ if (a->user_uid != a->uid) {
3741
+ mode &= ~ S_ISUID;
3742
+ if (a->flags & ARCHIVE_EXTRACT_OWNER) {
3743
+ archive_set_error(&a->archive, -1,
3744
+ "Can't make file SUID");
3745
+ r = ARCHIVE_WARN;
3746
+ }
3747
+ }
3748
+ a->todo &= ~TODO_SUID_CHECK;
3749
+ }
3750
+
3751
+ if (S_ISLNK(a->mode)) {
3752
+ #ifdef HAVE_LCHMOD
3753
+ /*
3754
+ * If this is a symlink, use lchmod(). If the
3755
+ * platform doesn't support lchmod(), just skip it. A
3756
+ * platform that doesn't provide a way to set
3757
+ * permissions on symlinks probably ignores
3758
+ * permissions on symlinks, so a failure here has no
3759
+ * impact.
3760
+ */
3761
+ if (lchmod(a->name, mode) != 0) {
3762
+ switch (errno) {
3763
+ case ENOTSUP:
3764
+ case ENOSYS:
3765
+ #if ENOTSUP != EOPNOTSUPP
3766
+ case EOPNOTSUPP:
3767
+ #endif
3768
+ /*
3769
+ * if lchmod is defined but the platform
3770
+ * doesn't support it, silently ignore
3771
+ * error
3772
+ */
3773
+ break;
3774
+ default:
3775
+ archive_set_error(&a->archive, errno,
3776
+ "Can't set permissions to 0%o", (int)mode);
3777
+ r = ARCHIVE_WARN;
3778
+ }
3779
+ }
3780
+ #endif
3781
+ } else if (!S_ISDIR(a->mode)) {
3782
+ /*
3783
+ * If it's not a symlink and not a dir, then use
3784
+ * fchmod() or chmod(), depending on whether we have
3785
+ * an fd. Dirs get their perms set during the
3786
+ * post-extract fixup, which is handled elsewhere.
3787
+ */
3788
+ #ifdef HAVE_FCHMOD
3789
+ if (a->fd >= 0)
3790
+ r2 = fchmod(a->fd, mode);
3791
+ else
3792
+ #endif
3793
+ /* If this platform lacks fchmod(), then
3794
+ * we'll just use chmod(). */
3795
+ r2 = chmod(a->name, mode);
3796
+
3797
+ if (r2 != 0) {
3798
+ archive_set_error(&a->archive, errno,
3799
+ "Can't set permissions to 0%o", (int)mode);
3800
+ r = ARCHIVE_WARN;
3801
+ }
3802
+ }
3803
+ return (r);
3804
+ }
3805
+
3806
+ static int
3807
+ set_fflags(struct archive_write_disk *a)
3808
+ {
3809
+ struct fixup_entry *le;
3810
+ unsigned long set, clear;
3811
+ int r;
3812
+ mode_t mode = archive_entry_mode(a->entry);
3813
+ /*
3814
+ * Make 'critical_flags' hold all file flags that can't be
3815
+ * immediately restored. For example, on BSD systems,
3816
+ * SF_IMMUTABLE prevents hardlinks from being created, so
3817
+ * should not be set until after any hardlinks are created. To
3818
+ * preserve some semblance of portability, this uses #ifdef
3819
+ * extensively. Ugly, but it works.
3820
+ *
3821
+ * Yes, Virginia, this does create a security race. It's mitigated
3822
+ * somewhat by the practice of creating dirs 0700 until the extract
3823
+ * is done, but it would be nice if we could do more than that.
3824
+ * People restoring critical file systems should be wary of
3825
+ * other programs that might try to muck with files as they're
3826
+ * being restored.
3827
+ */
3828
+ const int critical_flags = 0
3829
+ #ifdef SF_IMMUTABLE
3830
+ | SF_IMMUTABLE
3831
+ #endif
3832
+ #ifdef UF_IMMUTABLE
3833
+ | UF_IMMUTABLE
3834
+ #endif
3835
+ #ifdef SF_APPEND
3836
+ | SF_APPEND
3837
+ #endif
3838
+ #ifdef UF_APPEND
3839
+ | UF_APPEND
3840
+ #endif
3841
+ #if defined(FS_APPEND_FL)
3842
+ | FS_APPEND_FL
3843
+ #elif defined(EXT2_APPEND_FL)
3844
+ | EXT2_APPEND_FL
3845
+ #endif
3846
+ #if defined(FS_IMMUTABLE_FL)
3847
+ | FS_IMMUTABLE_FL
3848
+ #elif defined(EXT2_IMMUTABLE_FL)
3849
+ | EXT2_IMMUTABLE_FL
3850
+ #endif
3851
+ #ifdef FS_JOURNAL_DATA_FL
3852
+ | FS_JOURNAL_DATA_FL
3853
+ #endif
3854
+ ;
3855
+
3856
+ if (a->todo & TODO_FFLAGS) {
3857
+ archive_entry_fflags(a->entry, &set, &clear);
3858
+
3859
+ /*
3860
+ * The first test encourages the compiler to eliminate
3861
+ * all of this if it's not necessary.
3862
+ */
3863
+ if ((critical_flags != 0) && (set & critical_flags)) {
3864
+ le = current_fixup(a, a->name);
3865
+ if (le == NULL)
3866
+ return (ARCHIVE_FATAL);
3867
+ le->filetype = archive_entry_filetype(a->entry);
3868
+ le->fixup |= TODO_FFLAGS;
3869
+ le->fflags_set = set;
3870
+ /* Store the mode if it's not already there. */
3871
+ if ((le->fixup & TODO_MODE) == 0)
3872
+ le->mode = mode;
3873
+ } else {
3874
+ r = set_fflags_platform(a, a->fd,
3875
+ a->name, mode, set, clear);
3876
+ if (r != ARCHIVE_OK)
3877
+ return (r);
3878
+ }
3879
+ }
3880
+ return (ARCHIVE_OK);
3881
+ }
3882
+
3883
+ static int
3884
+ clear_nochange_fflags(struct archive_write_disk *a)
3885
+ {
3886
+ mode_t mode = archive_entry_mode(a->entry);
3887
+ const int nochange_flags = 0
3888
+ #ifdef SF_IMMUTABLE
3889
+ | SF_IMMUTABLE
3890
+ #endif
3891
+ #ifdef UF_IMMUTABLE
3892
+ | UF_IMMUTABLE
3893
+ #endif
3894
+ #ifdef SF_APPEND
3895
+ | SF_APPEND
3896
+ #endif
3897
+ #ifdef UF_APPEND
3898
+ | UF_APPEND
3899
+ #endif
3900
+ #ifdef EXT2_APPEND_FL
3901
+ | EXT2_APPEND_FL
3902
+ #endif
3903
+ #ifdef EXT2_IMMUTABLE_FL
3904
+ | EXT2_IMMUTABLE_FL
3905
+ #endif
3906
+ ;
3907
+
3908
+ return (set_fflags_platform(a, a->fd, a->name, mode, 0,
3909
+ nochange_flags));
3910
+ }
3911
+
3912
+
3913
+ #if ( defined(HAVE_LCHFLAGS) || defined(HAVE_CHFLAGS) || defined(HAVE_FCHFLAGS) ) && defined(HAVE_STRUCT_STAT_ST_FLAGS)
3914
+ /*
3915
+ * BSD reads flags using stat() and sets them with one of {f,l,}chflags()
3916
+ */
3917
+ static int
3918
+ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
3919
+ mode_t mode, unsigned long set, unsigned long clear)
3920
+ {
3921
+ int r;
3922
+ const int sf_mask = 0
3923
+ #ifdef SF_APPEND
3924
+ | SF_APPEND
3925
+ #endif
3926
+ #ifdef SF_ARCHIVED
3927
+ | SF_ARCHIVED
3928
+ #endif
3929
+ #ifdef SF_IMMUTABLE
3930
+ | SF_IMMUTABLE
3931
+ #endif
3932
+ #ifdef SF_NOUNLINK
3933
+ | SF_NOUNLINK
3934
+ #endif
3935
+ ;
3936
+ (void)mode; /* UNUSED */
3937
+
3938
+ if (set == 0 && clear == 0)
3939
+ return (ARCHIVE_OK);
3940
+
3941
+ /*
3942
+ * XXX Is the stat here really necessary? Or can I just use
3943
+ * the 'set' flags directly? In particular, I'm not sure
3944
+ * about the correct approach if we're overwriting an existing
3945
+ * file that already has flags on it. XXX
3946
+ */
3947
+ if ((r = lazy_stat(a)) != ARCHIVE_OK)
3948
+ return (r);
3949
+
3950
+ a->st.st_flags &= ~clear;
3951
+ a->st.st_flags |= set;
3952
+
3953
+ /* Only super-user may change SF_* flags */
3954
+
3955
+ if (a->user_uid != 0)
3956
+ a->st.st_flags &= ~sf_mask;
3957
+
3958
+ #ifdef HAVE_FCHFLAGS
3959
+ /* If platform has fchflags() and we were given an fd, use it. */
3960
+ if (fd >= 0 && fchflags(fd, a->st.st_flags) == 0)
3961
+ return (ARCHIVE_OK);
3962
+ #endif
3963
+ /*
3964
+ * If we can't use the fd to set the flags, we'll use the
3965
+ * pathname to set flags. We prefer lchflags() but will use
3966
+ * chflags() if we must.
3967
+ */
3968
+ #ifdef HAVE_LCHFLAGS
3969
+ if (lchflags(name, a->st.st_flags) == 0)
3970
+ return (ARCHIVE_OK);
3971
+ #elif defined(HAVE_CHFLAGS)
3972
+ if (S_ISLNK(a->st.st_mode)) {
3973
+ archive_set_error(&a->archive, errno,
3974
+ "Can't set file flags on symlink.");
3975
+ return (ARCHIVE_WARN);
3976
+ }
3977
+ if (chflags(name, a->st.st_flags) == 0)
3978
+ return (ARCHIVE_OK);
3979
+ #endif
3980
+ archive_set_error(&a->archive, errno,
3981
+ "Failed to set file flags");
3982
+ return (ARCHIVE_WARN);
3983
+ }
3984
+
3985
+ #elif (defined(FS_IOC_GETFLAGS) && defined(FS_IOC_SETFLAGS) && \
3986
+ defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
3987
+ (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) && \
3988
+ defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
3989
+ /*
3990
+ * Linux uses ioctl() to read and write file flags.
3991
+ */
3992
+ static int
3993
+ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
3994
+ mode_t mode, unsigned long set, unsigned long clear)
3995
+ {
3996
+ int ret;
3997
+ int myfd = fd;
3998
+ int newflags, oldflags;
3999
+ /*
4000
+ * Linux has no define for the flags that are only settable by
4001
+ * the root user. This code may seem a little complex, but
4002
+ * there seem to be some Linux systems that lack these
4003
+ * defines. (?) The code below degrades reasonably gracefully
4004
+ * if sf_mask is incomplete.
4005
+ */
4006
+ const int sf_mask = 0
4007
+ #if defined(FS_IMMUTABLE_FL)
4008
+ | FS_IMMUTABLE_FL
4009
+ #elif defined(EXT2_IMMUTABLE_FL)
4010
+ | EXT2_IMMUTABLE_FL
4011
+ #endif
4012
+ #if defined(FS_APPEND_FL)
4013
+ | FS_APPEND_FL
4014
+ #elif defined(EXT2_APPEND_FL)
4015
+ | EXT2_APPEND_FL
4016
+ #endif
4017
+ #if defined(FS_JOURNAL_DATA_FL)
4018
+ | FS_JOURNAL_DATA_FL
4019
+ #endif
4020
+ ;
4021
+
4022
+ if (set == 0 && clear == 0)
4023
+ return (ARCHIVE_OK);
4024
+ /* Only regular files and dirs can have flags. */
4025
+ if (!S_ISREG(mode) && !S_ISDIR(mode))
4026
+ return (ARCHIVE_OK);
4027
+
4028
+ /* If we weren't given an fd, open it ourselves. */
4029
+ if (myfd < 0) {
4030
+ myfd = open(name, O_RDONLY | O_NONBLOCK | O_BINARY |
4031
+ O_CLOEXEC | O_NOFOLLOW);
4032
+ __archive_ensure_cloexec_flag(myfd);
4033
+ }
4034
+ if (myfd < 0)
4035
+ return (ARCHIVE_OK);
4036
+
4037
+ /*
4038
+ * XXX As above, this would be way simpler if we didn't have
4039
+ * to read the current flags from disk. XXX
4040
+ */
4041
+ ret = ARCHIVE_OK;
4042
+
4043
+ /* Read the current file flags. */
4044
+ if (ioctl(myfd,
4045
+ #ifdef FS_IOC_GETFLAGS
4046
+ FS_IOC_GETFLAGS,
4047
+ #else
4048
+ EXT2_IOC_GETFLAGS,
4049
+ #endif
4050
+ &oldflags) < 0)
4051
+ goto fail;
4052
+
4053
+ /* Try setting the flags as given. */
4054
+ newflags = (oldflags & ~clear) | set;
4055
+ if (ioctl(myfd,
4056
+ #ifdef FS_IOC_SETFLAGS
4057
+ FS_IOC_SETFLAGS,
4058
+ #else
4059
+ EXT2_IOC_SETFLAGS,
4060
+ #endif
4061
+ &newflags) >= 0)
4062
+ goto cleanup;
4063
+ if (errno != EPERM)
4064
+ goto fail;
4065
+
4066
+ /* If we couldn't set all the flags, try again with a subset. */
4067
+ newflags &= ~sf_mask;
4068
+ oldflags &= sf_mask;
4069
+ newflags |= oldflags;
4070
+ if (ioctl(myfd,
4071
+ #ifdef FS_IOC_SETFLAGS
4072
+ FS_IOC_SETFLAGS,
4073
+ #else
4074
+ EXT2_IOC_SETFLAGS,
4075
+ #endif
4076
+ &newflags) >= 0)
4077
+ goto cleanup;
4078
+
4079
+ /* We couldn't set the flags, so report the failure. */
4080
+ fail:
4081
+ archive_set_error(&a->archive, errno,
4082
+ "Failed to set file flags");
4083
+ ret = ARCHIVE_WARN;
4084
+ cleanup:
4085
+ if (fd < 0)
4086
+ close(myfd);
4087
+ return (ret);
4088
+ }
4089
+
4090
+ #else
4091
+
4092
+ /*
4093
+ * Of course, some systems have neither BSD chflags() nor Linux' flags
4094
+ * support through ioctl().
4095
+ */
4096
+ static int
4097
+ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
4098
+ mode_t mode, unsigned long set, unsigned long clear)
4099
+ {
4100
+ (void)a; /* UNUSED */
4101
+ (void)fd; /* UNUSED */
4102
+ (void)name; /* UNUSED */
4103
+ (void)mode; /* UNUSED */
4104
+ (void)set; /* UNUSED */
4105
+ (void)clear; /* UNUSED */
4106
+ return (ARCHIVE_OK);
4107
+ }
4108
+
4109
+ #endif /* __linux */
4110
+
4111
+ #ifndef HAVE_COPYFILE_H
4112
+ /* Default is to simply drop Mac extended metadata. */
4113
+ static int
4114
+ set_mac_metadata(struct archive_write_disk *a, const char *pathname,
4115
+ const void *metadata, size_t metadata_size)
4116
+ {
4117
+ (void)a; /* UNUSED */
4118
+ (void)pathname; /* UNUSED */
4119
+ (void)metadata; /* UNUSED */
4120
+ (void)metadata_size; /* UNUSED */
4121
+ return (ARCHIVE_OK);
4122
+ }
4123
+
4124
+ static int
4125
+ fixup_appledouble(struct archive_write_disk *a, const char *pathname)
4126
+ {
4127
+ (void)a; /* UNUSED */
4128
+ (void)pathname; /* UNUSED */
4129
+ return (ARCHIVE_OK);
4130
+ }
4131
+ #else
4132
+
4133
+ /*
4134
+ * On Mac OS, we use copyfile() to unpack the metadata and
4135
+ * apply it to the target file.
4136
+ */
4137
+
4138
+ #if defined(HAVE_SYS_XATTR_H)
4139
+ static int
4140
+ copy_xattrs(struct archive_write_disk *a, int tmpfd, int dffd)
4141
+ {
4142
+ ssize_t xattr_size;
4143
+ char *xattr_names = NULL, *xattr_val = NULL;
4144
+ int ret = ARCHIVE_OK, xattr_i;
4145
+
4146
+ xattr_size = flistxattr(tmpfd, NULL, 0, 0);
4147
+ if (xattr_size == -1) {
4148
+ archive_set_error(&a->archive, errno,
4149
+ "Failed to read metadata(xattr)");
4150
+ ret = ARCHIVE_WARN;
4151
+ goto exit_xattr;
4152
+ }
4153
+ xattr_names = malloc(xattr_size);
4154
+ if (xattr_names == NULL) {
4155
+ archive_set_error(&a->archive, ENOMEM,
4156
+ "Can't allocate memory for metadata(xattr)");
4157
+ ret = ARCHIVE_FATAL;
4158
+ goto exit_xattr;
4159
+ }
4160
+ xattr_size = flistxattr(tmpfd, xattr_names, xattr_size, 0);
4161
+ if (xattr_size == -1) {
4162
+ archive_set_error(&a->archive, errno,
4163
+ "Failed to read metadata(xattr)");
4164
+ ret = ARCHIVE_WARN;
4165
+ goto exit_xattr;
4166
+ }
4167
+ for (xattr_i = 0; xattr_i < xattr_size;
4168
+ xattr_i += strlen(xattr_names + xattr_i) + 1) {
4169
+ char *xattr_val_saved;
4170
+ ssize_t s;
4171
+ int f;
4172
+
4173
+ s = fgetxattr(tmpfd, xattr_names + xattr_i, NULL, 0, 0, 0);
4174
+ if (s == -1) {
4175
+ archive_set_error(&a->archive, errno,
4176
+ "Failed to get metadata(xattr)");
4177
+ ret = ARCHIVE_WARN;
4178
+ goto exit_xattr;
4179
+ }
4180
+ xattr_val_saved = xattr_val;
4181
+ xattr_val = realloc(xattr_val, s);
4182
+ if (xattr_val == NULL) {
4183
+ archive_set_error(&a->archive, ENOMEM,
4184
+ "Failed to get metadata(xattr)");
4185
+ ret = ARCHIVE_WARN;
4186
+ free(xattr_val_saved);
4187
+ goto exit_xattr;
4188
+ }
4189
+ s = fgetxattr(tmpfd, xattr_names + xattr_i, xattr_val, s, 0, 0);
4190
+ if (s == -1) {
4191
+ archive_set_error(&a->archive, errno,
4192
+ "Failed to get metadata(xattr)");
4193
+ ret = ARCHIVE_WARN;
4194
+ goto exit_xattr;
4195
+ }
4196
+ f = fsetxattr(dffd, xattr_names + xattr_i, xattr_val, s, 0, 0);
4197
+ if (f == -1) {
4198
+ archive_set_error(&a->archive, errno,
4199
+ "Failed to get metadata(xattr)");
4200
+ ret = ARCHIVE_WARN;
4201
+ goto exit_xattr;
4202
+ }
4203
+ }
4204
+ exit_xattr:
4205
+ free(xattr_names);
4206
+ free(xattr_val);
4207
+ return (ret);
4208
+ }
4209
+ #endif
4210
+
4211
+ static int
4212
+ copy_acls(struct archive_write_disk *a, int tmpfd, int dffd)
4213
+ {
4214
+ #ifndef HAVE_SYS_ACL_H
4215
+ return 0;
4216
+ #else
4217
+ acl_t acl, dfacl = NULL;
4218
+ int acl_r, ret = ARCHIVE_OK;
4219
+
4220
+ acl = acl_get_fd(tmpfd);
4221
+ if (acl == NULL) {
4222
+ if (errno == ENOENT)
4223
+ /* There are not any ACLs. */
4224
+ return (ret);
4225
+ archive_set_error(&a->archive, errno,
4226
+ "Failed to get metadata(acl)");
4227
+ ret = ARCHIVE_WARN;
4228
+ goto exit_acl;
4229
+ }
4230
+ dfacl = acl_dup(acl);
4231
+ acl_r = acl_set_fd(dffd, dfacl);
4232
+ if (acl_r == -1) {
4233
+ archive_set_error(&a->archive, errno,
4234
+ "Failed to get metadata(acl)");
4235
+ ret = ARCHIVE_WARN;
4236
+ goto exit_acl;
4237
+ }
4238
+ exit_acl:
4239
+ if (acl)
4240
+ acl_free(acl);
4241
+ if (dfacl)
4242
+ acl_free(dfacl);
4243
+ return (ret);
4244
+ #endif
4245
+ }
4246
+
4247
+ static int
4248
+ create_tempdatafork(struct archive_write_disk *a, const char *pathname)
4249
+ {
4250
+ struct archive_string tmpdatafork;
4251
+ int tmpfd;
4252
+
4253
+ archive_string_init(&tmpdatafork);
4254
+ archive_strcpy(&tmpdatafork, "tar.md.XXXXXX");
4255
+ tmpfd = mkstemp(tmpdatafork.s);
4256
+ if (tmpfd < 0) {
4257
+ archive_set_error(&a->archive, errno,
4258
+ "Failed to mkstemp");
4259
+ archive_string_free(&tmpdatafork);
4260
+ return (-1);
4261
+ }
4262
+ if (copyfile(pathname, tmpdatafork.s, 0,
4263
+ COPYFILE_UNPACK | COPYFILE_NOFOLLOW
4264
+ | COPYFILE_ACL | COPYFILE_XATTR) < 0) {
4265
+ archive_set_error(&a->archive, errno,
4266
+ "Failed to restore metadata");
4267
+ close(tmpfd);
4268
+ tmpfd = -1;
4269
+ }
4270
+ unlink(tmpdatafork.s);
4271
+ archive_string_free(&tmpdatafork);
4272
+ return (tmpfd);
4273
+ }
4274
+
4275
+ static int
4276
+ copy_metadata(struct archive_write_disk *a, const char *metadata,
4277
+ const char *datafork, int datafork_compressed)
4278
+ {
4279
+ int ret = ARCHIVE_OK;
4280
+
4281
+ if (datafork_compressed) {
4282
+ int dffd, tmpfd;
4283
+
4284
+ tmpfd = create_tempdatafork(a, metadata);
4285
+ if (tmpfd == -1)
4286
+ return (ARCHIVE_WARN);
4287
+
4288
+ /*
4289
+ * Do not open the data fork compressed by HFS+ compression
4290
+ * with at least a writing mode(O_RDWR or O_WRONLY). it
4291
+ * makes the data fork uncompressed.
4292
+ */
4293
+ dffd = open(datafork, 0);
4294
+ if (dffd == -1) {
4295
+ archive_set_error(&a->archive, errno,
4296
+ "Failed to open the data fork for metadata");
4297
+ close(tmpfd);
4298
+ return (ARCHIVE_WARN);
4299
+ }
4300
+
4301
+ #if defined(HAVE_SYS_XATTR_H)
4302
+ ret = copy_xattrs(a, tmpfd, dffd);
4303
+ if (ret == ARCHIVE_OK)
4304
+ #endif
4305
+ ret = copy_acls(a, tmpfd, dffd);
4306
+ close(tmpfd);
4307
+ close(dffd);
4308
+ } else {
4309
+ if (copyfile(metadata, datafork, 0,
4310
+ COPYFILE_UNPACK | COPYFILE_NOFOLLOW
4311
+ | COPYFILE_ACL | COPYFILE_XATTR) < 0) {
4312
+ archive_set_error(&a->archive, errno,
4313
+ "Failed to restore metadata");
4314
+ ret = ARCHIVE_WARN;
4315
+ }
4316
+ }
4317
+ return (ret);
4318
+ }
4319
+
4320
+ static int
4321
+ set_mac_metadata(struct archive_write_disk *a, const char *pathname,
4322
+ const void *metadata, size_t metadata_size)
4323
+ {
4324
+ struct archive_string tmp;
4325
+ ssize_t written;
4326
+ int fd;
4327
+ int ret = ARCHIVE_OK;
4328
+
4329
+ /* This would be simpler if copyfile() could just accept the
4330
+ * metadata as a block of memory; then we could sidestep this
4331
+ * silly dance of writing the data to disk just so that
4332
+ * copyfile() can read it back in again. */
4333
+ archive_string_init(&tmp);
4334
+ archive_strcpy(&tmp, pathname);
4335
+ archive_strcat(&tmp, ".XXXXXX");
4336
+ fd = mkstemp(tmp.s);
4337
+
4338
+ if (fd < 0) {
4339
+ archive_set_error(&a->archive, errno,
4340
+ "Failed to restore metadata");
4341
+ archive_string_free(&tmp);
4342
+ return (ARCHIVE_WARN);
4343
+ }
4344
+ written = write(fd, metadata, metadata_size);
4345
+ close(fd);
4346
+ if ((size_t)written != metadata_size) {
4347
+ archive_set_error(&a->archive, errno,
4348
+ "Failed to restore metadata");
4349
+ ret = ARCHIVE_WARN;
4350
+ } else {
4351
+ int compressed;
4352
+
4353
+ #if defined(UF_COMPRESSED)
4354
+ if ((a->todo & TODO_HFS_COMPRESSION) != 0 &&
4355
+ (ret = lazy_stat(a)) == ARCHIVE_OK)
4356
+ compressed = a->st.st_flags & UF_COMPRESSED;
4357
+ else
4358
+ #endif
4359
+ compressed = 0;
4360
+ ret = copy_metadata(a, tmp.s, pathname, compressed);
4361
+ }
4362
+ unlink(tmp.s);
4363
+ archive_string_free(&tmp);
4364
+ return (ret);
4365
+ }
4366
+
4367
+ static int
4368
+ fixup_appledouble(struct archive_write_disk *a, const char *pathname)
4369
+ {
4370
+ char buff[8];
4371
+ struct stat st;
4372
+ const char *p;
4373
+ struct archive_string datafork;
4374
+ int fd = -1, ret = ARCHIVE_OK;
4375
+
4376
+ archive_string_init(&datafork);
4377
+ /* Check if the current file name is a type of the resource
4378
+ * fork file. */
4379
+ p = strrchr(pathname, '/');
4380
+ if (p == NULL)
4381
+ p = pathname;
4382
+ else
4383
+ p++;
4384
+ if (p[0] != '.' || p[1] != '_')
4385
+ goto skip_appledouble;
4386
+
4387
+ /*
4388
+ * Check if the data fork file exists.
4389
+ *
4390
+ * TODO: Check if this write disk object has handled it.
4391
+ */
4392
+ archive_strncpy(&datafork, pathname, p - pathname);
4393
+ archive_strcat(&datafork, p + 2);
4394
+ if (lstat(datafork.s, &st) == -1 ||
4395
+ (st.st_mode & AE_IFMT) != AE_IFREG)
4396
+ goto skip_appledouble;
4397
+
4398
+ /*
4399
+ * Check if the file is in the AppleDouble form.
4400
+ */
4401
+ fd = open(pathname, O_RDONLY | O_BINARY | O_CLOEXEC);
4402
+ __archive_ensure_cloexec_flag(fd);
4403
+ if (fd == -1) {
4404
+ archive_set_error(&a->archive, errno,
4405
+ "Failed to open a restoring file");
4406
+ ret = ARCHIVE_WARN;
4407
+ goto skip_appledouble;
4408
+ }
4409
+ if (read(fd, buff, 8) == -1) {
4410
+ archive_set_error(&a->archive, errno,
4411
+ "Failed to read a restoring file");
4412
+ close(fd);
4413
+ ret = ARCHIVE_WARN;
4414
+ goto skip_appledouble;
4415
+ }
4416
+ close(fd);
4417
+ /* Check AppleDouble Magic Code. */
4418
+ if (archive_be32dec(buff) != 0x00051607)
4419
+ goto skip_appledouble;
4420
+ /* Check AppleDouble Version. */
4421
+ if (archive_be32dec(buff+4) != 0x00020000)
4422
+ goto skip_appledouble;
4423
+
4424
+ ret = copy_metadata(a, pathname, datafork.s,
4425
+ #if defined(UF_COMPRESSED)
4426
+ st.st_flags & UF_COMPRESSED);
4427
+ #else
4428
+ 0);
4429
+ #endif
4430
+ if (ret == ARCHIVE_OK) {
4431
+ unlink(pathname);
4432
+ ret = ARCHIVE_EOF;
4433
+ }
4434
+ skip_appledouble:
4435
+ archive_string_free(&datafork);
4436
+ return (ret);
4437
+ }
4438
+ #endif
4439
+
4440
+ #if ARCHIVE_XATTR_LINUX || ARCHIVE_XATTR_DARWIN || ARCHIVE_XATTR_AIX
4441
+ /*
4442
+ * Restore extended attributes - Linux, Darwin and AIX implementations:
4443
+ * AIX' ea interface is syntaxwise identical to the Linux xattr interface.
4444
+ */
4445
+ static int
4446
+ set_xattrs(struct archive_write_disk *a)
4447
+ {
4448
+ struct archive_entry *entry = a->entry;
4449
+ struct archive_string errlist;
4450
+ int ret = ARCHIVE_OK;
4451
+ int i = archive_entry_xattr_reset(entry);
4452
+ short fail = 0;
4453
+
4454
+ archive_string_init(&errlist);
4455
+
4456
+ while (i--) {
4457
+ const char *name;
4458
+ const void *value;
4459
+ size_t size;
4460
+ int e;
4461
+
4462
+ archive_entry_xattr_next(entry, &name, &value, &size);
4463
+
4464
+ if (name == NULL)
4465
+ continue;
4466
+ #if ARCHIVE_XATTR_LINUX
4467
+ /* Linux: quietly skip POSIX.1e ACL extended attributes */
4468
+ if (strncmp(name, "system.", 7) == 0 &&
4469
+ (strcmp(name + 7, "posix_acl_access") == 0 ||
4470
+ strcmp(name + 7, "posix_acl_default") == 0))
4471
+ continue;
4472
+ if (strncmp(name, "trusted.SGI_", 12) == 0 &&
4473
+ (strcmp(name + 12, "ACL_DEFAULT") == 0 ||
4474
+ strcmp(name + 12, "ACL_FILE") == 0))
4475
+ continue;
4476
+
4477
+ /* Linux: xfsroot namespace is obsolete and unsupported */
4478
+ if (strncmp(name, "xfsroot.", 8) == 0) {
4479
+ fail = 1;
4480
+ archive_strcat(&errlist, name);
4481
+ archive_strappend_char(&errlist, ' ');
4482
+ continue;
4483
+ }
4484
+ #endif
4485
+
4486
+ if (a->fd >= 0) {
4487
+ #if ARCHIVE_XATTR_LINUX
4488
+ e = fsetxattr(a->fd, name, value, size, 0);
4489
+ #elif ARCHIVE_XATTR_DARWIN
4490
+ e = fsetxattr(a->fd, name, value, size, 0, 0);
4491
+ #elif ARCHIVE_XATTR_AIX
4492
+ e = fsetea(a->fd, name, value, size, 0);
4493
+ #endif
4494
+ } else {
4495
+ #if ARCHIVE_XATTR_LINUX
4496
+ e = lsetxattr(archive_entry_pathname(entry),
4497
+ name, value, size, 0);
4498
+ #elif ARCHIVE_XATTR_DARWIN
4499
+ e = setxattr(archive_entry_pathname(entry),
4500
+ name, value, size, 0, XATTR_NOFOLLOW);
4501
+ #elif ARCHIVE_XATTR_AIX
4502
+ e = lsetea(archive_entry_pathname(entry),
4503
+ name, value, size, 0);
4504
+ #endif
4505
+ }
4506
+ if (e == -1) {
4507
+ ret = ARCHIVE_WARN;
4508
+ archive_strcat(&errlist, name);
4509
+ archive_strappend_char(&errlist, ' ');
4510
+ if (errno != ENOTSUP && errno != ENOSYS)
4511
+ fail = 1;
4512
+ }
4513
+ }
4514
+
4515
+ if (ret == ARCHIVE_WARN) {
4516
+ if (fail && errlist.length > 0) {
4517
+ errlist.length--;
4518
+ errlist.s[errlist.length] = '\0';
4519
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
4520
+ "Cannot restore extended attributes: %s",
4521
+ errlist.s);
4522
+ } else
4523
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
4524
+ "Cannot restore extended "
4525
+ "attributes on this file system.");
4526
+ }
4527
+
4528
+ archive_string_free(&errlist);
4529
+ return (ret);
4530
+ }
4531
+ #elif ARCHIVE_XATTR_FREEBSD
4532
+ /*
4533
+ * Restore extended attributes - FreeBSD implementation
4534
+ */
4535
+ static int
4536
+ set_xattrs(struct archive_write_disk *a)
4537
+ {
4538
+ struct archive_entry *entry = a->entry;
4539
+ struct archive_string errlist;
4540
+ int ret = ARCHIVE_OK;
4541
+ int i = archive_entry_xattr_reset(entry);
4542
+ short fail = 0;
4543
+
4544
+ archive_string_init(&errlist);
4545
+
4546
+ while (i--) {
4547
+ const char *name;
4548
+ const void *value;
4549
+ size_t size;
4550
+ archive_entry_xattr_next(entry, &name, &value, &size);
4551
+ if (name != NULL) {
4552
+ int e;
4553
+ int namespace;
4554
+
4555
+ namespace = EXTATTR_NAMESPACE_USER;
4556
+
4557
+ if (strncmp(name, "user.", 5) == 0) {
4558
+ /* "user." attributes go to user namespace */
4559
+ name += 5;
4560
+ namespace = EXTATTR_NAMESPACE_USER;
4561
+ } else if (strncmp(name, "system.", 7) == 0) {
4562
+ name += 7;
4563
+ namespace = EXTATTR_NAMESPACE_SYSTEM;
4564
+ if (!strcmp(name, "nfs4.acl") ||
4565
+ !strcmp(name, "posix1e.acl_access") ||
4566
+ !strcmp(name, "posix1e.acl_default"))
4567
+ continue;
4568
+ } else {
4569
+ /* Other namespaces are unsupported */
4570
+ archive_strcat(&errlist, name);
4571
+ archive_strappend_char(&errlist, ' ');
4572
+ fail = 1;
4573
+ ret = ARCHIVE_WARN;
4574
+ continue;
4575
+ }
4576
+
4577
+ if (a->fd >= 0) {
4578
+ /*
4579
+ * On FreeBSD, extattr_set_fd does not
4580
+ * return the same as
4581
+ * extattr_set_file. It returns zero
4582
+ * on success, non-zero on failure.
4583
+ *
4584
+ * We can detect the failure by
4585
+ * manually setting errno prior to the
4586
+ * call and checking after.
4587
+ *
4588
+ * If errno remains zero, fake the
4589
+ * return value by setting e to size.
4590
+ *
4591
+ * This is a hack for now until I
4592
+ * (Shawn Webb) get FreeBSD to fix the
4593
+ * issue, if that's even possible.
4594
+ */
4595
+ errno = 0;
4596
+ e = extattr_set_fd(a->fd, namespace, name,
4597
+ value, size);
4598
+ if (e == 0 && errno == 0) {
4599
+ e = size;
4600
+ }
4601
+ } else {
4602
+ e = extattr_set_link(
4603
+ archive_entry_pathname(entry), namespace,
4604
+ name, value, size);
4605
+ }
4606
+ if (e != (int)size) {
4607
+ archive_strcat(&errlist, name);
4608
+ archive_strappend_char(&errlist, ' ');
4609
+ ret = ARCHIVE_WARN;
4610
+ if (errno != ENOTSUP && errno != ENOSYS)
4611
+ fail = 1;
4612
+ }
4613
+ }
4614
+ }
4615
+
4616
+ if (ret == ARCHIVE_WARN) {
4617
+ if (fail && errlist.length > 0) {
4618
+ errlist.length--;
4619
+ errlist.s[errlist.length] = '\0';
4620
+
4621
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
4622
+ "Cannot restore extended attributes: %s",
4623
+ errlist.s);
4624
+ } else
4625
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
4626
+ "Cannot restore extended "
4627
+ "attributes on this file system.");
4628
+ }
4629
+
4630
+ archive_string_free(&errlist);
4631
+ return (ret);
4632
+ }
4633
+ #else
4634
+ /*
4635
+ * Restore extended attributes - stub implementation for unsupported systems
4636
+ */
4637
+ static int
4638
+ set_xattrs(struct archive_write_disk *a)
4639
+ {
4640
+ static int warning_done = 0;
4641
+
4642
+ /* If there aren't any extended attributes, then it's okay not
4643
+ * to extract them, otherwise, issue a single warning. */
4644
+ if (archive_entry_xattr_count(a->entry) != 0 && !warning_done) {
4645
+ warning_done = 1;
4646
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
4647
+ "Cannot restore extended attributes on this system");
4648
+ return (ARCHIVE_WARN);
4649
+ }
4650
+ /* Warning was already emitted; suppress further warnings. */
4651
+ return (ARCHIVE_OK);
4652
+ }
4653
+ #endif
4654
+
4655
+ /*
4656
+ * Test if file on disk is older than entry.
4657
+ */
4658
+ static int
4659
+ older(struct stat *st, struct archive_entry *entry)
4660
+ {
4661
+ /* First, test the seconds and return if we have a definite answer. */
4662
+ /* Definitely older. */
4663
+ if (to_int64_time(st->st_mtime) < to_int64_time(archive_entry_mtime(entry)))
4664
+ return (1);
4665
+ /* Definitely younger. */
4666
+ if (to_int64_time(st->st_mtime) > to_int64_time(archive_entry_mtime(entry)))
4667
+ return (0);
4668
+ /* If this platform supports fractional seconds, try those. */
4669
+ #if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
4670
+ /* Definitely older. */
4671
+ if (st->st_mtimespec.tv_nsec < archive_entry_mtime_nsec(entry))
4672
+ return (1);
4673
+ #elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
4674
+ /* Definitely older. */
4675
+ if (st->st_mtim.tv_nsec < archive_entry_mtime_nsec(entry))
4676
+ return (1);
4677
+ #elif HAVE_STRUCT_STAT_ST_MTIME_N
4678
+ /* older. */
4679
+ if (st->st_mtime_n < archive_entry_mtime_nsec(entry))
4680
+ return (1);
4681
+ #elif HAVE_STRUCT_STAT_ST_UMTIME
4682
+ /* older. */
4683
+ if (st->st_umtime * 1000 < archive_entry_mtime_nsec(entry))
4684
+ return (1);
4685
+ #elif HAVE_STRUCT_STAT_ST_MTIME_USEC
4686
+ /* older. */
4687
+ if (st->st_mtime_usec * 1000 < archive_entry_mtime_nsec(entry))
4688
+ return (1);
4689
+ #else
4690
+ /* This system doesn't have high-res timestamps. */
4691
+ #endif
4692
+ /* Same age or newer, so not older. */
4693
+ return (0);
4694
+ }
4695
+
4696
+ #ifndef ARCHIVE_ACL_SUPPORT
4697
+ int
4698
+ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
4699
+ struct archive_acl *abstract_acl, __LA_MODE_T mode)
4700
+ {
4701
+ (void)a; /* UNUSED */
4702
+ (void)fd; /* UNUSED */
4703
+ (void)name; /* UNUSED */
4704
+ (void)abstract_acl; /* UNUSED */
4705
+ (void)mode; /* UNUSED */
4706
+ return (ARCHIVE_OK);
4707
+ }
4708
+ #endif
4709
+
4710
+ #endif /* !_WIN32 || __CYGWIN__ */
4711
+