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