[funini.com] -> [kei@sodan] -> Kernel Reading

root/fs/generic_acl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. generic_acl_list
  2. generic_acl_get
  3. generic_acl_set
  4. generic_acl_init
  5. generic_acl_chmod

/*
 * fs/generic_acl.c
 *
 * (C) 2005 Andreas Gruenbacher <agruen@suse.de>
 *
 * This file is released under the GPL.
 */

#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/generic_acl.h>

/**
 * generic_acl_list  -  Generic xattr_handler->list() operation
 * @ops:        Filesystem specific getacl and setacl callbacks
 */
size_t
generic_acl_list(struct inode *inode, struct generic_acl_operations *ops,
                 int type, char *list, size_t list_size)
{
        struct posix_acl *acl;
        const char *name;
        size_t size;

        acl = ops->getacl(inode, type);
        if (!acl)
                return 0;
        posix_acl_release(acl);

        switch(type) {
                case ACL_TYPE_ACCESS:
                        name = POSIX_ACL_XATTR_ACCESS;
                        break;

                case ACL_TYPE_DEFAULT:
                        name = POSIX_ACL_XATTR_DEFAULT;
                        break;

                default:
                        return 0;
        }
        size = strlen(name) + 1;
        if (list && size <= list_size)
                memcpy(list, name, size);
        return size;
}

/**
 * generic_acl_get  -  Generic xattr_handler->get() operation
 * @ops:        Filesystem specific getacl and setacl callbacks
 */
int
generic_acl_get(struct inode *inode, struct generic_acl_operations *ops,
                int type, void *buffer, size_t size)
{
        struct posix_acl *acl;
        int error;

        acl = ops->getacl(inode, type);
        if (!acl)
                return -ENODATA;
        error = posix_acl_to_xattr(acl, buffer, size);
        posix_acl_release(acl);

        return error;
}

/**
 * generic_acl_set  -  Generic xattr_handler->set() operation
 * @ops:        Filesystem specific getacl and setacl callbacks
 */
int
generic_acl_set(struct inode *inode, struct generic_acl_operations *ops,
                int type, const void *value, size_t size)
{
        struct posix_acl *acl = NULL;
        int error;

        if (S_ISLNK(inode->i_mode))
                return -EOPNOTSUPP;
        if (!is_owner_or_cap(inode))
                return -EPERM;
        if (value) {
                acl = posix_acl_from_xattr(value, size);
                if (IS_ERR(acl))
                        return PTR_ERR(acl);
        }
        if (acl) {
                mode_t mode;

                error = posix_acl_valid(acl);
                if (error)
                        goto failed;
                switch(type) {
                        case ACL_TYPE_ACCESS:
                                mode = inode->i_mode;
                                error = posix_acl_equiv_mode(acl, &mode);
                                if (error < 0)
                                        goto failed;
                                inode->i_mode = mode;
                                if (error == 0) {
                                        posix_acl_release(acl);
                                        acl = NULL;
                                }
                                break;

                        case ACL_TYPE_DEFAULT:
                                if (!S_ISDIR(inode->i_mode)) {
                                        error = -EINVAL;
                                        goto failed;
                                }
                                break;
                }
        }
        ops->setacl(inode, type, acl);
        error = 0;
failed:
        posix_acl_release(acl);
        return error;
}

/**
 * generic_acl_init  -  Take care of acl inheritance at @inode create time
 * @ops:        Filesystem specific getacl and setacl callbacks
 *
 * Files created inside a directory with a default ACL inherit the
 * directory's default ACL.
 */
int
generic_acl_init(struct inode *inode, struct inode *dir,
                 struct generic_acl_operations *ops)
{
        struct posix_acl *acl = NULL;
        mode_t mode = inode->i_mode;
        int error;

        inode->i_mode = mode & ~current->fs->umask;
        if (!S_ISLNK(inode->i_mode))
                acl = ops->getacl(dir, ACL_TYPE_DEFAULT);
        if (acl) {
                struct posix_acl *clone;

                if (S_ISDIR(inode->i_mode)) {
                        clone = posix_acl_clone(acl, GFP_KERNEL);
                        error = -ENOMEM;
                        if (!clone)
                                goto cleanup;
                        ops->setacl(inode, ACL_TYPE_DEFAULT, clone);
                        posix_acl_release(clone);
                }
                clone = posix_acl_clone(acl, GFP_KERNEL);
                error = -ENOMEM;
                if (!clone)
                        goto cleanup;
                error = posix_acl_create_masq(clone, &mode);
                if (error >= 0) {
                        inode->i_mode = mode;
                        if (error > 0)
                                ops->setacl(inode, ACL_TYPE_ACCESS, clone);
                }
                posix_acl_release(clone);
        }
        error = 0;

cleanup:
        posix_acl_release(acl);
        return error;
}

/**
 * generic_acl_chmod  -  change the access acl of @inode upon chmod()
 * @ops:        FIlesystem specific getacl and setacl callbacks
 *
 * A chmod also changes the permissions of the owner, group/mask, and
 * other ACL entries.
 */
int
generic_acl_chmod(struct inode *inode, struct generic_acl_operations *ops)
{
        struct posix_acl *acl, *clone;
        int error = 0;

        if (S_ISLNK(inode->i_mode))
                return -EOPNOTSUPP;
        acl = ops->getacl(inode, ACL_TYPE_ACCESS);
        if (acl) {
                clone = posix_acl_clone(acl, GFP_KERNEL);
                posix_acl_release(acl);
                if (!clone)
                        return -ENOMEM;
                error = posix_acl_chmod_masq(clone, inode->i_mode);
                if (!error)
                        ops->setacl(inode, ACL_TYPE_ACCESS, clone);
                posix_acl_release(clone);
        }
        return error;
}

/* [<][>][^][v][top][bottom][index][help] */

[funini.com] -> [kei@sodan] -> Kernel Reading