probe.c revision e12f2ae74c2eb8997bf13adf8fdd7e7313971eae
1/* 2 * probe.c - identify a block device by its contents, and return a dev 3 * struct with the details 4 * 5 * Copyright (C) 1999 by Andries Brouwer 6 * Copyright (C) 1999, 2000 by Theodore Ts'o 7 * Copyright (C) 2001 by Andreas Dilger 8 * 9 * %Begin-Header% 10 * This file may be redistributed under the terms of the 11 * GNU Lesser General Public License. 12 * %End-Header% 13 */ 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 "blkid/blkid.h" 31#include "uuid/uuid.h" 32#include "probe.h" 33 34/* #define DEBUG_PROBE */ 35#ifdef DEBUG_PROBE 36#define DEB_PROBE(fmt, arg...) printf("probe: " fmt, ## arg) 37#else 38#define DEB_PROBE(fmt, arg...) do {} while (0) 39#endif 40 41/* 42 * Do the required things for instantiating a new device. This is called if 43 * there is nor a probe handler for a filesystem type, and is also called by 44 * the filesystem-specific types to do common initialization tasks. 45 * 46 * The devname, dev_p, and id fields are required. The buf is 47 * a buffer to return superblock data in. 48 */ 49static int probe_default(int fd, blkid_dev **dev_p, const char *devname, 50 struct blkid_magic *id, unsigned char *buf, 51 blkid_loff_t size) 52{ 53 blkid_loff_t offset; 54 blkid_dev *dev; 55 struct stat st; 56 int ret; 57 58 if (!devname || !dev_p || !id || !buf || fd < 0) 59 return -BLKID_ERR_PARAM; 60 61 if (fstat(fd, &st) < 0 || !S_ISBLK(st.st_mode)) 62 return -BLKID_ERR_DEV; 63 64 offset = (blkid_loff_t)id->bim_kboff << 10; 65 if (id->bim_kboff < 0) 66 offset = (size & ~((blkid_loff_t)id->bim_align - 1)) + offset; 67 68 if (blkid_llseek(fd, offset, 0) < 0 || 69 read(fd, buf, id->bim_kbsize << 10) != id->bim_kbsize << 10) 70 return -BLKID_ERR_IO; 71 72 /* Revalidate magic for blkid_validate_devname */ 73 if (memcmp(id->bim_magic, buf + id->bim_sboff, id->bim_len)) 74 return -BLKID_ERR_PARAM; 75 76 dev = blkid_new_dev(); 77 if (!dev) 78 return -BLKID_ERR_MEM; 79 80 dev->bid_name = string_copy(devname); 81 if (!dev->bid_name) { 82 ret = -BLKID_ERR_MEM; 83 goto exit_dev; 84 } 85 86 /* Don't set this until there is no chance of error */ 87 *dev_p = dev; 88 dev->bid_devno = st.st_rdev; 89 dev->bid_devsize = size; 90 dev->bid_time = time(0); 91 dev->bid_flags |= BLKID_BID_FL_VERIFIED; 92 93 if (id->bim_type) 94 blkid_create_tag(dev, NULL, "TYPE", id->bim_type, 95 strlen(id->bim_type)); 96 97 DEB_PROBE("%s: devno 0x%04Lx, type %s\n", devname, 98 st.st_rdev, id->bim_type); 99 100 return 0; 101exit_dev: 102 blkid_free_dev(dev); 103 return ret; 104} 105 106static int probe_ext2(int fd, blkid_dev **dev_p, const char *devname, 107 struct blkid_magic *id, unsigned char *buf, 108 blkid_loff_t size) 109{ 110 blkid_dev *dev; 111 struct ext2_super_block *es; 112 int ret; 113 114 if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0) 115 return ret; 116 117 es = (struct ext2_super_block *)buf; 118 119 DEB_PROBE("size = %Ld, ext2_sb.compat = %08X:%08X:%08X\n", size, 120 le32_to_cpu(es->s_feature_compat), 121 le32_to_cpu(es->s_feature_incompat), 122 le32_to_cpu(es->s_feature_ro_compat)); 123 124 /* Make sure we don't keep re-probing as ext2 for a journaled fs */ 125 if (!strcmp(id->bim_type, "ext2") && 126 (le32_to_cpu(es->s_feature_compat) & 127 EXT3_FEATURE_COMPAT_HAS_JOURNAL || 128 le32_to_cpu(es->s_feature_incompat) & 129 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) { 130 blkid_free_dev(dev); 131 return -BLKID_ERR_PARAM; 132 } 133 134 /* Don't set this until there is no chance of error */ 135 *dev_p = dev; 136 137 dev->bid_size = (blkid_loff_t)le32_to_cpu(es->s_blocks_count) << 138 (le32_to_cpu(es->s_log_block_size) + 10); 139 140 /* This is a safe (minimum) number, as it ignores metadata usage. */ 141 dev->bid_free = (blkid_loff_t)le32_to_cpu(es->s_free_blocks_count) << 142 (le32_to_cpu(es->s_log_block_size) + 10); 143 144 if (strlen(es->s_volume_name)) { 145 blkid_create_tag(dev, NULL, "LABEL", es->s_volume_name, 146 sizeof(es->s_volume_name)); 147 } 148 149 if (!uuid_is_null(es->s_uuid)) { 150 unsigned char uuid[37]; 151 uuid_unparse(es->s_uuid, uuid); 152 blkid_create_tag(dev, NULL, "UUID", uuid, sizeof(uuid)); 153 } 154 155 return 0; 156} 157 158static int probe_jbd(int fd, blkid_dev **dev_p, const char *devname, 159 struct blkid_magic *id, unsigned char *buf, 160 blkid_loff_t size) 161{ 162 blkid_dev *dev; 163 struct ext2_super_block *es; 164 int ret; 165 166 if ((ret = probe_ext2(fd, &dev, devname, id, buf, size)) < 0) 167 return ret; 168 169 es = (struct ext2_super_block *)buf; 170 171 if (!(le32_to_cpu(es->s_feature_incompat) & 172 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) { 173 blkid_free_dev(dev); 174 return -BLKID_ERR_PARAM; 175 } 176 177 /* Don't set this until there is no chance of error */ 178 *dev_p = dev; 179 return 0; 180} 181 182static int probe_ext3(int fd, blkid_dev **dev_p, const char *devname, 183 struct blkid_magic *id, unsigned char *buf, 184 blkid_loff_t size) 185{ 186 blkid_dev *dev; 187 struct ext2_super_block *es; 188 int ret; 189 190 if ((ret = probe_ext2(fd, &dev, devname, id, buf, size)) < 0) 191 return ret; 192 193 es = (struct ext2_super_block *)buf; 194 195 if (!(le32_to_cpu(es->s_feature_compat) & 196 EXT3_FEATURE_COMPAT_HAS_JOURNAL)) { 197 blkid_free_dev(dev); 198 *dev_p = NULL; 199 return -BLKID_ERR_PARAM; 200 } 201 /* Don't set this until there is no chance of error */ 202 *dev_p = dev; 203 204 if (!(le32_to_cpu(es->s_feature_incompat) & 205 EXT3_FEATURE_INCOMPAT_RECOVER)) { 206 blkid_create_tag(dev, NULL, "TYPE", "ext2", 4); 207 dev->bid_flags |= BLKID_BID_FL_MTYPE; 208 } 209 210 return 0; 211} 212 213static int probe_vfat(int fd, blkid_dev **dev_p, const char *devname, 214 struct blkid_magic *id, unsigned char *buf, 215 blkid_loff_t size) 216{ 217 blkid_dev *dev; 218 struct vfat_super_block *vs; 219 char serno[10]; 220 blkid_loff_t sectors; 221 int cluster_size; 222 int ret; 223 224 if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0) 225 return ret; 226 227 vs = (struct vfat_super_block *)buf; 228 229 /* Don't set this until there is no chance of error */ 230 *dev_p = dev; 231 232 sectors = ((vs->vs_sectors[1] << 8) | vs->vs_sectors[0]); 233 if (sectors == 0) 234 sectors = vs->vs_total_sect; 235 cluster_size = ((vs->vs_sector_size[1] << 8) | vs->vs_sector_size[0]); 236 dev->bid_size = sectors * cluster_size; 237 DEB_PROBE("%Ld %d byte sectors\n", sectors, cluster_size); 238 239 if (strncmp(vs->vs_label, "NO NAME", 7)) { 240 unsigned char *end = vs->vs_label + sizeof(vs->vs_label) - 1; 241 242 while (*end == ' ' && end >= vs->vs_label) 243 --end; 244 if (end >= vs->vs_label) 245 blkid_create_tag(dev, NULL, "LABEL", vs->vs_label, 246 end - vs->vs_label + 1); 247 } 248 249 /* We can't just print them as %04X, because they are unaligned */ 250 sprintf(serno, "%02X%02X-%02X%02X", vs->vs_serno[3], vs->vs_serno[2], 251 vs->vs_serno[1], vs->vs_serno[0]); 252 blkid_create_tag(dev, NULL, "UUID", serno, sizeof(serno)); 253 254 return 0; 255} 256 257static int probe_msdos(int fd, blkid_dev **dev_p, const char *devname, 258 struct blkid_magic *id, unsigned char *buf, 259 blkid_loff_t size) 260{ 261 blkid_dev *dev; 262 struct msdos_super_block *ms; 263 char serno[10]; 264 int cluster_size; 265 blkid_loff_t sectors; 266 int ret; 267 268 if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0) 269 return ret; 270 271 ms = (struct msdos_super_block *)buf; 272 273 /* Don't set this until there is no chance of error */ 274 *dev_p = dev; 275 276 sectors = ((ms->ms_sectors[1] << 8) | ms->ms_sectors[0]); 277 if (sectors == 0) 278 sectors = ms->ms_total_sect; 279 cluster_size = ((ms->ms_sector_size[1] << 8) | ms->ms_sector_size[0]); 280 dev->bid_size = sectors * cluster_size; 281 DEB_PROBE("%Ld %d byte sectors\n", sectors, cluster_size); 282 283 if (strncmp(ms->ms_label, "NO NAME", 7)) { 284 unsigned char *end = ms->ms_label + sizeof(ms->ms_label) - 1; 285 286 while (*end == ' ' && end >= ms->ms_label) 287 --end; 288 if (end >= ms->ms_label) 289 blkid_create_tag(dev, NULL, "LABEL", ms->ms_label, 290 end - ms->ms_label + 1); 291 } 292 293 /* We can't just print them as %04X, because they are unaligned */ 294 sprintf(serno, "%02X%02X-%02X%02X", ms->ms_serno[3], ms->ms_serno[2], 295 ms->ms_serno[1], ms->ms_serno[0]); 296 blkid_create_tag(dev, NULL, "UUID", serno, sizeof(serno)); 297 298 return 0; 299} 300 301static int probe_xfs(int fd, blkid_dev **dev_p, const char *devname, 302 struct blkid_magic *id, unsigned char *buf, 303 blkid_loff_t size) 304{ 305 blkid_dev *dev; 306 struct xfs_super_block *xs; 307 int ret; 308 309 if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0) 310 return ret; 311 312 xs = (struct xfs_super_block *)buf; 313 314 /* Don't set this until there is no chance of error */ 315 *dev_p = dev; 316 /* If the filesystem size is larger than the device, this is bad */ 317 dev->bid_size = be64_to_cpu(xs->xs_dblocks) * 318 be32_to_cpu(xs->xs_blocksize); 319 dev->bid_free = be64_to_cpu(xs->xs_fdblocks) * 320 be32_to_cpu(xs->xs_blocksize); 321 322 if (strlen(xs->xs_fname)) 323 blkid_create_tag(dev, NULL, "LABEL", xs->xs_fname, 324 sizeof(xs->xs_fname)); 325 326 if (!uuid_is_null(xs->xs_uuid)) { 327 char uuid[37]; 328 uuid_unparse(xs->xs_uuid, uuid); 329 blkid_create_tag(dev, NULL, "UUID", uuid, sizeof(uuid)); 330 } 331 return 0; 332} 333 334static int probe_reiserfs(int fd, blkid_dev **dev_p, const char *devname, 335 struct blkid_magic *id, unsigned char *buf, 336 blkid_loff_t size) 337{ 338 blkid_dev *dev; 339 struct reiserfs_super_block *rs; 340 unsigned int blocksize; 341 int ret; 342 343 if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0) 344 return ret; 345 346 rs = (struct reiserfs_super_block *)buf; 347 348 blocksize = le16_to_cpu(rs->rs_blocksize); 349 350 /* If the superblock is inside the journal, we have the wrong one */ 351 if (id->bim_kboff/(blocksize>>10) > le32_to_cpu(rs->rs_journal_block)) { 352 blkid_free_dev(dev); 353 return -BLKID_ERR_BIG; 354 } 355 356 /* Don't set this until there is no chance of error */ 357 *dev_p = dev; 358 359 /* If the filesystem size is larger than the device, this is bad */ 360 dev->bid_size = le32_to_cpu(rs->rs_blocks_count) * blocksize; 361 dev->bid_free = le32_to_cpu(rs->rs_free_blocks) * blocksize; 362 363 /* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */ 364 if (!strcmp(id->bim_magic, "ReIsEr2Fs") || 365 !strcmp(id->bim_magic, "ReIsEr3Fs")) { 366 if (strlen(rs->rs_label)) { 367 blkid_create_tag(dev, NULL, "LABEL", rs->rs_label, 368 sizeof(rs->rs_label)); 369 } 370 371 if (!uuid_is_null(rs->rs_uuid)) { 372 unsigned char uuid[37]; 373 uuid_unparse(rs->rs_uuid, uuid); 374 blkid_create_tag(dev, NULL, "UUID", uuid, sizeof(uuid)); 375 } 376 } 377 378 return 0; 379} 380 381static int probe_minix(int fd, blkid_dev **dev_p, const char *devname, 382 struct blkid_magic *id, unsigned char *buf, 383 blkid_loff_t size) 384{ 385 blkid_dev *dev; 386 struct minix_super_block *ms; 387 int ret; 388 389 if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0) 390 return ret; 391 392 ms = (struct minix_super_block *)buf; 393 394 /* Don't set this until there is no chance of error */ 395 *dev_p = dev; 396 dev->bid_size = ms->ms_nzones << ms->ms_log_zone_size; 397 return 0; 398} 399 400static int probe_swap(int fd, blkid_dev **dev_p, const char *devname, 401 struct blkid_magic *id, unsigned char *buf, 402 blkid_loff_t size) 403{ 404 blkid_dev *dev; 405 struct swap_header *sh; 406 int psize; 407 int ret; 408 409 if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0) 410 return ret; 411 412 /* PAGE_SIZE can be found by where the magic is located */ 413 psize = (id->bim_kboff << 10) + (id->bim_sboff + 10); 414 415 /* Don't set this until there is no chance of error */ 416 *dev_p = dev; 417 418 sh = (struct swap_header *)buf; 419 /* Is swap data in local endian format? */ 420 dev->bid_size = (blkid_loff_t)(sh->sh_last_page + 1) * psize; 421 422 /* A label can not exist on the old (128MB max) swap format */ 423 if (!strcmp(id->bim_magic, "SWAPSPACE2") && sh->sh_label[0]) { 424 blkid_create_tag(dev, NULL, "LABEL", sh->sh_label, 425 sizeof(sh->sh_label)); 426 } 427 428 return 0; 429} 430 431static int probe_mdraid(int fd, blkid_dev **dev_p, const char *devname, 432 struct blkid_magic *id, unsigned char *buf, 433 blkid_loff_t size) 434{ 435 blkid_dev *dev; 436 struct mdp_superblock_s *md; 437 int ret; 438 439 if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0) 440 return ret; 441 442 /* Don't set this until there is no chance of error */ 443 *dev_p = dev; 444 445 md = (struct mdp_superblock_s *)buf; 446 /* What units is md->size in? Assume 512-byte sectors? */ 447 dev->bid_size = md->size * 512; 448 449 /* The MD UUID is not contiguous in the superblock, make it so */ 450 if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) { 451 unsigned char md_uuid[16]; 452 unsigned char uuid[37]; 453 454 memcpy(md_uuid, &md->set_uuid0, 4); 455 memcpy(md_uuid + 4, &md->set_uuid1, 12); 456 457 uuid_unparse(md_uuid, uuid); 458 blkid_create_tag(dev, NULL, "UUID", uuid, sizeof(uuid)); 459 } 460 return 0; 461} 462 463static int probe_hfs(int fd, blkid_dev **dev_p, const char *devname, 464 struct blkid_magic *id, unsigned char *buf, 465 blkid_loff_t size) 466{ 467 blkid_dev *dev; 468 struct hfs_super_block *hfs; 469 int ret; 470 471 if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0) 472 return ret; 473 474 hfs = (struct hfs_super_block *)buf; 475 476 if (be32_to_cpu(hfs->h_blksize) != 512) 477 return -BLKID_ERR_PARAM; 478 479 /* Don't set this until there is no chance of error */ 480 *dev_p = dev; 481 482 return 0; 483} 484 485 486/* 487 * BLKID_BLK_OFFS is at least as large as the highest bim_kboff defined 488 * in the type_array table below + bim_kbalign. If we ever start looking for magics 489 * relative to the end of a device, we can start using negative offsets 490 * in type_array. 491 */ 492#define BLKID_BLK_BITS (10) 493#define BLKID_BLK_KBITS (BLKID_BLK_BITS - 10) 494#define BLKID_BLK_SIZE (1024 << BLKID_BLK_KBITS) 495#define BLKID_BLK_MASK (BLKID_BLK_SIZE - 1) 496#define BLKID_BLK_OFFS 128 /* currently MDRAID kboff + align */ 497 498/* 499 * Various filesystem magics that we can check for. Note that kboff and 500 * sboff are in kilobytes and bytes respectively. All magics are in 501 * byte strings so we don't worry about endian issues. 502 */ 503struct blkid_magic type_array[] = { 504/* type kboff sboff len magic align kbsize probe */ 505 { "MDRAID", -64, 0, 4, "\251+N\374", 65536, 4, probe_mdraid }, 506/*{ "LVM", 0, 0, 4, "HM\001\000", 1, 4, probe_lvm },*/ 507 { "jbd", 1, 0x38, 2, "\123\357", 1, 1, probe_jbd }, 508 { "ext3", 1, 0x38, 2, "\123\357", 1, 1, probe_ext3 }, 509 { "ext2", 1, 0x38, 2, "\123\357", 1, 1, probe_ext2 }, 510 { "reiserfs", 8, 0x34, 8, "ReIsErFs", 1, 1, probe_reiserfs }, 511 { "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", 1, 1, probe_reiserfs }, 512 { "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", 1, 1, probe_reiserfs }, 513 { "reiserfs", 64, 0x34, 8, "ReIsErFs", 1, 1, probe_reiserfs }, 514 { "reiserfs", 8, 20, 8, "ReIsErFs", 1, 1, probe_reiserfs }, 515 { "ntfs", 0, 3, 8, "NTFS ", 1, 1, probe_default }, 516 { "vfat", 0, 0x52, 5, "MSWIN", 1, 1, probe_vfat }, 517 { "vfat", 0, 0x52, 8, "FAT32 ", 1, 1, probe_vfat }, 518 { "msdos", 0, 0x36, 5, "MSDOS", 1, 1, probe_msdos }, 519 { "msdos", 0, 0x36, 8, "FAT16 ", 1, 1, probe_msdos }, 520 { "msdos", 0, 0x36, 8, "FAT12 ", 1, 1, probe_msdos }, 521 { "minix", 1, 0x10, 2, "\177\023", 1, 1, probe_minix }, 522 { "minix", 1, 0x10, 2, "\217\023", 1, 1, probe_minix }, 523 { "minix", 1, 0x10, 2, "\150\044", 1, 1, probe_minix }, 524 { "minix", 1, 0x10, 2, "\170\044", 1, 1, probe_minix }, 525 { "vxfs", 1, 0, 4, "\365\374\001\245", 1, 1, probe_default }, 526 { "xfs", 0, 0, 4, "XFSB", 1, 1, probe_xfs }, 527 { "romfs", 0, 0, 8, "-rom1fs-", 1, 1, probe_default }, 528 { "bfs", 0, 0, 4, "\316\372\173\033", 1, 1, probe_default }, 529 { "cramfs", 0, 0, 4, "E=\315\034", 1, 1, probe_default }, 530 { "qnx4", 0, 4, 6, "QNX4FS", 1, 1, probe_default }, 531 { "iso9660", 32, 1, 5, "CD001", 1, 1, probe_default }, 532 { "iso9660", 32, 9, 5, "CDROM", 1, 1, probe_default }, 533 { "udf", 32, 1, 5, "BEA01", 1, 1, probe_default }, 534 { "udf", 32, 1, 5, "BOOT2", 1, 1, probe_default }, 535 { "udf", 32, 1, 5, "CD001", 1, 1, probe_default }, 536 { "udf", 32, 1, 5, "CDW02", 1, 1, probe_default }, 537 { "udf", 32, 1, 5, "NSR02", 1, 1, probe_default }, 538 { "udf", 32, 1, 5, "NSR03", 1, 1, probe_default }, 539 { "udf", 32, 1, 5, "TEA01", 1, 1, probe_default }, 540 { "jfs", 32, 0, 4, "JFS1", 1, 1, probe_default }, 541 { "hfs", 1, 0, 2, "BD", 1, 1, probe_hfs }, 542 { "ufs", 8, 0x55c, 4, "T\031\001\000", 1, 1, probe_default }, 543 { "hpfs", 8, 0, 4, "I\350\225\371", 1, 1, probe_default }, 544 { "sysv", 0, 0x3f8, 4, "\020~\030\375", 1, 1, probe_default }, 545 { "swap", 0, 0xff6, 10, "SWAP-SPACE", 1, 4, probe_swap }, 546 { "swap", 0, 0xff6, 10, "SWAPSPACE2", 1, 4, probe_swap }, 547 { "swap", 0, 0x1ff6, 10, "SWAP-SPACE", 1, 8, probe_swap }, 548 { "swap", 0, 0x1ff6, 10, "SWAPSPACE2", 1, 8, probe_swap }, 549 { "swap", 0, 0x3ff6, 10, "SWAP-SPACE", 1, 16, probe_swap }, 550 { "swap", 0, 0x3ff6, 10, "SWAPSPACE2", 1, 16, probe_swap }, 551 { NULL, 0, 0, 0, NULL, 1, 0, NULL } 552}; 553 554 555/* 556 * When probing for a lot of magics, we handle everything in 1kB buffers so 557 * that we don't have to worry about reading each combination of block sizes. 558 */ 559static unsigned char *read_one_buf(int fd, blkid_loff_t offset) 560{ 561 char *buf; 562 563 if (lseek(fd, offset, SEEK_SET) < 0) 564 return NULL; 565 566 if (!(buf = (unsigned char *)malloc(BLKID_BLK_SIZE))) 567 return NULL; 568 569 if (read(fd, buf, BLKID_BLK_SIZE) != BLKID_BLK_SIZE) { 570 free(buf); 571 return NULL; 572 } 573 574 return buf; 575} 576 577static unsigned char *read_sb_buf(int fd, unsigned char **bufs, int kboff, 578 blkid_loff_t start) 579{ 580 int index = kboff >> BLKID_BLK_KBITS; 581 unsigned char **buf; 582 583 if (index > BLKID_BLK_OFFS || index < -BLKID_BLK_OFFS) { 584 fprintf(stderr, "reading from invalid offset %d (%d)!\n", 585 kboff, index); 586 return NULL; 587 } 588 589 buf = bufs + index; 590 if (!*buf) 591 *buf = read_one_buf(fd, start); 592 593 return *buf; 594} 595 596static struct blkid_magic *devname_to_magic(const char *devname, int fd, 597 unsigned char **bufs, 598 struct blkid_magic *id, 599 blkid_loff_t size) 600{ 601 struct blkid_magic *ret = NULL; 602 603 if (!bufs || fd < 0) 604 return NULL; 605 606 if (id >= type_array + sizeof(type_array) / sizeof(*id)) 607 return NULL; 608 609 for (id = id < type_array ? type_array : id + 1; id->bim_type; ++id) { 610 unsigned char *buf; 611 blkid_loff_t start = 0LL; 612 blkid_loff_t offset = 0LL; 613 int kboff; 614 615 offset = ((blkid_loff_t)id->bim_kboff << 10) + 616 (id->bim_sboff & ~0x3ffULL); 617 /* 618 * We index negative buffers by their actual offset (including 619 * superblock offsets > 1kB, not the aligned offset, so that 620 * we correctly access negative buffers with different 621 * alignment requirements. 622 */ 623 if (id->bim_kboff < 0) { 624 start = (size & ~((blkid_loff_t)id->bim_align - 1)) + 625 offset; 626 if (start < 0) /* Device too small for alignment */ 627 continue; 628 kboff = (start - size) >> 10; 629 } else { 630 start = offset; 631 kboff = offset >> 10; 632 } 633 634 if ((buf = 635 read_sb_buf(fd, bufs, kboff, start)) && 636 !memcmp(id->bim_magic, buf + (id->bim_sboff&0x3ffULL), 637 id->bim_len)) { 638 ret = id; 639 break; 640 } 641 } 642 643 return ret; 644} 645 646/* 647 * Get data from a single block special device. 648 * 649 * Return a blkid_dev with at least the device type and size set. 650 * If the passed-in size is zero, then we get the device size here. 651 */ 652blkid_dev *blkid_devname_to_dev(const char *devname, blkid_loff_t size) 653{ 654 unsigned char *buf_array[BLKID_BLK_OFFS * 2 + 1]; 655 unsigned char **bufs = buf_array + BLKID_BLK_OFFS; 656 blkid_dev *dev = NULL, *last = NULL; 657 unsigned char *sb_buf = NULL; 658 int sb_size = 0; 659 struct blkid_magic *id = NULL; 660 blkid_loff_t diff_last = 0xf000000000000000ULL; 661 int fd; 662 663 if (!devname) 664 return NULL; 665 666 fd = open(devname, O_RDONLY); 667 if (fd < 0) 668 return NULL; 669 670 if (!size) 671 size = blkid_get_dev_size(fd); 672 if (size < 1024) 673 goto exit_fd; 674 675 memset(buf_array, 0, sizeof(buf_array)); 676 677 while ((id = devname_to_magic(devname, fd, bufs, id, size)) && 678 diff_last) { 679 int new_sb; 680 blkid_loff_t diff_dev; 681 682 DEB_PROBE("found type %s (#%d) on %s, probing\n", 683 id->bim_type, id - type_array, devname); 684 685 new_sb = id->bim_kbsize << 10; 686 if (sb_size < new_sb) { 687 unsigned char *sav = sb_buf; 688 if (!(sb_buf = realloc(sb_buf, new_sb))) { 689 sb_buf = sav; 690 continue; 691 } 692 sb_size = new_sb; 693 } 694 695 if (id->bim_probe(fd, &dev, devname, id, sb_buf, size) < 0) 696 continue; 697 698 diff_dev = size - dev->bid_size; 699 DEB_PROBE("size = %Lu, fs size = %Lu\n", size, dev->bid_size); 700 DEB_PROBE("checking best match: old %Ld, new %Ld\n", 701 diff_last, diff_dev); 702 /* See which type is a better match by checking size */ 703 if ((diff_last < 0 && diff_dev > diff_last) || 704 (diff_last > 0 && diff_dev >= 0 && diff_dev < diff_last)) { 705 if (last) 706 blkid_free_dev(last); 707 last = dev; 708 diff_last = diff_dev; 709 } else 710 blkid_free_dev(dev); 711 } 712 713 if (!last) 714 DEB_PROBE("unknown device type on %s\n", devname); 715 else 716 DEB_DUMP_DEV(last); 717 718 /* Free up any buffers we allocated */ 719 for (bufs = buf_array; bufs - buf_array < sizeof(buf_array) / 720 sizeof(buf_array[0]); bufs++) { 721 if (*bufs) 722 free(*bufs); 723 } 724 725 if (sb_buf) 726 free(sb_buf); 727exit_fd: 728 close(fd); 729 return last; 730} 731 732/* 733 * Verify that the data in dev is consistent with what is on the actual 734 * block device (using the devname field only). Normally this will be 735 * called when finding items in the cache, but for long running processes 736 * is also desirable to revalidate an item before use. 737 * 738 * If we are unable to revalidate the data, we return the old data and 739 * do not set the BLKID_BID_FL_VERIFIED flag on it. 740 */ 741blkid_dev *blkid_verify_devname(blkid_cache *cache, blkid_dev *dev) 742{ 743 blkid_loff_t size; 744 struct blkid_magic *id; 745 blkid_dev *new = NULL; 746 char *sb_buf = NULL; 747 int sb_size = 0; 748 time_t diff; 749 int fd; 750 751 if (!dev) 752 return NULL; 753 754 diff = time(0) - dev->bid_time; 755 756 if (diff < BLKID_PROBE_MIN || (dev->bid_flags & BLKID_BID_FL_VERIFIED && 757 diff < BLKID_PROBE_INTERVAL)) 758 return dev; 759 760 DEB_PROBE("need to revalidate %s\n", dev->bid_name); 761 762 if ((fd = open(dev->bid_name, O_RDONLY)) < 0) { 763 if (errno == ENXIO || errno == ENODEV) { 764 fprintf(stderr, "unable to open %s for revalidation\n", 765 dev->bid_name); 766 blkid_free_dev(dev); 767 return NULL; 768 } 769 /* We don't have read permission, just return cache data. */ 770 DEB_PROBE("returning unverified data for %s\n", dev->bid_name); 771 return dev; 772 } 773 774 size = blkid_get_dev_size(fd); 775 776 /* See if we can probe this device by its existing type directly */ 777 for (id = type_array; id->bim_type; id++) { 778 if (!strcmp(id->bim_type, dev->bid_type)) { 779 int new_sb = id->bim_kbsize << 10; 780 /* See if we need to allocate a larger sb buffer */ 781 if (sb_size < new_sb) { 782 char *sav = sb_buf; 783 784 /* We can't revalidate, return old dev */ 785 if (!(sb_buf = realloc(sb_buf, new_sb))) { 786 fprintf(stderr, "not enough memory for " 787 "%s revalidation\n", 788 dev->bid_name); 789 free(sav); 790 goto exit_fd; 791 } 792 sb_size = new_sb; 793 } 794 795 if (id->bim_probe(fd, &new, dev->bid_name, id, sb_buf, 796 size) == 0) 797 break; 798 } 799 } 800 801 if (sb_buf) 802 free(sb_buf); 803 804 /* Otherwise we need to determine the device type first */ 805 if (new || (new = blkid_devname_to_dev(dev->bid_name, size))) { 806 new->bid_id = dev->bid_id; /* save old id for cache */ 807 blkid_free_dev(dev); 808 dev = blkid_add_dev_to_cache(cache, new); 809 } 810 811exit_fd: 812 close(fd); 813 814 /* In case the cache is missing the device size */ 815 if (dev->bid_devsize == 0) 816 dev->bid_devsize = size; 817 return dev; 818 819} 820 821#ifdef TEST_PROGRAM 822int main(int argc, char **argv) 823{ 824 blkid_dev *dev; 825 826 if (argc != 2) { 827 fprintf(stderr, "Usage: %s device\n" 828 "Probe a single device to determine type\n", argv[0]); 829 exit(1); 830 } 831 dev = blkid_devname_to_dev(argv[1], 0); 832 if (dev) 833 blkid_free_dev(dev); 834 else 835 printf("%s: %s has an unsupported type\n", argv[0], argv[1]); 836 return (0); 837} 838#endif 839