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 #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
;
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
);
249 ret
= btrfs_size(file
, &real_size
);
251 error("Failed to get inode size: %s", file
);
255 if (!len
|| len
> real_size
- offset
)
256 len
= real_size
- offset
;
258 ret
= btrfs_file_read(root
, ino
, offset
, len
, buf
);
260 error("An error occurred while reading file %s", file
);
268 void btrfs_close(void)
270 if (current_fs_info
) {
271 close_ctree_fs_info(current_fs_info
);
272 current_fs_info
= NULL
;
276 int btrfs_uuid(char *uuid_str
)
278 #ifdef CONFIG_LIB_UUID
280 uuid_bin_to_str(current_fs_info
->super_copy
->fsid
, uuid_str
,
281 UUID_STR_FORMAT_STD
);