^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/fs/hfsplus/xattr.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Vyacheslav Dubeyko <slava@dubeyko.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Logic of processing extended attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "hfsplus_fs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/nls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "xattr.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) static int hfsplus_removexattr(struct inode *inode, const char *name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) const struct xattr_handler *hfsplus_xattr_handlers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) &hfsplus_xattr_osx_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) &hfsplus_xattr_user_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) &hfsplus_xattr_trusted_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) &hfsplus_xattr_security_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static int strcmp_xattr_finder_info(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) if (name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) return strncmp(name, HFSPLUS_XATTR_FINDER_INFO_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) sizeof(HFSPLUS_XATTR_FINDER_INFO_NAME));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static int strcmp_xattr_acl(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) if (name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return strncmp(name, HFSPLUS_XATTR_ACL_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) sizeof(HFSPLUS_XATTR_ACL_NAME));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static bool is_known_namespace(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static void hfsplus_init_header_node(struct inode *attr_file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) u32 clump_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) char *buf, u16 node_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct hfs_bnode_desc *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct hfs_btree_header_rec *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) u16 offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) __be16 *rec_offsets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) u32 hdr_node_map_rec_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) char *bmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) u32 used_nodes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) u32 used_bmp_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) u64 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) hfs_dbg(ATTR_MOD, "init_hdr_attr_file: clump %u, node_size %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) clump_size, node_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /* The end of the node contains list of record offsets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) rec_offsets = (__be16 *)(buf + node_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) desc = (struct hfs_bnode_desc *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) desc->type = HFS_NODE_HEADER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) desc->num_recs = cpu_to_be16(HFSPLUS_BTREE_HDR_NODE_RECS_COUNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) offset = sizeof(struct hfs_bnode_desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) *--rec_offsets = cpu_to_be16(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) head = (struct hfs_btree_header_rec *)(buf + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) head->node_size = cpu_to_be16(node_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) tmp = i_size_read(attr_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) do_div(tmp, node_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) head->node_count = cpu_to_be32(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) head->free_nodes = cpu_to_be32(be32_to_cpu(head->node_count) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) head->clump_size = cpu_to_be32(clump_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) head->attributes |= cpu_to_be32(HFS_TREE_BIGKEYS | HFS_TREE_VARIDXKEYS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) head->max_key_len = cpu_to_be16(HFSPLUS_ATTR_KEYLEN - sizeof(u16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) offset += sizeof(struct hfs_btree_header_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) *--rec_offsets = cpu_to_be16(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) offset += HFSPLUS_BTREE_HDR_USER_BYTES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) *--rec_offsets = cpu_to_be16(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) hdr_node_map_rec_bits = 8 * (node_size - offset - (4 * sizeof(u16)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (be32_to_cpu(head->node_count) > hdr_node_map_rec_bits) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) u32 map_node_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) u32 map_nodes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) desc->next = cpu_to_be32(be32_to_cpu(head->leaf_tail) + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) map_node_bits = 8 * (node_size - sizeof(struct hfs_bnode_desc) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) (2 * sizeof(u16)) - 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) map_nodes = (be32_to_cpu(head->node_count) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) hdr_node_map_rec_bits +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) (map_node_bits - 1)) / map_node_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) be32_add_cpu(&head->free_nodes, 0 - map_nodes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) bmp = buf + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) used_nodes =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) be32_to_cpu(head->node_count) - be32_to_cpu(head->free_nodes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) used_bmp_bytes = used_nodes / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (used_bmp_bytes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) memset(bmp, 0xFF, used_bmp_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) bmp += used_bmp_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) used_nodes %= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) *bmp = ~(0xFF >> used_nodes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) offset += hdr_node_map_rec_bits / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) *--rec_offsets = cpu_to_be16(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static int hfsplus_create_attributes_file(struct super_block *sb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct inode *attr_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct hfsplus_inode_info *hip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) u32 clump_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) u16 node_size = HFSPLUS_ATTR_TREE_NODE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) int index, written;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct address_space *mapping;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) int old_state = HFSPLUS_EMPTY_ATTR_TREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) hfs_dbg(ATTR_MOD, "create_attr_file: ino %d\n", HFSPLUS_ATTR_CNID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) check_attr_tree_state_again:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) switch (atomic_read(&sbi->attr_tree_state)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) case HFSPLUS_EMPTY_ATTR_TREE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (old_state != atomic_cmpxchg(&sbi->attr_tree_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) old_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) HFSPLUS_CREATING_ATTR_TREE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) goto check_attr_tree_state_again;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) case HFSPLUS_CREATING_ATTR_TREE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * This state means that another thread is in process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * of AttributesFile creation. Theoretically, it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * possible to be here. But really __setxattr() method
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * first of all calls hfs_find_init() for lookup in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * B-tree of CatalogFile. This method locks mutex of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * CatalogFile's B-tree. As a result, if some thread
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * is inside AttributedFile creation operation then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * another threads will be waiting unlocking of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * CatalogFile's B-tree's mutex. However, if code will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * change then we will return error code (-EAGAIN) from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * here. Really, it means that first try to set of xattr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * fails with error but second attempt will have success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) case HFSPLUS_VALID_ATTR_TREE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) case HFSPLUS_FAILED_ATTR_TREE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) attr_file = hfsplus_iget(sb, HFSPLUS_ATTR_CNID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (IS_ERR(attr_file)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) pr_err("failed to load attributes file\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return PTR_ERR(attr_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) BUG_ON(i_size_read(attr_file) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) hip = HFSPLUS_I(attr_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) clump_size = hfsplus_calc_btree_clump_size(sb->s_blocksize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) node_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) sbi->sect_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) HFSPLUS_ATTR_CNID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) mutex_lock(&hip->extents_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) hip->clump_blocks = clump_size >> sbi->alloc_blksz_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) mutex_unlock(&hip->extents_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (sbi->free_blocks <= (hip->clump_blocks << 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) err = -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) goto end_attr_file_creation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) while (hip->alloc_blocks < hip->clump_blocks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) err = hfsplus_file_extend(attr_file, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (unlikely(err)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) pr_err("failed to extend attributes file\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) goto end_attr_file_creation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) hip->phys_size = attr_file->i_size =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) (loff_t)hip->alloc_blocks << sbi->alloc_blksz_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) hip->fs_blocks = hip->alloc_blocks << sbi->fs_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) inode_set_bytes(attr_file, attr_file->i_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) buf = kzalloc(node_size, GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (!buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) pr_err("failed to allocate memory for header node\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) goto end_attr_file_creation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) hfsplus_init_header_node(attr_file, clump_size, buf, node_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) mapping = attr_file->i_mapping;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) written = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) for (; written < node_size; index++, written += PAGE_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) void *kaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) page = read_mapping_page(mapping, index, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (IS_ERR(page)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) err = PTR_ERR(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) goto failed_header_node_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) kaddr = kmap_atomic(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) memcpy(kaddr, buf + written,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) min_t(size_t, PAGE_SIZE, node_size - written));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) kunmap_atomic(kaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) set_page_dirty(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) put_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) hfsplus_mark_inode_dirty(attr_file, HFSPLUS_I_ATTR_DIRTY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) sbi->attr_tree = hfs_btree_open(sb, HFSPLUS_ATTR_CNID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (!sbi->attr_tree)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) pr_err("failed to load attributes file\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) failed_header_node_init:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) end_attr_file_creation:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) iput(attr_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) atomic_set(&sbi->attr_tree_state, HFSPLUS_VALID_ATTR_TREE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) else if (err == -ENOSPC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) atomic_set(&sbi->attr_tree_state, HFSPLUS_EMPTY_ATTR_TREE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) atomic_set(&sbi->attr_tree_state, HFSPLUS_FAILED_ATTR_TREE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) int __hfsplus_setxattr(struct inode *inode, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) const void *value, size_t size, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) struct hfs_find_data cat_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) hfsplus_cat_entry entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) u16 cat_entry_flags, cat_entry_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) u16 folder_finderinfo_len = sizeof(struct DInfo) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) sizeof(struct DXInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) u16 file_finderinfo_len = sizeof(struct FInfo) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) sizeof(struct FXInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if ((!S_ISREG(inode->i_mode) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) !S_ISDIR(inode->i_mode)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) HFSPLUS_IS_RSRC(inode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (value == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return hfsplus_removexattr(inode, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) err = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &cat_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) pr_err("can't init xattr find struct\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) err = hfsplus_find_cat(inode->i_sb, inode->i_ino, &cat_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) pr_err("catalog searching failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) goto end_setxattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (!strcmp_xattr_finder_info(name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (flags & XATTR_CREATE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) pr_err("xattr exists yet\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) err = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) goto end_setxattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) hfs_bnode_read(cat_fd.bnode, &entry, cat_fd.entryoffset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) sizeof(hfsplus_cat_entry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (be16_to_cpu(entry.type) == HFSPLUS_FOLDER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (size == folder_finderinfo_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) memcpy(&entry.folder.user_info, value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) folder_finderinfo_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) hfs_bnode_write(cat_fd.bnode, &entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) cat_fd.entryoffset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) sizeof(struct hfsplus_cat_folder));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) hfsplus_mark_inode_dirty(inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) HFSPLUS_I_CAT_DIRTY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) err = -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) goto end_setxattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) } else if (be16_to_cpu(entry.type) == HFSPLUS_FILE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (size == file_finderinfo_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) memcpy(&entry.file.user_info, value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) file_finderinfo_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) hfs_bnode_write(cat_fd.bnode, &entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) cat_fd.entryoffset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) sizeof(struct hfsplus_cat_file));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) hfsplus_mark_inode_dirty(inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) HFSPLUS_I_CAT_DIRTY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) err = -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) goto end_setxattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) err = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) goto end_setxattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) goto end_setxattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (!HFSPLUS_SB(inode->i_sb)->attr_tree) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) err = hfsplus_create_attributes_file(inode->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (unlikely(err))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) goto end_setxattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (hfsplus_attr_exists(inode, name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (flags & XATTR_CREATE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) pr_err("xattr exists yet\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) err = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) goto end_setxattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) err = hfsplus_delete_attr(inode, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) goto end_setxattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) err = hfsplus_create_attr(inode, name, value, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) goto end_setxattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (flags & XATTR_REPLACE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) pr_err("cannot replace xattr\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) err = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) goto end_setxattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) err = hfsplus_create_attr(inode, name, value, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) goto end_setxattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) cat_entry_type = hfs_bnode_read_u16(cat_fd.bnode, cat_fd.entryoffset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (cat_entry_type == HFSPLUS_FOLDER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) cat_entry_flags = hfs_bnode_read_u16(cat_fd.bnode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) cat_fd.entryoffset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) offsetof(struct hfsplus_cat_folder, flags));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) cat_entry_flags |= HFSPLUS_XATTR_EXISTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (!strcmp_xattr_acl(name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) cat_entry_flags |= HFSPLUS_ACL_EXISTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) hfs_bnode_write_u16(cat_fd.bnode, cat_fd.entryoffset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) offsetof(struct hfsplus_cat_folder, flags),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) cat_entry_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) hfsplus_mark_inode_dirty(inode, HFSPLUS_I_CAT_DIRTY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) } else if (cat_entry_type == HFSPLUS_FILE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) cat_entry_flags = hfs_bnode_read_u16(cat_fd.bnode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) cat_fd.entryoffset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) offsetof(struct hfsplus_cat_file, flags));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) cat_entry_flags |= HFSPLUS_XATTR_EXISTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (!strcmp_xattr_acl(name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) cat_entry_flags |= HFSPLUS_ACL_EXISTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) hfs_bnode_write_u16(cat_fd.bnode, cat_fd.entryoffset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) offsetof(struct hfsplus_cat_file, flags),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) cat_entry_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) hfsplus_mark_inode_dirty(inode, HFSPLUS_I_CAT_DIRTY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) pr_err("invalid catalog entry type\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) goto end_setxattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) end_setxattr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) hfs_find_exit(&cat_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) static int name_len(const char *xattr_name, int xattr_name_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) int len = xattr_name_len + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (!is_known_namespace(xattr_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) len += XATTR_MAC_OSX_PREFIX_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) static int copy_name(char *buffer, const char *xattr_name, int name_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) int len = name_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) int offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (!is_known_namespace(xattr_name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) memcpy(buffer, XATTR_MAC_OSX_PREFIX, XATTR_MAC_OSX_PREFIX_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) offset += XATTR_MAC_OSX_PREFIX_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) len += XATTR_MAC_OSX_PREFIX_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) strncpy(buffer + offset, xattr_name, name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) memset(buffer + offset + name_len, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) len += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) int hfsplus_setxattr(struct inode *inode, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) const void *value, size_t size, int flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) const char *prefix, size_t prefixlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) char *xattr_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (!xattr_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) strcpy(xattr_name, prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) strcpy(xattr_name + prefixlen, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) res = __hfsplus_setxattr(inode, xattr_name, value, size, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) kfree(xattr_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) static ssize_t hfsplus_getxattr_finder_info(struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) void *value, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) ssize_t res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) struct hfs_find_data fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) u16 entry_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) u16 folder_rec_len = sizeof(struct DInfo) + sizeof(struct DXInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) u16 file_rec_len = sizeof(struct FInfo) + sizeof(struct FXInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) u16 record_len = max(folder_rec_len, file_rec_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) u8 folder_finder_info[sizeof(struct DInfo) + sizeof(struct DXInfo)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) u8 file_finder_info[sizeof(struct FInfo) + sizeof(struct FXInfo)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (size >= record_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) pr_err("can't init xattr find struct\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) goto end_getxattr_finder_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) entry_type = hfs_bnode_read_u16(fd.bnode, fd.entryoffset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (entry_type == HFSPLUS_FOLDER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) hfs_bnode_read(fd.bnode, folder_finder_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) fd.entryoffset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) offsetof(struct hfsplus_cat_folder, user_info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) folder_rec_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) memcpy(value, folder_finder_info, folder_rec_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) res = folder_rec_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) } else if (entry_type == HFSPLUS_FILE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) hfs_bnode_read(fd.bnode, file_finder_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) fd.entryoffset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) offsetof(struct hfsplus_cat_file, user_info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) file_rec_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) memcpy(value, file_finder_info, file_rec_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) res = file_rec_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) res = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) goto end_getxattr_finder_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) res = size ? -ERANGE : record_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) end_getxattr_finder_info:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if (size >= record_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) hfs_find_exit(&fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) ssize_t __hfsplus_getxattr(struct inode *inode, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) void *value, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) struct hfs_find_data fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) hfsplus_attr_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) __be32 xattr_record_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) u32 record_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) u16 record_length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) ssize_t res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if ((!S_ISREG(inode->i_mode) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) !S_ISDIR(inode->i_mode)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) HFSPLUS_IS_RSRC(inode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (!strcmp_xattr_finder_info(name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) return hfsplus_getxattr_finder_info(inode, value, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (!HFSPLUS_SB(inode->i_sb)->attr_tree)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) entry = hfsplus_alloc_attr_entry();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (!entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) pr_err("can't allocate xattr entry\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->attr_tree, &fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) pr_err("can't init xattr find struct\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) goto failed_getxattr_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) res = hfsplus_find_attr(inode->i_sb, inode->i_ino, name, &fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (res == -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) res = -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) pr_err("xattr searching failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) hfs_bnode_read(fd.bnode, &xattr_record_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) fd.entryoffset, sizeof(xattr_record_type));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) record_type = be32_to_cpu(xattr_record_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (record_type == HFSPLUS_ATTR_INLINE_DATA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) record_length = hfs_bnode_read_u16(fd.bnode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) fd.entryoffset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) offsetof(struct hfsplus_attr_inline_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) length));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (record_length > HFSPLUS_MAX_INLINE_DATA_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) pr_err("invalid xattr record size\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) res = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) } else if (record_type == HFSPLUS_ATTR_FORK_DATA ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) record_type == HFSPLUS_ATTR_EXTENTS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) pr_err("only inline data xattr are supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) res = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) pr_err("invalid xattr record\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) res = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) hfs_bnode_read(fd.bnode, entry, fd.entryoffset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) offsetof(struct hfsplus_attr_inline_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) raw_bytes) + record_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (size >= record_length) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) memcpy(value, entry->inline_data.raw_bytes, record_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) res = record_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) res = size ? -ERANGE : record_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) hfs_find_exit(&fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) failed_getxattr_init:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) hfsplus_destroy_attr_entry(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) ssize_t hfsplus_getxattr(struct inode *inode, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) void *value, size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) const char *prefix, size_t prefixlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) char *xattr_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (!xattr_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) strcpy(xattr_name, prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) strcpy(xattr_name + prefixlen, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) res = __hfsplus_getxattr(inode, xattr_name, value, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) kfree(xattr_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) static inline int can_list(const char *xattr_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (!xattr_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return strncmp(xattr_name, XATTR_TRUSTED_PREFIX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) XATTR_TRUSTED_PREFIX_LEN) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) capable(CAP_SYS_ADMIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) static ssize_t hfsplus_listxattr_finder_info(struct dentry *dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) char *buffer, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) ssize_t res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) struct inode *inode = d_inode(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) struct hfs_find_data fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) u16 entry_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) u8 folder_finder_info[sizeof(struct DInfo) + sizeof(struct DXInfo)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) u8 file_finder_info[sizeof(struct FInfo) + sizeof(struct FXInfo)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) unsigned long len, found_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) int xattr_name_len, symbols_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) pr_err("can't init xattr find struct\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) goto end_listxattr_finder_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) entry_type = hfs_bnode_read_u16(fd.bnode, fd.entryoffset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (entry_type == HFSPLUS_FOLDER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) len = sizeof(struct DInfo) + sizeof(struct DXInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) hfs_bnode_read(fd.bnode, folder_finder_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) fd.entryoffset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) offsetof(struct hfsplus_cat_folder, user_info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) found_bit = find_first_bit((void *)folder_finder_info, len*8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) } else if (entry_type == HFSPLUS_FILE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) len = sizeof(struct FInfo) + sizeof(struct FXInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) hfs_bnode_read(fd.bnode, file_finder_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) fd.entryoffset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) offsetof(struct hfsplus_cat_file, user_info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) found_bit = find_first_bit((void *)file_finder_info, len*8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) res = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) goto end_listxattr_finder_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) if (found_bit >= (len*8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) symbols_count = sizeof(HFSPLUS_XATTR_FINDER_INFO_NAME) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) xattr_name_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) name_len(HFSPLUS_XATTR_FINDER_INFO_NAME, symbols_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (!buffer || !size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) if (can_list(HFSPLUS_XATTR_FINDER_INFO_NAME))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) res = xattr_name_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) } else if (can_list(HFSPLUS_XATTR_FINDER_INFO_NAME)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (size < xattr_name_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) res = -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) res = copy_name(buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) HFSPLUS_XATTR_FINDER_INFO_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) symbols_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) end_listxattr_finder_info:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) hfs_find_exit(&fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) ssize_t err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) ssize_t res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) struct inode *inode = d_inode(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) struct hfs_find_data fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) u16 key_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) struct hfsplus_attr_key attr_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) char *strbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) int xattr_name_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if ((!S_ISREG(inode->i_mode) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) !S_ISDIR(inode->i_mode)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) HFSPLUS_IS_RSRC(inode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) res = hfsplus_listxattr_finder_info(dentry, buffer, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (res < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) else if (!HFSPLUS_SB(inode->i_sb)->attr_tree)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) return (res == 0) ? -EOPNOTSUPP : res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) err = hfs_find_init(HFSPLUS_SB(inode->i_sb)->attr_tree, &fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) pr_err("can't init xattr find struct\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) strbuf = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) XATTR_MAC_OSX_PREFIX_LEN + 1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (!strbuf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) res = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) err = hfsplus_find_attr(inode->i_sb, inode->i_ino, NULL, &fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if (err == -ENOENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (res == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) res = -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) goto end_listxattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) res = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) goto end_listxattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) key_len = hfs_bnode_read_u16(fd.bnode, fd.keyoffset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (key_len == 0 || key_len > fd.tree->max_key_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) pr_err("invalid xattr key length: %d\n", key_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) res = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) goto end_listxattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) hfs_bnode_read(fd.bnode, &attr_key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) fd.keyoffset, key_len + sizeof(key_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (be32_to_cpu(attr_key.cnid) != inode->i_ino)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) goto end_listxattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) xattr_name_len = NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (hfsplus_uni2asc(inode->i_sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) (const struct hfsplus_unistr *)&fd.key->attr.key_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) strbuf, &xattr_name_len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) pr_err("unicode conversion failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) res = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) goto end_listxattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) if (!buffer || !size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (can_list(strbuf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) res += name_len(strbuf, xattr_name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) } else if (can_list(strbuf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (size < (res + name_len(strbuf, xattr_name_len))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) res = -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) goto end_listxattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) res += copy_name(buffer + res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) strbuf, xattr_name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (hfs_brec_goto(&fd, 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) goto end_listxattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) end_listxattr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) kfree(strbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) hfs_find_exit(&fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) static int hfsplus_removexattr(struct inode *inode, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) struct hfs_find_data cat_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) u16 flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) u16 cat_entry_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) int is_xattr_acl_deleted = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) int is_all_xattrs_deleted = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (!HFSPLUS_SB(inode->i_sb)->attr_tree)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (!strcmp_xattr_finder_info(name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) err = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &cat_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) pr_err("can't init xattr find struct\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) err = hfsplus_find_cat(inode->i_sb, inode->i_ino, &cat_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) pr_err("catalog searching failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) goto end_removexattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) err = hfsplus_delete_attr(inode, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) goto end_removexattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) is_xattr_acl_deleted = !strcmp_xattr_acl(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) is_all_xattrs_deleted = !hfsplus_attr_exists(inode, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (!is_xattr_acl_deleted && !is_all_xattrs_deleted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) goto end_removexattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) cat_entry_type = hfs_bnode_read_u16(cat_fd.bnode, cat_fd.entryoffset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) if (cat_entry_type == HFSPLUS_FOLDER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) flags = hfs_bnode_read_u16(cat_fd.bnode, cat_fd.entryoffset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) offsetof(struct hfsplus_cat_folder, flags));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if (is_xattr_acl_deleted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) flags &= ~HFSPLUS_ACL_EXISTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) if (is_all_xattrs_deleted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) flags &= ~HFSPLUS_XATTR_EXISTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) hfs_bnode_write_u16(cat_fd.bnode, cat_fd.entryoffset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) offsetof(struct hfsplus_cat_folder, flags),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) hfsplus_mark_inode_dirty(inode, HFSPLUS_I_CAT_DIRTY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) } else if (cat_entry_type == HFSPLUS_FILE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) flags = hfs_bnode_read_u16(cat_fd.bnode, cat_fd.entryoffset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) offsetof(struct hfsplus_cat_file, flags));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) if (is_xattr_acl_deleted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) flags &= ~HFSPLUS_ACL_EXISTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if (is_all_xattrs_deleted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) flags &= ~HFSPLUS_XATTR_EXISTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) hfs_bnode_write_u16(cat_fd.bnode, cat_fd.entryoffset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) offsetof(struct hfsplus_cat_file, flags),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) hfsplus_mark_inode_dirty(inode, HFSPLUS_I_CAT_DIRTY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) pr_err("invalid catalog entry type\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) goto end_removexattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) end_removexattr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) hfs_find_exit(&cat_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) static int hfsplus_osx_getxattr(const struct xattr_handler *handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) struct dentry *unused, struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) const char *name, void *buffer, size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) * Don't allow retrieving properly prefixed attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) * by prepending them with "osx."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (is_known_namespace(name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) * osx is the namespace we use to indicate an unprefixed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) * attribute on the filesystem (like the ones that OS X
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) * creates), so we pass the name through unmodified (after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) * ensuring it doesn't conflict with another namespace).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return __hfsplus_getxattr(inode, name, buffer, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) static int hfsplus_osx_setxattr(const struct xattr_handler *handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) struct dentry *unused, struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) const char *name, const void *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) size_t size, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) * Don't allow setting properly prefixed attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) * by prepending them with "osx."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (is_known_namespace(name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) * osx is the namespace we use to indicate an unprefixed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) * attribute on the filesystem (like the ones that OS X
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) * creates), so we pass the name through unmodified (after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) * ensuring it doesn't conflict with another namespace).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) return __hfsplus_setxattr(inode, name, buffer, size, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) const struct xattr_handler hfsplus_xattr_osx_handler = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) .prefix = XATTR_MAC_OSX_PREFIX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) .get = hfsplus_osx_getxattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) .set = hfsplus_osx_setxattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) };