Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 099e9245 authored by Vyacheslav Dubeyko's avatar Vyacheslav Dubeyko Committed by Linus Torvalds
Browse files

hfsplus: implement attributes file's header node initialization code



Implement functionality of AttributesFile's header node initialization.

Signed-off-by: default avatarVyacheslav Dubeyko <slava@dubeyko.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Hin-Tak Leung <htl10@users.sourceforge.net>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent b3b5b0f0
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -187,6 +187,9 @@ struct hfs_btree_header_rec {
/* HFS+ BTree misc info */
#define HFSPLUS_TREE_HEAD 0
#define HFSPLUS_NODE_MXSZ 32768
#define HFSPLUS_ATTR_TREE_NODE_SIZE		8192
#define HFSPLUS_BTREE_HDR_NODE_RECS_COUNT	3
#define HFSPLUS_BTREE_HDR_USER_BYTES		128

/* Some special File ID numbers (stolen from hfs.h) */
#define HFSPLUS_POR_CNID		1	/* Parent Of the Root */
+65 −0
Original line number Diff line number Diff line
@@ -127,6 +127,71 @@ static int can_set_xattr(struct inode *inode, const char *name,
	return 0;
}

static void hfsplus_init_header_node(struct inode *attr_file,
					u32 clump_size,
					char *buf, size_t node_size)
{
	struct hfs_bnode_desc *desc;
	struct hfs_btree_header_rec *head;
	u16 offset;
	__be16 *rec_offsets;
	u32 hdr_node_map_rec_bits;
	char *bmp;
	u32 used_nodes;
	u32 used_bmp_bytes;

	hfs_dbg(ATTR_MOD, "init_hdr_attr_file: clump %u, node_size %zu\n",
				clump_size, node_size);

	/* The end of the node contains list of record offsets */
	rec_offsets = (__be16 *)(buf + node_size);

	desc = (struct hfs_bnode_desc *)buf;
	desc->type = HFS_NODE_HEADER;
	desc->num_recs = cpu_to_be16(HFSPLUS_BTREE_HDR_NODE_RECS_COUNT);
	offset = sizeof(struct hfs_bnode_desc);
	*--rec_offsets = cpu_to_be16(offset);

	head = (struct hfs_btree_header_rec *)(buf + offset);
	head->node_size = cpu_to_be16(node_size);
	head->node_count = cpu_to_be32(i_size_read(attr_file) / node_size);
	head->free_nodes = cpu_to_be32(be32_to_cpu(head->node_count) - 1);
	head->clump_size = cpu_to_be32(clump_size);
	head->attributes |= cpu_to_be32(HFS_TREE_BIGKEYS | HFS_TREE_VARIDXKEYS);
	head->max_key_len = cpu_to_be16(HFSPLUS_ATTR_KEYLEN - sizeof(u16));
	offset += sizeof(struct hfs_btree_header_rec);
	*--rec_offsets = cpu_to_be16(offset);
	offset += HFSPLUS_BTREE_HDR_USER_BYTES;
	*--rec_offsets = cpu_to_be16(offset);

	hdr_node_map_rec_bits = 8 * (node_size - offset - (4 * sizeof(u16)));
	if (be32_to_cpu(head->node_count) > hdr_node_map_rec_bits) {
		u32 map_node_bits;
		u32 map_nodes;

		desc->next = cpu_to_be32(be32_to_cpu(head->leaf_tail) + 1);
		map_node_bits = 8 * (node_size - sizeof(struct hfs_bnode_desc) -
					(2 * sizeof(u16)) - 2);
		map_nodes = (be32_to_cpu(head->node_count) -
				hdr_node_map_rec_bits +
				(map_node_bits - 1)) / map_node_bits;
		be32_add_cpu(&head->free_nodes, 0 - map_nodes);
	}

	bmp = buf + offset;
	used_nodes =
		be32_to_cpu(head->node_count) - be32_to_cpu(head->free_nodes);
	used_bmp_bytes = used_nodes / 8;
	if (used_bmp_bytes) {
		memset(bmp, 0xFF, used_bmp_bytes);
		bmp += used_bmp_bytes;
		used_nodes %= 8;
	}
	*bmp = ~(0xFF >> used_nodes);
	offset += hdr_node_map_rec_bits / 8;
	*--rec_offsets = cpu_to_be16(offset);
}

int __hfsplus_setxattr(struct inode *inode, const char *name,
			const void *value, size_t size, int flags)
{