xref: /openbmc/u-boot/fs/btrfs/dir-item.c (revision e8f80a5a)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
221a14facSMarek Behún /*
321a14facSMarek Behún  * BTRFS filesystem implementation for U-Boot
421a14facSMarek Behún  *
521a14facSMarek Behún  * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
621a14facSMarek Behún  */
721a14facSMarek Behún 
821a14facSMarek Behún #include "btrfs.h"
921a14facSMarek Behún 
verify_dir_item(struct btrfs_dir_item * item,u32 start,u32 total)1021a14facSMarek Behún static int verify_dir_item(struct btrfs_dir_item *item, u32 start, u32 total)
1121a14facSMarek Behún {
1221a14facSMarek Behún 	u16 max_len = BTRFS_NAME_LEN;
1321a14facSMarek Behún 	u32 end;
1421a14facSMarek Behún 
1521a14facSMarek Behún 	if (item->type >= BTRFS_FT_MAX) {
1621a14facSMarek Behún 		printf("%s: invalid dir item type: %i\n", __func__, item->type);
1721a14facSMarek Behún 		return 1;
1821a14facSMarek Behún 	}
1921a14facSMarek Behún 
2021a14facSMarek Behún 	if (item->type == BTRFS_FT_XATTR)
2121a14facSMarek Behún 		max_len = 255; /* XATTR_NAME_MAX */
2221a14facSMarek Behún 
2321a14facSMarek Behún 	end = start + sizeof(*item) + item->name_len;
2421a14facSMarek Behún 	if (item->name_len > max_len || end > total) {
2521a14facSMarek Behún 		printf("%s: invalid dir item name len: %u\n", __func__,
2621a14facSMarek Behún 		       item->name_len);
2721a14facSMarek Behún 		return 1;
2821a14facSMarek Behún 	}
2921a14facSMarek Behún 
3021a14facSMarek Behún 	return 0;
3121a14facSMarek Behún }
3221a14facSMarek Behún 
3321a14facSMarek Behún static struct btrfs_dir_item *
btrfs_match_dir_item_name(struct btrfs_path * path,const char * name,int name_len)3421a14facSMarek Behún btrfs_match_dir_item_name(struct btrfs_path *path, const char *name,
3521a14facSMarek Behún 			  int name_len)
3621a14facSMarek Behún {
3721a14facSMarek Behún 	struct btrfs_dir_item *item;
3821a14facSMarek Behún 	u32 total_len, cur = 0, this_len;
3921a14facSMarek Behún 	const char *name_ptr;
4021a14facSMarek Behún 
4121a14facSMarek Behún 	item = btrfs_path_item_ptr(path, struct btrfs_dir_item);
4221a14facSMarek Behún 
4321a14facSMarek Behún 	total_len = btrfs_path_item_size(path);
4421a14facSMarek Behún 
4521a14facSMarek Behún 	while (cur < total_len) {
4621a14facSMarek Behún 		btrfs_dir_item_to_cpu(item);
4721a14facSMarek Behún 		this_len = sizeof(*item) + item->name_len + item->data_len;
4821a14facSMarek Behún 		name_ptr = (const char *) (item + 1);
4921a14facSMarek Behún 
5021a14facSMarek Behún 		if (verify_dir_item(item, cur, total_len))
5121a14facSMarek Behún 			return NULL;
5221a14facSMarek Behún 		if (item->name_len == name_len && !memcmp(name_ptr, name,
5321a14facSMarek Behún 							  name_len))
5421a14facSMarek Behún 			return item;
5521a14facSMarek Behún 
5621a14facSMarek Behún 		cur += this_len;
5721a14facSMarek Behún 		item = (struct btrfs_dir_item *) ((u8 *) item + this_len);
5821a14facSMarek Behún 	}
5921a14facSMarek Behún 
6021a14facSMarek Behún 	return NULL;
6121a14facSMarek Behún }
6221a14facSMarek Behún 
btrfs_lookup_dir_item(const struct btrfs_root * root,u64 dir,const char * name,int name_len,struct btrfs_dir_item * item)6321a14facSMarek Behún int btrfs_lookup_dir_item(const struct btrfs_root *root, u64 dir,
6421a14facSMarek Behún 			  const char *name, int name_len,
6521a14facSMarek Behún 			  struct btrfs_dir_item *item)
6621a14facSMarek Behún {
6721a14facSMarek Behún 	struct btrfs_path path;
6821a14facSMarek Behún 	struct btrfs_key key;
6921a14facSMarek Behún 	struct btrfs_dir_item *res = NULL;
7021a14facSMarek Behún 
7121a14facSMarek Behún 	key.objectid = dir;
7221a14facSMarek Behún 	key.type = BTRFS_DIR_ITEM_KEY;
7321a14facSMarek Behún 	key.offset = btrfs_name_hash(name, name_len);
7421a14facSMarek Behún 
7521a14facSMarek Behún 	if (btrfs_search_tree(root, &key, &path))
7621a14facSMarek Behún 		return -1;
7721a14facSMarek Behún 
7821a14facSMarek Behún 	if (btrfs_comp_keys_type(&key, btrfs_path_leaf_key(&path)))
7921a14facSMarek Behún 		goto out;
8021a14facSMarek Behún 
8121a14facSMarek Behún 	res = btrfs_match_dir_item_name(&path, name, name_len);
8221a14facSMarek Behún 	if (res)
8321a14facSMarek Behún 		*item = *res;
8421a14facSMarek Behún out:
8521a14facSMarek Behún 	btrfs_free_path(&path);
8621a14facSMarek Behún 	return res ? 0 : -1;
8721a14facSMarek Behún }
8821a14facSMarek Behún 
btrfs_readdir(const struct btrfs_root * root,u64 dir,btrfs_readdir_callback_t callback)8921a14facSMarek Behún int btrfs_readdir(const struct btrfs_root *root, u64 dir,
9021a14facSMarek Behún 		  btrfs_readdir_callback_t callback)
9121a14facSMarek Behún {
9221a14facSMarek Behún 	struct btrfs_path path;
9321a14facSMarek Behún 	struct btrfs_key key, *found_key;
9421a14facSMarek Behún 	struct btrfs_dir_item *item;
95ecab881cSMarek Behún 	int res = 0;
9621a14facSMarek Behún 
9721a14facSMarek Behún 	key.objectid = dir;
9821a14facSMarek Behún 	key.type = BTRFS_DIR_INDEX_KEY;
9921a14facSMarek Behún 	key.offset = 0;
10021a14facSMarek Behún 
10121a14facSMarek Behún 	if (btrfs_search_tree(root, &key, &path))
10221a14facSMarek Behún 		return -1;
10321a14facSMarek Behún 
10421a14facSMarek Behún 	do {
10521a14facSMarek Behún 		found_key = btrfs_path_leaf_key(&path);
10621a14facSMarek Behún 		if (btrfs_comp_keys_type(&key, found_key))
10721a14facSMarek Behún 			break;
10821a14facSMarek Behún 
10921a14facSMarek Behún 		item = btrfs_path_item_ptr(&path, struct btrfs_dir_item);
11021a14facSMarek Behún 		btrfs_dir_item_to_cpu(item);
11121a14facSMarek Behún 
11221a14facSMarek Behún 		if (verify_dir_item(item, 0, sizeof(*item) + item->name_len))
11321a14facSMarek Behún 			continue;
11421a14facSMarek Behún 		if (item->type == BTRFS_FT_XATTR)
11521a14facSMarek Behún 			continue;
11621a14facSMarek Behún 
11721a14facSMarek Behún 		if (callback(root, item))
11821a14facSMarek Behún 			break;
11921a14facSMarek Behún 	} while (!(res = btrfs_next_slot(&path)));
12021a14facSMarek Behún 
12121a14facSMarek Behún 	btrfs_free_path(&path);
12221a14facSMarek Behún 
12321a14facSMarek Behún 	return res < 0 ? -1 : 0;
12421a14facSMarek Behún }
125