probe.c 20 KB

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