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 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 * 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 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 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