libarchive-static 1.0.5 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (296) hide show
  1. checksums.yaml +5 -5
  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_internal.h +0 -1
  20. data/ext/libarchive-0.1.1/ext/libarchive_reader.c +6 -4
  21. data/ext/libarchive-0.1.1/ext/libarchive_reader.o +0 -0
  22. data/ext/libarchive-0.1.1/ext/libarchive_ruby.so +0 -0
  23. data/ext/libarchive-0.1.1/ext/libarchive_win32.h +1 -1
  24. data/ext/libarchive-0.1.1/ext/libarchive_writer.c +2 -2
  25. data/ext/libarchive-0.1.1/ext/libarchive_writer.o +0 -0
  26. data/ext/libarchive-3.6.2/Makefile.in +16892 -0
  27. data/ext/libarchive-3.6.2/build/autoconf/ax_append_compile_flags.m4 +67 -0
  28. data/ext/libarchive-3.6.2/build/autoconf/ax_append_flag.m4 +71 -0
  29. data/ext/libarchive-3.6.2/build/autoconf/ax_check_compile_flag.m4 +74 -0
  30. data/ext/libarchive-3.6.2/build/autoconf/ax_require_defined.m4 +37 -0
  31. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/build/autoconf/check_stdcall_func.m4 +0 -0
  32. data/ext/libarchive-3.6.2/build/autoconf/compile +348 -0
  33. data/ext/libarchive-3.6.2/build/autoconf/config.guess +1754 -0
  34. data/ext/libarchive-3.6.2/build/autoconf/config.rpath +696 -0
  35. data/ext/libarchive-3.6.2/build/autoconf/config.sub +1890 -0
  36. data/ext/libarchive-3.6.2/build/autoconf/depcomp +791 -0
  37. data/ext/libarchive-3.6.2/build/autoconf/iconv.m4 +271 -0
  38. data/ext/libarchive-3.6.2/build/autoconf/install-sh +541 -0
  39. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/build/autoconf/la_uid_t.m4 +0 -0
  40. data/ext/libarchive-3.6.2/build/autoconf/lib-ld.m4 +109 -0
  41. data/ext/libarchive-3.6.2/build/autoconf/lib-link.m4 +777 -0
  42. data/ext/libarchive-3.6.2/build/autoconf/lib-prefix.m4 +224 -0
  43. data/ext/libarchive-3.6.2/build/autoconf/ltmain.sh +11251 -0
  44. data/ext/libarchive-3.6.2/build/autoconf/m4_ax_compile_check_sizeof.m4 +115 -0
  45. data/ext/libarchive-3.6.2/build/autoconf/missing +215 -0
  46. data/ext/libarchive-3.6.2/build/autoconf/test-driver +153 -0
  47. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/build/pkgconfig/libarchive.pc.in +4 -1
  48. data/ext/libarchive-3.6.2/config.h.in +1504 -0
  49. data/ext/libarchive-3.6.2/configure +25558 -0
  50. data/ext/libarchive-3.6.2/libarchive/archive.h +1212 -0
  51. data/ext/libarchive-3.6.2/libarchive/archive_acl.c +2097 -0
  52. data/ext/libarchive-3.6.2/libarchive/archive_acl_private.h +83 -0
  53. data/ext/libarchive-3.6.2/libarchive/archive_blake2.h +197 -0
  54. data/ext/libarchive-3.6.2/libarchive/archive_blake2_impl.h +161 -0
  55. data/ext/libarchive-3.6.2/libarchive/archive_blake2s_ref.c +369 -0
  56. data/ext/libarchive-3.6.2/libarchive/archive_blake2sp_ref.c +361 -0
  57. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_check_magic.c +63 -22
  58. data/ext/libarchive-3.6.2/libarchive/archive_cmdline.c +227 -0
  59. data/ext/libarchive-3.6.2/libarchive/archive_cmdline_private.h +47 -0
  60. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_crc32.h +17 -0
  61. data/ext/libarchive-3.6.2/libarchive/archive_cryptor.c +534 -0
  62. data/ext/libarchive-3.6.2/libarchive/archive_cryptor_private.h +188 -0
  63. data/ext/libarchive-3.6.2/libarchive/archive_digest.c +1505 -0
  64. data/ext/libarchive-3.6.2/libarchive/archive_digest_private.h +416 -0
  65. data/ext/libarchive-3.6.2/libarchive/archive_disk_acl_darwin.c +559 -0
  66. data/ext/libarchive-3.6.2/libarchive/archive_disk_acl_freebsd.c +712 -0
  67. data/ext/libarchive-3.6.2/libarchive/archive_disk_acl_linux.c +760 -0
  68. data/ext/libarchive-3.6.2/libarchive/archive_disk_acl_sunos.c +824 -0
  69. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_endian.h +48 -15
  70. data/ext/libarchive-3.6.2/libarchive/archive_entry.c +2149 -0
  71. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry.h +305 -106
  72. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_copy_bhfi.c +5 -4
  73. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_copy_stat.c +9 -3
  74. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_link_resolver.c +104 -62
  75. data/ext/libarchive-3.6.2/libarchive/archive_entry_locale.h +92 -0
  76. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_private.h +65 -49
  77. data/ext/libarchive-3.6.2/libarchive/archive_entry_sparse.c +156 -0
  78. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_stat.c +6 -6
  79. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_strmode.c +1 -1
  80. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_xattr.c +4 -6
  81. data/ext/libarchive-3.6.2/libarchive/archive_getdate.c +1165 -0
  82. data/ext/libarchive-3.6.2/libarchive/archive_getdate.h +39 -0
  83. data/ext/libarchive-3.6.2/libarchive/archive_hmac.c +334 -0
  84. data/ext/libarchive-3.6.2/libarchive/archive_hmac_private.h +117 -0
  85. data/ext/libarchive-3.6.2/libarchive/archive_match.c +1875 -0
  86. data/ext/libarchive-3.6.2/libarchive/archive_openssl_evp_private.h +53 -0
  87. data/ext/libarchive-3.6.2/libarchive/archive_openssl_hmac_private.h +54 -0
  88. data/ext/libarchive-3.6.2/libarchive/archive_options.c +218 -0
  89. data/ext/libarchive-3.6.2/libarchive/archive_options_private.h +51 -0
  90. data/ext/libarchive-3.6.2/libarchive/archive_pack_dev.c +337 -0
  91. data/ext/libarchive-3.6.2/libarchive/archive_pack_dev.h +49 -0
  92. data/ext/libarchive-3.6.2/libarchive/archive_pathmatch.c +463 -0
  93. data/ext/libarchive-3.6.2/libarchive/archive_pathmatch.h +52 -0
  94. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_platform.h +77 -9
  95. data/ext/libarchive-3.6.2/libarchive/archive_platform_acl.h +55 -0
  96. data/ext/libarchive-3.6.2/libarchive/archive_platform_xattr.h +47 -0
  97. data/ext/libarchive-3.6.2/libarchive/archive_ppmd7.c +1168 -0
  98. data/ext/libarchive-3.6.2/libarchive/archive_ppmd7_private.h +119 -0
  99. data/ext/libarchive-3.6.2/libarchive/archive_ppmd8.c +1287 -0
  100. data/ext/libarchive-3.6.2/libarchive/archive_ppmd8_private.h +148 -0
  101. data/ext/libarchive-3.6.2/libarchive/archive_ppmd_private.h +151 -0
  102. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_private.h +74 -18
  103. data/ext/libarchive-3.6.2/libarchive/archive_random.c +272 -0
  104. data/ext/libarchive-3.6.2/libarchive/archive_random_private.h +36 -0
  105. data/ext/libarchive-3.6.2/libarchive/archive_rb.c +709 -0
  106. data/ext/libarchive-3.6.2/libarchive/archive_rb.h +113 -0
  107. data/ext/libarchive-3.6.2/libarchive/archive_read.c +1756 -0
  108. data/ext/libarchive-3.6.2/libarchive/archive_read_add_passphrase.c +190 -0
  109. data/ext/libarchive-3.6.2/libarchive/archive_read_append_filter.c +204 -0
  110. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_data_into_fd.c +64 -18
  111. data/ext/libarchive-3.6.2/libarchive/archive_read_disk_entry_from_file.c +1086 -0
  112. data/ext/libarchive-3.6.2/libarchive/archive_read_disk_posix.c +2732 -0
  113. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_disk_private.h +40 -4
  114. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_disk_set_standard_lookup.c +21 -11
  115. data/ext/libarchive-3.6.2/libarchive/archive_read_disk_windows.c +2479 -0
  116. data/ext/libarchive-3.6.2/libarchive/archive_read_extract.c +60 -0
  117. data/ext/{libarchive-2.8.4/libarchive/archive_read_extract.c → libarchive-3.6.2/libarchive/archive_read_extract2.c} +34 -61
  118. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_open_fd.c +70 -49
  119. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_open_file.c +38 -23
  120. data/ext/libarchive-3.6.2/libarchive/archive_read_open_filename.c +586 -0
  121. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_open_memory.c +58 -28
  122. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_private.h +127 -59
  123. data/ext/libarchive-3.6.2/libarchive/archive_read_set_format.c +117 -0
  124. data/ext/libarchive-3.6.2/libarchive/archive_read_set_options.c +133 -0
  125. 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
  126. data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_by_code.c +83 -0
  127. 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
  128. 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
  129. data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_grzip.c +112 -0
  130. 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
  131. data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_lrzip.c +122 -0
  132. data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_lz4.c +742 -0
  133. data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_lzop.c +499 -0
  134. 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
  135. 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
  136. 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
  137. 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
  138. 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
  139. data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_zstd.c +297 -0
  140. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_7zip.c +3900 -0
  141. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_all.c +89 -0
  142. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_ar.c +126 -72
  143. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_by_code.c +92 -0
  144. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_cab.c +3228 -0
  145. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_cpio.c +1104 -0
  146. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_empty.c +14 -11
  147. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_iso9660.c +990 -541
  148. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_lha.c +2916 -0
  149. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_mtree.c +2150 -0
  150. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_rar.c +3797 -0
  151. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_rar5.c +4251 -0
  152. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_raw.c +38 -31
  153. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_tar.c +1157 -629
  154. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_warc.c +848 -0
  155. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_xar.c +439 -258
  156. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_zip.c +4270 -0
  157. data/ext/libarchive-3.6.2/libarchive/archive_string.c +4240 -0
  158. data/ext/libarchive-3.6.2/libarchive/archive_string.h +243 -0
  159. data/ext/libarchive-3.6.2/libarchive/archive_string_composition.h +2292 -0
  160. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_string_sprintf.c +44 -16
  161. data/ext/libarchive-3.6.2/libarchive/archive_util.c +655 -0
  162. data/ext/libarchive-3.6.2/libarchive/archive_version_details.c +151 -0
  163. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_virtual.c +85 -16
  164. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_windows.c +214 -541
  165. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_windows.h +74 -106
  166. data/ext/libarchive-3.6.2/libarchive/archive_write.c +828 -0
  167. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter.c +72 -0
  168. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_b64encode.c +304 -0
  169. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_by_name.c +77 -0
  170. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_bzip2.c +401 -0
  171. 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
  172. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_grzip.c +135 -0
  173. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_gzip.c +442 -0
  174. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_lrzip.c +197 -0
  175. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_lz4.c +700 -0
  176. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_lzop.c +478 -0
  177. 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
  178. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_program.c +391 -0
  179. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_uuencode.c +295 -0
  180. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_xz.c +545 -0
  181. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_zstd.c +418 -0
  182. data/ext/libarchive-3.6.2/libarchive/archive_write_disk_posix.c +4711 -0
  183. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_disk_private.h +9 -2
  184. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_disk_set_standard_lookup.c +30 -29
  185. data/ext/libarchive-3.6.2/libarchive/archive_write_disk_windows.c +2842 -0
  186. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_open_fd.c +15 -10
  187. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_open_file.c +15 -9
  188. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_open_filename.c +128 -20
  189. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_open_memory.c +7 -18
  190. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_private.h +72 -29
  191. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format.c +56 -3
  192. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_7zip.c +2322 -0
  193. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_ar.c +54 -34
  194. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_by_name.c +20 -2
  195. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_cpio.c +11 -0
  196. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_cpio_binary.c +610 -0
  197. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_cpio_newc.c +457 -0
  198. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_cpio_odc.c +500 -0
  199. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_filter_by_ext.c +142 -0
  200. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_gnutar.c +755 -0
  201. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_iso9660.c +8165 -0
  202. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_mtree.c +2217 -0
  203. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_pax.c +1049 -387
  204. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_private.h +42 -0
  205. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_raw.c +125 -0
  206. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_shar.c +62 -47
  207. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_ustar.c +279 -108
  208. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_v7tar.c +638 -0
  209. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_warc.c +453 -0
  210. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_xar.c +3259 -0
  211. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_zip.c +1704 -0
  212. data/ext/libarchive-3.6.2/libarchive/archive_write_set_options.c +130 -0
  213. data/ext/libarchive-3.6.2/libarchive/archive_write_set_passphrase.c +95 -0
  214. data/ext/libarchive-3.6.2/libarchive/archive_xxhash.h +48 -0
  215. data/ext/libarchive-3.6.2/libarchive/config_freebsd.h +271 -0
  216. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/filter_fork.h +10 -5
  217. data/ext/{libarchive-2.8.4/libarchive/filter_fork.c → libarchive-3.6.2/libarchive/filter_fork_posix.c} +98 -19
  218. data/ext/libarchive-3.6.2/libarchive/filter_fork_windows.c +236 -0
  219. data/ext/libarchive-3.6.2/libarchive/xxhash.c +525 -0
  220. data/ext/libarchive-static-makefile +144 -80
  221. data/ext/libarchive-static-wrapper-makefile +1 -1
  222. data/ext/zlib-1.2.13/Makefile.in +404 -0
  223. data/ext/{zlib-1.2.5 → zlib-1.2.13}/adler32.c +51 -34
  224. data/ext/{zlib-1.2.5 → zlib-1.2.13}/compress.c +27 -21
  225. data/ext/zlib-1.2.13/configure +922 -0
  226. data/ext/zlib-1.2.13/crc32.c +1125 -0
  227. data/ext/zlib-1.2.13/crc32.h +9446 -0
  228. data/ext/{zlib-1.2.5 → zlib-1.2.13}/deflate.c +842 -459
  229. data/ext/{zlib-1.2.5 → zlib-1.2.13}/deflate.h +37 -33
  230. data/ext/{zlib-1.2.5 → zlib-1.2.13}/gzclose.c +0 -0
  231. data/ext/{zlib-1.2.5 → zlib-1.2.13}/gzguts.h +103 -16
  232. data/ext/{zlib-1.2.5 → zlib-1.2.13}/gzlib.c +155 -53
  233. data/ext/zlib-1.2.13/gzread.c +650 -0
  234. data/ext/zlib-1.2.13/gzwrite.c +677 -0
  235. data/ext/{zlib-1.2.5 → zlib-1.2.13}/infback.c +24 -12
  236. data/ext/{zlib-1.2.5 → zlib-1.2.13}/inffast.c +49 -66
  237. data/ext/{zlib-1.2.5 → zlib-1.2.13}/inffast.h +0 -0
  238. data/ext/{zlib-1.2.5 → zlib-1.2.13}/inffixed.h +3 -3
  239. data/ext/{zlib-1.2.5 → zlib-1.2.13}/inflate.c +209 -94
  240. data/ext/{zlib-1.2.5 → zlib-1.2.13}/inflate.h +9 -5
  241. data/ext/{zlib-1.2.5 → zlib-1.2.13}/inftrees.c +24 -50
  242. data/ext/{zlib-1.2.5 → zlib-1.2.13}/inftrees.h +1 -1
  243. data/ext/{zlib-1.2.5 → zlib-1.2.13}/trees.c +135 -198
  244. data/ext/{zlib-1.2.5 → zlib-1.2.13}/trees.h +0 -0
  245. data/ext/zlib-1.2.13/uncompr.c +93 -0
  246. data/ext/{zlib-1.2.5 → zlib-1.2.13}/zconf.h +182 -63
  247. data/ext/{zlib-1.2.5 → zlib-1.2.13}/zlib.h +617 -295
  248. data/ext/{zlib-1.2.5 → zlib-1.2.13}/zutil.c +50 -41
  249. data/ext/{zlib-1.2.5 → zlib-1.2.13}/zutil.h +83 -82
  250. metadata +244 -137
  251. data/ext/libarchive-0.1.1/libarchive.c +0 -1762
  252. data/ext/libarchive-2.8.4/Makefile.in +0 -7076
  253. data/ext/libarchive-2.8.4/build/autoconf/compile +0 -143
  254. data/ext/libarchive-2.8.4/build/autoconf/config.guess +0 -1502
  255. data/ext/libarchive-2.8.4/build/autoconf/config.sub +0 -1708
  256. data/ext/libarchive-2.8.4/build/autoconf/depcomp +0 -630
  257. data/ext/libarchive-2.8.4/build/autoconf/install-sh +0 -291
  258. data/ext/libarchive-2.8.4/build/autoconf/ltmain.sh +0 -8406
  259. data/ext/libarchive-2.8.4/build/autoconf/missing +0 -376
  260. data/ext/libarchive-2.8.4/config.h.in +0 -772
  261. data/ext/libarchive-2.8.4/configure +0 -17916
  262. data/ext/libarchive-2.8.4/libarchive/archive.h +0 -741
  263. data/ext/libarchive-2.8.4/libarchive/archive_entry.c +0 -2202
  264. data/ext/libarchive-2.8.4/libarchive/archive_hash.h +0 -281
  265. data/ext/libarchive-2.8.4/libarchive/archive_read.c +0 -1249
  266. data/ext/libarchive-2.8.4/libarchive/archive_read_disk.c +0 -198
  267. data/ext/libarchive-2.8.4/libarchive/archive_read_disk_entry_from_file.c +0 -570
  268. data/ext/libarchive-2.8.4/libarchive/archive_read_open_filename.c +0 -272
  269. data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_cpio.c +0 -777
  270. data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_mtree.c +0 -1304
  271. data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_zip.c +0 -903
  272. data/ext/libarchive-2.8.4/libarchive/archive_string.c +0 -453
  273. data/ext/libarchive-2.8.4/libarchive/archive_string.h +0 -148
  274. data/ext/libarchive-2.8.4/libarchive/archive_util.c +0 -391
  275. data/ext/libarchive-2.8.4/libarchive/archive_write.c +0 -466
  276. data/ext/libarchive-2.8.4/libarchive/archive_write_disk.c +0 -2628
  277. data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_bzip2.c +0 -408
  278. data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_gzip.c +0 -477
  279. data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_none.c +0 -257
  280. data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_program.c +0 -347
  281. data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_xz.c +0 -438
  282. data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_cpio.c +0 -344
  283. data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_cpio_newc.c +0 -295
  284. data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_mtree.c +0 -1050
  285. data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_zip.c +0 -667
  286. data/ext/libarchive-2.8.4/libarchive/config_freebsd.h +0 -154
  287. data/ext/libarchive-2.8.4/libarchive/filter_fork_windows.c +0 -113
  288. data/ext/zlib-1.2.5/Makefile.in +0 -257
  289. data/ext/zlib-1.2.5/configure +0 -596
  290. data/ext/zlib-1.2.5/crc32.c +0 -442
  291. data/ext/zlib-1.2.5/crc32.h +0 -441
  292. data/ext/zlib-1.2.5/example.c +0 -565
  293. data/ext/zlib-1.2.5/gzread.c +0 -653
  294. data/ext/zlib-1.2.5/gzwrite.c +0 -531
  295. data/ext/zlib-1.2.5/minigzip.c +0 -440
  296. 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
+