2 * BTRFS filesystem implementation for U-Boot
4 * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
6 * SPDX-License-Identifier: GPL-2.0+
12 #include <linux/time.h>
14 struct btrfs_info btrfs_info;
16 static int readdir_callback(const struct btrfs_root *root,
17 struct btrfs_dir_item *item)
19 static const char typestr[BTRFS_FT_MAX][4] = {
20 [BTRFS_FT_UNKNOWN] = " ? ",
21 [BTRFS_FT_REG_FILE] = " ",
22 [BTRFS_FT_DIR] = "DIR",
23 [BTRFS_FT_CHRDEV] = "CHR",
24 [BTRFS_FT_BLKDEV] = "BLK",
25 [BTRFS_FT_FIFO] = "FIF",
26 [BTRFS_FT_SOCK] = "SCK",
27 [BTRFS_FT_SYMLINK] = "SYM",
28 [BTRFS_FT_XATTR] = " ? ",
30 struct btrfs_inode_item inode;
31 const char *name = (const char *) (item + 1);
32 char filetime[32], *target = NULL;
35 if (btrfs_lookup_inode(root, &item->location, &inode, NULL)) {
36 printf("%s: Cannot find inode item for directory entry %.*s!\n",
37 __func__, item->name_len, name);
41 mtime = inode.mtime.sec;
42 ctime_r(&mtime, filetime);
44 if (item->type == BTRFS_FT_SYMLINK) {
45 target = malloc(min(inode.size + 1,
46 (u64) btrfs_info.sb.sectorsize));
48 if (target && btrfs_readlink(root, item->location.objectid,
55 printf("%s: Cannot read symlink target!\n", __func__);
58 printf("<%s> ", typestr[item->type]);
59 if (item->type == BTRFS_FT_CHRDEV || item->type == BTRFS_FT_BLKDEV)
60 printf("%4u,%5u ", (unsigned int) (inode.rdev >> 20),
61 (unsigned int) (inode.rdev & 0xfffff));
63 printf("%10llu ", inode.size);
65 printf("%24.24s %.*s", filetime, item->name_len, name);
67 if (item->type == BTRFS_FT_SYMLINK) {
68 printf(" -> %s", target ? target : "?");
78 int btrfs_probe(struct blk_desc *fs_dev_desc, disk_partition_t *fs_partition)
80 btrfs_blk_desc = fs_dev_desc;
81 btrfs_part_info = fs_partition;
83 memset(&btrfs_info, 0, sizeof(btrfs_info));
86 if (btrfs_read_superblock())
89 if (btrfs_chunk_map_init()) {
90 printf("%s: failed to init chunk map\n", __func__);
94 btrfs_info.tree_root.objectid = 0;
95 btrfs_info.tree_root.bytenr = btrfs_info.sb.root;
96 btrfs_info.chunk_root.objectid = 0;
97 btrfs_info.chunk_root.bytenr = btrfs_info.sb.chunk_root;
99 if (btrfs_read_chunk_tree()) {
100 printf("%s: failed to read chunk tree\n", __func__);
104 if (btrfs_find_root(btrfs_get_default_subvol_objectid(),
105 &btrfs_info.fs_root, NULL)) {
106 printf("%s: failed to find default subvolume\n", __func__);
113 int btrfs_ls(const char *path)
115 struct btrfs_root root = btrfs_info.fs_root;
119 inr = btrfs_lookup_path(&root, root.root_dirid, path, &type, NULL, 40);
122 printf("Cannot lookup path %s\n", path);
126 if (type != BTRFS_FT_DIR) {
127 printf("Not a directory: %s\n", path);
131 if (btrfs_readdir(&root, inr, readdir_callback)) {
132 printf("An error occured while listing directory %s\n", path);
139 int btrfs_exists(const char *file)
141 struct btrfs_root root = btrfs_info.fs_root;
145 inr = btrfs_lookup_path(&root, root.root_dirid, file, &type, NULL, 40);
147 return (inr != -1ULL && type == BTRFS_FT_REG_FILE);
150 int btrfs_size(const char *file, loff_t *size)
152 struct btrfs_root root = btrfs_info.fs_root;
153 struct btrfs_inode_item inode;
157 inr = btrfs_lookup_path(&root, root.root_dirid, file, &type, &inode,
161 printf("Cannot lookup file %s\n", file);
165 if (type != BTRFS_FT_REG_FILE) {
166 printf("Not a regular file: %s\n", file);
174 int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len,
177 struct btrfs_root root = btrfs_info.fs_root;
178 struct btrfs_inode_item inode;
182 inr = btrfs_lookup_path(&root, root.root_dirid, file, &type, &inode,
186 printf("Cannot lookup file %s\n", file);
190 if (type != BTRFS_FT_REG_FILE) {
191 printf("Not a regular file: %s\n", file);
198 if (len > inode.size - offset)
199 len = inode.size - offset;
201 rd = btrfs_file_read(&root, inr, offset, len, buf);
203 printf("An error occured while reading file %s\n", file);
211 void btrfs_close(void)
213 btrfs_chunk_map_exit();
216 int btrfs_uuid(char *uuid_str)
218 #ifdef CONFIG_LIB_UUID
219 uuid_bin_to_str(btrfs_info.sb.fsid, uuid_str, UUID_STR_FORMAT_STD);