/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
- /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
- /* gnome-vfs-acl.h - ACL Handling for the GNOME Virtual File System.
- Virtual File System.
- Copyright (C) 2005 Christian Kellner
- Copyright (C) 2005 Sun Microsystems
- The Gnome Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
- The Gnome Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
- You should have received a copy of the GNU Library General Public
- License along with the Gnome Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- Authors: Christian Kellner <gicmo@gnome.org>
- Alvaro Lopez Ortega <alvaro@sun.com>
- */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #include <stdio.h>
- #include <errno.h>
- #include <string.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #ifdef HAVE_SYS_RESOURCE_H
- #include <sys/resource.h>
- #endif
- #ifdef HAVE_PWD_H
- # include <pwd.h>
- #endif
- #ifdef HAVE_GRP_H
- # include <grp.h>
- #endif
- #ifdef HAVE_POSIX_ACL
- # include <acl/libacl.h>
- #define HAVE_ACL 1
- #endif
- #ifdef HAVE_SOLARIS_ACL
- # include <sys/acl.h>
- #define HAVE_ACL 1
- #endif
- #include "file-method-acl.h"
- #define CMD_PERM_READ 4
- #define CMD_PERM_WRITE 2
- #define CMD_PERM_EXECUTE 1
- #define CMD_PERM_COND_EXECUTE 8
- #ifdef HAVE_ACL
- static char *
- uid_to_string (uid_t uid)
- {
- char *uid_string = NULL;
- #ifdef HAVE_PWD_H
- struct passwd *pw = NULL;
- gpointer buffer = NULL;
- gint error;
- #if defined (HAVE_POSIX_GETPWUID_R) || defined (HAVE_NONPOSIX_GETPWUID_R)
- struct passwd pwd;
- glong bufsize;
-
- #ifdef _SC_GETPW_R_SIZE_MAX
- bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
- #else
- bufsize = 64;
- #endif /* _SC_GETPW_R_SIZE_MAX */
-
- do {
- g_free (buffer);
- /* why bufsize + 6 see #156446 */
- buffer = g_malloc (bufsize + 6);
- errno = 0;
-
- #ifdef HAVE_POSIX_GETPWUID_R
- error = getpwuid_r (uid, &pwd, buffer, bufsize, &pw);
- error = error < 0 ? errno : error;
- #else /* HAVE_NONPOSIX_GETPWUID_R */
- /* HPUX 11 falls into the HAVE_POSIX_GETPWUID_R case */
- #if defined(_AIX) || defined(__hpux)
- error = getpwuid_r (uid, &pwd, buffer, bufsize);
- pw = error == 0 ? &pwd : NULL;
- #else /* !_AIX */
- pw = getpwuid_r (uid, &pwd, buffer, bufsize);
- error = pw ? 0 : errno;
- #endif /* !_AIX */
- #endif /* HAVE_NONPOSIX_GETPWUID_R */
-
- if (pw == NULL) {
- if (error == 0 || error == ENOENT) {
- break;
- }
- }
- if (bufsize > 32 * 1024) {
- break;
- }
- bufsize *= 2;
-
- } while (pw == NULL);
- #endif /* HAVE_POSIX_GETPWUID_R || HAVE_NONPOSIX_GETPWUID_R */
- if (pw == NULL) {
- setpwent ();
- pw = getpwuid (uid);
- endpwent ();
- }
- if (pw != NULL) {
- uid_string = g_strdup (pw->pw_name);
- }
- #endif /* HAVE_PWD_H */
-
- if (uid_string == NULL) {
- uid_string = g_strdup_printf ("%d", uid);
- }
-
- return uid_string;
- }
- static char *
- gid_to_string (gid_t gid)
- {
- char *gid_string = NULL;
- #ifdef HAVE_GETGRGID_R
- struct group *gr = NULL;
- gpointer buffer = NULL;
- gint error;
- struct group grp;
- glong bufsize;
-
- #ifdef _SC_GETGR_R_SIZE_MAX
- bufsize = sysconf (_SC_GETGR_R_SIZE_MAX);
- #else
- bufsize = 64;
- #endif /* _SC_GETPW_R_SIZE_MAX */
- do {
- g_free (buffer);
- /* why bufsize + 6 see #156446 */
- buffer = g_malloc (bufsize + 6);
- error = getgrgid_r (gid, &grp, buffer, bufsize, &gr);
-
- error = error < 0 ? errno : error;
-
- if (gr == NULL) {
- if (error == 0 || error == ENOENT) {
- break;
- }
- }
- if (bufsize > 32 * 1024) {
- break;
- }
- bufsize *= 2;
-
- } while (gr == NULL);
-
- if (gr != NULL) {
- gid_string = g_strdup (gr->gr_name);
- }
-
- #endif
- if (gid_string == NULL) {
- gid_string = g_strdup_printf ("%d", gid);
- }
-
- return gid_string;
- }
- static uid_t
- string_to_uid (const char *uid)
- {
- struct passwd *passwd;
-
- passwd = getpwnam(uid);
- if (passwd == NULL) return 0;
-
- return passwd->pw_uid;
- }
- static gid_t
- string_to_gid (const char *gid)
- {
- struct group *group;
-
- group = getgrnam (gid);
- if (group == NULL) return 0;
-
- return group->gr_gid;
- }
- /* ************************************************************************** */
- /* POSIX ACL */
- #ifdef HAVE_POSIX_ACL
- #define POSIX_N_TAGS 3
- static int
- permset_to_perms (acl_permset_t set, GnomeVFSACLPerm *tags)
- {
- int i;
-
- memset (tags, 0, sizeof (GnomeVFSACLPerm) * (POSIX_N_TAGS + 1));
- i = 0;
- if (acl_get_perm (set, ACL_READ) == 1) {
- tags[0] = GNOME_VFS_ACL_READ;
- i++;
- }
-
- if (acl_get_perm (set, ACL_WRITE) == 1) {
- tags[i] = GNOME_VFS_ACL_WRITE;
- i++;
- }
-
- if (acl_get_perm (set, ACL_EXECUTE)) {
- tags[i] = GNOME_VFS_ACL_EXECUTE;
- }
- return i;
- }
- static acl_entry_t
- find_entry (acl_t acl, acl_tag_t type, id_t id)
- {
- acl_entry_t ent;
- acl_tag_t e_type;
- id_t *e_id_p;
-
- if (acl_get_entry(acl, ACL_FIRST_ENTRY, &ent) != 1)
- return NULL;
-
- for(;;) {
- acl_get_tag_type(ent, &e_type);
- if (type == e_type) {
- if (id == ACL_UNDEFINED_ID)
- return ent;
-
- e_id_p = acl_get_qualifier(ent);
-
- if (e_id_p == NULL)
- return NULL;
-
- if (*e_id_p == id) {
- acl_free(e_id_p);
- return ent;
- }
-
- acl_free(e_id_p);
- }
-
- if (acl_get_entry(acl, ACL_NEXT_ENTRY, &ent) != 1)
- return NULL;
- }
- }
- static void
- set_permset (acl_permset_t permset, mode_t perm)
- {
- if (perm & CMD_PERM_READ)
- acl_add_perm (permset, ACL_READ);
- else
- acl_delete_perm (permset, ACL_READ);
-
- if (perm & CMD_PERM_WRITE)
- acl_add_perm (permset, ACL_WRITE);
- else
- acl_delete_perm (permset, ACL_WRITE);
-
- if (perm & CMD_PERM_EXECUTE)
- acl_add_perm (permset, ACL_EXECUTE);
- else
- acl_delete_perm (permset, ACL_EXECUTE);
- }
- static int
- clone_entry (acl_t from_acl, acl_tag_t from_type,
- acl_t *to_acl, acl_tag_t to_type)
- {
- acl_entry_t from_entry;
- acl_entry_t to_entry;
-
- from_entry = find_entry(from_acl, from_type, ACL_UNDEFINED_ID);
- if (from_entry == NULL) return 1;
-
- if (acl_create_entry(to_acl, &to_entry) != 0)
- return -1;
-
- acl_copy_entry(to_entry, from_entry);
- acl_set_tag_type(to_entry, to_type);
-
- return 0;
- }
- static int
- posix_acl_read (GnomeVFSACL *acl,
- acl_t p_acl,
- gboolean def)
- {
- acl_entry_t entry;
- int res;
- int e_id;
- int n;
- if (p_acl == NULL) {
- return 0;
- }
- n = 0;
- e_id = ACL_FIRST_ENTRY;
- while ((res = acl_get_entry (p_acl, e_id, &entry)) == 1) {
- GnomeVFSACLPerm pset[POSIX_N_TAGS + 1];
- GnomeVFSACLKind kind;
- GnomeVFSACE *ace;
- acl_permset_t e_ps;
- acl_tag_t e_type;
- void *e_qf;
- char *id;
-
- e_id = ACL_NEXT_ENTRY;
- e_type = ACL_UNDEFINED_ID;
- e_qf = NULL;
-
- /* prop = (def) ? GNOME_VFS_ACL_DEFAULT : GNOME_VFS_ACL_TYPE_NULL; */
- /* Read "default"
- */
-
- res = acl_get_tag_type (entry, &e_type);
- if (res == -1 || e_type == ACL_UNDEFINED_ID || e_type == ACL_MASK) {
- continue;
- }
-
- if (def == FALSE && (e_type != ACL_USER && e_type != ACL_GROUP)) {
- /* skip the standard unix permissions */
- continue;
- }
- res = acl_get_permset (entry, &e_ps);
- if (res == -1) {
- continue;
- }
-
- e_qf = acl_get_qualifier (entry);
-
- id = NULL;
- kind = GNOME_VFS_ACL_KIND_NULL;
- switch (e_type) {
- case ACL_USER:
- id = uid_to_string (*(uid_t *) e_qf);
- /* FALLTHROUGH */
-
- case ACL_USER_OBJ:
- kind = GNOME_VFS_ACL_USER;
- break;
- case ACL_GROUP:
- id = gid_to_string (*(gid_t *) e_qf);
- /* FALLTHROUGH */
- case ACL_GROUP_OBJ:
- kind = GNOME_VFS_ACL_GROUP;
- break;
-
- case ACL_MASK:
- case ACL_OTHER:
- kind = GNOME_VFS_ACL_OTHER;
- break;
- }
-
- permset_to_perms (e_ps, pset);
- ace = gnome_vfs_ace_new (kind, id, pset);
- g_free (id);
- if (def) {
- g_object_set (G_OBJECT(ace), "inherit", def, NULL);
- }
- gnome_vfs_acl_set (acl, ace);
- g_object_unref (ace);
- if (e_qf) {
- acl_free (e_qf);
- }
-
- n++;
- }
-
- return n;
- }
- #endif /* HAVE_POSIX_ACL */
- /* ************************************************************************** */
- /* SOLARIS ACL */
- #ifdef HAVE_SOLARIS_ACL
- #define SOLARIS_N_TAGS 3
- static gboolean
- fixup_acl (GnomeVFSACL *acl, GSList *acls)
- {
- GSList *i;
- gboolean defaults = FALSE;
- gboolean user_obj = FALSE;
- gboolean group_obj = FALSE;
- gboolean other_obj = FALSE;
- gboolean mask_obj = FALSE;
- gboolean class_needed = FALSE;
- gboolean changed = FALSE;
- /* Is there some default entry?
- */
- for (i=acls; i != NULL; i=i->next) {
- const char *id_str;
- GnomeVFSACLKind kind;
- GnomeVFSACE *ace = GNOME_VFS_ACE(i->data);
-
- if (!gnome_vfs_ace_get_inherit(ace))
- continue;
- defaults = TRUE;
- id_str = gnome_vfs_ace_get_id (ace);
- kind = gnome_vfs_ace_get_kind (ace);
- switch (kind) {
- case GNOME_VFS_ACL_USER:
- if (id_str == NULL)
- user_obj = TRUE;
- else
- class_needed = TRUE;
- break;
- case GNOME_VFS_ACL_GROUP:
- if (id_str == NULL)
- group_obj = TRUE;
- else
- class_needed = TRUE;
- break;
- case GNOME_VFS_ACL_OTHER:
- if (id_str == NULL)
- other_obj = TRUE;
- break;
- case GNOME_VFS_ACL_MASK:
- if (id_str == NULL)
- mask_obj = TRUE;
- break;
- default:
- break;
- }
- }
- if (!defaults) return FALSE;
- /* Add the missing ACEs
- */
- if (!user_obj) {
- GnomeVFSACE *ace;
- GnomeVFSACLPerm perms[] = {GNOME_VFS_ACL_READ,
- GNOME_VFS_ACL_WRITE,
- GNOME_VFS_ACL_EXECUTE, 0};
- ace = gnome_vfs_ace_new (GNOME_VFS_ACL_USER, NULL, perms);
- gnome_vfs_ace_set_inherit (ace, TRUE);
- gnome_vfs_acl_set (acl, ace);
- g_slist_append(acls, ace);
- changed = TRUE;
- }
- if (!group_obj) {
- GnomeVFSACE *ace;
- GnomeVFSACLPerm perms[] = {0};
- ace = gnome_vfs_ace_new (GNOME_VFS_ACL_GROUP, NULL, perms);
- gnome_vfs_ace_set_inherit (ace, TRUE);
- gnome_vfs_acl_set (acl, ace);
- changed = TRUE;
- }
- if (!other_obj) {
- GnomeVFSACE *ace;
- GnomeVFSACLPerm perms[] = {0};
- ace = gnome_vfs_ace_new (GNOME_VFS_ACL_OTHER, NULL, perms);
- gnome_vfs_ace_set_inherit (ace, TRUE);
- gnome_vfs_acl_set (acl, ace);
- changed = TRUE;
- }
- if (class_needed && !mask_obj) {
- GnomeVFSACE *ace;
- GnomeVFSACLPerm perms[] = {GNOME_VFS_ACL_READ,
- GNOME_VFS_ACL_WRITE,
- GNOME_VFS_ACL_EXECUTE, 0};
- ace = gnome_vfs_ace_new (GNOME_VFS_ACL_MASK, NULL, perms);
- gnome_vfs_ace_set_inherit (ace, TRUE);
- gnome_vfs_acl_set (acl, ace);
- changed = TRUE;
- }
- return changed;
- }
- static int
- permset_to_perms (int set, GnomeVFSACLPerm *tags)
- {
- int i;
-
- memset (tags, 0, sizeof (GnomeVFSACLPerm) * (SOLARIS_N_TAGS + 1));
- i = 0;
- if (set & 4) {
- tags[i] = GNOME_VFS_ACL_READ;
- i++;
- }
- if (set & 2) {
- tags[i] = GNOME_VFS_ACL_WRITE;
- i++;
- }
- if (set & 1) {
- tags[i] = GNOME_VFS_ACL_EXECUTE;
- i++;
- }
- return i;
- }
- static int
- solaris_acl_read (GnomeVFSACL *acl,
- aclent_t *aclp,
- int aclcnt,
- gboolean def)
- {
- int i;
- aclent_t *tp;
- for (tp = aclp, i=0; i < aclcnt; tp++, i++) {
- GnomeVFSACE *ace;
- GnomeVFSACLKind kind;
- GnomeVFSACLPerm pset[SOLARIS_N_TAGS+1];
- char *id;
- id = NULL;
- kind = GNOME_VFS_ACL_KIND_NULL;
- switch (tp->a_type) {
- case USER:
- case DEF_USER:
- id = uid_to_string(tp->a_id);
- case USER_OBJ:
- case DEF_USER_OBJ:
- kind = GNOME_VFS_ACL_USER;
- break;
- case GROUP:
- case DEF_GROUP:
- id = gid_to_string(tp->a_id);
- case GROUP_OBJ:
- case DEF_GROUP_OBJ:
- kind = GNOME_VFS_ACL_GROUP;
- break;
- case OTHER_OBJ:
- case DEF_OTHER_OBJ:
- kind = GNOME_VFS_ACL_OTHER;
- break;
- case CLASS_OBJ:
- case DEF_CLASS_OBJ:
- kind = GNOME_VFS_ACL_MASK;
- break;
- default:
- g_warning ("Unhandled Solaris ACE: %d\n", tp->a_type);
- }
- permset_to_perms (tp->a_perm, pset);
- ace = gnome_vfs_ace_new (kind, id, pset);
- if (tp->a_type & ACL_DEFAULT)
- gnome_vfs_ace_set_inherit (ace, TRUE);
- gnome_vfs_acl_set (acl, ace);
- g_object_unref (ace);
- }
- return 0;
- }
- static GnomeVFSResult
- translate_ace_into_aclent (GnomeVFSACE *ace, aclent_t *aclp)
- {
- int re;
- gboolean is_default = FALSE;
- const char *id_str;
- GnomeVFSACLKind kind;
- int id;
-
- id_str = gnome_vfs_ace_get_id (ace);
- kind = gnome_vfs_ace_get_kind (ace);
- is_default = gnome_vfs_ace_get_inherit (ace);
- aclp->a_perm = 0;
- aclp->a_id = 0;
- aclp->a_type = 0;
- /* Permissions
- */
- if (gnome_vfs_ace_check_perm (ace, GNOME_VFS_ACL_READ)) {
- aclp->a_perm |= 4;
- }
- if (gnome_vfs_ace_check_perm (ace, GNOME_VFS_ACL_WRITE)) {
- aclp->a_perm |= 2;
- }
- if (gnome_vfs_ace_check_perm (ace, GNOME_VFS_ACL_EXECUTE)) {
- aclp->a_perm |= 1;
- }
- /* Kind
- */
- id = NULL;
- switch (kind) {
- case GNOME_VFS_ACL_USER:
- if (id_str) {
- aclp->a_type = (is_default) ? DEF_USER : USER;
- aclp->a_id = string_to_uid (id_str);
- } else {
- aclp->a_type = (is_default) ? DEF_USER_OBJ : USER_OBJ;
- }
- break;
- case GNOME_VFS_ACL_GROUP:
- if (id_str) {
- aclp->a_type = (is_default) ? DEF_GROUP : GROUP;
- aclp->a_id = string_to_gid (id_str);
- } else {
- aclp->a_type = (is_default) ? DEF_GROUP_OBJ : GROUP_OBJ;
- }
- break;
- case GNOME_VFS_ACL_OTHER:
- aclp->a_type = (is_default) ? DEF_OTHER_OBJ : OTHER_OBJ;
- break;
- case GNOME_VFS_ACL_MASK:
- aclp->a_type = (is_default) ? DEF_CLASS_OBJ : CLASS_OBJ;
- break;
- default:
- return GNOME_VFS_ERROR_NOT_SUPPORTED;
- }
- return GNOME_VFS_OK;
- }
- #endif /* HAVE_SOLARIS_ACL */
- /* ************************************************************************** */
- /* Common */
- static GnomeVFSResult
- aclerrno_to_vfserror (int acl_errno)
- {
- switch (acl_errno) {
- case ENOENT:
- case EINVAL:
- return GNOME_VFS_ERROR_BAD_FILE;
- case ENOSYS:
- return GNOME_VFS_ERROR_NOT_SUPPORTED;
- case EACCES:
- return GNOME_VFS_ERROR_ACCESS_DENIED;
- case ENAMETOOLONG:
- return GNOME_VFS_ERROR_NAME_TOO_LONG;
- case EPERM:
- return GNOME_VFS_ERROR_NOT_PERMITTED;
- case ENOSPC:
- return GNOME_VFS_ERROR_NO_SPACE;
- case EROFS:
- return GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM;
- default:
- break;
- }
-
- return GNOME_VFS_ERROR_GENERIC;
- }
- #endif /* HAVE_ACL */
- GnomeVFSResult file_get_acl (const char *path,
- GnomeVFSFileInfo *info,
- struct stat *statbuf,
- GnomeVFSContext *context)
- {
- #ifdef HAVE_SOLARIS_ACL
- int re;
- int aclcnt;
- aclent_t *aclp;
- if (info->acl != NULL) {
- gnome_vfs_acl_clear (info->acl);
- } else {
- info->acl = gnome_vfs_acl_new ();
- }
-
- aclcnt = acl (path, GETACLCNT, 0, NULL);
- if (aclcnt < 0) {
- return aclerrno_to_vfserror (errno);
- }
- if (aclcnt < MIN_ACL_ENTRIES) {
- return GNOME_VFS_ERROR_INTERNAL;
- }
- aclp = (aclent_t *)malloc(sizeof (aclent_t) * aclcnt);
- if (aclp == NULL) {
- return GNOME_VFS_ERROR_NO_MEMORY;
- }
- errno = 0;
- re = acl (path, GETACL, aclcnt, aclp);
- if (re < 0) {
- return aclerrno_to_vfserror (errno);
- }
-
- re = solaris_acl_read (info->acl, aclp, aclcnt, FALSE);
- if (re < 0) {
- return GNOME_VFS_ERROR_INTERNAL;
- }
- info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_ACL;
-
- free (aclp);
-
- return GNOME_VFS_OK;
- #elif defined(HAVE_POSIX_ACL)
- acl_t p_acl;
- int n;
-
- if (info->acl != NULL) {
- gnome_vfs_acl_clear (info->acl);
- } else {
- info->acl = gnome_vfs_acl_new ();
- }
-
- p_acl = acl_get_file (path, ACL_TYPE_ACCESS);
- n = posix_acl_read (info->acl, p_acl, FALSE);
-
- if (p_acl) {
- acl_free (p_acl);
- }
-
- if (S_ISDIR (statbuf->st_mode)) {
- p_acl = acl_get_file (path, ACL_TYPE_DEFAULT);
-
- n += posix_acl_read (info->acl, p_acl, TRUE);
-
- if (p_acl) {
- acl_free (p_acl);
- }
- }
-
- if (n > 0) {
- info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_ACL;
- } else {
- g_object_unref (info->acl);
- info->acl = NULL;
- }
-
- return GNOME_VFS_OK;
- #else
- return GNOME_VFS_ERROR_NOT_SUPPORTED;
- #endif
- }
- GnomeVFSResult
- file_set_acl (const char *path,
- const GnomeVFSFileInfo *info,
- GnomeVFSContext *context)
- {
- #ifdef HAVE_SOLARIS_ACL
- GList *acls;
- GList *entry;
- guint len;
- GnomeVFSResult re;
- aclent_t *new_aclp;
- aclent_t *taclp;
- guint aclp_i;
- gboolean changed;
- if (info->acl == NULL)
- return GNOME_VFS_ERROR_BAD_PARAMETERS;
- acls = gnome_vfs_acl_get_ace_list (info->acl);
- if (acls == NULL) return GNOME_VFS_OK;
- changed = fixup_acl (info->acl, acls);
- if (changed) {
- gnome_vfs_acl_free_ace_list (acls);
- acls = gnome_vfs_acl_get_ace_list (info->acl);
- if (acls == NULL) return GNOME_VFS_OK;
- }
- len = g_list_length (acls);
- if (len <= 0) return GNOME_VFS_OK;
- new_aclp = (aclent_t *) malloc (len * sizeof(aclent_t));
- if (new_aclp == NULL) return GNOME_VFS_ERROR_NO_MEMORY;
- memset (new_aclp, 0, len * sizeof(aclent_t));
- aclp_i = 0;
- taclp = new_aclp;
- for (entry=acls; entry != NULL; entry = entry->next) {
- GnomeVFSACE *ace = GNOME_VFS_ACE(entry->data);
-
- re = translate_ace_into_aclent (ace, taclp);
- if (re != GNOME_VFS_OK) continue;
- aclp_i++;
- taclp++;
- }
- /* Sort it out
- */
- re = aclsort (aclp_i, 0, (aclent_t *)new_aclp);
- if (re == -1) {
- g_free (new_aclp);
- return GNOME_VFS_ERROR_INTERNAL;
- }
- /* Commit it to the file system
- */
- re = acl (path, SETACL, aclp_i, (aclent_t *)new_aclp);
- if (re < 0) {
- int err = errno;
- g_free (new_aclp);
- return aclerrno_to_vfserror(err);
- }
- g_free (new_aclp);
- return GNOME_VFS_OK;
-
- #elif defined(HAVE_POSIX_ACL)
- GList *acls;
- GList *entry;
- acl_t acl_obj;
- acl_t acl_obj_default;
- if (info->acl == NULL)
- return GNOME_VFS_ERROR_BAD_PARAMETERS;
-
- /* POSIX ACL object
- */
- acl_obj_default = acl_get_file (path, ACL_TYPE_DEFAULT);
- acl_obj = acl_get_file (path, ACL_TYPE_ACCESS);
- if (acl_obj == NULL) return GNOME_VFS_ERROR_GENERIC;
- /* Parse stored information
- */
- acls = gnome_vfs_acl_get_ace_list (info->acl);
- if (acls == NULL) return GNOME_VFS_OK;
- for (entry=acls; entry != NULL; entry = entry->next) {
- GnomeVFSACE *ace = GNOME_VFS_ACE(entry->data);
- gboolean is_default = FALSE;
- const char *id_str;
- GnomeVFSACLKind kind;
- int id;
- int re;
- acl_tag_t type;
- mode_t perms = 0;
- acl_entry_t new_entry = NULL;
- acl_permset_t permset = NULL;
-
- id_str = gnome_vfs_ace_get_id (ace);
- kind = gnome_vfs_ace_get_kind (ace);
- is_default = gnome_vfs_ace_get_inherit (ace);
-
- /* Perms
- */
- if (gnome_vfs_ace_check_perm (ace, GNOME_VFS_ACL_READ))
- perms |= CMD_PERM_READ;
- else if (gnome_vfs_ace_check_perm (ace, GNOME_VFS_ACL_WRITE))
- perms |= CMD_PERM_WRITE;
- else if (gnome_vfs_ace_check_perm (ace, GNOME_VFS_ACL_EXECUTE))
- perms |= CMD_PERM_EXECUTE;
-
- /* Type
- */
- switch (kind) {
- case GNOME_VFS_ACL_USER:
- id = string_to_uid (id_str);
- type = ACL_USER;
- break;
- case GNOME_VFS_ACL_GROUP:
- id = string_to_gid (id_str);
- type = ACL_GROUP;
- break;
- case GNOME_VFS_ACL_OTHER:
- type = ACL_OTHER;
- break;
- default:
- return GNOME_VFS_ERROR_NOT_SUPPORTED;
- }
- /* Add the entry
- */
- new_entry = find_entry (acl_obj, type, id);
- if (new_entry == NULL) {
- /* new */
- if (is_default)
- re = acl_create_entry (&acl_obj_default, &new_entry);
- else
- re = acl_create_entry (&acl_obj, &new_entry);
- if (re != 0) return aclerrno_to_vfserror (errno);
-
- /* e_tag */
- re = acl_set_tag_type (new_entry, type);
- if (re != 0) return aclerrno_to_vfserror (errno);
-
- /* e_id */
- re = acl_set_qualifier (new_entry, &id);
- if (re != 0) return aclerrno_to_vfserror (errno);
- }
- /* e_perm */
- re = acl_get_permset (new_entry, &permset);
- if (re != 0) return aclerrno_to_vfserror (errno);
- set_permset (permset, perms);
- /* Fix it up
- */
- if (is_default && (acl_obj_default != NULL)) {
- if (! find_entry (acl_obj_default, ACL_USER_OBJ, ACL_UNDEFINED_ID)) {
- clone_entry (acl_obj, ACL_USER_OBJ, &acl_obj_default, ACL_USER_OBJ);
- }
-
- if (! find_entry (acl_obj_default, ACL_GROUP_OBJ, ACL_UNDEFINED_ID)) {
- clone_entry (acl_obj, ACL_GROUP_OBJ, &acl_obj_default, ACL_GROUP_OBJ);
- }
-
- if (! find_entry (acl_obj_default, ACL_OTHER, ACL_UNDEFINED_ID)) {
- clone_entry (acl_obj, ACL_OTHER, &acl_obj_default, ACL_OTHER);
- }
- }
-
- if (acl_equiv_mode (acl_obj, NULL) != 0) {
- if (! find_entry (acl_obj, ACL_MASK, ACL_UNDEFINED_ID)) {
- clone_entry (acl_obj, ACL_GROUP_OBJ, &acl_obj, ACL_MASK);
- }
- if (is_default)
- re = acl_calc_mask (&acl_obj_default);
- else
- re = acl_calc_mask (&acl_obj);
- if (re != 0) return aclerrno_to_vfserror (errno);
- }
- }
-
- gnome_vfs_acl_free_ace_list (acls);
- return GNOME_VFS_OK;
- #else
- return GNOME_VFS_ERROR_NOT_SUPPORTED;
- #endif
- }