/src/util-linux/libblkid/src/superblocks/minix.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) 1999 by Andries Brouwer |
3 | | * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o |
4 | | * Copyright (C) 2001 by Andreas Dilger |
5 | | * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> |
6 | | * Copyright (C) 2008-2013 Karel Zak <kzak@redhat.com> |
7 | | * |
8 | | * This file may be redistributed under the terms of the |
9 | | * GNU Lesser General Public License. |
10 | | */ |
11 | | |
12 | | #include <string.h> |
13 | | #include "superblocks.h" |
14 | | #include "minix.h" |
15 | | |
16 | 4.25k | #define minix_swab16(doit, num) ((uint16_t) (doit ? swab16(num) : num)) |
17 | 321 | #define minix_swab32(doit, num) ((uint32_t) (doit ? swab32(num) : num)) |
18 | | |
19 | | static int get_minix_version(const unsigned char *data, int *other_endian) |
20 | 1.77k | { |
21 | 1.77k | const struct minix_super_block *sb = (const struct minix_super_block *) data; |
22 | 1.77k | const struct minix3_super_block *sb3 = (const struct minix3_super_block *) data; |
23 | 1.77k | int version = 0; |
24 | 1.77k | char *endian; |
25 | | |
26 | 1.77k | *other_endian = 0; |
27 | | |
28 | 1.77k | switch (sb->s_magic) { |
29 | 295 | case MINIX_SUPER_MAGIC: |
30 | 551 | case MINIX_SUPER_MAGIC2: |
31 | 551 | version = 1; |
32 | 551 | break; |
33 | 271 | case MINIX2_SUPER_MAGIC: |
34 | 351 | case MINIX2_SUPER_MAGIC2: |
35 | 351 | version = 2; |
36 | 351 | break; |
37 | 873 | default: |
38 | 873 | if (sb3->s_magic == MINIX3_SUPER_MAGIC) |
39 | 94 | version = 3; |
40 | 873 | break; |
41 | 1.77k | } |
42 | | |
43 | 1.77k | if (!version) { |
44 | 779 | *other_endian = 1; |
45 | | |
46 | 779 | switch (swab16(sb->s_magic)) { |
47 | 106 | case MINIX_SUPER_MAGIC: |
48 | 371 | case MINIX_SUPER_MAGIC2: |
49 | 371 | version = 1; |
50 | 371 | break; |
51 | 12 | case MINIX2_SUPER_MAGIC: |
52 | 295 | case MINIX2_SUPER_MAGIC2: |
53 | 295 | version = 2; |
54 | 295 | break; |
55 | 113 | default: |
56 | 113 | if (sb3->s_magic == MINIX3_SUPER_MAGIC) |
57 | 0 | version = 3; |
58 | 113 | break; |
59 | 779 | } |
60 | 779 | } |
61 | 1.77k | if (!version) |
62 | 113 | return -1; |
63 | | |
64 | | #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
65 | | endian = *other_endian ? "LE" : "BE"; |
66 | | #else |
67 | 1.66k | endian = *other_endian ? "BE" : "LE"; |
68 | 1.66k | #endif |
69 | 1.66k | DBG(LOWPROBE, ul_debug("minix version %d detected [%s]", version, |
70 | 1.66k | endian)); |
71 | 1.66k | return version; |
72 | 1.77k | } |
73 | | |
74 | | static int probe_minix(blkid_probe pr, |
75 | | const struct blkid_idmag *mag __attribute__((__unused__))) |
76 | 1.77k | { |
77 | 1.77k | const unsigned char *ext; |
78 | 1.77k | const unsigned char *data; |
79 | 1.77k | int version = 0, swabme = 0; |
80 | 1.77k | unsigned long zones, ninodes, imaps, zmaps; |
81 | 1.77k | off_t firstz; |
82 | 1.77k | size_t zone_size; |
83 | 1.77k | unsigned block_size; |
84 | | |
85 | 1.77k | data = blkid_probe_get_buffer(pr, 1024, |
86 | 1.77k | max(sizeof(struct minix_super_block), |
87 | 1.77k | sizeof(struct minix3_super_block))); |
88 | 1.77k | if (!data) |
89 | 0 | return errno ? -errno : 1; |
90 | 1.77k | version = get_minix_version(data, &swabme); |
91 | 1.77k | switch (version) { |
92 | 922 | case 1: |
93 | 1.56k | case 2: { |
94 | 1.56k | const struct minix_super_block *sb = (const struct minix_super_block *) data; |
95 | | |
96 | 1.56k | uint16_t state = minix_swab16(swabme, sb->s_state); |
97 | 1.56k | if ((state & (MINIX_VALID_FS | MINIX_ERROR_FS)) != state) |
98 | 1.16k | return 1; |
99 | | |
100 | 408 | zones = version == 2 ? minix_swab32(swabme, sb->s_zones) : |
101 | 408 | minix_swab16(swabme, sb->s_nzones); |
102 | 408 | ninodes = minix_swab16(swabme, sb->s_ninodes); |
103 | 408 | imaps = minix_swab16(swabme, sb->s_imap_blocks); |
104 | 408 | zmaps = minix_swab16(swabme, sb->s_zmap_blocks); |
105 | 408 | firstz = minix_swab16(swabme, sb->s_firstdatazone); |
106 | 408 | zone_size = sb->s_log_zone_size; |
107 | 408 | block_size = 1024; |
108 | 408 | break; |
109 | 1.56k | } |
110 | 94 | case 3: { |
111 | 94 | const struct minix3_super_block *sb = (const struct minix3_super_block *) data; |
112 | | |
113 | 94 | zones = minix_swab32(swabme, sb->s_zones); |
114 | 94 | ninodes = minix_swab32(swabme, sb->s_ninodes); |
115 | 94 | imaps = minix_swab16(swabme, sb->s_imap_blocks); |
116 | 94 | zmaps = minix_swab16(swabme, sb->s_zmap_blocks); |
117 | 94 | firstz = minix_swab16(swabme, sb->s_firstdatazone); |
118 | 94 | zone_size = sb->s_log_zone_size; |
119 | 94 | block_size = minix_swab16(swabme, sb->s_blocksize); |
120 | | |
121 | 94 | break; |
122 | 1.56k | } |
123 | 113 | default: |
124 | 113 | return 1; |
125 | 1.77k | } |
126 | | |
127 | | /* sanity checks to be sure that the FS is really minix. |
128 | | * see disk-utils/fsck.minix.c read_superblock |
129 | | */ |
130 | 502 | if (zone_size != 0 || ninodes == 0 || ninodes == UINT32_MAX) |
131 | 219 | return 1; |
132 | 283 | if (imaps * MINIX_BLOCK_SIZE * 8 < ninodes + 1) |
133 | 135 | return 1; |
134 | 148 | if (firstz > (off_t) zones) |
135 | 18 | return 1; |
136 | 130 | if (zmaps * MINIX_BLOCK_SIZE * 8 < zones - firstz + 1) |
137 | 86 | return 1; |
138 | | |
139 | | /* unfortunately, some parts of ext3 is sometimes possible to |
140 | | * interpreted as minix superblock. So check for extN magic |
141 | | * string. (For extN magic string and offsets see ext.c.) |
142 | | */ |
143 | 44 | ext = blkid_probe_get_buffer(pr, 0x400 + 0x38, 2); |
144 | 44 | if (!ext) |
145 | 0 | return errno ? -errno : 1; |
146 | | |
147 | 44 | if (memcmp(ext, "\123\357", 2) == 0) |
148 | 7 | return 1; |
149 | | |
150 | 37 | blkid_probe_sprintf_version(pr, "%d", version); |
151 | 37 | blkid_probe_set_fsblocksize(pr, block_size); |
152 | 37 | blkid_probe_set_block_size(pr, block_size); |
153 | 37 | blkid_probe_set_fsendianness(pr, !swabme ? |
154 | 30 | BLKID_ENDIANNESS_NATIVE : BLKID_ENDIANNESS_OTHER); |
155 | 37 | return 0; |
156 | 44 | } |
157 | | |
158 | | const struct blkid_idinfo minix_idinfo = |
159 | | { |
160 | | .name = "minix", |
161 | | .usage = BLKID_USAGE_FILESYSTEM, |
162 | | .probefunc = probe_minix, |
163 | | .magics = |
164 | | { |
165 | | /* version 1 - LE */ |
166 | | { .magic = "\177\023", .len = 2, .kboff = 1, .sboff = 0x10 }, |
167 | | { .magic = "\217\023", .len = 2, .kboff = 1, .sboff = 0x10 }, |
168 | | |
169 | | /* version 1 - BE */ |
170 | | { .magic = "\023\177", .len = 2, .kboff = 1, .sboff = 0x10 }, |
171 | | { .magic = "\023\217", .len = 2, .kboff = 1, .sboff = 0x10 }, |
172 | | |
173 | | /* version 2 - LE */ |
174 | | { .magic = "\150\044", .len = 2, .kboff = 1, .sboff = 0x10 }, |
175 | | { .magic = "\170\044", .len = 2, .kboff = 1, .sboff = 0x10 }, |
176 | | |
177 | | /* version 2 - BE */ |
178 | | { .magic = "\044\150", .len = 2, .kboff = 1, .sboff = 0x10 }, |
179 | | { .magic = "\044\170", .len = 2, .kboff = 1, .sboff = 0x10 }, |
180 | | |
181 | | /* version 3 - LE */ |
182 | | { .magic = "\132\115", .len = 2, .kboff = 1, .sboff = 0x18 }, |
183 | | |
184 | | /* version 3 - BE */ |
185 | | { .magic = "\115\132", .len = 2, .kboff = 1, .sboff = 0x18 }, |
186 | | |
187 | | { NULL } |
188 | | } |
189 | | }; |
190 | | |