linux/fs/jfs/acl.c
<<
>>
Prefs
   1/*
   2 *   Copyright (C) International Business Machines  Corp., 2002-2004
   3 *   Copyright (C) Andreas Gruenbacher, 2001
   4 *   Copyright (C) Linus Torvalds, 1991, 1992
   5 *
   6 *   This program is free software;  you can redistribute it and/or modify
   7 *   it under the terms of the GNU General Public License as published by
   8 *   the Free Software Foundation; either version 2 of the License, or
   9 *   (at your option) any later version.
  10 *
  11 *   This program is distributed in the hope that it will be useful,
  12 *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
  13 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
  14 *   the GNU General Public License for more details.
  15 *
  16 *   You should have received a copy of the GNU General Public License
  17 *   along with this program;  if not, write to the Free Software
  18 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 */
  20
  21#include <linux/sched.h>
  22#include <linux/slab.h>
  23#include <linux/fs.h>
  24#include <linux/posix_acl_xattr.h>
  25#include "jfs_incore.h"
  26#include "jfs_txnmgr.h"
  27#include "jfs_xattr.h"
  28#include "jfs_acl.h"
  29
  30struct posix_acl *jfs_get_acl(struct inode *inode, int type)
  31{
  32        struct posix_acl *acl;
  33        char *ea_name;
  34        int size;
  35        char *value = NULL;
  36
  37        acl = get_cached_acl(inode, type);
  38        if (acl != ACL_NOT_CACHED)
  39                return acl;
  40
  41        switch(type) {
  42                case ACL_TYPE_ACCESS:
  43                        ea_name = POSIX_ACL_XATTR_ACCESS;
  44                        break;
  45                case ACL_TYPE_DEFAULT:
  46                        ea_name = POSIX_ACL_XATTR_DEFAULT;
  47                        break;
  48                default:
  49                        return ERR_PTR(-EINVAL);
  50        }
  51
  52        size = __jfs_getxattr(inode, ea_name, NULL, 0);
  53
  54        if (size > 0) {
  55                value = kmalloc(size, GFP_KERNEL);
  56                if (!value)
  57                        return ERR_PTR(-ENOMEM);
  58                size = __jfs_getxattr(inode, ea_name, value, size);
  59        }
  60
  61        if (size < 0) {
  62                if (size == -ENODATA)
  63                        acl = NULL;
  64                else
  65                        acl = ERR_PTR(size);
  66        } else {
  67                acl = posix_acl_from_xattr(value, size);
  68        }
  69        kfree(value);
  70        if (!IS_ERR(acl))
  71                set_cached_acl(inode, type, acl);
  72        return acl;
  73}
  74
  75static int jfs_set_acl(tid_t tid, struct inode *inode, int type,
  76                       struct posix_acl *acl)
  77{
  78        char *ea_name;
  79        int rc;
  80        int size = 0;
  81        char *value = NULL;
  82
  83        if (S_ISLNK(inode->i_mode))
  84                return -EOPNOTSUPP;
  85
  86        switch(type) {
  87                case ACL_TYPE_ACCESS:
  88                        ea_name = POSIX_ACL_XATTR_ACCESS;
  89                        break;
  90                case ACL_TYPE_DEFAULT:
  91                        ea_name = POSIX_ACL_XATTR_DEFAULT;
  92                        if (!S_ISDIR(inode->i_mode))
  93                                return acl ? -EACCES : 0;
  94                        break;
  95                default:
  96                        return -EINVAL;
  97        }
  98        if (acl) {
  99                size = posix_acl_xattr_size(acl->a_count);
 100                value = kmalloc(size, GFP_KERNEL);
 101                if (!value)
 102                        return -ENOMEM;
 103                rc = posix_acl_to_xattr(acl, value, size);
 104                if (rc < 0)
 105                        goto out;
 106        }
 107        rc = __jfs_setxattr(tid, inode, ea_name, value, size, 0);
 108out:
 109        kfree(value);
 110
 111        if (!rc)
 112                set_cached_acl(inode, type, acl);
 113
 114        return rc;
 115}
 116
 117int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
 118{
 119        struct posix_acl *acl = NULL;
 120        int rc = 0;
 121
 122        if (S_ISLNK(inode->i_mode))
 123                return 0;
 124
 125        acl = jfs_get_acl(dir, ACL_TYPE_DEFAULT);
 126        if (IS_ERR(acl))
 127                return PTR_ERR(acl);
 128
 129        if (acl) {
 130                if (S_ISDIR(inode->i_mode)) {
 131                        rc = jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, acl);
 132                        if (rc)
 133                                goto cleanup;
 134                }
 135                rc = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
 136                if (rc < 0)
 137                        goto cleanup; /* posix_acl_release(NULL) is no-op */
 138                if (rc > 0)
 139                        rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl);
 140cleanup:
 141                posix_acl_release(acl);
 142        } else
 143                inode->i_mode &= ~current_umask();
 144
 145        JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) |
 146                               inode->i_mode;
 147
 148        return rc;
 149}
 150
 151int jfs_acl_chmod(struct inode *inode)
 152{
 153        struct posix_acl *acl;
 154        int rc;
 155        tid_t tid;
 156
 157        if (S_ISLNK(inode->i_mode))
 158                return -EOPNOTSUPP;
 159
 160        acl = jfs_get_acl(inode, ACL_TYPE_ACCESS);
 161        if (IS_ERR(acl) || !acl)
 162                return PTR_ERR(acl);
 163
 164        rc = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
 165        if (rc)
 166                return rc;
 167
 168        tid = txBegin(inode->i_sb, 0);
 169        mutex_lock(&JFS_IP(inode)->commit_mutex);
 170        rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl);
 171        if (!rc)
 172                rc = txCommit(tid, 1, &inode, 0);
 173        txEnd(tid);
 174        mutex_unlock(&JFS_IP(inode)->commit_mutex);
 175
 176        posix_acl_release(acl);
 177        return rc;
 178}
 179
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.