Magellan Linux

Annotation of /trunk/mkinitrd-magellan/klibc/usr/kinit/fstype/fstype.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (hide 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)
-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 niro 532 /*
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     }