1 // SPDX-License-Identifier: GPL-2.0+
3 * BTRFS filesystem implementation for U-Boot
5 * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
11 #include <linux/time.h>
13 #include "crypto/hash.h"
16 struct btrfs_fs_info *current_fs_info;
18 static int show_dir(struct btrfs_root *root, struct extent_buffer *eb,
19 struct btrfs_dir_item *di)
21 struct btrfs_fs_info *fs_info = root->fs_info;
22 struct btrfs_inode_item ii;
24 static const char* dir_item_str[] = {
25 [BTRFS_FT_REG_FILE] = " ",
26 [BTRFS_FT_DIR] = "DIR",
27 [BTRFS_FT_CHRDEV] = "CHR",
28 [BTRFS_FT_BLKDEV] = "BLK",
29 [BTRFS_FT_FIFO] = "FIF",
30 [BTRFS_FT_SOCK] = "SCK",
31 [BTRFS_FT_SYMLINK] = "SYM",
33 u8 type = btrfs_dir_type(eb, di);
34 char namebuf[BTRFS_NAME_LEN];
40 /* skip XATTRs in directory listing */
41 if (type == BTRFS_FT_XATTR)
44 btrfs_dir_item_key_to_cpu(eb, di, &key);
46 if (key.type == BTRFS_ROOT_ITEM_KEY) {
47 struct btrfs_root *subvol;
49 /* It's a subvolume, get its mtime from root item */
50 subvol = btrfs_read_fs_root(fs_info, &key);
52 ret = PTR_ERR(subvol);
53 error("Can't find root %llu", key.objectid);
56 mtime = btrfs_stack_timespec_sec(&subvol->root_item.otime);
58 struct btrfs_path path;
60 /* It's regular inode, get its mtime from inode item */
61 btrfs_init_path(&path);
62 ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
66 error("Can't find inode %llu", key.objectid);
67 btrfs_release_path(&path);
70 read_extent_buffer(path.nodes[0], &ii,
71 btrfs_item_ptr_offset(path.nodes[0], path.slots[0]),
73 btrfs_release_path(&path);
74 mtime = btrfs_stack_timespec_sec(&ii.mtime);
76 ctime_r(&mtime, filetime);
78 if (type == BTRFS_FT_SYMLINK) {
79 target = malloc(fs_info->sectorsize);
81 error("Can't alloc memory for symlink %llu",
85 ret = btrfs_readlink(root, key.objectid, target);
87 error("Failed to read symlink %llu", key.objectid);
93 if (type < ARRAY_SIZE(dir_item_str) && dir_item_str[type])
94 printf("<%s> ", dir_item_str[type]);
96 printf("?%3u? ", type);
97 if (type == BTRFS_FT_CHRDEV || type == BTRFS_FT_BLKDEV) {
98 ASSERT(key.type == BTRFS_INODE_ITEM_KEY);
99 printf("%4llu,%5llu ", btrfs_stack_inode_rdev(&ii) >> 20,
100 btrfs_stack_inode_rdev(&ii) & 0xfffff);
102 if (key.type == BTRFS_INODE_ITEM_KEY)
103 printf("%10llu ", btrfs_stack_inode_size(&ii));
105 printf("%10llu ", 0ULL);
108 read_extent_buffer(eb, namebuf, (unsigned long)(di + 1),
109 btrfs_dir_name_len(eb, di));
110 printf("%24.24s %.*s", filetime, btrfs_dir_name_len(eb, di), namebuf);
111 if (type == BTRFS_FT_SYMLINK)
112 printf(" -> %s", target ? target : "?");
119 int btrfs_probe(struct blk_desc *fs_dev_desc,
120 struct disk_partition *fs_partition)
122 struct btrfs_fs_info *fs_info;
126 fs_info = open_ctree_fs_info(fs_dev_desc, fs_partition);
128 current_fs_info = fs_info;
134 int btrfs_ls(const char *path)
136 struct btrfs_fs_info *fs_info = current_fs_info;
137 struct btrfs_root *root = fs_info->fs_root;
138 u64 ino = BTRFS_FIRST_FREE_OBJECTID;
143 ret = btrfs_lookup_path(fs_info->fs_root, BTRFS_FIRST_FREE_OBJECTID,
144 path, &root, &ino, &type, 40);
146 printf("Cannot lookup path %s\n", path);
150 if (type != BTRFS_FT_DIR) {
151 error("Not a directory: %s", path);
154 ret = btrfs_iter_dir(root, ino, show_dir);
156 error("An error occurred while listing directory %s", path);
162 int btrfs_exists(const char *file)
164 struct btrfs_fs_info *fs_info = current_fs_info;
165 struct btrfs_root *root;
172 ret = btrfs_lookup_path(fs_info->fs_root, BTRFS_FIRST_FREE_OBJECTID,
173 file, &root, &ino, &type, 40);
177 if (type == BTRFS_FT_REG_FILE)
182 int btrfs_size(const char *file, loff_t *size)
184 struct btrfs_fs_info *fs_info = current_fs_info;
185 struct btrfs_inode_item *ii;
186 struct btrfs_root *root;
187 struct btrfs_path path;
188 struct btrfs_key key;
193 ret = btrfs_lookup_path(fs_info->fs_root, BTRFS_FIRST_FREE_OBJECTID,
194 file, &root, &ino, &type, 40);
196 printf("Cannot lookup file %s\n", file);
199 if (type != BTRFS_FT_REG_FILE) {
200 printf("Not a regular file: %s\n", file);
203 btrfs_init_path(&path);
205 key.type = BTRFS_INODE_ITEM_KEY;
208 ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
210 printf("Cannot lookup ino %llu\n", ino);
214 printf("Ino %llu does not exist\n", ino);
218 ii = btrfs_item_ptr(path.nodes[0], path.slots[0],
219 struct btrfs_inode_item);
220 *size = btrfs_inode_size(path.nodes[0], ii);
222 btrfs_release_path(&path);
226 int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len,
229 struct btrfs_fs_info *fs_info = current_fs_info;
230 struct btrfs_root *root;
231 loff_t real_size = 0;
237 ret = btrfs_lookup_path(fs_info->fs_root, BTRFS_FIRST_FREE_OBJECTID,
238 file, &root, &ino, &type, 40);
240 error("Cannot lookup file %s", file);
244 if (type != BTRFS_FT_REG_FILE) {
245 error("Not a regular file: %s", file);
250 ret = btrfs_size(file, &real_size);
252 error("Failed to get inode size: %s", file);
258 if (len > real_size - offset)
259 len = real_size - offset;
261 ret = btrfs_file_read(root, ino, offset, len, buf);
263 error("An error occurred while reading file %s", file);
271 void btrfs_close(void)
273 if (current_fs_info) {
274 close_ctree_fs_info(current_fs_info);
275 current_fs_info = NULL;
279 int btrfs_uuid(char *uuid_str)
281 #ifdef CONFIG_LIB_UUID
283 uuid_bin_to_str(current_fs_info->super_copy->fsid, uuid_str,
284 UUID_STR_FORMAT_STD);