Contents of /trunk/mkinitrd-magellan/klibc/usr/kinit/fstype/fstype.c
Parent Directory | Revision Log
Revision 532 -
(show annotations)
(download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 8060 byte(s)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 8060 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd
1 | /* |
2 | * by rmk |
3 | * |
4 | * Detect filesystem type (on stdin) and output strings for two |
5 | * environment variables: |
6 | * FSTYPE - filesystem type |
7 | * FSSIZE - filesystem size (if known) |
8 | * |
9 | * We currently detect the filesystems listed below in the struct |
10 | * "imagetype images" (in the order they are listed). |
11 | * |
12 | * MINIX, ext3 and Reiserfs bits are currently untested. |
13 | */ |
14 | |
15 | #include <sys/types.h> |
16 | #include <stdio.h> |
17 | #include <string.h> |
18 | #include <unistd.h> |
19 | #include <fcntl.h> |
20 | #include <endian.h> |
21 | #include <netinet/in.h> |
22 | #include <sys/vfs.h> |
23 | |
24 | #define cpu_to_be32(x) __cpu_to_be32(x) /* Needed by romfs_fs.h */ |
25 | |
26 | #include "romfs_fs.h" |
27 | #include "cramfs_fs.h" |
28 | #include "minix_fs.h" |
29 | #include "ext2_fs.h" |
30 | #include "ext3_fs.h" |
31 | #include "xfs_sb.h" |
32 | #include "luks_fs.h" |
33 | #include "lvm2_sb.h" |
34 | #include "iso9660_sb.h" |
35 | |
36 | /* |
37 | * Slightly cleaned up version of jfs_superblock to |
38 | * avoid pulling in other kernel header files. |
39 | */ |
40 | #include "jfs_superblock.h" |
41 | |
42 | /* |
43 | * reiserfs_fs.h is too sick to include directly. |
44 | * Use a cleaned up version. |
45 | */ |
46 | #include "reiserfs_fs.h" |
47 | |
48 | #include "fstype.h" |
49 | |
50 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) |
51 | |
52 | #define BLOCK_SIZE 1024 |
53 | |
54 | /* Swap needs the definition of block size */ |
55 | #include "swap_fs.h" |
56 | |
57 | static int gzip_image(const void *buf, unsigned long long *bytes) |
58 | { |
59 | const unsigned char *p = buf; |
60 | |
61 | if (p[0] == 037 && (p[1] == 0213 || p[1] == 0236)) { |
62 | /* The length of a gzip stream can only be determined |
63 | by processing the whole stream */ |
64 | *bytes = 0ULL; |
65 | return 1; |
66 | } |
67 | return 0; |
68 | } |
69 | |
70 | static int cramfs_image(const void *buf, unsigned long long *bytes) |
71 | { |
72 | const struct cramfs_super *sb = (const struct cramfs_super *)buf; |
73 | |
74 | if (sb->magic == CRAMFS_MAGIC) { |
75 | if (sb->flags & CRAMFS_FLAG_FSID_VERSION_2) |
76 | *bytes = (unsigned long long)sb->fsid.blocks << 10; |
77 | else |
78 | *bytes = 0; |
79 | return 1; |
80 | } |
81 | return 0; |
82 | } |
83 | |
84 | static int romfs_image(const void *buf, unsigned long long *bytes) |
85 | { |
86 | const struct romfs_super_block *sb = |
87 | (const struct romfs_super_block *)buf; |
88 | |
89 | if (sb->word0 == ROMSB_WORD0 && sb->word1 == ROMSB_WORD1) { |
90 | *bytes = __be32_to_cpu(sb->size); |
91 | return 1; |
92 | } |
93 | return 0; |
94 | } |
95 | |
96 | static int minix_image(const void *buf, unsigned long long *bytes) |
97 | { |
98 | const struct minix_super_block *sb = |
99 | (const struct minix_super_block *)buf; |
100 | |
101 | if (sb->s_magic == MINIX_SUPER_MAGIC || |
102 | sb->s_magic == MINIX_SUPER_MAGIC2) { |
103 | *bytes = (unsigned long long)sb->s_nzones |
104 | << (sb->s_log_zone_size + 10); |
105 | return 1; |
106 | } |
107 | return 0; |
108 | } |
109 | |
110 | static int ext3_image(const void *buf, unsigned long long *bytes) |
111 | { |
112 | const struct ext3_super_block *sb = |
113 | (const struct ext3_super_block *)buf; |
114 | |
115 | if (sb->s_magic == __cpu_to_le16(EXT2_SUPER_MAGIC) && |
116 | sb-> |
117 | s_feature_compat & __cpu_to_le32(EXT3_FEATURE_COMPAT_HAS_JOURNAL)) { |
118 | *bytes = (unsigned long long)__le32_to_cpu(sb->s_blocks_count) |
119 | << (10 + __le32_to_cpu(sb->s_log_block_size)); |
120 | return 1; |
121 | } |
122 | return 0; |
123 | } |
124 | |
125 | static int ext2_image(const void *buf, unsigned long long *bytes) |
126 | { |
127 | const struct ext2_super_block *sb = |
128 | (const struct ext2_super_block *)buf; |
129 | |
130 | if (sb->s_magic == __cpu_to_le16(EXT2_SUPER_MAGIC)) { |
131 | *bytes = (unsigned long long)__le32_to_cpu(sb->s_blocks_count) |
132 | << (10 + __le32_to_cpu(sb->s_log_block_size)); |
133 | return 1; |
134 | } |
135 | return 0; |
136 | } |
137 | |
138 | static int reiserfs_image(const void *buf, unsigned long long *bytes) |
139 | { |
140 | const struct reiserfs_super_block *sb = |
141 | (const struct reiserfs_super_block *)buf; |
142 | |
143 | if (memcmp(REISERFS_MAGIC(sb), REISERFS_SUPER_MAGIC_STRING, |
144 | sizeof(REISERFS_SUPER_MAGIC_STRING) - 1) == 0 || |
145 | memcmp(REISERFS_MAGIC(sb), REISER2FS_SUPER_MAGIC_STRING, |
146 | sizeof(REISER2FS_SUPER_MAGIC_STRING) - 1) == 0 || |
147 | memcmp(REISERFS_MAGIC(sb), REISER2FS_JR_SUPER_MAGIC_STRING, |
148 | sizeof(REISER2FS_JR_SUPER_MAGIC_STRING) - 1) == 0) { |
149 | *bytes = (unsigned long long)REISERFS_BLOCK_COUNT(sb) * |
150 | REISERFS_BLOCKSIZE(sb); |
151 | return 1; |
152 | } |
153 | return 0; |
154 | } |
155 | |
156 | static int xfs_image(const void *buf, unsigned long long *bytes) |
157 | { |
158 | const struct xfs_sb *sb = (const struct xfs_sb *)buf; |
159 | |
160 | if (__be32_to_cpu(sb->sb_magicnum) == XFS_SB_MAGIC) { |
161 | *bytes = __be64_to_cpu(sb->sb_dblocks) * |
162 | __be32_to_cpu(sb->sb_blocksize); |
163 | return 1; |
164 | } |
165 | return 0; |
166 | } |
167 | |
168 | static int jfs_image(const void *buf, unsigned long long *bytes) |
169 | { |
170 | const struct jfs_superblock *sb = (const struct jfs_superblock *)buf; |
171 | |
172 | if (!memcmp(sb->s_magic, JFS_MAGIC, 4)) { |
173 | *bytes = __le32_to_cpu(sb->s_size); |
174 | return 1; |
175 | } |
176 | return 0; |
177 | } |
178 | |
179 | static int luks_image(const void *buf, unsigned long long *blocks) |
180 | { |
181 | const struct luks_partition_header *lph = |
182 | (const struct luks_partition_header *)buf; |
183 | |
184 | if (!memcmp(lph->magic, LUKS_MAGIC, LUKS_MAGIC_L)) { |
185 | /* FSSIZE is dictated by the underlying fs, not by LUKS */ |
186 | *blocks = 0; |
187 | return 1; |
188 | } |
189 | return 0; |
190 | } |
191 | |
192 | static int swap_image(const void *buf, unsigned long long *blocks) |
193 | { |
194 | const struct swap_super_block *ssb = |
195 | (const struct swap_super_block *)buf; |
196 | |
197 | if (!memcmp(ssb->magic, SWAP_MAGIC_1, SWAP_MAGIC_L) || |
198 | !memcmp(ssb->magic, SWAP_MAGIC_2, SWAP_MAGIC_L)) { |
199 | *blocks = 0; |
200 | return 1; |
201 | } |
202 | return 0; |
203 | } |
204 | |
205 | static int suspend_image(const void *buf, unsigned long long *blocks) |
206 | { |
207 | const struct swap_super_block *ssb = |
208 | (const struct swap_super_block *)buf; |
209 | |
210 | if (!memcmp(ssb->magic, SUSP_MAGIC_1, SUSP_MAGIC_L) || |
211 | !memcmp(ssb->magic, SUSP_MAGIC_2, SUSP_MAGIC_L) || |
212 | !memcmp(ssb->magic, SUSP_MAGIC_U, SUSP_MAGIC_L)) { |
213 | *blocks = 0; |
214 | return 1; |
215 | } |
216 | return 0; |
217 | } |
218 | |
219 | static int lvm2_image(const void *buf, unsigned long long *blocks) |
220 | { |
221 | const struct lvm2_super_block *lsb; |
222 | int i; |
223 | |
224 | /* We must check every 512 byte sector */ |
225 | for (i = 0; i < BLOCK_SIZE; i += 0x200) { |
226 | lsb = (const struct lvm2_super_block *)(buf + i); |
227 | |
228 | if (!memcmp(lsb->magic, LVM2_MAGIC, LVM2_MAGIC_L) && |
229 | !memcmp(lsb->type, LVM2_TYPE, LVM2_TYPE_L)) { |
230 | /* This is just one of possibly many PV's */ |
231 | *blocks = 0; |
232 | return 1; |
233 | } |
234 | } |
235 | |
236 | return 0; |
237 | } |
238 | |
239 | static int iso_image(const void *buf, unsigned long long *blocks) |
240 | { |
241 | const struct iso_volume_descriptor *isovd = |
242 | (const struct iso_volume_descriptor *)buf; |
243 | const struct iso_hs_volume_descriptor *isohsvd = |
244 | (const struct iso_hs_volume_descriptor *)buf; |
245 | |
246 | if (!memcmp(isovd->id, ISO_MAGIC, ISO_MAGIC_L) || |
247 | !memcmp(isohsvd->id, ISO_HS_MAGIC, ISO_HS_MAGIC_L)) { |
248 | *blocks = 0; |
249 | return 1; |
250 | } |
251 | return 0; |
252 | } |
253 | |
254 | struct imagetype { |
255 | off_t block; |
256 | const char name[12]; |
257 | int (*identify) (const void *, unsigned long long *); |
258 | }; |
259 | |
260 | /* |
261 | * Note: |
262 | * |
263 | * Minix test needs to come after ext3/ext2, since it's possible for |
264 | * ext3/ext2 to look like minix by pure random chance. |
265 | * |
266 | * LVM comes after all other filesystems since it's possible |
267 | * that an old lvm signature is left on the disk if pvremove |
268 | * is not used before creating the new fs. |
269 | * |
270 | * The same goes for LUKS as for LVM. |
271 | */ |
272 | static struct imagetype images[] = { |
273 | {0, "gzip", gzip_image}, |
274 | {0, "cramfs", cramfs_image}, |
275 | {0, "romfs", romfs_image}, |
276 | {0, "xfs", xfs_image}, |
277 | {1, "ext3", ext3_image}, |
278 | {1, "ext2", ext2_image}, |
279 | {1, "minix", minix_image}, |
280 | {8, "reiserfs", reiserfs_image}, |
281 | {64, "reiserfs", reiserfs_image}, |
282 | {32, "jfs", jfs_image}, |
283 | {32, "iso9660", iso_image}, |
284 | {0, "luks", luks_image}, |
285 | {0, "lvm2", lvm2_image}, |
286 | {1, "lvm2", lvm2_image}, |
287 | {-1, "swap", swap_image}, |
288 | {-1, "suspend", suspend_image}, |
289 | {0, "", NULL} |
290 | }; |
291 | |
292 | int identify_fs(int fd, const char **fstype, |
293 | unsigned long long *bytes, off_t offset) |
294 | { |
295 | uint64_t buf[BLOCK_SIZE >> 3]; /* 64-bit worst case alignment */ |
296 | off_t cur_block = (off_t) - 1; |
297 | struct imagetype *ip; |
298 | int ret; |
299 | unsigned long long dummy; |
300 | |
301 | if (!bytes) |
302 | bytes = &dummy; |
303 | |
304 | *fstype = NULL; |
305 | *bytes = 0; |
306 | |
307 | for (ip = images; ip->identify; ip++) { |
308 | /* Hack for swap, which apparently is dependent on page size */ |
309 | if (ip->block == -1) |
310 | ip->block = SWAP_OFFSET(); |
311 | |
312 | if (cur_block != ip->block) { |
313 | /* |
314 | * Read block. |
315 | */ |
316 | cur_block = ip->block; |
317 | ret = pread(fd, buf, BLOCK_SIZE, |
318 | offset + cur_block * BLOCK_SIZE); |
319 | if (ret != BLOCK_SIZE) |
320 | return -1; /* error */ |
321 | } |
322 | |
323 | if (ip->identify(buf, bytes)) { |
324 | *fstype = ip->name; |
325 | return 0; |
326 | } |
327 | } |
328 | |
329 | return 1; /* Unknown filesystem */ |
330 | } |