Annotation of /trunk/mkinitrd-magellan/busybox/e2fsprogs/old_e2fsprogs/blkid/probe.c
Parent Directory | Revision Log
Revision 984 -
(hide annotations)
(download)
Sun May 30 11:32:42 2010 UTC (14 years ago) by niro
File MIME type: text/plain
File size: 20199 byte(s)
Sun May 30 11:32:42 2010 UTC (14 years ago) by niro
File MIME type: text/plain
File size: 20199 byte(s)
-updated to busybox-1.16.1 and enabled blkid/uuid support in default config
1 | niro | 532 | /* vi: set sw=4 ts=4: */ |
2 | /* | ||
3 | * probe.c - identify a block device by its contents, and return a dev | ||
4 | * struct with the details | ||
5 | * | ||
6 | * Copyright (C) 1999 by Andries Brouwer | ||
7 | * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o | ||
8 | * Copyright (C) 2001 by Andreas Dilger | ||
9 | * | ||
10 | * %Begin-Header% | ||
11 | * This file may be redistributed under the terms of the | ||
12 | * GNU Lesser General Public License. | ||
13 | * %End-Header% | ||
14 | */ | ||
15 | |||
16 | #include <stdio.h> | ||
17 | #include <string.h> | ||
18 | #include <stdlib.h> | ||
19 | #include <unistd.h> | ||
20 | #include <fcntl.h> | ||
21 | #include <sys/types.h> | ||
22 | #ifdef HAVE_SYS_STAT_H | ||
23 | #include <sys/stat.h> | ||
24 | #endif | ||
25 | #ifdef HAVE_SYS_MKDEV_H | ||
26 | #include <sys/mkdev.h> | ||
27 | #endif | ||
28 | #ifdef HAVE_ERRNO_H | ||
29 | #include <errno.h> | ||
30 | #endif | ||
31 | #include "blkidP.h" | ||
32 | #include "../uuid/uuid.h" | ||
33 | #include "probe.h" | ||
34 | |||
35 | /* | ||
36 | * This is a special case code to check for an MDRAID device. We do | ||
37 | * this special since it requires checking for a superblock at the end | ||
38 | * of the device. | ||
39 | */ | ||
40 | static int check_mdraid(int fd, unsigned char *ret_uuid) | ||
41 | { | ||
42 | struct mdp_superblock_s *md; | ||
43 | blkid_loff_t offset; | ||
44 | char buf[4096]; | ||
45 | |||
46 | if (fd < 0) | ||
47 | return -BLKID_ERR_PARAM; | ||
48 | |||
49 | offset = (blkid_get_dev_size(fd) & ~((blkid_loff_t)65535)) - 65536; | ||
50 | |||
51 | if (blkid_llseek(fd, offset, 0) < 0 || | ||
52 | read(fd, buf, 4096) != 4096) | ||
53 | return -BLKID_ERR_IO; | ||
54 | |||
55 | /* Check for magic number */ | ||
56 | if (memcmp("\251+N\374", buf, 4)) | ||
57 | return -BLKID_ERR_PARAM; | ||
58 | |||
59 | if (!ret_uuid) | ||
60 | return 0; | ||
61 | *ret_uuid = 0; | ||
62 | |||
63 | /* The MD UUID is not contiguous in the superblock, make it so */ | ||
64 | md = (struct mdp_superblock_s *)buf; | ||
65 | if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) { | ||
66 | memcpy(ret_uuid, &md->set_uuid0, 4); | ||
67 | memcpy(ret_uuid, &md->set_uuid1, 12); | ||
68 | } | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static void set_uuid(blkid_dev dev, uuid_t uuid) | ||
73 | { | ||
74 | char str[37]; | ||
75 | |||
76 | if (!uuid_is_null(uuid)) { | ||
77 | uuid_unparse(uuid, str); | ||
78 | blkid_set_tag(dev, "UUID", str, sizeof(str)); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | static void get_ext2_info(blkid_dev dev, unsigned char *buf) | ||
83 | { | ||
84 | struct ext2_super_block *es = (struct ext2_super_block *) buf; | ||
85 | const char *label = 0; | ||
86 | |||
87 | DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n", | ||
88 | blkid_le32(es->s_feature_compat), | ||
89 | blkid_le32(es->s_feature_incompat), | ||
90 | blkid_le32(es->s_feature_ro_compat))); | ||
91 | |||
92 | if (strlen(es->s_volume_name)) | ||
93 | label = es->s_volume_name; | ||
94 | blkid_set_tag(dev, "LABEL", label, sizeof(es->s_volume_name)); | ||
95 | |||
96 | set_uuid(dev, es->s_uuid); | ||
97 | } | ||
98 | |||
99 | static int probe_ext3(int fd __BLKID_ATTR((unused)), | ||
100 | blkid_cache cache __BLKID_ATTR((unused)), | ||
101 | blkid_dev dev, | ||
102 | const struct blkid_magic *id __BLKID_ATTR((unused)), | ||
103 | unsigned char *buf) | ||
104 | { | ||
105 | struct ext2_super_block *es; | ||
106 | |||
107 | es = (struct ext2_super_block *)buf; | ||
108 | |||
109 | /* Distinguish between jbd and ext2/3 fs */ | ||
110 | if (blkid_le32(es->s_feature_incompat) & | ||
111 | EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) | ||
112 | return -BLKID_ERR_PARAM; | ||
113 | |||
114 | /* Distinguish between ext3 and ext2 */ | ||
115 | if (!(blkid_le32(es->s_feature_compat) & | ||
116 | EXT3_FEATURE_COMPAT_HAS_JOURNAL)) | ||
117 | return -BLKID_ERR_PARAM; | ||
118 | |||
119 | get_ext2_info(dev, buf); | ||
120 | |||
121 | blkid_set_tag(dev, "SEC_TYPE", "ext2", sizeof("ext2")); | ||
122 | |||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static int probe_ext2(int fd __BLKID_ATTR((unused)), | ||
127 | blkid_cache cache __BLKID_ATTR((unused)), | ||
128 | blkid_dev dev, | ||
129 | const struct blkid_magic *id __BLKID_ATTR((unused)), | ||
130 | unsigned char *buf) | ||
131 | { | ||
132 | struct ext2_super_block *es; | ||
133 | |||
134 | es = (struct ext2_super_block *)buf; | ||
135 | |||
136 | /* Distinguish between jbd and ext2/3 fs */ | ||
137 | if (blkid_le32(es->s_feature_incompat) & | ||
138 | EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) | ||
139 | return -BLKID_ERR_PARAM; | ||
140 | |||
141 | get_ext2_info(dev, buf); | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | static int probe_jbd(int fd __BLKID_ATTR((unused)), | ||
147 | blkid_cache cache __BLKID_ATTR((unused)), | ||
148 | blkid_dev dev, | ||
149 | const struct blkid_magic *id __BLKID_ATTR((unused)), | ||
150 | unsigned char *buf) | ||
151 | { | ||
152 | struct ext2_super_block *es = (struct ext2_super_block *) buf; | ||
153 | |||
154 | if (!(blkid_le32(es->s_feature_incompat) & | ||
155 | EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) | ||
156 | return -BLKID_ERR_PARAM; | ||
157 | |||
158 | get_ext2_info(dev, buf); | ||
159 | |||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | static int probe_vfat(int fd __BLKID_ATTR((unused)), | ||
164 | blkid_cache cache __BLKID_ATTR((unused)), | ||
165 | blkid_dev dev, | ||
166 | const struct blkid_magic *id __BLKID_ATTR((unused)), | ||
167 | unsigned char *buf) | ||
168 | { | ||
169 | struct vfat_super_block *vs; | ||
170 | char serno[10]; | ||
171 | const char *label = 0; | ||
172 | int label_len = 0; | ||
173 | |||
174 | vs = (struct vfat_super_block *)buf; | ||
175 | |||
176 | if (strncmp(vs->vs_label, "NO NAME", 7)) { | ||
177 | char *end = vs->vs_label + sizeof(vs->vs_label) - 1; | ||
178 | |||
179 | while (*end == ' ' && end >= vs->vs_label) | ||
180 | --end; | ||
181 | if (end >= vs->vs_label) { | ||
182 | label = vs->vs_label; | ||
183 | label_len = end - vs->vs_label + 1; | ||
184 | } | ||
185 | } | ||
186 | |||
187 | /* We can't just print them as %04X, because they are unaligned */ | ||
188 | sprintf(serno, "%02X%02X-%02X%02X", vs->vs_serno[3], vs->vs_serno[2], | ||
189 | vs->vs_serno[1], vs->vs_serno[0]); | ||
190 | blkid_set_tag(dev, "LABEL", label, label_len); | ||
191 | blkid_set_tag(dev, "UUID", serno, sizeof(serno)); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | static int probe_msdos(int fd __BLKID_ATTR((unused)), | ||
197 | blkid_cache cache __BLKID_ATTR((unused)), | ||
198 | blkid_dev dev, | ||
199 | const struct blkid_magic *id __BLKID_ATTR((unused)), | ||
200 | unsigned char *buf) | ||
201 | { | ||
202 | struct msdos_super_block *ms = (struct msdos_super_block *) buf; | ||
203 | char serno[10]; | ||
204 | const char *label = 0; | ||
205 | int label_len = 0; | ||
206 | |||
207 | if (strncmp(ms->ms_label, "NO NAME", 7)) { | ||
208 | char *end = ms->ms_label + sizeof(ms->ms_label) - 1; | ||
209 | |||
210 | while (*end == ' ' && end >= ms->ms_label) | ||
211 | --end; | ||
212 | if (end >= ms->ms_label) { | ||
213 | label = ms->ms_label; | ||
214 | label_len = end - ms->ms_label + 1; | ||
215 | } | ||
216 | } | ||
217 | |||
218 | /* We can't just print them as %04X, because they are unaligned */ | ||
219 | sprintf(serno, "%02X%02X-%02X%02X", ms->ms_serno[3], ms->ms_serno[2], | ||
220 | ms->ms_serno[1], ms->ms_serno[0]); | ||
221 | blkid_set_tag(dev, "UUID", serno, 0); | ||
222 | blkid_set_tag(dev, "LABEL", label, label_len); | ||
223 | blkid_set_tag(dev, "SEC_TYPE", "msdos", sizeof("msdos")); | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static int probe_xfs(int fd __BLKID_ATTR((unused)), | ||
229 | blkid_cache cache __BLKID_ATTR((unused)), | ||
230 | blkid_dev dev, | ||
231 | const struct blkid_magic *id __BLKID_ATTR((unused)), | ||
232 | unsigned char *buf) | ||
233 | { | ||
234 | struct xfs_super_block *xs; | ||
235 | const char *label = 0; | ||
236 | |||
237 | xs = (struct xfs_super_block *)buf; | ||
238 | |||
239 | if (strlen(xs->xs_fname)) | ||
240 | label = xs->xs_fname; | ||
241 | blkid_set_tag(dev, "LABEL", label, sizeof(xs->xs_fname)); | ||
242 | set_uuid(dev, xs->xs_uuid); | ||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static int probe_reiserfs(int fd __BLKID_ATTR((unused)), | ||
247 | blkid_cache cache __BLKID_ATTR((unused)), | ||
248 | blkid_dev dev, | ||
249 | const struct blkid_magic *id, unsigned char *buf) | ||
250 | { | ||
251 | struct reiserfs_super_block *rs = (struct reiserfs_super_block *) buf; | ||
252 | unsigned int blocksize; | ||
253 | const char *label = 0; | ||
254 | |||
255 | blocksize = blkid_le16(rs->rs_blocksize); | ||
256 | |||
257 | /* If the superblock is inside the journal, we have the wrong one */ | ||
258 | if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block)) | ||
259 | return -BLKID_ERR_BIG; | ||
260 | |||
261 | /* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */ | ||
262 | if (!strcmp(id->bim_magic, "ReIsEr2Fs") || | ||
263 | !strcmp(id->bim_magic, "ReIsEr3Fs")) { | ||
264 | if (strlen(rs->rs_label)) | ||
265 | label = rs->rs_label; | ||
266 | set_uuid(dev, rs->rs_uuid); | ||
267 | } | ||
268 | blkid_set_tag(dev, "LABEL", label, sizeof(rs->rs_label)); | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static int probe_jfs(int fd __BLKID_ATTR((unused)), | ||
274 | blkid_cache cache __BLKID_ATTR((unused)), | ||
275 | blkid_dev dev, | ||
276 | const struct blkid_magic *id __BLKID_ATTR((unused)), | ||
277 | unsigned char *buf) | ||
278 | { | ||
279 | struct jfs_super_block *js; | ||
280 | const char *label = 0; | ||
281 | |||
282 | js = (struct jfs_super_block *)buf; | ||
283 | |||
284 | if (strlen((char *) js->js_label)) | ||
285 | label = (char *) js->js_label; | ||
286 | blkid_set_tag(dev, "LABEL", label, sizeof(js->js_label)); | ||
287 | set_uuid(dev, js->js_uuid); | ||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static int probe_romfs(int fd __BLKID_ATTR((unused)), | ||
292 | blkid_cache cache __BLKID_ATTR((unused)), | ||
293 | blkid_dev dev, | ||
294 | const struct blkid_magic *id __BLKID_ATTR((unused)), | ||
295 | unsigned char *buf) | ||
296 | { | ||
297 | struct romfs_super_block *ros; | ||
298 | const char *label = 0; | ||
299 | |||
300 | ros = (struct romfs_super_block *)buf; | ||
301 | |||
302 | if (strlen((char *) ros->ros_volume)) | ||
303 | label = (char *) ros->ros_volume; | ||
304 | blkid_set_tag(dev, "LABEL", label, 0); | ||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static int probe_cramfs(int fd __BLKID_ATTR((unused)), | ||
309 | blkid_cache cache __BLKID_ATTR((unused)), | ||
310 | blkid_dev dev, | ||
311 | const struct blkid_magic *id __BLKID_ATTR((unused)), | ||
312 | unsigned char *buf) | ||
313 | { | ||
314 | struct cramfs_super_block *csb; | ||
315 | const char *label = 0; | ||
316 | |||
317 | csb = (struct cramfs_super_block *)buf; | ||
318 | |||
319 | if (strlen((char *) csb->name)) | ||
320 | label = (char *) csb->name; | ||
321 | blkid_set_tag(dev, "LABEL", label, 0); | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static int probe_swap0(int fd __BLKID_ATTR((unused)), | ||
326 | blkid_cache cache __BLKID_ATTR((unused)), | ||
327 | blkid_dev dev, | ||
328 | const struct blkid_magic *id __BLKID_ATTR((unused)), | ||
329 | unsigned char *buf __BLKID_ATTR((unused))) | ||
330 | { | ||
331 | blkid_set_tag(dev, "UUID", 0, 0); | ||
332 | blkid_set_tag(dev, "LABEL", 0, 0); | ||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | static int probe_swap1(int fd, | ||
337 | blkid_cache cache __BLKID_ATTR((unused)), | ||
338 | blkid_dev dev, | ||
339 | const struct blkid_magic *id __BLKID_ATTR((unused)), | ||
340 | unsigned char *buf __BLKID_ATTR((unused))) | ||
341 | { | ||
342 | struct swap_id_block *sws; | ||
343 | |||
344 | probe_swap0(fd, cache, dev, id, buf); | ||
345 | /* | ||
346 | * Version 1 swap headers are always located at offset of 1024 | ||
347 | * bytes, although the swap signature itself is located at the | ||
348 | * end of the page (which may vary depending on hardware | ||
349 | * pagesize). | ||
350 | */ | ||
351 | if (lseek(fd, 1024, SEEK_SET) < 0) return 1; | ||
352 | sws = xmalloc(1024); | ||
353 | if (read(fd, sws, 1024) != 1024) { | ||
354 | free(sws); | ||
355 | return 1; | ||
356 | } | ||
357 | |||
358 | /* arbitrary sanity check.. is there any garbage down there? */ | ||
359 | if (sws->sws_pad[32] == 0 && sws->sws_pad[33] == 0) { | ||
360 | if (sws->sws_volume[0]) | ||
361 | blkid_set_tag(dev, "LABEL", (const char*)sws->sws_volume, | ||
362 | sizeof(sws->sws_volume)); | ||
363 | if (sws->sws_uuid[0]) | ||
364 | set_uuid(dev, sws->sws_uuid); | ||
365 | } | ||
366 | free(sws); | ||
367 | |||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static const char | ||
372 | * const udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02", | ||
373 | "NSR03", "TEA01", 0 }; | ||
374 | |||
375 | static int probe_udf(int fd, blkid_cache cache __BLKID_ATTR((unused)), | ||
376 | blkid_dev dev __BLKID_ATTR((unused)), | ||
377 | const struct blkid_magic *id __BLKID_ATTR((unused)), | ||
378 | unsigned char *buf __BLKID_ATTR((unused))) | ||
379 | { | ||
380 | int j, bs; | ||
381 | struct iso_volume_descriptor isosb; | ||
382 | niro | 816 | const char *const *m; |
383 | niro | 532 | |
384 | /* determine the block size by scanning in 2K increments | ||
385 | (block sizes larger than 2K will be null padded) */ | ||
386 | for (bs = 1; bs < 16; bs++) { | ||
387 | lseek(fd, bs*2048+32768, SEEK_SET); | ||
388 | if (read(fd, (char *)&isosb, sizeof(isosb)) != sizeof(isosb)) | ||
389 | return 1; | ||
390 | if (isosb.id[0]) | ||
391 | break; | ||
392 | } | ||
393 | |||
394 | /* Scan up to another 64 blocks looking for additional VSD's */ | ||
395 | for (j = 1; j < 64; j++) { | ||
396 | if (j > 1) { | ||
397 | lseek(fd, j*bs*2048+32768, SEEK_SET); | ||
398 | if (read(fd, (char *)&isosb, sizeof(isosb)) | ||
399 | != sizeof(isosb)) | ||
400 | return 1; | ||
401 | } | ||
402 | /* If we find NSR0x then call it udf: | ||
403 | NSR01 for UDF 1.00 | ||
404 | NSR02 for UDF 1.50 | ||
405 | NSR03 for UDF 2.00 */ | ||
406 | if (!strncmp(isosb.id, "NSR0", 4)) | ||
407 | return 0; | ||
408 | for (m = udf_magic; *m; m++) | ||
409 | if (!strncmp(*m, isosb.id, 5)) | ||
410 | break; | ||
411 | if (*m == 0) | ||
412 | return 1; | ||
413 | } | ||
414 | return 1; | ||
415 | } | ||
416 | |||
417 | static int probe_ocfs(int fd __BLKID_ATTR((unused)), | ||
418 | blkid_cache cache __BLKID_ATTR((unused)), | ||
419 | blkid_dev dev, | ||
420 | const struct blkid_magic *id __BLKID_ATTR((unused)), | ||
421 | unsigned char *buf) | ||
422 | { | ||
423 | struct ocfs_volume_header ovh; | ||
424 | struct ocfs_volume_label ovl; | ||
425 | __u32 major; | ||
426 | |||
427 | memcpy(&ovh, buf, sizeof(ovh)); | ||
428 | memcpy(&ovl, buf+512, sizeof(ovl)); | ||
429 | |||
430 | major = ocfsmajor(ovh); | ||
431 | if (major == 1) | ||
432 | niro | 816 | blkid_set_tag(dev, "SEC_TYPE", "ocfs1", sizeof("ocfs1")); |
433 | niro | 532 | else if (major >= 9) |
434 | niro | 816 | blkid_set_tag(dev, "SEC_TYPE", "ntocfs", sizeof("ntocfs")); |
435 | niro | 532 | |
436 | blkid_set_tag(dev, "LABEL", (const char*)ovl.label, ocfslabellen(ovl)); | ||
437 | blkid_set_tag(dev, "MOUNT", (const char*)ovh.mount, ocfsmountlen(ovh)); | ||
438 | set_uuid(dev, ovl.vol_id); | ||
439 | return 0; | ||
440 | } | ||
441 | |||
442 | static int probe_ocfs2(int fd __BLKID_ATTR((unused)), | ||
443 | blkid_cache cache __BLKID_ATTR((unused)), | ||
444 | blkid_dev dev, | ||
445 | const struct blkid_magic *id __BLKID_ATTR((unused)), | ||
446 | unsigned char *buf) | ||
447 | { | ||
448 | struct ocfs2_super_block *osb; | ||
449 | |||
450 | osb = (struct ocfs2_super_block *)buf; | ||
451 | |||
452 | blkid_set_tag(dev, "LABEL", (const char*)osb->s_label, sizeof(osb->s_label)); | ||
453 | set_uuid(dev, osb->s_uuid); | ||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | static int probe_oracleasm(int fd __BLKID_ATTR((unused)), | ||
458 | blkid_cache cache __BLKID_ATTR((unused)), | ||
459 | blkid_dev dev, | ||
460 | const struct blkid_magic *id __BLKID_ATTR((unused)), | ||
461 | unsigned char *buf) | ||
462 | { | ||
463 | struct oracle_asm_disk_label *dl; | ||
464 | |||
465 | dl = (struct oracle_asm_disk_label *)buf; | ||
466 | |||
467 | blkid_set_tag(dev, "LABEL", dl->dl_id, sizeof(dl->dl_id)); | ||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | /* | ||
472 | * BLKID_BLK_OFFS is at least as large as the highest bim_kboff defined | ||
473 | * in the type_array table below + bim_kbalign. | ||
474 | * | ||
475 | * When probing for a lot of magics, we handle everything in 1kB buffers so | ||
476 | * that we don't have to worry about reading each combination of block sizes. | ||
477 | */ | ||
478 | #define BLKID_BLK_OFFS 64 /* currently reiserfs */ | ||
479 | |||
480 | /* | ||
481 | * Various filesystem magics that we can check for. Note that kboff and | ||
482 | * sboff are in kilobytes and bytes respectively. All magics are in | ||
483 | * byte strings so we don't worry about endian issues. | ||
484 | */ | ||
485 | static const struct blkid_magic type_array[] = { | ||
486 | /* type kboff sboff len magic probe */ | ||
487 | { "oracleasm", 0, 32, 8, "ORCLDISK", probe_oracleasm }, | ||
488 | { "ntfs", 0, 3, 8, "NTFS ", 0 }, | ||
489 | { "jbd", 1, 0x38, 2, "\123\357", probe_jbd }, | ||
490 | { "ext3", 1, 0x38, 2, "\123\357", probe_ext3 }, | ||
491 | { "ext2", 1, 0x38, 2, "\123\357", probe_ext2 }, | ||
492 | { "reiserfs", 8, 0x34, 8, "ReIsErFs", probe_reiserfs }, | ||
493 | { "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", probe_reiserfs }, | ||
494 | { "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", probe_reiserfs }, | ||
495 | { "reiserfs", 64, 0x34, 8, "ReIsErFs", probe_reiserfs }, | ||
496 | { "reiserfs", 8, 20, 8, "ReIsErFs", probe_reiserfs }, | ||
497 | { "vfat", 0, 0x52, 5, "MSWIN", probe_vfat }, | ||
498 | { "vfat", 0, 0x52, 8, "FAT32 ", probe_vfat }, | ||
499 | { "vfat", 0, 0x36, 5, "MSDOS", probe_msdos }, | ||
500 | { "vfat", 0, 0x36, 8, "FAT16 ", probe_msdos }, | ||
501 | { "vfat", 0, 0x36, 8, "FAT12 ", probe_msdos }, | ||
502 | { "minix", 1, 0x10, 2, "\177\023", 0 }, | ||
503 | { "minix", 1, 0x10, 2, "\217\023", 0 }, | ||
504 | { "minix", 1, 0x10, 2, "\150\044", 0 }, | ||
505 | { "minix", 1, 0x10, 2, "\170\044", 0 }, | ||
506 | { "vxfs", 1, 0, 4, "\365\374\001\245", 0 }, | ||
507 | { "xfs", 0, 0, 4, "XFSB", probe_xfs }, | ||
508 | { "romfs", 0, 0, 8, "-rom1fs-", probe_romfs }, | ||
509 | { "bfs", 0, 0, 4, "\316\372\173\033", 0 }, | ||
510 | { "cramfs", 0, 0, 4, "E=\315\050", probe_cramfs }, | ||
511 | { "qnx4", 0, 4, 6, "QNX4FS", 0 }, | ||
512 | { "udf", 32, 1, 5, "BEA01", probe_udf }, | ||
513 | { "udf", 32, 1, 5, "BOOT2", probe_udf }, | ||
514 | { "udf", 32, 1, 5, "CD001", probe_udf }, | ||
515 | { "udf", 32, 1, 5, "CDW02", probe_udf }, | ||
516 | { "udf", 32, 1, 5, "NSR02", probe_udf }, | ||
517 | { "udf", 32, 1, 5, "NSR03", probe_udf }, | ||
518 | { "udf", 32, 1, 5, "TEA01", probe_udf }, | ||
519 | { "iso9660", 32, 1, 5, "CD001", 0 }, | ||
520 | { "iso9660", 32, 9, 5, "CDROM", 0 }, | ||
521 | { "jfs", 32, 0, 4, "JFS1", probe_jfs }, | ||
522 | { "hfs", 1, 0, 2, "BD", 0 }, | ||
523 | { "ufs", 8, 0x55c, 4, "T\031\001\000", 0 }, | ||
524 | { "hpfs", 8, 0, 4, "I\350\225\371", 0 }, | ||
525 | { "sysv", 0, 0x3f8, 4, "\020~\030\375", 0 }, | ||
526 | { "swap", 0, 0xff6, 10, "SWAP-SPACE", probe_swap0 }, | ||
527 | { "swap", 0, 0xff6, 10, "SWAPSPACE2", probe_swap1 }, | ||
528 | { "swap", 0, 0x1ff6, 10, "SWAP-SPACE", probe_swap0 }, | ||
529 | { "swap", 0, 0x1ff6, 10, "SWAPSPACE2", probe_swap1 }, | ||
530 | { "swap", 0, 0x3ff6, 10, "SWAP-SPACE", probe_swap0 }, | ||
531 | { "swap", 0, 0x3ff6, 10, "SWAPSPACE2", probe_swap1 }, | ||
532 | { "swap", 0, 0x7ff6, 10, "SWAP-SPACE", probe_swap0 }, | ||
533 | { "swap", 0, 0x7ff6, 10, "SWAPSPACE2", probe_swap1 }, | ||
534 | { "swap", 0, 0xfff6, 10, "SWAP-SPACE", probe_swap0 }, | ||
535 | { "swap", 0, 0xfff6, 10, "SWAPSPACE2", probe_swap1 }, | ||
536 | { "ocfs", 0, 8, 9, "OracleCFS", probe_ocfs }, | ||
537 | { "ocfs2", 1, 0, 6, "OCFSV2", probe_ocfs2 }, | ||
538 | { "ocfs2", 2, 0, 6, "OCFSV2", probe_ocfs2 }, | ||
539 | { "ocfs2", 4, 0, 6, "OCFSV2", probe_ocfs2 }, | ||
540 | { "ocfs2", 8, 0, 6, "OCFSV2", probe_ocfs2 }, | ||
541 | { NULL, 0, 0, 0, NULL, NULL } | ||
542 | }; | ||
543 | |||
544 | /* | ||
545 | * Verify that the data in dev is consistent with what is on the actual | ||
546 | * block device (using the devname field only). Normally this will be | ||
547 | * called when finding items in the cache, but for long running processes | ||
548 | * is also desirable to revalidate an item before use. | ||
549 | * | ||
550 | * If we are unable to revalidate the data, we return the old data and | ||
551 | * do not set the BLKID_BID_FL_VERIFIED flag on it. | ||
552 | */ | ||
553 | blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev) | ||
554 | { | ||
555 | const struct blkid_magic *id; | ||
556 | unsigned char *bufs[BLKID_BLK_OFFS + 1], *buf; | ||
557 | const char *type; | ||
558 | struct stat st; | ||
559 | time_t diff, now; | ||
560 | int fd, idx; | ||
561 | |||
562 | if (!dev) | ||
563 | return NULL; | ||
564 | |||
565 | niro | 984 | now = time(NULL); |
566 | niro | 532 | diff = now - dev->bid_time; |
567 | |||
568 | if ((now < dev->bid_time) || | ||
569 | (diff < BLKID_PROBE_MIN) || | ||
570 | (dev->bid_flags & BLKID_BID_FL_VERIFIED && | ||
571 | diff < BLKID_PROBE_INTERVAL)) | ||
572 | return dev; | ||
573 | |||
574 | DBG(DEBUG_PROBE, | ||
575 | printf("need to revalidate %s (time since last check %lu)\n", | ||
576 | dev->bid_name, diff)); | ||
577 | |||
578 | if (((fd = open(dev->bid_name, O_RDONLY)) < 0) || | ||
579 | (fstat(fd, &st) < 0)) { | ||
580 | if (errno == ENXIO || errno == ENODEV || errno == ENOENT) { | ||
581 | blkid_free_dev(dev); | ||
582 | return NULL; | ||
583 | } | ||
584 | /* We don't have read permission, just return cache data. */ | ||
585 | DBG(DEBUG_PROBE, | ||
586 | printf("returning unverified data for %s\n", | ||
587 | dev->bid_name)); | ||
588 | return dev; | ||
589 | } | ||
590 | |||
591 | memset(bufs, 0, sizeof(bufs)); | ||
592 | |||
593 | /* | ||
594 | * Iterate over the type array. If we already know the type, | ||
595 | * then try that first. If it doesn't work, then blow away | ||
596 | * the type information, and try again. | ||
597 | * | ||
598 | */ | ||
599 | try_again: | ||
600 | type = 0; | ||
601 | if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) { | ||
602 | uuid_t uuid; | ||
603 | |||
604 | if (check_mdraid(fd, uuid) == 0) { | ||
605 | set_uuid(dev, uuid); | ||
606 | type = "mdraid"; | ||
607 | goto found_type; | ||
608 | } | ||
609 | } | ||
610 | for (id = type_array; id->bim_type; id++) { | ||
611 | if (dev->bid_type && | ||
612 | strcmp(id->bim_type, dev->bid_type)) | ||
613 | continue; | ||
614 | |||
615 | idx = id->bim_kboff + (id->bim_sboff >> 10); | ||
616 | if (idx > BLKID_BLK_OFFS || idx < 0) | ||
617 | continue; | ||
618 | buf = bufs[idx]; | ||
619 | if (!buf) { | ||
620 | if (lseek(fd, idx << 10, SEEK_SET) < 0) | ||
621 | continue; | ||
622 | |||
623 | buf = xmalloc(1024); | ||
624 | |||
625 | if (read(fd, buf, 1024) != 1024) { | ||
626 | free(buf); | ||
627 | continue; | ||
628 | } | ||
629 | bufs[idx] = buf; | ||
630 | } | ||
631 | |||
632 | if (memcmp(id->bim_magic, buf + (id->bim_sboff&0x3ff), | ||
633 | id->bim_len)) | ||
634 | continue; | ||
635 | |||
636 | if ((id->bim_probe == NULL) || | ||
637 | (id->bim_probe(fd, cache, dev, id, buf) == 0)) { | ||
638 | type = id->bim_type; | ||
639 | goto found_type; | ||
640 | } | ||
641 | } | ||
642 | |||
643 | if (!id->bim_type && dev->bid_type) { | ||
644 | /* | ||
645 | * Zap the device filesystem type and try again | ||
646 | */ | ||
647 | blkid_set_tag(dev, "TYPE", 0, 0); | ||
648 | blkid_set_tag(dev, "SEC_TYPE", 0, 0); | ||
649 | blkid_set_tag(dev, "LABEL", 0, 0); | ||
650 | blkid_set_tag(dev, "UUID", 0, 0); | ||
651 | goto try_again; | ||
652 | } | ||
653 | |||
654 | if (!dev->bid_type) { | ||
655 | blkid_free_dev(dev); | ||
656 | return NULL; | ||
657 | } | ||
658 | |||
659 | found_type: | ||
660 | if (dev && type) { | ||
661 | dev->bid_devno = st.st_rdev; | ||
662 | niro | 984 | dev->bid_time = time(NULL); |
663 | niro | 532 | dev->bid_flags |= BLKID_BID_FL_VERIFIED; |
664 | cache->bic_flags |= BLKID_BIC_FL_CHANGED; | ||
665 | |||
666 | blkid_set_tag(dev, "TYPE", type, 0); | ||
667 | |||
668 | DBG(DEBUG_PROBE, printf("%s: devno 0x%04llx, type %s\n", | ||
669 | dev->bid_name, st.st_rdev, type)); | ||
670 | } | ||
671 | |||
672 | close(fd); | ||
673 | |||
674 | return dev; | ||
675 | } | ||
676 | |||
677 | int blkid_known_fstype(const char *fstype) | ||
678 | { | ||
679 | const struct blkid_magic *id; | ||
680 | |||
681 | for (id = type_array; id->bim_type; id++) { | ||
682 | if (strcmp(fstype, id->bim_type) == 0) | ||
683 | return 1; | ||
684 | } | ||
685 | return 0; | ||
686 | } | ||
687 | |||
688 | #ifdef TEST_PROGRAM | ||
689 | int main(int argc, char **argv) | ||
690 | { | ||
691 | blkid_dev dev; | ||
692 | blkid_cache cache; | ||
693 | int ret; | ||
694 | |||
695 | blkid_debug_mask = DEBUG_ALL; | ||
696 | if (argc != 2) { | ||
697 | fprintf(stderr, "Usage: %s device\n" | ||
698 | "Probe a single device to determine type\n", argv[0]); | ||
699 | exit(1); | ||
700 | } | ||
701 | if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) { | ||
702 | fprintf(stderr, "%s: error creating cache (%d)\n", | ||
703 | argv[0], ret); | ||
704 | exit(1); | ||
705 | } | ||
706 | dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL); | ||
707 | if (!dev) { | ||
708 | printf("%s: %s has an unsupported type\n", argv[0], argv[1]); | ||
709 | return 1; | ||
710 | } | ||
711 | printf("%s is type %s\n", argv[1], dev->bid_type ? | ||
712 | dev->bid_type : "(null)"); | ||
713 | if (dev->bid_label) | ||
714 | printf("\tlabel is '%s'\n", dev->bid_label); | ||
715 | if (dev->bid_uuid) | ||
716 | printf("\tuuid is %s\n", dev->bid_uuid); | ||
717 | |||
718 | blkid_free_dev(dev); | ||
719 | return 0; | ||
720 | } | ||
721 | #endif |