archive_read_disk_entry_from_file.c 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240
  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. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
  16. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  17. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  18. * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
  19. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  24. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include "archive_platform.h"
  27. __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 201084 2009-12-28 02:14:09Z kientzle $");
  28. /* This is the tree-walking code for POSIX systems. */
  29. #if !defined(_WIN32) || defined(__CYGWIN__)
  30. #ifdef HAVE_SYS_TYPES_H
  31. /* Mac OSX requires sys/types.h before sys/acl.h. */
  32. #include <sys/types.h>
  33. #endif
  34. #ifdef HAVE_SYS_ACL_H
  35. #include <sys/acl.h>
  36. #endif
  37. #ifdef HAVE_SYS_EXTATTR_H
  38. #include <sys/extattr.h>
  39. #endif
  40. #ifdef HAVE_SYS_IOCTL_H
  41. #include <sys/ioctl.h>
  42. #endif
  43. #ifdef HAVE_SYS_PARAM_H
  44. #include <sys/param.h>
  45. #endif
  46. #ifdef HAVE_SYS_STAT_H
  47. #include <sys/stat.h>
  48. #endif
  49. #if defined(HAVE_SYS_XATTR_H)
  50. #include <sys/xattr.h>
  51. #elif defined(HAVE_ATTR_XATTR_H)
  52. #include <attr/xattr.h>
  53. #endif
  54. #ifdef HAVE_SYS_EA_H
  55. #include <sys/ea.h>
  56. #endif
  57. #ifdef HAVE_ACL_LIBACL_H
  58. #include <acl/libacl.h>
  59. #endif
  60. #ifdef HAVE_COPYFILE_H
  61. #include <copyfile.h>
  62. #endif
  63. #ifdef HAVE_ERRNO_H
  64. #include <errno.h>
  65. #endif
  66. #ifdef HAVE_FCNTL_H
  67. #include <fcntl.h>
  68. #endif
  69. #ifdef HAVE_LIMITS_H
  70. #include <limits.h>
  71. #endif
  72. #ifdef HAVE_LINUX_TYPES_H
  73. #include <linux/types.h>
  74. #endif
  75. #ifdef HAVE_LINUX_FIEMAP_H
  76. #include <linux/fiemap.h>
  77. #endif
  78. #ifdef HAVE_LINUX_FS_H
  79. #include <linux/fs.h>
  80. #endif
  81. /*
  82. * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
  83. * As the include guards don't agree, the order of include is important.
  84. */
  85. #ifdef HAVE_LINUX_EXT2_FS_H
  86. #include <linux/ext2_fs.h> /* for Linux file flags */
  87. #endif
  88. #if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
  89. #include <ext2fs/ext2_fs.h> /* Linux file flags, broken on Cygwin */
  90. #endif
  91. #ifdef HAVE_PATHS_H
  92. #include <paths.h>
  93. #endif
  94. #ifdef HAVE_UNISTD_H
  95. #include <unistd.h>
  96. #endif
  97. #include "archive.h"
  98. #include "archive_entry.h"
  99. #include "archive_private.h"
  100. #include "archive_read_disk_private.h"
  101. #ifndef O_CLOEXEC
  102. #define O_CLOEXEC 0
  103. #endif
  104. /*
  105. * Linux and FreeBSD plug this obvious hole in POSIX.1e in
  106. * different ways.
  107. */
  108. #if HAVE_ACL_GET_PERM
  109. #define ACL_GET_PERM acl_get_perm
  110. #elif HAVE_ACL_GET_PERM_NP
  111. #define ACL_GET_PERM acl_get_perm_np
  112. #endif
  113. static int setup_acls(struct archive_read_disk *,
  114. struct archive_entry *, int *fd);
  115. static int setup_mac_metadata(struct archive_read_disk *,
  116. struct archive_entry *, int *fd);
  117. static int setup_xattrs(struct archive_read_disk *,
  118. struct archive_entry *, int *fd);
  119. static int setup_sparse(struct archive_read_disk *,
  120. struct archive_entry *, int *fd);
  121. int
  122. archive_read_disk_entry_from_file(struct archive *_a,
  123. struct archive_entry *entry,
  124. int fd,
  125. const struct stat *st)
  126. {
  127. struct archive_read_disk *a = (struct archive_read_disk *)_a;
  128. const char *path, *name;
  129. struct stat s;
  130. int initial_fd = fd;
  131. int r, r1;
  132. archive_clear_error(_a);
  133. path = archive_entry_sourcepath(entry);
  134. if (path == NULL)
  135. path = archive_entry_pathname(entry);
  136. if (a->tree == NULL) {
  137. if (st == NULL) {
  138. #if HAVE_FSTAT
  139. if (fd >= 0) {
  140. if (fstat(fd, &s) != 0) {
  141. archive_set_error(&a->archive, errno,
  142. "Can't fstat");
  143. return (ARCHIVE_FAILED);
  144. }
  145. } else
  146. #endif
  147. #if HAVE_LSTAT
  148. if (!a->follow_symlinks) {
  149. if (lstat(path, &s) != 0) {
  150. archive_set_error(&a->archive, errno,
  151. "Can't lstat %s", path);
  152. return (ARCHIVE_FAILED);
  153. }
  154. } else
  155. #endif
  156. if (stat(path, &s) != 0) {
  157. archive_set_error(&a->archive, errno,
  158. "Can't stat %s", path);
  159. return (ARCHIVE_FAILED);
  160. }
  161. st = &s;
  162. }
  163. archive_entry_copy_stat(entry, st);
  164. }
  165. /* Lookup uname/gname */
  166. name = archive_read_disk_uname(_a, archive_entry_uid(entry));
  167. if (name != NULL)
  168. archive_entry_copy_uname(entry, name);
  169. name = archive_read_disk_gname(_a, archive_entry_gid(entry));
  170. if (name != NULL)
  171. archive_entry_copy_gname(entry, name);
  172. #ifdef HAVE_STRUCT_STAT_ST_FLAGS
  173. /* On FreeBSD, we get flags for free with the stat. */
  174. /* TODO: Does this belong in copy_stat()? */
  175. if (st->st_flags != 0)
  176. archive_entry_set_fflags(entry, st->st_flags, 0);
  177. #endif
  178. #if defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
  179. /* Linux requires an extra ioctl to pull the flags. Although
  180. * this is an extra step, it has a nice side-effect: We get an
  181. * open file descriptor which we can use in the subsequent lookups. */
  182. if ((S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) {
  183. if (fd < 0) {
  184. if (a->tree != NULL)
  185. fd = a->open_on_current_dir(a->tree, path,
  186. O_RDONLY | O_NONBLOCK | O_CLOEXEC);
  187. else
  188. fd = open(path, O_RDONLY | O_NONBLOCK |
  189. O_CLOEXEC);
  190. __archive_ensure_cloexec_flag(fd);
  191. }
  192. if (fd >= 0) {
  193. int stflags;
  194. r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags);
  195. if (r == 0 && stflags != 0)
  196. archive_entry_set_fflags(entry, stflags, 0);
  197. }
  198. }
  199. #endif
  200. #if defined(HAVE_READLINK) || defined(HAVE_READLINKAT)
  201. if (S_ISLNK(st->st_mode)) {
  202. size_t linkbuffer_len = st->st_size + 1;
  203. char *linkbuffer;
  204. int lnklen;
  205. linkbuffer = malloc(linkbuffer_len);
  206. if (linkbuffer == NULL) {
  207. archive_set_error(&a->archive, ENOMEM,
  208. "Couldn't read link data");
  209. return (ARCHIVE_FAILED);
  210. }
  211. if (a->tree != NULL) {
  212. #ifdef HAVE_READLINKAT
  213. lnklen = readlinkat(a->tree_current_dir_fd(a->tree),
  214. path, linkbuffer, linkbuffer_len);
  215. #else
  216. if (a->tree_enter_working_dir(a->tree) != 0) {
  217. archive_set_error(&a->archive, errno,
  218. "Couldn't read link data");
  219. free(linkbuffer);
  220. return (ARCHIVE_FAILED);
  221. }
  222. lnklen = readlink(path, linkbuffer, linkbuffer_len);
  223. #endif /* HAVE_READLINKAT */
  224. } else
  225. lnklen = readlink(path, linkbuffer, linkbuffer_len);
  226. if (lnklen < 0) {
  227. archive_set_error(&a->archive, errno,
  228. "Couldn't read link data");
  229. free(linkbuffer);
  230. return (ARCHIVE_FAILED);
  231. }
  232. linkbuffer[lnklen] = 0;
  233. archive_entry_set_symlink(entry, linkbuffer);
  234. free(linkbuffer);
  235. }
  236. #endif /* HAVE_READLINK || HAVE_READLINKAT */
  237. r = setup_acls(a, entry, &fd);
  238. r1 = setup_xattrs(a, entry, &fd);
  239. if (r1 < r)
  240. r = r1;
  241. if (a->enable_copyfile) {
  242. r1 = setup_mac_metadata(a, entry, &fd);
  243. if (r1 < r)
  244. r = r1;
  245. }
  246. r1 = setup_sparse(a, entry, &fd);
  247. if (r1 < r)
  248. r = r1;
  249. /* If we opened the file earlier in this function, close it. */
  250. if (initial_fd != fd)
  251. close(fd);
  252. return (r);
  253. }
  254. #if defined(__APPLE__) && defined(HAVE_COPYFILE_H)
  255. /*
  256. * The Mac OS "copyfile()" API copies the extended metadata for a
  257. * file into a separate file in AppleDouble format (see RFC 1740).
  258. *
  259. * Mac OS tar and cpio implementations store this extended
  260. * metadata as a separate entry just before the regular entry
  261. * with a "._" prefix added to the filename.
  262. *
  263. * Note that this is currently done unconditionally; the tar program has
  264. * an option to discard this information before the archive is written.
  265. *
  266. * TODO: If there's a failure, report it and return ARCHIVE_WARN.
  267. */
  268. static int
  269. setup_mac_metadata(struct archive_read_disk *a,
  270. struct archive_entry *entry, int *fd)
  271. {
  272. int tempfd = -1;
  273. int copyfile_flags = COPYFILE_NOFOLLOW | COPYFILE_ACL | COPYFILE_XATTR;
  274. struct stat copyfile_stat;
  275. int ret = ARCHIVE_OK;
  276. void *buff = NULL;
  277. int have_attrs;
  278. const char *name, *tempdir;
  279. struct archive_string tempfile;
  280. (void)fd; /* UNUSED */
  281. name = archive_entry_sourcepath(entry);
  282. if (name == NULL)
  283. name = archive_entry_pathname(entry);
  284. if (name == NULL) {
  285. archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
  286. "Can't open file to read extended attributes: No name");
  287. return (ARCHIVE_WARN);
  288. }
  289. if (a->tree != NULL) {
  290. if (a->tree_enter_working_dir(a->tree) != 0) {
  291. archive_set_error(&a->archive, errno,
  292. "Couldn't change dir");
  293. return (ARCHIVE_FAILED);
  294. }
  295. }
  296. /* Short-circuit if there's nothing to do. */
  297. have_attrs = copyfile(name, NULL, 0, copyfile_flags | COPYFILE_CHECK);
  298. if (have_attrs == -1) {
  299. archive_set_error(&a->archive, errno,
  300. "Could not check extended attributes");
  301. return (ARCHIVE_WARN);
  302. }
  303. if (have_attrs == 0)
  304. return (ARCHIVE_OK);
  305. tempdir = NULL;
  306. if (issetugid() == 0)
  307. tempdir = getenv("TMPDIR");
  308. if (tempdir == NULL)
  309. tempdir = _PATH_TMP;
  310. archive_string_init(&tempfile);
  311. archive_strcpy(&tempfile, tempdir);
  312. archive_strcat(&tempfile, "tar.md.XXXXXX");
  313. tempfd = mkstemp(tempfile.s);
  314. if (tempfd < 0) {
  315. archive_set_error(&a->archive, errno,
  316. "Could not open extended attribute file");
  317. ret = ARCHIVE_WARN;
  318. goto cleanup;
  319. }
  320. __archive_ensure_cloexec_flag(tempfd);
  321. /* XXX I wish copyfile() could pack directly to a memory
  322. * buffer; that would avoid the temp file here. For that
  323. * matter, it would be nice if fcopyfile() actually worked,
  324. * that would reduce the many open/close races here. */
  325. if (copyfile(name, tempfile.s, 0, copyfile_flags | COPYFILE_PACK)) {
  326. archive_set_error(&a->archive, errno,
  327. "Could not pack extended attributes");
  328. ret = ARCHIVE_WARN;
  329. goto cleanup;
  330. }
  331. if (fstat(tempfd, &copyfile_stat)) {
  332. archive_set_error(&a->archive, errno,
  333. "Could not check size of extended attributes");
  334. ret = ARCHIVE_WARN;
  335. goto cleanup;
  336. }
  337. buff = malloc(copyfile_stat.st_size);
  338. if (buff == NULL) {
  339. archive_set_error(&a->archive, errno,
  340. "Could not allocate memory for extended attributes");
  341. ret = ARCHIVE_WARN;
  342. goto cleanup;
  343. }
  344. if (copyfile_stat.st_size != read(tempfd, buff, copyfile_stat.st_size)) {
  345. archive_set_error(&a->archive, errno,
  346. "Could not read extended attributes into memory");
  347. ret = ARCHIVE_WARN;
  348. goto cleanup;
  349. }
  350. archive_entry_copy_mac_metadata(entry, buff, copyfile_stat.st_size);
  351. cleanup:
  352. if (tempfd >= 0) {
  353. close(tempfd);
  354. unlink(tempfile.s);
  355. }
  356. archive_string_free(&tempfile);
  357. free(buff);
  358. return (ret);
  359. }
  360. #else
  361. /*
  362. * Stub implementation for non-Mac systems.
  363. */
  364. static int
  365. setup_mac_metadata(struct archive_read_disk *a,
  366. struct archive_entry *entry, int *fd)
  367. {
  368. (void)a; /* UNUSED */
  369. (void)entry; /* UNUSED */
  370. (void)fd; /* UNUSED */
  371. return (ARCHIVE_OK);
  372. }
  373. #endif
  374. #ifdef HAVE_POSIX_ACL
  375. static int translate_acl(struct archive_read_disk *a,
  376. struct archive_entry *entry, acl_t acl, int archive_entry_acl_type);
  377. static int
  378. setup_acls(struct archive_read_disk *a,
  379. struct archive_entry *entry, int *fd)
  380. {
  381. const char *accpath;
  382. acl_t acl;
  383. #if HAVE_ACL_IS_TRIVIAL_NP
  384. int r;
  385. #endif
  386. accpath = archive_entry_sourcepath(entry);
  387. if (accpath == NULL)
  388. accpath = archive_entry_pathname(entry);
  389. archive_entry_acl_clear(entry);
  390. #ifdef ACL_TYPE_NFS4
  391. /* Try NFS4 ACL first. */
  392. if (*fd >= 0)
  393. acl = acl_get_fd(*fd);
  394. #if HAVE_ACL_GET_LINK_NP
  395. else if (!a->follow_symlinks)
  396. acl = acl_get_link_np(accpath, ACL_TYPE_NFS4);
  397. #else
  398. else if ((!a->follow_symlinks)
  399. && (archive_entry_filetype(entry) == AE_IFLNK))
  400. /* We can't get the ACL of a symlink, so we assume it can't
  401. have one. */
  402. acl = NULL;
  403. #endif
  404. else
  405. acl = acl_get_file(accpath, ACL_TYPE_NFS4);
  406. #if HAVE_ACL_IS_TRIVIAL_NP
  407. /* Ignore "trivial" ACLs that just mirror the file mode. */
  408. acl_is_trivial_np(acl, &r);
  409. if (r) {
  410. acl_free(acl);
  411. acl = NULL;
  412. }
  413. #endif
  414. if (acl != NULL) {
  415. translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
  416. acl_free(acl);
  417. return (ARCHIVE_OK);
  418. }
  419. #endif
  420. /* Retrieve access ACL from file. */
  421. if (*fd >= 0)
  422. acl = acl_get_fd(*fd);
  423. #if HAVE_ACL_GET_LINK_NP
  424. else if (!a->follow_symlinks)
  425. acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS);
  426. #else
  427. else if ((!a->follow_symlinks)
  428. && (archive_entry_filetype(entry) == AE_IFLNK))
  429. /* We can't get the ACL of a symlink, so we assume it can't
  430. have one. */
  431. acl = NULL;
  432. #endif
  433. else
  434. acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
  435. if (acl != NULL) {
  436. translate_acl(a, entry, acl,
  437. ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
  438. acl_free(acl);
  439. }
  440. /* Only directories can have default ACLs. */
  441. if (S_ISDIR(archive_entry_mode(entry))) {
  442. acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
  443. if (acl != NULL) {
  444. translate_acl(a, entry, acl,
  445. ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
  446. acl_free(acl);
  447. }
  448. }
  449. return (ARCHIVE_OK);
  450. }
  451. /*
  452. * Translate system ACL into libarchive internal structure.
  453. */
  454. static struct {
  455. int archive_perm;
  456. int platform_perm;
  457. } acl_perm_map[] = {
  458. {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
  459. {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
  460. {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
  461. #ifdef ACL_TYPE_NFS4
  462. {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
  463. {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
  464. {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
  465. {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
  466. {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
  467. {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
  468. {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
  469. {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
  470. {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
  471. {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
  472. {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
  473. {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
  474. {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
  475. {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
  476. {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
  477. {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
  478. #endif
  479. };
  480. #ifdef ACL_TYPE_NFS4
  481. static struct {
  482. int archive_inherit;
  483. int platform_inherit;
  484. } acl_inherit_map[] = {
  485. {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
  486. {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
  487. {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
  488. {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}
  489. };
  490. #endif
  491. static int
  492. translate_acl(struct archive_read_disk *a,
  493. struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
  494. {
  495. acl_tag_t acl_tag;
  496. #ifdef ACL_TYPE_NFS4
  497. acl_entry_type_t acl_type;
  498. acl_flagset_t acl_flagset;
  499. int brand, r;
  500. #endif
  501. acl_entry_t acl_entry;
  502. acl_permset_t acl_permset;
  503. int i, entry_acl_type;
  504. int s, ae_id, ae_tag, ae_perm;
  505. const char *ae_name;
  506. #ifdef ACL_TYPE_NFS4
  507. // FreeBSD "brands" ACLs as POSIX.1e or NFSv4
  508. // Make sure the "brand" on this ACL is consistent
  509. // with the default_entry_acl_type bits provided.
  510. acl_get_brand_np(acl, &brand);
  511. switch (brand) {
  512. case ACL_BRAND_POSIX:
  513. switch (default_entry_acl_type) {
  514. case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
  515. case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
  516. break;
  517. default:
  518. // XXX set warning message?
  519. return ARCHIVE_FAILED;
  520. }
  521. break;
  522. case ACL_BRAND_NFS4:
  523. if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
  524. // XXX set warning message?
  525. return ARCHIVE_FAILED;
  526. }
  527. break;
  528. default:
  529. // XXX set warning message?
  530. return ARCHIVE_FAILED;
  531. break;
  532. }
  533. #endif
  534. s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
  535. while (s == 1) {
  536. ae_id = -1;
  537. ae_name = NULL;
  538. ae_perm = 0;
  539. acl_get_tag_type(acl_entry, &acl_tag);
  540. switch (acl_tag) {
  541. case ACL_USER:
  542. ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry);
  543. ae_name = archive_read_disk_uname(&a->archive, ae_id);
  544. ae_tag = ARCHIVE_ENTRY_ACL_USER;
  545. break;
  546. case ACL_GROUP:
  547. ae_id = (int)*(gid_t *)acl_get_qualifier(acl_entry);
  548. ae_name = archive_read_disk_gname(&a->archive, ae_id);
  549. ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
  550. break;
  551. case ACL_MASK:
  552. ae_tag = ARCHIVE_ENTRY_ACL_MASK;
  553. break;
  554. case ACL_USER_OBJ:
  555. ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
  556. break;
  557. case ACL_GROUP_OBJ:
  558. ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
  559. break;
  560. case ACL_OTHER:
  561. ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
  562. break;
  563. #ifdef ACL_TYPE_NFS4
  564. case ACL_EVERYONE:
  565. ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
  566. break;
  567. #endif
  568. default:
  569. /* Skip types that libarchive can't support. */
  570. s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
  571. continue;
  572. }
  573. // XXX acl type maps to allow/deny/audit/YYYY bits
  574. // XXX acl_get_entry_type_np on FreeBSD returns EINVAL for
  575. // non-NFSv4 ACLs
  576. entry_acl_type = default_entry_acl_type;
  577. #ifdef ACL_TYPE_NFS4
  578. r = acl_get_entry_type_np(acl_entry, &acl_type);
  579. if (r == 0) {
  580. switch (acl_type) {
  581. case ACL_ENTRY_TYPE_ALLOW:
  582. entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
  583. break;
  584. case ACL_ENTRY_TYPE_DENY:
  585. entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
  586. break;
  587. case ACL_ENTRY_TYPE_AUDIT:
  588. entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
  589. break;
  590. case ACL_ENTRY_TYPE_ALARM:
  591. entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
  592. break;
  593. }
  594. }
  595. /*
  596. * Libarchive stores "flag" (NFSv4 inheritance bits)
  597. * in the ae_perm bitmap.
  598. */
  599. acl_get_flagset_np(acl_entry, &acl_flagset);
  600. for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
  601. if (acl_get_flag_np(acl_flagset,
  602. acl_inherit_map[i].platform_inherit))
  603. ae_perm |= acl_inherit_map[i].archive_inherit;
  604. }
  605. #endif
  606. acl_get_permset(acl_entry, &acl_permset);
  607. for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
  608. /*
  609. * acl_get_perm() is spelled differently on different
  610. * platforms; see above.
  611. */
  612. if (ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm))
  613. ae_perm |= acl_perm_map[i].archive_perm;
  614. }
  615. archive_entry_acl_add_entry(entry, entry_acl_type,
  616. ae_perm, ae_tag,
  617. ae_id, ae_name);
  618. s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
  619. }
  620. return (ARCHIVE_OK);
  621. }
  622. #else
  623. static int
  624. setup_acls(struct archive_read_disk *a,
  625. struct archive_entry *entry, int *fd)
  626. {
  627. (void)a; /* UNUSED */
  628. (void)entry; /* UNUSED */
  629. (void)fd; /* UNUSED */
  630. return (ARCHIVE_OK);
  631. }
  632. #endif
  633. #if (HAVE_FGETXATTR && HAVE_FLISTXATTR && HAVE_LISTXATTR && \
  634. HAVE_LLISTXATTR && HAVE_GETXATTR && HAVE_LGETXATTR) || \
  635. (HAVE_FGETEA && HAVE_FLISTEA && HAVE_LISTEA)
  636. /*
  637. * Linux and AIX extended attribute support.
  638. *
  639. * TODO: By using a stack-allocated buffer for the first
  640. * call to getxattr(), we might be able to avoid the second
  641. * call entirely. We only need the second call if the
  642. * stack-allocated buffer is too small. But a modest buffer
  643. * of 1024 bytes or so will often be big enough. Same applies
  644. * to listxattr().
  645. */
  646. static int
  647. setup_xattr(struct archive_read_disk *a,
  648. struct archive_entry *entry, const char *name, int fd)
  649. {
  650. ssize_t size;
  651. void *value = NULL;
  652. const char *accpath;
  653. accpath = archive_entry_sourcepath(entry);
  654. if (accpath == NULL)
  655. accpath = archive_entry_pathname(entry);
  656. #if HAVE_FGETXATTR
  657. if (fd >= 0)
  658. size = fgetxattr(fd, name, NULL, 0);
  659. else if (!a->follow_symlinks)
  660. size = lgetxattr(accpath, name, NULL, 0);
  661. else
  662. size = getxattr(accpath, name, NULL, 0);
  663. #elif HAVE_FGETEA
  664. if (fd >= 0)
  665. size = fgetea(fd, name, NULL, 0);
  666. else if (!a->follow_symlinks)
  667. size = lgetea(accpath, name, NULL, 0);
  668. else
  669. size = getea(accpath, name, NULL, 0);
  670. #endif
  671. if (size == -1) {
  672. archive_set_error(&a->archive, errno,
  673. "Couldn't query extended attribute");
  674. return (ARCHIVE_WARN);
  675. }
  676. if (size > 0 && (value = malloc(size)) == NULL) {
  677. archive_set_error(&a->archive, errno, "Out of memory");
  678. return (ARCHIVE_FATAL);
  679. }
  680. #if HAVE_FGETXATTR
  681. if (fd >= 0)
  682. size = fgetxattr(fd, name, value, size);
  683. else if (!a->follow_symlinks)
  684. size = lgetxattr(accpath, name, value, size);
  685. else
  686. size = getxattr(accpath, name, value, size);
  687. #elif HAVE_FGETEA
  688. if (fd >= 0)
  689. size = fgetea(fd, name, value, size);
  690. else if (!a->follow_symlinks)
  691. size = lgetea(accpath, name, value, size);
  692. else
  693. size = getea(accpath, name, value, size);
  694. #endif
  695. if (size == -1) {
  696. archive_set_error(&a->archive, errno,
  697. "Couldn't read extended attribute");
  698. return (ARCHIVE_WARN);
  699. }
  700. archive_entry_xattr_add_entry(entry, name, value, size);
  701. free(value);
  702. return (ARCHIVE_OK);
  703. }
  704. static int
  705. setup_xattrs(struct archive_read_disk *a,
  706. struct archive_entry *entry, int *fd)
  707. {
  708. char *list, *p;
  709. const char *path;
  710. ssize_t list_size;
  711. path = archive_entry_sourcepath(entry);
  712. if (path == NULL)
  713. path = archive_entry_pathname(entry);
  714. if (*fd < 0 && a->tree != NULL) {
  715. if (a->follow_symlinks ||
  716. archive_entry_filetype(entry) != AE_IFLNK)
  717. *fd = a->open_on_current_dir(a->tree, path,
  718. O_RDONLY | O_NONBLOCK);
  719. if (*fd < 0) {
  720. if (a->tree_enter_working_dir(a->tree) != 0) {
  721. archive_set_error(&a->archive, errno,
  722. "Couldn't access %s", path);
  723. return (ARCHIVE_FAILED);
  724. }
  725. }
  726. }
  727. #if HAVE_FLISTXATTR
  728. if (*fd >= 0)
  729. list_size = flistxattr(*fd, NULL, 0);
  730. else if (!a->follow_symlinks)
  731. list_size = llistxattr(path, NULL, 0);
  732. else
  733. list_size = listxattr(path, NULL, 0);
  734. #elif HAVE_FLISTEA
  735. if (*fd >= 0)
  736. list_size = flistea(*fd, NULL, 0);
  737. else if (!a->follow_symlinks)
  738. list_size = llistea(path, NULL, 0);
  739. else
  740. list_size = listea(path, NULL, 0);
  741. #endif
  742. if (list_size == -1) {
  743. if (errno == ENOTSUP || errno == ENOSYS)
  744. return (ARCHIVE_OK);
  745. archive_set_error(&a->archive, errno,
  746. "Couldn't list extended attributes");
  747. return (ARCHIVE_WARN);
  748. }
  749. if (list_size == 0)
  750. return (ARCHIVE_OK);
  751. if ((list = malloc(list_size)) == NULL) {
  752. archive_set_error(&a->archive, errno, "Out of memory");
  753. return (ARCHIVE_FATAL);
  754. }
  755. #if HAVE_FLISTXATTR
  756. if (*fd >= 0)
  757. list_size = flistxattr(*fd, list, list_size);
  758. else if (!a->follow_symlinks)
  759. list_size = llistxattr(path, list, list_size);
  760. else
  761. list_size = listxattr(path, list, list_size);
  762. #elif HAVE_FLISTEA
  763. if (*fd >= 0)
  764. list_size = flistea(*fd, list, list_size);
  765. else if (!a->follow_symlinks)
  766. list_size = llistea(path, list, list_size);
  767. else
  768. list_size = listea(path, list, list_size);
  769. #endif
  770. if (list_size == -1) {
  771. archive_set_error(&a->archive, errno,
  772. "Couldn't retrieve extended attributes");
  773. free(list);
  774. return (ARCHIVE_WARN);
  775. }
  776. for (p = list; (p - list) < list_size; p += strlen(p) + 1) {
  777. if (strncmp(p, "system.", 7) == 0 ||
  778. strncmp(p, "xfsroot.", 8) == 0)
  779. continue;
  780. setup_xattr(a, entry, p, *fd);
  781. }
  782. free(list);
  783. return (ARCHIVE_OK);
  784. }
  785. #elif HAVE_EXTATTR_GET_FILE && HAVE_EXTATTR_LIST_FILE && \
  786. HAVE_DECL_EXTATTR_NAMESPACE_USER
  787. /*
  788. * FreeBSD extattr interface.
  789. */
  790. /* TODO: Implement this. Follow the Linux model above, but
  791. * with FreeBSD-specific system calls, of course. Be careful
  792. * to not include the system extattrs that hold ACLs; we handle
  793. * those separately.
  794. */
  795. static int
  796. setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
  797. int namespace, const char *name, const char *fullname, int fd);
  798. static int
  799. setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
  800. int namespace, const char *name, const char *fullname, int fd)
  801. {
  802. ssize_t size;
  803. void *value = NULL;
  804. const char *accpath;
  805. accpath = archive_entry_sourcepath(entry);
  806. if (accpath == NULL)
  807. accpath = archive_entry_pathname(entry);
  808. if (fd >= 0)
  809. size = extattr_get_fd(fd, namespace, name, NULL, 0);
  810. else if (!a->follow_symlinks)
  811. size = extattr_get_link(accpath, namespace, name, NULL, 0);
  812. else
  813. size = extattr_get_file(accpath, namespace, name, NULL, 0);
  814. if (size == -1) {
  815. archive_set_error(&a->archive, errno,
  816. "Couldn't query extended attribute");
  817. return (ARCHIVE_WARN);
  818. }
  819. if (size > 0 && (value = malloc(size)) == NULL) {
  820. archive_set_error(&a->archive, errno, "Out of memory");
  821. return (ARCHIVE_FATAL);
  822. }
  823. if (fd >= 0)
  824. size = extattr_get_fd(fd, namespace, name, value, size);
  825. else if (!a->follow_symlinks)
  826. size = extattr_get_link(accpath, namespace, name, value, size);
  827. else
  828. size = extattr_get_file(accpath, namespace, name, value, size);
  829. if (size == -1) {
  830. free(value);
  831. archive_set_error(&a->archive, errno,
  832. "Couldn't read extended attribute");
  833. return (ARCHIVE_WARN);
  834. }
  835. archive_entry_xattr_add_entry(entry, fullname, value, size);
  836. free(value);
  837. return (ARCHIVE_OK);
  838. }
  839. static int
  840. setup_xattrs(struct archive_read_disk *a,
  841. struct archive_entry *entry, int *fd)
  842. {
  843. char buff[512];
  844. char *list, *p;
  845. ssize_t list_size;
  846. const char *path;
  847. int namespace = EXTATTR_NAMESPACE_USER;
  848. path = archive_entry_sourcepath(entry);
  849. if (path == NULL)
  850. path = archive_entry_pathname(entry);
  851. if (*fd < 0 && a->tree != NULL) {
  852. if (a->follow_symlinks ||
  853. archive_entry_filetype(entry) != AE_IFLNK)
  854. *fd = a->open_on_current_dir(a->tree, path,
  855. O_RDONLY | O_NONBLOCK);
  856. if (*fd < 0) {
  857. if (a->tree_enter_working_dir(a->tree) != 0) {
  858. archive_set_error(&a->archive, errno,
  859. "Couldn't access %s", path);
  860. return (ARCHIVE_FAILED);
  861. }
  862. }
  863. }
  864. if (*fd >= 0)
  865. list_size = extattr_list_fd(*fd, namespace, NULL, 0);
  866. else if (!a->follow_symlinks)
  867. list_size = extattr_list_link(path, namespace, NULL, 0);
  868. else
  869. list_size = extattr_list_file(path, namespace, NULL, 0);
  870. if (list_size == -1 && errno == EOPNOTSUPP)
  871. return (ARCHIVE_OK);
  872. if (list_size == -1) {
  873. archive_set_error(&a->archive, errno,
  874. "Couldn't list extended attributes");
  875. return (ARCHIVE_WARN);
  876. }
  877. if (list_size == 0)
  878. return (ARCHIVE_OK);
  879. if ((list = malloc(list_size)) == NULL) {
  880. archive_set_error(&a->archive, errno, "Out of memory");
  881. return (ARCHIVE_FATAL);
  882. }
  883. if (*fd >= 0)
  884. list_size = extattr_list_fd(*fd, namespace, list, list_size);
  885. else if (!a->follow_symlinks)
  886. list_size = extattr_list_link(path, namespace, list, list_size);
  887. else
  888. list_size = extattr_list_file(path, namespace, list, list_size);
  889. if (list_size == -1) {
  890. archive_set_error(&a->archive, errno,
  891. "Couldn't retrieve extended attributes");
  892. free(list);
  893. return (ARCHIVE_WARN);
  894. }
  895. p = list;
  896. while ((p - list) < list_size) {
  897. size_t len = 255 & (int)*p;
  898. char *name;
  899. strcpy(buff, "user.");
  900. name = buff + strlen(buff);
  901. memcpy(name, p + 1, len);
  902. name[len] = '\0';
  903. setup_xattr(a, entry, namespace, name, buff, *fd);
  904. p += 1 + len;
  905. }
  906. free(list);
  907. return (ARCHIVE_OK);
  908. }
  909. #else
  910. /*
  911. * Generic (stub) extended attribute support.
  912. */
  913. static int
  914. setup_xattrs(struct archive_read_disk *a,
  915. struct archive_entry *entry, int *fd)
  916. {
  917. (void)a; /* UNUSED */
  918. (void)entry; /* UNUSED */
  919. (void)fd; /* UNUSED */
  920. return (ARCHIVE_OK);
  921. }
  922. #endif
  923. #if defined(HAVE_LINUX_FIEMAP_H)
  924. /*
  925. * Linux sparse interface.
  926. *
  927. * The FIEMAP ioctl returns an "extent" for each physical allocation
  928. * on disk. We need to process those to generate a more compact list
  929. * of logical file blocks. We also need to be very careful to use
  930. * FIEMAP_FLAG_SYNC here, since there are reports that Linux sometimes
  931. * does not report allocations for newly-written data that hasn't
  932. * been synced to disk.
  933. *
  934. * It's important to return a minimal sparse file list because we want
  935. * to not trigger sparse file extensions if we don't have to, since
  936. * not all readers support them.
  937. */
  938. static int
  939. setup_sparse(struct archive_read_disk *a,
  940. struct archive_entry *entry, int *fd)
  941. {
  942. char buff[4096];
  943. struct fiemap *fm;
  944. struct fiemap_extent *fe;
  945. int64_t size;
  946. int count, do_fiemap;
  947. int exit_sts = ARCHIVE_OK;
  948. if (archive_entry_filetype(entry) != AE_IFREG
  949. || archive_entry_size(entry) <= 0
  950. || archive_entry_hardlink(entry) != NULL)
  951. return (ARCHIVE_OK);
  952. if (*fd < 0) {
  953. const char *path;
  954. path = archive_entry_sourcepath(entry);
  955. if (path == NULL)
  956. path = archive_entry_pathname(entry);
  957. if (a->tree != NULL)
  958. *fd = a->open_on_current_dir(a->tree, path,
  959. O_RDONLY | O_NONBLOCK | O_CLOEXEC);
  960. else
  961. *fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
  962. if (*fd < 0) {
  963. archive_set_error(&a->archive, errno,
  964. "Can't open `%s'", path);
  965. return (ARCHIVE_FAILED);
  966. }
  967. __archive_ensure_cloexec_flag(*fd);
  968. }
  969. /* Initialize buffer to avoid the error valgrind complains about. */
  970. memset(buff, 0, sizeof(buff));
  971. count = (sizeof(buff) - sizeof(*fm))/sizeof(*fe);
  972. fm = (struct fiemap *)buff;
  973. fm->fm_start = 0;
  974. fm->fm_length = ~0ULL;;
  975. fm->fm_flags = FIEMAP_FLAG_SYNC;
  976. fm->fm_extent_count = count;
  977. do_fiemap = 1;
  978. size = archive_entry_size(entry);
  979. for (;;) {
  980. int i, r;
  981. r = ioctl(*fd, FS_IOC_FIEMAP, fm);
  982. if (r < 0) {
  983. /* When something error happens, it is better we
  984. * should return ARCHIVE_OK because an earlier
  985. * version(<2.6.28) cannot perfom FS_IOC_FIEMAP. */
  986. goto exit_setup_sparse;
  987. }
  988. if (fm->fm_mapped_extents == 0)
  989. break;
  990. fe = fm->fm_extents;
  991. for (i = 0; i < (int)fm->fm_mapped_extents; i++, fe++) {
  992. if (!(fe->fe_flags & FIEMAP_EXTENT_UNWRITTEN)) {
  993. /* The fe_length of the last block does not
  994. * adjust itself to its size files. */
  995. int64_t length = fe->fe_length;
  996. if (fe->fe_logical + length > (uint64_t)size)
  997. length -= fe->fe_logical + length - size;
  998. if (fe->fe_logical == 0 && length == size) {
  999. /* This is not sparse. */
  1000. do_fiemap = 0;
  1001. break;
  1002. }
  1003. if (length > 0)
  1004. archive_entry_sparse_add_entry(entry,
  1005. fe->fe_logical, length);
  1006. }
  1007. if (fe->fe_flags & FIEMAP_EXTENT_LAST)
  1008. do_fiemap = 0;
  1009. }
  1010. if (do_fiemap) {
  1011. fe = fm->fm_extents + fm->fm_mapped_extents -1;
  1012. fm->fm_start = fe->fe_logical + fe->fe_length;
  1013. } else
  1014. break;
  1015. }
  1016. exit_setup_sparse:
  1017. return (exit_sts);
  1018. }
  1019. #elif defined(SEEK_HOLE) && defined(SEEK_DATA) && defined(_PC_MIN_HOLE_SIZE)
  1020. /*
  1021. * FreeBSD and Solaris sparse interface.
  1022. */
  1023. static int
  1024. setup_sparse(struct archive_read_disk *a,
  1025. struct archive_entry *entry, int *fd)
  1026. {
  1027. int64_t size;
  1028. off_t initial_off; /* FreeBSD/Solaris only, so off_t okay here */
  1029. off_t off_s, off_e; /* FreeBSD/Solaris only, so off_t okay here */
  1030. int exit_sts = ARCHIVE_OK;
  1031. if (archive_entry_filetype(entry) != AE_IFREG
  1032. || archive_entry_size(entry) <= 0
  1033. || archive_entry_hardlink(entry) != NULL)
  1034. return (ARCHIVE_OK);
  1035. /* Does filesystem support the reporting of hole ? */
  1036. if (*fd < 0 && a->tree != NULL) {
  1037. const char *path;
  1038. path = archive_entry_sourcepath(entry);
  1039. if (path == NULL)
  1040. path = archive_entry_pathname(entry);
  1041. *fd = a->open_on_current_dir(a->tree, path,
  1042. O_RDONLY | O_NONBLOCK);
  1043. if (*fd < 0) {
  1044. archive_set_error(&a->archive, errno,
  1045. "Can't open `%s'", path);
  1046. return (ARCHIVE_FAILED);
  1047. }
  1048. }
  1049. if (*fd >= 0) {
  1050. if (fpathconf(*fd, _PC_MIN_HOLE_SIZE) <= 0)
  1051. return (ARCHIVE_OK);
  1052. initial_off = lseek(*fd, 0, SEEK_CUR);
  1053. if (initial_off != 0)
  1054. lseek(*fd, 0, SEEK_SET);
  1055. } else {
  1056. const char *path;
  1057. path = archive_entry_sourcepath(entry);
  1058. if (path == NULL)
  1059. path = archive_entry_pathname(entry);
  1060. if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0)
  1061. return (ARCHIVE_OK);
  1062. *fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
  1063. if (*fd < 0) {
  1064. archive_set_error(&a->archive, errno,
  1065. "Can't open `%s'", path);
  1066. return (ARCHIVE_FAILED);
  1067. }
  1068. __archive_ensure_cloexec_flag(*fd);
  1069. initial_off = 0;
  1070. }
  1071. off_s = 0;
  1072. size = archive_entry_size(entry);
  1073. while (off_s < size) {
  1074. off_s = lseek(*fd, off_s, SEEK_DATA);
  1075. if (off_s == (off_t)-1) {
  1076. if (errno == ENXIO)
  1077. break;/* no more hole */
  1078. archive_set_error(&a->archive, errno,
  1079. "lseek(SEEK_HOLE) failed");
  1080. exit_sts = ARCHIVE_FAILED;
  1081. goto exit_setup_sparse;
  1082. }
  1083. off_e = lseek(*fd, off_s, SEEK_HOLE);
  1084. if (off_e == (off_t)-1) {
  1085. if (errno == ENXIO) {
  1086. off_e = lseek(*fd, 0, SEEK_END);
  1087. if (off_e != (off_t)-1)
  1088. break;/* no more data */
  1089. }
  1090. archive_set_error(&a->archive, errno,
  1091. "lseek(SEEK_DATA) failed");
  1092. exit_sts = ARCHIVE_FAILED;
  1093. goto exit_setup_sparse;
  1094. }
  1095. if (off_s == 0 && off_e == size)
  1096. break;/* This is not spase. */
  1097. archive_entry_sparse_add_entry(entry, off_s,
  1098. off_e - off_s);
  1099. off_s = off_e;
  1100. }
  1101. exit_setup_sparse:
  1102. lseek(*fd, initial_off, SEEK_SET);
  1103. return (exit_sts);
  1104. }
  1105. #else
  1106. /*
  1107. * Generic (stub) sparse support.
  1108. */
  1109. static int
  1110. setup_sparse(struct archive_read_disk *a,
  1111. struct archive_entry *entry, int *fd)
  1112. {
  1113. (void)a; /* UNUSED */
  1114. (void)entry; /* UNUSED */
  1115. (void)fd; /* UNUSED */
  1116. return (ARCHIVE_OK);
  1117. }
  1118. #endif
  1119. #endif /* !defined(_WIN32) || defined(__CYGWIN__) */