linux/fs/hfs/attr.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *  linux/fs/hfs/attr.c
   4 *
   5 * (C) 2003 Ardis Technologies <roman@ardistech.com>
   6 *
   7 * Export hfs data via xattr
   8 */
   9
  10
  11#include <linux/fs.h>
  12#include <linux/xattr.h>
  13
  14#include "hfs_fs.h"
  15#include "btree.h"
  16
  17enum hfs_xattr_type {
  18        HFS_TYPE,
  19        HFS_CREATOR,
  20};
  21
  22static int __hfs_setxattr(struct inode *inode, enum hfs_xattr_type type,
  23                          const void *value, size_t size, int flags)
  24{
  25        struct hfs_find_data fd;
  26        hfs_cat_rec rec;
  27        struct hfs_cat_file *file;
  28        int res;
  29
  30        if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode))
  31                return -EOPNOTSUPP;
  32
  33        res = hfs_find_init(HFS_SB(inode->i_sb)->cat_tree, &fd);
  34        if (res)
  35                return res;
  36        fd.search_key->cat = HFS_I(inode)->cat_key;
  37        res = hfs_brec_find(&fd);
  38        if (res)
  39                goto out;
  40        hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
  41                        sizeof(struct hfs_cat_file));
  42        file = &rec.file;
  43
  44        switch (type) {
  45        case HFS_TYPE:
  46                if (size == 4)
  47                        memcpy(&file->UsrWds.fdType, value, 4);
  48                else
  49                        res = -ERANGE;
  50                break;
  51
  52        case HFS_CREATOR:
  53                if (size == 4)
  54                        memcpy(&file->UsrWds.fdCreator, value, 4);
  55                else
  56                        res = -ERANGE;
  57                break;
  58        }
  59
  60        if (!res)
  61                hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
  62                                sizeof(struct hfs_cat_file));
  63out:
  64        hfs_find_exit(&fd);
  65        return res;
  66}
  67
  68static ssize_t __hfs_getxattr(struct inode *inode, enum hfs_xattr_type type,
  69                              void *value, size_t size)
  70{
  71        struct hfs_find_data fd;
  72        hfs_cat_rec rec;
  73        struct hfs_cat_file *file;
  74        ssize_t res = 0;
  75
  76        if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode))
  77                return -EOPNOTSUPP;
  78
  79        if (size) {
  80                res = hfs_find_init(HFS_SB(inode->i_sb)->cat_tree, &fd);
  81                if (res)
  82                        return res;
  83                fd.search_key->cat = HFS_I(inode)->cat_key;
  84                res = hfs_brec_find(&fd);
  85                if (res)
  86                        goto out;
  87                hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
  88                                sizeof(struct hfs_cat_file));
  89        }
  90        file = &rec.file;
  91
  92        switch (type) {
  93        case HFS_TYPE:
  94                if (size >= 4) {
  95                        memcpy(value, &file->UsrWds.fdType, 4);
  96                        res = 4;
  97                } else
  98                        res = size ? -ERANGE : 4;
  99                break;
 100
 101        case HFS_CREATOR:
 102                if (size >= 4) {
 103                        memcpy(value, &file->UsrWds.fdCreator, 4);
 104                        res = 4;
 105                } else
 106                        res = size ? -ERANGE : 4;
 107                break;
 108        }
 109
 110out:
 111        if (size)
 112                hfs_find_exit(&fd);
 113        return res;
 114}
 115
 116static int hfs_xattr_get(const struct xattr_handler *handler,
 117                         struct dentry *unused, struct inode *inode,
 118                         const char *name, void *value, size_t size)
 119{
 120        return __hfs_getxattr(inode, handler->flags, value, size);
 121}
 122
 123static int hfs_xattr_set(const struct xattr_handler *handler,
 124                         struct user_namespace *mnt_userns,
 125                         struct dentry *unused, struct inode *inode,
 126                         const char *name, const void *value, size_t size,
 127                         int flags)
 128{
 129        if (!value)
 130                return -EOPNOTSUPP;
 131
 132        return __hfs_setxattr(inode, handler->flags, value, size, flags);
 133}
 134
 135static const struct xattr_handler hfs_creator_handler = {
 136        .name = "hfs.creator",
 137        .flags = HFS_CREATOR,
 138        .get = hfs_xattr_get,
 139        .set = hfs_xattr_set,
 140};
 141
 142static const struct xattr_handler hfs_type_handler = {
 143        .name = "hfs.type",
 144        .flags = HFS_TYPE,
 145        .get = hfs_xattr_get,
 146        .set = hfs_xattr_set,
 147};
 148
 149const struct xattr_handler *hfs_xattr_handlers[] = {
 150        &hfs_creator_handler,
 151        &hfs_type_handler,
 152        NULL
 153};
 154