PageRenderTime 63ms CodeModel.GetById 36ms RepoModel.GetById 0ms app.codeStats 0ms

/gnome-vfs-2.24.4/modules/file-method-acl.c

#
C | 1017 lines | 736 code | 213 blank | 68 comment | 186 complexity | 305a302ed45a09a41e9b13795f5c5cb9 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0
  1. /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
  2. /* gnome-vfs-acl.h - ACL Handling for the GNOME Virtual File System.
  3. Virtual File System.
  4. Copyright (C) 2005 Christian Kellner
  5. Copyright (C) 2005 Sun Microsystems
  6. The Gnome Library is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU Library General Public License as
  8. published by the Free Software Foundation; either version 2 of the
  9. License, or (at your option) any later version.
  10. The Gnome Library is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. Library General Public License for more details.
  14. You should have received a copy of the GNU Library General Public
  15. License along with the Gnome Library; see the file COPYING.LIB. If not,
  16. write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  17. Boston, MA 02111-1307, USA.
  18. Authors: Christian Kellner <gicmo@gnome.org>
  19. Alvaro Lopez Ortega <alvaro@sun.com>
  20. */
  21. #ifdef HAVE_CONFIG_H
  22. #include <config.h>
  23. #endif
  24. #include <stdio.h>
  25. #include <errno.h>
  26. #include <string.h>
  27. #include <unistd.h>
  28. #include <stdlib.h>
  29. #include <sys/types.h>
  30. #ifdef HAVE_SYS_RESOURCE_H
  31. #include <sys/resource.h>
  32. #endif
  33. #ifdef HAVE_PWD_H
  34. # include <pwd.h>
  35. #endif
  36. #ifdef HAVE_GRP_H
  37. # include <grp.h>
  38. #endif
  39. #ifdef HAVE_POSIX_ACL
  40. # include <acl/libacl.h>
  41. #define HAVE_ACL 1
  42. #endif
  43. #ifdef HAVE_SOLARIS_ACL
  44. # include <sys/acl.h>
  45. #define HAVE_ACL 1
  46. #endif
  47. #include "file-method-acl.h"
  48. #define CMD_PERM_READ 4
  49. #define CMD_PERM_WRITE 2
  50. #define CMD_PERM_EXECUTE 1
  51. #define CMD_PERM_COND_EXECUTE 8
  52. #ifdef HAVE_ACL
  53. static char *
  54. uid_to_string (uid_t uid)
  55. {
  56. char *uid_string = NULL;
  57. #ifdef HAVE_PWD_H
  58. struct passwd *pw = NULL;
  59. gpointer buffer = NULL;
  60. gint error;
  61. #if defined (HAVE_POSIX_GETPWUID_R) || defined (HAVE_NONPOSIX_GETPWUID_R)
  62. struct passwd pwd;
  63. glong bufsize;
  64. #ifdef _SC_GETPW_R_SIZE_MAX
  65. bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
  66. #else
  67. bufsize = 64;
  68. #endif /* _SC_GETPW_R_SIZE_MAX */
  69. do {
  70. g_free (buffer);
  71. /* why bufsize + 6 see #156446 */
  72. buffer = g_malloc (bufsize + 6);
  73. errno = 0;
  74. #ifdef HAVE_POSIX_GETPWUID_R
  75. error = getpwuid_r (uid, &pwd, buffer, bufsize, &pw);
  76. error = error < 0 ? errno : error;
  77. #else /* HAVE_NONPOSIX_GETPWUID_R */
  78. /* HPUX 11 falls into the HAVE_POSIX_GETPWUID_R case */
  79. #if defined(_AIX) || defined(__hpux)
  80. error = getpwuid_r (uid, &pwd, buffer, bufsize);
  81. pw = error == 0 ? &pwd : NULL;
  82. #else /* !_AIX */
  83. pw = getpwuid_r (uid, &pwd, buffer, bufsize);
  84. error = pw ? 0 : errno;
  85. #endif /* !_AIX */
  86. #endif /* HAVE_NONPOSIX_GETPWUID_R */
  87. if (pw == NULL) {
  88. if (error == 0 || error == ENOENT) {
  89. break;
  90. }
  91. }
  92. if (bufsize > 32 * 1024) {
  93. break;
  94. }
  95. bufsize *= 2;
  96. } while (pw == NULL);
  97. #endif /* HAVE_POSIX_GETPWUID_R || HAVE_NONPOSIX_GETPWUID_R */
  98. if (pw == NULL) {
  99. setpwent ();
  100. pw = getpwuid (uid);
  101. endpwent ();
  102. }
  103. if (pw != NULL) {
  104. uid_string = g_strdup (pw->pw_name);
  105. }
  106. #endif /* HAVE_PWD_H */
  107. if (uid_string == NULL) {
  108. uid_string = g_strdup_printf ("%d", uid);
  109. }
  110. return uid_string;
  111. }
  112. static char *
  113. gid_to_string (gid_t gid)
  114. {
  115. char *gid_string = NULL;
  116. #ifdef HAVE_GETGRGID_R
  117. struct group *gr = NULL;
  118. gpointer buffer = NULL;
  119. gint error;
  120. struct group grp;
  121. glong bufsize;
  122. #ifdef _SC_GETGR_R_SIZE_MAX
  123. bufsize = sysconf (_SC_GETGR_R_SIZE_MAX);
  124. #else
  125. bufsize = 64;
  126. #endif /* _SC_GETPW_R_SIZE_MAX */
  127. do {
  128. g_free (buffer);
  129. /* why bufsize + 6 see #156446 */
  130. buffer = g_malloc (bufsize + 6);
  131. error = getgrgid_r (gid, &grp, buffer, bufsize, &gr);
  132. error = error < 0 ? errno : error;
  133. if (gr == NULL) {
  134. if (error == 0 || error == ENOENT) {
  135. break;
  136. }
  137. }
  138. if (bufsize > 32 * 1024) {
  139. break;
  140. }
  141. bufsize *= 2;
  142. } while (gr == NULL);
  143. if (gr != NULL) {
  144. gid_string = g_strdup (gr->gr_name);
  145. }
  146. #endif
  147. if (gid_string == NULL) {
  148. gid_string = g_strdup_printf ("%d", gid);
  149. }
  150. return gid_string;
  151. }
  152. static uid_t
  153. string_to_uid (const char *uid)
  154. {
  155. struct passwd *passwd;
  156. passwd = getpwnam(uid);
  157. if (passwd == NULL) return 0;
  158. return passwd->pw_uid;
  159. }
  160. static gid_t
  161. string_to_gid (const char *gid)
  162. {
  163. struct group *group;
  164. group = getgrnam (gid);
  165. if (group == NULL) return 0;
  166. return group->gr_gid;
  167. }
  168. /* ************************************************************************** */
  169. /* POSIX ACL */
  170. #ifdef HAVE_POSIX_ACL
  171. #define POSIX_N_TAGS 3
  172. static int
  173. permset_to_perms (acl_permset_t set, GnomeVFSACLPerm *tags)
  174. {
  175. int i;
  176. memset (tags, 0, sizeof (GnomeVFSACLPerm) * (POSIX_N_TAGS + 1));
  177. i = 0;
  178. if (acl_get_perm (set, ACL_READ) == 1) {
  179. tags[0] = GNOME_VFS_ACL_READ;
  180. i++;
  181. }
  182. if (acl_get_perm (set, ACL_WRITE) == 1) {
  183. tags[i] = GNOME_VFS_ACL_WRITE;
  184. i++;
  185. }
  186. if (acl_get_perm (set, ACL_EXECUTE)) {
  187. tags[i] = GNOME_VFS_ACL_EXECUTE;
  188. }
  189. return i;
  190. }
  191. static acl_entry_t
  192. find_entry (acl_t acl, acl_tag_t type, id_t id)
  193. {
  194. acl_entry_t ent;
  195. acl_tag_t e_type;
  196. id_t *e_id_p;
  197. if (acl_get_entry(acl, ACL_FIRST_ENTRY, &ent) != 1)
  198. return NULL;
  199. for(;;) {
  200. acl_get_tag_type(ent, &e_type);
  201. if (type == e_type) {
  202. if (id == ACL_UNDEFINED_ID)
  203. return ent;
  204. e_id_p = acl_get_qualifier(ent);
  205. if (e_id_p == NULL)
  206. return NULL;
  207. if (*e_id_p == id) {
  208. acl_free(e_id_p);
  209. return ent;
  210. }
  211. acl_free(e_id_p);
  212. }
  213. if (acl_get_entry(acl, ACL_NEXT_ENTRY, &ent) != 1)
  214. return NULL;
  215. }
  216. }
  217. static void
  218. set_permset (acl_permset_t permset, mode_t perm)
  219. {
  220. if (perm & CMD_PERM_READ)
  221. acl_add_perm (permset, ACL_READ);
  222. else
  223. acl_delete_perm (permset, ACL_READ);
  224. if (perm & CMD_PERM_WRITE)
  225. acl_add_perm (permset, ACL_WRITE);
  226. else
  227. acl_delete_perm (permset, ACL_WRITE);
  228. if (perm & CMD_PERM_EXECUTE)
  229. acl_add_perm (permset, ACL_EXECUTE);
  230. else
  231. acl_delete_perm (permset, ACL_EXECUTE);
  232. }
  233. static int
  234. clone_entry (acl_t from_acl, acl_tag_t from_type,
  235. acl_t *to_acl, acl_tag_t to_type)
  236. {
  237. acl_entry_t from_entry;
  238. acl_entry_t to_entry;
  239. from_entry = find_entry(from_acl, from_type, ACL_UNDEFINED_ID);
  240. if (from_entry == NULL) return 1;
  241. if (acl_create_entry(to_acl, &to_entry) != 0)
  242. return -1;
  243. acl_copy_entry(to_entry, from_entry);
  244. acl_set_tag_type(to_entry, to_type);
  245. return 0;
  246. }
  247. static int
  248. posix_acl_read (GnomeVFSACL *acl,
  249. acl_t p_acl,
  250. gboolean def)
  251. {
  252. acl_entry_t entry;
  253. int res;
  254. int e_id;
  255. int n;
  256. if (p_acl == NULL) {
  257. return 0;
  258. }
  259. n = 0;
  260. e_id = ACL_FIRST_ENTRY;
  261. while ((res = acl_get_entry (p_acl, e_id, &entry)) == 1) {
  262. GnomeVFSACLPerm pset[POSIX_N_TAGS + 1];
  263. GnomeVFSACLKind kind;
  264. GnomeVFSACE *ace;
  265. acl_permset_t e_ps;
  266. acl_tag_t e_type;
  267. void *e_qf;
  268. char *id;
  269. e_id = ACL_NEXT_ENTRY;
  270. e_type = ACL_UNDEFINED_ID;
  271. e_qf = NULL;
  272. /* prop = (def) ? GNOME_VFS_ACL_DEFAULT : GNOME_VFS_ACL_TYPE_NULL; */
  273. /* Read "default"
  274. */
  275. res = acl_get_tag_type (entry, &e_type);
  276. if (res == -1 || e_type == ACL_UNDEFINED_ID || e_type == ACL_MASK) {
  277. continue;
  278. }
  279. if (def == FALSE && (e_type != ACL_USER && e_type != ACL_GROUP)) {
  280. /* skip the standard unix permissions */
  281. continue;
  282. }
  283. res = acl_get_permset (entry, &e_ps);
  284. if (res == -1) {
  285. continue;
  286. }
  287. e_qf = acl_get_qualifier (entry);
  288. id = NULL;
  289. kind = GNOME_VFS_ACL_KIND_NULL;
  290. switch (e_type) {
  291. case ACL_USER:
  292. id = uid_to_string (*(uid_t *) e_qf);
  293. /* FALLTHROUGH */
  294. case ACL_USER_OBJ:
  295. kind = GNOME_VFS_ACL_USER;
  296. break;
  297. case ACL_GROUP:
  298. id = gid_to_string (*(gid_t *) e_qf);
  299. /* FALLTHROUGH */
  300. case ACL_GROUP_OBJ:
  301. kind = GNOME_VFS_ACL_GROUP;
  302. break;
  303. case ACL_MASK:
  304. case ACL_OTHER:
  305. kind = GNOME_VFS_ACL_OTHER;
  306. break;
  307. }
  308. permset_to_perms (e_ps, pset);
  309. ace = gnome_vfs_ace_new (kind, id, pset);
  310. g_free (id);
  311. if (def) {
  312. g_object_set (G_OBJECT(ace), "inherit", def, NULL);
  313. }
  314. gnome_vfs_acl_set (acl, ace);
  315. g_object_unref (ace);
  316. if (e_qf) {
  317. acl_free (e_qf);
  318. }
  319. n++;
  320. }
  321. return n;
  322. }
  323. #endif /* HAVE_POSIX_ACL */
  324. /* ************************************************************************** */
  325. /* SOLARIS ACL */
  326. #ifdef HAVE_SOLARIS_ACL
  327. #define SOLARIS_N_TAGS 3
  328. static gboolean
  329. fixup_acl (GnomeVFSACL *acl, GSList *acls)
  330. {
  331. GSList *i;
  332. gboolean defaults = FALSE;
  333. gboolean user_obj = FALSE;
  334. gboolean group_obj = FALSE;
  335. gboolean other_obj = FALSE;
  336. gboolean mask_obj = FALSE;
  337. gboolean class_needed = FALSE;
  338. gboolean changed = FALSE;
  339. /* Is there some default entry?
  340. */
  341. for (i=acls; i != NULL; i=i->next) {
  342. const char *id_str;
  343. GnomeVFSACLKind kind;
  344. GnomeVFSACE *ace = GNOME_VFS_ACE(i->data);
  345. if (!gnome_vfs_ace_get_inherit(ace))
  346. continue;
  347. defaults = TRUE;
  348. id_str = gnome_vfs_ace_get_id (ace);
  349. kind = gnome_vfs_ace_get_kind (ace);
  350. switch (kind) {
  351. case GNOME_VFS_ACL_USER:
  352. if (id_str == NULL)
  353. user_obj = TRUE;
  354. else
  355. class_needed = TRUE;
  356. break;
  357. case GNOME_VFS_ACL_GROUP:
  358. if (id_str == NULL)
  359. group_obj = TRUE;
  360. else
  361. class_needed = TRUE;
  362. break;
  363. case GNOME_VFS_ACL_OTHER:
  364. if (id_str == NULL)
  365. other_obj = TRUE;
  366. break;
  367. case GNOME_VFS_ACL_MASK:
  368. if (id_str == NULL)
  369. mask_obj = TRUE;
  370. break;
  371. default:
  372. break;
  373. }
  374. }
  375. if (!defaults) return FALSE;
  376. /* Add the missing ACEs
  377. */
  378. if (!user_obj) {
  379. GnomeVFSACE *ace;
  380. GnomeVFSACLPerm perms[] = {GNOME_VFS_ACL_READ,
  381. GNOME_VFS_ACL_WRITE,
  382. GNOME_VFS_ACL_EXECUTE, 0};
  383. ace = gnome_vfs_ace_new (GNOME_VFS_ACL_USER, NULL, perms);
  384. gnome_vfs_ace_set_inherit (ace, TRUE);
  385. gnome_vfs_acl_set (acl, ace);
  386. g_slist_append(acls, ace);
  387. changed = TRUE;
  388. }
  389. if (!group_obj) {
  390. GnomeVFSACE *ace;
  391. GnomeVFSACLPerm perms[] = {0};
  392. ace = gnome_vfs_ace_new (GNOME_VFS_ACL_GROUP, NULL, perms);
  393. gnome_vfs_ace_set_inherit (ace, TRUE);
  394. gnome_vfs_acl_set (acl, ace);
  395. changed = TRUE;
  396. }
  397. if (!other_obj) {
  398. GnomeVFSACE *ace;
  399. GnomeVFSACLPerm perms[] = {0};
  400. ace = gnome_vfs_ace_new (GNOME_VFS_ACL_OTHER, NULL, perms);
  401. gnome_vfs_ace_set_inherit (ace, TRUE);
  402. gnome_vfs_acl_set (acl, ace);
  403. changed = TRUE;
  404. }
  405. if (class_needed && !mask_obj) {
  406. GnomeVFSACE *ace;
  407. GnomeVFSACLPerm perms[] = {GNOME_VFS_ACL_READ,
  408. GNOME_VFS_ACL_WRITE,
  409. GNOME_VFS_ACL_EXECUTE, 0};
  410. ace = gnome_vfs_ace_new (GNOME_VFS_ACL_MASK, NULL, perms);
  411. gnome_vfs_ace_set_inherit (ace, TRUE);
  412. gnome_vfs_acl_set (acl, ace);
  413. changed = TRUE;
  414. }
  415. return changed;
  416. }
  417. static int
  418. permset_to_perms (int set, GnomeVFSACLPerm *tags)
  419. {
  420. int i;
  421. memset (tags, 0, sizeof (GnomeVFSACLPerm) * (SOLARIS_N_TAGS + 1));
  422. i = 0;
  423. if (set & 4) {
  424. tags[i] = GNOME_VFS_ACL_READ;
  425. i++;
  426. }
  427. if (set & 2) {
  428. tags[i] = GNOME_VFS_ACL_WRITE;
  429. i++;
  430. }
  431. if (set & 1) {
  432. tags[i] = GNOME_VFS_ACL_EXECUTE;
  433. i++;
  434. }
  435. return i;
  436. }
  437. static int
  438. solaris_acl_read (GnomeVFSACL *acl,
  439. aclent_t *aclp,
  440. int aclcnt,
  441. gboolean def)
  442. {
  443. int i;
  444. aclent_t *tp;
  445. for (tp = aclp, i=0; i < aclcnt; tp++, i++) {
  446. GnomeVFSACE *ace;
  447. GnomeVFSACLKind kind;
  448. GnomeVFSACLPerm pset[SOLARIS_N_TAGS+1];
  449. char *id;
  450. id = NULL;
  451. kind = GNOME_VFS_ACL_KIND_NULL;
  452. switch (tp->a_type) {
  453. case USER:
  454. case DEF_USER:
  455. id = uid_to_string(tp->a_id);
  456. case USER_OBJ:
  457. case DEF_USER_OBJ:
  458. kind = GNOME_VFS_ACL_USER;
  459. break;
  460. case GROUP:
  461. case DEF_GROUP:
  462. id = gid_to_string(tp->a_id);
  463. case GROUP_OBJ:
  464. case DEF_GROUP_OBJ:
  465. kind = GNOME_VFS_ACL_GROUP;
  466. break;
  467. case OTHER_OBJ:
  468. case DEF_OTHER_OBJ:
  469. kind = GNOME_VFS_ACL_OTHER;
  470. break;
  471. case CLASS_OBJ:
  472. case DEF_CLASS_OBJ:
  473. kind = GNOME_VFS_ACL_MASK;
  474. break;
  475. default:
  476. g_warning ("Unhandled Solaris ACE: %d\n", tp->a_type);
  477. }
  478. permset_to_perms (tp->a_perm, pset);
  479. ace = gnome_vfs_ace_new (kind, id, pset);
  480. if (tp->a_type & ACL_DEFAULT)
  481. gnome_vfs_ace_set_inherit (ace, TRUE);
  482. gnome_vfs_acl_set (acl, ace);
  483. g_object_unref (ace);
  484. }
  485. return 0;
  486. }
  487. static GnomeVFSResult
  488. translate_ace_into_aclent (GnomeVFSACE *ace, aclent_t *aclp)
  489. {
  490. int re;
  491. gboolean is_default = FALSE;
  492. const char *id_str;
  493. GnomeVFSACLKind kind;
  494. int id;
  495. id_str = gnome_vfs_ace_get_id (ace);
  496. kind = gnome_vfs_ace_get_kind (ace);
  497. is_default = gnome_vfs_ace_get_inherit (ace);
  498. aclp->a_perm = 0;
  499. aclp->a_id = 0;
  500. aclp->a_type = 0;
  501. /* Permissions
  502. */
  503. if (gnome_vfs_ace_check_perm (ace, GNOME_VFS_ACL_READ)) {
  504. aclp->a_perm |= 4;
  505. }
  506. if (gnome_vfs_ace_check_perm (ace, GNOME_VFS_ACL_WRITE)) {
  507. aclp->a_perm |= 2;
  508. }
  509. if (gnome_vfs_ace_check_perm (ace, GNOME_VFS_ACL_EXECUTE)) {
  510. aclp->a_perm |= 1;
  511. }
  512. /* Kind
  513. */
  514. id = NULL;
  515. switch (kind) {
  516. case GNOME_VFS_ACL_USER:
  517. if (id_str) {
  518. aclp->a_type = (is_default) ? DEF_USER : USER;
  519. aclp->a_id = string_to_uid (id_str);
  520. } else {
  521. aclp->a_type = (is_default) ? DEF_USER_OBJ : USER_OBJ;
  522. }
  523. break;
  524. case GNOME_VFS_ACL_GROUP:
  525. if (id_str) {
  526. aclp->a_type = (is_default) ? DEF_GROUP : GROUP;
  527. aclp->a_id = string_to_gid (id_str);
  528. } else {
  529. aclp->a_type = (is_default) ? DEF_GROUP_OBJ : GROUP_OBJ;
  530. }
  531. break;
  532. case GNOME_VFS_ACL_OTHER:
  533. aclp->a_type = (is_default) ? DEF_OTHER_OBJ : OTHER_OBJ;
  534. break;
  535. case GNOME_VFS_ACL_MASK:
  536. aclp->a_type = (is_default) ? DEF_CLASS_OBJ : CLASS_OBJ;
  537. break;
  538. default:
  539. return GNOME_VFS_ERROR_NOT_SUPPORTED;
  540. }
  541. return GNOME_VFS_OK;
  542. }
  543. #endif /* HAVE_SOLARIS_ACL */
  544. /* ************************************************************************** */
  545. /* Common */
  546. static GnomeVFSResult
  547. aclerrno_to_vfserror (int acl_errno)
  548. {
  549. switch (acl_errno) {
  550. case ENOENT:
  551. case EINVAL:
  552. return GNOME_VFS_ERROR_BAD_FILE;
  553. case ENOSYS:
  554. return GNOME_VFS_ERROR_NOT_SUPPORTED;
  555. case EACCES:
  556. return GNOME_VFS_ERROR_ACCESS_DENIED;
  557. case ENAMETOOLONG:
  558. return GNOME_VFS_ERROR_NAME_TOO_LONG;
  559. case EPERM:
  560. return GNOME_VFS_ERROR_NOT_PERMITTED;
  561. case ENOSPC:
  562. return GNOME_VFS_ERROR_NO_SPACE;
  563. case EROFS:
  564. return GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM;
  565. default:
  566. break;
  567. }
  568. return GNOME_VFS_ERROR_GENERIC;
  569. }
  570. #endif /* HAVE_ACL */
  571. GnomeVFSResult file_get_acl (const char *path,
  572. GnomeVFSFileInfo *info,
  573. struct stat *statbuf,
  574. GnomeVFSContext *context)
  575. {
  576. #ifdef HAVE_SOLARIS_ACL
  577. int re;
  578. int aclcnt;
  579. aclent_t *aclp;
  580. if (info->acl != NULL) {
  581. gnome_vfs_acl_clear (info->acl);
  582. } else {
  583. info->acl = gnome_vfs_acl_new ();
  584. }
  585. aclcnt = acl (path, GETACLCNT, 0, NULL);
  586. if (aclcnt < 0) {
  587. return aclerrno_to_vfserror (errno);
  588. }
  589. if (aclcnt < MIN_ACL_ENTRIES) {
  590. return GNOME_VFS_ERROR_INTERNAL;
  591. }
  592. aclp = (aclent_t *)malloc(sizeof (aclent_t) * aclcnt);
  593. if (aclp == NULL) {
  594. return GNOME_VFS_ERROR_NO_MEMORY;
  595. }
  596. errno = 0;
  597. re = acl (path, GETACL, aclcnt, aclp);
  598. if (re < 0) {
  599. return aclerrno_to_vfserror (errno);
  600. }
  601. re = solaris_acl_read (info->acl, aclp, aclcnt, FALSE);
  602. if (re < 0) {
  603. return GNOME_VFS_ERROR_INTERNAL;
  604. }
  605. info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_ACL;
  606. free (aclp);
  607. return GNOME_VFS_OK;
  608. #elif defined(HAVE_POSIX_ACL)
  609. acl_t p_acl;
  610. int n;
  611. if (info->acl != NULL) {
  612. gnome_vfs_acl_clear (info->acl);
  613. } else {
  614. info->acl = gnome_vfs_acl_new ();
  615. }
  616. p_acl = acl_get_file (path, ACL_TYPE_ACCESS);
  617. n = posix_acl_read (info->acl, p_acl, FALSE);
  618. if (p_acl) {
  619. acl_free (p_acl);
  620. }
  621. if (S_ISDIR (statbuf->st_mode)) {
  622. p_acl = acl_get_file (path, ACL_TYPE_DEFAULT);
  623. n += posix_acl_read (info->acl, p_acl, TRUE);
  624. if (p_acl) {
  625. acl_free (p_acl);
  626. }
  627. }
  628. if (n > 0) {
  629. info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_ACL;
  630. } else {
  631. g_object_unref (info->acl);
  632. info->acl = NULL;
  633. }
  634. return GNOME_VFS_OK;
  635. #else
  636. return GNOME_VFS_ERROR_NOT_SUPPORTED;
  637. #endif
  638. }
  639. GnomeVFSResult
  640. file_set_acl (const char *path,
  641. const GnomeVFSFileInfo *info,
  642. GnomeVFSContext *context)
  643. {
  644. #ifdef HAVE_SOLARIS_ACL
  645. GList *acls;
  646. GList *entry;
  647. guint len;
  648. GnomeVFSResult re;
  649. aclent_t *new_aclp;
  650. aclent_t *taclp;
  651. guint aclp_i;
  652. gboolean changed;
  653. if (info->acl == NULL)
  654. return GNOME_VFS_ERROR_BAD_PARAMETERS;
  655. acls = gnome_vfs_acl_get_ace_list (info->acl);
  656. if (acls == NULL) return GNOME_VFS_OK;
  657. changed = fixup_acl (info->acl, acls);
  658. if (changed) {
  659. gnome_vfs_acl_free_ace_list (acls);
  660. acls = gnome_vfs_acl_get_ace_list (info->acl);
  661. if (acls == NULL) return GNOME_VFS_OK;
  662. }
  663. len = g_list_length (acls);
  664. if (len <= 0) return GNOME_VFS_OK;
  665. new_aclp = (aclent_t *) malloc (len * sizeof(aclent_t));
  666. if (new_aclp == NULL) return GNOME_VFS_ERROR_NO_MEMORY;
  667. memset (new_aclp, 0, len * sizeof(aclent_t));
  668. aclp_i = 0;
  669. taclp = new_aclp;
  670. for (entry=acls; entry != NULL; entry = entry->next) {
  671. GnomeVFSACE *ace = GNOME_VFS_ACE(entry->data);
  672. re = translate_ace_into_aclent (ace, taclp);
  673. if (re != GNOME_VFS_OK) continue;
  674. aclp_i++;
  675. taclp++;
  676. }
  677. /* Sort it out
  678. */
  679. re = aclsort (aclp_i, 0, (aclent_t *)new_aclp);
  680. if (re == -1) {
  681. g_free (new_aclp);
  682. return GNOME_VFS_ERROR_INTERNAL;
  683. }
  684. /* Commit it to the file system
  685. */
  686. re = acl (path, SETACL, aclp_i, (aclent_t *)new_aclp);
  687. if (re < 0) {
  688. int err = errno;
  689. g_free (new_aclp);
  690. return aclerrno_to_vfserror(err);
  691. }
  692. g_free (new_aclp);
  693. return GNOME_VFS_OK;
  694. #elif defined(HAVE_POSIX_ACL)
  695. GList *acls;
  696. GList *entry;
  697. acl_t acl_obj;
  698. acl_t acl_obj_default;
  699. if (info->acl == NULL)
  700. return GNOME_VFS_ERROR_BAD_PARAMETERS;
  701. /* POSIX ACL object
  702. */
  703. acl_obj_default = acl_get_file (path, ACL_TYPE_DEFAULT);
  704. acl_obj = acl_get_file (path, ACL_TYPE_ACCESS);
  705. if (acl_obj == NULL) return GNOME_VFS_ERROR_GENERIC;
  706. /* Parse stored information
  707. */
  708. acls = gnome_vfs_acl_get_ace_list (info->acl);
  709. if (acls == NULL) return GNOME_VFS_OK;
  710. for (entry=acls; entry != NULL; entry = entry->next) {
  711. GnomeVFSACE *ace = GNOME_VFS_ACE(entry->data);
  712. gboolean is_default = FALSE;
  713. const char *id_str;
  714. GnomeVFSACLKind kind;
  715. int id;
  716. int re;
  717. acl_tag_t type;
  718. mode_t perms = 0;
  719. acl_entry_t new_entry = NULL;
  720. acl_permset_t permset = NULL;
  721. id_str = gnome_vfs_ace_get_id (ace);
  722. kind = gnome_vfs_ace_get_kind (ace);
  723. is_default = gnome_vfs_ace_get_inherit (ace);
  724. /* Perms
  725. */
  726. if (gnome_vfs_ace_check_perm (ace, GNOME_VFS_ACL_READ))
  727. perms |= CMD_PERM_READ;
  728. else if (gnome_vfs_ace_check_perm (ace, GNOME_VFS_ACL_WRITE))
  729. perms |= CMD_PERM_WRITE;
  730. else if (gnome_vfs_ace_check_perm (ace, GNOME_VFS_ACL_EXECUTE))
  731. perms |= CMD_PERM_EXECUTE;
  732. /* Type
  733. */
  734. switch (kind) {
  735. case GNOME_VFS_ACL_USER:
  736. id = string_to_uid (id_str);
  737. type = ACL_USER;
  738. break;
  739. case GNOME_VFS_ACL_GROUP:
  740. id = string_to_gid (id_str);
  741. type = ACL_GROUP;
  742. break;
  743. case GNOME_VFS_ACL_OTHER:
  744. type = ACL_OTHER;
  745. break;
  746. default:
  747. return GNOME_VFS_ERROR_NOT_SUPPORTED;
  748. }
  749. /* Add the entry
  750. */
  751. new_entry = find_entry (acl_obj, type, id);
  752. if (new_entry == NULL) {
  753. /* new */
  754. if (is_default)
  755. re = acl_create_entry (&acl_obj_default, &new_entry);
  756. else
  757. re = acl_create_entry (&acl_obj, &new_entry);
  758. if (re != 0) return aclerrno_to_vfserror (errno);
  759. /* e_tag */
  760. re = acl_set_tag_type (new_entry, type);
  761. if (re != 0) return aclerrno_to_vfserror (errno);
  762. /* e_id */
  763. re = acl_set_qualifier (new_entry, &id);
  764. if (re != 0) return aclerrno_to_vfserror (errno);
  765. }
  766. /* e_perm */
  767. re = acl_get_permset (new_entry, &permset);
  768. if (re != 0) return aclerrno_to_vfserror (errno);
  769. set_permset (permset, perms);
  770. /* Fix it up
  771. */
  772. if (is_default && (acl_obj_default != NULL)) {
  773. if (! find_entry (acl_obj_default, ACL_USER_OBJ, ACL_UNDEFINED_ID)) {
  774. clone_entry (acl_obj, ACL_USER_OBJ, &acl_obj_default, ACL_USER_OBJ);
  775. }
  776. if (! find_entry (acl_obj_default, ACL_GROUP_OBJ, ACL_UNDEFINED_ID)) {
  777. clone_entry (acl_obj, ACL_GROUP_OBJ, &acl_obj_default, ACL_GROUP_OBJ);
  778. }
  779. if (! find_entry (acl_obj_default, ACL_OTHER, ACL_UNDEFINED_ID)) {
  780. clone_entry (acl_obj, ACL_OTHER, &acl_obj_default, ACL_OTHER);
  781. }
  782. }
  783. if (acl_equiv_mode (acl_obj, NULL) != 0) {
  784. if (! find_entry (acl_obj, ACL_MASK, ACL_UNDEFINED_ID)) {
  785. clone_entry (acl_obj, ACL_GROUP_OBJ, &acl_obj, ACL_MASK);
  786. }
  787. if (is_default)
  788. re = acl_calc_mask (&acl_obj_default);
  789. else
  790. re = acl_calc_mask (&acl_obj);
  791. if (re != 0) return aclerrno_to_vfserror (errno);
  792. }
  793. }
  794. gnome_vfs_acl_free_ace_list (acls);
  795. return GNOME_VFS_OK;
  796. #else
  797. return GNOME_VFS_ERROR_NOT_SUPPORTED;
  798. #endif
  799. }