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