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(&init_user_ns, 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        switch (type) {
  84        case ACL_TYPE_ACCESS:
  85                ea_name = POSIX_ACL_XATTR_ACCESS;
  86                if (acl) {
  87                        rc = posix_acl_equiv_mode(acl, &inode->i_mode);
  88                        if (rc < 0)
  89                                return rc;
  90                        inode->i_ctime = CURRENT_TIME;
  91                        mark_inode_dirty(inode);
  92                        if (rc == 0)
  93                                acl = NULL;
  94                }
  95                break;
  96        case ACL_TYPE_DEFAULT:
  97                ea_name = POSIX_ACL_XATTR_DEFAULT;
  98                break;
  99        default:
 100                return -EINVAL;
 101        }
 102
 103        if (acl) {
 104                size = posix_acl_xattr_size(acl->a_count);
 105                value = kmalloc(size, GFP_KERNEL);
 106                if (!value)
 107                        return -ENOMEM;
 108                rc = posix_acl_to_xattr(&init_user_ns, acl, value, size);
 109                if (rc < 0)
 110                        goto out;
 111        }
 112        rc = __jfs_setxattr(tid, inode, ea_name, value, size, 0);
 113out:
 114        kfree(value);
 115
 116        if (!rc)
 117                set_cached_acl(inode, type, acl);
 118
 119        return rc;
 120}
 121
 122int jfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 123{
 124        int rc;
 125        tid_t tid;
 126
 127        tid = txBegin(inode->i_sb, 0);
 128        mutex_lock(&JFS_IP(inode)->commit_mutex);
 129        rc = __jfs_set_acl(tid, inode, type, acl);
 130        if (!rc)
 131                rc = txCommit(tid, 1, &inode, 0);
 132        txEnd(tid);
 133        mutex_unlock(&JFS_IP(inode)->commit_mutex);
 134        return rc;
 135}
 136
 137int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
 138{
 139        struct posix_acl *default_acl, *acl;
 140        int rc = 0;
 141
 142        rc = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
 143        if (rc)
 144                return rc;
 145
 146        if (default_acl) {
 147                rc = __jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, default_acl);
 148                posix_acl_release(default_acl);
 149        }
 150
 151        if (acl) {
 152                if (!rc)
 153                        rc = __jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl);
 154                posix_acl_release(acl);
 155        }
 156
 157        JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) |
 158                               inode->i_mode;
 159
 160        return rc;
 161}
 162