1 /* 2 * BTRFS filesystem implementation for U-Boot 3 * 4 * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #include "btrfs.h" 10 11 static int verify_dir_item(struct btrfs_dir_item *item, u32 start, u32 total) 12 { 13 u16 max_len = BTRFS_NAME_LEN; 14 u32 end; 15 16 if (item->type >= BTRFS_FT_MAX) { 17 printf("%s: invalid dir item type: %i\n", __func__, item->type); 18 return 1; 19 } 20 21 if (item->type == BTRFS_FT_XATTR) 22 max_len = 255; /* XATTR_NAME_MAX */ 23 24 end = start + sizeof(*item) + item->name_len; 25 if (item->name_len > max_len || end > total) { 26 printf("%s: invalid dir item name len: %u\n", __func__, 27 item->name_len); 28 return 1; 29 } 30 31 return 0; 32 } 33 34 static struct btrfs_dir_item * 35 btrfs_match_dir_item_name(struct btrfs_path *path, const char *name, 36 int name_len) 37 { 38 struct btrfs_dir_item *item; 39 u32 total_len, cur = 0, this_len; 40 const char *name_ptr; 41 42 item = btrfs_path_item_ptr(path, struct btrfs_dir_item); 43 44 total_len = btrfs_path_item_size(path); 45 46 while (cur < total_len) { 47 btrfs_dir_item_to_cpu(item); 48 this_len = sizeof(*item) + item->name_len + item->data_len; 49 name_ptr = (const char *) (item + 1); 50 51 if (verify_dir_item(item, cur, total_len)) 52 return NULL; 53 if (item->name_len == name_len && !memcmp(name_ptr, name, 54 name_len)) 55 return item; 56 57 cur += this_len; 58 item = (struct btrfs_dir_item *) ((u8 *) item + this_len); 59 } 60 61 return NULL; 62 } 63 64 int btrfs_lookup_dir_item(const struct btrfs_root *root, u64 dir, 65 const char *name, int name_len, 66 struct btrfs_dir_item *item) 67 { 68 struct btrfs_path path; 69 struct btrfs_key key; 70 struct btrfs_dir_item *res = NULL; 71 72 key.objectid = dir; 73 key.type = BTRFS_DIR_ITEM_KEY; 74 key.offset = btrfs_name_hash(name, name_len); 75 76 if (btrfs_search_tree(root, &key, &path)) 77 return -1; 78 79 if (btrfs_comp_keys_type(&key, btrfs_path_leaf_key(&path))) 80 goto out; 81 82 res = btrfs_match_dir_item_name(&path, name, name_len); 83 if (res) 84 *item = *res; 85 out: 86 btrfs_free_path(&path); 87 return res ? 0 : -1; 88 } 89 90 int btrfs_readdir(const struct btrfs_root *root, u64 dir, 91 btrfs_readdir_callback_t callback) 92 { 93 struct btrfs_path path; 94 struct btrfs_key key, *found_key; 95 struct btrfs_dir_item *item; 96 int res = 0; 97 98 key.objectid = dir; 99 key.type = BTRFS_DIR_INDEX_KEY; 100 key.offset = 0; 101 102 if (btrfs_search_tree(root, &key, &path)) 103 return -1; 104 105 do { 106 found_key = btrfs_path_leaf_key(&path); 107 if (btrfs_comp_keys_type(&key, found_key)) 108 break; 109 110 item = btrfs_path_item_ptr(&path, struct btrfs_dir_item); 111 btrfs_dir_item_to_cpu(item); 112 113 if (verify_dir_item(item, 0, sizeof(*item) + item->name_len)) 114 continue; 115 if (item->type == BTRFS_FT_XATTR) 116 continue; 117 118 if (callback(root, item)) 119 break; 120 } while (!(res = btrfs_next_slot(&path))); 121 122 btrfs_free_path(&path); 123 124 return res < 0 ? -1 : 0; 125 } 126