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 struct btrfs_info btrfs_info;
15 static int readdir_callback(const struct btrfs_root *root,
16 struct btrfs_dir_item *item)
18 static const char typestr[BTRFS_FT_MAX][4] = {
19 [BTRFS_FT_UNKNOWN] = " ? ",
20 [BTRFS_FT_REG_FILE] = " ",
21 [BTRFS_FT_DIR] = "DIR",
22 [BTRFS_FT_CHRDEV] = "CHR",
23 [BTRFS_FT_BLKDEV] = "BLK",
24 [BTRFS_FT_FIFO] = "FIF",
25 [BTRFS_FT_SOCK] = "SCK",
26 [BTRFS_FT_SYMLINK] = "SYM",
27 [BTRFS_FT_XATTR] = " ? ",
29 struct btrfs_inode_item inode;
30 const char *name = (const char *) (item + 1);
31 char filetime[32], *target = NULL;
34 if (btrfs_lookup_inode(root, &item->location, &inode, NULL)) {
35 printf("%s: Cannot find inode item for directory entry %.*s!\n",
36 __func__, item->name_len, name);
40 mtime = inode.mtime.sec;
41 ctime_r(&mtime, filetime);
43 if (item->type == BTRFS_FT_SYMLINK) {
44 target = malloc(min(inode.size + 1,
45 (u64) btrfs_info.sb.sectorsize));
47 if (target && btrfs_readlink(root, item->location.objectid,
54 printf("%s: Cannot read symlink target!\n", __func__);
57 printf("<%s> ", typestr[item->type]);
58 if (item->type == BTRFS_FT_CHRDEV || item->type == BTRFS_FT_BLKDEV)
59 printf("%4u,%5u ", (unsigned int) (inode.rdev >> 20),
60 (unsigned int) (inode.rdev & 0xfffff));
62 printf("%10llu ", inode.size);
64 printf("%24.24s %.*s", filetime, item->name_len, name);
66 if (item->type == BTRFS_FT_SYMLINK) {
67 printf(" -> %s", target ? target : "?");
77 int btrfs_probe(struct blk_desc *fs_dev_desc, disk_partition_t *fs_partition)
79 btrfs_blk_desc = fs_dev_desc;
80 btrfs_part_info = fs_partition;
82 memset(&btrfs_info, 0, sizeof(btrfs_info));
85 if (btrfs_read_superblock())
88 if (btrfs_chunk_map_init()) {
89 printf("%s: failed to init chunk map\n", __func__);
93 btrfs_info.tree_root.objectid = 0;
94 btrfs_info.tree_root.bytenr = btrfs_info.sb.root;
95 btrfs_info.chunk_root.objectid = 0;
96 btrfs_info.chunk_root.bytenr = btrfs_info.sb.chunk_root;
98 if (btrfs_read_chunk_tree()) {
99 printf("%s: failed to read chunk tree\n", __func__);
103 if (btrfs_find_root(btrfs_get_default_subvol_objectid(),
104 &btrfs_info.fs_root, NULL)) {
105 printf("%s: failed to find default subvolume\n", __func__);
112 int btrfs_ls(const char *path)
114 struct btrfs_root root = btrfs_info.fs_root;
118 inr = btrfs_lookup_path(&root, root.root_dirid, path, &type, NULL, 40);
121 printf("Cannot lookup path %s\n", path);
125 if (type != BTRFS_FT_DIR) {
126 printf("Not a directory: %s\n", path);
130 if (btrfs_readdir(&root, inr, readdir_callback)) {
131 printf("An error occured while listing directory %s\n", path);
138 int btrfs_exists(const char *file)
140 struct btrfs_root root = btrfs_info.fs_root;
144 inr = btrfs_lookup_path(&root, root.root_dirid, file, &type, NULL, 40);
146 return (inr != -1ULL && type == BTRFS_FT_REG_FILE);
149 int btrfs_size(const char *file, loff_t *size)
151 struct btrfs_root root = btrfs_info.fs_root;
152 struct btrfs_inode_item inode;
156 inr = btrfs_lookup_path(&root, root.root_dirid, file, &type, &inode,
160 printf("Cannot lookup file %s\n", file);
164 if (type != BTRFS_FT_REG_FILE) {
165 printf("Not a regular file: %s\n", file);
173 int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len,
176 struct btrfs_root root = btrfs_info.fs_root;
177 struct btrfs_inode_item inode;
181 inr = btrfs_lookup_path(&root, root.root_dirid, file, &type, &inode,
185 printf("Cannot lookup file %s\n", file);
189 if (type != BTRFS_FT_REG_FILE) {
190 printf("Not a regular file: %s\n", file);
197 if (len > inode.size - offset)
198 len = inode.size - offset;
200 rd = btrfs_file_read(&root, inr, offset, len, buf);
202 printf("An error occured while reading file %s\n", file);
210 void btrfs_close(void)
212 btrfs_chunk_map_exit();
215 int btrfs_uuid(char *uuid_str)
217 #ifdef CONFIG_LIB_UUID
218 uuid_bin_to_str(btrfs_info.sb.fsid, uuid_str, UUID_STR_FORMAT_STD);