Home | History | Annotate | Download | only in blkid
      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, 2003 by Theodore Ts'o
      7  * Copyright (C) 2001 by Andreas Dilger
      8  * Copyright (C) 2004 Kay Sievers <kay.sievers (at) vrfy.org>
      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 <ctype.h>
     22 #include <sys/types.h>
     23 #ifdef HAVE_SYS_STAT_H
     24 #include <sys/stat.h>
     25 #endif
     26 #ifdef HAVE_SYS_MKDEV_H
     27 #include <sys/mkdev.h>
     28 #endif
     29 #include <sys/utsname.h>
     30 #ifdef HAVE_ERRNO_H
     31 #include <errno.h>
     32 #endif
     33 #include "blkidP.h"
     34 #include "uuid/uuid.h"
     35 #include "probe.h"
     36 
     37 static int figure_label_len(const unsigned char *label, int len)
     38 {
     39 	const unsigned char *end = label + len - 1;
     40 
     41 	while ((*end == ' ' || *end == 0) && end >= label)
     42 		--end;
     43 	if (end >= label) {
     44 		label = label;
     45 		return end - label + 1;
     46 	}
     47 	return 0;
     48 }
     49 
     50 static unsigned char *get_buffer(struct blkid_probe *pr,
     51 			  blkid_loff_t off, size_t len)
     52 {
     53 	ssize_t		ret_read;
     54 	unsigned char	*newbuf;
     55 
     56 	if (off + len <= SB_BUFFER_SIZE) {
     57 		if (!pr->sbbuf) {
     58 			pr->sbbuf = malloc(SB_BUFFER_SIZE);
     59 			if (!pr->sbbuf)
     60 				return NULL;
     61 			if (lseek(pr->fd, 0, SEEK_SET) < 0)
     62 				return NULL;
     63 			ret_read = read(pr->fd, pr->sbbuf, SB_BUFFER_SIZE);
     64 			if (ret_read < 0)
     65 				ret_read = 0;
     66 			pr->sb_valid = ret_read;
     67 		}
     68 		if (off+len > pr->sb_valid)
     69 			return NULL;
     70 		return pr->sbbuf + off;
     71 	} else {
     72 		if (len > pr->buf_max) {
     73 			newbuf = realloc(pr->buf, len);
     74 			if (newbuf == NULL)
     75 				return NULL;
     76 			pr->buf = newbuf;
     77 			pr->buf_max = len;
     78 		}
     79 		if (blkid_llseek(pr->fd, off, SEEK_SET) < 0)
     80 			return NULL;
     81 		ret_read = read(pr->fd, pr->buf, len);
     82 		if (ret_read != (ssize_t) len)
     83 			return NULL;
     84 		return pr->buf;
     85 	}
     86 }
     87 
     88 
     89 /*
     90  * This is a special case code to check for an MDRAID device.  We do
     91  * this special since it requires checking for a superblock at the end
     92  * of the device.
     93  */
     94 static int check_mdraid(int fd, unsigned char *ret_uuid)
     95 {
     96 	struct mdp_superblock_s *md;
     97 	blkid_loff_t		offset;
     98 	char			buf[4096];
     99 
    100 	if (fd < 0)
    101 		return -BLKID_ERR_PARAM;
    102 
    103 	offset = (blkid_get_dev_size(fd) & ~((blkid_loff_t)65535)) - 65536;
    104 
    105 	if (blkid_llseek(fd, offset, 0) < 0 ||
    106 	    read(fd, buf, 4096) != 4096)
    107 		return -BLKID_ERR_IO;
    108 
    109 	/* Check for magic number */
    110 	if (memcmp("\251+N\374", buf, 4) && memcmp("\374N+\251", buf, 4))
    111 		return -BLKID_ERR_PARAM;
    112 
    113 	if (!ret_uuid)
    114 		return 0;
    115 	*ret_uuid = 0;
    116 
    117 	/* The MD UUID is not contiguous in the superblock, make it so */
    118 	md = (struct mdp_superblock_s *)buf;
    119 	if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) {
    120 		memcpy(ret_uuid, &md->set_uuid0, 4);
    121 		memcpy(ret_uuid + 4, &md->set_uuid1, 12);
    122 	}
    123 	return 0;
    124 }
    125 
    126 static void set_uuid(blkid_dev dev, uuid_t uuid, const char *tag)
    127 {
    128 	char	str[37];
    129 
    130 	if (!uuid_is_null(uuid)) {
    131 		uuid_unparse(uuid, str);
    132 		blkid_set_tag(dev, tag ? tag : "UUID", str, sizeof(str));
    133 	}
    134 }
    135 
    136 static void get_ext2_info(blkid_dev dev, struct blkid_magic *id,
    137 			  unsigned char *buf)
    138 {
    139 	struct ext2_super_block *es = (struct ext2_super_block *) buf;
    140 	const char *label = 0;
    141 
    142 	DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n",
    143 		   blkid_le32(es->s_feature_compat),
    144 		   blkid_le32(es->s_feature_incompat),
    145 		   blkid_le32(es->s_feature_ro_compat)));
    146 
    147 	if (strlen(es->s_volume_name))
    148 		label = es->s_volume_name;
    149 	blkid_set_tag(dev, "LABEL", label, sizeof(es->s_volume_name));
    150 
    151 	set_uuid(dev, es->s_uuid, 0);
    152 
    153 	if ((es->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
    154 	    !uuid_is_null(es->s_journal_uuid))
    155 		set_uuid(dev, es->s_journal_uuid, "EXT_JOURNAL");
    156 
    157 	if (strcmp(id->bim_type, "ext2") &&
    158 	    ((blkid_le32(es->s_feature_incompat) &
    159 	      EXT2_FEATURE_INCOMPAT_UNSUPPORTED) == 0))
    160 		blkid_set_tag(dev, "SEC_TYPE", "ext2", sizeof("ext2"));
    161 }
    162 
    163 /*
    164  * Check to see if a filesystem is in /proc/filesystems.
    165  * Returns 1 if found, 0 if not
    166  */
    167 static int fs_proc_check(const char *fs_name)
    168 {
    169 	FILE	*f;
    170 	char	buf[80], *cp, *t;
    171 
    172 	f = fopen("/proc/filesystems", "r");
    173 	if (!f)
    174 		return (0);
    175 	while (!feof(f)) {
    176 		if (!fgets(buf, sizeof(buf), f))
    177 			break;
    178 		cp = buf;
    179 		if (!isspace(*cp)) {
    180 			while (*cp && !isspace(*cp))
    181 				cp++;
    182 		}
    183 		while (*cp && isspace(*cp))
    184 			cp++;
    185 		if ((t = strchr(cp, '\n')) != NULL)
    186 			*t = 0;
    187 		if ((t = strchr(cp, '\t')) != NULL)
    188 			*t = 0;
    189 		if ((t = strchr(cp, ' ')) != NULL)
    190 			*t = 0;
    191 		if (!strcmp(fs_name, cp)) {
    192 			fclose(f);
    193 			return (1);
    194 		}
    195 	}
    196 	fclose(f);
    197 	return (0);
    198 }
    199 
    200 /*
    201  * Check to see if a filesystem is available as a module
    202  * Returns 1 if found, 0 if not
    203  */
    204 static int check_for_modules(const char *fs_name)
    205 {
    206 	struct utsname	uts;
    207 	FILE		*f;
    208 	char		buf[1024], *cp, *t;
    209 	int		i;
    210 
    211 	if (uname(&uts))
    212 		return (0);
    213 	snprintf(buf, sizeof(buf), "/lib/modules/%s/modules.dep", uts.release);
    214 
    215 	f = fopen(buf, "r");
    216 	if (!f)
    217 		return (0);
    218 	while (!feof(f)) {
    219 		if (!fgets(buf, sizeof(buf), f))
    220 			break;
    221 		if ((cp = strchr(buf, ':')) != NULL)
    222 			*cp = 0;
    223 		else
    224 			continue;
    225 		if ((cp = strrchr(buf, '/')) != NULL)
    226 			cp++;
    227 		i = strlen(cp);
    228 		if (i > 3) {
    229 			t = cp + i - 3;
    230 			if (!strcmp(t, ".ko"))
    231 				*t = 0;
    232 		}
    233 		if (!strcmp(cp, fs_name))
    234 			return (1);
    235 	}
    236 	fclose(f);
    237 	return (0);
    238 }
    239 
    240 static int system_supports_ext4(void)
    241 {
    242 	static time_t	last_check = 0;
    243 	static int	ret = -1;
    244 	time_t		now = time(0);
    245 
    246 	if (ret != -1 || (last_check - now) < 5)
    247 		return ret;
    248 	last_check = now;
    249 	ret = (fs_proc_check("ext4") || check_for_modules("ext4"));
    250 	return ret;
    251 }
    252 
    253 static int system_supports_ext4dev(void)
    254 {
    255 	static time_t	last_check = 0;
    256 	static int	ret = -1;
    257 	time_t		now = time(0);
    258 
    259 	if (ret != -1 || (last_check - now) < 5)
    260 		return ret;
    261 	last_check = now;
    262 	ret = (fs_proc_check("ext4dev") || check_for_modules("ext4dev"));
    263 	return ret;
    264 }
    265 
    266 static int probe_ext4dev(struct blkid_probe *probe,
    267 			 struct blkid_magic *id,
    268 			 unsigned char *buf)
    269 {
    270 	struct ext2_super_block *es;
    271 	es = (struct ext2_super_block *)buf;
    272 
    273 	/* Distinguish from jbd */
    274 	if (blkid_le32(es->s_feature_incompat) &
    275 	    EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
    276 		return -BLKID_ERR_PARAM;
    277 
    278 	/* ext4dev requires a journal */
    279 	if (!(blkid_le32(es->s_feature_compat) &
    280 	      EXT3_FEATURE_COMPAT_HAS_JOURNAL))
    281 		return -BLKID_ERR_PARAM;
    282 
    283 	/*
    284 	 * If the filesystem is marked as OK for use by in-development
    285 	 * filesystem code, but ext4dev is not supported, and ext4 is,
    286 	 * then don't call ourselves ext4dev, since we should be
    287 	 * detected as ext4 in that case.
    288 	 *
    289 	 * If the filesystem is marked as in use by production
    290 	 * filesystem, then it can only be used by ext4 and NOT by
    291 	 * ext4dev, so always disclaim we are ext4dev in that case.
    292 	 */
    293 	if (blkid_le32(es->s_flags) & EXT2_FLAGS_TEST_FILESYS) {
    294 		if (!system_supports_ext4dev() && system_supports_ext4())
    295 			return -BLKID_ERR_PARAM;
    296 	} else
    297 		return -BLKID_ERR_PARAM;
    298 
    299     	get_ext2_info(probe->dev, id, buf);
    300 	return 0;
    301 }
    302 
    303 static int probe_ext4(struct blkid_probe *probe, struct blkid_magic *id,
    304 		      unsigned char *buf)
    305 {
    306 	struct ext2_super_block *es;
    307 	es = (struct ext2_super_block *)buf;
    308 
    309 	/* Distinguish from jbd */
    310 	if (blkid_le32(es->s_feature_incompat) &
    311 	    EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
    312 		return -BLKID_ERR_PARAM;
    313 
    314 	/* ext4 requires journal */
    315 	if (!(blkid_le32(es->s_feature_compat) &
    316 	      EXT3_FEATURE_COMPAT_HAS_JOURNAL))
    317 		return -BLKID_ERR_PARAM;
    318 
    319 	/* Ext4 has at least one feature which ext3 doesn't understand */
    320 	if (!(blkid_le32(es->s_feature_ro_compat) &
    321 	      EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) &&
    322 	    !(blkid_le32(es->s_feature_incompat) &
    323 	      EXT3_FEATURE_INCOMPAT_UNSUPPORTED))
    324 		return -BLKID_ERR_PARAM;
    325 
    326 	/*
    327 	 * If the filesystem is a OK for use by in-development
    328 	 * filesystem code, and ext4dev is supported or ext4 is not
    329 	 * supported, then don't call ourselves ext4, so we can redo
    330 	 * the detection and mark the filesystem as ext4dev.
    331 	 *
    332 	 * If the filesystem is marked as in use by production
    333 	 * filesystem, then it can only be used by ext4 and NOT by
    334 	 * ext4dev.
    335 	 */
    336 	if (blkid_le32(es->s_flags) & EXT2_FLAGS_TEST_FILESYS) {
    337 		if (system_supports_ext4dev() || !system_supports_ext4())
    338 			return -BLKID_ERR_PARAM;
    339 	}
    340     	get_ext2_info(probe->dev, id, buf);
    341 	return 0;
    342 }
    343 
    344 static int probe_ext3(struct blkid_probe *probe, struct blkid_magic *id,
    345 		      unsigned char *buf)
    346 {
    347 	struct ext2_super_block *es;
    348 	es = (struct ext2_super_block *)buf;
    349 
    350 	/* Distinguish from ext4dev */
    351 	if (blkid_le32(es->s_flags) & EXT2_FLAGS_TEST_FILESYS)
    352 		return -BLKID_ERR_PARAM;
    353 
    354 	/* ext3 requires journal */
    355 	if (!(blkid_le32(es->s_feature_compat) &
    356 	      EXT3_FEATURE_COMPAT_HAS_JOURNAL))
    357 		return -BLKID_ERR_PARAM;
    358 
    359 	/* Any features which ext3 doesn't understand */
    360 	if ((blkid_le32(es->s_feature_ro_compat) &
    361 	     EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) ||
    362 	    (blkid_le32(es->s_feature_incompat) &
    363 	     EXT3_FEATURE_INCOMPAT_UNSUPPORTED))
    364 		return -BLKID_ERR_PARAM;
    365 
    366     	get_ext2_info(probe->dev, id, buf);
    367 	return 0;
    368 }
    369 
    370 static int probe_ext2(struct blkid_probe *probe, struct blkid_magic *id,
    371 		      unsigned char *buf)
    372 {
    373 	struct ext2_super_block *es;
    374 
    375 	es = (struct ext2_super_block *)buf;
    376 
    377 	/* Distinguish between ext3 and ext2 */
    378 	if ((blkid_le32(es->s_feature_compat) &
    379 	      EXT3_FEATURE_COMPAT_HAS_JOURNAL))
    380 		return -BLKID_ERR_PARAM;
    381 
    382 	/* Any features which ext2 doesn't understand */
    383 	if ((blkid_le32(es->s_feature_ro_compat) &
    384 	     EXT2_FEATURE_RO_COMPAT_UNSUPPORTED) ||
    385 	    (blkid_le32(es->s_feature_incompat) &
    386 	     EXT2_FEATURE_INCOMPAT_UNSUPPORTED))
    387 		return -BLKID_ERR_PARAM;
    388 
    389 	get_ext2_info(probe->dev, id, buf);
    390 	return 0;
    391 }
    392 
    393 static int probe_jbd(struct blkid_probe *probe, struct blkid_magic *id,
    394 		     unsigned char *buf)
    395 {
    396 	struct ext2_super_block *es = (struct ext2_super_block *) buf;
    397 
    398 	if (!(blkid_le32(es->s_feature_incompat) &
    399 	      EXT3_FEATURE_INCOMPAT_JOURNAL_DEV))
    400 		return -BLKID_ERR_PARAM;
    401 
    402 	get_ext2_info(probe->dev, id, buf);
    403 
    404 	return 0;
    405 }
    406 
    407 #define FAT_ATTR_VOLUME_ID		0x08
    408 #define FAT_ATTR_DIR			0x10
    409 #define FAT_ATTR_LONG_NAME		0x0f
    410 #define FAT_ATTR_MASK			0x3f
    411 #define FAT_ENTRY_FREE			0xe5
    412 
    413 static const char *no_name = "NO NAME    ";
    414 
    415 static unsigned char *search_fat_label(struct vfat_dir_entry *dir, int count)
    416 {
    417 	int i;
    418 
    419 	for (i = 0; i < count; i++) {
    420 		if (dir[i].name[0] == 0x00)
    421 			break;
    422 
    423 		if ((dir[i].name[0] == FAT_ENTRY_FREE) ||
    424 		    (dir[i].cluster_high != 0 || dir[i].cluster_low != 0) ||
    425 		    ((dir[i].attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME))
    426 			continue;
    427 
    428 		if ((dir[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) ==
    429 		    FAT_ATTR_VOLUME_ID) {
    430 			return dir[i].name;
    431 		}
    432 	}
    433 	return 0;
    434 }
    435 
    436 /* FAT label extraction from the root directory taken from Kay
    437  * Sievers's volume_id library */
    438 static int probe_fat(struct blkid_probe *probe,
    439 		      struct blkid_magic *id __BLKID_ATTR((unused)),
    440 		      unsigned char *buf)
    441 {
    442 	struct vfat_super_block *vs = (struct vfat_super_block *) buf;
    443 	struct msdos_super_block *ms = (struct msdos_super_block *) buf;
    444 	struct vfat_dir_entry *dir;
    445 	char serno[10];
    446 	const unsigned char *label = 0, *vol_label = 0, *tmp;
    447 	unsigned char	*vol_serno;
    448 	int label_len = 0, maxloop = 100;
    449 	__u16 sector_size, dir_entries, reserved;
    450 	__u32 sect_count, fat_size, dir_size, cluster_count, fat_length;
    451 	__u32 buf_size, start_data_sect, next, root_start, root_dir_entries;
    452 
    453 	/* sector size check */
    454 	tmp = (unsigned char *)&ms->ms_sector_size;
    455 	sector_size = tmp[0] + (tmp[1] << 8);
    456 	if (sector_size != 0x200 && sector_size != 0x400 &&
    457 	    sector_size != 0x800 && sector_size != 0x1000)
    458 		return 1;
    459 
    460 	tmp = (unsigned char *)&ms->ms_dir_entries;
    461 	dir_entries = tmp[0] + (tmp[1] << 8);
    462 	reserved =  blkid_le16(ms->ms_reserved);
    463 	tmp = (unsigned char *)&ms->ms_sectors;
    464 	sect_count = tmp[0] + (tmp[1] << 8);
    465 	if (sect_count == 0)
    466 		sect_count = blkid_le32(ms->ms_total_sect);
    467 
    468 	fat_length = blkid_le16(ms->ms_fat_length);
    469 	if (fat_length == 0)
    470 		fat_length = blkid_le32(vs->vs_fat32_length);
    471 
    472 	fat_size = fat_length * ms->ms_fats;
    473 	dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) +
    474 			(sector_size-1)) / sector_size;
    475 
    476 	cluster_count = sect_count - (reserved + fat_size + dir_size);
    477 	if (ms->ms_cluster_size == 0)
    478 		return 1;
    479 	cluster_count /= ms->ms_cluster_size;
    480 
    481 	if (cluster_count > FAT32_MAX)
    482 		return 1;
    483 
    484 	if (ms->ms_fat_length) {
    485 		/* the label may be an attribute in the root directory */
    486 		root_start = (reserved + fat_size) * sector_size;
    487 		root_dir_entries = vs->vs_dir_entries[0] +
    488 			(vs->vs_dir_entries[1] << 8);
    489 
    490 		buf_size = root_dir_entries * sizeof(struct vfat_dir_entry);
    491 		dir = (struct vfat_dir_entry *) get_buffer(probe, root_start,
    492 							   buf_size);
    493 		if (dir)
    494 			vol_label = search_fat_label(dir, root_dir_entries);
    495 
    496 		if (!vol_label || !memcmp(vol_label, no_name, 11))
    497 			vol_label = ms->ms_label;
    498 		vol_serno = ms->ms_serno;
    499 
    500 		blkid_set_tag(probe->dev, "SEC_TYPE", "msdos",
    501 			      sizeof("msdos"));
    502 	} else {
    503 		/* Search the FAT32 root dir for the label attribute */
    504 		buf_size = vs->vs_cluster_size * sector_size;
    505 		start_data_sect = reserved + fat_size;
    506 
    507 		next = blkid_le32(vs->vs_root_cluster);
    508 		while (next && --maxloop) {
    509 			__u32 next_sect_off;
    510 			__u64 next_off, fat_entry_off;
    511 			int count;
    512 
    513 			next_sect_off = (next - 2) * vs->vs_cluster_size;
    514 			next_off = (start_data_sect + next_sect_off) *
    515 				sector_size;
    516 
    517 			dir = (struct vfat_dir_entry *)
    518 				get_buffer(probe, next_off, buf_size);
    519 			if (dir == NULL)
    520 				break;
    521 
    522 			count = buf_size / sizeof(struct vfat_dir_entry);
    523 
    524 			vol_label = search_fat_label(dir, count);
    525 			if (vol_label)
    526 				break;
    527 
    528 			/* get FAT entry */
    529 			fat_entry_off = (reserved * sector_size) +
    530 				(next * sizeof(__u32));
    531 			buf = get_buffer(probe, fat_entry_off, buf_size);
    532 			if (buf == NULL)
    533 				break;
    534 
    535 			/* set next cluster */
    536 			next = blkid_le32(*((__u32 *) buf) & 0x0fffffff);
    537 		}
    538 
    539 		if (!vol_label || !memcmp(vol_label, no_name, 11))
    540 			vol_label = vs->vs_label;
    541 		vol_serno = vs->vs_serno;
    542 	}
    543 
    544 	if (vol_label && memcmp(vol_label, no_name, 11)) {
    545 		if ((label_len = figure_label_len(vol_label, 11)))
    546 			label = vol_label;
    547 	}
    548 
    549 	/* We can't just print them as %04X, because they are unaligned */
    550 	sprintf(serno, "%02X%02X-%02X%02X", vol_serno[3], vol_serno[2],
    551 		vol_serno[1], vol_serno[0]);
    552 
    553 	blkid_set_tag(probe->dev, "LABEL", (const char *) label, label_len);
    554 	blkid_set_tag(probe->dev, "UUID", serno, sizeof(serno)-1);
    555 
    556 	return 0;
    557 }
    558 
    559 /*
    560  * The FAT filesystem could be without a magic string in superblock
    561  * (e.g. old floppies).  This heuristic for FAT detection is inspired
    562  * by http://vrfy.org/projects/volume_id/ and Linux kernel.
    563  * [7-Jul-2005, Karel Zak <kzak (at) redhat.com>]
    564  */
    565 static int probe_fat_nomagic(struct blkid_probe *probe,
    566 			     struct blkid_magic *id __BLKID_ATTR((unused)),
    567 			     unsigned char *buf)
    568 {
    569 	struct vfat_super_block *vs;
    570 
    571 	vs = (struct vfat_super_block *)buf;
    572 
    573 	/* heads check */
    574 	if (vs->vs_heads == 0)
    575 		return 1;
    576 
    577 	/* cluster size check*/
    578 	if (vs->vs_cluster_size == 0 ||
    579 	    (vs->vs_cluster_size & (vs->vs_cluster_size-1)))
    580 		return 1;
    581 
    582 	/* media check */
    583 	if (vs->vs_media < 0xf8 && vs->vs_media != 0xf0)
    584 		return 1;
    585 
    586 	/* fat counts(Linux kernel expects at least 1 FAT table) */
    587 	if (!vs->vs_fats)
    588 		return 1;
    589 
    590 	return probe_fat(probe, id, buf);
    591 }
    592 
    593 static int probe_ntfs(struct blkid_probe *probe,
    594 		      struct blkid_magic *id __BLKID_ATTR((unused)),
    595 		      unsigned char *buf)
    596 {
    597 	struct ntfs_super_block *ns;
    598 	struct master_file_table_record *mft;
    599 	struct file_attribute *attr;
    600 	char		uuid_str[17], label_str[129], *cp;
    601 	int		bytes_per_sector, sectors_per_cluster;
    602 	int		mft_record_size, attr_off, attr_len;
    603 	unsigned int	i, attr_type, val_len;
    604 	int		val_off;
    605 	__u64		nr_clusters;
    606 	blkid_loff_t off;
    607 	unsigned char *buf_mft, *val;
    608 
    609 	ns = (struct ntfs_super_block *) buf;
    610 
    611 	bytes_per_sector = ns->bios_parameter_block[0] +
    612 		(ns->bios_parameter_block[1]  << 8);
    613 	sectors_per_cluster = ns->bios_parameter_block[2];
    614 
    615 	if ((bytes_per_sector < 512) || (sectors_per_cluster == 0))
    616 		return 1;
    617 
    618 	if (ns->cluster_per_mft_record < 0)
    619 		mft_record_size = 1 << (0-ns->cluster_per_mft_record);
    620 	else
    621 		mft_record_size = ns->cluster_per_mft_record *
    622 			sectors_per_cluster * bytes_per_sector;
    623 	nr_clusters = blkid_le64(ns->number_of_sectors) / sectors_per_cluster;
    624 
    625 	if ((blkid_le64(ns->mft_cluster_location) > nr_clusters) ||
    626 	    (blkid_le64(ns->mft_mirror_cluster_location) > nr_clusters))
    627 		return 1;
    628 
    629 	off = blkid_le64(ns->mft_mirror_cluster_location) *
    630 		bytes_per_sector * sectors_per_cluster;
    631 
    632 	buf_mft = get_buffer(probe, off, mft_record_size);
    633 	if (!buf_mft)
    634 		return 1;
    635 
    636 	if (memcmp(buf_mft, "FILE", 4))
    637 		return 1;
    638 
    639 	off = blkid_le64(ns->mft_cluster_location) * bytes_per_sector *
    640 		sectors_per_cluster;
    641 
    642 	buf_mft = get_buffer(probe, off, mft_record_size);
    643 	if (!buf_mft)
    644 		return 1;
    645 
    646 	if (memcmp(buf_mft, "FILE", 4))
    647 		return 1;
    648 
    649 	off += MFT_RECORD_VOLUME * mft_record_size;
    650 
    651 	buf_mft = get_buffer(probe, off, mft_record_size);
    652 	if (!buf_mft)
    653 		return 1;
    654 
    655 	if (memcmp(buf_mft, "FILE", 4))
    656 		return 1;
    657 
    658 	mft = (struct master_file_table_record *) buf_mft;
    659 
    660 	attr_off = blkid_le16(mft->attrs_offset);
    661 	label_str[0] = 0;
    662 
    663 	while (1) {
    664 		attr = (struct file_attribute *) (buf_mft + attr_off);
    665 		attr_len = blkid_le16(attr->len);
    666 		attr_type = blkid_le32(attr->type);
    667 		val_off = blkid_le16(attr->value_offset);
    668 		val_len = blkid_le32(attr->value_len);
    669 
    670 		attr_off += attr_len;
    671 
    672 		if ((attr_off > mft_record_size) ||
    673 		    (attr_len == 0))
    674 			break;
    675 
    676 		if (attr_type == MFT_RECORD_ATTR_END)
    677 			break;
    678 
    679 		if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) {
    680 			if (val_len > sizeof(label_str))
    681 				val_len = sizeof(label_str)-1;
    682 
    683 			for (i=0, cp=label_str; i < val_len; i+=2,cp++) {
    684 				val = ((__u8 *) attr) + val_off + i;
    685 				*cp = val[0];
    686 				if (val[1])
    687 					*cp = '?';
    688 			}
    689 			*cp = 0;
    690 		}
    691 	}
    692 
    693 	sprintf(uuid_str, "%016llX", blkid_le64(ns->volume_serial));
    694 	blkid_set_tag(probe->dev, "UUID", uuid_str, 0);
    695 	if (label_str[0])
    696 		blkid_set_tag(probe->dev, "LABEL", label_str, 0);
    697 	return 0;
    698 }
    699 
    700 
    701 static int probe_xfs(struct blkid_probe *probe,
    702 		     struct blkid_magic *id __BLKID_ATTR((unused)),
    703 		     unsigned char *buf)
    704 {
    705 	struct xfs_super_block *xs;
    706 	const char *label = 0;
    707 
    708 	xs = (struct xfs_super_block *)buf;
    709 
    710 	if (strlen(xs->xs_fname))
    711 		label = xs->xs_fname;
    712 	blkid_set_tag(probe->dev, "LABEL", label, sizeof(xs->xs_fname));
    713 	set_uuid(probe->dev, xs->xs_uuid, 0);
    714 	return 0;
    715 }
    716 
    717 static int probe_reiserfs(struct blkid_probe *probe,
    718 			  struct blkid_magic *id, unsigned char *buf)
    719 {
    720 	struct reiserfs_super_block *rs = (struct reiserfs_super_block *) buf;
    721 	unsigned int blocksize;
    722 	const char *label = 0;
    723 
    724 	blocksize = blkid_le16(rs->rs_blocksize);
    725 
    726 	/* The blocksize must be at least 1k */
    727 	if ((blocksize >> 10) == 0)
    728 		return -BLKID_ERR_PARAM;
    729 
    730 	/* If the superblock is inside the journal, we have the wrong one */
    731 	if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block))
    732 		return -BLKID_ERR_BIG;
    733 
    734 	/* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */
    735 	if (id->bim_magic[6] == '2' || id->bim_magic[6] == '3') {
    736 		if (strlen(rs->rs_label))
    737 			label = rs->rs_label;
    738 		set_uuid(probe->dev, rs->rs_uuid, 0);
    739 	}
    740 	blkid_set_tag(probe->dev, "LABEL", label, sizeof(rs->rs_label));
    741 
    742 	return 0;
    743 }
    744 
    745 static int probe_reiserfs4(struct blkid_probe *probe,
    746 			   struct blkid_magic *id __BLKID_ATTR((unused)),
    747 			   unsigned char *buf)
    748 {
    749 	struct reiser4_super_block *rs4 = (struct reiser4_super_block *) buf;
    750 	const unsigned char *label = 0;
    751 
    752 	if (strlen((char *) rs4->rs4_label))
    753 		label = rs4->rs4_label;
    754 	set_uuid(probe->dev, rs4->rs4_uuid, 0);
    755 	blkid_set_tag(probe->dev, "LABEL", (const char *) label,
    756 		      sizeof(rs4->rs4_label));
    757 
    758 	return 0;
    759 }
    760 
    761 static int probe_jfs(struct blkid_probe *probe,
    762 		     struct blkid_magic *id __BLKID_ATTR((unused)),
    763 		     unsigned char *buf)
    764 {
    765 	struct jfs_super_block *js;
    766 	const char *label = 0;
    767 
    768 	js = (struct jfs_super_block *)buf;
    769 
    770 	if (strlen((char *) js->js_label))
    771 		label = (char *) js->js_label;
    772 	blkid_set_tag(probe->dev, "LABEL", label, sizeof(js->js_label));
    773 	set_uuid(probe->dev, js->js_uuid, 0);
    774 	return 0;
    775 }
    776 
    777 static int probe_luks(struct blkid_probe *probe,
    778 		       struct blkid_magic *id __BLKID_ATTR((unused)),
    779 		       unsigned char *buf)
    780 {
    781 	char uuid[40];
    782 	/* 168 is the offset to the 40 character uuid:
    783 	 * http://luks.endorphin.org/LUKS-on-disk-format.pdf */
    784 	strncpy(uuid, (char *) buf+168, 40);
    785 	blkid_set_tag(probe->dev, "UUID", uuid, sizeof(uuid));
    786 	return 0;
    787 }
    788 
    789 static int probe_romfs(struct blkid_probe *probe,
    790 		       struct blkid_magic *id __BLKID_ATTR((unused)),
    791 		       unsigned char *buf)
    792 {
    793 	struct romfs_super_block *ros;
    794 	const char *label = 0;
    795 
    796 	ros = (struct romfs_super_block *)buf;
    797 
    798 	if (strlen((char *) ros->ros_volume))
    799 		label = (char *) ros->ros_volume;
    800 	blkid_set_tag(probe->dev, "LABEL", label, 0);
    801 	return 0;
    802 }
    803 
    804 static int probe_cramfs(struct blkid_probe *probe,
    805 			struct blkid_magic *id __BLKID_ATTR((unused)),
    806 			unsigned char *buf)
    807 {
    808 	struct cramfs_super_block *csb;
    809 	const char *label = 0;
    810 
    811 	csb = (struct cramfs_super_block *)buf;
    812 
    813 	if (strlen((char *) csb->name))
    814 		label = (char *) csb->name;
    815 	blkid_set_tag(probe->dev, "LABEL", label, 0);
    816 	return 0;
    817 }
    818 
    819 static int probe_swap0(struct blkid_probe *probe,
    820 		       struct blkid_magic *id __BLKID_ATTR((unused)),
    821 		       unsigned char *buf __BLKID_ATTR((unused)))
    822 {
    823 	blkid_set_tag(probe->dev, "UUID", 0, 0);
    824 	blkid_set_tag(probe->dev, "LABEL", 0, 0);
    825 	return 0;
    826 }
    827 
    828 static int probe_swap1(struct blkid_probe *probe,
    829 		       struct blkid_magic *id __BLKID_ATTR((unused)),
    830 		       unsigned char *buf __BLKID_ATTR((unused)))
    831 {
    832 	struct swap_id_block *sws;
    833 
    834 	probe_swap0(probe, id, buf);
    835 	/*
    836 	 * Version 1 swap headers are always located at offset of 1024
    837 	 * bytes, although the swap signature itself is located at the
    838 	 * end of the page (which may vary depending on hardware
    839 	 * pagesize).
    840 	 */
    841 	sws = (struct swap_id_block *) get_buffer(probe, 1024, 1024);
    842 	if (!sws)
    843 		return 1;
    844 
    845 	/* arbitrary sanity check.. is there any garbage down there? */
    846 	if (sws->sws_pad[32] == 0 && sws->sws_pad[33] == 0)  {
    847 		if (sws->sws_volume[0])
    848 			blkid_set_tag(probe->dev, "LABEL", sws->sws_volume,
    849 				      sizeof(sws->sws_volume));
    850 		if (sws->sws_uuid[0])
    851 			set_uuid(probe->dev, sws->sws_uuid, 0);
    852 	}
    853 	return 0;
    854 }
    855 
    856 static int probe_iso9660(struct blkid_probe *probe,
    857 			 struct blkid_magic *id __BLKID_ATTR((unused)),
    858 			 unsigned char *buf)
    859 {
    860 	struct iso_volume_descriptor *iso;
    861 	const unsigned char *label;
    862 
    863 	iso = (struct iso_volume_descriptor *) buf;
    864 	label = iso->volume_id;
    865 
    866 	blkid_set_tag(probe->dev, "LABEL", (const char *) label,
    867 		      figure_label_len(label, 32));
    868 	return 0;
    869 }
    870 
    871 
    872 static const char
    873 *udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
    874 		 "NSR03", "TEA01", 0 };
    875 
    876 static int probe_udf(struct blkid_probe *probe,
    877 		     struct blkid_magic *id __BLKID_ATTR((unused)),
    878 		     unsigned char *buf __BLKID_ATTR((unused)))
    879 {
    880 	int j, bs;
    881 	struct iso_volume_descriptor *isosb;
    882 	const char ** m;
    883 
    884 	/* determine the block size by scanning in 2K increments
    885 	   (block sizes larger than 2K will be null padded) */
    886 	for (bs = 1; bs < 16; bs++) {
    887 		isosb = (struct iso_volume_descriptor *)
    888 			get_buffer(probe, bs*2048+32768, sizeof(isosb));
    889 		if (!isosb)
    890 			return 1;
    891 		if (isosb->vd_id[0])
    892 			break;
    893 	}
    894 
    895 	/* Scan up to another 64 blocks looking for additional VSD's */
    896 	for (j = 1; j < 64; j++) {
    897 		if (j > 1) {
    898 			isosb = (struct iso_volume_descriptor *)
    899 				get_buffer(probe, j*bs*2048+32768,
    900 					   sizeof(isosb));
    901 			if (!isosb)
    902 				return 1;
    903 		}
    904 		/* If we find NSR0x then call it udf:
    905 		   NSR01 for UDF 1.00
    906 		   NSR02 for UDF 1.50
    907 		   NSR03 for UDF 2.00 */
    908 		if (!memcmp(isosb->vd_id, "NSR0", 4))
    909 			return probe_iso9660(probe, id, buf);
    910 		for (m = udf_magic; *m; m++)
    911 			if (!memcmp(*m, isosb->vd_id, 5))
    912 				break;
    913 		if (*m == 0)
    914 			return 1;
    915 	}
    916 	return 1;
    917 }
    918 
    919 static int probe_ocfs(struct blkid_probe *probe,
    920 		      struct blkid_magic *id __BLKID_ATTR((unused)),
    921 		      unsigned char *buf)
    922 {
    923 	struct ocfs_volume_header ovh;
    924 	struct ocfs_volume_label ovl;
    925 	__u32 major;
    926 
    927 	memcpy(&ovh, buf, sizeof(ovh));
    928 	memcpy(&ovl, buf+512, sizeof(ovl));
    929 
    930 	major = ocfsmajor(ovh);
    931 	if (major == 1)
    932 		blkid_set_tag(probe->dev,"SEC_TYPE","ocfs1",sizeof("ocfs1"));
    933 	else if (major >= 9)
    934 		blkid_set_tag(probe->dev,"SEC_TYPE","ntocfs",sizeof("ntocfs"));
    935 
    936 	blkid_set_tag(probe->dev, "LABEL", ovl.label, ocfslabellen(ovl));
    937 	blkid_set_tag(probe->dev, "MOUNT", ovh.mount, ocfsmountlen(ovh));
    938 	set_uuid(probe->dev, ovl.vol_id, 0);
    939 	return 0;
    940 }
    941 
    942 static int probe_ocfs2(struct blkid_probe *probe,
    943 		       struct blkid_magic *id __BLKID_ATTR((unused)),
    944 		       unsigned char *buf)
    945 {
    946 	struct ocfs2_super_block *osb;
    947 
    948 	osb = (struct ocfs2_super_block *)buf;
    949 
    950 	blkid_set_tag(probe->dev, "LABEL", osb->s_label, sizeof(osb->s_label));
    951 	set_uuid(probe->dev, osb->s_uuid, 0);
    952 	return 0;
    953 }
    954 
    955 static int probe_oracleasm(struct blkid_probe *probe,
    956 			   struct blkid_magic *id __BLKID_ATTR((unused)),
    957 			   unsigned char *buf)
    958 {
    959 	struct oracle_asm_disk_label *dl;
    960 
    961 	dl = (struct oracle_asm_disk_label *)buf;
    962 
    963 	blkid_set_tag(probe->dev, "LABEL", dl->dl_id, sizeof(dl->dl_id));
    964 	return 0;
    965 }
    966 
    967 static int probe_gfs(struct blkid_probe *probe,
    968 		     struct blkid_magic *id __BLKID_ATTR((unused)),
    969 		     unsigned char *buf)
    970 {
    971 	struct gfs2_sb *sbd;
    972 	const char *label = 0;
    973 
    974 	sbd = (struct gfs2_sb *)buf;
    975 
    976 	if (blkid_be32(sbd->sb_fs_format) == GFS_FORMAT_FS &&
    977 	    blkid_be32(sbd->sb_multihost_format) == GFS_FORMAT_MULTI)
    978 	{
    979 		blkid_set_tag(probe->dev, "UUID", 0, 0);
    980 
    981 		if (strlen(sbd->sb_locktable))
    982 			label = sbd->sb_locktable;
    983 		blkid_set_tag(probe->dev, "LABEL", label, sizeof(sbd->sb_locktable));
    984 		return 0;
    985 	}
    986 	return 1;
    987 }
    988 
    989 static int probe_gfs2(struct blkid_probe *probe,
    990 		     struct blkid_magic *id __BLKID_ATTR((unused)),
    991 		     unsigned char *buf)
    992 {
    993 	struct gfs2_sb *sbd;
    994 	const char *label = 0;
    995 
    996 	sbd = (struct gfs2_sb *)buf;
    997 
    998 	if (blkid_be32(sbd->sb_fs_format) == GFS2_FORMAT_FS &&
    999 	    blkid_be32(sbd->sb_multihost_format) == GFS2_FORMAT_MULTI)
   1000 	{
   1001 		blkid_set_tag(probe->dev, "UUID", 0, 0);
   1002 
   1003 		if (strlen(sbd->sb_locktable))
   1004 			label = sbd->sb_locktable;
   1005 		blkid_set_tag(probe->dev, "LABEL", label, sizeof(sbd->sb_locktable));
   1006 		return 0;
   1007 	}
   1008 	return 1;
   1009 }
   1010 
   1011 static int probe_hfsplus(struct blkid_probe *probe __BLKID_ATTR((unused)),
   1012 			 struct blkid_magic *id __BLKID_ATTR((unused)),
   1013 			 unsigned char *buf)
   1014 {
   1015 	struct hfs_mdb *sbd = (struct hfs_mdb *)buf;
   1016 
   1017 	/* Check for a HFS+ volume embedded in a HFS volume */
   1018 	if (memcmp(sbd->embed_sig, "H+", 2) == 0)
   1019 		return 0;
   1020 
   1021 	return 1;
   1022 }
   1023 
   1024 #define LVM2_LABEL_SIZE 512
   1025 static unsigned int lvm2_calc_crc(const void *buf, unsigned int size)
   1026 {
   1027 	static const unsigned int crctab[] = {
   1028 		0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
   1029 		0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
   1030 		0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
   1031 		0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
   1032 	};
   1033 	unsigned int i, crc = 0xf597a6cf;
   1034 	const __u8 *data = (const __u8 *) buf;
   1035 
   1036 	for (i = 0; i < size; i++) {
   1037 		crc ^= *data++;
   1038 		crc = (crc >> 4) ^ crctab[crc & 0xf];
   1039 		crc = (crc >> 4) ^ crctab[crc & 0xf];
   1040 	}
   1041 	return crc;
   1042 }
   1043 
   1044 static int probe_lvm2(struct blkid_probe *probe,
   1045 			struct blkid_magic *id __BLKID_ATTR((unused)),
   1046 			unsigned char *buf)
   1047 {
   1048 	int sector = (id->bim_kboff) << 1;;
   1049 	struct lvm2_pv_label_header *label;
   1050 	label = (struct lvm2_pv_label_header *)buf;
   1051 	char *p, *q, uuid[40];
   1052 	unsigned int i, b;
   1053 
   1054 	/* buf is at 0k or 1k offset; find label inside */
   1055 	if (memcmp(buf, "LABELONE", 8) == 0) {
   1056 		label = (struct lvm2_pv_label_header *)buf;
   1057 	} else if (memcmp(buf + 512, "LABELONE", 8) == 0) {
   1058 		label = (struct lvm2_pv_label_header *)(buf + 512);
   1059 		sector++;
   1060 	} else {
   1061 		return 1;
   1062 	}
   1063 
   1064 	if (blkid_le64(label->sector_xl) != (unsigned) sector) {
   1065 		DBG(DEBUG_PROBE,
   1066 		    printf("LVM2: label for sector %llu found at sector %d\n",
   1067 			   blkid_le64(label->sector_xl), sector));
   1068 		return 1;
   1069 	}
   1070 
   1071 	if (lvm2_calc_crc(&label->offset_xl, LVM2_LABEL_SIZE -
   1072 			  ((char *)&label->offset_xl - (char *)label)) !=
   1073 			blkid_le32(label->crc_xl)) {
   1074 		DBG(DEBUG_PROBE,
   1075 		    printf("LVM2: label checksum incorrect at sector %d\n",
   1076 			   sector));
   1077 		return 1;
   1078 	}
   1079 
   1080 	for (i=0, b=1, p=uuid, q= (char *) label->pv_uuid; i <= 32;
   1081 	     i++, b <<= 1) {
   1082 		if (b & 0x4444440)
   1083 			*p++ = '-';
   1084 		*p++ = *q++;
   1085 	}
   1086 
   1087 	blkid_set_tag(probe->dev, "UUID", uuid, LVM2_ID_LEN+6);
   1088 
   1089 	return 0;
   1090 }
   1091 /*
   1092  * BLKID_BLK_OFFS is at least as large as the highest bim_kboff defined
   1093  * in the type_array table below + bim_kbalign.
   1094  *
   1095  * When probing for a lot of magics, we handle everything in 1kB buffers so
   1096  * that we don't have to worry about reading each combination of block sizes.
   1097  */
   1098 #define BLKID_BLK_OFFS	64	/* currently reiserfs */
   1099 
   1100 /*
   1101  * Various filesystem magics that we can check for.  Note that kboff and
   1102  * sboff are in kilobytes and bytes respectively.  All magics are in
   1103  * byte strings so we don't worry about endian issues.
   1104  */
   1105 static struct blkid_magic type_array[] = {
   1106 /*  type     kboff   sboff len  magic			probe */
   1107   { "oracleasm", 0,	32,  8, "ORCLDISK",		probe_oracleasm },
   1108   { "ntfs",	 0,	 3,  8, "NTFS    ",		probe_ntfs },
   1109   { "jbd",	 1,   0x38,  2, "\123\357",		probe_jbd },
   1110   { "ext4dev",	 1,   0x38,  2, "\123\357",		probe_ext4dev },
   1111   { "ext4",	 1,   0x38,  2, "\123\357",		probe_ext4 },
   1112   { "ext3",	 1,   0x38,  2, "\123\357",		probe_ext3 },
   1113   { "ext2",	 1,   0x38,  2, "\123\357",		probe_ext2 },
   1114   { "reiserfs",	 8,   0x34,  8, "ReIsErFs",		probe_reiserfs },
   1115   { "reiserfs", 64,   0x34,  9, "ReIsEr2Fs",		probe_reiserfs },
   1116   { "reiserfs", 64,   0x34,  9, "ReIsEr3Fs",		probe_reiserfs },
   1117   { "reiserfs", 64,   0x34,  8, "ReIsErFs",		probe_reiserfs },
   1118   { "reiserfs",	 8,	20,  8, "ReIsErFs",		probe_reiserfs },
   1119   { "reiser4",  64,	 0,  7, "ReIsEr4",		probe_reiserfs4 },
   1120   { "gfs2",     64,      0,  4, "\x01\x16\x19\x70",     probe_gfs2 },
   1121   { "gfs",      64,      0,  4, "\x01\x16\x19\x70",     probe_gfs },
   1122   { "vfat",      0,   0x52,  5, "MSWIN",                probe_fat },
   1123   { "vfat",      0,   0x52,  8, "FAT32   ",             probe_fat },
   1124   { "vfat",      0,   0x36,  5, "MSDOS",                probe_fat },
   1125   { "vfat",      0,   0x36,  8, "FAT16   ",             probe_fat },
   1126   { "vfat",      0,   0x36,  8, "FAT12   ",             probe_fat },
   1127   { "vfat",      0,      0,  1, "\353",                 probe_fat_nomagic },
   1128   { "vfat",      0,      0,  1, "\351",                 probe_fat_nomagic },
   1129   { "vfat",      0,  0x1fe,  2, "\125\252",             probe_fat_nomagic },
   1130   { "minix",     1,   0x10,  2, "\177\023",             0 },
   1131   { "minix",     1,   0x10,  2, "\217\023",             0 },
   1132   { "minix",	 1,   0x10,  2, "\150\044",		0 },
   1133   { "minix",	 1,   0x10,  2, "\170\044",		0 },
   1134   { "vxfs",	 1,	 0,  4, "\365\374\001\245",	0 },
   1135   { "xfs",	 0,	 0,  4, "XFSB",			probe_xfs },
   1136   { "romfs",	 0,	 0,  8, "-rom1fs-",		probe_romfs },
   1137   { "bfs",	 0,	 0,  4, "\316\372\173\033",	0 },
   1138   { "cramfs",	 0,	 0,  4, "E=\315\050",		probe_cramfs },
   1139   { "qnx4",	 0,	 4,  6, "QNX4FS",		0 },
   1140   { "udf",	32,	 1,  5, "BEA01",		probe_udf },
   1141   { "udf",	32,	 1,  5, "BOOT2",		probe_udf },
   1142   { "udf",	32,	 1,  5, "CD001",		probe_udf },
   1143   { "udf",	32,	 1,  5, "CDW02",		probe_udf },
   1144   { "udf",	32,	 1,  5, "NSR02",		probe_udf },
   1145   { "udf",	32,	 1,  5, "NSR03",		probe_udf },
   1146   { "udf",	32,	 1,  5, "TEA01",		probe_udf },
   1147   { "iso9660",	32,	 1,  5, "CD001",		probe_iso9660 },
   1148   { "iso9660",	32,	 9,  5, "CDROM",		probe_iso9660 },
   1149   { "jfs",	32,	 0,  4, "JFS1",			probe_jfs },
   1150   { "hfsplus",	 1,	 0,  2, "BD",			probe_hfsplus },
   1151   { "hfsplus",	 1,	 0,  2, "H+",			0 },
   1152   { "hfs",	 1,	 0,  2, "BD",			0 },
   1153   { "ufs",	 8,  0x55c,  4, "T\031\001\000",	0 },
   1154   { "hpfs",	 8,	 0,  4, "I\350\225\371",	0 },
   1155   { "sysv",	 0,  0x3f8,  4, "\020~\030\375",	0 },
   1156   { "swap",	 0,  0xff6, 10, "SWAP-SPACE",		probe_swap0 },
   1157   { "swap",	 0,  0xff6, 10, "SWAPSPACE2",		probe_swap1 },
   1158   { "swsuspend", 0,  0xff6,  9, "S1SUSPEND",		probe_swap1 },
   1159   { "swsuspend", 0,  0xff6,  9, "S2SUSPEND",		probe_swap1 },
   1160   { "swap",	 0, 0x1ff6, 10, "SWAP-SPACE",		probe_swap0 },
   1161   { "swap",	 0, 0x1ff6, 10, "SWAPSPACE2",		probe_swap1 },
   1162   { "swsuspend", 0, 0x1ff6,  9, "S1SUSPEND",		probe_swap1 },
   1163   { "swsuspend", 0, 0x1ff6,  9, "S2SUSPEND",		probe_swap1 },
   1164   { "swap",	 0, 0x3ff6, 10, "SWAP-SPACE",		probe_swap0 },
   1165   { "swap",	 0, 0x3ff6, 10, "SWAPSPACE2",		probe_swap1 },
   1166   { "swsuspend", 0, 0x3ff6,  9, "S1SUSPEND",		probe_swap1 },
   1167   { "swsuspend", 0, 0x3ff6,  9, "S2SUSPEND",		probe_swap1 },
   1168   { "swap",	 0, 0x7ff6, 10, "SWAP-SPACE",		probe_swap0 },
   1169   { "swap",	 0, 0x7ff6, 10, "SWAPSPACE2",		probe_swap1 },
   1170   { "swsuspend", 0, 0x7ff6,  9, "S1SUSPEND",		probe_swap1 },
   1171   { "swsuspend", 0, 0x7ff6,  9, "S2SUSPEND",		probe_swap1 },
   1172   { "swap",	 0, 0xfff6, 10, "SWAP-SPACE",		probe_swap0 },
   1173   { "swap",	 0, 0xfff6, 10, "SWAPSPACE2",		probe_swap1 },
   1174   { "swsuspend", 0, 0xfff6,  9, "S1SUSPEND",		probe_swap1 },
   1175   { "swsuspend", 0, 0xfff6,  9, "S2SUSPEND",		probe_swap1 },
   1176   { "ocfs",	 0,	 8,  9,	"OracleCFS",		probe_ocfs },
   1177   { "ocfs2",	 1,	 0,  6,	"OCFSV2",		probe_ocfs2 },
   1178   { "ocfs2",	 2,	 0,  6,	"OCFSV2",		probe_ocfs2 },
   1179   { "ocfs2",	 4,	 0,  6,	"OCFSV2",		probe_ocfs2 },
   1180   { "ocfs2",	 8,	 0,  6,	"OCFSV2",		probe_ocfs2 },
   1181   { "crypt_LUKS", 0,	 0,  6,	"LUKS\xba\xbe",		probe_luks },
   1182   { "squashfs",	 0,	 0,  4,	"sqsh",			0 },
   1183   { "squashfs",	 0,	 0,  4,	"hsqs",			0 },
   1184   { "lvm2pv",	 0,  0x218,  8, "LVM2 001",		probe_lvm2 },
   1185   { "lvm2pv",	 0,  0x018,  8, "LVM2 001",		probe_lvm2 },
   1186   { "lvm2pv",	 1,  0x018,  8, "LVM2 001",		probe_lvm2 },
   1187   { "lvm2pv",	 1,  0x218,  8, "LVM2 001",		probe_lvm2 },
   1188   {   NULL,	 0,	 0,  0, NULL,			NULL }
   1189 };
   1190 
   1191 /*
   1192  * Verify that the data in dev is consistent with what is on the actual
   1193  * block device (using the devname field only).  Normally this will be
   1194  * called when finding items in the cache, but for long running processes
   1195  * is also desirable to revalidate an item before use.
   1196  *
   1197  * If we are unable to revalidate the data, we return the old data and
   1198  * do not set the BLKID_BID_FL_VERIFIED flag on it.
   1199  */
   1200 blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
   1201 {
   1202 	struct blkid_magic *id;
   1203 	struct blkid_probe probe;
   1204 	blkid_tag_iterate iter;
   1205 	unsigned char *buf;
   1206 	const char *type, *value;
   1207 	struct stat st;
   1208 	time_t diff, now;
   1209 	int idx;
   1210 
   1211 	if (!dev)
   1212 		return NULL;
   1213 
   1214 	now = time(0);
   1215 	diff = now - dev->bid_time;
   1216 
   1217 	if ((now > dev->bid_time) && (diff > 0) &&
   1218 	    ((diff < BLKID_PROBE_MIN) ||
   1219 	     (dev->bid_flags & BLKID_BID_FL_VERIFIED &&
   1220 	      diff < BLKID_PROBE_INTERVAL)))
   1221 		return dev;
   1222 
   1223 	DBG(DEBUG_PROBE,
   1224 	    printf("need to revalidate %s (time since last check %llu)\n",
   1225 		   dev->bid_name, (unsigned long long)diff));
   1226 
   1227 	if (((probe.fd = open(dev->bid_name, O_RDONLY)) < 0) ||
   1228 	    (fstat(probe.fd, &st) < 0)) {
   1229 		if (probe.fd >= 0) close(probe.fd);
   1230 		if (errno != EPERM) {
   1231 			blkid_free_dev(dev);
   1232 			return NULL;
   1233 		}
   1234 		/* We don't have read permission, just return cache data. */
   1235 		DBG(DEBUG_PROBE,
   1236 		    printf("returning unverified data for %s\n",
   1237 			   dev->bid_name));
   1238 		return dev;
   1239 	}
   1240 
   1241 	probe.cache = cache;
   1242 	probe.dev = dev;
   1243 	probe.sbbuf = 0;
   1244 	probe.buf = 0;
   1245 	probe.buf_max = 0;
   1246 
   1247 	/*
   1248 	 * Iterate over the type array.  If we already know the type,
   1249 	 * then try that first.  If it doesn't work, then blow away
   1250 	 * the type information, and try again.
   1251 	 *
   1252 	 */
   1253 try_again:
   1254 	type = 0;
   1255 	if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) {
   1256 		uuid_t	uuid;
   1257 
   1258 		if (check_mdraid(probe.fd, uuid) == 0) {
   1259 			set_uuid(dev, uuid, 0);
   1260 			type = "mdraid";
   1261 			goto found_type;
   1262 		}
   1263 	}
   1264 	for (id = type_array; id->bim_type; id++) {
   1265 		if (dev->bid_type &&
   1266 		    strcmp(id->bim_type, dev->bid_type))
   1267 			continue;
   1268 
   1269 		idx = id->bim_kboff + (id->bim_sboff >> 10);
   1270 		buf = get_buffer(&probe, idx << 10, 1024);
   1271 		if (!buf)
   1272 			continue;
   1273 
   1274 		if (memcmp(id->bim_magic, buf + (id->bim_sboff&0x3ff),
   1275 			   id->bim_len))
   1276 			continue;
   1277 
   1278 		if ((id->bim_probe == NULL) ||
   1279 		    (id->bim_probe(&probe, id, buf) == 0)) {
   1280 			type = id->bim_type;
   1281 			goto found_type;
   1282 		}
   1283 	}
   1284 
   1285 	if (!id->bim_type && dev->bid_type) {
   1286 		/*
   1287 		 * Zap the device filesystem information and try again
   1288 		 */
   1289 		DBG(DEBUG_PROBE,
   1290 		    printf("previous fs type %s not valid, "
   1291 			   "trying full probe\n", dev->bid_type));
   1292 		iter = blkid_tag_iterate_begin(dev);
   1293 		while (blkid_tag_next(iter, &type, &value) == 0)
   1294 			blkid_set_tag(dev, type, 0, 0);
   1295 		blkid_tag_iterate_end(iter);
   1296 		goto try_again;
   1297 	}
   1298 
   1299 	if (!dev->bid_type) {
   1300 		blkid_free_dev(dev);
   1301 		dev = 0;
   1302 		goto found_type;
   1303 	}
   1304 
   1305 found_type:
   1306 	if (dev && type) {
   1307 		dev->bid_devno = st.st_rdev;
   1308 		dev->bid_time = time(0);
   1309 		dev->bid_flags |= BLKID_BID_FL_VERIFIED;
   1310 		cache->bic_flags |= BLKID_BIC_FL_CHANGED;
   1311 
   1312 		blkid_set_tag(dev, "TYPE", type, 0);
   1313 
   1314 		DBG(DEBUG_PROBE, printf("%s: devno 0x%04llx, type %s\n",
   1315 			   dev->bid_name, (long long)st.st_rdev, type));
   1316 	}
   1317 
   1318 	if (probe.sbbuf)
   1319 		free(probe.sbbuf);
   1320 	if (probe.buf)
   1321 		free(probe.buf);
   1322 	if (probe.fd >= 0)
   1323 		close(probe.fd);
   1324 
   1325 	return dev;
   1326 }
   1327 
   1328 int blkid_known_fstype(const char *fstype)
   1329 {
   1330 	struct blkid_magic *id;
   1331 
   1332 	for (id = type_array; id->bim_type; id++) {
   1333 		if (strcmp(fstype, id->bim_type) == 0)
   1334 			return 1;
   1335 	}
   1336 	return 0;
   1337 }
   1338 
   1339 #ifdef TEST_PROGRAM
   1340 int main(int argc, char **argv)
   1341 {
   1342 	blkid_dev dev;
   1343 	blkid_cache cache;
   1344 	int ret;
   1345 
   1346 	if (argc != 2) {
   1347 		fprintf(stderr, "Usage: %s device\n"
   1348 			"Probe a single device to determine type\n", argv[0]);
   1349 		exit(1);
   1350 	}
   1351 	if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) {
   1352 		fprintf(stderr, "%s: error creating cache (%d)\n",
   1353 			argv[0], ret);
   1354 		exit(1);
   1355 	}
   1356 	dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL);
   1357 	if (!dev) {
   1358 		printf("%s: %s has an unsupported type\n", argv[0], argv[1]);
   1359 		return (1);
   1360 	}
   1361 	printf("TYPE='%s'\n", dev->bid_type ? dev->bid_type : "(null)");
   1362 	if (dev->bid_label)
   1363 		printf("LABEL='%s'\n", dev->bid_label);
   1364 	if (dev->bid_uuid)
   1365 		printf("UUID='%s'\n", dev->bid_uuid);
   1366 
   1367 	blkid_free_dev(dev);
   1368 	return (0);
   1369 }
   1370 #endif
   1371