• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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 
figure_label_len(const unsigned char * label,int len)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 
get_buffer(struct blkid_probe * pr,blkid_loff_t off,size_t len)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  */
check_mdraid(int fd,unsigned char * ret_uuid)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 
set_uuid(blkid_dev dev,uuid_t uuid,const char * tag)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 
get_ext2_info(blkid_dev dev,struct blkid_magic * id,unsigned char * buf)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  */
fs_proc_check(const char * fs_name)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  */
check_for_modules(const char * fs_name)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 
system_supports_ext4(void)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 
system_supports_ext4dev(void)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 
probe_ext4dev(struct blkid_probe * probe,struct blkid_magic * id,unsigned char * buf)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 
probe_ext4(struct blkid_probe * probe,struct blkid_magic * id,unsigned char * buf)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 
probe_ext3(struct blkid_probe * probe,struct blkid_magic * id,unsigned char * buf)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 
probe_ext2(struct blkid_probe * probe,struct blkid_magic * id,unsigned char * buf)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 
probe_jbd(struct blkid_probe * probe,struct blkid_magic * id,unsigned char * buf)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 
search_fat_label(struct vfat_dir_entry * dir,int count)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 */
probe_fat(struct blkid_probe * probe,struct blkid_magic * id __BLKID_ATTR ((unused)),unsigned char * buf)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@redhat.com>]
564  */
probe_fat_nomagic(struct blkid_probe * probe,struct blkid_magic * id __BLKID_ATTR ((unused)),unsigned char * buf)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 
probe_ntfs(struct blkid_probe * probe,struct blkid_magic * id __BLKID_ATTR ((unused)),unsigned char * buf)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 
probe_xfs(struct blkid_probe * probe,struct blkid_magic * id __BLKID_ATTR ((unused)),unsigned char * buf)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 
probe_reiserfs(struct blkid_probe * probe,struct blkid_magic * id,unsigned char * buf)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 
probe_reiserfs4(struct blkid_probe * probe,struct blkid_magic * id __BLKID_ATTR ((unused)),unsigned char * buf)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 
probe_jfs(struct blkid_probe * probe,struct blkid_magic * id __BLKID_ATTR ((unused)),unsigned char * buf)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 
probe_luks(struct blkid_probe * probe,struct blkid_magic * id __BLKID_ATTR ((unused)),unsigned char * buf)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 
probe_romfs(struct blkid_probe * probe,struct blkid_magic * id __BLKID_ATTR ((unused)),unsigned char * buf)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 
probe_cramfs(struct blkid_probe * probe,struct blkid_magic * id __BLKID_ATTR ((unused)),unsigned char * buf)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 
probe_swap0(struct blkid_probe * probe,struct blkid_magic * id __BLKID_ATTR ((unused)),unsigned char * buf __BLKID_ATTR ((unused)))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 
probe_swap1(struct blkid_probe * probe,struct blkid_magic * id __BLKID_ATTR ((unused)),unsigned char * buf __BLKID_ATTR ((unused)))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 
probe_iso9660(struct blkid_probe * probe,struct blkid_magic * id __BLKID_ATTR ((unused)),unsigned char * buf)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 
probe_udf(struct blkid_probe * probe,struct blkid_magic * id __BLKID_ATTR ((unused)),unsigned char * buf __BLKID_ATTR ((unused)))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 
probe_ocfs(struct blkid_probe * probe,struct blkid_magic * id __BLKID_ATTR ((unused)),unsigned char * buf)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 
probe_ocfs2(struct blkid_probe * probe,struct blkid_magic * id __BLKID_ATTR ((unused)),unsigned char * buf)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 
probe_oracleasm(struct blkid_probe * probe,struct blkid_magic * id __BLKID_ATTR ((unused)),unsigned char * buf)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 
probe_gfs(struct blkid_probe * probe,struct blkid_magic * id __BLKID_ATTR ((unused)),unsigned char * buf)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 
probe_gfs2(struct blkid_probe * probe,struct blkid_magic * id __BLKID_ATTR ((unused)),unsigned char * buf)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 
probe_hfsplus(struct blkid_probe * probe __BLKID_ATTR ((unused)),struct blkid_magic * id __BLKID_ATTR ((unused)),unsigned char * buf)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
lvm2_calc_crc(const void * buf,unsigned int size)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 
probe_lvm2(struct blkid_probe * probe,struct blkid_magic * id __BLKID_ATTR ((unused)),unsigned char * buf)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  */
blkid_verify(blkid_cache cache,blkid_dev dev)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 
blkid_known_fstype(const char * fstype)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
main(int argc,char ** argv)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