1 /* SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0 */
2 /*
3 * Copyright (C) 2019 HUAWEI, Inc.
4 * http://www.huawei.com/
5 * Created by Gao Xiang <gaoxiang25@huawei.com>
6 */
7 #ifndef __EROFS_INTERNAL_H
8 #define __EROFS_INTERNAL_H
9
10 #ifdef __cplusplus
11 extern "C"
12 {
13 #endif
14
15 #include "list.h"
16 #include "err.h"
17
18 typedef unsigned short umode_t;
19
20 #include "erofs_fs.h"
21 #include <fcntl.h>
22 #include <sys/types.h> /* for off_t definition */
23 #include <sys/stat.h> /* for S_ISCHR definition */
24 #include <stdio.h>
25
26 #ifndef PATH_MAX
27 #define PATH_MAX 4096 /* # chars in a path name including nul */
28 #endif
29
30 #ifndef EROFS_MAX_BLOCK_SIZE
31 #define EROFS_MAX_BLOCK_SIZE 4096
32 #endif
33
34 #define EROFS_ISLOTBITS 5
35 #define EROFS_SLOTSIZE (1U << EROFS_ISLOTBITS)
36
37 typedef u64 erofs_off_t;
38 typedef u64 erofs_nid_t;
39 /* data type for filesystem-wide blocks number */
40 typedef u32 erofs_blk_t;
41
42 #define NULL_ADDR ((unsigned int)-1)
43 #define NULL_ADDR_UL ((unsigned long)-1)
44
45 /* global sbi */
46 extern struct erofs_sb_info sbi;
47
48 #define erofs_blksiz(sbi) (1u << (sbi)->blkszbits)
49 #define erofs_blknr(sbi, addr) ((addr) >> (sbi)->blkszbits)
50 #define erofs_blkoff(sbi, addr) ((addr) & (erofs_blksiz(sbi) - 1))
51 #define erofs_pos(sbi, nr) ((erofs_off_t)(nr) << (sbi)->blkszbits)
52 #define BLK_ROUND_UP(sbi, addr) DIV_ROUND_UP(addr, erofs_blksiz(sbi))
53
54 struct erofs_buffer_head;
55
56 struct erofs_device_info {
57 u8 tag[64];
58 u32 blocks;
59 u32 mapped_blkaddr;
60 };
61
62 struct erofs_xattr_prefix_item {
63 struct erofs_xattr_long_prefix *prefix;
64 u8 infix_len;
65 };
66
67 #define EROFS_PACKED_NID_UNALLOCATED -1
68
69 struct erofs_sb_info {
70 struct erofs_device_info *devs;
71 char *devname;
72
73 u64 total_blocks;
74 u64 primarydevice_blocks;
75
76 erofs_blk_t meta_blkaddr;
77 erofs_blk_t xattr_blkaddr;
78
79 u32 feature_compat;
80 u32 feature_incompat;
81 u64 build_time;
82 u32 build_time_nsec;
83
84 u8 extslots;
85 unsigned char islotbits;
86 unsigned char blkszbits;
87
88 /* what we really care is nid, rather than ino.. */
89 erofs_nid_t root_nid;
90 /* used for statfs, f_files - f_favail */
91 u64 inos;
92
93 u8 uuid[16];
94 char volume_name[16];
95
96 u16 available_compr_algs;
97 u16 lz4_max_distance;
98
99 u32 checksum;
100 u16 extra_devices;
101 union {
102 u16 devt_slotoff; /* used for mkfs */
103 u16 device_id_mask; /* used for others */
104 };
105 erofs_nid_t packed_nid;
106
107 u32 xattr_prefix_start;
108 u8 xattr_prefix_count;
109 struct erofs_xattr_prefix_item *xattr_prefixes;
110
111 int devfd, devblksz;
112 u64 devsz;
113 dev_t dev;
114 unsigned int nblobs;
115 unsigned int blobfd[256];
116
117 struct list_head list;
118
119 u64 saved_by_deduplication;
120 };
121
122 /* make sure that any user of the erofs headers has atleast 64bit off_t type */
123 extern int erofs_assert_largefile[sizeof(off_t)-8];
124
125 #define EROFS_FEATURE_FUNCS(name, compat, feature) \
126 static inline bool erofs_sb_has_##name(struct erofs_sb_info *sbi) \
127 { \
128 return sbi->feature_##compat & EROFS_FEATURE_##feature; \
129 } \
130 static inline void erofs_sb_set_##name(struct erofs_sb_info *sbi) \
131 { \
132 sbi->feature_##compat |= EROFS_FEATURE_##feature; \
133 } \
134 static inline void erofs_sb_clear_##name(struct erofs_sb_info *sbi) \
135 { \
136 sbi->feature_##compat &= ~EROFS_FEATURE_##feature; \
137 }
138
139 EROFS_FEATURE_FUNCS(lz4_0padding, incompat, INCOMPAT_ZERO_PADDING)
140 EROFS_FEATURE_FUNCS(compr_cfgs, incompat, INCOMPAT_COMPR_CFGS)
141 EROFS_FEATURE_FUNCS(big_pcluster, incompat, INCOMPAT_BIG_PCLUSTER)
142 EROFS_FEATURE_FUNCS(chunked_file, incompat, INCOMPAT_CHUNKED_FILE)
143 EROFS_FEATURE_FUNCS(device_table, incompat, INCOMPAT_DEVICE_TABLE)
144 EROFS_FEATURE_FUNCS(ztailpacking, incompat, INCOMPAT_ZTAILPACKING)
145 EROFS_FEATURE_FUNCS(fragments, incompat, INCOMPAT_FRAGMENTS)
146 EROFS_FEATURE_FUNCS(dedupe, incompat, INCOMPAT_DEDUPE)
147 EROFS_FEATURE_FUNCS(xattr_prefixes, incompat, INCOMPAT_XATTR_PREFIXES)
148 EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM)
149 EROFS_FEATURE_FUNCS(xattr_filter, compat, COMPAT_XATTR_FILTER)
150
151 #define EROFS_I_EA_INITED (1 << 0)
152 #define EROFS_I_Z_INITED (1 << 1)
153
154 struct erofs_diskbuf;
155
156 struct erofs_inode {
157 struct list_head i_hash, i_subdirs, i_xattrs;
158
159 union {
160 /* (erofsfuse) runtime flags */
161 unsigned int flags;
162
163 /* (mkfs.erofs) next pointer for directory dumping */
164 struct erofs_inode *next_dirwrite;
165 };
166 unsigned int i_count;
167 struct erofs_sb_info *sbi;
168 struct erofs_inode *i_parent;
169
170 /* (mkfs.erofs) device ID containing source file */
171 u32 dev;
172
173 umode_t i_mode;
174 erofs_off_t i_size;
175
176 u64 i_ino[2];
177 u32 i_uid;
178 u32 i_gid;
179 u64 i_mtime;
180 u32 i_mtime_nsec;
181 u32 i_nlink;
182
183 union {
184 u32 i_blkaddr;
185 u32 i_blocks;
186 u32 i_rdev;
187 struct {
188 unsigned short chunkformat;
189 unsigned char chunkbits;
190 };
191 } u;
192
193 char *i_srcpath;
194 union {
195 char *i_link;
196 struct erofs_diskbuf *i_diskbuf;
197 };
198 unsigned char datalayout;
199 unsigned char inode_isize;
200 /* inline tail-end packing size */
201 unsigned short idata_size;
202 bool compressed_idata;
203 bool lazy_tailblock;
204 bool with_diskbuf;
205 bool opaque;
206 /* OVL: non-merge dir that may contain whiteout entries */
207 bool whiteouts;
208
209 unsigned int xattr_isize;
210 unsigned int extent_isize;
211
212 unsigned int xattr_shared_count;
213 unsigned int *xattr_shared_xattrs;
214
215 erofs_nid_t nid;
216 struct erofs_buffer_head *bh;
217 struct erofs_buffer_head *bh_inline, *bh_data;
218
219 void *idata;
220
221 /* (ztailpacking) in order to recover uncompressed EOF data */
222 void *eof_tailraw;
223 unsigned int eof_tailrawsize;
224
225 union {
226 void *compressmeta;
227 void *chunkindexes;
228 struct {
229 uint16_t z_advise;
230 uint8_t z_algorithmtype[2];
231 uint8_t z_logical_clusterbits;
232 uint8_t z_physical_clusterblks;
233 uint64_t z_tailextent_headlcn;
234 unsigned int z_idataoff;
235 #define z_idata_size idata_size
236 };
237 };
238 #ifdef WITH_ANDROID
239 uint64_t capabilities;
240 #endif
241 erofs_off_t fragmentoff;
242 unsigned int fragment_size;
243 };
244
erofs_iloc(struct erofs_inode * inode)245 static inline erofs_off_t erofs_iloc(struct erofs_inode *inode)
246 {
247 struct erofs_sb_info *sbi = inode->sbi;
248
249 return erofs_pos(sbi, sbi->meta_blkaddr) +
250 (inode->nid << sbi->islotbits);
251 }
252
is_inode_layout_compression(struct erofs_inode * inode)253 static inline bool is_inode_layout_compression(struct erofs_inode *inode)
254 {
255 return erofs_inode_is_data_compressed(inode->datalayout);
256 }
257
erofs_bitrange(unsigned int value,unsigned int bit,unsigned int bits)258 static inline unsigned int erofs_bitrange(unsigned int value, unsigned int bit,
259 unsigned int bits)
260 {
261 return (value >> bit) & ((1 << bits) - 1);
262 }
263
erofs_inode_version(unsigned int value)264 static inline unsigned int erofs_inode_version(unsigned int value)
265 {
266 return erofs_bitrange(value, EROFS_I_VERSION_BIT,
267 EROFS_I_VERSION_BITS);
268 }
269
erofs_inode_datalayout(unsigned int value)270 static inline unsigned int erofs_inode_datalayout(unsigned int value)
271 {
272 return erofs_bitrange(value, EROFS_I_DATALAYOUT_BIT,
273 EROFS_I_DATALAYOUT_BITS);
274 }
275
276 #define IS_ROOT(x) ((x) == (x)->i_parent)
277
278 struct erofs_dentry {
279 struct list_head d_child; /* child of parent list */
280
281 unsigned int type;
282 char name[EROFS_NAME_LEN];
283 union {
284 struct erofs_inode *inode;
285 erofs_nid_t nid;
286 };
287 };
288
is_dot_dotdot_len(const char * name,unsigned int len)289 static inline bool is_dot_dotdot_len(const char *name, unsigned int len)
290 {
291 if (len >= 1 && name[0] != '.')
292 return false;
293
294 return len == 1 || (len == 2 && name[1] == '.');
295 }
296
is_dot_dotdot(const char * name)297 static inline bool is_dot_dotdot(const char *name)
298 {
299 if (name[0] != '.')
300 return false;
301
302 return name[1] == '\0' || (name[1] == '.' && name[2] == '\0');
303 }
304
305 #include <stdio.h>
306 #include <string.h>
307
erofs_strerror(int err)308 static inline const char *erofs_strerror(int err)
309 {
310 static char msg[256];
311
312 sprintf(msg, "[Error %d] %s", -err, strerror(-err));
313 return msg;
314 }
315
316 enum {
317 BH_Meta,
318 BH_Mapped,
319 BH_Encoded,
320 BH_FullMapped,
321 BH_Fragment,
322 BH_Partialref,
323 };
324
325 /* Has a disk mapping */
326 #define EROFS_MAP_MAPPED (1 << BH_Mapped)
327 /* Located in metadata (could be copied from bd_inode) */
328 #define EROFS_MAP_META (1 << BH_Meta)
329 /* The extent is encoded */
330 #define EROFS_MAP_ENCODED (1 << BH_Encoded)
331 /* The length of extent is full */
332 #define EROFS_MAP_FULL_MAPPED (1 << BH_FullMapped)
333 /* Located in the special packed inode */
334 #define EROFS_MAP_FRAGMENT (1 << BH_Fragment)
335 /* The extent refers to partial decompressed data */
336 #define EROFS_MAP_PARTIAL_REF (1 << BH_Partialref)
337
338 struct erofs_map_blocks {
339 char mpage[EROFS_MAX_BLOCK_SIZE];
340
341 erofs_off_t m_pa, m_la;
342 u64 m_plen, m_llen;
343
344 unsigned short m_deviceid;
345 char m_algorithmformat;
346 unsigned int m_flags;
347 erofs_blk_t index;
348 };
349
350 /*
351 * Used to get the exact decompressed length, e.g. fiemap (consider lookback
352 * approach instead if possible since it's more metadata lightweight.)
353 */
354 #define EROFS_GET_BLOCKS_FIEMAP 0x0002
355 /* Used to map tail extent for tailpacking inline or fragment pcluster */
356 #define EROFS_GET_BLOCKS_FINDTAIL 0x0008
357
358 enum {
359 Z_EROFS_COMPRESSION_SHIFTED = Z_EROFS_COMPRESSION_MAX,
360 Z_EROFS_COMPRESSION_INTERLACED,
361 Z_EROFS_COMPRESSION_RUNTIME_MAX
362 };
363
364 struct erofs_map_dev {
365 erofs_off_t m_pa;
366 unsigned int m_deviceid;
367 };
368
369 /* super.c */
370 int erofs_read_superblock(struct erofs_sb_info *sbi);
371 void erofs_put_super(struct erofs_sb_info *sbi);
372
373 /* namei.c */
374 int erofs_read_inode_from_disk(struct erofs_inode *vi);
375 int erofs_ilookup(const char *path, struct erofs_inode *vi);
376
377 /* data.c */
378 int erofs_pread(struct erofs_inode *inode, char *buf,
379 erofs_off_t count, erofs_off_t offset);
380 int erofs_map_blocks(struct erofs_inode *inode,
381 struct erofs_map_blocks *map, int flags);
382 int erofs_map_dev(struct erofs_sb_info *sbi, struct erofs_map_dev *map);
383 int erofs_read_one_data(struct erofs_inode *inode, struct erofs_map_blocks *map,
384 char *buffer, u64 offset, size_t len);
385 int z_erofs_read_one_data(struct erofs_inode *inode,
386 struct erofs_map_blocks *map, char *raw, char *buffer,
387 erofs_off_t skip, erofs_off_t length, bool trimmed);
388 void *erofs_read_metadata(struct erofs_sb_info *sbi, erofs_nid_t nid,
389 erofs_off_t *offset, int *lengthp);
390
erofs_get_occupied_size(const struct erofs_inode * inode,erofs_off_t * size)391 static inline int erofs_get_occupied_size(const struct erofs_inode *inode,
392 erofs_off_t *size)
393 {
394 *size = 0;
395 switch (inode->datalayout) {
396 case EROFS_INODE_FLAT_INLINE:
397 case EROFS_INODE_FLAT_PLAIN:
398 case EROFS_INODE_CHUNK_BASED:
399 *size = inode->i_size;
400 break;
401 case EROFS_INODE_COMPRESSED_FULL:
402 case EROFS_INODE_COMPRESSED_COMPACT:
403 *size = inode->u.i_blocks * erofs_blksiz(inode->sbi);
404 break;
405 default:
406 return -EOPNOTSUPP;
407 }
408 return 0;
409 }
410
411 /* data.c */
412 int erofs_getxattr(struct erofs_inode *vi, const char *name, char *buffer,
413 size_t buffer_size);
414 int erofs_listxattr(struct erofs_inode *vi, char *buffer, size_t buffer_size);
415
416 /* zmap.c */
417 int z_erofs_fill_inode(struct erofs_inode *vi);
418 int z_erofs_map_blocks_iter(struct erofs_inode *vi,
419 struct erofs_map_blocks *map, int flags);
420
421 #ifdef EUCLEAN
422 #define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */
423 #else
424 #define EFSCORRUPTED EIO
425 #endif
426
427 #define CRC32C_POLY_LE 0x82F63B78
erofs_crc32c(u32 crc,const u8 * in,size_t len)428 static inline u32 erofs_crc32c(u32 crc, const u8 *in, size_t len)
429 {
430 int i;
431
432 while (len--) {
433 crc ^= *in++;
434 for (i = 0; i < 8; i++)
435 crc = (crc >> 1) ^ ((crc & 1) ? CRC32C_POLY_LE : 0);
436 }
437 return crc;
438 }
439
440 #define EROFS_WHITEOUT_DEV 0
erofs_inode_is_whiteout(struct erofs_inode * inode)441 static inline bool erofs_inode_is_whiteout(struct erofs_inode *inode)
442 {
443 return S_ISCHR(inode->i_mode) && inode->u.i_rdev == EROFS_WHITEOUT_DEV;
444 }
445
446 #ifdef __cplusplus
447 }
448 #endif
449
450 #endif
451