attr.c 3.02 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0
Linus Torvalds's avatar
Linus Torvalds committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 *  linux/fs/hfs/attr.c
 *
 * (C) 2003 Ardis Technologies <roman@ardistech.com>
 *
 * Export hfs data via xattr
 */


#include <linux/fs.h>
#include <linux/xattr.h>

#include "hfs_fs.h"
#include "btree.h"

17 18 19 20 21 22 23
enum hfs_xattr_type {
	HFS_TYPE,
	HFS_CREATOR,
};

static int __hfs_setxattr(struct inode *inode, enum hfs_xattr_type type,
			  const void *value, size_t size, int flags)
Linus Torvalds's avatar
Linus Torvalds committed
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
{
	struct hfs_find_data fd;
	hfs_cat_rec rec;
	struct hfs_cat_file *file;
	int res;

	if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode))
		return -EOPNOTSUPP;

	res = hfs_find_init(HFS_SB(inode->i_sb)->cat_tree, &fd);
	if (res)
		return res;
	fd.search_key->cat = HFS_I(inode)->cat_key;
	res = hfs_brec_find(&fd);
	if (res)
		goto out;
	hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
			sizeof(struct hfs_cat_file));
	file = &rec.file;

44 45
	switch (type) {
	case HFS_TYPE:
Linus Torvalds's avatar
Linus Torvalds committed
46 47 48 49
		if (size == 4)
			memcpy(&file->UsrWds.fdType, value, 4);
		else
			res = -ERANGE;
50 51 52
		break;

	case HFS_CREATOR:
Linus Torvalds's avatar
Linus Torvalds committed
53 54 55 56
		if (size == 4)
			memcpy(&file->UsrWds.fdCreator, value, 4);
		else
			res = -ERANGE;
57 58 59
		break;
	}

Linus Torvalds's avatar
Linus Torvalds committed
60 61 62 63 64 65 66 67
	if (!res)
		hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
				sizeof(struct hfs_cat_file));
out:
	hfs_find_exit(&fd);
	return res;
}

68 69
static ssize_t __hfs_getxattr(struct inode *inode, enum hfs_xattr_type type,
			      void *value, size_t size)
Linus Torvalds's avatar
Linus Torvalds committed
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
{
	struct hfs_find_data fd;
	hfs_cat_rec rec;
	struct hfs_cat_file *file;
	ssize_t res = 0;

	if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode))
		return -EOPNOTSUPP;

	if (size) {
		res = hfs_find_init(HFS_SB(inode->i_sb)->cat_tree, &fd);
		if (res)
			return res;
		fd.search_key->cat = HFS_I(inode)->cat_key;
		res = hfs_brec_find(&fd);
		if (res)
			goto out;
		hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
				sizeof(struct hfs_cat_file));
	}
	file = &rec.file;

92 93
	switch (type) {
	case HFS_TYPE:
Linus Torvalds's avatar
Linus Torvalds committed
94 95 96 97 98
		if (size >= 4) {
			memcpy(value, &file->UsrWds.fdType, 4);
			res = 4;
		} else
			res = size ? -ERANGE : 4;
99 100 101
		break;

	case HFS_CREATOR:
Linus Torvalds's avatar
Linus Torvalds committed
102 103 104 105 106
		if (size >= 4) {
			memcpy(value, &file->UsrWds.fdCreator, 4);
			res = 4;
		} else
			res = size ? -ERANGE : 4;
107 108 109
		break;
	}

Linus Torvalds's avatar
Linus Torvalds committed
110 111 112 113 114 115
out:
	if (size)
		hfs_find_exit(&fd);
	return res;
}

116 117 118
static int hfs_xattr_get(const struct xattr_handler *handler,
			 struct dentry *unused, struct inode *inode,
			 const char *name, void *value, size_t size)
Linus Torvalds's avatar
Linus Torvalds committed
119
{
120 121
	return __hfs_getxattr(inode, handler->flags, value, size);
}
Linus Torvalds's avatar
Linus Torvalds committed
122

123 124 125 126 127 128
static int hfs_xattr_set(const struct xattr_handler *handler,
			 struct dentry *unused, struct inode *inode,
			 const char *name, const void *value, size_t size,
			 int flags)
{
	if (!value)
Linus Torvalds's avatar
Linus Torvalds committed
129 130
		return -EOPNOTSUPP;

131
	return __hfs_setxattr(inode, handler->flags, value, size, flags);
Linus Torvalds's avatar
Linus Torvalds committed
132
}
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152

static const struct xattr_handler hfs_creator_handler = {
	.name = "hfs.creator",
	.flags = HFS_CREATOR,
	.get = hfs_xattr_get,
	.set = hfs_xattr_set,
};

static const struct xattr_handler hfs_type_handler = {
	.name = "hfs.type",
	.flags = HFS_TYPE,
	.get = hfs_xattr_get,
	.set = hfs_xattr_set,
};

const struct xattr_handler *hfs_xattr_handlers[] = {
	&hfs_creator_handler,
	&hfs_type_handler,
	NULL
};