1e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o/*
2e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * probe.c - identify a block device by its contents, and return a dev
3e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o *           struct with the details
4e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o *
5e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * Copyright (C) 1999 by Andries Brouwer
650b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
7e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * Copyright (C) 2001 by Andreas Dilger
82f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
9e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o *
10e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * %Begin-Header%
11e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * This file may be redistributed under the terms of the
12e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * GNU Lesser General Public License.
13e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * %End-Header%
14e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o */
15e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
16e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <stdio.h>
17e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <string.h>
18e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <stdlib.h>
19e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <unistd.h>
20e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <fcntl.h>
213a538e42441afa5e5b34942062acb976e0d345f6Theodore Ts'o#include <ctype.h>
22e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <sys/types.h>
23e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#ifdef HAVE_SYS_STAT_H
24e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <sys/stat.h>
25e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#endif
26e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#ifdef HAVE_SYS_MKDEV_H
27e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <sys/mkdev.h>
28e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#endif
2918f734301012301efbeb87a7c67f6cf82f1721d7Eric Sandeen#ifdef __linux__
30cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o#include <sys/utsname.h>
3118f734301012301efbeb87a7c67f6cf82f1721d7Eric Sandeen#endif
32e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#ifdef HAVE_ERRNO_H
33e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <errno.h>
34e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#endif
357a603aa89fcffb8798eca34ca3858db6f0393046Theodore Ts'o#include "blkidP.h"
36e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include "uuid/uuid.h"
37e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include "probe.h"
38e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
3945a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'ostatic int figure_label_len(const unsigned char *label, int len)
4045a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o{
4145a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o	const unsigned char *end = label + len - 1;
4245a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o
4345a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o	while ((*end == ' ' || *end == 0) && end >= label)
4445a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o		--end;
45e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (end >= label)
4645a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o		return end - label + 1;
4745a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o	return 0;
4845a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o}
4945a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o
50efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ostatic unsigned char *get_buffer(struct blkid_probe *pr,
51cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o			  blkid_loff_t off, size_t len)
52ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o{
53ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	ssize_t		ret_read;
54ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	unsigned char	*newbuf;
55ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o
56ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	if (off + len <= SB_BUFFER_SIZE) {
57ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		if (!pr->sbbuf) {
58ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			pr->sbbuf = malloc(SB_BUFFER_SIZE);
59ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			if (!pr->sbbuf)
60ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o				return NULL;
61ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			if (lseek(pr->fd, 0, SEEK_SET) < 0)
62ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o				return NULL;
63ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			ret_read = read(pr->fd, pr->sbbuf, SB_BUFFER_SIZE);
64ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			if (ret_read < 0)
65ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o				ret_read = 0;
66ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			pr->sb_valid = ret_read;
67ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		}
68ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		if (off+len > pr->sb_valid)
69ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			return NULL;
70ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		return pr->sbbuf + off;
71ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	} else {
72ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		if (len > pr->buf_max) {
73ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			newbuf = realloc(pr->buf, len);
74ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			if (newbuf == NULL)
75ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o				return NULL;
76ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			pr->buf = newbuf;
77ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			pr->buf_max = len;
78ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		}
79cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		if (blkid_llseek(pr->fd, off, SEEK_SET) < 0)
80ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			return NULL;
81ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		ret_read = read(pr->fd, pr->buf, len);
82ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		if (ret_read != (ssize_t) len)
83ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			return NULL;
84ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		return pr->buf;
85ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	}
86ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o}
87ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o
88ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o
89e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o/*
9050b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o * This is a special case code to check for an MDRAID device.  We do
9150b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o * this special since it requires checking for a superblock at the end
9250b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o * of the device.
93e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o */
9450b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'ostatic int check_mdraid(int fd, unsigned char *ret_uuid)
95e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o{
9650b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	struct mdp_superblock_s *md;
9750b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	blkid_loff_t		offset;
9850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	char			buf[4096];
99efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
10050b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	if (fd < 0)
101e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		return -BLKID_ERR_PARAM;
102e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
10350b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	offset = (blkid_get_dev_size(fd) & ~((blkid_loff_t)65535)) - 65536;
104e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
105e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	if (blkid_llseek(fd, offset, 0) < 0 ||
10650b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	    read(fd, buf, 4096) != 4096)
107e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		return -BLKID_ERR_IO;
108e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
10950b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	/* Check for magic number */
1106b8be16e3ac9c5fc350ea25d864df7bb6e2f6f4cSergey Vlasov	if (memcmp("\251+N\374", buf, 4) && memcmp("\374N+\251", buf, 4))
111e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		return -BLKID_ERR_PARAM;
112e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
11350b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	if (!ret_uuid)
11450b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		return 0;
11550b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	*ret_uuid = 0;
116e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
11750b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	/* The MD UUID is not contiguous in the superblock, make it so */
11850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	md = (struct mdp_superblock_s *)buf;
11950b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) {
12050b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		memcpy(ret_uuid, &md->set_uuid0, 4);
121c9105ffbe55d2a25dea9fab0595baace3a59bd51Sergey Vlasov		memcpy(ret_uuid + 4, &md->set_uuid1, 12);
122e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	}
12350b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	return 0;
12450b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o}
125e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
126d4e0b1c6f5aa8c6a248d9149ed5634a310952411Theodore Ts'ostatic void set_uuid(blkid_dev dev, uuid_t uuid, const char *tag)
12750b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o{
12850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	char	str[37];
129e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
13050b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	if (!uuid_is_null(uuid)) {
13150b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		uuid_unparse(uuid, str);
132ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o		blkid_set_tag(dev, tag ? tag : "UUID", str, sizeof(str));
13350b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	}
134e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o}
135e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
1362921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'ostatic void get_ext2_info(blkid_dev dev, struct blkid_magic *id,
1372921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o			  unsigned char *buf)
1382e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o{
1392e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o	struct ext2_super_block *es = (struct ext2_super_block *) buf;
1402e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o	const char *label = 0;
1412e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o
142efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n",
1432e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o		   blkid_le32(es->s_feature_compat),
1442e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o		   blkid_le32(es->s_feature_incompat),
1452e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o		   blkid_le32(es->s_feature_ro_compat)));
1462e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o
1477369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	if (strlen(es->s_volume_name))
1482e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o		label = es->s_volume_name;
1497369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	blkid_set_tag(dev, "LABEL", label, sizeof(es->s_volume_name));
1502e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o
151ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o	set_uuid(dev, es->s_uuid, 0);
1522921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o
1532921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	if ((es->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
1542921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	    !uuid_is_null(es->s_journal_uuid))
1552921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o		set_uuid(dev, es->s_journal_uuid, "EXT_JOURNAL");
1562921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o
1572921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	if (strcmp(id->bim_type, "ext2") &&
1582921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	    ((blkid_le32(es->s_feature_incompat) &
1592921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	      EXT2_FEATURE_INCOMPAT_UNSUPPORTED) == 0))
1602921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o		blkid_set_tag(dev, "SEC_TYPE", "ext2", sizeof("ext2"));
1612e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o}
1622e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o
163cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o/*
164cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o * Check to see if a filesystem is in /proc/filesystems.
165cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o * Returns 1 if found, 0 if not
166cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o */
1673a538e42441afa5e5b34942062acb976e0d345f6Theodore Ts'ostatic int fs_proc_check(const char *fs_name)
168cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o{
169cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	FILE	*f;
170cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	char	buf[80], *cp, *t;
171cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o
172cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	f = fopen("/proc/filesystems", "r");
173cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	if (!f)
174cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o		return (0);
175cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	while (!feof(f)) {
176cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o		if (!fgets(buf, sizeof(buf), f))
177cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o			break;
178cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o		cp = buf;
179cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o		if (!isspace(*cp)) {
180cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o			while (*cp && !isspace(*cp))
181cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o				cp++;
182cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o		}
183cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o		while (*cp && isspace(*cp))
184cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o			cp++;
185cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o		if ((t = strchr(cp, '\n')) != NULL)
186cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o			*t = 0;
187cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o		if ((t = strchr(cp, '\t')) != NULL)
188cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o			*t = 0;
189cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o		if ((t = strchr(cp, ' ')) != NULL)
190cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o			*t = 0;
191cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o		if (!strcmp(fs_name, cp)) {
192cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o			fclose(f);
193cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o			return (1);
194cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o		}
195cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	}
196cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	fclose(f);
197cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	return (0);
198cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o}
199cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o
200cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o/*
201cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o * Check to see if a filesystem is available as a module
202cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o * Returns 1 if found, 0 if not
203cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o */
2043a538e42441afa5e5b34942062acb976e0d345f6Theodore Ts'ostatic int check_for_modules(const char *fs_name)
205cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o{
20618f734301012301efbeb87a7c67f6cf82f1721d7Eric Sandeen#ifdef __linux__
207cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	struct utsname	uts;
208cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	FILE		*f;
209249c962ad8f2daabc403577d0c994e4c986c8f9aKarel Zak	char		buf[1024], *cp;
210249c962ad8f2daabc403577d0c994e4c986c8f9aKarel Zak	int		namesz;
211cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o
212cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	if (uname(&uts))
213cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o		return (0);
214cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	snprintf(buf, sizeof(buf), "/lib/modules/%s/modules.dep", uts.release);
215cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o
216cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	f = fopen(buf, "r");
217cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	if (!f)
218cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o		return (0);
219249c962ad8f2daabc403577d0c994e4c986c8f9aKarel Zak
220249c962ad8f2daabc403577d0c994e4c986c8f9aKarel Zak	namesz = strlen(fs_name);
221249c962ad8f2daabc403577d0c994e4c986c8f9aKarel Zak
222cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	while (!feof(f)) {
223cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o		if (!fgets(buf, sizeof(buf), f))
224cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o			break;
225cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o		if ((cp = strchr(buf, ':')) != NULL)
226cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o			*cp = 0;
227cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o		else
228cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o			continue;
229cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o		if ((cp = strrchr(buf, '/')) != NULL)
230cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o			cp++;
231f2fe5da31deebc689bb64e71c8e873efc925d312Eric Sandeen		else
232f2fe5da31deebc689bb64e71c8e873efc925d312Eric Sandeen			cp = buf;
233249c962ad8f2daabc403577d0c994e4c986c8f9aKarel Zak		if (!strncmp(cp, fs_name, namesz) &&
234249c962ad8f2daabc403577d0c994e4c986c8f9aKarel Zak		    (!strcmp(cp + namesz, ".ko") ||
235249c962ad8f2daabc403577d0c994e4c986c8f9aKarel Zak		     !strcmp(cp + namesz, ".ko.gz"))) {
2366964a17720ca88acd2075b57dde9c381f093e492Theodore Ts'o			fclose(f);
237cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o			return (1);
2386964a17720ca88acd2075b57dde9c381f093e492Theodore Ts'o		}
239cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	}
240cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	fclose(f);
24118f734301012301efbeb87a7c67f6cf82f1721d7Eric Sandeen#endif
242cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	return (0);
243cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o}
244cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o
2451361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'ostatic int linux_version_code()
2461361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o{
2471361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o#ifdef __linux__
2481361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	struct utsname	ut;
249e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	static int	version_code = -1;
2501361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	int		major, minor, rev;
2511361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	char		*endptr;
2521361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	const char 	*cp;
2531361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o
2541361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	if (version_code > 0)
2551361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o		return version_code;
2561361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o
2571361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	if (uname(&ut))
2581361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o		return 0;
2591361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	cp = ut.release;
2601361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o
2611361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	major = strtol(cp, &endptr, 10);
2621361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	if (cp == endptr || *endptr != '.')
2631361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o		return 0;
2641361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	cp = endptr + 1;
2651361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	minor = strtol(cp, &endptr, 10);
2661361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	if (cp == endptr || *endptr != '.')
2671361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o		return 0;
2681361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	cp = endptr + 1;
2691361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	rev = strtol(cp, &endptr, 10);
2701361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	if (cp == endptr)
2711361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o		return 0;
2721361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	version_code = (((major * 256) + minor) * 256) + rev;
2731361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	return version_code;
2741361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o#else
2751361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	return 0;
2761361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o#endif
2771361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o}
2781361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o
2791361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o#define EXT4_SUPPORTS_EXT2 (2 * 65536 + 6*256 + 29)
2801361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o
2811361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'ostatic int system_supports_ext2(void)
2821361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o{
2831361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	static time_t	last_check = 0;
2841361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	static int	ret = -1;
2851361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	time_t		now = time(0);
2861361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o
2871361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	if (ret != -1 || (now - last_check) < 5)
2881361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o		return ret;
2891361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	last_check = now;
2901361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	ret = (fs_proc_check("ext2") || check_for_modules("ext2"));
2911361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	return ret;
2921361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o}
2931361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o
2943a538e42441afa5e5b34942062acb976e0d345f6Theodore Ts'ostatic int system_supports_ext4(void)
295cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o{
296cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	static time_t	last_check = 0;
297cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	static int	ret = -1;
298cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	time_t		now = time(0);
299cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o
30018f734301012301efbeb87a7c67f6cf82f1721d7Eric Sandeen	if (ret != -1 || (now - last_check) < 5)
301cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o		return ret;
302cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	last_check = now;
303cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	ret = (fs_proc_check("ext4") || check_for_modules("ext4"));
304cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	return ret;
305cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o}
306cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o
3073a538e42441afa5e5b34942062acb976e0d345f6Theodore Ts'ostatic int system_supports_ext4dev(void)
308cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o{
309cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	static time_t	last_check = 0;
310cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	static int	ret = -1;
311cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	time_t		now = time(0);
312cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o
31318f734301012301efbeb87a7c67f6cf82f1721d7Eric Sandeen	if (ret != -1 || (now - last_check) < 5)
314cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o		return ret;
315cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	last_check = now;
316cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	ret = (fs_proc_check("ext4dev") || check_for_modules("ext4dev"));
317cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	return ret;
318cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o}
319cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o
3202921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'ostatic int probe_ext4dev(struct blkid_probe *probe,
3212921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o			 struct blkid_magic *id,
3222921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o			 unsigned char *buf)
3232921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o{
3242921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	struct ext2_super_block *es;
3252921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	es = (struct ext2_super_block *)buf;
3262921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o
3272921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	/* Distinguish from jbd */
3282921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	if (blkid_le32(es->s_feature_incompat) &
3292921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	    EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
3302921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o		return -BLKID_ERR_PARAM;
3312921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o
3321361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	/*
3331361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	 * If the filesystem does not have a journal and ext2 and ext4
3341361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	 * is not present, then force this to be detected as an
3351361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	 * ext4dev filesystem.
3361361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	 */
3371361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	if (!(blkid_le32(es->s_feature_compat) &
3381361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	      EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
3391361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	    !system_supports_ext2() && !system_supports_ext4() &&
3401361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	    system_supports_ext4dev() &&
3411361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	    linux_version_code() >= EXT4_SUPPORTS_EXT2)
3421361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o		goto force_ext4dev;
3431361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o
344cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	/*
345cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	 * If the filesystem is marked as OK for use by in-development
346cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	 * filesystem code, but ext4dev is not supported, and ext4 is,
347cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	 * then don't call ourselves ext4dev, since we should be
348cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	 * detected as ext4 in that case.
349cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	 *
350cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	 * If the filesystem is marked as in use by production
351cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	 * filesystem, then it can only be used by ext4 and NOT by
352cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	 * ext4dev, so always disclaim we are ext4dev in that case.
353cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	 */
354cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	if (blkid_le32(es->s_flags) & EXT2_FLAGS_TEST_FILESYS) {
355cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o		if (!system_supports_ext4dev() && system_supports_ext4())
356cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o			return -BLKID_ERR_PARAM;
357cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	} else
358cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o		return -BLKID_ERR_PARAM;
359cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o
3601361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'oforce_ext4dev:
3612921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o    	get_ext2_info(probe->dev, id, buf);
3622921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	return 0;
3632921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o}
3642921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o
3652921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'ostatic int probe_ext4(struct blkid_probe *probe, struct blkid_magic *id,
36612b3c8ec1d314b8775fc7d9cefd6bfff551f1de0Theodore Ts'o		      unsigned char *buf)
367e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o{
368e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	struct ext2_super_block *es;
369e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	es = (struct ext2_super_block *)buf;
370e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
3712921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	/* Distinguish from jbd */
372efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	if (blkid_le32(es->s_feature_incompat) &
3732e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o	    EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
374e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		return -BLKID_ERR_PARAM;
375e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
3761361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	/*
3771361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	 * If the filesystem does not have a journal and ext2 is not
3781361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	 * present, then force this to be detected as an ext2
3791361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	 * filesystem.
3801361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	 */
3811361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	if (!(blkid_le32(es->s_feature_compat) &
3821361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	      EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
3831361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	    !system_supports_ext2() && system_supports_ext4() &&
3841361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	    linux_version_code() >= EXT4_SUPPORTS_EXT2)
3851361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o		goto force_ext4;
3861361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o
3872921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	/* Ext4 has at least one feature which ext3 doesn't understand */
3882921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	if (!(blkid_le32(es->s_feature_ro_compat) &
3892921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	      EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) &&
3902921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	    !(blkid_le32(es->s_feature_incompat) &
3912921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	      EXT3_FEATURE_INCOMPAT_UNSUPPORTED))
3922921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o		return -BLKID_ERR_PARAM;
393e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
3941361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'oforce_ext4:
395cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	/*
396cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	 * If the filesystem is a OK for use by in-development
397cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	 * filesystem code, and ext4dev is supported or ext4 is not
398cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	 * supported, then don't call ourselves ext4, so we can redo
399cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	 * the detection and mark the filesystem as ext4dev.
400cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	 *
401cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	 * If the filesystem is marked as in use by production
402cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	 * filesystem, then it can only be used by ext4 and NOT by
403cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	 * ext4dev.
404cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	 */
405cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	if (blkid_le32(es->s_flags) & EXT2_FLAGS_TEST_FILESYS) {
406cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o		if (system_supports_ext4dev() || !system_supports_ext4())
407cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o			return -BLKID_ERR_PARAM;
408cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o	}
4092921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o    	get_ext2_info(probe->dev, id, buf);
4102921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	return 0;
4112921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o}
412ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o
4132921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'ostatic int probe_ext3(struct blkid_probe *probe, struct blkid_magic *id,
4142921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o		      unsigned char *buf)
4152921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o{
4162921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	struct ext2_super_block *es;
4172921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	es = (struct ext2_super_block *)buf;
4182e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o
4192921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	/* ext3 requires journal */
4202921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	if (!(blkid_le32(es->s_feature_compat) &
4212921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	      EXT3_FEATURE_COMPAT_HAS_JOURNAL))
4222921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o		return -BLKID_ERR_PARAM;
4232e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o
4242921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	/* Any features which ext3 doesn't understand */
4252921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	if ((blkid_le32(es->s_feature_ro_compat) &
4262921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	     EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) ||
4272921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	    (blkid_le32(es->s_feature_incompat) &
4282921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	     EXT3_FEATURE_INCOMPAT_UNSUPPORTED))
4292921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o		return -BLKID_ERR_PARAM;
4302921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o
4312921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o    	get_ext2_info(probe->dev, id, buf);
4322e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o	return 0;
4332e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o}
4342e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o
4352921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'ostatic int probe_ext2(struct blkid_probe *probe, struct blkid_magic *id,
43612b3c8ec1d314b8775fc7d9cefd6bfff551f1de0Theodore Ts'o		      unsigned char *buf)
4372e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o{
4382e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o	struct ext2_super_block *es;
4392e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o
4402e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o	es = (struct ext2_super_block *)buf;
4412e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o
44205a6edf4fdf3beb93d22116cf4ec39d161ab2790Karel Zak	/* Distinguish between ext3 and ext2 */
44305a6edf4fdf3beb93d22116cf4ec39d161ab2790Karel Zak	if ((blkid_le32(es->s_feature_compat) &
44405a6edf4fdf3beb93d22116cf4ec39d161ab2790Karel Zak	      EXT3_FEATURE_COMPAT_HAS_JOURNAL))
44505a6edf4fdf3beb93d22116cf4ec39d161ab2790Karel Zak		return -BLKID_ERR_PARAM;
4462e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o
4472921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	/* Any features which ext2 doesn't understand */
4482921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	if ((blkid_le32(es->s_feature_ro_compat) &
4492921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	     EXT2_FEATURE_RO_COMPAT_UNSUPPORTED) ||
4502921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	    (blkid_le32(es->s_feature_incompat) &
4512921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	     EXT2_FEATURE_INCOMPAT_UNSUPPORTED))
4522921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o		return -BLKID_ERR_PARAM;
45379dd234a799434b6dc8365c49e743f00eb09d2fdTheodore Ts'o
4541361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	/*
4551361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	 * If ext2 is not present, but ext4 or ext4dev are, then
4561361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	 * disclaim we are ext2
4571361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	 */
4581361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	if (!system_supports_ext2() &&
4591361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	    (system_supports_ext4() || system_supports_ext4dev()) &&
4601361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	    linux_version_code() >= EXT4_SUPPORTS_EXT2)
4611361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o		return -BLKID_ERR_PARAM;
4621361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o
4632921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	get_ext2_info(probe->dev, id, buf);
464e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	return 0;
465e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o}
466e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
4672921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'ostatic int probe_jbd(struct blkid_probe *probe, struct blkid_magic *id,
468544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o		     unsigned char *buf)
469e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o{
47050b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	struct ext2_super_block *es = (struct ext2_super_block *) buf;
471e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
47276b07bb1bc9cbcb70a94cb235954eaac993920adTheodore Ts'o	if (!(blkid_le32(es->s_feature_incompat) &
47350b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	      EXT3_FEATURE_INCOMPAT_JOURNAL_DEV))
474e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		return -BLKID_ERR_PARAM;
475e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
4762921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o	get_ext2_info(probe->dev, id, buf);
4772e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o
4782e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o	return 0;
479e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o}
480e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
4812f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o#define FAT_ATTR_VOLUME_ID		0x08
4822f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o#define FAT_ATTR_DIR			0x10
4832f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o#define FAT_ATTR_LONG_NAME		0x0f
4842f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o#define FAT_ATTR_MASK			0x3f
4852f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o#define FAT_ENTRY_FREE			0xe5
4862f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o
487d4e0b1c6f5aa8c6a248d9149ed5634a310952411Theodore Ts'ostatic const char *no_name = "NO NAME    ";
4882f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o
4892f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'ostatic unsigned char *search_fat_label(struct vfat_dir_entry *dir, int count)
4902f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o{
49112a829dcdc57fb8ddc4887b07b40136288b6e7feMatthias Andree	int i;
4922f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o
4932f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o	for (i = 0; i < count; i++) {
4942f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o		if (dir[i].name[0] == 0x00)
4952f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			break;
496efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
4972f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o		if ((dir[i].name[0] == FAT_ENTRY_FREE) ||
4982f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o		    (dir[i].cluster_high != 0 || dir[i].cluster_low != 0) ||
4992f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o		    ((dir[i].attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME))
5002f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			continue;
5012f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o
502efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		if ((dir[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) ==
5032f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o		    FAT_ATTR_VOLUME_ID) {
5042f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			return dir[i].name;
5052f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o		}
5062f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o	}
5072f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o	return 0;
5082f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o}
5092f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o
5102f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o/* FAT label extraction from the root directory taken from Kay
5112f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o * Sievers's volume_id library */
512ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_fat(struct blkid_probe *probe,
513efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		      struct blkid_magic *id __BLKID_ATTR((unused)),
514544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o		      unsigned char *buf)
515e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o{
516038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o	struct vfat_super_block *vs = (struct vfat_super_block *) buf;
517038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o	struct msdos_super_block *ms = (struct msdos_super_block *) buf;
5182f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o	struct vfat_dir_entry *dir;
519e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	char serno[10];
52094fa1108eecb92bc595ae6f4927d2aeaea4049e8Matthias Andree	const unsigned char *label = 0, *vol_label = 0, *tmp;
521038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o	unsigned char	*vol_serno;
5222f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o	int label_len = 0, maxloop = 100;
5232f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o	__u16 sector_size, dir_entries, reserved;
5242f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o	__u32 sect_count, fat_size, dir_size, cluster_count, fat_length;
5252f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o	__u32 buf_size, start_data_sect, next, root_start, root_dir_entries;
526e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
527038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o	/* sector size check */
528aadac9b7bbe7d1f4f0db02f3d7dbd70a856f9153Matthias Andree	tmp = (unsigned char *)&ms->ms_sector_size;
529aadac9b7bbe7d1f4f0db02f3d7dbd70a856f9153Matthias Andree	sector_size = tmp[0] + (tmp[1] << 8);
530038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o	if (sector_size != 0x200 && sector_size != 0x400 &&
531038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o	    sector_size != 0x800 && sector_size != 0x1000)
532038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o		return 1;
533e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
534aadac9b7bbe7d1f4f0db02f3d7dbd70a856f9153Matthias Andree	tmp = (unsigned char *)&ms->ms_dir_entries;
535aadac9b7bbe7d1f4f0db02f3d7dbd70a856f9153Matthias Andree	dir_entries = tmp[0] + (tmp[1] << 8);
536038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o	reserved =  blkid_le16(ms->ms_reserved);
537aadac9b7bbe7d1f4f0db02f3d7dbd70a856f9153Matthias Andree	tmp = (unsigned char *)&ms->ms_sectors;
538aadac9b7bbe7d1f4f0db02f3d7dbd70a856f9153Matthias Andree	sect_count = tmp[0] + (tmp[1] << 8);
539038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o	if (sect_count == 0)
540038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o		sect_count = blkid_le32(ms->ms_total_sect);
541e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
542038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o	fat_length = blkid_le16(ms->ms_fat_length);
543038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o	if (fat_length == 0)
544038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o		fat_length = blkid_le32(vs->vs_fat32_length);
545e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
546038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o	fat_size = fat_length * ms->ms_fats;
547038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o	dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) +
548038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o			(sector_size-1)) / sector_size;
549e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
550038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o	cluster_count = sect_count - (reserved + fat_size + dir_size);
55120c10a766788d9271e36f3ba3b0682a3027cb272Theodore Ts'o	if (ms->ms_cluster_size == 0)
55220c10a766788d9271e36f3ba3b0682a3027cb272Theodore Ts'o		return 1;
553038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o	cluster_count /= ms->ms_cluster_size;
554e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
555038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o	if (cluster_count > FAT32_MAX)
556038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o		return 1;
557038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o
558038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o	if (ms->ms_fat_length) {
5592f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o		/* the label may be an attribute in the root directory */
5602f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o		root_start = (reserved + fat_size) * sector_size;
561efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		root_dir_entries = vs->vs_dir_entries[0] +
5622f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			(vs->vs_dir_entries[1] << 8);
5632f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o
5642f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o		buf_size = root_dir_entries * sizeof(struct vfat_dir_entry);
565efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		dir = (struct vfat_dir_entry *) get_buffer(probe, root_start,
5662f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o							   buf_size);
5672f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o		if (dir)
5682f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			vol_label = search_fat_label(dir, root_dir_entries);
5692f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o
5702f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o		if (!vol_label || !memcmp(vol_label, no_name, 11))
5712f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			vol_label = ms->ms_label;
572038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o		vol_serno = ms->ms_serno;
573038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o
574efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		blkid_set_tag(probe->dev, "SEC_TYPE", "msdos",
5752f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			      sizeof("msdos"));
576038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o	} else {
5772f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o		/* Search the FAT32 root dir for the label attribute */
5782f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o		buf_size = vs->vs_cluster_size * sector_size;
5792f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o		start_data_sect = reserved + fat_size;
5802f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o
5812f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o		next = blkid_le32(vs->vs_root_cluster);
5822f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o		while (next && --maxloop) {
5832f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			__u32 next_sect_off;
5842f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			__u64 next_off, fat_entry_off;
5852f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			int count;
5862f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o
5872f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			next_sect_off = (next - 2) * vs->vs_cluster_size;
588efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			next_off = (start_data_sect + next_sect_off) *
5892f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o				sector_size;
5902f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o
591efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			dir = (struct vfat_dir_entry *)
5922f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o				get_buffer(probe, next_off, buf_size);
5932f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			if (dir == NULL)
5942f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o				break;
5952f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o
5962f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			count = buf_size / sizeof(struct vfat_dir_entry);
5972f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o
5982f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			vol_label = search_fat_label(dir, count);
5992f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			if (vol_label)
6002f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o				break;
6012f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o
6022f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			/* get FAT entry */
603efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			fat_entry_off = (reserved * sector_size) +
6042f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o				(next * sizeof(__u32));
6052f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			buf = get_buffer(probe, fat_entry_off, buf_size);
6062f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			if (buf == NULL)
6072f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o				break;
6082f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o
6092f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			/* set next cluster */
6102f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			next = blkid_le32(*((__u32 *) buf) & 0x0fffffff);
6112f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o		}
6122f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o
6132f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o		if (!vol_label || !memcmp(vol_label, no_name, 11))
6142f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			vol_label = vs->vs_label;
615038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o		vol_serno = vs->vs_serno;
616038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o	}
617e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
6182f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o	if (vol_label && memcmp(vol_label, no_name, 11)) {
619633f453db14b0fb91294887a9629f5cc2f95407fKarel Zak		if ((label_len = figure_label_len(vol_label, 11)))
620633f453db14b0fb91294887a9629f5cc2f95407fKarel Zak			label = vol_label;
621e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	}
622e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
623e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	/* We can't just print them as %04X, because they are unaligned */
624038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o	sprintf(serno, "%02X%02X-%02X%02X", vol_serno[3], vol_serno[2],
625038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o		vol_serno[1], vol_serno[0]);
626038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o
627ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", (const char *) label, label_len);
628ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "UUID", serno, sizeof(serno)-1);
629e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
630e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	return 0;
631e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o}
632e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
633c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak/*
634c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak * The FAT filesystem could be without a magic string in superblock
635c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak * (e.g. old floppies).  This heuristic for FAT detection is inspired
636c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak * by http://vrfy.org/projects/volume_id/ and Linux kernel.
637c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak * [7-Jul-2005, Karel Zak <kzak@redhat.com>]
638c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak */
639ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_fat_nomagic(struct blkid_probe *probe,
640efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			     struct blkid_magic *id __BLKID_ATTR((unused)),
641038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o			     unsigned char *buf)
642c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak{
64378d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	struct msdos_super_block *ms;
644c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak
64578d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	ms = (struct msdos_super_block *)buf;
646c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak
647c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak	/* heads check */
64878d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	if (ms->ms_heads == 0)
649c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak		return 1;
650c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak
651efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	/* cluster size check*/
65278d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	if (ms->ms_cluster_size == 0 ||
65378d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	    (ms->ms_cluster_size & (ms->ms_cluster_size-1)))
654c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak		return 1;
655c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak
656c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak	/* media check */
65778d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	if (ms->ms_media < 0xf8 && ms->ms_media != 0xf0)
658c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak		return 1;
659c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak
660c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak	/* fat counts(Linux kernel expects at least 1 FAT table) */
66178d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	if (!ms->ms_fats)
66278d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o		return 1;
66378d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o
66478d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	/*
66578d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	 * OS/2 and apparently DFSee will place a FAT12/16-like
66678d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	 * pseudo-superblock in the first 512 bytes of non-FAT
66778d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	 * filesystems --- at least JFS and HPFS, and possibly others.
66878d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	 * So we explicitly check for those filesystems at the
66978d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	 * FAT12/16 filesystem magic field identifier, and if they are
67078d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	 * present, we rule this out as a FAT filesystem, despite the
67178d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	 * FAT-like pseudo-header.
67278d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o         */
67378d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	if ((memcmp(ms->ms_magic, "JFS     ", 8) == 0) ||
67478d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	    (memcmp(ms->ms_magic, "HPFS    ", 8) == 0))
675c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak		return 1;
676c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak
677ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	return probe_fat(probe, id, buf);
678c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak}
679c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak
680cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'ostatic int probe_ntfs(struct blkid_probe *probe,
681efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		      struct blkid_magic *id __BLKID_ATTR((unused)),
682cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		      unsigned char *buf)
683cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o{
684cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	struct ntfs_super_block *ns;
685cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	struct master_file_table_record *mft;
686cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	struct file_attribute *attr;
687cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	char		uuid_str[17], label_str[129], *cp;
688cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	int		bytes_per_sector, sectors_per_cluster;
689cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	int		mft_record_size, attr_off, attr_len;
690cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	unsigned int	i, attr_type, val_len;
691cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	int		val_off;
692cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	__u64		nr_clusters;
693cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	blkid_loff_t off;
694cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	unsigned char *buf_mft, *val;
695cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
696cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	ns = (struct ntfs_super_block *) buf;
697cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
698cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	bytes_per_sector = ns->bios_parameter_block[0] +
699cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		(ns->bios_parameter_block[1]  << 8);
700cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	sectors_per_cluster = ns->bios_parameter_block[2];
701cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
70230dd2622353b9fde462c9112fb0c863620a3bf91Theodore Ts'o	if ((bytes_per_sector < 512) || (sectors_per_cluster == 0))
70330dd2622353b9fde462c9112fb0c863620a3bf91Theodore Ts'o		return 1;
70430dd2622353b9fde462c9112fb0c863620a3bf91Theodore Ts'o
705cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	if (ns->cluster_per_mft_record < 0)
70630dd2622353b9fde462c9112fb0c863620a3bf91Theodore Ts'o		mft_record_size = 1 << (0-ns->cluster_per_mft_record);
707cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	else
708efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		mft_record_size = ns->cluster_per_mft_record *
709cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o			sectors_per_cluster * bytes_per_sector;
710cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	nr_clusters = blkid_le64(ns->number_of_sectors) / sectors_per_cluster;
711cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
712cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	if ((blkid_le64(ns->mft_cluster_location) > nr_clusters) ||
713cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	    (blkid_le64(ns->mft_mirror_cluster_location) > nr_clusters))
714cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		return 1;
715cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
716efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	off = blkid_le64(ns->mft_mirror_cluster_location) *
717cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		bytes_per_sector * sectors_per_cluster;
718cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
719cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	buf_mft = get_buffer(probe, off, mft_record_size);
720cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	if (!buf_mft)
721cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		return 1;
722cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
723cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	if (memcmp(buf_mft, "FILE", 4))
724cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		return 1;
725cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
726efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	off = blkid_le64(ns->mft_cluster_location) * bytes_per_sector *
727cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		sectors_per_cluster;
728cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
729cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	buf_mft = get_buffer(probe, off, mft_record_size);
730cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	if (!buf_mft)
731cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		return 1;
732cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
733cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	if (memcmp(buf_mft, "FILE", 4))
734cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		return 1;
735cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
736cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	off += MFT_RECORD_VOLUME * mft_record_size;
737cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
738cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	buf_mft = get_buffer(probe, off, mft_record_size);
739cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	if (!buf_mft)
740cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		return 1;
741cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
742cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	if (memcmp(buf_mft, "FILE", 4))
743cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		return 1;
744cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
745cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	mft = (struct master_file_table_record *) buf_mft;
746cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
747cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	attr_off = blkid_le16(mft->attrs_offset);
748cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	label_str[0] = 0;
749efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
750cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	while (1) {
751cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		attr = (struct file_attribute *) (buf_mft + attr_off);
752cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		attr_len = blkid_le16(attr->len);
753cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		attr_type = blkid_le32(attr->type);
754cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		val_off = blkid_le16(attr->value_offset);
755cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		val_len = blkid_le32(attr->value_len);
756cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
757cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		attr_off += attr_len;
758cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
759cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		if ((attr_off > mft_record_size) ||
760cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		    (attr_len == 0))
761cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o			break;
762cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
763cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		if (attr_type == MFT_RECORD_ATTR_END)
764cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o			break;
765cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
766cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) {
767cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o			if (val_len > sizeof(label_str))
768cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o				val_len = sizeof(label_str)-1;
769cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
770cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o			for (i=0, cp=label_str; i < val_len; i+=2,cp++) {
771cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o				val = ((__u8 *) attr) + val_off + i;
772cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o				*cp = val[0];
773cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o				if (val[1])
774cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o					*cp = '?';
775cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o			}
776cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o			*cp = 0;
777cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		}
778cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	}
779cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
780c40ad3674c9d2f0709cbe8f2f607633f25c4bb4bPixel	sprintf(uuid_str, "%016llX", blkid_le64(ns->volume_serial));
781cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	blkid_set_tag(probe->dev, "UUID", uuid_str, 0);
782cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	if (label_str[0])
783cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		blkid_set_tag(probe->dev, "LABEL", label_str, 0);
784cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	return 0;
785cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o}
786cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
787cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
788ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_xfs(struct blkid_probe *probe,
789efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		     struct blkid_magic *id __BLKID_ATTR((unused)),
790544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o		     unsigned char *buf)
791e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o{
792e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	struct xfs_super_block *xs;
793a30b9446d1899260159968826428722f2dcbbc64Theodore Ts'o	const char *label = 0;
794e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
795e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	xs = (struct xfs_super_block *)buf;
796e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
797e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	if (strlen(xs->xs_fname))
798a30b9446d1899260159968826428722f2dcbbc64Theodore Ts'o		label = xs->xs_fname;
799ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", label, sizeof(xs->xs_fname));
800ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o	set_uuid(probe->dev, xs->xs_uuid, 0);
801e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	return 0;
802e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o}
803e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
804ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_reiserfs(struct blkid_probe *probe,
80579dd234a799434b6dc8365c49e743f00eb09d2fdTheodore Ts'o			  struct blkid_magic *id, unsigned char *buf)
806e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o{
80750b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	struct reiserfs_super_block *rs = (struct reiserfs_super_block *) buf;
808e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	unsigned int blocksize;
809a30b9446d1899260159968826428722f2dcbbc64Theodore Ts'o	const char *label = 0;
810e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
81176b07bb1bc9cbcb70a94cb235954eaac993920adTheodore Ts'o	blocksize = blkid_le16(rs->rs_blocksize);
812e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
8134dc30dac2c2732e25765984263a3ecafd8c66932Theodore Ts'o	/* The blocksize must be at least 1k */
8144dc30dac2c2732e25765984263a3ecafd8c66932Theodore Ts'o	if ((blocksize >> 10) == 0)
8154dc30dac2c2732e25765984263a3ecafd8c66932Theodore Ts'o		return -BLKID_ERR_PARAM;
8164dc30dac2c2732e25765984263a3ecafd8c66932Theodore Ts'o
817e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	/* If the superblock is inside the journal, we have the wrong one */
81850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block))
819e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		return -BLKID_ERR_BIG;
820e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
821e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	/* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */
822ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	if (id->bim_magic[6] == '2' || id->bim_magic[6] == '3') {
823a30b9446d1899260159968826428722f2dcbbc64Theodore Ts'o		if (strlen(rs->rs_label))
824a30b9446d1899260159968826428722f2dcbbc64Theodore Ts'o			label = rs->rs_label;
825ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o		set_uuid(probe->dev, rs->rs_uuid, 0);
826e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	}
827ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", label, sizeof(rs->rs_label));
828e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
829e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	return 0;
830e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o}
831e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
832ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_reiserfs4(struct blkid_probe *probe,
833efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			   struct blkid_magic *id __BLKID_ATTR((unused)),
834ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			   unsigned char *buf)
835bb626bcd546a039b39b9f25e65881b36b2abe24fTheodore Ts'o{
836bb626bcd546a039b39b9f25e65881b36b2abe24fTheodore Ts'o	struct reiser4_super_block *rs4 = (struct reiser4_super_block *) buf;
837ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	const unsigned char *label = 0;
838bb626bcd546a039b39b9f25e65881b36b2abe24fTheodore Ts'o
839ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	if (strlen((char *) rs4->rs4_label))
840bb626bcd546a039b39b9f25e65881b36b2abe24fTheodore Ts'o		label = rs4->rs4_label;
841ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o	set_uuid(probe->dev, rs4->rs4_uuid, 0);
842efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", (const char *) label,
843ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		      sizeof(rs4->rs4_label));
844bb626bcd546a039b39b9f25e65881b36b2abe24fTheodore Ts'o
845bb626bcd546a039b39b9f25e65881b36b2abe24fTheodore Ts'o	return 0;
846bb626bcd546a039b39b9f25e65881b36b2abe24fTheodore Ts'o}
847bb626bcd546a039b39b9f25e65881b36b2abe24fTheodore Ts'o
848ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_jfs(struct blkid_probe *probe,
849efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		     struct blkid_magic *id __BLKID_ATTR((unused)),
850544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o		     unsigned char *buf)
85109a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o{
85209a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o	struct jfs_super_block *js;
853a30b9446d1899260159968826428722f2dcbbc64Theodore Ts'o	const char *label = 0;
85409a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o
85509a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o	js = (struct jfs_super_block *)buf;
85609a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o
857b41fb002257d4b997560cd77676b78219be03c24Theodore Ts'o	if (blkid_le32(js->js_bsize) != (1 << blkid_le16(js->js_l2bsize)))
858b41fb002257d4b997560cd77676b78219be03c24Theodore Ts'o		return 1;
859b41fb002257d4b997560cd77676b78219be03c24Theodore Ts'o
860b41fb002257d4b997560cd77676b78219be03c24Theodore Ts'o	if (blkid_le32(js->js_pbsize) != (1 << blkid_le16(js->js_l2pbsize)))
861b41fb002257d4b997560cd77676b78219be03c24Theodore Ts'o		return 1;
862b41fb002257d4b997560cd77676b78219be03c24Theodore Ts'o
863b41fb002257d4b997560cd77676b78219be03c24Theodore Ts'o	if ((blkid_le16(js->js_l2bsize) - blkid_le16(js->js_l2pbsize)) !=
864b41fb002257d4b997560cd77676b78219be03c24Theodore Ts'o	    blkid_le16(js->js_l2bfactor))
865b41fb002257d4b997560cd77676b78219be03c24Theodore Ts'o		return 1;
866b41fb002257d4b997560cd77676b78219be03c24Theodore Ts'o
86748e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o	if (strlen((char *) js->js_label))
868a30b9446d1899260159968826428722f2dcbbc64Theodore Ts'o		label = (char *) js->js_label;
869ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", label, sizeof(js->js_label));
870ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o	set_uuid(probe->dev, js->js_uuid, 0);
87109a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o	return 0;
87209a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o}
87309a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o
874c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correiastatic int probe_zfs(struct blkid_probe *probe, struct blkid_magic *id,
875c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia		     unsigned char *buf)
876c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia{
87779e62409b3a247e258d9e9206484ed8f193a183eEric Sandeen#if 0
878c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia	char *vdev_label;
879c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia	const char *pool_name = 0;
880c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia
881c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia	/* read nvpair data for pool name, pool GUID (complex) */
882c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia	blkid_set_tag(probe->dev, "LABEL", pool_name, sizeof(pool_name));
883c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia	set_uuid(probe->dev, pool_guid, 0);
884c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia#endif
885c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia	return 0;
886c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia}
887c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia
888e382a7eaded3ec6b38114988ae9b0723bb48002aKarsten Hoppstatic int probe_luks(struct blkid_probe *probe,
889e382a7eaded3ec6b38114988ae9b0723bb48002aKarsten Hopp		       struct blkid_magic *id __BLKID_ATTR((unused)),
890e382a7eaded3ec6b38114988ae9b0723bb48002aKarsten Hopp		       unsigned char *buf)
891e382a7eaded3ec6b38114988ae9b0723bb48002aKarsten Hopp{
892d4e0b1c6f5aa8c6a248d9149ed5634a310952411Theodore Ts'o	char uuid[40];
893d4e0b1c6f5aa8c6a248d9149ed5634a310952411Theodore Ts'o
894e382a7eaded3ec6b38114988ae9b0723bb48002aKarsten Hopp	/* 168 is the offset to the 40 character uuid:
895e382a7eaded3ec6b38114988ae9b0723bb48002aKarsten Hopp	 * http://luks.endorphin.org/LUKS-on-disk-format.pdf */
896d4e0b1c6f5aa8c6a248d9149ed5634a310952411Theodore Ts'o	strncpy(uuid, (char *) buf+168, 40);
897e382a7eaded3ec6b38114988ae9b0723bb48002aKarsten Hopp	blkid_set_tag(probe->dev, "UUID", uuid, sizeof(uuid));
898e382a7eaded3ec6b38114988ae9b0723bb48002aKarsten Hopp	return 0;
899e382a7eaded3ec6b38114988ae9b0723bb48002aKarsten Hopp}
900e382a7eaded3ec6b38114988ae9b0723bb48002aKarsten Hopp
901ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_romfs(struct blkid_probe *probe,
902efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		       struct blkid_magic *id __BLKID_ATTR((unused)),
903544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o		       unsigned char *buf)
90409a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o{
90509a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o	struct romfs_super_block *ros;
906a30b9446d1899260159968826428722f2dcbbc64Theodore Ts'o	const char *label = 0;
90709a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o
90809a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o	ros = (struct romfs_super_block *)buf;
90909a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o
910a30b9446d1899260159968826428722f2dcbbc64Theodore Ts'o	if (strlen((char *) ros->ros_volume))
911a30b9446d1899260159968826428722f2dcbbc64Theodore Ts'o		label = (char *) ros->ros_volume;
912ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", label, 0);
9137369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	return 0;
9147369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o}
9157369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o
916ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_cramfs(struct blkid_probe *probe,
917efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			struct blkid_magic *id __BLKID_ATTR((unused)),
918ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			unsigned char *buf)
9194c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o{
9204c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o	struct cramfs_super_block *csb;
9214c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o	const char *label = 0;
9224c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o
9234c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o	csb = (struct cramfs_super_block *)buf;
9244c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o
9254c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o	if (strlen((char *) csb->name))
9264c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o		label = (char *) csb->name;
927ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", label, 0);
9284c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o	return 0;
9294c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o}
9304c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o
931ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_swap0(struct blkid_probe *probe,
9327369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o		       struct blkid_magic *id __BLKID_ATTR((unused)),
9337369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o		       unsigned char *buf __BLKID_ATTR((unused)))
9347369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o{
935ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "UUID", 0, 0);
936ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", 0, 0);
9377369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	return 0;
9387369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o}
9397369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o
940ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_swap1(struct blkid_probe *probe,
9416360d129d003f25942f62fab2cdc5e1d97cc88a6Eric Sandeen		       struct blkid_magic *id,
9427369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o		       unsigned char *buf __BLKID_ATTR((unused)))
9437369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o{
9447369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	struct swap_id_block *sws;
9457369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o
946ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	probe_swap0(probe, id, buf);
9477369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	/*
9487369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	 * Version 1 swap headers are always located at offset of 1024
9497369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	 * bytes, although the swap signature itself is located at the
9507369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	 * end of the page (which may vary depending on hardware
9517369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	 * pagesize).
9527369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	 */
953ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	sws = (struct swap_id_block *) get_buffer(probe, 1024, 1024);
954ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	if (!sws)
9557369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o		return 1;
9567369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o
9576360d129d003f25942f62fab2cdc5e1d97cc88a6Eric Sandeen	/* check for wrong version or zeroed pagecount, for sanity */
9586360d129d003f25942f62fab2cdc5e1d97cc88a6Eric Sandeen	if (!memcmp(id->bim_magic, "SWAPSPACE2", id->bim_len) &&
95922269b8b60da320b3c27ea8d053f9e2b0fbe2ae2Eric Sandeen			(sws->sws_version != 1 || sws->sws_lastpage == 0))
9606360d129d003f25942f62fab2cdc5e1d97cc88a6Eric Sandeen		return 1;
9616360d129d003f25942f62fab2cdc5e1d97cc88a6Eric Sandeen
9627369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	/* arbitrary sanity check.. is there any garbage down there? */
9637369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	if (sws->sws_pad[32] == 0 && sws->sws_pad[33] == 0)  {
9647369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o		if (sws->sws_volume[0])
965efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			blkid_set_tag(probe->dev, "LABEL", sws->sws_volume,
9667369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o				      sizeof(sws->sws_volume));
9677369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o		if (sws->sws_uuid[0])
968ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o			set_uuid(probe->dev, sws->sws_uuid, 0);
9697369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	}
97009a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o	return 0;
97109a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o}
97209a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o
973ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_iso9660(struct blkid_probe *probe,
974efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			 struct blkid_magic *id __BLKID_ATTR((unused)),
97545a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o			 unsigned char *buf)
97645a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o{
97745a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o	struct iso_volume_descriptor *iso;
97845a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o	const unsigned char *label;
97945a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o
98045a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o	iso = (struct iso_volume_descriptor *) buf;
98145a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o	label = iso->volume_id;
98245a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o
983efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", (const char *) label,
984ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		      figure_label_len(label, 32));
98545a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o	return 0;
98645a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o}
98745a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o
98845a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o
989544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'ostatic const char
9903de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o*udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
9913de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o		 "NSR03", "TEA01", 0 };
9923de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o
993ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_udf(struct blkid_probe *probe,
994efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		     struct blkid_magic *id __BLKID_ATTR((unused)),
995544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o		     unsigned char *buf __BLKID_ATTR((unused)))
9963de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o{
9973de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o	int j, bs;
998ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	struct iso_volume_descriptor *isosb;
999544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	const char ** m;
10003de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o
10013de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o	/* determine the block size by scanning in 2K increments
10023de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o	   (block sizes larger than 2K will be null padded) */
10033de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o	for (bs = 1; bs < 16; bs++) {
1004efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		isosb = (struct iso_volume_descriptor *)
1005ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			get_buffer(probe, bs*2048+32768, sizeof(isosb));
1006ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		if (!isosb)
10073de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o			return 1;
1008ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		if (isosb->vd_id[0])
10093de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o			break;
10103de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o	}
10113de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o
10123de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o	/* Scan up to another 64 blocks looking for additional VSD's */
10133de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o	for (j = 1; j < 64; j++) {
10143de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o		if (j > 1) {
1015efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			isosb = (struct iso_volume_descriptor *)
1016efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o				get_buffer(probe, j*bs*2048+32768,
1017ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o					   sizeof(isosb));
1018ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			if (!isosb)
10193de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o				return 1;
10203de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o		}
10213de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o		/* If we find NSR0x then call it udf:
10223de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o		   NSR01 for UDF 1.00
10233de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o		   NSR02 for UDF 1.50
10243de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o		   NSR03 for UDF 2.00 */
102549487b79da9ccc4a5f9d4e8f08c10ec9c8185a90Theodore Ts'o		if (!memcmp(isosb->vd_id, "NSR0", 4))
1026a4045c21a30ddf36528b0b1fc0cc6e4fffb33ce6Theodore Ts'o			return probe_iso9660(probe, id, buf);
10273de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o		for (m = udf_magic; *m; m++)
102849487b79da9ccc4a5f9d4e8f08c10ec9c8185a90Theodore Ts'o			if (!memcmp(*m, isosb->vd_id, 5))
10293de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o				break;
10303de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o		if (*m == 0)
10313de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o			return 1;
10323de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o	}
10333de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o	return 1;
10343de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o}
10353de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o
1036ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_ocfs(struct blkid_probe *probe,
1037efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		      struct blkid_magic *id __BLKID_ATTR((unused)),
10389387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o		      unsigned char *buf)
10399387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o{
10409387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o	struct ocfs_volume_header ovh;
10419387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o	struct ocfs_volume_label ovl;
10423838f7df134035089e8e8df317112e4fd645602dTheodore Ts'o	__u32 major;
10439387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o
10449387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o	memcpy(&ovh, buf, sizeof(ovh));
10459387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o	memcpy(&ovl, buf+512, sizeof(ovl));
10469387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o
10479387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o	major = ocfsmajor(ovh);
10489387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o	if (major == 1)
1049ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		blkid_set_tag(probe->dev,"SEC_TYPE","ocfs1",sizeof("ocfs1"));
10509387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o	else if (major >= 9)
1051ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		blkid_set_tag(probe->dev,"SEC_TYPE","ntocfs",sizeof("ntocfs"));
1052efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1053ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", ovl.label, ocfslabellen(ovl));
1054ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "MOUNT", ovh.mount, ocfsmountlen(ovh));
1055ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o	set_uuid(probe->dev, ovl.vol_id, 0);
10569387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o	return 0;
10579387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o}
10589387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o
1059ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_ocfs2(struct blkid_probe *probe,
1060efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		       struct blkid_magic *id __BLKID_ATTR((unused)),
10612c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o		       unsigned char *buf)
1062414846b126d4d751bd6b36df0a39dcb030e0feb3Theodore Ts'o{
1063414846b126d4d751bd6b36df0a39dcb030e0feb3Theodore Ts'o	struct ocfs2_super_block *osb;
1064414846b126d4d751bd6b36df0a39dcb030e0feb3Theodore Ts'o
1065414846b126d4d751bd6b36df0a39dcb030e0feb3Theodore Ts'o	osb = (struct ocfs2_super_block *)buf;
1066414846b126d4d751bd6b36df0a39dcb030e0feb3Theodore Ts'o
1067ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", osb->s_label, sizeof(osb->s_label));
1068ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o	set_uuid(probe->dev, osb->s_uuid, 0);
1069414846b126d4d751bd6b36df0a39dcb030e0feb3Theodore Ts'o	return 0;
1070414846b126d4d751bd6b36df0a39dcb030e0feb3Theodore Ts'o}
1071414846b126d4d751bd6b36df0a39dcb030e0feb3Theodore Ts'o
1072ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_oracleasm(struct blkid_probe *probe,
1073efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			   struct blkid_magic *id __BLKID_ATTR((unused)),
10742c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o			   unsigned char *buf)
10752c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o{
10762c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o	struct oracle_asm_disk_label *dl;
10772c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o
10782c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o	dl = (struct oracle_asm_disk_label *)buf;
10792c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o
1080ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", dl->dl_id, sizeof(dl->dl_id));
10812c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o	return 0;
10822c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o}
10832c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o
1084b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zakstatic int probe_gfs(struct blkid_probe *probe,
1085b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		     struct blkid_magic *id __BLKID_ATTR((unused)),
1086b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		     unsigned char *buf)
1087b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak{
1088b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	struct gfs2_sb *sbd;
1089b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	const char *label = 0;
1090b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak
1091b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	sbd = (struct gfs2_sb *)buf;
1092b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak
1093b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	if (blkid_be32(sbd->sb_fs_format) == GFS_FORMAT_FS &&
1094b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	    blkid_be32(sbd->sb_multihost_format) == GFS_FORMAT_MULTI)
1095efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	{
1096b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		blkid_set_tag(probe->dev, "UUID", 0, 0);
1097efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1098b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		if (strlen(sbd->sb_locktable))
1099b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak			label = sbd->sb_locktable;
1100b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		blkid_set_tag(probe->dev, "LABEL", label, sizeof(sbd->sb_locktable));
1101b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		return 0;
1102b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	}
1103b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	return 1;
1104b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak}
1105b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak
1106b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zakstatic int probe_gfs2(struct blkid_probe *probe,
1107b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		     struct blkid_magic *id __BLKID_ATTR((unused)),
1108b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		     unsigned char *buf)
1109b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak{
1110b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	struct gfs2_sb *sbd;
1111b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	const char *label = 0;
1112b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak
1113b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	sbd = (struct gfs2_sb *)buf;
1114b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak
1115b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	if (blkid_be32(sbd->sb_fs_format) == GFS2_FORMAT_FS &&
1116b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	    blkid_be32(sbd->sb_multihost_format) == GFS2_FORMAT_MULTI)
1117efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	{
1118b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		blkid_set_tag(probe->dev, "UUID", 0, 0);
1119efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1120b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		if (strlen(sbd->sb_locktable))
1121b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak			label = sbd->sb_locktable;
1122b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		blkid_set_tag(probe->dev, "LABEL", label, sizeof(sbd->sb_locktable));
1123b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		return 0;
1124b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	}
1125b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	return 1;
1126b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak}
1127b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak
1128efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ostatic void unicode_16be_to_utf8(unsigned char *str, int out_len,
1129d56ccbd8f97e90d34a2b18a45fbd6681d3dba726Theodore Ts'o				 const unsigned char *buf, int in_len)
11309c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o{
11319c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	int i, j;
11329c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int c;
11339c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
11349c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	for (i = j = 0; i + 2 <= in_len; i += 2) {
11359c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		c = (buf[i] << 8) | buf[i+1];
11369c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		if (c == 0) {
11379c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			str[j] = '\0';
11389c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			break;
11399c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		} else if (c < 0x80) {
11409c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			if (j+1 >= out_len)
11419c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o				break;
11429c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			str[j++] = (unsigned char) c;
11439c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		} else if (c < 0x800) {
11449c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			if (j+2 >= out_len)
11459c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o				break;
11469c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			str[j++] = (unsigned char) (0xc0 | (c >> 6));
11479c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			str[j++] = (unsigned char) (0x80 | (c & 0x3f));
11489c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		} else {
11499c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			if (j+3 >= out_len)
11509c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o				break;
11519c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			str[j++] = (unsigned char) (0xe0 | (c >> 12));
11529c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			str[j++] = (unsigned char) (0x80 | ((c >> 6) & 0x3f));
11539c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			str[j++] = (unsigned char) (0x80 | (c & 0x3f));
11549c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		}
11559c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	}
11569c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	str[j] = '\0';
11579c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o}
11589c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
11599c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'ostatic int probe_hfs(struct blkid_probe *probe __BLKID_ATTR((unused)),
116069d742284d083c8f6ce7d9240019e21f2fbd9ed5Theodore Ts'o			 struct blkid_magic *id __BLKID_ATTR((unused)),
116169d742284d083c8f6ce7d9240019e21f2fbd9ed5Theodore Ts'o			 unsigned char *buf)
116269d742284d083c8f6ce7d9240019e21f2fbd9ed5Theodore Ts'o{
1163e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	struct hfs_mdb *hfs = (struct hfs_mdb *)buf;
1164e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	unsigned long long *uuid_ptr;
11659c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	char	uuid_str[17];
11669c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	__u64	uuid;
11679c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
11689c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if ((memcmp(hfs->embed_sig, "H+", 2) == 0) ||
11699c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	    (memcmp(hfs->embed_sig, "HX", 2) == 0))
11709c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		return 1;	/* Not hfs, but an embedded HFS+ */
11719c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
1172e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	uuid_ptr = (unsigned long long *)hfs->finder_info.id;
1173e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	uuid = blkid_le64(*uuid_ptr);
11749c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if (uuid) {
11759c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		sprintf(uuid_str, "%016llX", uuid);
11769c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		blkid_set_tag(probe->dev, "UUID", uuid_str, 0);
11779c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	}
1178e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blkid_set_tag(probe->dev, "LABEL", (char *)hfs->label, hfs->label_len);
11799c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	return 0;
11809c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o}
11819c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
11829c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
11839c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'ostatic int probe_hfsplus(struct blkid_probe *probe,
11849c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			 struct blkid_magic *id,
11859c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			 unsigned char *buf)
11869c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o{
11879c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
11889c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	struct hfsplus_bnode_descriptor *descr;
11899c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	struct hfsplus_bheader_record *bnode;
11909c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	struct hfsplus_catalog_key *key;
11919c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	struct hfsplus_vol_header *hfsplus;
11929c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	struct hfs_mdb *sbd = (struct hfs_mdb *) buf;
11939c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int alloc_block_size;
11949c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int alloc_first_block;
11959c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int embed_first_block;
11969c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int off = 0;
11979c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int blocksize;
11989c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int cat_block;
11999c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int ext_block_start;
12009c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int ext_block_count;
12019c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int record_count;
12029c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int leaf_node_head;
12039c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int leaf_node_count;
12049c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int leaf_node_size;
12059c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int leaf_block;
12069c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int label_len;
1207e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	unsigned long long *uuid_ptr;
12089c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	__u64 leaf_off, uuid;
12099c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	char	uuid_str[17], label[512];
1210e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	int ext;
121169d742284d083c8f6ce7d9240019e21f2fbd9ed5Theodore Ts'o
121269d742284d083c8f6ce7d9240019e21f2fbd9ed5Theodore Ts'o	/* Check for a HFS+ volume embedded in a HFS volume */
12139c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if (memcmp(sbd->signature, "BD", 2) == 0) {
12149c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		if ((memcmp(sbd->embed_sig, "H+", 2) != 0) &&
12159c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		    (memcmp(sbd->embed_sig, "HX", 2) != 0))
12169c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			/* This must be an HFS volume, so fail */
12179c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			return 1;
1218efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
12199c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		alloc_block_size = blkid_be32(sbd->al_blk_size);
12209c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		alloc_first_block = blkid_be16(sbd->al_bl_st);
12219c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		embed_first_block = blkid_be16(sbd->embed_startblock);
12229c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		off = (alloc_first_block * 512) +
12239c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			(embed_first_block * alloc_block_size);
12249c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		buf = get_buffer(probe, off + (id->bim_kboff * 1024),
12259c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o				 sizeof(sbd));
12269c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		if (!buf)
12279c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			return 1;
12289c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12299c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		hfsplus = (struct hfsplus_vol_header *) buf;
12309c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	}
12319c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12329c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	hfsplus = (struct hfsplus_vol_header *) buf;
12339c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12349c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if ((memcmp(hfsplus->signature, "H+", 2) != 0) &&
12359c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	    (memcmp(hfsplus->signature, "HX", 2) != 0))
12369c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		return 1;
12379c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
1238e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	uuid_ptr = (unsigned long long *)hfsplus->finder_info.id;
1239e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	uuid = blkid_le64(*uuid_ptr);
12409c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if (uuid) {
12419c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		sprintf(uuid_str, "%016llX", uuid);
12429c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		blkid_set_tag(probe->dev, "UUID", uuid_str, 0);
12439c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	}
12449c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12459c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	blocksize = blkid_be32(hfsplus->blocksize);
12469c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	memcpy(extents, hfsplus->cat_file.extents, sizeof(extents));
12479c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	cat_block = blkid_be32(extents[0].start_block);
12489c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12499c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	buf = get_buffer(probe, off + (cat_block * blocksize), 0x2000);
12509c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if (!buf)
125169d742284d083c8f6ce7d9240019e21f2fbd9ed5Theodore Ts'o		return 0;
125269d742284d083c8f6ce7d9240019e21f2fbd9ed5Theodore Ts'o
12539c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	bnode = (struct hfsplus_bheader_record *)
12549c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		&buf[sizeof(struct hfsplus_bnode_descriptor)];
12559c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12569c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	leaf_node_head = blkid_be32(bnode->leaf_head);
12579c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	leaf_node_size = blkid_be16(bnode->node_size);
12589c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	leaf_node_count = blkid_be32(bnode->leaf_count);
12599c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if (leaf_node_count == 0)
12609c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		return 0;
12619c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12629c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	leaf_block = (leaf_node_head * leaf_node_size) / blocksize;
12639c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12649c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	/* get physical location */
12659c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) {
12669c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		ext_block_start = blkid_be32(extents[ext].start_block);
12679c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		ext_block_count = blkid_be32(extents[ext].block_count);
12689c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		if (ext_block_count == 0)
12699c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			return 0;
12709c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12719c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		/* this is our extent */
12729c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		if (leaf_block < ext_block_count)
12739c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			break;
12749c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12759c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		leaf_block -= ext_block_count;
12769c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	}
12779c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if (ext == HFSPLUS_EXTENT_COUNT)
12789c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		return 0;
12799c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12809c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	leaf_off = (ext_block_start + leaf_block) * blocksize;
12819c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12829c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	buf = get_buffer(probe, off + leaf_off, leaf_node_size);
12839c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if (!buf)
12849c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		return 0;
12859c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12869c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	descr = (struct hfsplus_bnode_descriptor *) buf;
12879c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	record_count = blkid_be16(descr->num_recs);
12889c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if (record_count == 0)
12899c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		return 0;
12909c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12919c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if (descr->type != HFS_NODE_LEAF)
12929c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		return 0;
12939c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12949c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	key = (struct hfsplus_catalog_key *)
12959c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		&buf[sizeof(struct hfsplus_bnode_descriptor)];
12969c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12979c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if (blkid_be32(key->parent_id) != HFSPLUS_POR_CNID)
12989c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		return 0;
12999c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
13009c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	label_len = blkid_be16(key->unicode_len) * 2;
1301e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	unicode_16be_to_utf8((unsigned char *)label, sizeof(label),
1302e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			     key->unicode, label_len);
13039c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", label, 0);
13049c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	return 0;
130569d742284d083c8f6ce7d9240019e21f2fbd9ed5Theodore Ts'o}
130669d742284d083c8f6ce7d9240019e21f2fbd9ed5Theodore Ts'o
1307a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen#define LVM2_LABEL_SIZE 512
1308dd232049d19112d46d4b296c1b253ef05e9dc67cTheodore Ts'ostatic unsigned int lvm2_calc_crc(const void *buf, unsigned int size)
1309a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen{
1310dd232049d19112d46d4b296c1b253ef05e9dc67cTheodore Ts'o	static const unsigned int crctab[] = {
1311a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
1312a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
1313a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
1314a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
1315a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	};
1316dd232049d19112d46d4b296c1b253ef05e9dc67cTheodore Ts'o	unsigned int i, crc = 0xf597a6cf;
1317a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	const __u8 *data = (const __u8 *) buf;
1318a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen
1319a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	for (i = 0; i < size; i++) {
1320a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		crc ^= *data++;
1321a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		crc = (crc >> 4) ^ crctab[crc & 0xf];
1322a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		crc = (crc >> 4) ^ crctab[crc & 0xf];
1323a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	}
1324a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	return crc;
1325a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen}
1326a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen
1327a451d92f38188f7218a837a395b310354864b5a4Eric Sandeenstatic int probe_lvm2(struct blkid_probe *probe,
1328cc19b958602775ef48f347d16859ce6623a385daTheodore Ts'o			struct blkid_magic *id,
1329a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen			unsigned char *buf)
1330a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen{
13318d45e2104cdebcd509810786756cfb2e40588620Theodore Ts'o	int sector = (id->bim_kboff) << 1;
1332cc19b958602775ef48f347d16859ce6623a385daTheodore Ts'o	struct lvm2_pv_label_header *label= (struct lvm2_pv_label_header *)buf;
1333a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	char *p, *q, uuid[40];
1334a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	unsigned int i, b;
1335a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen
1336a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	/* buf is at 0k or 1k offset; find label inside */
1337a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	if (memcmp(buf, "LABELONE", 8) == 0) {
1338a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		label = (struct lvm2_pv_label_header *)buf;
1339a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	} else if (memcmp(buf + 512, "LABELONE", 8) == 0) {
1340a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		label = (struct lvm2_pv_label_header *)(buf + 512);
1341a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		sector++;
1342a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	} else {
1343a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		return 1;
1344a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	}
1345a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen
13463a538e42441afa5e5b34942062acb976e0d345f6Theodore Ts'o	if (blkid_le64(label->sector_xl) != (unsigned) sector) {
1347a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		DBG(DEBUG_PROBE,
13483a538e42441afa5e5b34942062acb976e0d345f6Theodore Ts'o		    printf("LVM2: label for sector %llu found at sector %d\n",
1349a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen			   blkid_le64(label->sector_xl), sector));
1350a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		return 1;
1351a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	}
1352a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen
1353a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	if (lvm2_calc_crc(&label->offset_xl, LVM2_LABEL_SIZE -
13543a538e42441afa5e5b34942062acb976e0d345f6Theodore Ts'o			  ((char *)&label->offset_xl - (char *)label)) !=
1355a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen			blkid_le32(label->crc_xl)) {
1356a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		DBG(DEBUG_PROBE,
1357a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		    printf("LVM2: label checksum incorrect at sector %d\n",
1358a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen			   sector));
1359a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		return 1;
1360a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	}
1361a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen
13623a538e42441afa5e5b34942062acb976e0d345f6Theodore Ts'o	for (i=0, b=1, p=uuid, q= (char *) label->pv_uuid; i <= 32;
13633a538e42441afa5e5b34942062acb976e0d345f6Theodore Ts'o	     i++, b <<= 1) {
1364a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		if (b & 0x4444440)
1365a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen			*p++ = '-';
1366a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		*p++ = *q++;
1367a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	}
1368a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen
1369a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	blkid_set_tag(probe->dev, "UUID", uuid, LVM2_ID_LEN+6);
1370a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen
1371a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	return 0;
1372a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen}
1373801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen
1374801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeenstatic int probe_btrfs(struct blkid_probe *probe,
1375801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen			struct blkid_magic *id,
1376801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen			unsigned char *buf)
1377801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen{
1378801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen	struct btrfs_super_block *bs;
1379801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen	const char *label = 0;
1380801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen
1381801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen	bs = (struct btrfs_super_block *)buf;
1382801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen
1383801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen	if (strlen(bs->label))
1384801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen		label = bs->label;
1385801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen	blkid_set_tag(probe->dev, "LABEL", label, sizeof(bs->label));
1386801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen	set_uuid(probe->dev, bs->fsid, 0);
1387801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen	return 0;
1388801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen}
1389e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o/*
1390e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * Various filesystem magics that we can check for.  Note that kboff and
1391e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * sboff are in kilobytes and bytes respectively.  All magics are in
1392e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * byte strings so we don't worry about endian issues.
1393e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o */
139450b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'ostatic struct blkid_magic type_array[] = {
139550b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o/*  type     kboff   sboff len  magic			probe */
13962c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o  { "oracleasm", 0,	32,  8, "ORCLDISK",		probe_oracleasm },
1397cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o  { "ntfs",	 0,	 3,  8, "NTFS    ",		probe_ntfs },
139850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "jbd",	 1,   0x38,  2, "\123\357",		probe_jbd },
13992921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o  { "ext4dev",	 1,   0x38,  2, "\123\357",		probe_ext4dev },
14002921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o  { "ext4",	 1,   0x38,  2, "\123\357",		probe_ext4 },
14012e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o  { "ext3",	 1,   0x38,  2, "\123\357",		probe_ext3 },
140250b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "ext2",	 1,   0x38,  2, "\123\357",		probe_ext2 },
140350b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "reiserfs",	 8,   0x34,  8, "ReIsErFs",		probe_reiserfs },
140450b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "reiserfs", 64,   0x34,  9, "ReIsEr2Fs",		probe_reiserfs },
140550b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "reiserfs", 64,   0x34,  9, "ReIsEr3Fs",		probe_reiserfs },
140650b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "reiserfs", 64,   0x34,  8, "ReIsErFs",		probe_reiserfs },
140750b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "reiserfs",	 8,	20,  8, "ReIsErFs",		probe_reiserfs },
1408bb626bcd546a039b39b9f25e65881b36b2abe24fTheodore Ts'o  { "reiser4",  64,	 0,  7, "ReIsEr4",		probe_reiserfs4 },
1409b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak  { "gfs2",     64,      0,  4, "\x01\x16\x19\x70",     probe_gfs2 },
1410b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak  { "gfs",      64,      0,  4, "\x01\x16\x19\x70",     probe_gfs },
1411038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o  { "vfat",      0,   0x52,  5, "MSWIN",                probe_fat },
1412038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o  { "vfat",      0,   0x52,  8, "FAT32   ",             probe_fat },
1413038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o  { "vfat",      0,   0x36,  5, "MSDOS",                probe_fat },
1414038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o  { "vfat",      0,   0x36,  8, "FAT16   ",             probe_fat },
1415038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o  { "vfat",      0,   0x36,  8, "FAT12   ",             probe_fat },
1416846be6db813895c354cc54beaa8fa6aba8d98085Theodore Ts'o  { "vfat",      0,      0,  1, "\353",                 probe_fat_nomagic },
1417038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o  { "vfat",      0,      0,  1, "\351",                 probe_fat_nomagic },
1418846be6db813895c354cc54beaa8fa6aba8d98085Theodore Ts'o  { "vfat",      0,  0x1fe,  2, "\125\252",             probe_fat_nomagic },
141950b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "minix",     1,   0x10,  2, "\177\023",             0 },
142050b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "minix",     1,   0x10,  2, "\217\023",             0 },
142150b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "minix",	 1,   0x10,  2, "\150\044",		0 },
142250b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "minix",	 1,   0x10,  2, "\170\044",		0 },
142350b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "vxfs",	 1,	 0,  4, "\365\374\001\245",	0 },
142450b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "xfs",	 0,	 0,  4, "XFSB",			probe_xfs },
142509a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o  { "romfs",	 0,	 0,  8, "-rom1fs-",		probe_romfs },
142650b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "bfs",	 0,	 0,  4, "\316\372\173\033",	0 },
14274c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o  { "cramfs",	 0,	 0,  4, "E=\315\050",		probe_cramfs },
142850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "qnx4",	 0,	 4,  6, "QNX4FS",		0 },
14293de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o  { "udf",	32,	 1,  5, "BEA01",		probe_udf },
14303de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o  { "udf",	32,	 1,  5, "BOOT2",		probe_udf },
14313de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o  { "udf",	32,	 1,  5, "CD001",		probe_udf },
14323de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o  { "udf",	32,	 1,  5, "CDW02",		probe_udf },
14333de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o  { "udf",	32,	 1,  5, "NSR02",		probe_udf },
14343de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o  { "udf",	32,	 1,  5, "NSR03",		probe_udf },
14353de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o  { "udf",	32,	 1,  5, "TEA01",		probe_udf },
143645a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o  { "iso9660",	32,	 1,  5, "CD001",		probe_iso9660 },
143745a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o  { "iso9660",	32,	 9,  5, "CDROM",		probe_iso9660 },
143809a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o  { "jfs",	32,	 0,  4, "JFS1",			probe_jfs },
1439c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia  { "zfs",       8,	 0,  8, "\0\0\x02\xf5\xb0\x07\xb1\x0c", probe_zfs },
1440c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia  { "zfs",       8,	 0,  8, "\x0c\xb1\x07\xb0\xf5\x02\0\0", probe_zfs },
1441c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia  { "zfs",     264,	 0,  8, "\0\0\x02\xf5\xb0\x07\xb1\x0c", probe_zfs },
1442c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia  { "zfs",     264,	 0,  8, "\x0c\xb1\x07\xb0\xf5\x02\0\0", probe_zfs },
144369d742284d083c8f6ce7d9240019e21f2fbd9ed5Theodore Ts'o  { "hfsplus",	 1,	 0,  2, "BD",			probe_hfsplus },
14449c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o  { "hfsplus",	 1,	 0,  2, "H+",			probe_hfsplus },
14459c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o  { "hfsplus",	 1,	 0,  2, "HX",			probe_hfsplus },
14469c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o  { "hfs",	 1,	 0,  2, "BD",			probe_hfs },
144750b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "ufs",	 8,  0x55c,  4, "T\031\001\000",	0 },
144850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "hpfs",	 8,	 0,  4, "I\350\225\371",	0 },
144950b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "sysv",	 0,  0x3f8,  4, "\020~\030\375",	0 },
14507369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o  { "swap",	 0,  0xff6, 10, "SWAP-SPACE",		probe_swap0 },
14517369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o  { "swap",	 0,  0xff6, 10, "SWAPSPACE2",		probe_swap1 },
1452abaa11240a742bcfc4783e2cbebb7dd0cdf17e96Karel Zak  { "swsuspend", 0,  0xff6,  9, "S1SUSPEND",		probe_swap1 },
1453abaa11240a742bcfc4783e2cbebb7dd0cdf17e96Karel Zak  { "swsuspend", 0,  0xff6,  9, "S2SUSPEND",		probe_swap1 },
145431e2a75484816db0e5e68afacb13beef7e751061Theodore Ts'o  { "swsuspend", 0,  0xff6,  9, "ULSUSPEND",		probe_swap1 },
14557369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o  { "swap",	 0, 0x1ff6, 10, "SWAP-SPACE",		probe_swap0 },
14567369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o  { "swap",	 0, 0x1ff6, 10, "SWAPSPACE2",		probe_swap1 },
1457abaa11240a742bcfc4783e2cbebb7dd0cdf17e96Karel Zak  { "swsuspend", 0, 0x1ff6,  9, "S1SUSPEND",		probe_swap1 },
1458abaa11240a742bcfc4783e2cbebb7dd0cdf17e96Karel Zak  { "swsuspend", 0, 0x1ff6,  9, "S2SUSPEND",		probe_swap1 },
145931e2a75484816db0e5e68afacb13beef7e751061Theodore Ts'o  { "swsuspend", 0, 0x1ff6,  9, "ULSUSPEND",		probe_swap1 },
14607369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o  { "swap",	 0, 0x3ff6, 10, "SWAP-SPACE",		probe_swap0 },
14617369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o  { "swap",	 0, 0x3ff6, 10, "SWAPSPACE2",		probe_swap1 },
1462abaa11240a742bcfc4783e2cbebb7dd0cdf17e96Karel Zak  { "swsuspend", 0, 0x3ff6,  9, "S1SUSPEND",		probe_swap1 },
1463abaa11240a742bcfc4783e2cbebb7dd0cdf17e96Karel Zak  { "swsuspend", 0, 0x3ff6,  9, "S2SUSPEND",		probe_swap1 },
146431e2a75484816db0e5e68afacb13beef7e751061Theodore Ts'o  { "swsuspend", 0, 0x3ff6,  9, "ULSUSPEND",		probe_swap1 },
14657369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o  { "swap",	 0, 0x7ff6, 10, "SWAP-SPACE",		probe_swap0 },
14667369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o  { "swap",	 0, 0x7ff6, 10, "SWAPSPACE2",		probe_swap1 },
1467abaa11240a742bcfc4783e2cbebb7dd0cdf17e96Karel Zak  { "swsuspend", 0, 0x7ff6,  9, "S1SUSPEND",		probe_swap1 },
1468abaa11240a742bcfc4783e2cbebb7dd0cdf17e96Karel Zak  { "swsuspend", 0, 0x7ff6,  9, "S2SUSPEND",		probe_swap1 },
146931e2a75484816db0e5e68afacb13beef7e751061Theodore Ts'o  { "swsuspend", 0, 0x7ff6,  9, "ULSUSPEND",		probe_swap1 },
14707369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o  { "swap",	 0, 0xfff6, 10, "SWAP-SPACE",		probe_swap0 },
14717369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o  { "swap",	 0, 0xfff6, 10, "SWAPSPACE2",		probe_swap1 },
1472abaa11240a742bcfc4783e2cbebb7dd0cdf17e96Karel Zak  { "swsuspend", 0, 0xfff6,  9, "S1SUSPEND",		probe_swap1 },
1473abaa11240a742bcfc4783e2cbebb7dd0cdf17e96Karel Zak  { "swsuspend", 0, 0xfff6,  9, "S2SUSPEND",		probe_swap1 },
147431e2a75484816db0e5e68afacb13beef7e751061Theodore Ts'o  { "swsuspend", 0, 0xfff6,  9, "ULSUSPEND",		probe_swap1 },
14752c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o  { "ocfs",	 0,	 8,  9,	"OracleCFS",		probe_ocfs },
14762c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o  { "ocfs2",	 1,	 0,  6,	"OCFSV2",		probe_ocfs2 },
14772c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o  { "ocfs2",	 2,	 0,  6,	"OCFSV2",		probe_ocfs2 },
14782c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o  { "ocfs2",	 4,	 0,  6,	"OCFSV2",		probe_ocfs2 },
14792c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o  { "ocfs2",	 8,	 0,  6,	"OCFSV2",		probe_ocfs2 },
1480e382a7eaded3ec6b38114988ae9b0723bb48002aKarsten Hopp  { "crypt_LUKS", 0,	 0,  6,	"LUKS\xba\xbe",		probe_luks },
1481f493d4e0ac93a5c500a2e9360a2398a8637895b6Eric Sandeen  { "squashfs",	 0,	 0,  4,	"sqsh",			0 },
14825845efd1238081e48b0fc37e8bb55c87a0a537bfEric Sandeen  { "squashfs",	 0,	 0,  4,	"hsqs",			0 },
1483a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen  { "lvm2pv",	 0,  0x218,  8, "LVM2 001",		probe_lvm2 },
1484a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen  { "lvm2pv",	 0,  0x018,  8, "LVM2 001",		probe_lvm2 },
1485a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen  { "lvm2pv",	 1,  0x018,  8, "LVM2 001",		probe_lvm2 },
1486a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen  { "lvm2pv",	 1,  0x218,  8, "LVM2 001",		probe_lvm2 },
1487801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen  { "btrfs",	 64,  0x40,  8, "_BHRfS_M",		probe_btrfs },
148850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  {   NULL,	 0,	 0,  0, NULL,			NULL }
1489e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o};
1490e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
1491e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o/*
1492e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * Verify that the data in dev is consistent with what is on the actual
1493e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * block device (using the devname field only).  Normally this will be
1494e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * called when finding items in the cache, but for long running processes
1495e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * is also desirable to revalidate an item before use.
1496e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o *
1497e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * If we are unable to revalidate the data, we return the old data and
1498e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * do not set the BLKID_BID_FL_VERIFIED flag on it.
1499e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o */
150018d12963335b04a402d097af1d714e8708805adaTheodore Ts'oblkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
1501e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o{
1502e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	struct blkid_magic *id;
1503ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	struct blkid_probe probe;
1504ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o	blkid_tag_iterate iter;
1505ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	unsigned char *buf;
1506ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o	const char *type, *value;
150750b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	struct stat st;
15089f9a0502c08474b18ab6084f0c251672eb8543d7Jeff Sharkey	time_t now;
15099f9a0502c08474b18ab6084f0c251672eb8543d7Jeff Sharkey	double diff;
1510ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	int idx;
1511e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
1512e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	if (!dev)
1513e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		return NULL;
1514e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
15157ce08064061ed66647fa2c152c65f2f28eac9a0aTheodore Ts'o	now = time(0);
15169f9a0502c08474b18ab6084f0c251672eb8543d7Jeff Sharkey	diff = difftime(now, dev->bid_time);
1517e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
1518492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o	if (stat(dev->bid_name, &st) < 0) {
1519492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o		DBG(DEBUG_PROBE,
1520492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o		    printf("blkid_verify: error %s (%d) while "
1521492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o			   "trying to stat %s\n", strerror(errno), errno,
1522492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o			   dev->bid_name));
1523492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o	open_err:
1524492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o		if ((errno == EPERM) || (errno == EACCES) || (errno == ENOENT)) {
1525492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o			/* We don't have read permission, just return cache data. */
1526492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o			DBG(DEBUG_PROBE, printf("returning unverified data for %s\n",
1527492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o						dev->bid_name));
1528492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o			return dev;
1529492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o		}
1530492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o		blkid_free_dev(dev);
1531492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o		return NULL;
1532492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o	}
1533492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o
1534492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o	if ((now >= dev->bid_time) &&
1535492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o	    (st.st_mtime <= dev->bid_time) &&
1536efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	    ((diff < BLKID_PROBE_MIN) ||
1537e324b250593a32680309015eba7c6c5db7851227Theodore Ts'o	     (dev->bid_flags & BLKID_BID_FL_VERIFIED &&
1538e324b250593a32680309015eba7c6c5db7851227Theodore Ts'o	      diff < BLKID_PROBE_INTERVAL)))
1539e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		return dev;
1540e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
1541f0a22d0fd3ec3f45b562af5afba8811f72b94a28Theodore Ts'o	DBG(DEBUG_PROBE,
154279e62409b3a247e258d9e9206484ed8f193a183eEric Sandeen	    printf("need to revalidate %s (cache time %lu, stat time %lu,\n\t"
1543492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o		   "time since last check %lu)\n",
154479e62409b3a247e258d9e9206484ed8f193a183eEric Sandeen		   dev->bid_name, (unsigned long)dev->bid_time,
154579e62409b3a247e258d9e9206484ed8f193a183eEric Sandeen		   (unsigned long)st.st_mtime, (unsigned long)diff));
1546492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o
1547492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o	if ((probe.fd = open(dev->bid_name, O_RDONLY)) < 0) {
1548492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o		DBG(DEBUG_PROBE, printf("blkid_verify: error %s (%d) while "
1549efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o					"opening %s\n", strerror(errno), errno,
1550492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o					dev->bid_name));
1551492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o		goto open_err;
1552e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	}
1553e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
1554ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	probe.cache = cache;
1555ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	probe.dev = dev;
1556ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	probe.sbbuf = 0;
1557ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	probe.buf = 0;
1558ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	probe.buf_max = 0;
1559efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
156050b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	/*
156150b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	 * Iterate over the type array.  If we already know the type,
156250b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	 * then try that first.  If it doesn't work, then blow away
156350b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	 * the type information, and try again.
1564efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	 *
156550b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	 */
156650b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'otry_again:
156750b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	type = 0;
156850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) {
156950b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		uuid_t	uuid;
157050b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o
1571ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		if (check_mdraid(probe.fd, uuid) == 0) {
1572ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o			set_uuid(dev, uuid, 0);
157350b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o			type = "mdraid";
157450b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o			goto found_type;
157550b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		}
157650b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	}
1577e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	for (id = type_array; id->bim_type; id++) {
157850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		if (dev->bid_type &&
157950b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		    strcmp(id->bim_type, dev->bid_type))
158050b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o			continue;
158150b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o
158250b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		idx = id->bim_kboff + (id->bim_sboff >> 10);
1583ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		buf = get_buffer(&probe, idx << 10, 1024);
1584ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		if (!buf)
158550b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o			continue;
1586e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
1587c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia		if (memcmp(id->bim_magic, buf + (id->bim_sboff & 0x3ff),
158850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o			   id->bim_len))
158950b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o			continue;
159050b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o
159150b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		if ((id->bim_probe == NULL) ||
1592ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		    (id->bim_probe(&probe, id, buf) == 0)) {
159350b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o			type = id->bim_type;
159450b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o			goto found_type;
1595e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		}
1596e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	}
1597e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
159850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	if (!id->bim_type && dev->bid_type) {
159950b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		/*
1600ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o		 * Zap the device filesystem information and try again
160150b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		 */
16020225face1bd0dddaf19ee8089dc28980a0395633Theodore Ts'o		DBG(DEBUG_PROBE,
16030225face1bd0dddaf19ee8089dc28980a0395633Theodore Ts'o		    printf("previous fs type %s not valid, "
16040225face1bd0dddaf19ee8089dc28980a0395633Theodore Ts'o			   "trying full probe\n", dev->bid_type));
1605ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o		iter = blkid_tag_iterate_begin(dev);
1606ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o		while (blkid_tag_next(iter, &type, &value) == 0)
1607ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o			blkid_set_tag(dev, type, 0, 0);
1608ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o		blkid_tag_iterate_end(iter);
160950b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		goto try_again;
161050b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	}
1611e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
161250b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	if (!dev->bid_type) {
1613e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		blkid_free_dev(dev);
1614257ace82b77a281da6d0491294eda6f0b27ef424Theodore Ts'o		dev = 0;
1615257ace82b77a281da6d0491294eda6f0b27ef424Theodore Ts'o		goto found_type;
161650b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	}
1617c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia
161850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'ofound_type:
161950b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	if (dev && type) {
162050b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		dev->bid_devno = st.st_rdev;
162150b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		dev->bid_time = time(0);
162250b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		dev->bid_flags |= BLKID_BID_FL_VERIFIED;
1623ce72b862c59da24ba16b354d687549276a24f908Theodore Ts'o		cache->bic_flags |= BLKID_BIC_FL_CHANGED;
162450b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o
162579dd234a799434b6dc8365c49e743f00eb09d2fdTheodore Ts'o		blkid_set_tag(dev, "TYPE", type, 0);
1626c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia
162712b3c8ec1d314b8775fc7d9cefd6bfff551f1de0Theodore Ts'o		DBG(DEBUG_PROBE, printf("%s: devno 0x%04llx, type %s\n",
162812a829dcdc57fb8ddc4887b07b40136288b6e7feMatthias Andree			   dev->bid_name, (long long)st.st_rdev, type));
1629e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	}
1630e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
163145e338f5332a54295893dba2e32cc093d1316f60Jim Meyering	free(probe.sbbuf);
163245e338f5332a54295893dba2e32cc093d1316f60Jim Meyering	free(probe.buf);
1633efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	if (probe.fd >= 0)
1634257ace82b77a281da6d0491294eda6f0b27ef424Theodore Ts'o		close(probe.fd);
1635e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
1636e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	return dev;
1637e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o}
1638e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
163978e2edf796e7902b8ce615ca8388840ef1387194Theodore Ts'oint blkid_known_fstype(const char *fstype)
164078e2edf796e7902b8ce615ca8388840ef1387194Theodore Ts'o{
164178e2edf796e7902b8ce615ca8388840ef1387194Theodore Ts'o	struct blkid_magic *id;
164278e2edf796e7902b8ce615ca8388840ef1387194Theodore Ts'o
164378e2edf796e7902b8ce615ca8388840ef1387194Theodore Ts'o	for (id = type_array; id->bim_type; id++) {
164478e2edf796e7902b8ce615ca8388840ef1387194Theodore Ts'o		if (strcmp(fstype, id->bim_type) == 0)
164578e2edf796e7902b8ce615ca8388840ef1387194Theodore Ts'o			return 1;
164678e2edf796e7902b8ce615ca8388840ef1387194Theodore Ts'o	}
164778e2edf796e7902b8ce615ca8388840ef1387194Theodore Ts'o	return 0;
164878e2edf796e7902b8ce615ca8388840ef1387194Theodore Ts'o}
164978e2edf796e7902b8ce615ca8388840ef1387194Theodore Ts'o
1650e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#ifdef TEST_PROGRAM
1651e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'oint main(int argc, char **argv)
1652e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o{
16537a603aa89fcffb8798eca34ca3858db6f0393046Theodore Ts'o	blkid_dev dev;
165450b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	blkid_cache cache;
165579dd234a799434b6dc8365c49e743f00eb09d2fdTheodore Ts'o	int ret;
1656e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
1657e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	if (argc != 2) {
1658e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		fprintf(stderr, "Usage: %s device\n"
1659e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o			"Probe a single device to determine type\n", argv[0]);
1660e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		exit(1);
1661e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	}
166279dd234a799434b6dc8365c49e743f00eb09d2fdTheodore Ts'o	if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) {
166379dd234a799434b6dc8365c49e743f00eb09d2fdTheodore Ts'o		fprintf(stderr, "%s: error creating cache (%d)\n",
166479dd234a799434b6dc8365c49e743f00eb09d2fdTheodore Ts'o			argv[0], ret);
166579dd234a799434b6dc8365c49e743f00eb09d2fdTheodore Ts'o		exit(1);
166679dd234a799434b6dc8365c49e743f00eb09d2fdTheodore Ts'o	}
166798999c399d563c248728bf217467a788cb0c1aadTheodore Ts'o	dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL);
166850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	if (!dev) {
1669e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		printf("%s: %s has an unsupported type\n", argv[0], argv[1]);
167050b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		return (1);
167150b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	}
16721e5630abab066035602437ed047e0988064687f0Theodore Ts'o	printf("TYPE='%s'\n", dev->bid_type ? dev->bid_type : "(null)");
167350b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	if (dev->bid_label)
16741e5630abab066035602437ed047e0988064687f0Theodore Ts'o		printf("LABEL='%s'\n", dev->bid_label);
167550b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	if (dev->bid_uuid)
16761e5630abab066035602437ed047e0988064687f0Theodore Ts'o		printf("UUID='%s'\n", dev->bid_uuid);
1677efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
167850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	blkid_free_dev(dev);
1679e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	return (0);
1680e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o}
1681e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#endif
1682