clk: fixed-rate: Enable DM_FLAG_PRE_RELOC flag
[platform/kernel/u-boot.git] / fs / btrfs / btrfs.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * BTRFS filesystem implementation for U-Boot
4  *
5  * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
6  */
7
8 #include "btrfs.h"
9 #include <config.h>
10 #include <malloc.h>
11 #include <uuid.h>
12 #include <linux/time.h>
13
14 struct btrfs_info btrfs_info;
15
16 static int readdir_callback(const struct btrfs_root *root,
17                             struct btrfs_dir_item *item)
18 {
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]    = " ? ",
29         };
30         struct btrfs_inode_item inode;
31         const char *name = (const char *) (item + 1);
32         char filetime[32], *target = NULL;
33         time_t mtime;
34
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);
38                 return 0;
39         }
40
41         mtime = inode.mtime.sec;
42         ctime_r(&mtime, filetime);
43
44         if (item->type == BTRFS_FT_SYMLINK) {
45                 target = malloc(min(inode.size + 1,
46                                     (u64) btrfs_info.sb.sectorsize));
47
48                 if (target && btrfs_readlink(root, item->location.objectid,
49                                              target)) {
50                         free(target);
51                         target = NULL;
52                 }
53
54                 if (!target)
55                         printf("%s: Cannot read symlink target!\n", __func__);
56         }
57
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));
62         else
63                 printf("%10llu  ", inode.size);
64
65         printf("%24.24s  %.*s", filetime, item->name_len, name);
66
67         if (item->type == BTRFS_FT_SYMLINK) {
68                 printf(" -> %s", target ? target : "?");
69                 if (target)
70                         free(target);
71         }
72
73         printf("\n");
74
75         return 0;
76 }
77
78 int btrfs_probe(struct blk_desc *fs_dev_desc,
79                 struct disk_partition *fs_partition)
80 {
81         btrfs_blk_desc = fs_dev_desc;
82         btrfs_part_info = fs_partition;
83
84         memset(&btrfs_info, 0, sizeof(btrfs_info));
85
86         btrfs_hash_init();
87         if (btrfs_read_superblock())
88                 return -1;
89
90         if (btrfs_chunk_map_init()) {
91                 printf("%s: failed to init chunk map\n", __func__);
92                 return -1;
93         }
94
95         btrfs_info.tree_root.objectid = 0;
96         btrfs_info.tree_root.bytenr = btrfs_info.sb.root;
97         btrfs_info.chunk_root.objectid = 0;
98         btrfs_info.chunk_root.bytenr = btrfs_info.sb.chunk_root;
99
100         if (btrfs_read_chunk_tree()) {
101                 printf("%s: failed to read chunk tree\n", __func__);
102                 return -1;
103         }
104
105         if (btrfs_find_root(btrfs_get_default_subvol_objectid(),
106                             &btrfs_info.fs_root, NULL)) {
107                 printf("%s: failed to find default subvolume\n", __func__);
108                 return -1;
109         }
110
111         return 0;
112 }
113
114 int btrfs_ls(const char *path)
115 {
116         struct btrfs_root root = btrfs_info.fs_root;
117         u64 inr;
118         u8 type;
119
120         inr = btrfs_lookup_path(&root, root.root_dirid, path, &type, NULL, 40);
121
122         if (inr == -1ULL) {
123                 printf("Cannot lookup path %s\n", path);
124                 return -1;
125         }
126
127         if (type != BTRFS_FT_DIR) {
128                 printf("Not a directory: %s\n", path);
129                 return -1;
130         }
131
132         if (btrfs_readdir(&root, inr, readdir_callback)) {
133                 printf("An error occured while listing directory %s\n", path);
134                 return -1;
135         }
136
137         return 0;
138 }
139
140 int btrfs_exists(const char *file)
141 {
142         struct btrfs_root root = btrfs_info.fs_root;
143         u64 inr;
144         u8 type;
145
146         inr = btrfs_lookup_path(&root, root.root_dirid, file, &type, NULL, 40);
147
148         return (inr != -1ULL && type == BTRFS_FT_REG_FILE);
149 }
150
151 int btrfs_size(const char *file, loff_t *size)
152 {
153         struct btrfs_root root = btrfs_info.fs_root;
154         struct btrfs_inode_item inode;
155         u64 inr;
156         u8 type;
157
158         inr = btrfs_lookup_path(&root, root.root_dirid, file, &type, &inode,
159                                 40);
160
161         if (inr == -1ULL) {
162                 printf("Cannot lookup file %s\n", file);
163                 return -1;
164         }
165
166         if (type != BTRFS_FT_REG_FILE) {
167                 printf("Not a regular file: %s\n", file);
168                 return -1;
169         }
170
171         *size = inode.size;
172         return 0;
173 }
174
175 int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len,
176                loff_t *actread)
177 {
178         struct btrfs_root root = btrfs_info.fs_root;
179         struct btrfs_inode_item inode;
180         u64 inr, rd;
181         u8 type;
182
183         inr = btrfs_lookup_path(&root, root.root_dirid, file, &type, &inode,
184                                 40);
185
186         if (inr == -1ULL) {
187                 printf("Cannot lookup file %s\n", file);
188                 return -1;
189         }
190
191         if (type != BTRFS_FT_REG_FILE) {
192                 printf("Not a regular file: %s\n", file);
193                 return -1;
194         }
195
196         if (!len)
197                 len = inode.size;
198
199         if (len > inode.size - offset)
200                 len = inode.size - offset;
201
202         rd = btrfs_file_read(&root, inr, offset, len, buf);
203         if (rd == -1ULL) {
204                 printf("An error occured while reading file %s\n", file);
205                 return -1;
206         }
207
208         *actread = rd;
209         return 0;
210 }
211
212 void btrfs_close(void)
213 {
214         btrfs_chunk_map_exit();
215 }
216
217 int btrfs_uuid(char *uuid_str)
218 {
219 #ifdef CONFIG_LIB_UUID
220         uuid_bin_to_str(btrfs_info.sb.fsid, uuid_str, UUID_STR_FORMAT_STD);
221         return 0;
222 #endif
223         return -ENOSYS;
224 }