1 // SPDX-License-Identifier: GPL-2.0+
3 * BTRFS filesystem implementation for U-Boot
5 * 2017 Marek BehĂșn, CZ.NIC, kabel@kernel.org
11 static int verify_dir_item(struct btrfs_root
*root
,
12 struct extent_buffer
*leaf
,
13 struct btrfs_dir_item
*dir_item
)
15 u16 namelen
= BTRFS_NAME_LEN
;
16 u8 type
= btrfs_dir_type(leaf
, dir_item
);
18 if (type
== BTRFS_FT_XATTR
)
19 namelen
= XATTR_NAME_MAX
;
21 if (btrfs_dir_name_len(leaf
, dir_item
) > namelen
) {
22 fprintf(stderr
, "invalid dir item name len: %u\n",
23 (unsigned)btrfs_dir_data_len(leaf
, dir_item
));
27 /* BTRFS_MAX_XATTR_SIZE is the same for all dir items */
28 if ((btrfs_dir_data_len(leaf
, dir_item
) +
29 btrfs_dir_name_len(leaf
, dir_item
)) >
30 BTRFS_MAX_XATTR_SIZE(root
->fs_info
)) {
31 fprintf(stderr
, "invalid dir item name + data len: %u + %u\n",
32 (unsigned)btrfs_dir_name_len(leaf
, dir_item
),
33 (unsigned)btrfs_dir_data_len(leaf
, dir_item
));
40 struct btrfs_dir_item
*btrfs_match_dir_item_name(struct btrfs_root
*root
,
41 struct btrfs_path
*path
,
42 const char *name
, int name_len
)
44 struct btrfs_dir_item
*dir_item
;
45 unsigned long name_ptr
;
49 struct extent_buffer
*leaf
;
51 leaf
= path
->nodes
[0];
52 dir_item
= btrfs_item_ptr(leaf
, path
->slots
[0], struct btrfs_dir_item
);
53 total_len
= btrfs_item_size_nr(leaf
, path
->slots
[0]);
54 if (verify_dir_item(root
, leaf
, dir_item
))
57 while(cur
< total_len
) {
58 this_len
= sizeof(*dir_item
) +
59 btrfs_dir_name_len(leaf
, dir_item
) +
60 btrfs_dir_data_len(leaf
, dir_item
);
61 if (this_len
> (total_len
- cur
)) {
62 fprintf(stderr
, "invalid dir item size\n");
66 name_ptr
= (unsigned long)(dir_item
+ 1);
68 if (btrfs_dir_name_len(leaf
, dir_item
) == name_len
&&
69 memcmp_extent_buffer(leaf
, name
, name_ptr
, name_len
) == 0)
73 dir_item
= (struct btrfs_dir_item
*)((char *)dir_item
+
79 struct btrfs_dir_item
*btrfs_lookup_dir_item(struct btrfs_trans_handle
*trans
,
80 struct btrfs_root
*root
,
81 struct btrfs_path
*path
, u64 dir
,
82 const char *name
, int name_len
,
87 int ins_len
= mod
< 0 ? -1 : 0;
89 struct btrfs_key found_key
;
90 struct extent_buffer
*leaf
;
93 key
.type
= BTRFS_DIR_ITEM_KEY
;
95 key
.offset
= btrfs_name_hash(name
, name_len
);
97 ret
= btrfs_search_slot(trans
, root
, &key
, path
, ins_len
, cow
);
101 if (path
->slots
[0] == 0)
106 leaf
= path
->nodes
[0];
107 btrfs_item_key_to_cpu(leaf
, &found_key
, path
->slots
[0]);
109 if (found_key
.objectid
!= dir
||
110 found_key
.type
!= BTRFS_DIR_ITEM_KEY
||
111 found_key
.offset
!= key
.offset
)
114 return btrfs_match_dir_item_name(root
, path
, name
, name_len
);
117 int btrfs_iter_dir(struct btrfs_root
*root
, u64 ino
,
118 btrfs_iter_dir_callback_t callback
)
120 struct btrfs_path path
;
121 struct btrfs_key key
;
124 btrfs_init_path(&path
);
126 key
.type
= BTRFS_DIR_INDEX_KEY
;
129 ret
= btrfs_search_slot(NULL
, root
, &key
, &path
, 0, 0);
132 /* Should not happen */
137 if (path
.slots
[0] >= btrfs_header_nritems(path
.nodes
[0])) {
138 ret
= btrfs_next_leaf(root
, &path
);
147 struct btrfs_dir_item
*di
;
149 btrfs_item_key_to_cpu(path
.nodes
[0], &key
, path
.slots
[0]);
150 if (key
.objectid
!= ino
|| key
.type
!= BTRFS_DIR_INDEX_KEY
)
152 di
= btrfs_item_ptr(path
.nodes
[0], path
.slots
[0],
153 struct btrfs_dir_item
);
154 if (verify_dir_item(root
, path
.nodes
[0], di
)) {
158 ret
= callback(root
, path
.nodes
[0], di
);
161 } while (!(ret
= btrfs_next_item(root
, &path
)));
166 btrfs_release_path(&path
);