file-has-acl.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920
  1. /* Test whether a file has a nontrivial access control list.
  2. Copyright (C) 2002-2003, 2005-2015 Free Software Foundation, Inc.
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */
  14. /* Without this pragma, gcc 4.7.0 20120126 may suggest that the
  15. file_has_acl function might be candidate for attribute 'const' */
  16. #if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__
  17. # pragma GCC diagnostic ignored "-Wsuggest-attribute=const"
  18. #endif
  19. #include <config.h>
  20. #include "acl.h"
  21. #include "acl-internal.h"
  22. #if USE_ACL && HAVE_ACL_GET_FILE
  23. # if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
  24. /* ACL is an ACL, from a file, stored as type ACL_TYPE_EXTENDED.
  25. Return 1 if the given ACL is non-trivial.
  26. Return 0 if it is trivial. */
  27. int
  28. acl_extended_nontrivial (acl_t acl)
  29. {
  30. /* acl is non-trivial if it is non-empty. */
  31. return (acl_entries (acl) > 0);
  32. }
  33. # else /* Linux, FreeBSD, IRIX, Tru64 */
  34. /* ACL is an ACL, from a file, stored as type ACL_TYPE_ACCESS.
  35. Return 1 if the given ACL is non-trivial.
  36. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.
  37. Return -1 and set errno upon failure to determine it. */
  38. int
  39. acl_access_nontrivial (acl_t acl)
  40. {
  41. /* acl is non-trivial if it has some entries other than for "user::",
  42. "group::", and "other::". Normally these three should be present
  43. at least, allowing us to write
  44. return (3 < acl_entries (acl));
  45. but the following code is more robust. */
  46. # if HAVE_ACL_FIRST_ENTRY /* Linux, FreeBSD */
  47. acl_entry_t ace;
  48. int got_one;
  49. for (got_one = acl_get_entry (acl, ACL_FIRST_ENTRY, &ace);
  50. got_one > 0;
  51. got_one = acl_get_entry (acl, ACL_NEXT_ENTRY, &ace))
  52. {
  53. acl_tag_t tag;
  54. if (acl_get_tag_type (ace, &tag) < 0)
  55. return -1;
  56. if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || tag == ACL_OTHER))
  57. return 1;
  58. }
  59. return got_one;
  60. # elif HAVE_ACL_TO_SHORT_TEXT /* IRIX */
  61. /* Don't use acl_get_entry: it is undocumented. */
  62. int count = acl->acl_cnt;
  63. int i;
  64. for (i = 0; i < count; i++)
  65. {
  66. acl_entry_t ace = &acl->acl_entry[i];
  67. acl_tag_t tag = ace->ae_tag;
  68. if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ
  69. || tag == ACL_OTHER_OBJ))
  70. return 1;
  71. }
  72. return 0;
  73. # elif HAVE_ACL_FREE_TEXT /* Tru64 */
  74. /* Don't use acl_get_entry: it takes only one argument and does not work. */
  75. int count = acl->acl_num;
  76. acl_entry_t ace;
  77. for (ace = acl->acl_first; count > 0; ace = ace->next, count--)
  78. {
  79. acl_tag_t tag;
  80. acl_perm_t perm;
  81. tag = ace->entry->acl_type;
  82. if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || tag == ACL_OTHER))
  83. return 1;
  84. perm = ace->entry->acl_perm;
  85. /* On Tru64, perm can also contain non-standard bits such as
  86. PERM_INSERT, PERM_DELETE, PERM_MODIFY, PERM_LOOKUP, ... */
  87. if ((perm & ~(ACL_READ | ACL_WRITE | ACL_EXECUTE)) != 0)
  88. return 1;
  89. }
  90. return 0;
  91. # else
  92. errno = ENOSYS;
  93. return -1;
  94. # endif
  95. }
  96. # endif
  97. #elif USE_ACL && HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
  98. /* Test an ACL retrieved with GETACL.
  99. Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
  100. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
  101. int
  102. acl_nontrivial (int count, aclent_t *entries)
  103. {
  104. int i;
  105. for (i = 0; i < count; i++)
  106. {
  107. aclent_t *ace = &entries[i];
  108. /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat().
  109. If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat().
  110. We don't need to check ace->a_id in these cases. */
  111. if (!(ace->a_type == USER_OBJ
  112. || ace->a_type == GROUP_OBJ
  113. || ace->a_type == OTHER_OBJ
  114. /* Note: Cygwin does not return a CLASS_OBJ ("mask:") entry
  115. sometimes. */
  116. || ace->a_type == CLASS_OBJ))
  117. return 1;
  118. }
  119. return 0;
  120. }
  121. # ifdef ACE_GETACL
  122. /* A shortcut for a bitmask. */
  123. # define NEW_ACE_WRITEA_DATA (NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA)
  124. /* Test an ACL retrieved with ACE_GETACL.
  125. Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
  126. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
  127. int
  128. acl_ace_nontrivial (int count, ace_t *entries)
  129. {
  130. int i;
  131. /* The flags in the ace_t structure changed in a binary incompatible way
  132. when ACL_NO_TRIVIAL etc. were introduced in <sys/acl.h> version 1.15.
  133. How to distinguish the two conventions at runtime?
  134. In the old convention, usually three ACEs have a_flags = ACE_OWNER /
  135. ACE_GROUP / ACE_OTHER, in the range 0x0100..0x0400. In the new
  136. convention, these values are not used. */
  137. int old_convention = 0;
  138. for (i = 0; i < count; i++)
  139. if (entries[i].a_flags & (OLD_ACE_OWNER | OLD_ACE_GROUP | OLD_ACE_OTHER))
  140. {
  141. old_convention = 1;
  142. break;
  143. }
  144. if (old_convention)
  145. /* Running on Solaris 10. */
  146. for (i = 0; i < count; i++)
  147. {
  148. ace_t *ace = &entries[i];
  149. /* Note:
  150. If ace->a_flags = ACE_OWNER, ace->a_who is the st_uid from stat().
  151. If ace->a_flags = ACE_GROUP, ace->a_who is the st_gid from stat().
  152. We don't need to check ace->a_who in these cases. */
  153. if (!(ace->a_type == OLD_ALLOW
  154. && (ace->a_flags == OLD_ACE_OWNER
  155. || ace->a_flags == OLD_ACE_GROUP
  156. || ace->a_flags == OLD_ACE_OTHER)))
  157. return 1;
  158. }
  159. else
  160. {
  161. /* Running on Solaris 10 (newer version) or Solaris 11. */
  162. unsigned int access_masks[6] =
  163. {
  164. 0, /* owner@ deny */
  165. 0, /* owner@ allow */
  166. 0, /* group@ deny */
  167. 0, /* group@ allow */
  168. 0, /* everyone@ deny */
  169. 0 /* everyone@ allow */
  170. };
  171. for (i = 0; i < count; i++)
  172. {
  173. ace_t *ace = &entries[i];
  174. unsigned int index1;
  175. unsigned int index2;
  176. if (ace->a_type == NEW_ACE_ACCESS_ALLOWED_ACE_TYPE)
  177. index1 = 1;
  178. else if (ace->a_type == NEW_ACE_ACCESS_DENIED_ACE_TYPE)
  179. index1 = 0;
  180. else
  181. return 1;
  182. if (ace->a_flags == NEW_ACE_OWNER)
  183. index2 = 0;
  184. else if (ace->a_flags == (NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP))
  185. index2 = 2;
  186. else if (ace->a_flags == NEW_ACE_EVERYONE)
  187. index2 = 4;
  188. else
  189. return 1;
  190. access_masks[index1 + index2] |= ace->a_access_mask;
  191. }
  192. /* The same bit shouldn't be both allowed and denied. */
  193. if (access_masks[0] & access_masks[1])
  194. return 1;
  195. if (access_masks[2] & access_masks[3])
  196. return 1;
  197. if (access_masks[4] & access_masks[5])
  198. return 1;
  199. /* Check minimum masks. */
  200. if ((NEW_ACE_WRITE_NAMED_ATTRS
  201. | NEW_ACE_WRITE_ATTRIBUTES
  202. | NEW_ACE_WRITE_ACL
  203. | NEW_ACE_WRITE_OWNER)
  204. & ~ access_masks[1])
  205. return 1;
  206. access_masks[1] &= ~(NEW_ACE_WRITE_NAMED_ATTRS
  207. | NEW_ACE_WRITE_ATTRIBUTES
  208. | NEW_ACE_WRITE_ACL
  209. | NEW_ACE_WRITE_OWNER);
  210. if ((NEW_ACE_READ_NAMED_ATTRS
  211. | NEW_ACE_READ_ATTRIBUTES
  212. | NEW_ACE_READ_ACL
  213. | NEW_ACE_SYNCHRONIZE)
  214. & ~ access_masks[5])
  215. return 1;
  216. access_masks[5] &= ~(NEW_ACE_READ_NAMED_ATTRS
  217. | NEW_ACE_READ_ATTRIBUTES
  218. | NEW_ACE_READ_ACL
  219. | NEW_ACE_SYNCHRONIZE);
  220. /* Check the allowed or denied bits. */
  221. switch ((access_masks[0] | access_masks[1])
  222. & ~(NEW_ACE_READ_NAMED_ATTRS
  223. | NEW_ACE_READ_ATTRIBUTES
  224. | NEW_ACE_READ_ACL
  225. | NEW_ACE_SYNCHRONIZE))
  226. {
  227. case 0:
  228. case NEW_ACE_READ_DATA:
  229. case NEW_ACE_WRITEA_DATA:
  230. case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA:
  231. case NEW_ACE_EXECUTE:
  232. case NEW_ACE_READ_DATA | NEW_ACE_EXECUTE:
  233. case NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
  234. case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
  235. break;
  236. default:
  237. return 1;
  238. }
  239. switch ((access_masks[2] | access_masks[3])
  240. & ~(NEW_ACE_READ_NAMED_ATTRS
  241. | NEW_ACE_READ_ATTRIBUTES
  242. | NEW_ACE_READ_ACL
  243. | NEW_ACE_SYNCHRONIZE))
  244. {
  245. case 0:
  246. case NEW_ACE_READ_DATA:
  247. case NEW_ACE_WRITEA_DATA:
  248. case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA:
  249. case NEW_ACE_EXECUTE:
  250. case NEW_ACE_READ_DATA | NEW_ACE_EXECUTE:
  251. case NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
  252. case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
  253. break;
  254. default:
  255. return 1;
  256. }
  257. switch ((access_masks[4] | access_masks[5])
  258. & ~(NEW_ACE_WRITE_NAMED_ATTRS
  259. | NEW_ACE_WRITE_ATTRIBUTES
  260. | NEW_ACE_WRITE_ACL
  261. | NEW_ACE_WRITE_OWNER))
  262. {
  263. case 0:
  264. case NEW_ACE_READ_DATA:
  265. case NEW_ACE_WRITEA_DATA:
  266. case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA:
  267. case NEW_ACE_EXECUTE:
  268. case NEW_ACE_READ_DATA | NEW_ACE_EXECUTE:
  269. case NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
  270. case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
  271. break;
  272. default:
  273. return 1;
  274. }
  275. /* Check that the NEW_ACE_WRITE_DATA and NEW_ACE_APPEND_DATA bits are
  276. either both allowed or both denied. */
  277. if (((access_masks[0] & NEW_ACE_WRITE_DATA) != 0)
  278. != ((access_masks[0] & NEW_ACE_APPEND_DATA) != 0))
  279. return 1;
  280. if (((access_masks[2] & NEW_ACE_WRITE_DATA) != 0)
  281. != ((access_masks[2] & NEW_ACE_APPEND_DATA) != 0))
  282. return 1;
  283. if (((access_masks[4] & NEW_ACE_WRITE_DATA) != 0)
  284. != ((access_masks[4] & NEW_ACE_APPEND_DATA) != 0))
  285. return 1;
  286. }
  287. return 0;
  288. }
  289. # endif
  290. #elif USE_ACL && HAVE_GETACL /* HP-UX */
  291. /* Return 1 if the given ACL is non-trivial.
  292. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
  293. int
  294. acl_nontrivial (int count, struct acl_entry *entries, struct stat *sb)
  295. {
  296. int i;
  297. for (i = 0; i < count; i++)
  298. {
  299. struct acl_entry *ace = &entries[i];
  300. if (!((ace->uid == sb->st_uid && ace->gid == ACL_NSGROUP)
  301. || (ace->uid == ACL_NSUSER && ace->gid == sb->st_gid)
  302. || (ace->uid == ACL_NSUSER && ace->gid == ACL_NSGROUP)))
  303. return 1;
  304. }
  305. return 0;
  306. }
  307. # if HAVE_ACLV_H /* HP-UX >= 11.11 */
  308. /* Return 1 if the given ACL is non-trivial.
  309. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
  310. int
  311. aclv_nontrivial (int count, struct acl *entries)
  312. {
  313. int i;
  314. for (i = 0; i < count; i++)
  315. {
  316. struct acl *ace = &entries[i];
  317. /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat().
  318. If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat().
  319. We don't need to check ace->a_id in these cases. */
  320. if (!(ace->a_type == USER_OBJ /* no need to check ace->a_id here */
  321. || ace->a_type == GROUP_OBJ /* no need to check ace->a_id here */
  322. || ace->a_type == CLASS_OBJ
  323. || ace->a_type == OTHER_OBJ))
  324. return 1;
  325. }
  326. return 0;
  327. }
  328. # endif
  329. #elif USE_ACL && (HAVE_ACLX_GET || HAVE_STATACL) /* AIX */
  330. /* Return 1 if the given ACL is non-trivial.
  331. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
  332. int
  333. acl_nontrivial (struct acl *a)
  334. {
  335. /* The normal way to iterate through an ACL is like this:
  336. struct acl_entry *ace;
  337. for (ace = a->acl_ext; ace != acl_last (a); ace = acl_nxt (ace))
  338. {
  339. struct ace_id *aei;
  340. switch (ace->ace_type)
  341. {
  342. case ACC_PERMIT:
  343. case ACC_DENY:
  344. case ACC_SPECIFY:
  345. ...;
  346. }
  347. for (aei = ace->ace_id; aei != id_last (ace); aei = id_nxt (aei))
  348. ...
  349. }
  350. */
  351. return (acl_last (a) != a->acl_ext ? 1 : 0);
  352. }
  353. # if HAVE_ACLX_GET && defined ACL_AIX_WIP /* newer AIX */
  354. /* Return 1 if the given ACL is non-trivial.
  355. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
  356. int
  357. acl_nfs4_nontrivial (nfs4_acl_int_t *a)
  358. {
  359. # if 1 /* let's try this first */
  360. return (a->aclEntryN > 0 ? 1 : 0);
  361. # else
  362. int count = a->aclEntryN;
  363. int i;
  364. for (i = 0; i < count; i++)
  365. {
  366. nfs4_ace_int_t *ace = &a->aclEntry[i];
  367. if (!((ace->flags & ACE4_ID_SPECIAL) != 0
  368. && (ace->aceWho.special_whoid == ACE4_WHO_OWNER
  369. || ace->aceWho.special_whoid == ACE4_WHO_GROUP
  370. || ace->aceWho.special_whoid == ACE4_WHO_EVERYONE)
  371. && ace->aceType == ACE4_ACCESS_ALLOWED_ACE_TYPE
  372. && ace->aceFlags == 0
  373. && (ace->aceMask & ~(ACE4_READ_DATA | ACE4_LIST_DIRECTORY
  374. | ACE4_WRITE_DATA | ACE4_ADD_FILE
  375. | ACE4_EXECUTE)) == 0))
  376. return 1;
  377. }
  378. return 0;
  379. # endif
  380. }
  381. # endif
  382. #elif USE_ACL && HAVE_ACLSORT /* NonStop Kernel */
  383. /* Test an ACL retrieved with ACL_GET.
  384. Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
  385. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
  386. int
  387. acl_nontrivial (int count, struct acl *entries)
  388. {
  389. int i;
  390. for (i = 0; i < count; i++)
  391. {
  392. struct acl *ace = &entries[i];
  393. /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat().
  394. If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat().
  395. We don't need to check ace->a_id in these cases. */
  396. if (!(ace->a_type == USER_OBJ /* no need to check ace->a_id here */
  397. || ace->a_type == GROUP_OBJ /* no need to check ace->a_id here */
  398. || ace->a_type == CLASS_OBJ
  399. || ace->a_type == OTHER_OBJ))
  400. return 1;
  401. }
  402. return 0;
  403. }
  404. #endif
  405. /* Return 1 if NAME has a nontrivial access control list, 0 if NAME
  406. only has no or a base access control list, and -1 (setting errno)
  407. on error. SB must be set to the stat buffer of NAME, obtained
  408. through stat() or lstat(). */
  409. int
  410. file_has_acl (char const *name, struct stat const *sb)
  411. {
  412. #if USE_ACL
  413. if (! S_ISLNK (sb->st_mode))
  414. {
  415. # if HAVE_ACL_GET_FILE
  416. /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */
  417. /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */
  418. int ret;
  419. if (HAVE_ACL_EXTENDED_FILE) /* Linux */
  420. {
  421. /* On Linux, acl_extended_file is an optimized function: It only
  422. makes two calls to getxattr(), one for ACL_TYPE_ACCESS, one for
  423. ACL_TYPE_DEFAULT. */
  424. ret = acl_extended_file (name);
  425. }
  426. else /* FreeBSD, Mac OS X, IRIX, Tru64 */
  427. {
  428. # if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
  429. /* On Mac OS X, acl_get_file (name, ACL_TYPE_ACCESS)
  430. and acl_get_file (name, ACL_TYPE_DEFAULT)
  431. always return NULL / EINVAL. There is no point in making
  432. these two useless calls. The real ACL is retrieved through
  433. acl_get_file (name, ACL_TYPE_EXTENDED). */
  434. acl_t acl = acl_get_file (name, ACL_TYPE_EXTENDED);
  435. if (acl)
  436. {
  437. ret = acl_extended_nontrivial (acl);
  438. acl_free (acl);
  439. }
  440. else
  441. ret = -1;
  442. # else /* FreeBSD, IRIX, Tru64 */
  443. acl_t acl = acl_get_file (name, ACL_TYPE_ACCESS);
  444. if (acl)
  445. {
  446. int saved_errno;
  447. ret = acl_access_nontrivial (acl);
  448. saved_errno = errno;
  449. acl_free (acl);
  450. errno = saved_errno;
  451. # if HAVE_ACL_FREE_TEXT /* Tru64 */
  452. /* On OSF/1, acl_get_file (name, ACL_TYPE_DEFAULT) always
  453. returns NULL with errno not set. There is no point in
  454. making this call. */
  455. # else /* FreeBSD, IRIX */
  456. /* On Linux, FreeBSD, IRIX, acl_get_file (name, ACL_TYPE_ACCESS)
  457. and acl_get_file (name, ACL_TYPE_DEFAULT) on a directory
  458. either both succeed or both fail; it depends on the
  459. file system. Therefore there is no point in making the second
  460. call if the first one already failed. */
  461. if (ret == 0 && S_ISDIR (sb->st_mode))
  462. {
  463. acl = acl_get_file (name, ACL_TYPE_DEFAULT);
  464. if (acl)
  465. {
  466. ret = (0 < acl_entries (acl));
  467. acl_free (acl);
  468. }
  469. else
  470. ret = -1;
  471. }
  472. # endif
  473. }
  474. else
  475. ret = -1;
  476. # endif
  477. }
  478. if (ret < 0)
  479. return - acl_errno_valid (errno);
  480. return ret;
  481. # elif HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
  482. # if defined ACL_NO_TRIVIAL
  483. /* Solaris 10 (newer version), which has additional API declared in
  484. <sys/acl.h> (acl_t) and implemented in libsec (acl_set, acl_trivial,
  485. acl_fromtext, ...). */
  486. return acl_trivial (name);
  487. # else /* Solaris, Cygwin, general case */
  488. /* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions
  489. of Unixware. The acl() call returns the access and default ACL both
  490. at once. */
  491. {
  492. /* Initially, try to read the entries into a stack-allocated buffer.
  493. Use malloc if it does not fit. */
  494. enum
  495. {
  496. alloc_init = 4000 / sizeof (aclent_t), /* >= 3 */
  497. alloc_max = MIN (INT_MAX, SIZE_MAX / sizeof (aclent_t))
  498. };
  499. aclent_t buf[alloc_init];
  500. size_t alloc = alloc_init;
  501. aclent_t *entries = buf;
  502. aclent_t *malloced = NULL;
  503. int count;
  504. for (;;)
  505. {
  506. count = acl (name, GETACL, alloc, entries);
  507. if (count < 0 && errno == ENOSPC)
  508. {
  509. /* Increase the size of the buffer. */
  510. free (malloced);
  511. if (alloc > alloc_max / 2)
  512. {
  513. errno = ENOMEM;
  514. return -1;
  515. }
  516. alloc = 2 * alloc; /* <= alloc_max */
  517. entries = malloced =
  518. (aclent_t *) malloc (alloc * sizeof (aclent_t));
  519. if (entries == NULL)
  520. {
  521. errno = ENOMEM;
  522. return -1;
  523. }
  524. continue;
  525. }
  526. break;
  527. }
  528. if (count < 0)
  529. {
  530. if (errno == ENOSYS || errno == ENOTSUP)
  531. ;
  532. else
  533. {
  534. int saved_errno = errno;
  535. free (malloced);
  536. errno = saved_errno;
  537. return -1;
  538. }
  539. }
  540. else if (count == 0)
  541. ;
  542. else
  543. {
  544. /* Don't use MIN_ACL_ENTRIES: It's set to 4 on Cygwin, but Cygwin
  545. returns only 3 entries for files with no ACL. But this is safe:
  546. If there are more than 4 entries, there cannot be only the
  547. "user::", "group::", "other:", and "mask:" entries. */
  548. if (count > 4)
  549. {
  550. free (malloced);
  551. return 1;
  552. }
  553. if (acl_nontrivial (count, entries))
  554. {
  555. free (malloced);
  556. return 1;
  557. }
  558. }
  559. free (malloced);
  560. }
  561. # ifdef ACE_GETACL
  562. /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4
  563. file systems (whereas the other ones are used in UFS file systems). */
  564. {
  565. /* Initially, try to read the entries into a stack-allocated buffer.
  566. Use malloc if it does not fit. */
  567. enum
  568. {
  569. alloc_init = 4000 / sizeof (ace_t), /* >= 3 */
  570. alloc_max = MIN (INT_MAX, SIZE_MAX / sizeof (ace_t))
  571. };
  572. ace_t buf[alloc_init];
  573. size_t alloc = alloc_init;
  574. ace_t *entries = buf;
  575. ace_t *malloced = NULL;
  576. int count;
  577. for (;;)
  578. {
  579. count = acl (name, ACE_GETACL, alloc, entries);
  580. if (count < 0 && errno == ENOSPC)
  581. {
  582. /* Increase the size of the buffer. */
  583. free (malloced);
  584. if (alloc > alloc_max / 2)
  585. {
  586. errno = ENOMEM;
  587. return -1;
  588. }
  589. alloc = 2 * alloc; /* <= alloc_max */
  590. entries = malloced = (ace_t *) malloc (alloc * sizeof (ace_t));
  591. if (entries == NULL)
  592. {
  593. errno = ENOMEM;
  594. return -1;
  595. }
  596. continue;
  597. }
  598. break;
  599. }
  600. if (count < 0)
  601. {
  602. if (errno == ENOSYS || errno == EINVAL)
  603. ;
  604. else
  605. {
  606. int saved_errno = errno;
  607. free (malloced);
  608. errno = saved_errno;
  609. return -1;
  610. }
  611. }
  612. else if (count == 0)
  613. ;
  614. else
  615. {
  616. /* In the old (original Solaris 10) convention:
  617. If there are more than 3 entries, there cannot be only the
  618. ACE_OWNER, ACE_GROUP, ACE_OTHER entries.
  619. In the newer Solaris 10 and Solaris 11 convention:
  620. If there are more than 6 entries, there cannot be only the
  621. ACE_OWNER, ACE_GROUP, ACE_EVERYONE entries, each once with
  622. NEW_ACE_ACCESS_ALLOWED_ACE_TYPE and once with
  623. NEW_ACE_ACCESS_DENIED_ACE_TYPE. */
  624. if (count > 6)
  625. {
  626. free (malloced);
  627. return 1;
  628. }
  629. if (acl_ace_nontrivial (count, entries))
  630. {
  631. free (malloced);
  632. return 1;
  633. }
  634. }
  635. free (malloced);
  636. }
  637. # endif
  638. return 0;
  639. # endif
  640. # elif HAVE_GETACL /* HP-UX */
  641. {
  642. struct acl_entry entries[NACLENTRIES];
  643. int count;
  644. count = getacl (name, NACLENTRIES, entries);
  645. if (count < 0)
  646. {
  647. /* ENOSYS is seen on newer HP-UX versions.
  648. EOPNOTSUPP is typically seen on NFS mounts.
  649. ENOTSUP was seen on Quantum StorNext file systems (cvfs). */
  650. if (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP)
  651. ;
  652. else
  653. return -1;
  654. }
  655. else if (count == 0)
  656. return 0;
  657. else /* count > 0 */
  658. {
  659. if (count > NACLENTRIES)
  660. /* If NACLENTRIES cannot be trusted, use dynamic memory
  661. allocation. */
  662. abort ();
  663. /* If there are more than 3 entries, there cannot be only the
  664. (uid,%), (%,gid), (%,%) entries. */
  665. if (count > 3)
  666. return 1;
  667. {
  668. struct stat statbuf;
  669. if (stat (name, &statbuf) < 0)
  670. return -1;
  671. return acl_nontrivial (count, entries, &statbuf);
  672. }
  673. }
  674. }
  675. # if HAVE_ACLV_H /* HP-UX >= 11.11 */
  676. {
  677. struct acl entries[NACLVENTRIES];
  678. int count;
  679. count = acl ((char *) name, ACL_GET, NACLVENTRIES, entries);
  680. if (count < 0)
  681. {
  682. /* EOPNOTSUPP is seen on NFS in HP-UX 11.11, 11.23.
  683. EINVAL is seen on NFS in HP-UX 11.31. */
  684. if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL)
  685. ;
  686. else
  687. return -1;
  688. }
  689. else if (count == 0)
  690. return 0;
  691. else /* count > 0 */
  692. {
  693. if (count > NACLVENTRIES)
  694. /* If NACLVENTRIES cannot be trusted, use dynamic memory
  695. allocation. */
  696. abort ();
  697. /* If there are more than 4 entries, there cannot be only the
  698. four base ACL entries. */
  699. if (count > 4)
  700. return 1;
  701. return aclv_nontrivial (count, entries);
  702. }
  703. }
  704. # endif
  705. # elif HAVE_ACLX_GET && defined ACL_AIX_WIP /* AIX */
  706. acl_type_t type;
  707. char aclbuf[1024];
  708. void *acl = aclbuf;
  709. size_t aclsize = sizeof (aclbuf);
  710. mode_t mode;
  711. for (;;)
  712. {
  713. /* The docs say that type being 0 is equivalent to ACL_ANY, but it
  714. is not true, in AIX 5.3. */
  715. type.u64 = ACL_ANY;
  716. if (aclx_get (name, 0, &type, aclbuf, &aclsize, &mode) >= 0)
  717. break;
  718. if (errno == ENOSYS)
  719. return 0;
  720. if (errno != ENOSPC)
  721. {
  722. if (acl != aclbuf)
  723. {
  724. int saved_errno = errno;
  725. free (acl);
  726. errno = saved_errno;
  727. }
  728. return -1;
  729. }
  730. aclsize = 2 * aclsize;
  731. if (acl != aclbuf)
  732. free (acl);
  733. acl = malloc (aclsize);
  734. if (acl == NULL)
  735. {
  736. errno = ENOMEM;
  737. return -1;
  738. }
  739. }
  740. if (type.u64 == ACL_AIXC)
  741. {
  742. int result = acl_nontrivial ((struct acl *) acl);
  743. if (acl != aclbuf)
  744. free (acl);
  745. return result;
  746. }
  747. else if (type.u64 == ACL_NFS4)
  748. {
  749. int result = acl_nfs4_nontrivial ((nfs4_acl_int_t *) acl);
  750. if (acl != aclbuf)
  751. free (acl);
  752. return result;
  753. }
  754. else
  755. {
  756. /* A newer type of ACL has been introduced in the system.
  757. We should better support it. */
  758. if (acl != aclbuf)
  759. free (acl);
  760. errno = EINVAL;
  761. return -1;
  762. }
  763. # elif HAVE_STATACL /* older AIX */
  764. union { struct acl a; char room[4096]; } u;
  765. if (statacl (name, STX_NORMAL, &u.a, sizeof (u)) < 0)
  766. return -1;
  767. return acl_nontrivial (&u.a);
  768. # elif HAVE_ACLSORT /* NonStop Kernel */
  769. {
  770. struct acl entries[NACLENTRIES];
  771. int count;
  772. count = acl ((char *) name, ACL_GET, NACLENTRIES, entries);
  773. if (count < 0)
  774. {
  775. if (errno == ENOSYS || errno == ENOTSUP)
  776. ;
  777. else
  778. return -1;
  779. }
  780. else if (count == 0)
  781. return 0;
  782. else /* count > 0 */
  783. {
  784. if (count > NACLENTRIES)
  785. /* If NACLENTRIES cannot be trusted, use dynamic memory
  786. allocation. */
  787. abort ();
  788. /* If there are more than 4 entries, there cannot be only the
  789. four base ACL entries. */
  790. if (count > 4)
  791. return 1;
  792. return acl_nontrivial (count, entries);
  793. }
  794. }
  795. # endif
  796. }
  797. #endif
  798. return 0;
  799. }