/src/util-linux/libblkid/src/superblocks/erofs.c
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /*  | 
2  |  |  * Copyright (C) 2020 Gao Xiang  | 
3  |  |  *  | 
4  |  |  * This file may be redistributed under the terms of the  | 
5  |  |  * GNU Lesser General Public License  | 
6  |  |  *  | 
7  |  |  * https://docs.kernel.org/filesystems/erofs.html  | 
8  |  |  */  | 
9  |  | #include <stddef.h>  | 
10  |  | #include <string.h>  | 
11  |  |  | 
12  |  | #include "superblocks.h"  | 
13  |  | #include "crc32c.h"  | 
14  |  |  | 
15  | 35  | #define EROFS_SUPER_OFFSET      1024  | 
16  |  | #define EROFS_SB_KBOFF    (EROFS_SUPER_OFFSET >> 10)  | 
17  | 47  | #define EROFS_FEATURE_SB_CSUM (1 << 0)  | 
18  |  |  | 
19  |  | #define EROFS_SUPER_MAGIC_V1  "\xe2\xe1\xf5\xe0"  | 
20  |  | #define EROFS_MAGIC_OFF   0  | 
21  |  |  | 
22  |  | /* All in little-endian */  | 
23  |  | struct erofs_super_block { | 
24  |  |   uint32_t  magic;  | 
25  |  |   uint32_t  checksum;  | 
26  |  |   uint32_t  feature_compat;  | 
27  |  |   uint8_t   blkszbits;  | 
28  |  |   uint8_t   reserved;  | 
29  |  |  | 
30  |  |   uint16_t  root_nid;  | 
31  |  |   uint64_t  inos;  | 
32  |  |  | 
33  |  |   uint64_t  build_time;  | 
34  |  |   uint32_t  build_time_nsec;  | 
35  |  |   uint32_t  blocks;  | 
36  |  |   uint32_t  meta_blkaddr;  | 
37  |  |   uint32_t  xattr_blkaddr;  | 
38  |  |   uint8_t   uuid[16];  | 
39  |  |   uint8_t   volume_name[16];  | 
40  |  |   uint32_t  feature_incompat;  | 
41  |  |   uint8_t   reserved2[44];  | 
42  |  | } __attribute__((packed));  | 
43  |  |  | 
44  |  | static int erofs_verify_checksum(blkid_probe pr, const struct blkid_idmag *mag,  | 
45  |  |     const struct erofs_super_block *sb)  | 
46  | 47  | { | 
47  | 47  |   uint32_t expected, csum;  | 
48  | 47  |   size_t csummed_size;  | 
49  | 47  |   const unsigned char *csummed;  | 
50  |  |  | 
51  | 47  |   if (!(le32_to_cpu(sb->feature_compat) & EROFS_FEATURE_SB_CSUM))  | 
52  | 12  |     return 1;  | 
53  |  |  | 
54  | 35  |   expected = le32_to_cpu(sb->checksum);  | 
55  | 35  |   csummed_size = (1U << sb->blkszbits) - EROFS_SUPER_OFFSET;  | 
56  |  |  | 
57  | 35  |   csummed = blkid_probe_get_sb_buffer(pr, mag, csummed_size);  | 
58  | 35  |   if (!csummed)  | 
59  | 11  |     return 0;  | 
60  |  |  | 
61  | 24  |   csum = ul_crc32c_exclude_offset(~0L, csummed, csummed_size,  | 
62  | 24  |                       offsetof(struct erofs_super_block, checksum),  | 
63  | 24  |           sizeof_member(struct erofs_super_block, checksum));  | 
64  |  |  | 
65  | 24  |   return blkid_probe_verify_csum(pr, csum, expected);  | 
66  | 35  | }  | 
67  |  |  | 
68  |  | static int probe_erofs(blkid_probe pr, const struct blkid_idmag *mag)  | 
69  | 398  | { | 
70  | 398  |   const struct erofs_super_block *sb;  | 
71  |  |  | 
72  | 398  |   sb = blkid_probe_get_sb(pr, mag, struct erofs_super_block);  | 
73  | 398  |   if (!sb)  | 
74  | 0  |     return errno ? -errno : BLKID_PROBE_NONE;  | 
75  |  |  | 
76  |  |   /* block size must be between 512 and 64k */  | 
77  | 398  |   if (sb->blkszbits < 9 || sb->blkszbits > 16)  | 
78  | 351  |     return BLKID_PROBE_NONE;  | 
79  |  |  | 
80  | 47  |   if (!erofs_verify_checksum(pr, mag, sb))  | 
81  | 35  |     return BLKID_PROBE_NONE;  | 
82  |  |  | 
83  | 12  |   if (sb->volume_name[0])  | 
84  | 1  |     blkid_probe_set_label(pr, (unsigned char *)sb->volume_name,  | 
85  | 1  |               sizeof(sb->volume_name));  | 
86  |  |  | 
87  | 12  |   blkid_probe_set_uuid(pr, sb->uuid);  | 
88  | 12  |   blkid_probe_set_fsblocksize(pr, 1U << sb->blkszbits);  | 
89  | 12  |   blkid_probe_set_block_size(pr, 1U << sb->blkszbits);  | 
90  | 12  |   blkid_probe_set_fssize(pr, (uint64_t) (1U << sb->blkszbits) * le32_to_cpu(sb->blocks));  | 
91  |  |  | 
92  | 12  |   return BLKID_PROBE_OK;  | 
93  | 47  | }  | 
94  |  |  | 
95  |  | const struct blkid_idinfo erofs_idinfo =  | 
96  |  | { | 
97  |  |   .name           = "erofs",  | 
98  |  |   .usage          = BLKID_USAGE_FILESYSTEM,  | 
99  |  |   .probefunc      = probe_erofs,  | 
100  |  |   .magics         =  | 
101  |  |         { | 
102  |  |     { | 
103  |  |       .magic = EROFS_SUPER_MAGIC_V1,  | 
104  |  |       .len = 4,  | 
105  |  |       .kboff = EROFS_SB_KBOFF,  | 
106  |  |       .sboff = EROFS_MAGIC_OFF,  | 
107  |  |     }, { NULL } | 
108  |  |   }  | 
109  |  | };  |