libarchive-static 1.0.6 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (295) hide show
  1. checksums.yaml +4 -4
  2. data/ext/extconf.rb +2 -9
  3. data/ext/libarchive-0.1.1/ext/archive_read_support_compression.c +6 -6
  4. data/ext/libarchive-0.1.1/ext/archive_read_support_compression.o +0 -0
  5. data/ext/libarchive-0.1.1/ext/archive_read_support_format.o +0 -0
  6. data/ext/libarchive-0.1.1/ext/archive_write_open_rb_str.c +1 -1
  7. data/ext/libarchive-0.1.1/ext/archive_write_open_rb_str.o +0 -0
  8. data/ext/libarchive-0.1.1/ext/archive_write_set_compression.c +5 -5
  9. data/ext/libarchive-0.1.1/ext/archive_write_set_compression.o +0 -0
  10. data/ext/libarchive-0.1.1/ext/config.h +23 -0
  11. data/ext/libarchive-0.1.1/ext/config.log +230 -0
  12. data/ext/libarchive-0.1.1/ext/config.status +671 -0
  13. data/ext/libarchive-0.1.1/ext/libarchive.c +1 -1
  14. data/ext/libarchive-0.1.1/ext/libarchive.o +0 -0
  15. data/ext/libarchive-0.1.1/ext/libarchive_archive.c +7 -7
  16. data/ext/libarchive-0.1.1/ext/libarchive_archive.o +0 -0
  17. data/ext/libarchive-0.1.1/ext/libarchive_entry.c +6 -0
  18. data/ext/libarchive-0.1.1/ext/libarchive_entry.o +0 -0
  19. data/ext/libarchive-0.1.1/ext/libarchive_reader.c +6 -4
  20. data/ext/libarchive-0.1.1/ext/libarchive_reader.o +0 -0
  21. data/ext/libarchive-0.1.1/ext/libarchive_ruby.so +0 -0
  22. data/ext/libarchive-0.1.1/ext/libarchive_win32.h +1 -1
  23. data/ext/libarchive-0.1.1/ext/libarchive_writer.c +2 -2
  24. data/ext/libarchive-0.1.1/ext/libarchive_writer.o +0 -0
  25. data/ext/libarchive-3.6.2/Makefile.in +16892 -0
  26. data/ext/libarchive-3.6.2/build/autoconf/ax_append_compile_flags.m4 +67 -0
  27. data/ext/libarchive-3.6.2/build/autoconf/ax_append_flag.m4 +71 -0
  28. data/ext/libarchive-3.6.2/build/autoconf/ax_check_compile_flag.m4 +74 -0
  29. data/ext/libarchive-3.6.2/build/autoconf/ax_require_defined.m4 +37 -0
  30. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/build/autoconf/check_stdcall_func.m4 +0 -0
  31. data/ext/libarchive-3.6.2/build/autoconf/compile +348 -0
  32. data/ext/libarchive-3.6.2/build/autoconf/config.guess +1754 -0
  33. data/ext/libarchive-3.6.2/build/autoconf/config.rpath +696 -0
  34. data/ext/libarchive-3.6.2/build/autoconf/config.sub +1890 -0
  35. data/ext/libarchive-3.6.2/build/autoconf/depcomp +791 -0
  36. data/ext/libarchive-3.6.2/build/autoconf/iconv.m4 +271 -0
  37. data/ext/libarchive-3.6.2/build/autoconf/install-sh +541 -0
  38. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/build/autoconf/la_uid_t.m4 +0 -0
  39. data/ext/libarchive-3.6.2/build/autoconf/lib-ld.m4 +109 -0
  40. data/ext/libarchive-3.6.2/build/autoconf/lib-link.m4 +777 -0
  41. data/ext/libarchive-3.6.2/build/autoconf/lib-prefix.m4 +224 -0
  42. data/ext/libarchive-3.6.2/build/autoconf/ltmain.sh +11251 -0
  43. data/ext/libarchive-3.6.2/build/autoconf/m4_ax_compile_check_sizeof.m4 +115 -0
  44. data/ext/libarchive-3.6.2/build/autoconf/missing +215 -0
  45. data/ext/libarchive-3.6.2/build/autoconf/test-driver +153 -0
  46. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/build/pkgconfig/libarchive.pc.in +4 -1
  47. data/ext/libarchive-3.6.2/config.h.in +1504 -0
  48. data/ext/libarchive-3.6.2/configure +25558 -0
  49. data/ext/libarchive-3.6.2/libarchive/archive.h +1212 -0
  50. data/ext/libarchive-3.6.2/libarchive/archive_acl.c +2097 -0
  51. data/ext/libarchive-3.6.2/libarchive/archive_acl_private.h +83 -0
  52. data/ext/libarchive-3.6.2/libarchive/archive_blake2.h +197 -0
  53. data/ext/libarchive-3.6.2/libarchive/archive_blake2_impl.h +161 -0
  54. data/ext/libarchive-3.6.2/libarchive/archive_blake2s_ref.c +369 -0
  55. data/ext/libarchive-3.6.2/libarchive/archive_blake2sp_ref.c +361 -0
  56. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_check_magic.c +63 -22
  57. data/ext/libarchive-3.6.2/libarchive/archive_cmdline.c +227 -0
  58. data/ext/libarchive-3.6.2/libarchive/archive_cmdline_private.h +47 -0
  59. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_crc32.h +17 -0
  60. data/ext/libarchive-3.6.2/libarchive/archive_cryptor.c +534 -0
  61. data/ext/libarchive-3.6.2/libarchive/archive_cryptor_private.h +188 -0
  62. data/ext/libarchive-3.6.2/libarchive/archive_digest.c +1505 -0
  63. data/ext/libarchive-3.6.2/libarchive/archive_digest_private.h +416 -0
  64. data/ext/libarchive-3.6.2/libarchive/archive_disk_acl_darwin.c +559 -0
  65. data/ext/libarchive-3.6.2/libarchive/archive_disk_acl_freebsd.c +712 -0
  66. data/ext/libarchive-3.6.2/libarchive/archive_disk_acl_linux.c +760 -0
  67. data/ext/libarchive-3.6.2/libarchive/archive_disk_acl_sunos.c +824 -0
  68. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_endian.h +48 -15
  69. data/ext/libarchive-3.6.2/libarchive/archive_entry.c +2149 -0
  70. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry.h +305 -106
  71. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_copy_bhfi.c +5 -4
  72. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_copy_stat.c +9 -3
  73. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_link_resolver.c +104 -62
  74. data/ext/libarchive-3.6.2/libarchive/archive_entry_locale.h +92 -0
  75. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_private.h +65 -49
  76. data/ext/libarchive-3.6.2/libarchive/archive_entry_sparse.c +156 -0
  77. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_stat.c +6 -6
  78. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_strmode.c +1 -1
  79. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_xattr.c +4 -6
  80. data/ext/libarchive-3.6.2/libarchive/archive_getdate.c +1165 -0
  81. data/ext/libarchive-3.6.2/libarchive/archive_getdate.h +39 -0
  82. data/ext/libarchive-3.6.2/libarchive/archive_hmac.c +334 -0
  83. data/ext/libarchive-3.6.2/libarchive/archive_hmac_private.h +117 -0
  84. data/ext/libarchive-3.6.2/libarchive/archive_match.c +1875 -0
  85. data/ext/libarchive-3.6.2/libarchive/archive_openssl_evp_private.h +53 -0
  86. data/ext/libarchive-3.6.2/libarchive/archive_openssl_hmac_private.h +54 -0
  87. data/ext/libarchive-3.6.2/libarchive/archive_options.c +218 -0
  88. data/ext/libarchive-3.6.2/libarchive/archive_options_private.h +51 -0
  89. data/ext/libarchive-3.6.2/libarchive/archive_pack_dev.c +337 -0
  90. data/ext/libarchive-3.6.2/libarchive/archive_pack_dev.h +49 -0
  91. data/ext/libarchive-3.6.2/libarchive/archive_pathmatch.c +463 -0
  92. data/ext/libarchive-3.6.2/libarchive/archive_pathmatch.h +52 -0
  93. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_platform.h +77 -9
  94. data/ext/libarchive-3.6.2/libarchive/archive_platform_acl.h +55 -0
  95. data/ext/libarchive-3.6.2/libarchive/archive_platform_xattr.h +47 -0
  96. data/ext/libarchive-3.6.2/libarchive/archive_ppmd7.c +1168 -0
  97. data/ext/libarchive-3.6.2/libarchive/archive_ppmd7_private.h +119 -0
  98. data/ext/libarchive-3.6.2/libarchive/archive_ppmd8.c +1287 -0
  99. data/ext/libarchive-3.6.2/libarchive/archive_ppmd8_private.h +148 -0
  100. data/ext/libarchive-3.6.2/libarchive/archive_ppmd_private.h +151 -0
  101. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_private.h +74 -18
  102. data/ext/libarchive-3.6.2/libarchive/archive_random.c +272 -0
  103. data/ext/libarchive-3.6.2/libarchive/archive_random_private.h +36 -0
  104. data/ext/libarchive-3.6.2/libarchive/archive_rb.c +709 -0
  105. data/ext/libarchive-3.6.2/libarchive/archive_rb.h +113 -0
  106. data/ext/libarchive-3.6.2/libarchive/archive_read.c +1756 -0
  107. data/ext/libarchive-3.6.2/libarchive/archive_read_add_passphrase.c +190 -0
  108. data/ext/libarchive-3.6.2/libarchive/archive_read_append_filter.c +204 -0
  109. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_data_into_fd.c +64 -18
  110. data/ext/libarchive-3.6.2/libarchive/archive_read_disk_entry_from_file.c +1086 -0
  111. data/ext/libarchive-3.6.2/libarchive/archive_read_disk_posix.c +2732 -0
  112. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_disk_private.h +40 -4
  113. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_disk_set_standard_lookup.c +21 -11
  114. data/ext/libarchive-3.6.2/libarchive/archive_read_disk_windows.c +2479 -0
  115. data/ext/libarchive-3.6.2/libarchive/archive_read_extract.c +60 -0
  116. data/ext/{libarchive-2.8.4/libarchive/archive_read_extract.c → libarchive-3.6.2/libarchive/archive_read_extract2.c} +34 -61
  117. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_open_fd.c +70 -49
  118. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_open_file.c +38 -23
  119. data/ext/libarchive-3.6.2/libarchive/archive_read_open_filename.c +586 -0
  120. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_open_memory.c +58 -28
  121. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_private.h +127 -59
  122. data/ext/libarchive-3.6.2/libarchive/archive_read_set_format.c +117 -0
  123. data/ext/libarchive-3.6.2/libarchive/archive_read_set_options.c +133 -0
  124. data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_all.c → libarchive-3.6.2/libarchive/archive_read_support_filter_all.c} +35 -10
  125. data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_by_code.c +83 -0
  126. data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_bzip2.c → libarchive-3.6.2/libarchive/archive_read_support_filter_bzip2.c} +38 -26
  127. data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_compress.c → libarchive-3.6.2/libarchive/archive_read_support_filter_compress.c} +52 -44
  128. data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_grzip.c +112 -0
  129. data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_gzip.c → libarchive-3.6.2/libarchive/archive_read_support_filter_gzip.c} +108 -37
  130. data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_lrzip.c +122 -0
  131. data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_lz4.c +742 -0
  132. data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_lzop.c +499 -0
  133. data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_none.c → libarchive-3.6.2/libarchive/archive_read_support_filter_none.c} +15 -3
  134. data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_program.c → libarchive-3.6.2/libarchive/archive_read_support_filter_program.c} +114 -77
  135. data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_rpm.c → libarchive-3.6.2/libarchive/archive_read_support_filter_rpm.c} +31 -31
  136. data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_uu.c → libarchive-3.6.2/libarchive/archive_read_support_filter_uu.c} +141 -85
  137. data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_xz.c → libarchive-3.6.2/libarchive/archive_read_support_filter_xz.c} +369 -284
  138. data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_zstd.c +297 -0
  139. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_7zip.c +3900 -0
  140. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_all.c +89 -0
  141. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_ar.c +126 -72
  142. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_by_code.c +92 -0
  143. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_cab.c +3228 -0
  144. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_cpio.c +1104 -0
  145. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_empty.c +14 -11
  146. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_iso9660.c +990 -541
  147. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_lha.c +2916 -0
  148. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_mtree.c +2150 -0
  149. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_rar.c +3797 -0
  150. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_rar5.c +4251 -0
  151. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_raw.c +38 -31
  152. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_tar.c +1157 -629
  153. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_warc.c +848 -0
  154. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_xar.c +439 -258
  155. data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_zip.c +4270 -0
  156. data/ext/libarchive-3.6.2/libarchive/archive_string.c +4240 -0
  157. data/ext/libarchive-3.6.2/libarchive/archive_string.h +243 -0
  158. data/ext/libarchive-3.6.2/libarchive/archive_string_composition.h +2292 -0
  159. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_string_sprintf.c +44 -16
  160. data/ext/libarchive-3.6.2/libarchive/archive_util.c +655 -0
  161. data/ext/libarchive-3.6.2/libarchive/archive_version_details.c +151 -0
  162. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_virtual.c +85 -16
  163. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_windows.c +214 -541
  164. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_windows.h +74 -106
  165. data/ext/libarchive-3.6.2/libarchive/archive_write.c +828 -0
  166. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter.c +72 -0
  167. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_b64encode.c +304 -0
  168. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_by_name.c +77 -0
  169. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_bzip2.c +401 -0
  170. data/ext/{libarchive-2.8.4/libarchive/archive_write_set_compression_compress.c → libarchive-3.6.2/libarchive/archive_write_add_filter_compress.c} +86 -131
  171. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_grzip.c +135 -0
  172. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_gzip.c +442 -0
  173. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_lrzip.c +197 -0
  174. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_lz4.c +700 -0
  175. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_lzop.c +478 -0
  176. data/ext/{libarchive-2.8.4/libarchive/archive_read_support_format_all.c → libarchive-3.6.2/libarchive/archive_write_add_filter_none.c} +11 -11
  177. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_program.c +391 -0
  178. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_uuencode.c +295 -0
  179. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_xz.c +545 -0
  180. data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_zstd.c +418 -0
  181. data/ext/libarchive-3.6.2/libarchive/archive_write_disk_posix.c +4711 -0
  182. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_disk_private.h +9 -2
  183. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_disk_set_standard_lookup.c +30 -29
  184. data/ext/libarchive-3.6.2/libarchive/archive_write_disk_windows.c +2842 -0
  185. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_open_fd.c +15 -10
  186. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_open_file.c +15 -9
  187. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_open_filename.c +128 -20
  188. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_open_memory.c +7 -18
  189. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_private.h +72 -29
  190. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format.c +56 -3
  191. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_7zip.c +2322 -0
  192. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_ar.c +54 -34
  193. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_by_name.c +20 -2
  194. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_cpio.c +11 -0
  195. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_cpio_binary.c +610 -0
  196. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_cpio_newc.c +457 -0
  197. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_cpio_odc.c +500 -0
  198. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_filter_by_ext.c +142 -0
  199. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_gnutar.c +755 -0
  200. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_iso9660.c +8165 -0
  201. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_mtree.c +2217 -0
  202. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_pax.c +1049 -387
  203. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_private.h +42 -0
  204. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_raw.c +125 -0
  205. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_shar.c +62 -47
  206. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_ustar.c +279 -108
  207. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_v7tar.c +638 -0
  208. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_warc.c +453 -0
  209. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_xar.c +3259 -0
  210. data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_zip.c +1704 -0
  211. data/ext/libarchive-3.6.2/libarchive/archive_write_set_options.c +130 -0
  212. data/ext/libarchive-3.6.2/libarchive/archive_write_set_passphrase.c +95 -0
  213. data/ext/libarchive-3.6.2/libarchive/archive_xxhash.h +48 -0
  214. data/ext/libarchive-3.6.2/libarchive/config_freebsd.h +271 -0
  215. data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/filter_fork.h +10 -5
  216. data/ext/{libarchive-2.8.4/libarchive/filter_fork.c → libarchive-3.6.2/libarchive/filter_fork_posix.c} +98 -19
  217. data/ext/libarchive-3.6.2/libarchive/filter_fork_windows.c +236 -0
  218. data/ext/libarchive-3.6.2/libarchive/xxhash.c +525 -0
  219. data/ext/libarchive-static-makefile +144 -80
  220. data/ext/libarchive-static-wrapper-makefile +1 -1
  221. data/ext/zlib-1.2.13/Makefile.in +404 -0
  222. data/ext/{zlib-1.2.5 → zlib-1.2.13}/adler32.c +51 -34
  223. data/ext/{zlib-1.2.5 → zlib-1.2.13}/compress.c +27 -21
  224. data/ext/zlib-1.2.13/configure +922 -0
  225. data/ext/zlib-1.2.13/crc32.c +1125 -0
  226. data/ext/zlib-1.2.13/crc32.h +9446 -0
  227. data/ext/{zlib-1.2.5 → zlib-1.2.13}/deflate.c +842 -459
  228. data/ext/{zlib-1.2.5 → zlib-1.2.13}/deflate.h +37 -33
  229. data/ext/{zlib-1.2.5 → zlib-1.2.13}/gzclose.c +0 -0
  230. data/ext/{zlib-1.2.5 → zlib-1.2.13}/gzguts.h +103 -16
  231. data/ext/{zlib-1.2.5 → zlib-1.2.13}/gzlib.c +155 -53
  232. data/ext/zlib-1.2.13/gzread.c +650 -0
  233. data/ext/zlib-1.2.13/gzwrite.c +677 -0
  234. data/ext/{zlib-1.2.5 → zlib-1.2.13}/infback.c +24 -12
  235. data/ext/{zlib-1.2.5 → zlib-1.2.13}/inffast.c +49 -66
  236. data/ext/{zlib-1.2.5 → zlib-1.2.13}/inffast.h +0 -0
  237. data/ext/{zlib-1.2.5 → zlib-1.2.13}/inffixed.h +3 -3
  238. data/ext/{zlib-1.2.5 → zlib-1.2.13}/inflate.c +209 -94
  239. data/ext/{zlib-1.2.5 → zlib-1.2.13}/inflate.h +9 -5
  240. data/ext/{zlib-1.2.5 → zlib-1.2.13}/inftrees.c +24 -50
  241. data/ext/{zlib-1.2.5 → zlib-1.2.13}/inftrees.h +1 -1
  242. data/ext/{zlib-1.2.5 → zlib-1.2.13}/trees.c +135 -198
  243. data/ext/{zlib-1.2.5 → zlib-1.2.13}/trees.h +0 -0
  244. data/ext/zlib-1.2.13/uncompr.c +93 -0
  245. data/ext/{zlib-1.2.5 → zlib-1.2.13}/zconf.h +182 -63
  246. data/ext/{zlib-1.2.5 → zlib-1.2.13}/zlib.h +617 -295
  247. data/ext/{zlib-1.2.5 → zlib-1.2.13}/zutil.c +50 -41
  248. data/ext/{zlib-1.2.5 → zlib-1.2.13}/zutil.h +83 -82
  249. metadata +241 -133
  250. data/ext/libarchive-0.1.1/libarchive.c +0 -1762
  251. data/ext/libarchive-2.8.4/Makefile.in +0 -7076
  252. data/ext/libarchive-2.8.4/build/autoconf/compile +0 -143
  253. data/ext/libarchive-2.8.4/build/autoconf/config.guess +0 -1502
  254. data/ext/libarchive-2.8.4/build/autoconf/config.sub +0 -1708
  255. data/ext/libarchive-2.8.4/build/autoconf/depcomp +0 -630
  256. data/ext/libarchive-2.8.4/build/autoconf/install-sh +0 -291
  257. data/ext/libarchive-2.8.4/build/autoconf/ltmain.sh +0 -8406
  258. data/ext/libarchive-2.8.4/build/autoconf/missing +0 -376
  259. data/ext/libarchive-2.8.4/config.h.in +0 -772
  260. data/ext/libarchive-2.8.4/configure +0 -17916
  261. data/ext/libarchive-2.8.4/libarchive/archive.h +0 -741
  262. data/ext/libarchive-2.8.4/libarchive/archive_entry.c +0 -2202
  263. data/ext/libarchive-2.8.4/libarchive/archive_hash.h +0 -281
  264. data/ext/libarchive-2.8.4/libarchive/archive_read.c +0 -1249
  265. data/ext/libarchive-2.8.4/libarchive/archive_read_disk.c +0 -198
  266. data/ext/libarchive-2.8.4/libarchive/archive_read_disk_entry_from_file.c +0 -570
  267. data/ext/libarchive-2.8.4/libarchive/archive_read_open_filename.c +0 -272
  268. data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_cpio.c +0 -777
  269. data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_mtree.c +0 -1304
  270. data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_zip.c +0 -903
  271. data/ext/libarchive-2.8.4/libarchive/archive_string.c +0 -453
  272. data/ext/libarchive-2.8.4/libarchive/archive_string.h +0 -148
  273. data/ext/libarchive-2.8.4/libarchive/archive_util.c +0 -391
  274. data/ext/libarchive-2.8.4/libarchive/archive_write.c +0 -466
  275. data/ext/libarchive-2.8.4/libarchive/archive_write_disk.c +0 -2628
  276. data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_bzip2.c +0 -408
  277. data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_gzip.c +0 -477
  278. data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_none.c +0 -257
  279. data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_program.c +0 -347
  280. data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_xz.c +0 -438
  281. data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_cpio.c +0 -344
  282. data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_cpio_newc.c +0 -295
  283. data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_mtree.c +0 -1050
  284. data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_zip.c +0 -667
  285. data/ext/libarchive-2.8.4/libarchive/config_freebsd.h +0 -154
  286. data/ext/libarchive-2.8.4/libarchive/filter_fork_windows.c +0 -113
  287. data/ext/zlib-1.2.5/Makefile.in +0 -257
  288. data/ext/zlib-1.2.5/configure +0 -596
  289. data/ext/zlib-1.2.5/crc32.c +0 -442
  290. data/ext/zlib-1.2.5/crc32.h +0 -441
  291. data/ext/zlib-1.2.5/example.c +0 -565
  292. data/ext/zlib-1.2.5/gzread.c +0 -653
  293. data/ext/zlib-1.2.5/gzwrite.c +0 -531
  294. data/ext/zlib-1.2.5/minigzip.c +0 -440
  295. data/ext/zlib-1.2.5/uncompr.c +0 -59
