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        switch(type) {
  38                case ACL_TYPE_ACCESS:
  39                        ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
  40                        break;
  41                case ACL_TYPE_DEFAULT:
  42                        ea_name = XATTR_NAME_POSIX_ACL_DEFAULT;
  43                        break;
  44                default:
  45                        return ERR_PTR(-EINVAL);
  46        }
  47
  48        size = __jfs_getxattr(inode, ea_name, NULL, 0);
  49
  50        if (size > 0) {
  51                value = kmalloc(size, GFP_KERNEL);
  52                if (!value)
  53                        return ERR_PTR(-ENOMEM);
  54                size = __jfs_getxattr(inode, ea_name, value, size);
  55        }
  56
  57        if (size < 0) {
  58                if (size == -ENODATA)
  59                        acl = NULL;
  60                else
  61                        acl = ERR_PTR(size);
  62        } else {
  63                acl = posix_acl_from_xattr(&init_user_ns, value, size);
  64        }
  65        kfree(value);
  66        return acl;
  67}
  68
  69static int __jfs_set_acl(tid_t tid, struct inode *inode, int type,
  70                       struct posix_acl *acl)
  71{
  72        char *ea_name;
  73        int rc;
  74        int size = 0;
  75        char *value = NULL;
  76
  77        switch (type) {
  78        case ACL_TYPE_ACCESS:
  79                ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
  80                if (acl) {
  81                        rc = posix_acl_update_mode(inode, &inode->i_mode, &acl);
  82                        if (rc)
  83                                return rc;
  84                        inode->i_ctime = current_time(inode);
  85                        mark_inode_dirty(inode);
  86                }
  87                break;
  88        case ACL_TYPE_DEFAULT:
  89                ea_name = XATTR_NAME_POSIX_ACL_DEFAULT;
  90                break;
  91        default:
  92                return -EINVAL;
  93        }
  94
  95        if (acl) {
  96                size = posix_acl_xattr_size(acl->a_count);
  97                value = kmalloc(size, GFP_KERNEL);
  98                if (!value)
  99                        return -ENOMEM;
 100                rc = posix_acl_to_xattr(&init_user_ns, acl, value, size);
 101                if (rc < 0)
 102                        goto out;
 103        }
 104        rc = __jfs_setxattr(tid, inode, ea_name, value, size, 0);
 105out:
 106        kfree(value);
 107
 108        if (!rc)
 109                set_cached_acl(inode, type, acl);
 110
 111        return rc;
 112}
 113
 114int jfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 115{
 116        int rc;
 117        tid_t tid;
 118
 119        tid = txBegin(inode->i_sb, 0);
 120        mutex_lock(&JFS_IP(inode)->commit_mutex);
 121        rc = __jfs_set_acl(tid, inode, type, acl);
 122        if (!rc)
 123                rc = txCommit(tid, 1, &inode, 0);
 124        txEnd(tid);
 125        mutex_unlock(&JFS_IP(inode)->commit_mutex);
 126        return rc;
 127}
 128
 129int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
 130{
 131        struct posix_acl *default_acl, *acl;
 132        int rc = 0;
 133
 134        rc = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
 135        if (rc)
 136                return rc;
 137
 138        if (default_acl) {
 139                rc = __jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, default_acl);
 140                posix_acl_release(default_acl);
 141        }
 142
 143        if (acl) {
 144                if (!rc)
 145                        rc = __jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl);
 146                posix_acl_release(acl);
 147        }
 148
 149        JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) |
 150                               inode->i_mode;
 151
 152        return rc;
 153}
 154