]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
21a14fac MB |
2 | /* |
3 | * BTRFS filesystem implementation for U-Boot | |
4 | * | |
5 | * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz | |
21a14fac MB |
6 | */ |
7 | ||
8 | #include "btrfs.h" | |
565a4147 | 9 | #include "disk-io.h" |
21a14fac | 10 | |
cafffc50 | 11 | static int __verify_dir_item(struct btrfs_dir_item *item, u32 start, u32 total) |
21a14fac MB |
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 * | |
cafffc50 | 35 | __btrfs_match_dir_item_name(struct __btrfs_path *path, const char *name, |
21a14fac MB |
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 | ||
cafffc50 | 51 | if (__verify_dir_item(item, cur, total_len)) |
21a14fac MB |
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 | ||
cafffc50 | 64 | int __btrfs_lookup_dir_item(const struct __btrfs_root *root, u64 dir, |
21a14fac MB |
65 | const char *name, int name_len, |
66 | struct btrfs_dir_item *item) | |
67 | { | |
33966de3 | 68 | struct __btrfs_path path; |
21a14fac MB |
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 | ||
cafffc50 | 82 | res = __btrfs_match_dir_item_name(&path, name, name_len); |
21a14fac MB |
83 | if (res) |
84 | *item = *res; | |
85 | out: | |
33966de3 | 86 | __btrfs_free_path(&path); |
21a14fac MB |
87 | return res ? 0 : -1; |
88 | } | |
89 | ||
207011b8 | 90 | int btrfs_readdir(const struct __btrfs_root *root, u64 dir, |
21a14fac MB |
91 | btrfs_readdir_callback_t callback) |
92 | { | |
33966de3 | 93 | struct __btrfs_path path; |
21a14fac MB |
94 | struct btrfs_key key, *found_key; |
95 | struct btrfs_dir_item *item; | |
ecab881c | 96 | int res = 0; |
21a14fac MB |
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 | ||
cafffc50 | 113 | if (__verify_dir_item(item, 0, sizeof(*item) + item->name_len)) |
21a14fac MB |
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 | ||
33966de3 | 122 | __btrfs_free_path(&path); |
21a14fac MB |
123 | |
124 | return res < 0 ? -1 : 0; | |
125 | } |