@@ -0,0 +1,2479 @@
1
+ /*-
2
+ * Copyright (c) 2003-2009 Tim Kientzle
3
+ * Copyright (c) 2010-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
+ #include "archive_platform.h"
28
+ __FBSDID("$FreeBSD$");
29
+
30
+ #if defined(_WIN32) && !defined(__CYGWIN__)
31
+
32
+ #ifdef HAVE_ERRNO_H
33
+ #include <errno.h>
34
+ #endif
35
+ #ifdef HAVE_STDLIB_H
36
+ #include <stdlib.h>
37
+ #endif
38
+ #include <winioctl.h>
39
+
40
+ #include "archive.h"
41
+ #include "archive_string.h"
42
+ #include "archive_entry.h"
43
+ #include "archive_private.h"
44
+ #include "archive_read_disk_private.h"
45
+
46
+ #ifndef O_BINARY
47
+ #define O_BINARY 0
48
+ #endif
49
+ #ifndef IO_REPARSE_TAG_SYMLINK
50
+ /* Old SDKs do not provide IO_REPARSE_TAG_SYMLINK */
51
+ #define IO_REPARSE_TAG_SYMLINK 0xA000000CL
52
+ #endif
53
+
54
+ /*-
55
+ * This is a new directory-walking system that addresses a number
56
+ * of problems I've had with fts(3). In particular, it has no
57
+ * pathname-length limits (other than the size of 'int'), handles
58
+ * deep logical traversals, uses considerably less memory, and has
59
+ * an opaque interface (easier to modify in the future).
60
+ *
61
+ * Internally, it keeps a single list of "tree_entry" items that
62
+ * represent filesystem objects that require further attention.
63
+ * Non-directories are not kept in memory: they are pulled from
64
+ * readdir(), returned to the client, then freed as soon as possible.
65
+ * Any directory entry to be traversed gets pushed onto the stack.
66
+ *
67
+ * There is surprisingly little information that needs to be kept for
68
+ * each item on the stack. Just the name, depth (represented here as the
69
+ * string length of the parent directory's pathname), and some markers
70
+ * indicating how to get back to the parent (via chdir("..") for a
71
+ * regular dir or via fchdir(2) for a symlink).
72
+ */
73
+
74
+ struct restore_time {
75
+ const wchar_t *full_path;
76
+ FILETIME lastWriteTime;
77
+ FILETIME lastAccessTime;
78
+ mode_t filetype;
79
+ };
80
+
81
+ struct tree_entry {
82
+ int depth;
83
+ struct tree_entry *next;
84
+ struct tree_entry *parent;
85
+ size_t full_path_dir_length;
86
+ struct archive_wstring name;
87
+ struct archive_wstring full_path;
88
+ size_t dirname_length;
89
+ int64_t dev;
90
+ int64_t ino;
91
+ int flags;
92
+ int filesystem_id;
93
+ /* How to restore time of a directory. */
94
+ struct restore_time restore_time;
95
+ };
96
+
97
+ struct filesystem {
98
+ int64_t dev;
99
+ int synthetic;
100
+ int remote;
101
+ DWORD bytesPerSector;
102
+ };
103
+
104
+ /* Definitions for tree_entry.flags bitmap. */
105
+ #define isDir 1 /* This entry is a regular directory. */
106
+ #define isDirLink 2 /* This entry is a symbolic link to a directory. */
107
+ #define needsFirstVisit 4 /* This is an initial entry. */
108
+ #define needsDescent 8 /* This entry needs to be previsited. */
109
+ #define needsOpen 16 /* This is a directory that needs to be opened. */
110
+ #define needsAscent 32 /* This entry needs to be postvisited. */
111
+
112
+ /*
113
+ * On Windows, "first visit" is handled as a pattern to be handed to
114
+ * _findfirst(). This is consistent with Windows conventions that
115
+ * file patterns are handled within the application. On Posix,
116
+ * "first visit" is just returned to the client.
117
+ */
118
+
119
+ #define MAX_OVERLAPPED 8
120
+ #define READ_BUFFER_SIZE (1024 * 64) /* Default to 64KB per https://technet.microsoft.com/en-us/library/cc938632.aspx */
121
+ #define DIRECT_IO 0/* Disabled */
122
+ #define ASYNC_IO 1/* Enabled */
123
+
124
+ /*
125
+ * Local data for this package.
126
+ */
127
+ struct tree {
128
+ struct tree_entry *stack;
129
+ struct tree_entry *current;
130
+ HANDLE d;
131
+ WIN32_FIND_DATAW _findData;
132
+ WIN32_FIND_DATAW *findData;
133
+ int flags;
134
+ int visit_type;
135
+ /* Error code from last failed operation. */
136
+ int tree_errno;
137
+
138
+ /* A full path with "\\?\" prefix. */
139
+ struct archive_wstring full_path;
140
+ size_t full_path_dir_length;
141
+ /* Dynamically-sized buffer for holding path */
142
+ struct archive_wstring path;
143
+
144
+ /* Last path element */
145
+ const wchar_t *basename;
146
+ /* Leading dir length */
147
+ size_t dirname_length;
148
+
149
+ int depth;
150
+
151
+ BY_HANDLE_FILE_INFORMATION lst;
152
+ BY_HANDLE_FILE_INFORMATION st;
153
+ int descend;
154
+ /* How to restore time of a file. */
155
+ struct restore_time restore_time;
156
+
157
+ struct entry_sparse {
158
+ int64_t length;
159
+ int64_t offset;
160
+ } *sparse_list, *current_sparse;
161
+ int sparse_count;
162
+ int sparse_list_size;
163
+
164
+ char initial_symlink_mode;
165
+ char symlink_mode;
166
+ struct filesystem *current_filesystem;
167
+ struct filesystem *filesystem_table;
168
+ int initial_filesystem_id;
169
+ int current_filesystem_id;
170
+ int max_filesystem_id;
171
+ int allocated_filesystem;
172
+
173
+ HANDLE entry_fh;
174
+ int entry_eof;
175
+ int64_t entry_remaining_bytes;
176
+ int64_t entry_total;
177
+
178
+ int ol_idx_doing;
179
+ int ol_idx_done;
180
+ int ol_num_doing;
181
+ int ol_num_done;
182
+ int64_t ol_remaining_bytes;
183
+ int64_t ol_total;
184
+ struct la_overlapped {
185
+ OVERLAPPED ol;
186
+ struct archive * _a;
187
+ unsigned char *buff;
188
+ size_t buff_size;
189
+ int64_t offset;
190
+ size_t bytes_expected;
191
+ size_t bytes_transferred;
192
+ } ol[MAX_OVERLAPPED];
193
+ int direct_io;
194
+ int async_io;
195
+ };
196
+
197
+ #define bhfi_dev(bhfi) ((bhfi)->dwVolumeSerialNumber)
198
+ /* Treat FileIndex as i-node. We should remove a sequence number
199
+ * which is high-16-bits of nFileIndexHigh. */
200
+ #define bhfi_ino(bhfi) \
201
+ ((((int64_t)((bhfi)->nFileIndexHigh & 0x0000FFFFUL)) << 32) \
202
+ + (bhfi)->nFileIndexLow)
203
+
204
+ /* Definitions for tree.flags bitmap. */
205
+ #define hasStat 16 /* The st entry is valid. */
206
+ #define hasLstat 32 /* The lst entry is valid. */
207
+ #define needsRestoreTimes 128
208
+
209
+ static int
210
+ tree_dir_next_windows(struct tree *t, const wchar_t *pattern);
211
+
212
+ /* Initiate/terminate a tree traversal. */
213
+ static struct tree *tree_open(const wchar_t *, int, int);
214
+ static struct tree *tree_reopen(struct tree *, const wchar_t *, int);
215
+ static void tree_close(struct tree *);
216
+ static void tree_free(struct tree *);
217
+ static void tree_push(struct tree *, const wchar_t *, const wchar_t *,
218
+ int, int64_t, int64_t, struct restore_time *);
219
+
220
+ /*
221
+ * tree_next() returns Zero if there is no next entry, non-zero if
222
+ * there is. Note that directories are visited three times.
223
+ * Directories are always visited first as part of enumerating their
224
+ * parent; that is a "regular" visit. If tree_descend() is invoked at
225
+ * that time, the directory is added to a work list and will
226
+ * subsequently be visited two more times: once just after descending
227
+ * into the directory ("postdescent") and again just after ascending
228
+ * back to the parent ("postascent").
229
+ *
230
+ * TREE_ERROR_DIR is returned if the descent failed (because the
231
+ * directory couldn't be opened, for instance). This is returned
232
+ * instead of TREE_POSTDESCENT/TREE_POSTASCENT. TREE_ERROR_DIR is not a
233
+ * fatal error, but it does imply that the relevant subtree won't be
234
+ * visited. TREE_ERROR_FATAL is returned for an error that left the
235
+ * traversal completely hosed. Right now, this is only returned for
236
+ * chdir() failures during ascent.
237
+ */
238
+ #define TREE_REGULAR 1
239
+ #define TREE_POSTDESCENT 2
240
+ #define TREE_POSTASCENT 3
241
+ #define TREE_ERROR_DIR -1
242
+ #define TREE_ERROR_FATAL -2
243
+
244
+ static int tree_next(struct tree *);
245
+
246
+ /*
247
+ * Return information about the current entry.
248
+ */
249
+
250
+ /*
251
+ * The current full pathname, length of the full pathname, and a name
252
+ * that can be used to access the file. Because tree does use chdir
253
+ * extensively, the access path is almost never the same as the full
254
+ * current path.
255
+ *
256
+ */
257
+ static const wchar_t *tree_current_path(struct tree *);
258
+ static const wchar_t *tree_current_access_path(struct tree *);
259
+
260
+ /*
261
+ * Request the lstat() or stat() data for the current path. Since the
262
+ * tree package needs to do some of this anyway, and caches the
263
+ * results, you should take advantage of it here if you need it rather
264
+ * than make a redundant stat() or lstat() call of your own.
265
+ */
266
+ static const BY_HANDLE_FILE_INFORMATION *tree_current_stat(struct tree *);
267
+ static const BY_HANDLE_FILE_INFORMATION *tree_current_lstat(struct tree *);
268
+
269
+ /* The following functions use tricks to avoid a certain number of
270
+ * stat()/lstat() calls. */
271
+ /* "is_physical_dir" is equivalent to S_ISDIR(tree_current_lstat()->st_mode) */
272
+ static int tree_current_is_physical_dir(struct tree *);
273
+ /* "is_physical_link" is equivalent to S_ISLNK(tree_current_lstat()->st_mode) */
274
+ static int tree_current_is_physical_link(struct tree *);
275
+ /* Instead of archive_entry_copy_stat for BY_HANDLE_FILE_INFORMATION */
276
+ static void tree_archive_entry_copy_bhfi(struct archive_entry *,
277
+ struct tree *, const BY_HANDLE_FILE_INFORMATION *);
278
+ /* "is_dir" is equivalent to S_ISDIR(tree_current_stat()->st_mode) */
279
+ static int tree_current_is_dir(struct tree *);
280
+ static int update_current_filesystem(struct archive_read_disk *a,
281
+ int64_t dev);
282
+ static int setup_current_filesystem(struct archive_read_disk *);
283
+ static int tree_target_is_same_as_parent(struct tree *,
284
+ const BY_HANDLE_FILE_INFORMATION *);
285
+
286
+ static int _archive_read_disk_open_w(struct archive *, const wchar_t *);
287
+ static int _archive_read_free(struct archive *);
288
+ static int _archive_read_close(struct archive *);
289
+ static int _archive_read_data_block(struct archive *,
290
+ const void **, size_t *, int64_t *);
291
+ static int _archive_read_next_header(struct archive *,
292
+ struct archive_entry **);
293
+ static int _archive_read_next_header2(struct archive *,
294
+ struct archive_entry *);
295
+ static const char *trivial_lookup_gname(void *, int64_t gid);
296
+ static const char *trivial_lookup_uname(void *, int64_t uid);
297
+ static int setup_sparse(struct archive_read_disk *, struct archive_entry *);
298
+ static int close_and_restore_time(HANDLE, struct tree *,
299
+ struct restore_time *);
300
+ static int setup_sparse_from_disk(struct archive_read_disk *,
301
+ struct archive_entry *, HANDLE);
302
+ static int la_linkname_from_handle(HANDLE, wchar_t **, int *);
303
+ static int la_linkname_from_pathw(const wchar_t *, wchar_t **, int *);
304
+ static void entry_symlink_from_pathw(struct archive_entry *,
305
+ const wchar_t *path);
306
+
307
+ typedef struct _REPARSE_DATA_BUFFER {
308
+ ULONG ReparseTag;
309
+ USHORT ReparseDataLength;
310
+ USHORT Reserved;
311
+ union {
312
+ struct {
313
+ USHORT SubstituteNameOffset;
314
+ USHORT SubstituteNameLength;
315
+ USHORT PrintNameOffset;
316
+ USHORT PrintNameLength;
317
+ ULONG Flags;
318
+ WCHAR PathBuffer[1];
319
+ } SymbolicLinkReparseBuffer;
320
+ struct {
321
+ USHORT SubstituteNameOffset;
322
+ USHORT SubstituteNameLength;
323
+ USHORT PrintNameOffset;
324
+ USHORT PrintNameLength;
325
+ WCHAR PathBuffer[1];
326
+ } MountPointReparseBuffer;
327
+ struct {
328
+ UCHAR DataBuffer[1];
329
+ } GenericReparseBuffer;
330
+ } DUMMYUNIONNAME;
331
+ } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
332
+
333
+ /*
334
+ * Reads the target of a symbolic link
335
+ *
336
+ * Returns 0 on success and -1 on failure
337
+ * outbuf is allocated in the function
338
+ */
339
+ static int
340
+ la_linkname_from_handle(HANDLE h, wchar_t **linkname, int *linktype)
341
+ {
342
+ DWORD inbytes;
343
+ REPARSE_DATA_BUFFER *buf;
344
+ BY_HANDLE_FILE_INFORMATION st;
345
+ size_t len;
346
+ BOOL ret;
347
+ BYTE *indata;
348
+ wchar_t *tbuf;
349
+
350
+ ret = GetFileInformationByHandle(h, &st);
351
+ if (ret == 0 ||
352
+ (st.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
353
+ return (-1);
354
+ }
355
+
356
+ indata = malloc(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
357
+ ret = DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, indata,
358
+ 1024, &inbytes, NULL);
359
+ if (ret == 0) {
360
+ la_dosmaperr(GetLastError());
361
+ free(indata);
362
+ return (-1);
363
+ }
364
+
365
+ buf = (REPARSE_DATA_BUFFER *) indata;
366
+ if (buf->ReparseTag != IO_REPARSE_TAG_SYMLINK) {
367
+ free(indata);
368
+ /* File is not a symbolic link */
369
+ errno = EINVAL;
370
+ return (-1);
371
+ }
372
+
373
+ len = buf->SymbolicLinkReparseBuffer.SubstituteNameLength;
374
+ if (len <= 0) {
375
+ free(indata);
376
+ return (-1);
377
+ }
378
+
379
+ tbuf = malloc(len + 1 * sizeof(wchar_t));
380
+ if (tbuf == NULL) {
381
+ free(indata);
382
+ return (-1);
383
+ }
384
+
385
+ memcpy(tbuf, &((BYTE *)buf->SymbolicLinkReparseBuffer.PathBuffer)
386
+ [buf->SymbolicLinkReparseBuffer.SubstituteNameOffset], len);
387
+ free(indata);
388
+
389
+ tbuf[len / sizeof(wchar_t)] = L'\0';
390
+
391
+ *linkname = tbuf;
392
+
393
+ /*
394
+ * Translate backslashes to slashes for libarchive internal use
395
+ */
396
+ while(*tbuf != L'\0') {
397
+ if (*tbuf == L'\\')
398
+ *tbuf = L'/';
399
+ tbuf++;
400
+ }
401
+
402
+ if ((st.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
403
+ *linktype = AE_SYMLINK_TYPE_FILE;
404
+ else
405
+ *linktype = AE_SYMLINK_TYPE_DIRECTORY;
406
+
407
+ return (0);
408
+ }
409
+
410
+ /*
411
+ * Returns AE_SYMLINK_TYPE_FILE, AE_SYMLINK_TYPE_DIRECTORY or -1 on error
412
+ */
413
+ static int
414
+ la_linkname_from_pathw(const wchar_t *path, wchar_t **outbuf, int *linktype)
415
+ {
416
+ HANDLE h;
417
+ const DWORD flag = FILE_FLAG_BACKUP_SEMANTICS |
418
+ FILE_FLAG_OPEN_REPARSE_POINT;
419
+ int ret;
420
+
421
+ h = CreateFileW(path, 0,
422
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
423
+ OPEN_EXISTING, flag, NULL);
424
+ if (h == INVALID_HANDLE_VALUE) {
425
+ la_dosmaperr(GetLastError());
426
+ return (-1);
427
+ }
428
+
429
+ ret = la_linkname_from_handle(h, outbuf, linktype);
430
+ CloseHandle(h);
431
+
432
+ return (ret);
433
+ }
434
+
435
+ static void
436
+ entry_symlink_from_pathw(struct archive_entry *entry, const wchar_t *path)
437
+ {
438
+ wchar_t *linkname = NULL;
439
+ int ret, linktype;
440
+
441
+ ret = la_linkname_from_pathw(path, &linkname, &linktype);
442
+ if (ret != 0)
443
+ return;
444
+ if (linktype >= 0) {
445
+ archive_entry_copy_symlink_w(entry, linkname);
446
+ archive_entry_set_symlink_type(entry, linktype);
447
+ }
448
+ free(linkname);
449
+
450
+ return;
451
+ }
452
+
453
+ static const struct archive_vtable
454
+ archive_read_disk_vtable = {
455
+ .archive_free = _archive_read_free,
456
+ .archive_close = _archive_read_close,
457
+ .archive_read_data_block = _archive_read_data_block,
458
+ .archive_read_next_header = _archive_read_next_header,
459
+ .archive_read_next_header2 = _archive_read_next_header2,
460
+ };
461
+
462
+ const char *
463
+ archive_read_disk_gname(struct archive *_a, la_int64_t gid)
464
+ {
465
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
466
+ if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
467
+ ARCHIVE_STATE_ANY, "archive_read_disk_gname"))
468
+ return (NULL);
469
+ if (a->lookup_gname == NULL)
470
+ return (NULL);
471
+ return ((*a->lookup_gname)(a->lookup_gname_data, gid));
472
+ }
473
+
474
+ const char *
475
+ archive_read_disk_uname(struct archive *_a, la_int64_t uid)
476
+ {
477
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
478
+ if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
479
+ ARCHIVE_STATE_ANY, "archive_read_disk_uname"))
480
+ return (NULL);
481
+ if (a->lookup_uname == NULL)
482
+ return (NULL);
483
+ return ((*a->lookup_uname)(a->lookup_uname_data, uid));
484
+ }
485
+
486
+ int
487
+ archive_read_disk_set_gname_lookup(struct archive *_a,
488
+ void *private_data,
489
+ const char * (*lookup_gname)(void *private, la_int64_t gid),
490
+ void (*cleanup_gname)(void *private))
491
+ {
492
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
493
+ archive_check_magic(&a->archive, ARCHIVE_READ_DISK_MAGIC,
494
+ ARCHIVE_STATE_ANY, "archive_read_disk_set_gname_lookup");
495
+
496
+ if (a->cleanup_gname != NULL && a->lookup_gname_data != NULL)
497
+ (a->cleanup_gname)(a->lookup_gname_data);
498
+
499
+ a->lookup_gname = lookup_gname;
500
+ a->cleanup_gname = cleanup_gname;
501
+ a->lookup_gname_data = private_data;
502
+ return (ARCHIVE_OK);
503
+ }
504
+
505
+ int
506
+ archive_read_disk_set_uname_lookup(struct archive *_a,
507
+ void *private_data,
508
+ const char * (*lookup_uname)(void *private, int64_t uid),
509
+ void (*cleanup_uname)(void *private))
510
+ {
511
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
512
+ archive_check_magic(&a->archive, ARCHIVE_READ_DISK_MAGIC,
513
+ ARCHIVE_STATE_ANY, "archive_read_disk_set_uname_lookup");
514
+
515
+ if (a->cleanup_uname != NULL && a->lookup_uname_data != NULL)
516
+ (a->cleanup_uname)(a->lookup_uname_data);
517
+
518
+ a->lookup_uname = lookup_uname;
519
+ a->cleanup_uname = cleanup_uname;
520
+ a->lookup_uname_data = private_data;
521
+ return (ARCHIVE_OK);
522
+ }
523
+
524
+ /*
525
+ * Create a new archive_read_disk object and initialize it with global state.
526
+ */
527
+ struct archive *
528
+ archive_read_disk_new(void)
529
+ {
530
+ struct archive_read_disk *a;
531
+
532
+ a = (struct archive_read_disk *)calloc(1, sizeof(*a));
533
+ if (a == NULL)
534
+ return (NULL);
535
+ a->archive.magic = ARCHIVE_READ_DISK_MAGIC;
536
+ a->archive.state = ARCHIVE_STATE_NEW;
537
+ a->archive.vtable = &archive_read_disk_vtable;
538
+ a->entry = archive_entry_new2(&a->archive);
539
+ a->lookup_uname = trivial_lookup_uname;
540
+ a->lookup_gname = trivial_lookup_gname;
541
+ a->flags = ARCHIVE_READDISK_MAC_COPYFILE;
542
+ return (&a->archive);
543
+ }
544
+
545
+ static int
546
+ _archive_read_free(struct archive *_a)
547
+ {
548
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
549
+ int r;
550
+
551
+ if (_a == NULL)
552
+ return (ARCHIVE_OK);
553
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
554
+ ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_free");
555
+
556
+ if (a->archive.state != ARCHIVE_STATE_CLOSED)
557
+ r = _archive_read_close(&a->archive);
558
+ else
559
+ r = ARCHIVE_OK;
560
+
561
+ tree_free(a->tree);
562
+ if (a->cleanup_gname != NULL && a->lookup_gname_data != NULL)
563
+ (a->cleanup_gname)(a->lookup_gname_data);
564
+ if (a->cleanup_uname != NULL && a->lookup_uname_data != NULL)
565
+ (a->cleanup_uname)(a->lookup_uname_data);
566
+ archive_string_free(&a->archive.error_string);
567
+ archive_entry_free(a->entry);
568
+ a->archive.magic = 0;
569
+ free(a);
570
+ return (r);
571
+ }
572
+
573
+ static int
574
+ _archive_read_close(struct archive *_a)
575
+ {
576
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
577
+
578
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
579
+ ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_close");
580
+
581
+ if (a->archive.state != ARCHIVE_STATE_FATAL)
582
+ a->archive.state = ARCHIVE_STATE_CLOSED;
583
+
584
+ tree_close(a->tree);
585
+
586
+ return (ARCHIVE_OK);
587
+ }
588
+
589
+ static void
590
+ setup_symlink_mode(struct archive_read_disk *a, char symlink_mode,
591
+ int follow_symlinks)
592
+ {
593
+ a->symlink_mode = symlink_mode;
594
+ a->follow_symlinks = follow_symlinks;
595
+ if (a->tree != NULL) {
596
+ a->tree->initial_symlink_mode = a->symlink_mode;
597
+ a->tree->symlink_mode = a->symlink_mode;
598
+ }
599
+ }
600
+
601
+ int
602
+ archive_read_disk_set_symlink_logical(struct archive *_a)
603
+ {
604
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
605
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
606
+ ARCHIVE_STATE_ANY, "archive_read_disk_set_symlink_logical");
607
+ setup_symlink_mode(a, 'L', 1);
608
+ return (ARCHIVE_OK);
609
+ }
610
+
611
+ int
612
+ archive_read_disk_set_symlink_physical(struct archive *_a)
613
+ {
614
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
615
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
616
+ ARCHIVE_STATE_ANY, "archive_read_disk_set_symlink_physical");
617
+ setup_symlink_mode(a, 'P', 0);
618
+ return (ARCHIVE_OK);
619
+ }
620
+
621
+ int
622
+ archive_read_disk_set_symlink_hybrid(struct archive *_a)
623
+ {
624
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
625
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
626
+ ARCHIVE_STATE_ANY, "archive_read_disk_set_symlink_hybrid");
627
+ setup_symlink_mode(a, 'H', 1);/* Follow symlinks initially. */
628
+ return (ARCHIVE_OK);
629
+ }
630
+
631
+ int
632
+ archive_read_disk_set_atime_restored(struct archive *_a)
633
+ {
634
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
635
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
636
+ ARCHIVE_STATE_ANY, "archive_read_disk_restore_atime");
637
+ a->flags |= ARCHIVE_READDISK_RESTORE_ATIME;
638
+ if (a->tree != NULL)
639
+ a->tree->flags |= needsRestoreTimes;
640
+ return (ARCHIVE_OK);
641
+ }
642
+
643
+ int
644
+ archive_read_disk_set_behavior(struct archive *_a, int flags)
645
+ {
646
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
647
+ int r = ARCHIVE_OK;
648
+
649
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
650
+ ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump");
651
+
652
+ a->flags = flags;
653
+
654
+ if (flags & ARCHIVE_READDISK_RESTORE_ATIME)
655
+ r = archive_read_disk_set_atime_restored(_a);
656
+ else {
657
+ if (a->tree != NULL)
658
+ a->tree->flags &= ~needsRestoreTimes;
659
+ }
660
+ return (r);
661
+ }
662
+
663
+ /*
664
+ * Trivial implementations of gname/uname lookup functions.
665
+ * These are normally overridden by the client, but these stub
666
+ * versions ensure that we always have something that works.
667
+ */
668
+ static const char *
669
+ trivial_lookup_gname(void *private_data, int64_t gid)
670
+ {
671
+ (void)private_data; /* UNUSED */
672
+ (void)gid; /* UNUSED */
673
+ return (NULL);
674
+ }
675
+
676
+ static const char *
677
+ trivial_lookup_uname(void *private_data, int64_t uid)
678
+ {
679
+ (void)private_data; /* UNUSED */
680
+ (void)uid; /* UNUSED */
681
+ return (NULL);
682
+ }
683
+
684
+ static int64_t
685
+ align_num_per_sector(struct tree *t, int64_t size)
686
+ {
687
+ int64_t surplus;
688
+
689
+ size += t->current_filesystem->bytesPerSector -1;
690
+ surplus = size % t->current_filesystem->bytesPerSector;
691
+ size -= surplus;
692
+ return (size);
693
+ }
694
+
695
+ static int
696
+ start_next_async_read(struct archive_read_disk *a, struct tree *t)
697
+ {
698
+ struct la_overlapped *olp;
699
+ DWORD buffbytes, rbytes;
700
+
701
+ if (t->ol_remaining_bytes == 0)
702
+ return (ARCHIVE_EOF);
703
+
704
+ olp = &(t->ol[t->ol_idx_doing]);
705
+ t->ol_idx_doing = (t->ol_idx_doing + 1) % MAX_OVERLAPPED;
706
+
707
+ /* Allocate read buffer. */
708
+ if (olp->buff == NULL) {
709
+ void *p;
710
+ size_t s = (size_t)align_num_per_sector(t, READ_BUFFER_SIZE);
711
+ p = VirtualAlloc(NULL, s, MEM_COMMIT, PAGE_READWRITE);
712
+ if (p == NULL) {
713
+ archive_set_error(&a->archive, ENOMEM,
714
+ "Couldn't allocate memory");
715
+ a->archive.state = ARCHIVE_STATE_FATAL;
716
+ return (ARCHIVE_FATAL);
717
+ }
718
+ olp->buff = p;
719
+ olp->buff_size = s;
720
+ olp->_a = &a->archive;
721
+ olp->ol.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
722
+ if (olp->ol.hEvent == NULL) {
723
+ la_dosmaperr(GetLastError());
724
+ archive_set_error(&a->archive, errno,
725
+ "CreateEvent failed");
726
+ a->archive.state = ARCHIVE_STATE_FATAL;
727
+ return (ARCHIVE_FATAL);
728
+ }
729
+ } else
730
+ ResetEvent(olp->ol.hEvent);
731
+
732
+ buffbytes = (DWORD)olp->buff_size;
733
+ if (buffbytes > t->current_sparse->length)
734
+ buffbytes = (DWORD)t->current_sparse->length;
735
+
736
+ /* Skip hole. */
737
+ if (t->current_sparse->offset > t->ol_total) {
738
+ t->ol_remaining_bytes -=
739
+ t->current_sparse->offset - t->ol_total;
740
+ }
741
+
742
+ olp->offset = t->current_sparse->offset;
743
+ olp->ol.Offset = (DWORD)(olp->offset & 0xffffffff);
744
+ olp->ol.OffsetHigh = (DWORD)(olp->offset >> 32);
745
+
746
+ if (t->ol_remaining_bytes > buffbytes) {
747
+ olp->bytes_expected = buffbytes;
748
+ t->ol_remaining_bytes -= buffbytes;
749
+ } else {
750
+ olp->bytes_expected = (size_t)t->ol_remaining_bytes;
751
+ t->ol_remaining_bytes = 0;
752
+ }
753
+ olp->bytes_transferred = 0;
754
+ t->current_sparse->offset += buffbytes;
755
+ t->current_sparse->length -= buffbytes;
756
+ t->ol_total = t->current_sparse->offset;
757
+ if (t->current_sparse->length == 0 && t->ol_remaining_bytes > 0)
758
+ t->current_sparse++;
759
+
760
+ if (!ReadFile(t->entry_fh, olp->buff, buffbytes, &rbytes, &(olp->ol))) {
761
+ DWORD lasterr;
762
+
763
+ lasterr = GetLastError();
764
+ if (lasterr == ERROR_HANDLE_EOF) {
765
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
766
+ "Reading file truncated");
767
+ a->archive.state = ARCHIVE_STATE_FATAL;
768
+ return (ARCHIVE_FATAL);
769
+ } else if (lasterr != ERROR_IO_PENDING) {
770
+ if (lasterr == ERROR_NO_DATA)
771
+ errno = EAGAIN;
772
+ else if (lasterr == ERROR_ACCESS_DENIED)
773
+ errno = EBADF;
774
+ else
775
+ la_dosmaperr(lasterr);
776
+ archive_set_error(&a->archive, errno, "Read error");
777
+ a->archive.state = ARCHIVE_STATE_FATAL;
778
+ return (ARCHIVE_FATAL);
779
+ }
780
+ } else
781
+ olp->bytes_transferred = rbytes;
782
+ t->ol_num_doing++;
783
+
784
+ return (t->ol_remaining_bytes == 0)? ARCHIVE_EOF: ARCHIVE_OK;
785
+ }
786
+
787
+ static void
788
+ cancel_async(struct tree *t)
789
+ {
790
+ if (t->ol_num_doing != t->ol_num_done) {
791
+ CancelIo(t->entry_fh);
792
+ t->ol_num_doing = t->ol_num_done = 0;
793
+ }
794
+ }
795
+
796
+ static int
797
+ _archive_read_data_block(struct archive *_a, const void **buff,
798
+ size_t *size, int64_t *offset)
799
+ {
800
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
801
+ struct tree *t = a->tree;
802
+ struct la_overlapped *olp;
803
+ DWORD bytes_transferred;
804
+ int r = ARCHIVE_FATAL;
805
+
806
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
807
+ "archive_read_data_block");
808
+
809
+ if (t->entry_eof || t->entry_remaining_bytes <= 0) {
810
+ r = ARCHIVE_EOF;
811
+ goto abort_read_data;
812
+ }
813
+
814
+ /*
815
+ * Make a request to read the file in asynchronous.
816
+ */
817
+ if (t->ol_num_doing == 0) {
818
+ do {
819
+ r = start_next_async_read(a, t);
820
+ if (r == ARCHIVE_FATAL)
821
+ goto abort_read_data;
822
+ if (!t->async_io)
823
+ break;
824
+ } while (r == ARCHIVE_OK && t->ol_num_doing < MAX_OVERLAPPED);
825
+ } else {
826
+ if ((r = start_next_async_read(a, t)) == ARCHIVE_FATAL)
827
+ goto abort_read_data;
828
+ }
829
+
830
+ olp = &(t->ol[t->ol_idx_done]);
831
+ t->ol_idx_done = (t->ol_idx_done + 1) % MAX_OVERLAPPED;
832
+ if (olp->bytes_transferred)
833
+ bytes_transferred = (DWORD)olp->bytes_transferred;
834
+ else if (!GetOverlappedResult(t->entry_fh, &(olp->ol),
835
+ &bytes_transferred, TRUE)) {
836
+ la_dosmaperr(GetLastError());
837
+ archive_set_error(&a->archive, errno,
838
+ "GetOverlappedResult failed");
839
+ a->archive.state = ARCHIVE_STATE_FATAL;
840
+ r = ARCHIVE_FATAL;
841
+ goto abort_read_data;
842
+ }
843
+ t->ol_num_done++;
844
+
845
+ if (bytes_transferred == 0 ||
846
+ olp->bytes_expected != bytes_transferred) {
847
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
848
+ "Reading file truncated");
849
+ a->archive.state = ARCHIVE_STATE_FATAL;
850
+ r = ARCHIVE_FATAL;
851
+ goto abort_read_data;
852
+ }
853
+
854
+ *buff = olp->buff;
855
+ *size = bytes_transferred;
856
+ *offset = olp->offset;
857
+ if (olp->offset > t->entry_total)
858
+ t->entry_remaining_bytes -= olp->offset - t->entry_total;
859
+ t->entry_total = olp->offset + *size;
860
+ t->entry_remaining_bytes -= *size;
861
+ if (t->entry_remaining_bytes == 0) {
862
+ /* Close the current file descriptor */
863
+ close_and_restore_time(t->entry_fh, t, &t->restore_time);
864
+ t->entry_fh = INVALID_HANDLE_VALUE;
865
+ t->entry_eof = 1;
866
+ }
867
+ return (ARCHIVE_OK);
868
+
869
+ abort_read_data:
870
+ *buff = NULL;
871
+ *size = 0;
872
+ *offset = t->entry_total;
873
+ if (t->entry_fh != INVALID_HANDLE_VALUE) {
874
+ cancel_async(t);
875
+ /* Close the current file descriptor */
876
+ close_and_restore_time(t->entry_fh, t, &t->restore_time);
877
+ t->entry_fh = INVALID_HANDLE_VALUE;
878
+ }
879
+ return (r);
880
+ }
881
+
882
+ static int
883
+ next_entry(struct archive_read_disk *a, struct tree *t,
884
+ struct archive_entry *entry)
885
+ {
886
+ const BY_HANDLE_FILE_INFORMATION *st;
887
+ const BY_HANDLE_FILE_INFORMATION *lst;
888
+ const char*name;
889
+ int descend, r;
890
+
891
+ st = NULL;
892
+ lst = NULL;
893
+ t->descend = 0;
894
+ do {
895
+ switch (tree_next(t)) {
896
+ case TREE_ERROR_FATAL:
897
+ archive_set_error(&a->archive, t->tree_errno,
898
+ "%ls: Unable to continue traversing directory tree",
899
+ tree_current_path(t));
900
+ a->archive.state = ARCHIVE_STATE_FATAL;
901
+ return (ARCHIVE_FATAL);
902
+ case TREE_ERROR_DIR:
903
+ archive_set_error(&a->archive, t->tree_errno,
904
+ "%ls: Couldn't visit directory",
905
+ tree_current_path(t));
906
+ return (ARCHIVE_FAILED);
907
+ case 0:
908
+ return (ARCHIVE_EOF);
909
+ case TREE_POSTDESCENT:
910
+ case TREE_POSTASCENT:
911
+ break;
912
+ case TREE_REGULAR:
913
+ lst = tree_current_lstat(t);
914
+ if (lst == NULL) {
915
+ archive_set_error(&a->archive, t->tree_errno,
916
+ "%ls: Cannot stat",
917
+ tree_current_path(t));
918
+ return (ARCHIVE_FAILED);
919
+ }
920
+ break;
921
+ }
922
+ } while (lst == NULL);
923
+
924
+ archive_entry_copy_pathname_w(entry, tree_current_path(t));
925
+
926
+ /*
927
+ * Perform path matching.
928
+ */
929
+ if (a->matching) {
930
+ r = archive_match_path_excluded(a->matching, entry);
931
+ if (r < 0) {
932
+ archive_set_error(&(a->archive), errno,
933
+ "Failed : %s", archive_error_string(a->matching));
934
+ return (r);
935
+ }
936
+ if (r) {
937
+ if (a->excluded_cb_func)
938
+ a->excluded_cb_func(&(a->archive),
939
+ a->excluded_cb_data, entry);
940
+ return (ARCHIVE_RETRY);
941
+ }
942
+ }
943
+
944
+ /*
945
+ * Distinguish 'L'/'P'/'H' symlink following.
946
+ */
947
+ switch(t->symlink_mode) {
948
+ case 'H':
949
+ /* 'H': After the first item, rest like 'P'. */
950
+ t->symlink_mode = 'P';
951
+ /* 'H': First item (from command line) like 'L'. */
952
+ /* FALLTHROUGH */
953
+ case 'L':
954
+ /* 'L': Do descend through a symlink to dir. */
955
+ descend = tree_current_is_dir(t);
956
+ /* 'L': Follow symlinks to files. */
957
+ a->symlink_mode = 'L';
958
+ a->follow_symlinks = 1;
959
+ /* 'L': Archive symlinks as targets, if we can. */
960
+ st = tree_current_stat(t);
961
+ if (st != NULL && !tree_target_is_same_as_parent(t, st))
962
+ break;
963
+ /* If stat fails, we have a broken symlink;
964
+ * in that case, don't follow the link. */
965
+ /* FALLTHROUGH */
966
+ default:
967
+ /* 'P': Don't descend through a symlink to dir. */
968
+ descend = tree_current_is_physical_dir(t);
969
+ /* 'P': Don't follow symlinks to files. */
970
+ a->symlink_mode = 'P';
971
+ a->follow_symlinks = 0;
972
+ /* 'P': Archive symlinks as symlinks. */
973
+ st = lst;
974
+ break;
975
+ }
976
+
977
+ if (update_current_filesystem(a, bhfi_dev(st)) != ARCHIVE_OK) {
978
+ a->archive.state = ARCHIVE_STATE_FATAL;
979
+ return (ARCHIVE_FATAL);
980
+ }
981
+ if (t->initial_filesystem_id == -1)
982
+ t->initial_filesystem_id = t->current_filesystem_id;
983
+ if (a->flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) {
984
+ if (t->initial_filesystem_id != t->current_filesystem_id)
985
+ return (ARCHIVE_RETRY);
986
+ }
987
+ t->descend = descend;
988
+
989
+ tree_archive_entry_copy_bhfi(entry, t, st);
990
+
991
+ /* Save the times to be restored. This must be in before
992
+ * calling archive_read_disk_descend() or any chance of it,
993
+ * especially, invoking a callback. */
994
+ t->restore_time.lastWriteTime = st->ftLastWriteTime;
995
+ t->restore_time.lastAccessTime = st->ftLastAccessTime;
996
+ t->restore_time.filetype = archive_entry_filetype(entry);
997
+
998
+ /*
999
+ * Perform time matching.
1000
+ */
1001
+ if (a->matching) {
1002
+ r = archive_match_time_excluded(a->matching, entry);
1003
+ if (r < 0) {
1004
+ archive_set_error(&(a->archive), errno,
1005
+ "Failed : %s", archive_error_string(a->matching));
1006
+ return (r);
1007
+ }
1008
+ if (r) {
1009
+ if (a->excluded_cb_func)
1010
+ a->excluded_cb_func(&(a->archive),
1011
+ a->excluded_cb_data, entry);
1012
+ return (ARCHIVE_RETRY);
1013
+ }
1014
+ }
1015
+
1016
+ /* Lookup uname/gname */
1017
+ name = archive_read_disk_uname(&(a->archive), archive_entry_uid(entry));
1018
+ if (name != NULL)
1019
+ archive_entry_copy_uname(entry, name);
1020
+ name = archive_read_disk_gname(&(a->archive), archive_entry_gid(entry));
1021
+ if (name != NULL)
1022
+ archive_entry_copy_gname(entry, name);
1023
+
1024
+ /*
1025
+ * Perform owner matching.
1026
+ */
1027
+ if (a->matching) {
1028
+ r = archive_match_owner_excluded(a->matching, entry);
1029
+ if (r < 0) {
1030
+ archive_set_error(&(a->archive), errno,
1031
+ "Failed : %s", archive_error_string(a->matching));
1032
+ return (r);
1033
+ }
1034
+ if (r) {
1035
+ if (a->excluded_cb_func)
1036
+ a->excluded_cb_func(&(a->archive),
1037
+ a->excluded_cb_data, entry);
1038
+ return (ARCHIVE_RETRY);
1039
+ }
1040
+ }
1041
+
1042
+ /*
1043
+ * File attributes
1044
+ */
1045
+ if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0) {
1046
+ const int supported_attrs =
1047
+ FILE_ATTRIBUTE_READONLY |
1048
+ FILE_ATTRIBUTE_HIDDEN |
1049
+ FILE_ATTRIBUTE_SYSTEM;
1050
+ DWORD file_attrs = st->dwFileAttributes & supported_attrs;
1051
+ if (file_attrs != 0)
1052
+ archive_entry_set_fflags(entry, file_attrs, 0);
1053
+ }
1054
+
1055
+ /*
1056
+ * Invoke a meta data filter callback.
1057
+ */
1058
+ if (a->metadata_filter_func) {
1059
+ if (!a->metadata_filter_func(&(a->archive),
1060
+ a->metadata_filter_data, entry))
1061
+ return (ARCHIVE_RETRY);
1062
+ }
1063
+
1064
+ archive_entry_copy_sourcepath_w(entry, tree_current_access_path(t));
1065
+
1066
+ r = ARCHIVE_OK;
1067
+ if (archive_entry_filetype(entry) == AE_IFREG &&
1068
+ archive_entry_size(entry) > 0) {
1069
+ DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
1070
+ if (t->async_io)
1071
+ flags |= FILE_FLAG_OVERLAPPED;
1072
+ if (t->direct_io)
1073
+ flags |= FILE_FLAG_NO_BUFFERING;
1074
+ else
1075
+ flags |= FILE_FLAG_SEQUENTIAL_SCAN;
1076
+ t->entry_fh = CreateFileW(tree_current_access_path(t),
1077
+ GENERIC_READ,
1078
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1079
+ NULL, OPEN_EXISTING, flags, NULL);
1080
+ if (t->entry_fh == INVALID_HANDLE_VALUE) {
1081
+ la_dosmaperr(GetLastError());
1082
+ archive_set_error(&a->archive, errno,
1083
+ "Couldn't open %ls", tree_current_path(a->tree));
1084
+ return (ARCHIVE_FAILED);
1085
+ }
1086
+
1087
+ /* Find sparse data from the disk. */
1088
+ if ((a->flags & ARCHIVE_READDISK_NO_SPARSE) == 0) {
1089
+ if (archive_entry_hardlink(entry) == NULL &&
1090
+ (st->dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) != 0)
1091
+ r = setup_sparse_from_disk(a, entry, t->entry_fh);
1092
+ }
1093
+ }
1094
+ return (r);
1095
+ }
1096
+
1097
+ static int
1098
+ _archive_read_next_header(struct archive *_a, struct archive_entry **entryp)
1099
+ {
1100
+ int ret;
1101
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
1102
+ *entryp = NULL;
1103
+ ret = _archive_read_next_header2(_a, a->entry);
1104
+ *entryp = a->entry;
1105
+ return ret;
1106
+ }
1107
+
1108
+ static int
1109
+ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
1110
+ {
1111
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
1112
+ struct tree *t;
1113
+ int r;
1114
+
1115
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
1116
+ ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
1117
+ "archive_read_next_header2");
1118
+
1119
+ t = a->tree;
1120
+ if (t->entry_fh != INVALID_HANDLE_VALUE) {
1121
+ cancel_async(t);
1122
+ close_and_restore_time(t->entry_fh, t, &t->restore_time);
1123
+ t->entry_fh = INVALID_HANDLE_VALUE;
1124
+ }
1125
+
1126
+ archive_entry_clear(entry);
1127
+
1128
+ while ((r = next_entry(a, t, entry)) == ARCHIVE_RETRY)
1129
+ archive_entry_clear(entry);
1130
+
1131
+ /*
1132
+ * EOF and FATAL are persistent at this layer. By
1133
+ * modifying the state, we guarantee that future calls to
1134
+ * read a header or read data will fail.
1135
+ */
1136
+ switch (r) {
1137
+ case ARCHIVE_EOF:
1138
+ a->archive.state = ARCHIVE_STATE_EOF;
1139
+ break;
1140
+ case ARCHIVE_OK:
1141
+ case ARCHIVE_WARN:
1142
+ t->entry_total = 0;
1143
+ if (archive_entry_filetype(entry) == AE_IFREG) {
1144
+ t->entry_remaining_bytes = archive_entry_size(entry);
1145
+ t->entry_eof = (t->entry_remaining_bytes == 0)? 1: 0;
1146
+ if (!t->entry_eof &&
1147
+ setup_sparse(a, entry) != ARCHIVE_OK)
1148
+ return (ARCHIVE_FATAL);
1149
+ } else {
1150
+ t->entry_remaining_bytes = 0;
1151
+ t->entry_eof = 1;
1152
+ }
1153
+ t->ol_idx_doing = t->ol_idx_done = 0;
1154
+ t->ol_num_doing = t->ol_num_done = 0;
1155
+ t->ol_remaining_bytes = t->entry_remaining_bytes;
1156
+ t->ol_total = 0;
1157
+ a->archive.state = ARCHIVE_STATE_DATA;
1158
+ break;
1159
+ case ARCHIVE_RETRY:
1160
+ break;
1161
+ case ARCHIVE_FATAL:
1162
+ a->archive.state = ARCHIVE_STATE_FATAL;
1163
+ break;
1164
+ }
1165
+
1166
+ __archive_reset_read_data(&a->archive);
1167
+ return (r);
1168
+ }
1169
+
1170
+ static int
1171
+ setup_sparse(struct archive_read_disk *a, struct archive_entry *entry)
1172
+ {
1173
+ struct tree *t = a->tree;
1174
+ int64_t aligned, length, offset;
1175
+ int i;
1176
+
1177
+ t->sparse_count = archive_entry_sparse_reset(entry);
1178
+ if (t->sparse_count+1 > t->sparse_list_size) {
1179
+ free(t->sparse_list);
1180
+ t->sparse_list_size = t->sparse_count + 1;
1181
+ t->sparse_list = malloc(sizeof(t->sparse_list[0]) *
1182
+ t->sparse_list_size);
1183
+ if (t->sparse_list == NULL) {
1184
+ t->sparse_list_size = 0;
1185
+ archive_set_error(&a->archive, ENOMEM,
1186
+ "Can't allocate data");
1187
+ a->archive.state = ARCHIVE_STATE_FATAL;
1188
+ return (ARCHIVE_FATAL);
1189
+ }
1190
+ }
1191
+ /*
1192
+ * Get sparse list and make sure those offsets and lengths are
1193
+ * aligned by a sector size.
1194
+ */
1195
+ for (i = 0; i < t->sparse_count; i++) {
1196
+ archive_entry_sparse_next(entry, &offset, &length);
1197
+ aligned = align_num_per_sector(t, offset);
1198
+ if (aligned != offset) {
1199
+ aligned -= t->current_filesystem->bytesPerSector;
1200
+ length += offset - aligned;
1201
+ }
1202
+ t->sparse_list[i].offset = aligned;
1203
+ aligned = align_num_per_sector(t, length);
1204
+ t->sparse_list[i].length = aligned;
1205
+ }
1206
+
1207
+ aligned = align_num_per_sector(t, archive_entry_size(entry));
1208
+ if (i == 0) {
1209
+ t->sparse_list[i].offset = 0;
1210
+ t->sparse_list[i].length = aligned;
1211
+ } else {
1212
+ int j, last = i;
1213
+
1214
+ t->sparse_list[i].offset = aligned;
1215
+ t->sparse_list[i].length = 0;
1216
+ for (i = 0; i < last; i++) {
1217
+ if ((t->sparse_list[i].offset +
1218
+ t->sparse_list[i].length) <=
1219
+ t->sparse_list[i+1].offset)
1220
+ continue;
1221
+ /*
1222
+ * Now sparse_list[i+1] is overlapped by sparse_list[i].
1223
+ * Merge those two.
1224
+ */
1225
+ length = t->sparse_list[i+1].offset -
1226
+ t->sparse_list[i].offset;
1227
+ t->sparse_list[i+1].offset = t->sparse_list[i].offset;
1228
+ t->sparse_list[i+1].length += length;
1229
+ /* Remove sparse_list[i]. */
1230
+ for (j = i; j < last; j++) {
1231
+ t->sparse_list[j].offset =
1232
+ t->sparse_list[j+1].offset;
1233
+ t->sparse_list[j].length =
1234
+ t->sparse_list[j+1].length;
1235
+ }
1236
+ last--;
1237
+ }
1238
+ }
1239
+ t->current_sparse = t->sparse_list;
1240
+
1241
+ return (ARCHIVE_OK);
1242
+ }
1243
+
1244
+ int
1245
+ archive_read_disk_set_matching(struct archive *_a, struct archive *_ma,
1246
+ void (*_excluded_func)(struct archive *, void *, struct archive_entry *),
1247
+ void *_client_data)
1248
+ {
1249
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
1250
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
1251
+ ARCHIVE_STATE_ANY, "archive_read_disk_set_matching");
1252
+ a->matching = _ma;
1253
+ a->excluded_cb_func = _excluded_func;
1254
+ a->excluded_cb_data = _client_data;
1255
+ return (ARCHIVE_OK);
1256
+ }
1257
+
1258
+ int
1259
+ archive_read_disk_set_metadata_filter_callback(struct archive *_a,
1260
+ int (*_metadata_filter_func)(struct archive *, void *,
1261
+ struct archive_entry *), void *_client_data)
1262
+ {
1263
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
1264
+
1265
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY,
1266
+ "archive_read_disk_set_metadata_filter_callback");
1267
+
1268
+ a->metadata_filter_func = _metadata_filter_func;
1269
+ a->metadata_filter_data = _client_data;
1270
+ return (ARCHIVE_OK);
1271
+ }
1272
+
1273
+ int
1274
+ archive_read_disk_can_descend(struct archive *_a)
1275
+ {
1276
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
1277
+ struct tree *t = a->tree;
1278
+
1279
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
1280
+ ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
1281
+ "archive_read_disk_can_descend");
1282
+
1283
+ return (t->visit_type == TREE_REGULAR && t->descend);
1284
+ }
1285
+
1286
+ /*
1287
+ * Called by the client to mark the directory just returned from
1288
+ * tree_next() as needing to be visited.
1289
+ */
1290
+ int
1291
+ archive_read_disk_descend(struct archive *_a)
1292
+ {
1293
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
1294
+ struct tree *t = a->tree;
1295
+
1296
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
1297
+ ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
1298
+ "archive_read_disk_descend");
1299
+
1300
+ if (!archive_read_disk_can_descend(_a))
1301
+ return (ARCHIVE_OK);
1302
+
1303
+ if (tree_current_is_physical_dir(t)) {
1304
+ tree_push(t, t->basename, t->full_path.s,
1305
+ t->current_filesystem_id,
1306
+ bhfi_dev(&(t->lst)), bhfi_ino(&(t->lst)),
1307
+ &t->restore_time);
1308
+ t->stack->flags |= isDir;
1309
+ } else if (tree_current_is_dir(t)) {
1310
+ tree_push(t, t->basename, t->full_path.s,
1311
+ t->current_filesystem_id,
1312
+ bhfi_dev(&(t->st)), bhfi_ino(&(t->st)),
1313
+ &t->restore_time);
1314
+ t->stack->flags |= isDirLink;
1315
+ }
1316
+ t->descend = 0;
1317
+ return (ARCHIVE_OK);
1318
+ }
1319
+
1320
+ int
1321
+ archive_read_disk_open(struct archive *_a, const char *pathname)
1322
+ {
1323
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
1324
+ struct archive_wstring wpath;
1325
+ int ret;
1326
+
1327
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
1328
+ ARCHIVE_STATE_NEW | ARCHIVE_STATE_CLOSED,
1329
+ "archive_read_disk_open");
1330
+ archive_clear_error(&a->archive);
1331
+
1332
+ /* Make a wchar_t string from a char string. */
1333
+ archive_string_init(&wpath);
1334
+ if (archive_wstring_append_from_mbs(&wpath, pathname,
1335
+ strlen(pathname)) != 0) {
1336
+ if (errno == ENOMEM)
1337
+ archive_set_error(&a->archive, ENOMEM,
1338
+ "Can't allocate memory");
1339
+ else
1340
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1341
+ "Can't convert a path to a wchar_t string");
1342
+ a->archive.state = ARCHIVE_STATE_FATAL;
1343
+ ret = ARCHIVE_FATAL;
1344
+ } else
1345
+ ret = _archive_read_disk_open_w(_a, wpath.s);
1346
+
1347
+ archive_wstring_free(&wpath);
1348
+ return (ret);
1349
+ }
1350
+
1351
+ int
1352
+ archive_read_disk_open_w(struct archive *_a, const wchar_t *pathname)
1353
+ {
1354
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
1355
+
1356
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
1357
+ ARCHIVE_STATE_NEW | ARCHIVE_STATE_CLOSED,
1358
+ "archive_read_disk_open_w");
1359
+ archive_clear_error(&a->archive);
1360
+
1361
+ return (_archive_read_disk_open_w(_a, pathname));
1362
+ }
1363
+
1364
+ static int
1365
+ _archive_read_disk_open_w(struct archive *_a, const wchar_t *pathname)
1366
+ {
1367
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
1368
+
1369
+ if (a->tree != NULL)
1370
+ a->tree = tree_reopen(a->tree, pathname,
1371
+ a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
1372
+ else
1373
+ a->tree = tree_open(pathname, a->symlink_mode,
1374
+ a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
1375
+ if (a->tree == NULL) {
1376
+ archive_set_error(&a->archive, ENOMEM,
1377
+ "Can't allocate directory traversal data");
1378
+ a->archive.state = ARCHIVE_STATE_FATAL;
1379
+ return (ARCHIVE_FATAL);
1380
+ }
1381
+ a->archive.state = ARCHIVE_STATE_HEADER;
1382
+
1383
+ return (ARCHIVE_OK);
1384
+ }
1385
+
1386
+ /*
1387
+ * Return a current filesystem ID which is index of the filesystem entry
1388
+ * you've visited through archive_read_disk.
1389
+ */
1390
+ int
1391
+ archive_read_disk_current_filesystem(struct archive *_a)
1392
+ {
1393
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
1394
+
1395
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
1396
+ "archive_read_disk_current_filesystem");
1397
+
1398
+ return (a->tree->current_filesystem_id);
1399
+ }
1400
+
1401
+ static int
1402
+ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
1403
+ {
1404
+ struct tree *t = a->tree;
1405
+ int i, fid;
1406
+
1407
+ if (t->current_filesystem != NULL &&
1408
+ t->current_filesystem->dev == dev)
1409
+ return (ARCHIVE_OK);
1410
+
1411
+ for (i = 0; i < t->max_filesystem_id; i++) {
1412
+ if (t->filesystem_table[i].dev == dev) {
1413
+ /* There is the filesystem ID we've already generated. */
1414
+ t->current_filesystem_id = i;
1415
+ t->current_filesystem = &(t->filesystem_table[i]);
1416
+ return (ARCHIVE_OK);
1417
+ }
1418
+ }
1419
+
1420
+ /*
1421
+ * There is a new filesystem, we generate a new ID for.
1422
+ */
1423
+ fid = t->max_filesystem_id++;
1424
+ if (t->max_filesystem_id > t->allocated_filesystem) {
1425
+ size_t s;
1426
+ void *p;
1427
+
1428
+ s = t->max_filesystem_id * 2;
1429
+ p = realloc(t->filesystem_table,
1430
+ s * sizeof(*t->filesystem_table));
1431
+ if (p == NULL) {
1432
+ archive_set_error(&a->archive, ENOMEM,
1433
+ "Can't allocate tar data");
1434
+ return (ARCHIVE_FATAL);
1435
+ }
1436
+ t->filesystem_table = (struct filesystem *)p;
1437
+ t->allocated_filesystem = (int)s;
1438
+ }
1439
+ t->current_filesystem_id = fid;
1440
+ t->current_filesystem = &(t->filesystem_table[fid]);
1441
+ t->current_filesystem->dev = dev;
1442
+
1443
+ return (setup_current_filesystem(a));
1444
+ }
1445
+
1446
+ /*
1447
+ * Returns 1 if current filesystem is generated filesystem, 0 if it is not
1448
+ * or -1 if it is unknown.
1449
+ */
1450
+ int
1451
+ archive_read_disk_current_filesystem_is_synthetic(struct archive *_a)
1452
+ {
1453
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
1454
+
1455
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
1456
+ "archive_read_disk_current_filesystem");
1457
+
1458
+ return (a->tree->current_filesystem->synthetic);
1459
+ }
1460
+
1461
+ /*
1462
+ * Returns 1 if current filesystem is remote filesystem, 0 if it is not
1463
+ * or -1 if it is unknown.
1464
+ */
1465
+ int
1466
+ archive_read_disk_current_filesystem_is_remote(struct archive *_a)
1467
+ {
1468
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
1469
+
1470
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
1471
+ "archive_read_disk_current_filesystem");
1472
+
1473
+ return (a->tree->current_filesystem->remote);
1474
+ }
1475
+
1476
+ /*
1477
+ * If symlink is broken, statfs or statvfs will fail.
1478
+ * Use its directory path instead.
1479
+ */
1480
+ static wchar_t *
1481
+ safe_path_for_statfs(struct tree *t)
1482
+ {
1483
+ const wchar_t *path;
1484
+ wchar_t *cp, *p = NULL;
1485
+
1486
+ path = tree_current_access_path(t);
1487
+ if (tree_current_stat(t) == NULL) {
1488
+ p = _wcsdup(path);
1489
+ cp = wcsrchr(p, '/');
1490
+ if (cp != NULL && wcslen(cp) >= 2) {
1491
+ cp[1] = '.';
1492
+ cp[2] = '\0';
1493
+ path = p;
1494
+ }
1495
+ } else
1496
+ p = _wcsdup(path);
1497
+ return (p);
1498
+ }
1499
+
1500
+ /*
1501
+ * Get conditions of synthetic and remote on Windows
1502
+ */
1503
+ static int
1504
+ setup_current_filesystem(struct archive_read_disk *a)
1505
+ {
1506
+ struct tree *t = a->tree;
1507
+ wchar_t vol[256];
1508
+ wchar_t *path;
1509
+
1510
+ t->current_filesystem->synthetic = -1;/* Not supported */
1511
+ path = safe_path_for_statfs(t);
1512
+ if (!GetVolumePathNameW(path, vol, sizeof(vol)/sizeof(vol[0]))) {
1513
+ free(path);
1514
+ t->current_filesystem->remote = -1;
1515
+ t->current_filesystem->bytesPerSector = 0;
1516
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1517
+ "GetVolumePathName failed: %d", (int)GetLastError());
1518
+ return (ARCHIVE_FAILED);
1519
+ }
1520
+ free(path);
1521
+ switch (GetDriveTypeW(vol)) {
1522
+ case DRIVE_UNKNOWN:
1523
+ case DRIVE_NO_ROOT_DIR:
1524
+ t->current_filesystem->remote = -1;
1525
+ break;
1526
+ case DRIVE_REMOTE:
1527
+ t->current_filesystem->remote = 1;
1528
+ break;
1529
+ default:
1530
+ t->current_filesystem->remote = 0;
1531
+ break;
1532
+ }
1533
+
1534
+ if (!GetDiskFreeSpaceW(vol, NULL,
1535
+ &(t->current_filesystem->bytesPerSector), NULL, NULL)) {
1536
+ t->current_filesystem->bytesPerSector = 0;
1537
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1538
+ "GetDiskFreeSpace failed: %d", (int)GetLastError());
1539
+ return (ARCHIVE_FAILED);
1540
+ }
1541
+
1542
+ return (ARCHIVE_OK);
1543
+ }
1544
+
1545
+ static int
1546
+ close_and_restore_time(HANDLE h, struct tree *t, struct restore_time *rt)
1547
+ {
1548
+ HANDLE handle;
1549
+ int r = 0;
1550
+
1551
+ if (h == INVALID_HANDLE_VALUE && AE_IFLNK == rt->filetype)
1552
+ return (0);
1553
+
1554
+ /* Close a file descriptor.
1555
+ * It will not be used for SetFileTime() because it has been opened
1556
+ * by a read only mode.
1557
+ */
1558
+ if (h != INVALID_HANDLE_VALUE)
1559
+ CloseHandle(h);
1560
+ if ((t->flags & needsRestoreTimes) == 0)
1561
+ return (r);
1562
+
1563
+ handle = CreateFileW(rt->full_path, FILE_WRITE_ATTRIBUTES,
1564
+ 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
1565
+ if (handle == INVALID_HANDLE_VALUE) {
1566
+ errno = EINVAL;
1567
+ return (-1);
1568
+ }
1569
+
1570
+ if (SetFileTime(handle, NULL, &rt->lastAccessTime,
1571
+ &rt->lastWriteTime) == 0) {
1572
+ errno = EINVAL;
1573
+ r = -1;
1574
+ } else
1575
+ r = 0;
1576
+ CloseHandle(handle);
1577
+ return (r);
1578
+ }
1579
+
1580
+ /*
1581
+ * Add a directory path to the current stack.
1582
+ */
1583
+ static void
1584
+ tree_push(struct tree *t, const wchar_t *path, const wchar_t *full_path,
1585
+ int filesystem_id, int64_t dev, int64_t ino, struct restore_time *rt)
1586
+ {
1587
+ struct tree_entry *te;
1588
+
1589
+ te = calloc(1, sizeof(*te));
1590
+ te->next = t->stack;
1591
+ te->parent = t->current;
1592
+ if (te->parent)
1593
+ te->depth = te->parent->depth + 1;
1594
+ t->stack = te;
1595
+ archive_string_init(&te->name);
1596
+ archive_wstrcpy(&te->name, path);
1597
+ archive_string_init(&te->full_path);
1598
+ archive_wstrcpy(&te->full_path, full_path);
1599
+ te->flags = needsDescent | needsOpen | needsAscent;
1600
+ te->filesystem_id = filesystem_id;
1601
+ te->dev = dev;
1602
+ te->ino = ino;
1603
+ te->dirname_length = t->dirname_length;
1604
+ te->full_path_dir_length = t->full_path_dir_length;
1605
+ te->restore_time.full_path = te->full_path.s;
1606
+ if (rt != NULL) {
1607
+ te->restore_time.lastWriteTime = rt->lastWriteTime;
1608
+ te->restore_time.lastAccessTime = rt->lastAccessTime;
1609
+ te->restore_time.filetype = rt->filetype;
1610
+ }
1611
+ }
1612
+
1613
+ /*
1614
+ * Append a name to the current dir path.
1615
+ */
1616
+ static void
1617
+ tree_append(struct tree *t, const wchar_t *name, size_t name_length)
1618
+ {
1619
+ size_t size_needed;
1620
+
1621
+ t->path.s[t->dirname_length] = L'\0';
1622
+ t->path.length = t->dirname_length;
1623
+ /* Strip trailing '/' from name, unless entire name is "/". */
1624
+ while (name_length > 1 && name[name_length - 1] == L'/')
1625
+ name_length--;
1626
+
1627
+ /* Resize pathname buffer as needed. */
1628
+ size_needed = name_length + t->dirname_length + 2;
1629
+ archive_wstring_ensure(&t->path, size_needed);
1630
+ /* Add a separating '/' if it's needed. */
1631
+ if (t->dirname_length > 0 &&
1632
+ t->path.s[archive_strlen(&t->path)-1] != L'/')
1633
+ archive_wstrappend_wchar(&t->path, L'/');
1634
+ t->basename = t->path.s + archive_strlen(&t->path);
1635
+ archive_wstrncat(&t->path, name, name_length);
1636
+ t->restore_time.full_path = t->basename;
1637
+ if (t->full_path_dir_length > 0) {
1638
+ t->full_path.s[t->full_path_dir_length] = L'\0';
1639
+ t->full_path.length = t->full_path_dir_length;
1640
+ size_needed = name_length + t->full_path_dir_length + 2;
1641
+ archive_wstring_ensure(&t->full_path, size_needed);
1642
+ /* Add a separating '\' if it's needed. */
1643
+ if (t->full_path.s[archive_strlen(&t->full_path)-1] != L'\\')
1644
+ archive_wstrappend_wchar(&t->full_path, L'\\');
1645
+ archive_wstrncat(&t->full_path, name, name_length);
1646
+ t->restore_time.full_path = t->full_path.s;
1647
+ }
1648
+ }
1649
+
1650
+ /*
1651
+ * Open a directory tree for traversal.
1652
+ */
1653
+ static struct tree *
1654
+ tree_open(const wchar_t *path, int symlink_mode, int restore_time)
1655
+ {
1656
+ struct tree *t;
1657
+
1658
+ t = calloc(1, sizeof(*t));
1659
+ archive_string_init(&(t->full_path));
1660
+ archive_string_init(&t->path);
1661
+ archive_wstring_ensure(&t->path, 15);
1662
+ t->initial_symlink_mode = symlink_mode;
1663
+ return (tree_reopen(t, path, restore_time));
1664
+ }
1665
+
1666
+ static struct tree *
1667
+ tree_reopen(struct tree *t, const wchar_t *path, int restore_time)
1668
+ {
1669
+ struct archive_wstring ws;
1670
+ wchar_t *pathname, *p, *base;
1671
+
1672
+ t->flags = (restore_time != 0)?needsRestoreTimes:0;
1673
+ t->visit_type = 0;
1674
+ t->tree_errno = 0;
1675
+ t->full_path_dir_length = 0;
1676
+ t->dirname_length = 0;
1677
+ t->depth = 0;
1678
+ t->descend = 0;
1679
+ t->current = NULL;
1680
+ t->d = INVALID_HANDLE_VALUE;
1681
+ t->symlink_mode = t->initial_symlink_mode;
1682
+ archive_string_empty(&(t->full_path));
1683
+ archive_string_empty(&t->path);
1684
+ t->entry_fh = INVALID_HANDLE_VALUE;
1685
+ t->entry_eof = 0;
1686
+ t->entry_remaining_bytes = 0;
1687
+ t->initial_filesystem_id = -1;
1688
+
1689
+ /* Get wchar_t strings from char strings. */
1690
+ archive_string_init(&ws);
1691
+ archive_wstrcpy(&ws, path);
1692
+ pathname = ws.s;
1693
+ /* Get a full-path-name. */
1694
+ p = __la_win_permissive_name_w(pathname);
1695
+ if (p == NULL)
1696
+ goto failed;
1697
+ archive_wstrcpy(&(t->full_path), p);
1698
+ free(p);
1699
+
1700
+ /* Convert path separators from '\' to '/' */
1701
+ for (p = pathname; *p != L'\0'; ++p) {
1702
+ if (*p == L'\\')
1703
+ *p = L'/';
1704
+ }
1705
+ base = pathname;
1706
+
1707
+ /* First item is set up a lot like a symlink traversal. */
1708
+ /* printf("Looking for wildcard in %s\n", path); */
1709
+ if ((base[0] == L'/' && base[1] == L'/' &&
1710
+ base[2] == L'?' && base[3] == L'/' &&
1711
+ (wcschr(base+4, L'*') || wcschr(base+4, L'?'))) ||
1712
+ (!(base[0] == L'/' && base[1] == L'/' &&
1713
+ base[2] == L'?' && base[3] == L'/') &&
1714
+ (wcschr(base, L'*') || wcschr(base, L'?')))) {
1715
+ // It has a wildcard in it...
1716
+ // Separate the last element.
1717
+ p = wcsrchr(base, L'/');
1718
+ if (p != NULL) {
1719
+ *p = L'\0';
1720
+ tree_append(t, base, p - base);
1721
+ t->dirname_length = archive_strlen(&t->path);
1722
+ base = p + 1;
1723
+ }
1724
+ p = wcsrchr(t->full_path.s, L'\\');
1725
+ if (p != NULL) {
1726
+ *p = L'\0';
1727
+ t->full_path.length = wcslen(t->full_path.s);
1728
+ t->full_path_dir_length = archive_strlen(&t->full_path);
1729
+ }
1730
+ }
1731
+ tree_push(t, base, t->full_path.s, 0, 0, 0, NULL);
1732
+ archive_wstring_free(&ws);
1733
+ t->stack->flags = needsFirstVisit;
1734
+ /*
1735
+ * Debug flag for Direct IO(No buffering) or Async IO.
1736
+ * Those dependent on environment variable switches
1737
+ * will be removed until next release.
1738
+ */
1739
+ {
1740
+ const char *e;
1741
+ if ((e = getenv("LIBARCHIVE_DIRECT_IO")) != NULL) {
1742
+ if (e[0] == '0')
1743
+ t->direct_io = 0;
1744
+ else
1745
+ t->direct_io = 1;
1746
+ fprintf(stderr, "LIBARCHIVE_DIRECT_IO=%s\n",
1747
+ (t->direct_io)?"Enabled":"Disabled");
1748
+ } else
1749
+ t->direct_io = DIRECT_IO;
1750
+ if ((e = getenv("LIBARCHIVE_ASYNC_IO")) != NULL) {
1751
+ if (e[0] == '0')
1752
+ t->async_io = 0;
1753
+ else
1754
+ t->async_io = 1;
1755
+ fprintf(stderr, "LIBARCHIVE_ASYNC_IO=%s\n",
1756
+ (t->async_io)?"Enabled":"Disabled");
1757
+ } else
1758
+ t->async_io = ASYNC_IO;
1759
+ }
1760
+ return (t);
1761
+ failed:
1762
+ archive_wstring_free(&ws);
1763
+ tree_free(t);
1764
+ return (NULL);
1765
+ }
1766
+
1767
+ static int
1768
+ tree_descent(struct tree *t)
1769
+ {
1770
+ t->dirname_length = archive_strlen(&t->path);
1771
+ t->full_path_dir_length = archive_strlen(&t->full_path);
1772
+ t->depth++;
1773
+ return (0);
1774
+ }
1775
+
1776
+ /*
1777
+ * We've finished a directory; ascend back to the parent.
1778
+ */
1779
+ static int
1780
+ tree_ascend(struct tree *t)
1781
+ {
1782
+ struct tree_entry *te;
1783
+
1784
+ te = t->stack;
1785
+ t->depth--;
1786
+ close_and_restore_time(INVALID_HANDLE_VALUE, t, &te->restore_time);
1787
+ return (0);
1788
+ }
1789
+
1790
+ /*
1791
+ * Pop the working stack.
1792
+ */
1793
+ static void
1794
+ tree_pop(struct tree *t)
1795
+ {
1796
+ struct tree_entry *te;
1797
+
1798
+ t->full_path.s[t->full_path_dir_length] = L'\0';
1799
+ t->full_path.length = t->full_path_dir_length;
1800
+ t->path.s[t->dirname_length] = L'\0';
1801
+ t->path.length = t->dirname_length;
1802
+ if (t->stack == t->current && t->current != NULL)
1803
+ t->current = t->current->parent;
1804
+ te = t->stack;
1805
+ t->stack = te->next;
1806
+ t->dirname_length = te->dirname_length;
1807
+ t->basename = t->path.s + t->dirname_length;
1808
+ t->full_path_dir_length = te->full_path_dir_length;
1809
+ while (t->basename[0] == L'/')
1810
+ t->basename++;
1811
+ archive_wstring_free(&te->name);
1812
+ archive_wstring_free(&te->full_path);
1813
+ free(te);
1814
+ }
1815
+
1816
+ /*
1817
+ * Get the next item in the tree traversal.
1818
+ */
1819
+ static int
1820
+ tree_next(struct tree *t)
1821
+ {
1822
+ int r;
1823
+
1824
+ while (t->stack != NULL) {
1825
+ /* If there's an open dir, get the next entry from there. */
1826
+ if (t->d != INVALID_HANDLE_VALUE) {
1827
+ r = tree_dir_next_windows(t, NULL);
1828
+ if (r == 0)
1829
+ continue;
1830
+ return (r);
1831
+ }
1832
+
1833
+ if (t->stack->flags & needsFirstVisit) {
1834
+ wchar_t *d = t->stack->name.s;
1835
+ t->stack->flags &= ~needsFirstVisit;
1836
+ if (!(d[0] == L'/' && d[1] == L'/' &&
1837
+ d[2] == L'?' && d[3] == L'/') &&
1838
+ (wcschr(d, L'*') || wcschr(d, L'?'))) {
1839
+ r = tree_dir_next_windows(t, d);
1840
+ if (r == 0)
1841
+ continue;
1842
+ return (r);
1843
+ } else {
1844
+ HANDLE h = FindFirstFileW(t->stack->full_path.s, &t->_findData);
1845
+ if (h == INVALID_HANDLE_VALUE) {
1846
+ la_dosmaperr(GetLastError());
1847
+ t->tree_errno = errno;
1848
+ t->visit_type = TREE_ERROR_DIR;
1849
+ return (t->visit_type);
1850
+ }
1851
+ t->findData = &t->_findData;
1852
+ FindClose(h);
1853
+ }
1854
+ /* Top stack item needs a regular visit. */
1855
+ t->current = t->stack;
1856
+ tree_append(t, t->stack->name.s,
1857
+ archive_strlen(&(t->stack->name)));
1858
+ //t->dirname_length = t->path_length;
1859
+ //tree_pop(t);
1860
+ t->stack->flags &= ~needsFirstVisit;
1861
+ return (t->visit_type = TREE_REGULAR);
1862
+ } else if (t->stack->flags & needsDescent) {
1863
+ /* Top stack item is dir to descend into. */
1864
+ t->current = t->stack;
1865
+ tree_append(t, t->stack->name.s,
1866
+ archive_strlen(&(t->stack->name)));
1867
+ t->stack->flags &= ~needsDescent;
1868
+ r = tree_descent(t);
1869
+ if (r != 0) {
1870
+ tree_pop(t);
1871
+ t->visit_type = r;
1872
+ } else
1873
+ t->visit_type = TREE_POSTDESCENT;
1874
+ return (t->visit_type);
1875
+ } else if (t->stack->flags & needsOpen) {
1876
+ t->stack->flags &= ~needsOpen;
1877
+ r = tree_dir_next_windows(t, L"*");
1878
+ if (r == 0)
1879
+ continue;
1880
+ return (r);
1881
+ } else if (t->stack->flags & needsAscent) {
1882
+ /* Top stack item is dir and we're done with it. */
1883
+ r = tree_ascend(t);
1884
+ tree_pop(t);
1885
+ t->visit_type = r != 0 ? r : TREE_POSTASCENT;
1886
+ return (t->visit_type);
1887
+ } else {
1888
+ /* Top item on stack is dead. */
1889
+ tree_pop(t);
1890
+ t->flags &= ~hasLstat;
1891
+ t->flags &= ~hasStat;
1892
+ }
1893
+ }
1894
+ return (t->visit_type = 0);
1895
+ }
1896
+
1897
+ static int
1898
+ tree_dir_next_windows(struct tree *t, const wchar_t *pattern)
1899
+ {
1900
+ const wchar_t *name;
1901
+ size_t namelen;
1902
+ int r;
1903
+
1904
+ for (;;) {
1905
+ if (pattern != NULL) {
1906
+ struct archive_wstring pt;
1907
+
1908
+ archive_string_init(&pt);
1909
+ archive_wstring_ensure(&pt,
1910
+ archive_strlen(&(t->full_path))
1911
+ + 2 + wcslen(pattern));
1912
+ archive_wstring_copy(&pt, &(t->full_path));
1913
+ archive_wstrappend_wchar(&pt, L'\\');
1914
+ archive_wstrcat(&pt, pattern);
1915
+ t->d = FindFirstFileW(pt.s, &t->_findData);
1916
+ archive_wstring_free(&pt);
1917
+ if (t->d == INVALID_HANDLE_VALUE) {
1918
+ la_dosmaperr(GetLastError());
1919
+ t->tree_errno = errno;
1920
+ r = tree_ascend(t); /* Undo "chdir" */
1921
+ tree_pop(t);
1922
+ t->visit_type = r != 0 ? r : TREE_ERROR_DIR;
1923
+ return (t->visit_type);
1924
+ }
1925
+ t->findData = &t->_findData;
1926
+ pattern = NULL;
1927
+ } else if (!FindNextFileW(t->d, &t->_findData)) {
1928
+ FindClose(t->d);
1929
+ t->d = INVALID_HANDLE_VALUE;
1930
+ t->findData = NULL;
1931
+ return (0);
1932
+ }
1933
+ name = t->findData->cFileName;
1934
+ namelen = wcslen(name);
1935
+ t->flags &= ~hasLstat;
1936
+ t->flags &= ~hasStat;
1937
+ if (name[0] == L'.' && name[1] == L'\0')
1938
+ continue;
1939
+ if (name[0] == L'.' && name[1] == L'.' && name[2] == L'\0')
1940
+ continue;
1941
+ tree_append(t, name, namelen);
1942
+ return (t->visit_type = TREE_REGULAR);
1943
+ }
1944
+ }
1945
+
1946
+ #define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
1947
+ static void
1948
+ fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns)
1949
+ {
1950
+ ULARGE_INTEGER utc;
1951
+
1952
+ utc.HighPart = filetime->dwHighDateTime;
1953
+ utc.LowPart = filetime->dwLowDateTime;
1954
+ if (utc.QuadPart >= EPOC_TIME) {
1955
+ utc.QuadPart -= EPOC_TIME;
1956
+ /* milli seconds base */
1957
+ *t = (time_t)(utc.QuadPart / 10000000);
1958
+ /* nano seconds base */
1959
+ *ns = (long)(utc.QuadPart % 10000000) * 100;
1960
+ } else {
1961
+ *t = 0;
1962
+ *ns = 0;
1963
+ }
1964
+ }
1965
+
1966
+ static void
1967
+ entry_copy_bhfi(struct archive_entry *entry, const wchar_t *path,
1968
+ const WIN32_FIND_DATAW *findData,
1969
+ const BY_HANDLE_FILE_INFORMATION *bhfi)
1970
+ {
1971
+ time_t secs;
1972
+ long nsecs;
1973
+ mode_t mode;
1974
+
1975
+ fileTimeToUtc(&bhfi->ftLastAccessTime, &secs, &nsecs);
1976
+ archive_entry_set_atime(entry, secs, nsecs);
1977
+ fileTimeToUtc(&bhfi->ftLastWriteTime, &secs, &nsecs);
1978
+ archive_entry_set_mtime(entry, secs, nsecs);
1979
+ fileTimeToUtc(&bhfi->ftCreationTime, &secs, &nsecs);
1980
+ archive_entry_set_birthtime(entry, secs, nsecs);
1981
+ archive_entry_set_ctime(entry, secs, nsecs);
1982
+ archive_entry_set_dev(entry, bhfi_dev(bhfi));
1983
+ archive_entry_set_ino64(entry, bhfi_ino(bhfi));
1984
+ if (bhfi->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1985
+ archive_entry_set_nlink(entry, bhfi->nNumberOfLinks + 1);
1986
+ else
1987
+ archive_entry_set_nlink(entry, bhfi->nNumberOfLinks);
1988
+ archive_entry_set_size(entry,
1989
+ (((int64_t)bhfi->nFileSizeHigh) << 32)
1990
+ + bhfi->nFileSizeLow);
1991
+ archive_entry_set_uid(entry, 0);
1992
+ archive_entry_set_gid(entry, 0);
1993
+ archive_entry_set_rdev(entry, 0);
1994
+
1995
+ mode = S_IRUSR | S_IRGRP | S_IROTH;
1996
+ if ((bhfi->dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0)
1997
+ mode |= S_IWUSR | S_IWGRP | S_IWOTH;
1998
+ if ((bhfi->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
1999
+ findData != NULL &&
2000
+ findData->dwReserved0 == IO_REPARSE_TAG_SYMLINK) {
2001
+ mode |= S_IFLNK;
2002
+ entry_symlink_from_pathw(entry, path);
2003
+ } else if (bhfi->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2004
+ mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
2005
+ else {
2006
+ const wchar_t *p;
2007
+
2008
+ mode |= S_IFREG;
2009
+ p = wcsrchr(path, L'.');
2010
+ if (p != NULL && wcslen(p) == 4) {
2011
+ switch (p[1]) {
2012
+ case L'B': case L'b':
2013
+ if ((p[2] == L'A' || p[2] == L'a' ) &&
2014
+ (p[3] == L'T' || p[3] == L't' ))
2015
+ mode |= S_IXUSR | S_IXGRP | S_IXOTH;
2016
+ break;
2017
+ case L'C': case L'c':
2018
+ if (((p[2] == L'M' || p[2] == L'm' ) &&
2019
+ (p[3] == L'D' || p[3] == L'd' )))
2020
+ mode |= S_IXUSR | S_IXGRP | S_IXOTH;
2021
+ break;
2022
+ case L'E': case L'e':
2023
+ if ((p[2] == L'X' || p[2] == L'x' ) &&
2024
+ (p[3] == L'E' || p[3] == L'e' ))
2025
+ mode |= S_IXUSR | S_IXGRP | S_IXOTH;
2026
+ break;
2027
+ default:
2028
+ break;
2029
+ }
2030
+ }
2031
+ }
2032
+ archive_entry_set_mode(entry, mode);
2033
+ }
2034
+
2035
+ static void
2036
+ tree_archive_entry_copy_bhfi(struct archive_entry *entry, struct tree *t,
2037
+ const BY_HANDLE_FILE_INFORMATION *bhfi)
2038
+ {
2039
+ entry_copy_bhfi(entry, tree_current_path(t), t->findData, bhfi);
2040
+ }
2041
+
2042
+ static int
2043
+ tree_current_file_information(struct tree *t, BY_HANDLE_FILE_INFORMATION *st,
2044
+ int sim_lstat)
2045
+ {
2046
+ HANDLE h;
2047
+ int r;
2048
+ DWORD flag = FILE_FLAG_BACKUP_SEMANTICS;
2049
+
2050
+ if (sim_lstat && tree_current_is_physical_link(t))
2051
+ flag |= FILE_FLAG_OPEN_REPARSE_POINT;
2052
+ h = CreateFileW(tree_current_access_path(t), 0,
2053
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
2054
+ OPEN_EXISTING, flag, NULL);
2055
+ if (h == INVALID_HANDLE_VALUE) {
2056
+ la_dosmaperr(GetLastError());
2057
+ t->tree_errno = errno;
2058
+ return (0);
2059
+ }
2060
+ r = GetFileInformationByHandle(h, st);
2061
+ CloseHandle(h);
2062
+ return (r);
2063
+ }
2064
+
2065
+ /*
2066
+ * Get the stat() data for the entry just returned from tree_next().
2067
+ */
2068
+ static const BY_HANDLE_FILE_INFORMATION *
2069
+ tree_current_stat(struct tree *t)
2070
+ {
2071
+ if (!(t->flags & hasStat)) {
2072
+ if (!tree_current_file_information(t, &t->st, 0))
2073
+ return NULL;
2074
+ t->flags |= hasStat;
2075
+ }
2076
+ return (&t->st);
2077
+ }
2078
+
2079
+ /*
2080
+ * Get the lstat() data for the entry just returned from tree_next().
2081
+ */
2082
+ static const BY_HANDLE_FILE_INFORMATION *
2083
+ tree_current_lstat(struct tree *t)
2084
+ {
2085
+ if (!(t->flags & hasLstat)) {
2086
+ if (!tree_current_file_information(t, &t->lst, 1))
2087
+ return NULL;
2088
+ t->flags |= hasLstat;
2089
+ }
2090
+ return (&t->lst);
2091
+ }
2092
+
2093
+ /*
2094
+ * Test whether current entry is a dir or link to a dir.
2095
+ */
2096
+ static int
2097
+ tree_current_is_dir(struct tree *t)
2098
+ {
2099
+ if (t->findData)
2100
+ return (t->findData->dwFileAttributes
2101
+ & FILE_ATTRIBUTE_DIRECTORY);
2102
+ return (0);
2103
+ }
2104
+
2105
+ /*
2106
+ * Test whether current entry is a physical directory. Usually, we
2107
+ * already have at least one of stat() or lstat() in memory, so we
2108
+ * use tricks to try to avoid an extra trip to the disk.
2109
+ */
2110
+ static int
2111
+ tree_current_is_physical_dir(struct tree *t)
2112
+ {
2113
+ if (tree_current_is_physical_link(t))
2114
+ return (0);
2115
+ return (tree_current_is_dir(t));
2116
+ }
2117
+
2118
+ /*
2119
+ * Test whether current entry is a symbolic link.
2120
+ */
2121
+ static int
2122
+ tree_current_is_physical_link(struct tree *t)
2123
+ {
2124
+ if (t->findData)
2125
+ return ((t->findData->dwFileAttributes
2126
+ & FILE_ATTRIBUTE_REPARSE_POINT) &&
2127
+ (t->findData->dwReserved0
2128
+ == IO_REPARSE_TAG_SYMLINK));
2129
+ return (0);
2130
+ }
2131
+
2132
+ /*
2133
+ * Test whether the same file has been in the tree as its parent.
2134
+ */
2135
+ static int
2136
+ tree_target_is_same_as_parent(struct tree *t,
2137
+ const BY_HANDLE_FILE_INFORMATION *st)
2138
+ {
2139
+ struct tree_entry *te;
2140
+ int64_t dev = bhfi_dev(st);
2141
+ int64_t ino = bhfi_ino(st);
2142
+
2143
+ for (te = t->current->parent; te != NULL; te = te->parent) {
2144
+ if (te->dev == dev && te->ino == ino)
2145
+ return (1);
2146
+ }
2147
+ return (0);
2148
+ }
2149
+
2150
+ /*
2151
+ * Return the access path for the entry just returned from tree_next().
2152
+ */
2153
+ static const wchar_t *
2154
+ tree_current_access_path(struct tree *t)
2155
+ {
2156
+ return (t->full_path.s);
2157
+ }
2158
+
2159
+ /*
2160
+ * Return the full path for the entry just returned from tree_next().
2161
+ */
2162
+ static const wchar_t *
2163
+ tree_current_path(struct tree *t)
2164
+ {
2165
+ return (t->path.s);
2166
+ }
2167
+
2168
+ /*
2169
+ * Terminate the traversal.
2170
+ */
2171
+ static void
2172
+ tree_close(struct tree *t)
2173
+ {
2174
+
2175
+ if (t == NULL)
2176
+ return;
2177
+ if (t->entry_fh != INVALID_HANDLE_VALUE) {
2178
+ cancel_async(t);
2179
+ close_and_restore_time(t->entry_fh, t, &t->restore_time);
2180
+ t->entry_fh = INVALID_HANDLE_VALUE;
2181
+ }
2182
+ /* Close the handle of FindFirstFileW */
2183
+ if (t->d != INVALID_HANDLE_VALUE) {
2184
+ FindClose(t->d);
2185
+ t->d = INVALID_HANDLE_VALUE;
2186
+ t->findData = NULL;
2187
+ }
2188
+ /* Release anything remaining in the stack. */
2189
+ while (t->stack != NULL)
2190
+ tree_pop(t);
2191
+ }
2192
+
2193
+ /*
2194
+ * Release any resources.
2195
+ */
2196
+ static void
2197
+ tree_free(struct tree *t)
2198
+ {
2199
+ int i;
2200
+
2201
+ if (t == NULL)
2202
+ return;
2203
+ archive_wstring_free(&t->path);
2204
+ archive_wstring_free(&t->full_path);
2205
+ free(t->sparse_list);
2206
+ free(t->filesystem_table);
2207
+ for (i = 0; i < MAX_OVERLAPPED; i++) {
2208
+ if (t->ol[i].buff)
2209
+ VirtualFree(t->ol[i].buff, 0, MEM_RELEASE);
2210
+ CloseHandle(t->ol[i].ol.hEvent);
2211
+ }
2212
+ free(t);
2213
+ }
2214
+
2215
+
2216
+ /*
2217
+ * Populate the archive_entry with metadata from the disk.
2218
+ */
2219
+ int
2220
+ archive_read_disk_entry_from_file(struct archive *_a,
2221
+ struct archive_entry *entry, int fd, const struct stat *st)
2222
+ {
2223
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
2224
+ const wchar_t *path;
2225
+ const wchar_t *wname;
2226
+ const char *name;
2227
+ HANDLE h;
2228
+ BY_HANDLE_FILE_INFORMATION bhfi;
2229
+ DWORD fileAttributes = 0;
2230
+ int r;
2231
+
2232
+ archive_clear_error(_a);
2233
+ wname = archive_entry_sourcepath_w(entry);
2234
+ if (wname == NULL)
2235
+ wname = archive_entry_pathname_w(entry);
2236
+ if (wname == NULL) {
2237
+ archive_set_error(&a->archive, EINVAL,
2238
+ "Can't get a wide character version of the path");
2239
+ return (ARCHIVE_FAILED);
2240
+ }
2241
+ path = __la_win_permissive_name_w(wname);
2242
+
2243
+ if (st == NULL) {
2244
+ /*
2245
+ * Get metadata through GetFileInformationByHandle().
2246
+ */
2247
+ if (fd >= 0) {
2248
+ h = (HANDLE)_get_osfhandle(fd);
2249
+ r = GetFileInformationByHandle(h, &bhfi);
2250
+ if (r == 0) {
2251
+ la_dosmaperr(GetLastError());
2252
+ archive_set_error(&a->archive, errno,
2253
+ "Can't GetFileInformationByHandle");
2254
+ return (ARCHIVE_FAILED);
2255
+ }
2256
+ entry_copy_bhfi(entry, path, NULL, &bhfi);
2257
+ } else {
2258
+ WIN32_FIND_DATAW findData;
2259
+ DWORD flag, desiredAccess;
2260
+
2261
+ h = FindFirstFileW(path, &findData);
2262
+ if (h == INVALID_HANDLE_VALUE) {
2263
+ la_dosmaperr(GetLastError());
2264
+ archive_set_error(&a->archive, errno,
2265
+ "Can't FindFirstFileW");
2266
+ return (ARCHIVE_FAILED);
2267
+ }
2268
+ FindClose(h);
2269
+
2270
+ flag = FILE_FLAG_BACKUP_SEMANTICS;
2271
+ if (!a->follow_symlinks &&
2272
+ (findData.dwFileAttributes
2273
+ & FILE_ATTRIBUTE_REPARSE_POINT) &&
2274
+ (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) {
2275
+ flag |= FILE_FLAG_OPEN_REPARSE_POINT;
2276
+ desiredAccess = 0;
2277
+ } else if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
2278
+ desiredAccess = 0;
2279
+ } else
2280
+ desiredAccess = GENERIC_READ;
2281
+
2282
+ h = CreateFileW(path, desiredAccess,
2283
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
2284
+ OPEN_EXISTING, flag, NULL);
2285
+ if (h == INVALID_HANDLE_VALUE) {
2286
+ la_dosmaperr(GetLastError());
2287
+ archive_set_error(&a->archive, errno,
2288
+ "Can't CreateFileW");
2289
+ return (ARCHIVE_FAILED);
2290
+ }
2291
+ r = GetFileInformationByHandle(h, &bhfi);
2292
+ if (r == 0) {
2293
+ la_dosmaperr(GetLastError());
2294
+ archive_set_error(&a->archive, errno,
2295
+ "Can't GetFileInformationByHandle");
2296
+ CloseHandle(h);
2297
+ return (ARCHIVE_FAILED);
2298
+ }
2299
+ entry_copy_bhfi(entry, path, &findData, &bhfi);
2300
+ }
2301
+ fileAttributes = bhfi.dwFileAttributes;
2302
+ } else {
2303
+ archive_entry_copy_stat(entry, st);
2304
+ if (st->st_mode & S_IFLNK)
2305
+ entry_symlink_from_pathw(entry, path);
2306
+ h = INVALID_HANDLE_VALUE;
2307
+ }
2308
+
2309
+ /* Lookup uname/gname */
2310
+ name = archive_read_disk_uname(_a, archive_entry_uid(entry));
2311
+ if (name != NULL)
2312
+ archive_entry_copy_uname(entry, name);
2313
+ name = archive_read_disk_gname(_a, archive_entry_gid(entry));
2314
+ if (name != NULL)
2315
+ archive_entry_copy_gname(entry, name);
2316
+
2317
+ /*
2318
+ * File attributes
2319
+ */
2320
+ if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0) {
2321
+ const int supported_attrs =
2322
+ FILE_ATTRIBUTE_READONLY |
2323
+ FILE_ATTRIBUTE_HIDDEN |
2324
+ FILE_ATTRIBUTE_SYSTEM;
2325
+ DWORD file_attrs = fileAttributes & supported_attrs;
2326
+ if (file_attrs != 0)
2327
+ archive_entry_set_fflags(entry, file_attrs, 0);
2328
+ }
2329
+
2330
+ /*
2331
+ * Can this file be sparse file ?
2332
+ */
2333
+ if (archive_entry_filetype(entry) != AE_IFREG
2334
+ || archive_entry_size(entry) <= 0
2335
+ || archive_entry_hardlink(entry) != NULL) {
2336
+ if (h != INVALID_HANDLE_VALUE && fd < 0)
2337
+ CloseHandle(h);
2338
+ return (ARCHIVE_OK);
2339
+ }
2340
+
2341
+ if (h == INVALID_HANDLE_VALUE) {
2342
+ if (fd >= 0) {
2343
+ h = (HANDLE)_get_osfhandle(fd);
2344
+ } else {
2345
+ h = CreateFileW(path, GENERIC_READ,
2346
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
2347
+ OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
2348
+ if (h == INVALID_HANDLE_VALUE) {
2349
+ la_dosmaperr(GetLastError());
2350
+ archive_set_error(&a->archive, errno,
2351
+ "Can't CreateFileW");
2352
+ return (ARCHIVE_FAILED);
2353
+ }
2354
+ }
2355
+ r = GetFileInformationByHandle(h, &bhfi);
2356
+ if (r == 0) {
2357
+ la_dosmaperr(GetLastError());
2358
+ archive_set_error(&a->archive, errno,
2359
+ "Can't GetFileInformationByHandle");
2360
+ if (h != INVALID_HANDLE_VALUE && fd < 0)
2361
+ CloseHandle(h);
2362
+ return (ARCHIVE_FAILED);
2363
+ }
2364
+ fileAttributes = bhfi.dwFileAttributes;
2365
+ }
2366
+
2367
+ /* Sparse file must be set a mark, FILE_ATTRIBUTE_SPARSE_FILE */
2368
+ if ((fileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) == 0) {
2369
+ if (fd < 0)
2370
+ CloseHandle(h);
2371
+ return (ARCHIVE_OK);
2372
+ }
2373
+
2374
+ if ((a->flags & ARCHIVE_READDISK_NO_SPARSE) == 0) {
2375
+ r = setup_sparse_from_disk(a, entry, h);
2376
+ if (fd < 0)
2377
+ CloseHandle(h);
2378
+ }
2379
+
2380
+ return (r);
2381
+ }
2382
+
2383
+ /*
2384
+ * Windows sparse interface.
2385
+ */
2386
+ #if defined(__MINGW32__) && !defined(FSCTL_QUERY_ALLOCATED_RANGES)
2387
+ #define FSCTL_QUERY_ALLOCATED_RANGES 0x940CF
2388
+ typedef struct {
2389
+ LARGE_INTEGER FileOffset;
2390
+ LARGE_INTEGER Length;
2391
+ } FILE_ALLOCATED_RANGE_BUFFER;
2392
+ #endif
2393
+
2394
+ static int
2395
+ setup_sparse_from_disk(struct archive_read_disk *a,
2396
+ struct archive_entry *entry, HANDLE handle)
2397
+ {
2398
+ FILE_ALLOCATED_RANGE_BUFFER range, *outranges = NULL;
2399
+ size_t outranges_size;
2400
+ int64_t entry_size = archive_entry_size(entry);
2401
+ int exit_sts = ARCHIVE_OK;
2402
+
2403
+ range.FileOffset.QuadPart = 0;
2404
+ range.Length.QuadPart = entry_size;
2405
+ outranges_size = 2048;
2406
+ outranges = (FILE_ALLOCATED_RANGE_BUFFER *)malloc(outranges_size);
2407
+ if (outranges == NULL) {
2408
+ archive_set_error(&a->archive, ENOMEM,
2409
+ "Couldn't allocate memory");
2410
+ exit_sts = ARCHIVE_FATAL;
2411
+ goto exit_setup_sparse;
2412
+ }
2413
+
2414
+ for (;;) {
2415
+ DWORD retbytes;
2416
+ BOOL ret;
2417
+
2418
+ for (;;) {
2419
+ ret = DeviceIoControl(handle,
2420
+ FSCTL_QUERY_ALLOCATED_RANGES,
2421
+ &range, sizeof(range), outranges,
2422
+ (DWORD)outranges_size, &retbytes, NULL);
2423
+ if (ret == 0 && GetLastError() == ERROR_MORE_DATA) {
2424
+ free(outranges);
2425
+ outranges_size *= 2;
2426
+ outranges = (FILE_ALLOCATED_RANGE_BUFFER *)
2427
+ malloc(outranges_size);
2428
+ if (outranges == NULL) {
2429
+ archive_set_error(&a->archive, ENOMEM,
2430
+ "Couldn't allocate memory");
2431
+ exit_sts = ARCHIVE_FATAL;
2432
+ goto exit_setup_sparse;
2433
+ }
2434
+ continue;
2435
+ } else
2436
+ break;
2437
+ }
2438
+ if (ret != 0) {
2439
+ if (retbytes > 0) {
2440
+ DWORD i, n;
2441
+
2442
+ n = retbytes / sizeof(outranges[0]);
2443
+ if (n == 1 &&
2444
+ outranges[0].FileOffset.QuadPart == 0 &&
2445
+ outranges[0].Length.QuadPart == entry_size)
2446
+ break;/* This is not sparse. */
2447
+ for (i = 0; i < n; i++)
2448
+ archive_entry_sparse_add_entry(entry,
2449
+ outranges[i].FileOffset.QuadPart,
2450
+ outranges[i].Length.QuadPart);
2451
+ range.FileOffset.QuadPart =
2452
+ outranges[n-1].FileOffset.QuadPart
2453
+ + outranges[n-1].Length.QuadPart;
2454
+ range.Length.QuadPart =
2455
+ entry_size - range.FileOffset.QuadPart;
2456
+ if (range.Length.QuadPart > 0)
2457
+ continue;
2458
+ } else {
2459
+ /* The entire file is a hole. Add one data block of size 0 at the end. */
2460
+ archive_entry_sparse_add_entry(entry,
2461
+ entry_size,
2462
+ 0);
2463
+ }
2464
+ break;
2465
+ } else {
2466
+ la_dosmaperr(GetLastError());
2467
+ archive_set_error(&a->archive, errno,
2468
+ "DeviceIoControl Failed: %lu", GetLastError());
2469
+ exit_sts = ARCHIVE_FAILED;
2470
+ goto exit_setup_sparse;
2471
+ }
2472
+ }
2473
+ exit_setup_sparse:
2474
+ free(outranges);
2475
+
2476
+ return (exit_sts);
2477
+ }
2478
+
2479
+ #endif