8 |
* |
* |
9 |
* We currently detect the filesystems listed below in the struct |
* We currently detect the filesystems listed below in the struct |
10 |
* "imagetype images" (in the order they are listed). |
* "imagetype images" (in the order they are listed). |
|
* |
|
|
* MINIX, ext3 and Reiserfs bits are currently untested. |
|
11 |
*/ |
*/ |
12 |
|
|
13 |
#include <sys/types.h> |
#include <sys/types.h> |
14 |
#include <stdio.h> |
#include <stdio.h> |
15 |
|
#include <ctype.h> |
16 |
#include <string.h> |
#include <string.h> |
17 |
#include <unistd.h> |
#include <unistd.h> |
18 |
#include <fcntl.h> |
#include <fcntl.h> |
19 |
#include <endian.h> |
#include <endian.h> |
20 |
#include <netinet/in.h> |
#include <netinet/in.h> |
21 |
|
#include <sys/utsname.h> |
22 |
#include <sys/vfs.h> |
#include <sys/vfs.h> |
23 |
|
|
24 |
#define cpu_to_be32(x) __cpu_to_be32(x) /* Needed by romfs_fs.h */ |
#define cpu_to_be32(x) __cpu_to_be32(x) /* Needed by romfs_fs.h */ |
32 |
#include "luks_fs.h" |
#include "luks_fs.h" |
33 |
#include "lvm2_sb.h" |
#include "lvm2_sb.h" |
34 |
#include "iso9660_sb.h" |
#include "iso9660_sb.h" |
35 |
|
#include "squashfs_fs.h" |
36 |
|
#include "gfs2_fs.h" |
37 |
|
#include "ocfs2_fs.h" |
38 |
|
#include "nilfs_fs.h" |
39 |
|
|
40 |
/* |
/* |
41 |
* Slightly cleaned up version of jfs_superblock to |
* Slightly cleaned up version of jfs_superblock to |
48 |
* Use a cleaned up version. |
* Use a cleaned up version. |
49 |
*/ |
*/ |
50 |
#include "reiserfs_fs.h" |
#include "reiserfs_fs.h" |
51 |
|
#include "reiser4_fs.h" |
52 |
|
|
53 |
#include "fstype.h" |
#include "fstype.h" |
54 |
|
|
112 |
return 0; |
return 0; |
113 |
} |
} |
114 |
|
|
115 |
|
/* |
116 |
|
* Check to see if a filesystem is in /proc/filesystems. |
117 |
|
* Returns 1 if found, 0 if not |
118 |
|
*/ |
119 |
|
static int fs_proc_check(const char *fs_name) |
120 |
|
{ |
121 |
|
FILE *f; |
122 |
|
char buf[80], *cp, *t; |
123 |
|
|
124 |
|
f = fopen("/proc/filesystems", "r"); |
125 |
|
if (!f) |
126 |
|
return (0); |
127 |
|
while (fgets(buf, sizeof(buf), f)) { |
128 |
|
cp = buf; |
129 |
|
if (!isspace(*cp)) { |
130 |
|
while (*cp && !isspace(*cp)) |
131 |
|
cp++; |
132 |
|
} |
133 |
|
while (*cp && isspace(*cp)) |
134 |
|
cp++; |
135 |
|
if ((t = strchr(cp, '\n')) != NULL) |
136 |
|
*t = 0; |
137 |
|
if ((t = strchr(cp, '\t')) != NULL) |
138 |
|
*t = 0; |
139 |
|
if ((t = strchr(cp, ' ')) != NULL) |
140 |
|
*t = 0; |
141 |
|
if (!strcmp(fs_name, cp)) { |
142 |
|
fclose(f); |
143 |
|
return (1); |
144 |
|
} |
145 |
|
} |
146 |
|
fclose(f); |
147 |
|
return (0); |
148 |
|
} |
149 |
|
|
150 |
|
/* |
151 |
|
* Check to see if a filesystem is available as a module |
152 |
|
* Returns 1 if found, 0 if not |
153 |
|
*/ |
154 |
|
static int check_for_modules(const char *fs_name) |
155 |
|
{ |
156 |
|
struct utsname uts; |
157 |
|
FILE *f; |
158 |
|
char buf[1024], *cp, *t; |
159 |
|
int i; |
160 |
|
|
161 |
|
if (uname(&uts)) |
162 |
|
return (0); |
163 |
|
snprintf(buf, sizeof(buf), "/lib/modules/%s/modules.dep", uts.release); |
164 |
|
|
165 |
|
f = fopen(buf, "r"); |
166 |
|
if (!f) |
167 |
|
return (0); |
168 |
|
while (fgets(buf, sizeof(buf), f)) { |
169 |
|
if ((cp = strchr(buf, ':')) != NULL) |
170 |
|
*cp = 0; |
171 |
|
else |
172 |
|
continue; |
173 |
|
if ((cp = strrchr(buf, '/')) != NULL) |
174 |
|
cp++; |
175 |
|
i = strlen(cp); |
176 |
|
if (i > 3) { |
177 |
|
t = cp + i - 3; |
178 |
|
if (!strcmp(t, ".ko")) |
179 |
|
*t = 0; |
180 |
|
} |
181 |
|
if (!strcmp(cp, fs_name)) { |
182 |
|
fclose(f); |
183 |
|
return (1); |
184 |
|
} |
185 |
|
} |
186 |
|
fclose(f); |
187 |
|
return (0); |
188 |
|
} |
189 |
|
|
190 |
|
static int base_ext4_image(const void *buf, unsigned long long *bytes, |
191 |
|
int *test_fs) |
192 |
|
{ |
193 |
|
const struct ext3_super_block *sb = |
194 |
|
(const struct ext3_super_block *)buf; |
195 |
|
|
196 |
|
if (sb->s_magic != __cpu_to_le16(EXT2_SUPER_MAGIC)) |
197 |
|
return 0; |
198 |
|
|
199 |
|
/* |
200 |
|
* For now, ext4 requires a journal -- but this may change |
201 |
|
* soon if we get that patch from Google. :-) |
202 |
|
*/ |
203 |
|
if ((sb->s_feature_compat |
204 |
|
& __cpu_to_le32(EXT3_FEATURE_COMPAT_HAS_JOURNAL)) == 0) |
205 |
|
return 0; |
206 |
|
|
207 |
|
/* There is at least one feature not supported by ext3 */ |
208 |
|
if ((sb->s_feature_incompat |
209 |
|
& __cpu_to_le32(EXT3_FEATURE_INCOMPAT_UNSUPPORTED)) || |
210 |
|
(sb->s_feature_ro_compat |
211 |
|
& __cpu_to_le32(EXT3_FEATURE_RO_COMPAT_UNSUPPORTED))) { |
212 |
|
*bytes = (unsigned long long)__le32_to_cpu(sb->s_blocks_count) |
213 |
|
<< (10 + __le32_to_cpu(sb->s_log_block_size)); |
214 |
|
*test_fs = (sb->s_flags & |
215 |
|
__cpu_to_le32(EXT2_FLAGS_TEST_FILESYS)) != 0; |
216 |
|
return 1; |
217 |
|
} |
218 |
|
return 0; |
219 |
|
} |
220 |
|
|
221 |
|
static int ext4_image(const void *buf, unsigned long long *bytes) |
222 |
|
{ |
223 |
|
int ret, test_fs, ext4dev_present, ext4_present; |
224 |
|
|
225 |
|
ret = base_ext4_image(buf, bytes, &test_fs); |
226 |
|
if (ret == 0) |
227 |
|
return 0; |
228 |
|
ext4dev_present = (fs_proc_check("ext4dev") || |
229 |
|
check_for_modules("ext4dev")); |
230 |
|
ext4_present = (fs_proc_check("ext4") || check_for_modules("ext4")); |
231 |
|
if ((test_fs || !ext4_present) && ext4dev_present) |
232 |
|
return 0; |
233 |
|
return 1; |
234 |
|
} |
235 |
|
|
236 |
|
static int ext4dev_image(const void *buf, unsigned long long *bytes) |
237 |
|
{ |
238 |
|
int ret, test_fs, ext4dev_present, ext4_present; |
239 |
|
|
240 |
|
ret = base_ext4_image(buf, bytes, &test_fs); |
241 |
|
if (ret == 0) |
242 |
|
return 0; |
243 |
|
ext4dev_present = (fs_proc_check("ext4dev") || |
244 |
|
check_for_modules("ext4dev")); |
245 |
|
ext4_present = (fs_proc_check("ext4") || check_for_modules("ext4")); |
246 |
|
if ((!test_fs || !ext4dev_present) && ext4_present) |
247 |
|
return 0; |
248 |
|
return 1; |
249 |
|
} |
250 |
|
|
251 |
static int ext3_image(const void *buf, unsigned long long *bytes) |
static int ext3_image(const void *buf, unsigned long long *bytes) |
252 |
{ |
{ |
253 |
const struct ext3_super_block *sb = |
const struct ext3_super_block *sb = |
294 |
return 0; |
return 0; |
295 |
} |
} |
296 |
|
|
297 |
|
static int reiser4_image(const void *buf, unsigned long long *bytes) |
298 |
|
{ |
299 |
|
const struct reiser4_master_sb *sb = |
300 |
|
(const struct reiser4_master_sb *)buf; |
301 |
|
|
302 |
|
if (memcmp(sb->ms_magic, REISER4_SUPER_MAGIC_STRING, |
303 |
|
sizeof(REISER4_SUPER_MAGIC_STRING) - 1) == 0) { |
304 |
|
*bytes = (unsigned long long) __le32_to_cpu(sb->ms_format) * |
305 |
|
__le32_to_cpu(sb->ms_blksize); |
306 |
|
return 1; |
307 |
|
} |
308 |
|
return 0; |
309 |
|
} |
310 |
|
|
311 |
static int xfs_image(const void *buf, unsigned long long *bytes) |
static int xfs_image(const void *buf, unsigned long long *bytes) |
312 |
{ |
{ |
313 |
const struct xfs_sb *sb = (const struct xfs_sb *)buf; |
const struct xfs_sb *sb = (const struct xfs_sb *)buf; |
325 |
const struct jfs_superblock *sb = (const struct jfs_superblock *)buf; |
const struct jfs_superblock *sb = (const struct jfs_superblock *)buf; |
326 |
|
|
327 |
if (!memcmp(sb->s_magic, JFS_MAGIC, 4)) { |
if (!memcmp(sb->s_magic, JFS_MAGIC, 4)) { |
328 |
*bytes = __le32_to_cpu(sb->s_size); |
*bytes = __le64_to_cpu(sb->s_size) << __le16_to_cpu(sb->s_l2pbsize); |
329 |
return 1; |
return 1; |
330 |
} |
} |
331 |
return 0; |
return 0; |
406 |
return 0; |
return 0; |
407 |
} |
} |
408 |
|
|
409 |
|
static int squashfs_image(const void *buf, unsigned long long *blocks) |
410 |
|
{ |
411 |
|
const struct squashfs_super_block *sb = |
412 |
|
(const struct squashfs_super_block *)buf; |
413 |
|
|
414 |
|
if (sb->s_magic == SQUASHFS_MAGIC |
415 |
|
|| sb->s_magic == SQUASHFS_MAGIC_SWAP |
416 |
|
|| sb->s_magic == SQUASHFS_MAGIC_LZMA |
417 |
|
|| sb->s_magic == SQUASHFS_MAGIC_LZMA_SWAP) { |
418 |
|
*blocks = (unsigned long long) sb->bytes_used; |
419 |
|
return 1; |
420 |
|
} |
421 |
|
return 0; |
422 |
|
} |
423 |
|
|
424 |
|
static int gfs2_image(const void *buf, unsigned long long *bytes) |
425 |
|
{ |
426 |
|
const struct gfs2_sb *sb = |
427 |
|
(const struct gfs2_sb *)buf; |
428 |
|
|
429 |
|
if (__be32_to_cpu(sb->sb_header.mh_magic) == GFS2_MAGIC |
430 |
|
&& (__be32_to_cpu(sb->sb_fs_format) == GFS2_FORMAT_FS |
431 |
|
|| __be32_to_cpu(sb->sb_fs_format) == GFS2_FORMAT_MULTI)) { |
432 |
|
*bytes = 0; /* cpu_to_be32(sb->sb_bsize) * ?; */ |
433 |
|
return 1; |
434 |
|
} |
435 |
|
return 0; |
436 |
|
} |
437 |
|
|
438 |
|
static int ocfs2_image(const void *buf, unsigned long long *bytes) |
439 |
|
{ |
440 |
|
const struct ocfs2_dinode *sb = |
441 |
|
(const struct ocfs2_dinode *)buf; |
442 |
|
|
443 |
|
if (!memcmp(sb->i_signature, OCFS2_SUPER_BLOCK_SIGNATURE, |
444 |
|
sizeof(OCFS2_SUPER_BLOCK_SIGNATURE) - 1)) { |
445 |
|
*bytes = 0; |
446 |
|
return 1; |
447 |
|
} |
448 |
|
return 0; |
449 |
|
} |
450 |
|
|
451 |
|
static int nilfs2_image(const void *buf, unsigned long long *bytes) |
452 |
|
{ |
453 |
|
const struct nilfs_super_block *sb = |
454 |
|
(const struct nilfs_super_block *)buf; |
455 |
|
|
456 |
|
if (sb->s_magic == __cpu_to_le16(NILFS_SUPER_MAGIC) && |
457 |
|
sb->s_rev_level == __cpu_to_le32(2)) { |
458 |
|
*bytes = (unsigned long long)__le64_to_cpu(sb->s_dev_size); |
459 |
|
return 1; |
460 |
|
} |
461 |
|
return 0; |
462 |
|
} |
463 |
|
|
464 |
struct imagetype { |
struct imagetype { |
465 |
off_t block; |
off_t block; |
466 |
const char name[12]; |
const char name[12]; |
484 |
{0, "cramfs", cramfs_image}, |
{0, "cramfs", cramfs_image}, |
485 |
{0, "romfs", romfs_image}, |
{0, "romfs", romfs_image}, |
486 |
{0, "xfs", xfs_image}, |
{0, "xfs", xfs_image}, |
487 |
|
{0, "squashfs", squashfs_image}, |
488 |
|
{1, "ext4dev", ext4dev_image}, |
489 |
|
{1, "ext4", ext4_image}, |
490 |
{1, "ext3", ext3_image}, |
{1, "ext3", ext3_image}, |
491 |
{1, "ext2", ext2_image}, |
{1, "ext2", ext2_image}, |
492 |
{1, "minix", minix_image}, |
{1, "minix", minix_image}, |
493 |
|
{1, "nilfs2", nilfs2_image}, |
494 |
|
{2, "ocfs2", ocfs2_image}, |
495 |
{8, "reiserfs", reiserfs_image}, |
{8, "reiserfs", reiserfs_image}, |
496 |
{64, "reiserfs", reiserfs_image}, |
{64, "reiserfs", reiserfs_image}, |
497 |
|
{64, "reiser4", reiser4_image}, |
498 |
|
{64, "gfs2", gfs2_image}, |
499 |
{32, "jfs", jfs_image}, |
{32, "jfs", jfs_image}, |
500 |
{32, "iso9660", iso_image}, |
{32, "iso9660", iso_image}, |
501 |
{0, "luks", luks_image}, |
{0, "luks", luks_image}, |