archive_disk_acl_freebsd.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
  1. /*-
  2. * Copyright (c) 2003-2009 Tim Kientzle
  3. * Copyright (c) 2010-2012 Michihiro NAKAJIMA
  4. * Copyright (c) 2017 Martin Matuska
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  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. #if ARCHIVE_ACL_FREEBSD
  29. #ifdef HAVE_ERRNO_H
  30. #include <errno.h>
  31. #endif
  32. #ifdef HAVE_FCNTL_H
  33. #include <fcntl.h>
  34. #endif
  35. #ifdef HAVE_SYS_TYPES_H
  36. #include <sys/types.h>
  37. #endif
  38. #ifdef HAVE_SYS_ACL_H
  39. #define _ACL_PRIVATE /* For debugging */
  40. #include <sys/acl.h>
  41. #endif
  42. #include "archive_entry.h"
  43. #include "archive_private.h"
  44. #include "archive_read_disk_private.h"
  45. #include "archive_write_disk_private.h"
  46. typedef struct {
  47. const int a_perm; /* Libarchive permission or flag */
  48. const int p_perm; /* Platform permission or flag */
  49. } acl_perm_map_t;
  50. static const acl_perm_map_t acl_posix_perm_map[] = {
  51. {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
  52. {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
  53. {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
  54. };
  55. static const int acl_posix_perm_map_size =
  56. (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0]));
  57. #if ARCHIVE_ACL_FREEBSD_NFS4
  58. static const acl_perm_map_t acl_nfs4_perm_map[] = {
  59. {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
  60. {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
  61. {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
  62. {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
  63. {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
  64. {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
  65. {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
  66. {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
  67. {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
  68. {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
  69. {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
  70. {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
  71. {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
  72. {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
  73. {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
  74. {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
  75. {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
  76. };
  77. static const int acl_nfs4_perm_map_size =
  78. (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
  79. static const acl_perm_map_t acl_nfs4_flag_map[] = {
  80. {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
  81. {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
  82. {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
  83. {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
  84. {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
  85. {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
  86. {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
  87. };
  88. static const int acl_nfs4_flag_map_size =
  89. (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
  90. #endif /* ARCHIVE_ACL_FREEBSD_NFS4 */
  91. static int
  92. translate_acl(struct archive_read_disk *a,
  93. struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
  94. {
  95. #if ARCHIVE_ACL_FREEBSD_NFS4
  96. int brand;
  97. acl_flagset_t acl_flagset;
  98. acl_entry_type_t acl_type;
  99. #endif
  100. acl_tag_t acl_tag;
  101. acl_entry_t acl_entry;
  102. acl_permset_t acl_permset;
  103. int i, entry_acl_type, perm_map_size;
  104. const acl_perm_map_t *perm_map;
  105. int r, s, ae_id, ae_tag, ae_perm;
  106. void *q;
  107. const char *ae_name;
  108. #if ARCHIVE_ACL_FREEBSD_NFS4
  109. // FreeBSD "brands" ACLs as POSIX.1e or NFSv4
  110. // Make sure the "brand" on this ACL is consistent
  111. // with the default_entry_acl_type bits provided.
  112. if (acl_get_brand_np(acl, &brand) != 0) {
  113. archive_set_error(&a->archive, errno,
  114. "Failed to read ACL brand");
  115. return (ARCHIVE_WARN);
  116. }
  117. switch (brand) {
  118. case ACL_BRAND_POSIX:
  119. switch (default_entry_acl_type) {
  120. case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
  121. case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
  122. break;
  123. default:
  124. archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
  125. "Invalid ACL entry type for POSIX.1e ACL");
  126. return (ARCHIVE_WARN);
  127. }
  128. break;
  129. case ACL_BRAND_NFS4:
  130. if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
  131. archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
  132. "Invalid ACL entry type for NFSv4 ACL");
  133. return (ARCHIVE_WARN);
  134. }
  135. break;
  136. default:
  137. archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
  138. "Unknown ACL brand");
  139. return (ARCHIVE_WARN);
  140. }
  141. #endif
  142. s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
  143. if (s == -1) {
  144. archive_set_error(&a->archive, errno,
  145. "Failed to get first ACL entry");
  146. return (ARCHIVE_WARN);
  147. }
  148. while (s == 1) {
  149. ae_id = -1;
  150. ae_name = NULL;
  151. ae_perm = 0;
  152. if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
  153. archive_set_error(&a->archive, errno,
  154. "Failed to get ACL tag type");
  155. return (ARCHIVE_WARN);
  156. }
  157. switch (acl_tag) {
  158. case ACL_USER:
  159. q = acl_get_qualifier(acl_entry);
  160. if (q != NULL) {
  161. ae_id = (int)*(uid_t *)q;
  162. acl_free(q);
  163. ae_name = archive_read_disk_uname(&a->archive,
  164. ae_id);
  165. }
  166. ae_tag = ARCHIVE_ENTRY_ACL_USER;
  167. break;
  168. case ACL_GROUP:
  169. q = acl_get_qualifier(acl_entry);
  170. if (q != NULL) {
  171. ae_id = (int)*(gid_t *)q;
  172. acl_free(q);
  173. ae_name = archive_read_disk_gname(&a->archive,
  174. ae_id);
  175. }
  176. ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
  177. break;
  178. case ACL_MASK:
  179. ae_tag = ARCHIVE_ENTRY_ACL_MASK;
  180. break;
  181. case ACL_USER_OBJ:
  182. ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
  183. break;
  184. case ACL_GROUP_OBJ:
  185. ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
  186. break;
  187. case ACL_OTHER:
  188. ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
  189. break;
  190. #if ARCHIVE_ACL_FREEBSD_NFS4
  191. case ACL_EVERYONE:
  192. ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
  193. break;
  194. #endif
  195. default:
  196. /* Skip types that libarchive can't support. */
  197. s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
  198. continue;
  199. }
  200. // XXX acl_type maps to allow/deny/audit/YYYY bits
  201. entry_acl_type = default_entry_acl_type;
  202. #if ARCHIVE_ACL_FREEBSD_NFS4
  203. if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
  204. /*
  205. * acl_get_entry_type_np() fails with non-NFSv4 ACLs
  206. */
  207. if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) {
  208. archive_set_error(&a->archive, errno, "Failed "
  209. "to get ACL type from a NFSv4 ACL entry");
  210. return (ARCHIVE_WARN);
  211. }
  212. switch (acl_type) {
  213. case ACL_ENTRY_TYPE_ALLOW:
  214. entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
  215. break;
  216. case ACL_ENTRY_TYPE_DENY:
  217. entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
  218. break;
  219. case ACL_ENTRY_TYPE_AUDIT:
  220. entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
  221. break;
  222. case ACL_ENTRY_TYPE_ALARM:
  223. entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
  224. break;
  225. default:
  226. archive_set_error(&a->archive, errno,
  227. "Invalid NFSv4 ACL entry type");
  228. return (ARCHIVE_WARN);
  229. }
  230. /*
  231. * Libarchive stores "flag" (NFSv4 inheritance bits)
  232. * in the ae_perm bitmap.
  233. *
  234. * acl_get_flagset_np() fails with non-NFSv4 ACLs
  235. */
  236. if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
  237. archive_set_error(&a->archive, errno,
  238. "Failed to get flagset from a NFSv4 "
  239. "ACL entry");
  240. return (ARCHIVE_WARN);
  241. }
  242. for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
  243. r = acl_get_flag_np(acl_flagset,
  244. acl_nfs4_flag_map[i].p_perm);
  245. if (r == -1) {
  246. archive_set_error(&a->archive, errno,
  247. "Failed to check flag in a NFSv4 "
  248. "ACL flagset");
  249. return (ARCHIVE_WARN);
  250. } else if (r)
  251. ae_perm |= acl_nfs4_flag_map[i].a_perm;
  252. }
  253. }
  254. #endif
  255. if (acl_get_permset(acl_entry, &acl_permset) != 0) {
  256. archive_set_error(&a->archive, errno,
  257. "Failed to get ACL permission set");
  258. return (ARCHIVE_WARN);
  259. }
  260. #if ARCHIVE_ACL_FREEBSD_NFS4
  261. if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
  262. perm_map_size = acl_nfs4_perm_map_size;
  263. perm_map = acl_nfs4_perm_map;
  264. } else {
  265. #endif
  266. perm_map_size = acl_posix_perm_map_size;
  267. perm_map = acl_posix_perm_map;
  268. #if ARCHIVE_ACL_FREEBSD_NFS4
  269. }
  270. #endif
  271. for (i = 0; i < perm_map_size; ++i) {
  272. r = acl_get_perm_np(acl_permset, perm_map[i].p_perm);
  273. if (r == -1) {
  274. archive_set_error(&a->archive, errno,
  275. "Failed to check permission in an ACL "
  276. "permission set");
  277. return (ARCHIVE_WARN);
  278. } else if (r)
  279. ae_perm |= perm_map[i].a_perm;
  280. }
  281. archive_entry_acl_add_entry(entry, entry_acl_type,
  282. ae_perm, ae_tag,
  283. ae_id, ae_name);
  284. s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
  285. if (s == -1) {
  286. archive_set_error(&a->archive, errno,
  287. "Failed to get next ACL entry");
  288. return (ARCHIVE_WARN);
  289. }
  290. }
  291. return (ARCHIVE_OK);
  292. }
  293. static int
  294. set_acl(struct archive *a, int fd, const char *name,
  295. struct archive_acl *abstract_acl,
  296. int ae_requested_type, const char *tname)
  297. {
  298. int acl_type = 0;
  299. acl_t acl;
  300. acl_entry_t acl_entry;
  301. acl_permset_t acl_permset;
  302. #if ARCHIVE_ACL_FREEBSD_NFS4
  303. acl_flagset_t acl_flagset;
  304. int r;
  305. #endif
  306. int ret;
  307. int ae_type, ae_permset, ae_tag, ae_id;
  308. int perm_map_size;
  309. const acl_perm_map_t *perm_map;
  310. uid_t ae_uid;
  311. gid_t ae_gid;
  312. const char *ae_name;
  313. int entries;
  314. int i;
  315. ret = ARCHIVE_OK;
  316. entries = archive_acl_reset(abstract_acl, ae_requested_type);
  317. if (entries == 0)
  318. return (ARCHIVE_OK);
  319. switch (ae_requested_type) {
  320. case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
  321. acl_type = ACL_TYPE_ACCESS;
  322. break;
  323. case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
  324. acl_type = ACL_TYPE_DEFAULT;
  325. break;
  326. #if ARCHIVE_ACL_FREEBSD_NFS4
  327. case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
  328. acl_type = ACL_TYPE_NFS4;
  329. break;
  330. #endif
  331. default:
  332. errno = ENOENT;
  333. archive_set_error(a, errno, "Unsupported ACL type");
  334. return (ARCHIVE_FAILED);
  335. }
  336. acl = acl_init(entries);
  337. if (acl == (acl_t)NULL) {
  338. archive_set_error(a, errno,
  339. "Failed to initialize ACL working storage");
  340. return (ARCHIVE_FAILED);
  341. }
  342. while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
  343. &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
  344. if (acl_create_entry(&acl, &acl_entry) != 0) {
  345. archive_set_error(a, errno,
  346. "Failed to create a new ACL entry");
  347. ret = ARCHIVE_FAILED;
  348. goto exit_free;
  349. }
  350. switch (ae_tag) {
  351. case ARCHIVE_ENTRY_ACL_USER:
  352. ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
  353. acl_set_tag_type(acl_entry, ACL_USER);
  354. acl_set_qualifier(acl_entry, &ae_uid);
  355. break;
  356. case ARCHIVE_ENTRY_ACL_GROUP:
  357. ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
  358. acl_set_tag_type(acl_entry, ACL_GROUP);
  359. acl_set_qualifier(acl_entry, &ae_gid);
  360. break;
  361. case ARCHIVE_ENTRY_ACL_USER_OBJ:
  362. acl_set_tag_type(acl_entry, ACL_USER_OBJ);
  363. break;
  364. case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
  365. acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
  366. break;
  367. case ARCHIVE_ENTRY_ACL_MASK:
  368. acl_set_tag_type(acl_entry, ACL_MASK);
  369. break;
  370. case ARCHIVE_ENTRY_ACL_OTHER:
  371. acl_set_tag_type(acl_entry, ACL_OTHER);
  372. break;
  373. #if ARCHIVE_ACL_FREEBSD_NFS4
  374. case ARCHIVE_ENTRY_ACL_EVERYONE:
  375. acl_set_tag_type(acl_entry, ACL_EVERYONE);
  376. break;
  377. #endif
  378. default:
  379. archive_set_error(a, ARCHIVE_ERRNO_MISC,
  380. "Unsupported ACL tag");
  381. ret = ARCHIVE_FAILED;
  382. goto exit_free;
  383. }
  384. #if ARCHIVE_ACL_FREEBSD_NFS4
  385. r = 0;
  386. switch (ae_type) {
  387. case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
  388. r = acl_set_entry_type_np(acl_entry,
  389. ACL_ENTRY_TYPE_ALLOW);
  390. break;
  391. case ARCHIVE_ENTRY_ACL_TYPE_DENY:
  392. r = acl_set_entry_type_np(acl_entry,
  393. ACL_ENTRY_TYPE_DENY);
  394. break;
  395. case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
  396. r = acl_set_entry_type_np(acl_entry,
  397. ACL_ENTRY_TYPE_AUDIT);
  398. break;
  399. case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
  400. r = acl_set_entry_type_np(acl_entry,
  401. ACL_ENTRY_TYPE_ALARM);
  402. break;
  403. case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
  404. case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
  405. // These don't translate directly into the system ACL.
  406. break;
  407. default:
  408. archive_set_error(a, ARCHIVE_ERRNO_MISC,
  409. "Unsupported ACL entry type");
  410. ret = ARCHIVE_FAILED;
  411. goto exit_free;
  412. }
  413. if (r != 0) {
  414. archive_set_error(a, errno,
  415. "Failed to set ACL entry type");
  416. ret = ARCHIVE_FAILED;
  417. goto exit_free;
  418. }
  419. #endif
  420. if (acl_get_permset(acl_entry, &acl_permset) != 0) {
  421. archive_set_error(a, errno,
  422. "Failed to get ACL permission set");
  423. ret = ARCHIVE_FAILED;
  424. goto exit_free;
  425. }
  426. if (acl_clear_perms(acl_permset) != 0) {
  427. archive_set_error(a, errno,
  428. "Failed to clear ACL permissions");
  429. ret = ARCHIVE_FAILED;
  430. goto exit_free;
  431. }
  432. #if ARCHIVE_ACL_FREEBSD_NFS4
  433. if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
  434. perm_map_size = acl_nfs4_perm_map_size;
  435. perm_map = acl_nfs4_perm_map;
  436. } else {
  437. #endif
  438. perm_map_size = acl_posix_perm_map_size;
  439. perm_map = acl_posix_perm_map;
  440. #if ARCHIVE_ACL_FREEBSD_NFS4
  441. }
  442. #endif
  443. for (i = 0; i < perm_map_size; ++i) {
  444. if (ae_permset & perm_map[i].a_perm) {
  445. if (acl_add_perm(acl_permset,
  446. perm_map[i].p_perm) != 0) {
  447. archive_set_error(a, errno,
  448. "Failed to add ACL permission");
  449. ret = ARCHIVE_FAILED;
  450. goto exit_free;
  451. }
  452. }
  453. }
  454. #if ARCHIVE_ACL_FREEBSD_NFS4
  455. if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
  456. /*
  457. * acl_get_flagset_np() fails with non-NFSv4 ACLs
  458. */
  459. if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
  460. archive_set_error(a, errno,
  461. "Failed to get flagset from an NFSv4 "
  462. "ACL entry");
  463. ret = ARCHIVE_FAILED;
  464. goto exit_free;
  465. }
  466. if (acl_clear_flags_np(acl_flagset) != 0) {
  467. archive_set_error(a, errno,
  468. "Failed to clear flags from an NFSv4 "
  469. "ACL flagset");
  470. ret = ARCHIVE_FAILED;
  471. goto exit_free;
  472. }
  473. for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
  474. if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
  475. if (acl_add_flag_np(acl_flagset,
  476. acl_nfs4_flag_map[i].p_perm) != 0) {
  477. archive_set_error(a, errno,
  478. "Failed to add flag to "
  479. "NFSv4 ACL flagset");
  480. ret = ARCHIVE_FAILED;
  481. goto exit_free;
  482. }
  483. }
  484. }
  485. }
  486. #endif
  487. }
  488. /* Try restoring the ACL through 'fd' if we can. */
  489. if (fd >= 0) {
  490. if (acl_set_fd_np(fd, acl, acl_type) == 0)
  491. ret = ARCHIVE_OK;
  492. else {
  493. if (errno == EOPNOTSUPP) {
  494. /* Filesystem doesn't support ACLs */
  495. ret = ARCHIVE_OK;
  496. } else {
  497. archive_set_error(a, errno,
  498. "Failed to set acl on fd: %s", tname);
  499. ret = ARCHIVE_WARN;
  500. }
  501. }
  502. }
  503. #if HAVE_ACL_SET_LINK_NP
  504. else if (acl_set_link_np(name, acl_type, acl) != 0)
  505. #else
  506. /* FreeBSD older than 8.0 */
  507. else if (acl_set_file(name, acl_type, acl) != 0)
  508. #endif
  509. {
  510. if (errno == EOPNOTSUPP) {
  511. /* Filesystem doesn't support ACLs */
  512. ret = ARCHIVE_OK;
  513. } else {
  514. archive_set_error(a, errno, "Failed to set acl: %s",
  515. tname);
  516. ret = ARCHIVE_WARN;
  517. }
  518. }
  519. exit_free:
  520. acl_free(acl);
  521. return (ret);
  522. }
  523. int
  524. archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
  525. struct archive_entry *entry, int *fd)
  526. {
  527. const char *accpath;
  528. acl_t acl;
  529. int r;
  530. accpath = NULL;
  531. if (*fd < 0) {
  532. accpath = archive_read_disk_entry_setup_path(a, entry, fd);
  533. if (accpath == NULL)
  534. return (ARCHIVE_WARN);
  535. }
  536. archive_entry_acl_clear(entry);
  537. acl = NULL;
  538. #if ARCHIVE_ACL_FREEBSD_NFS4
  539. /* Try NFSv4 ACL first. */
  540. if (*fd >= 0)
  541. acl = acl_get_fd_np(*fd, ACL_TYPE_NFS4);
  542. else if (!a->follow_symlinks)
  543. acl = acl_get_link_np(accpath, ACL_TYPE_NFS4);
  544. else
  545. acl = acl_get_file(accpath, ACL_TYPE_NFS4);
  546. /* Ignore "trivial" ACLs that just mirror the file mode. */
  547. if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) {
  548. acl_free(acl);
  549. acl = NULL;
  550. return (ARCHIVE_OK);
  551. }
  552. if (acl != NULL) {
  553. r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
  554. acl_free(acl);
  555. acl = NULL;
  556. if (r != ARCHIVE_OK) {
  557. archive_set_error(&a->archive, errno,
  558. "Couldn't translate NFSv4 ACLs");
  559. }
  560. return (r);
  561. }
  562. #endif
  563. /* Retrieve access ACL from file. */
  564. if (*fd >= 0)
  565. acl = acl_get_fd_np(*fd, ACL_TYPE_ACCESS);
  566. #if HAVE_ACL_GET_LINK_NP
  567. else if (!a->follow_symlinks)
  568. acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS);
  569. #else
  570. else if ((!a->follow_symlinks)
  571. && (archive_entry_filetype(entry) == AE_IFLNK))
  572. /* We can't get the ACL of a symlink, so we assume it can't
  573. have one. */
  574. acl = NULL;
  575. #endif
  576. else
  577. acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
  578. #if HAVE_ACL_IS_TRIVIAL_NP
  579. /* Ignore "trivial" ACLs that just mirror the file mode. */
  580. if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) {
  581. acl_free(acl);
  582. acl = NULL;
  583. }
  584. #endif
  585. if (acl != NULL) {
  586. r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
  587. acl_free(acl);
  588. acl = NULL;
  589. if (r != ARCHIVE_OK) {
  590. archive_set_error(&a->archive, errno,
  591. "Couldn't translate access ACLs");
  592. return (r);
  593. }
  594. }
  595. /* Only directories can have default ACLs. */
  596. if (S_ISDIR(archive_entry_mode(entry))) {
  597. if (*fd >= 0)
  598. acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT);
  599. else
  600. acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
  601. if (acl != NULL) {
  602. r = translate_acl(a, entry, acl,
  603. ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
  604. acl_free(acl);
  605. if (r != ARCHIVE_OK) {
  606. archive_set_error(&a->archive, errno,
  607. "Couldn't translate default ACLs");
  608. return (r);
  609. }
  610. }
  611. }
  612. return (ARCHIVE_OK);
  613. }
  614. int
  615. archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
  616. struct archive_acl *abstract_acl, __LA_MODE_T mode)
  617. {
  618. int ret = ARCHIVE_OK;
  619. (void)mode; /* UNUSED */
  620. if ((archive_acl_types(abstract_acl)
  621. & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
  622. if ((archive_acl_types(abstract_acl)
  623. & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
  624. ret = set_acl(a, fd, name, abstract_acl,
  625. ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
  626. if (ret != ARCHIVE_OK)
  627. return (ret);
  628. }
  629. if ((archive_acl_types(abstract_acl)
  630. & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
  631. ret = set_acl(a, fd, name, abstract_acl,
  632. ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
  633. /* Simultaneous POSIX.1e and NFSv4 is not supported */
  634. return (ret);
  635. }
  636. #if ARCHIVE_ACL_FREEBSD_NFS4
  637. else if ((archive_acl_types(abstract_acl) &
  638. ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
  639. ret = set_acl(a, fd, name, abstract_acl,
  640. ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
  641. }
  642. #endif
  643. return (ret);
  644. }
  645. #endif /* ARCHIVE_ACL_FREEBSD */