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
16d1154eb460efe588eaed3d439c1caaca149fa362Theodore Ts'o#include "config.h"
17e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <stdio.h>
18e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <string.h>
19e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <stdlib.h>
20e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <unistd.h>
21e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <fcntl.h>
223a538e42441afa5e5b34942062acb976e0d345f6Theodore Ts'o#include <ctype.h>
23e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <sys/types.h>
24e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#ifdef HAVE_SYS_STAT_H
25e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <sys/stat.h>
26e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#endif
27e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#ifdef HAVE_SYS_MKDEV_H
28e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <sys/mkdev.h>
29e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#endif
3018f734301012301efbeb87a7c67f6cf82f1721d7Eric Sandeen#ifdef __linux__
31cfc19311947dc4bd1731f641a8c52135a02e5559Theodore Ts'o#include <sys/utsname.h>
3218f734301012301efbeb87a7c67f6cf82f1721d7Eric Sandeen#endif
33e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#ifdef HAVE_ERRNO_H
34e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <errno.h>
35e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#endif
367a603aa89fcffb8798eca34ca3858db6f0393046Theodore Ts'o#include "blkidP.h"
37e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include "uuid/uuid.h"
38e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include "probe.h"
39e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
4045a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'ostatic int figure_label_len(const unsigned char *label, int len)
4145a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o{
4245a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o	const unsigned char *end = label + len - 1;
4345a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o
4445a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o	while ((*end == ' ' || *end == 0) && end >= label)
4545a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o		--end;
46871ad942641b604631a9d33a7008e073ba946a9eTheodore Ts'o	if (end >= label)
4745a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o		return end - label + 1;
4845a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o	return 0;
4945a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o}
5045a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o
51efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ostatic unsigned char *get_buffer(struct blkid_probe *pr,
52cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o			  blkid_loff_t off, size_t len)
53ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o{
54ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	ssize_t		ret_read;
55ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	unsigned char	*newbuf;
56ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o
57ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	if (off + len <= SB_BUFFER_SIZE) {
58ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		if (!pr->sbbuf) {
59ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			pr->sbbuf = malloc(SB_BUFFER_SIZE);
60ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			if (!pr->sbbuf)
61ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o				return NULL;
62ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			if (lseek(pr->fd, 0, SEEK_SET) < 0)
63ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o				return NULL;
64ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			ret_read = read(pr->fd, pr->sbbuf, SB_BUFFER_SIZE);
65ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			if (ret_read < 0)
66ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o				ret_read = 0;
67ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			pr->sb_valid = ret_read;
68ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		}
69ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		if (off+len > pr->sb_valid)
70ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			return NULL;
71ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		return pr->sbbuf + off;
72ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	} else {
73ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		if (len > pr->buf_max) {
74ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			newbuf = realloc(pr->buf, len);
75ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			if (newbuf == NULL)
76ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o				return NULL;
77ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			pr->buf = newbuf;
78ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			pr->buf_max = len;
79ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		}
80cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		if (blkid_llseek(pr->fd, off, SEEK_SET) < 0)
81ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			return NULL;
82ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		ret_read = read(pr->fd, pr->buf, len);
83ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		if (ret_read != (ssize_t) len)
84ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			return NULL;
85ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		return pr->buf;
86ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	}
87ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o}
88ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o
89ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o
90e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o/*
9150b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o * This is a special case code to check for an MDRAID device.  We do
9250b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o * this special since it requires checking for a superblock at the end
9350b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o * of the device.
94e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o */
9550b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'ostatic int check_mdraid(int fd, unsigned char *ret_uuid)
96e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o{
9750b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	struct mdp_superblock_s *md;
9850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	blkid_loff_t		offset;
9950b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	char			buf[4096];
100efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
10150b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	if (fd < 0)
102e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		return -BLKID_ERR_PARAM;
103e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
10450b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	offset = (blkid_get_dev_size(fd) & ~((blkid_loff_t)65535)) - 65536;
105e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
106e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	if (blkid_llseek(fd, offset, 0) < 0 ||
10750b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	    read(fd, buf, 4096) != 4096)
108e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		return -BLKID_ERR_IO;
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
245d1da14b5b0496621046179e5644cc924ce01dae1Theodore Ts'ostatic int linux_version_code(void)
2461361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o{
2471361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o#ifdef __linux__
2481361821e7e248166f0740c832b164e6cd6b89de9Theodore Ts'o	struct utsname	ut;
249cf5301d7f2c3bbed3d26600335102414cbf0c4baAndreas Dilger	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
3321206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao	/*
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
3761206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao	/*
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
4541206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao	/*
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
587a8307ab8cc3699aa47cd4d9fc176fc2cfde7b0e7Theodore Ts'o			next_sect_off = (next - 2) * vs->vs_cluster_size;
588a8307ab8cc3699aa47cd4d9fc176fc2cfde7b0e7Theodore Ts'o			next_off = (__u64) (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 */
603d1da14b5b0496621046179e5644cc924ce01dae1Theodore Ts'o			fat_entry_off =
604d1da14b5b0496621046179e5644cc924ce01dae1Theodore Ts'o				((unsigned int) reserved *
605d1da14b5b0496621046179e5644cc924ce01dae1Theodore Ts'o				 (unsigned int) sector_size) +
6062f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o				(next * sizeof(__u32));
6072f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			buf = get_buffer(probe, fat_entry_off, buf_size);
6082f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			if (buf == NULL)
6092f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o				break;
6102f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o
6112f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			/* set next cluster */
6122f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			next = blkid_le32(*((__u32 *) buf) & 0x0fffffff);
6132f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o		}
6142f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o
6152f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o		if (!vol_label || !memcmp(vol_label, no_name, 11))
6162f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o			vol_label = vs->vs_label;
617038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o		vol_serno = vs->vs_serno;
618038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o	}
619e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
6202f79e5193fa14bb338f14e07c3c96070092b6e8aTheodore Ts'o	if (vol_label && memcmp(vol_label, no_name, 11)) {
621633f453db14b0fb91294887a9629f5cc2f95407fKarel Zak		if ((label_len = figure_label_len(vol_label, 11)))
622633f453db14b0fb91294887a9629f5cc2f95407fKarel Zak			label = vol_label;
623e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	}
624e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
625e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	/* We can't just print them as %04X, because they are unaligned */
626038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o	sprintf(serno, "%02X%02X-%02X%02X", vol_serno[3], vol_serno[2],
627038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o		vol_serno[1], vol_serno[0]);
628038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o
629ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", (const char *) label, label_len);
630ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "UUID", serno, sizeof(serno)-1);
631e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
632e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	return 0;
633e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o}
634e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
635c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak/*
636c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak * The FAT filesystem could be without a magic string in superblock
637c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak * (e.g. old floppies).  This heuristic for FAT detection is inspired
638c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak * by http://vrfy.org/projects/volume_id/ and Linux kernel.
639c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak * [7-Jul-2005, Karel Zak <kzak@redhat.com>]
640c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak */
641ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_fat_nomagic(struct blkid_probe *probe,
642efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			     struct blkid_magic *id __BLKID_ATTR((unused)),
643038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o			     unsigned char *buf)
644c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak{
64578d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	struct msdos_super_block *ms;
646c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak
64778d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	ms = (struct msdos_super_block *)buf;
648c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak
649c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak	/* heads check */
65078d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	if (ms->ms_heads == 0)
651c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak		return 1;
652c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak
653efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	/* cluster size check*/
65478d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	if (ms->ms_cluster_size == 0 ||
65578d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	    (ms->ms_cluster_size & (ms->ms_cluster_size-1)))
656c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak		return 1;
657c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak
658c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak	/* media check */
65978d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	if (ms->ms_media < 0xf8 && ms->ms_media != 0xf0)
660c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak		return 1;
661c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak
662c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak	/* fat counts(Linux kernel expects at least 1 FAT table) */
66378d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	if (!ms->ms_fats)
66478d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o		return 1;
66578d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o
66678d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	/*
66778d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	 * OS/2 and apparently DFSee will place a FAT12/16-like
66878d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	 * pseudo-superblock in the first 512 bytes of non-FAT
66978d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	 * filesystems --- at least JFS and HPFS, and possibly others.
67078d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	 * So we explicitly check for those filesystems at the
67178d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	 * FAT12/16 filesystem magic field identifier, and if they are
67278d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	 * present, we rule this out as a FAT filesystem, despite the
67378d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	 * FAT-like pseudo-header.
67478d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o         */
67578d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	if ((memcmp(ms->ms_magic, "JFS     ", 8) == 0) ||
67678d89cda680498957e4ad78602751d1f905cee08Theodore Ts'o	    (memcmp(ms->ms_magic, "HPFS    ", 8) == 0))
677c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak		return 1;
678c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak
679ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	return probe_fat(probe, id, buf);
680c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak}
681c4c740ff488dae232dd3a64fccd26ec7265165a4Karel Zak
682cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'ostatic int probe_ntfs(struct blkid_probe *probe,
683efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		      struct blkid_magic *id __BLKID_ATTR((unused)),
684cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		      unsigned char *buf)
685cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o{
686cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	struct ntfs_super_block *ns;
687cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	struct master_file_table_record *mft;
688cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	struct file_attribute *attr;
689cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	char		uuid_str[17], label_str[129], *cp;
690cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	int		bytes_per_sector, sectors_per_cluster;
691cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	int		mft_record_size, attr_off, attr_len;
692cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	unsigned int	i, attr_type, val_len;
693cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	int		val_off;
694cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	__u64		nr_clusters;
695cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	blkid_loff_t off;
696cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	unsigned char *buf_mft, *val;
697cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
698cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	ns = (struct ntfs_super_block *) buf;
699cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
700cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	bytes_per_sector = ns->bios_parameter_block[0] +
701cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		(ns->bios_parameter_block[1]  << 8);
702cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	sectors_per_cluster = ns->bios_parameter_block[2];
703cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
70430dd2622353b9fde462c9112fb0c863620a3bf91Theodore Ts'o	if ((bytes_per_sector < 512) || (sectors_per_cluster == 0))
70530dd2622353b9fde462c9112fb0c863620a3bf91Theodore Ts'o		return 1;
70630dd2622353b9fde462c9112fb0c863620a3bf91Theodore Ts'o
707cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	if (ns->cluster_per_mft_record < 0)
70830dd2622353b9fde462c9112fb0c863620a3bf91Theodore Ts'o		mft_record_size = 1 << (0-ns->cluster_per_mft_record);
709cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	else
710efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		mft_record_size = ns->cluster_per_mft_record *
711cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o			sectors_per_cluster * bytes_per_sector;
712cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	nr_clusters = blkid_le64(ns->number_of_sectors) / sectors_per_cluster;
713cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
714cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	if ((blkid_le64(ns->mft_cluster_location) > nr_clusters) ||
715cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	    (blkid_le64(ns->mft_mirror_cluster_location) > nr_clusters))
716cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		return 1;
717cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
718efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	off = blkid_le64(ns->mft_mirror_cluster_location) *
719cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		bytes_per_sector * sectors_per_cluster;
720cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
721cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	buf_mft = get_buffer(probe, off, mft_record_size);
722cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	if (!buf_mft)
723cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		return 1;
724cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
725cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	if (memcmp(buf_mft, "FILE", 4))
726cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		return 1;
727cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
728efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	off = blkid_le64(ns->mft_cluster_location) * bytes_per_sector *
729cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		sectors_per_cluster;
730cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
731cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	buf_mft = get_buffer(probe, off, mft_record_size);
732cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	if (!buf_mft)
733cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		return 1;
734cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
735cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	if (memcmp(buf_mft, "FILE", 4))
736cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		return 1;
737cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
738cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	off += MFT_RECORD_VOLUME * mft_record_size;
739cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
740cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	buf_mft = get_buffer(probe, off, mft_record_size);
741cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	if (!buf_mft)
742cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		return 1;
743cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
744cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	if (memcmp(buf_mft, "FILE", 4))
745cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		return 1;
746cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
747cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	mft = (struct master_file_table_record *) buf_mft;
748cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
749cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	attr_off = blkid_le16(mft->attrs_offset);
750cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	label_str[0] = 0;
751efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
752cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	while (1) {
753cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		attr = (struct file_attribute *) (buf_mft + attr_off);
754cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		attr_len = blkid_le16(attr->len);
755cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		attr_type = blkid_le32(attr->type);
756cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		val_off = blkid_le16(attr->value_offset);
757cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		val_len = blkid_le32(attr->value_len);
758cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
759cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		attr_off += attr_len;
760cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
761cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		if ((attr_off > mft_record_size) ||
762cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		    (attr_len == 0))
763cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o			break;
764cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
765cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		if (attr_type == MFT_RECORD_ATTR_END)
766cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o			break;
767cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
768cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) {
769cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o			if (val_len > sizeof(label_str))
770cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o				val_len = sizeof(label_str)-1;
771cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
772cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o			for (i=0, cp=label_str; i < val_len; i+=2,cp++) {
773cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o				val = ((__u8 *) attr) + val_off + i;
774cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o				*cp = val[0];
775cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o				if (val[1])
776cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o					*cp = '?';
777cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o			}
778cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o			*cp = 0;
779cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		}
780cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	}
781cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
782c40ad3674c9d2f0709cbe8f2f607633f25c4bb4bPixel	sprintf(uuid_str, "%016llX", blkid_le64(ns->volume_serial));
783cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	blkid_set_tag(probe->dev, "UUID", uuid_str, 0);
784cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	if (label_str[0])
785cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o		blkid_set_tag(probe->dev, "LABEL", label_str, 0);
786cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o	return 0;
787cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o}
788cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
789cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o
790ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_xfs(struct blkid_probe *probe,
791efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		     struct blkid_magic *id __BLKID_ATTR((unused)),
792544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o		     unsigned char *buf)
793e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o{
794e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	struct xfs_super_block *xs;
795a30b9446d1899260159968826428722f2dcbbc64Theodore Ts'o	const char *label = 0;
796e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
797e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	xs = (struct xfs_super_block *)buf;
798e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
799e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	if (strlen(xs->xs_fname))
800a30b9446d1899260159968826428722f2dcbbc64Theodore Ts'o		label = xs->xs_fname;
801ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", label, sizeof(xs->xs_fname));
802ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o	set_uuid(probe->dev, xs->xs_uuid, 0);
803e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	return 0;
804e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o}
805e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
806ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_reiserfs(struct blkid_probe *probe,
80779dd234a799434b6dc8365c49e743f00eb09d2fdTheodore Ts'o			  struct blkid_magic *id, unsigned char *buf)
808e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o{
80950b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	struct reiserfs_super_block *rs = (struct reiserfs_super_block *) buf;
810e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	unsigned int blocksize;
811a30b9446d1899260159968826428722f2dcbbc64Theodore Ts'o	const char *label = 0;
812e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
81376b07bb1bc9cbcb70a94cb235954eaac993920adTheodore Ts'o	blocksize = blkid_le16(rs->rs_blocksize);
814e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
8154dc30dac2c2732e25765984263a3ecafd8c66932Theodore Ts'o	/* The blocksize must be at least 1k */
8164dc30dac2c2732e25765984263a3ecafd8c66932Theodore Ts'o	if ((blocksize >> 10) == 0)
8174dc30dac2c2732e25765984263a3ecafd8c66932Theodore Ts'o		return -BLKID_ERR_PARAM;
8184dc30dac2c2732e25765984263a3ecafd8c66932Theodore Ts'o
819e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	/* If the superblock is inside the journal, we have the wrong one */
82050b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block))
821e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		return -BLKID_ERR_BIG;
822e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
823e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	/* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */
824ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	if (id->bim_magic[6] == '2' || id->bim_magic[6] == '3') {
825a30b9446d1899260159968826428722f2dcbbc64Theodore Ts'o		if (strlen(rs->rs_label))
826a30b9446d1899260159968826428722f2dcbbc64Theodore Ts'o			label = rs->rs_label;
827ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o		set_uuid(probe->dev, rs->rs_uuid, 0);
828e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	}
829ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", label, sizeof(rs->rs_label));
830e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
831e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	return 0;
832e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o}
833e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
834ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_reiserfs4(struct blkid_probe *probe,
835efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			   struct blkid_magic *id __BLKID_ATTR((unused)),
836ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			   unsigned char *buf)
837bb626bcd546a039b39b9f25e65881b36b2abe24fTheodore Ts'o{
838bb626bcd546a039b39b9f25e65881b36b2abe24fTheodore Ts'o	struct reiser4_super_block *rs4 = (struct reiser4_super_block *) buf;
839ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	const unsigned char *label = 0;
840bb626bcd546a039b39b9f25e65881b36b2abe24fTheodore Ts'o
841ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	if (strlen((char *) rs4->rs4_label))
842bb626bcd546a039b39b9f25e65881b36b2abe24fTheodore Ts'o		label = rs4->rs4_label;
843ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o	set_uuid(probe->dev, rs4->rs4_uuid, 0);
844efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", (const char *) label,
845ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		      sizeof(rs4->rs4_label));
846bb626bcd546a039b39b9f25e65881b36b2abe24fTheodore Ts'o
847bb626bcd546a039b39b9f25e65881b36b2abe24fTheodore Ts'o	return 0;
848bb626bcd546a039b39b9f25e65881b36b2abe24fTheodore Ts'o}
849bb626bcd546a039b39b9f25e65881b36b2abe24fTheodore Ts'o
850ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_jfs(struct blkid_probe *probe,
851efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		     struct blkid_magic *id __BLKID_ATTR((unused)),
852544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o		     unsigned char *buf)
85309a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o{
85409a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o	struct jfs_super_block *js;
855a30b9446d1899260159968826428722f2dcbbc64Theodore Ts'o	const char *label = 0;
85609a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o
85709a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o	js = (struct jfs_super_block *)buf;
85809a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o
859478360f50b68356849813f97db46fd156da5248eTheodore Ts'o	if (blkid_le32(js->js_bsize) != (1U << blkid_le16(js->js_l2bsize)))
860b41fb002257d4b997560cd77676b78219be03c24Theodore Ts'o		return 1;
861b41fb002257d4b997560cd77676b78219be03c24Theodore Ts'o
862478360f50b68356849813f97db46fd156da5248eTheodore Ts'o	if (blkid_le32(js->js_pbsize) != (1U << blkid_le16(js->js_l2pbsize)))
863b41fb002257d4b997560cd77676b78219be03c24Theodore Ts'o		return 1;
864b41fb002257d4b997560cd77676b78219be03c24Theodore Ts'o
865b41fb002257d4b997560cd77676b78219be03c24Theodore Ts'o	if ((blkid_le16(js->js_l2bsize) - blkid_le16(js->js_l2pbsize)) !=
866b41fb002257d4b997560cd77676b78219be03c24Theodore Ts'o	    blkid_le16(js->js_l2bfactor))
867b41fb002257d4b997560cd77676b78219be03c24Theodore Ts'o		return 1;
868b41fb002257d4b997560cd77676b78219be03c24Theodore Ts'o
86948e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o	if (strlen((char *) js->js_label))
870a30b9446d1899260159968826428722f2dcbbc64Theodore Ts'o		label = (char *) js->js_label;
871ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", label, sizeof(js->js_label));
872ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o	set_uuid(probe->dev, js->js_uuid, 0);
87309a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o	return 0;
87409a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o}
87509a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o
87625f291c9b32d8017e6969c72a75e37d354c0570bTheodore Ts'ostatic int probe_zfs(struct blkid_probe *probe __BLKID_ATTR((unused)),
87725f291c9b32d8017e6969c72a75e37d354c0570bTheodore Ts'o		     struct blkid_magic *id __BLKID_ATTR((unused)),
87825f291c9b32d8017e6969c72a75e37d354c0570bTheodore Ts'o		     unsigned char *buf __BLKID_ATTR((unused)))
879c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia{
88079e62409b3a247e258d9e9206484ed8f193a183eEric Sandeen#if 0
881c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia	char *vdev_label;
882c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia	const char *pool_name = 0;
883c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia
884c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia	/* read nvpair data for pool name, pool GUID (complex) */
885c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia	blkid_set_tag(probe->dev, "LABEL", pool_name, sizeof(pool_name));
886c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia	set_uuid(probe->dev, pool_guid, 0);
887c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia#endif
888c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia	return 0;
889c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia}
890c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia
891e382a7eaded3ec6b38114988ae9b0723bb48002aKarsten Hoppstatic int probe_luks(struct blkid_probe *probe,
892e382a7eaded3ec6b38114988ae9b0723bb48002aKarsten Hopp		       struct blkid_magic *id __BLKID_ATTR((unused)),
893e382a7eaded3ec6b38114988ae9b0723bb48002aKarsten Hopp		       unsigned char *buf)
894e382a7eaded3ec6b38114988ae9b0723bb48002aKarsten Hopp{
895d4e0b1c6f5aa8c6a248d9149ed5634a310952411Theodore Ts'o	char uuid[40];
896d4e0b1c6f5aa8c6a248d9149ed5634a310952411Theodore Ts'o
897e382a7eaded3ec6b38114988ae9b0723bb48002aKarsten Hopp	/* 168 is the offset to the 40 character uuid:
898e382a7eaded3ec6b38114988ae9b0723bb48002aKarsten Hopp	 * http://luks.endorphin.org/LUKS-on-disk-format.pdf */
899d4e0b1c6f5aa8c6a248d9149ed5634a310952411Theodore Ts'o	strncpy(uuid, (char *) buf+168, 40);
900e382a7eaded3ec6b38114988ae9b0723bb48002aKarsten Hopp	blkid_set_tag(probe->dev, "UUID", uuid, sizeof(uuid));
901e382a7eaded3ec6b38114988ae9b0723bb48002aKarsten Hopp	return 0;
902e382a7eaded3ec6b38114988ae9b0723bb48002aKarsten Hopp}
903e382a7eaded3ec6b38114988ae9b0723bb48002aKarsten Hopp
904ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_romfs(struct blkid_probe *probe,
905efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		       struct blkid_magic *id __BLKID_ATTR((unused)),
906544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o		       unsigned char *buf)
90709a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o{
90809a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o	struct romfs_super_block *ros;
909a30b9446d1899260159968826428722f2dcbbc64Theodore Ts'o	const char *label = 0;
91009a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o
91109a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o	ros = (struct romfs_super_block *)buf;
91209a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o
913a30b9446d1899260159968826428722f2dcbbc64Theodore Ts'o	if (strlen((char *) ros->ros_volume))
914a30b9446d1899260159968826428722f2dcbbc64Theodore Ts'o		label = (char *) ros->ros_volume;
915ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", label, 0);
9167369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	return 0;
9177369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o}
9187369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o
919ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_cramfs(struct blkid_probe *probe,
920efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			struct blkid_magic *id __BLKID_ATTR((unused)),
921ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			unsigned char *buf)
9224c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o{
9234c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o	struct cramfs_super_block *csb;
9244c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o	const char *label = 0;
9254c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o
9264c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o	csb = (struct cramfs_super_block *)buf;
9274c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o
9284c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o	if (strlen((char *) csb->name))
9294c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o		label = (char *) csb->name;
930ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", label, 0);
9314c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o	return 0;
9324c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o}
9334c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o
934ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_swap0(struct blkid_probe *probe,
9357369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o		       struct blkid_magic *id __BLKID_ATTR((unused)),
9367369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o		       unsigned char *buf __BLKID_ATTR((unused)))
9377369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o{
938ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "UUID", 0, 0);
939ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", 0, 0);
9407369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	return 0;
9417369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o}
9427369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o
943ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_swap1(struct blkid_probe *probe,
9446360d129d003f25942f62fab2cdc5e1d97cc88a6Eric Sandeen		       struct blkid_magic *id,
9457369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o		       unsigned char *buf __BLKID_ATTR((unused)))
9467369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o{
9477369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	struct swap_id_block *sws;
9487369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o
949ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	probe_swap0(probe, id, buf);
9507369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	/*
9517369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	 * Version 1 swap headers are always located at offset of 1024
9527369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	 * bytes, although the swap signature itself is located at the
9537369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	 * end of the page (which may vary depending on hardware
9547369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	 * pagesize).
9557369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	 */
956ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	sws = (struct swap_id_block *) get_buffer(probe, 1024, 1024);
957ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	if (!sws)
9587369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o		return 1;
9597369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o
9606360d129d003f25942f62fab2cdc5e1d97cc88a6Eric Sandeen	/* check for wrong version or zeroed pagecount, for sanity */
9616360d129d003f25942f62fab2cdc5e1d97cc88a6Eric Sandeen	if (!memcmp(id->bim_magic, "SWAPSPACE2", id->bim_len) &&
96222269b8b60da320b3c27ea8d053f9e2b0fbe2ae2Eric Sandeen			(sws->sws_version != 1 || sws->sws_lastpage == 0))
9636360d129d003f25942f62fab2cdc5e1d97cc88a6Eric Sandeen		return 1;
9646360d129d003f25942f62fab2cdc5e1d97cc88a6Eric Sandeen
9657369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	/* arbitrary sanity check.. is there any garbage down there? */
9667369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	if (sws->sws_pad[32] == 0 && sws->sws_pad[33] == 0)  {
9677369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o		if (sws->sws_volume[0])
968efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			blkid_set_tag(probe->dev, "LABEL", sws->sws_volume,
9697369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o				      sizeof(sws->sws_volume));
9707369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o		if (sws->sws_uuid[0])
971ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o			set_uuid(probe->dev, sws->sws_uuid, 0);
9727369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o	}
97309a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o	return 0;
97409a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o}
97509a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o
976ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_iso9660(struct blkid_probe *probe,
977efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			 struct blkid_magic *id __BLKID_ATTR((unused)),
97845a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o			 unsigned char *buf)
97945a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o{
98045a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o	struct iso_volume_descriptor *iso;
98145a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o	const unsigned char *label;
98245a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o
98345a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o	iso = (struct iso_volume_descriptor *) buf;
98445a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o	label = iso->volume_id;
98545a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o
986efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", (const char *) label,
987ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		      figure_label_len(label, 32));
98845a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o	return 0;
98945a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o}
99045a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o
99145a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o
992544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'ostatic const char
9933de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o*udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
9943de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o		 "NSR03", "TEA01", 0 };
9953de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o
996ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_udf(struct blkid_probe *probe,
997efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		     struct blkid_magic *id __BLKID_ATTR((unused)),
998544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o		     unsigned char *buf __BLKID_ATTR((unused)))
9993de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o{
10003de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o	int j, bs;
1001ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	struct iso_volume_descriptor *isosb;
1002544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	const char ** m;
10033de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o
10043de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o	/* determine the block size by scanning in 2K increments
10053de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o	   (block sizes larger than 2K will be null padded) */
10063de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o	for (bs = 1; bs < 16; bs++) {
1007efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		isosb = (struct iso_volume_descriptor *)
1008d1da14b5b0496621046179e5644cc924ce01dae1Theodore Ts'o			get_buffer(probe, (blkid_loff_t) bs*2048+32768,
1009d1da14b5b0496621046179e5644cc924ce01dae1Theodore Ts'o				   sizeof(*isosb));
1010ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		if (!isosb)
10113de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o			return 1;
1012ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		if (isosb->vd_id[0])
10133de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o			break;
10143de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o	}
10153de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o
10163de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o	/* Scan up to another 64 blocks looking for additional VSD's */
10173de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o	for (j = 1; j < 64; j++) {
10183de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o		if (j > 1) {
1019efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			isosb = (struct iso_volume_descriptor *)
1020efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o				get_buffer(probe, j*bs*2048+32768,
102175954ccf2a4fb2a5da632e7988450afee5e02509Theodore Ts'o					   sizeof(*isosb));
1022ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o			if (!isosb)
10233de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o				return 1;
10243de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o		}
10253de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o		/* If we find NSR0x then call it udf:
10263de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o		   NSR01 for UDF 1.00
10273de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o		   NSR02 for UDF 1.50
10283de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o		   NSR03 for UDF 2.00 */
102949487b79da9ccc4a5f9d4e8f08c10ec9c8185a90Theodore Ts'o		if (!memcmp(isosb->vd_id, "NSR0", 4))
1030a4045c21a30ddf36528b0b1fc0cc6e4fffb33ce6Theodore Ts'o			return probe_iso9660(probe, id, buf);
10313de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o		for (m = udf_magic; *m; m++)
103249487b79da9ccc4a5f9d4e8f08c10ec9c8185a90Theodore Ts'o			if (!memcmp(*m, isosb->vd_id, 5))
10333de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o				break;
10343de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o		if (*m == 0)
10353de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o			return 1;
10363de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o	}
10373de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o	return 1;
10383de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o}
10393de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o
1040ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_ocfs(struct blkid_probe *probe,
1041efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		      struct blkid_magic *id __BLKID_ATTR((unused)),
10429387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o		      unsigned char *buf)
10439387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o{
10449387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o	struct ocfs_volume_header ovh;
10459387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o	struct ocfs_volume_label ovl;
10463838f7df134035089e8e8df317112e4fd645602dTheodore Ts'o	__u32 major;
10479387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o
10489387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o	memcpy(&ovh, buf, sizeof(ovh));
10499387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o	memcpy(&ovl, buf+512, sizeof(ovl));
10509387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o
10519387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o	major = ocfsmajor(ovh);
10529387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o	if (major == 1)
1053ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		blkid_set_tag(probe->dev,"SEC_TYPE","ocfs1",sizeof("ocfs1"));
10549387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o	else if (major >= 9)
1055ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		blkid_set_tag(probe->dev,"SEC_TYPE","ntocfs",sizeof("ntocfs"));
1056efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1057ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", ovl.label, ocfslabellen(ovl));
1058ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "MOUNT", ovh.mount, ocfsmountlen(ovh));
1059ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o	set_uuid(probe->dev, ovl.vol_id, 0);
10609387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o	return 0;
10619387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o}
10629387c281ef88cd1fba7cb1c9336b5ab00a2d82b4Theodore Ts'o
1063ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_ocfs2(struct blkid_probe *probe,
1064efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		       struct blkid_magic *id __BLKID_ATTR((unused)),
10652c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o		       unsigned char *buf)
1066414846b126d4d751bd6b36df0a39dcb030e0feb3Theodore Ts'o{
1067414846b126d4d751bd6b36df0a39dcb030e0feb3Theodore Ts'o	struct ocfs2_super_block *osb;
1068414846b126d4d751bd6b36df0a39dcb030e0feb3Theodore Ts'o
1069414846b126d4d751bd6b36df0a39dcb030e0feb3Theodore Ts'o	osb = (struct ocfs2_super_block *)buf;
1070414846b126d4d751bd6b36df0a39dcb030e0feb3Theodore Ts'o
1071ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", osb->s_label, sizeof(osb->s_label));
1072ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o	set_uuid(probe->dev, osb->s_uuid, 0);
1073414846b126d4d751bd6b36df0a39dcb030e0feb3Theodore Ts'o	return 0;
1074414846b126d4d751bd6b36df0a39dcb030e0feb3Theodore Ts'o}
1075414846b126d4d751bd6b36df0a39dcb030e0feb3Theodore Ts'o
1076ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'ostatic int probe_oracleasm(struct blkid_probe *probe,
1077efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			   struct blkid_magic *id __BLKID_ATTR((unused)),
10782c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o			   unsigned char *buf)
10792c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o{
10802c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o	struct oracle_asm_disk_label *dl;
10812c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o
10822c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o	dl = (struct oracle_asm_disk_label *)buf;
10832c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o
1084ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", dl->dl_id, sizeof(dl->dl_id));
10852c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o	return 0;
10862c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o}
10872c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o
1088b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zakstatic int probe_gfs(struct blkid_probe *probe,
1089b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		     struct blkid_magic *id __BLKID_ATTR((unused)),
1090b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		     unsigned char *buf)
1091b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak{
1092b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	struct gfs2_sb *sbd;
1093b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	const char *label = 0;
1094b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak
1095b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	sbd = (struct gfs2_sb *)buf;
1096b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak
1097b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	if (blkid_be32(sbd->sb_fs_format) == GFS_FORMAT_FS &&
1098b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	    blkid_be32(sbd->sb_multihost_format) == GFS_FORMAT_MULTI)
1099efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	{
1100b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		blkid_set_tag(probe->dev, "UUID", 0, 0);
1101efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1102b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		if (strlen(sbd->sb_locktable))
1103b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak			label = sbd->sb_locktable;
1104b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		blkid_set_tag(probe->dev, "LABEL", label, sizeof(sbd->sb_locktable));
1105b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		return 0;
1106b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	}
1107b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	return 1;
1108b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak}
1109b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak
1110b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zakstatic int probe_gfs2(struct blkid_probe *probe,
1111b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		     struct blkid_magic *id __BLKID_ATTR((unused)),
1112b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		     unsigned char *buf)
1113b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak{
1114b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	struct gfs2_sb *sbd;
1115b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	const char *label = 0;
1116b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak
1117b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	sbd = (struct gfs2_sb *)buf;
1118b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak
1119b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	if (blkid_be32(sbd->sb_fs_format) == GFS2_FORMAT_FS &&
1120b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	    blkid_be32(sbd->sb_multihost_format) == GFS2_FORMAT_MULTI)
1121efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	{
1122b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		blkid_set_tag(probe->dev, "UUID", 0, 0);
1123efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1124b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		if (strlen(sbd->sb_locktable))
1125b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak			label = sbd->sb_locktable;
1126b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		blkid_set_tag(probe->dev, "LABEL", label, sizeof(sbd->sb_locktable));
1127b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak		return 0;
1128b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	}
1129b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak	return 1;
1130b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak}
1131b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak
1132efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ostatic void unicode_16be_to_utf8(unsigned char *str, int out_len,
1133d56ccbd8f97e90d34a2b18a45fbd6681d3dba726Theodore Ts'o				 const unsigned char *buf, int in_len)
11349c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o{
11359c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	int i, j;
11369c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int c;
11379c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
11389c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	for (i = j = 0; i + 2 <= in_len; i += 2) {
11399c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		c = (buf[i] << 8) | buf[i+1];
11409c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		if (c == 0) {
11419c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			str[j] = '\0';
11429c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			break;
11439c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		} else if (c < 0x80) {
11449c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			if (j+1 >= out_len)
11459c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o				break;
11469c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			str[j++] = (unsigned char) c;
11479c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		} else if (c < 0x800) {
11489c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			if (j+2 >= out_len)
11499c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o				break;
11509c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			str[j++] = (unsigned char) (0xc0 | (c >> 6));
11519c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			str[j++] = (unsigned char) (0x80 | (c & 0x3f));
11529c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		} else {
11539c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			if (j+3 >= out_len)
11549c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o				break;
11559c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			str[j++] = (unsigned char) (0xe0 | (c >> 12));
11569c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			str[j++] = (unsigned char) (0x80 | ((c >> 6) & 0x3f));
11579c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			str[j++] = (unsigned char) (0x80 | (c & 0x3f));
11589c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		}
11599c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	}
11609c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	str[j] = '\0';
11619c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o}
11629c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
11639c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'ostatic int probe_hfs(struct blkid_probe *probe __BLKID_ATTR((unused)),
116469d742284d083c8f6ce7d9240019e21f2fbd9ed5Theodore Ts'o			 struct blkid_magic *id __BLKID_ATTR((unused)),
116569d742284d083c8f6ce7d9240019e21f2fbd9ed5Theodore Ts'o			 unsigned char *buf)
116669d742284d083c8f6ce7d9240019e21f2fbd9ed5Theodore Ts'o{
116700eb0eee0addfd3b7ede98b85e00dff1547838a0Andreas Dilger	struct hfs_mdb *hfs = (struct hfs_mdb *)buf;
116800eb0eee0addfd3b7ede98b85e00dff1547838a0Andreas Dilger	unsigned long long *uuid_ptr;
11699c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	char	uuid_str[17];
11709c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	__u64	uuid;
11719c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
11729c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if ((memcmp(hfs->embed_sig, "H+", 2) == 0) ||
11739c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	    (memcmp(hfs->embed_sig, "HX", 2) == 0))
11749c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		return 1;	/* Not hfs, but an embedded HFS+ */
11759c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
117600eb0eee0addfd3b7ede98b85e00dff1547838a0Andreas Dilger	uuid_ptr = (unsigned long long *)hfs->finder_info.id;
117700eb0eee0addfd3b7ede98b85e00dff1547838a0Andreas Dilger	uuid = blkid_le64(*uuid_ptr);
11789c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if (uuid) {
11799c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		sprintf(uuid_str, "%016llX", uuid);
11809c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		blkid_set_tag(probe->dev, "UUID", uuid_str, 0);
11819c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	}
1182cf5301d7f2c3bbed3d26600335102414cbf0c4baAndreas Dilger	blkid_set_tag(probe->dev, "LABEL", (char *)hfs->label, hfs->label_len);
11839c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	return 0;
11849c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o}
11859c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
11869c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
11879c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'ostatic int probe_hfsplus(struct blkid_probe *probe,
11889c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			 struct blkid_magic *id,
11899c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			 unsigned char *buf)
11909c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o{
11919c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
11929c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	struct hfsplus_bnode_descriptor *descr;
11939c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	struct hfsplus_bheader_record *bnode;
11949c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	struct hfsplus_catalog_key *key;
11959c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	struct hfsplus_vol_header *hfsplus;
11969c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	struct hfs_mdb *sbd = (struct hfs_mdb *) buf;
11979c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int alloc_block_size;
11989c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int alloc_first_block;
11999c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int embed_first_block;
12009c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int off = 0;
12019c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int blocksize;
12029c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int cat_block;
12039c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int ext_block_start;
12049c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int ext_block_count;
12059c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int record_count;
12069c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int leaf_node_head;
12079c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int leaf_node_count;
12089c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int leaf_node_size;
12099c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int leaf_block;
12109c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	unsigned int label_len;
121100eb0eee0addfd3b7ede98b85e00dff1547838a0Andreas Dilger	unsigned long long *uuid_ptr;
12129c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	__u64 leaf_off, uuid;
12139c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	char	uuid_str[17], label[512];
121400eb0eee0addfd3b7ede98b85e00dff1547838a0Andreas Dilger	int ext;
121569d742284d083c8f6ce7d9240019e21f2fbd9ed5Theodore Ts'o
121669d742284d083c8f6ce7d9240019e21f2fbd9ed5Theodore Ts'o	/* Check for a HFS+ volume embedded in a HFS volume */
12179c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if (memcmp(sbd->signature, "BD", 2) == 0) {
12189c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		if ((memcmp(sbd->embed_sig, "H+", 2) != 0) &&
12199c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		    (memcmp(sbd->embed_sig, "HX", 2) != 0))
12209c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			/* This must be an HFS volume, so fail */
12219c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			return 1;
1222efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
12239c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		alloc_block_size = blkid_be32(sbd->al_blk_size);
12249c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		alloc_first_block = blkid_be16(sbd->al_bl_st);
12259c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		embed_first_block = blkid_be16(sbd->embed_startblock);
12269c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		off = (alloc_first_block * 512) +
12279c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			(embed_first_block * alloc_block_size);
12289c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		buf = get_buffer(probe, off + (id->bim_kboff * 1024),
122975954ccf2a4fb2a5da632e7988450afee5e02509Theodore Ts'o				 sizeof(*sbd));
12309c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		if (!buf)
12319c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			return 1;
12329c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12339c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		hfsplus = (struct hfsplus_vol_header *) buf;
12349c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	}
12359c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12369c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	hfsplus = (struct hfsplus_vol_header *) buf;
12379c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12389c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if ((memcmp(hfsplus->signature, "H+", 2) != 0) &&
12399c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	    (memcmp(hfsplus->signature, "HX", 2) != 0))
12409c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		return 1;
12419c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
124200eb0eee0addfd3b7ede98b85e00dff1547838a0Andreas Dilger	uuid_ptr = (unsigned long long *)hfsplus->finder_info.id;
124300eb0eee0addfd3b7ede98b85e00dff1547838a0Andreas Dilger	uuid = blkid_le64(*uuid_ptr);
12449c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if (uuid) {
12459c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		sprintf(uuid_str, "%016llX", uuid);
12469c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		blkid_set_tag(probe->dev, "UUID", uuid_str, 0);
12479c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	}
12489c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12499c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	blocksize = blkid_be32(hfsplus->blocksize);
12509c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	memcpy(extents, hfsplus->cat_file.extents, sizeof(extents));
12519c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	cat_block = blkid_be32(extents[0].start_block);
12529c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
1253d1da14b5b0496621046179e5644cc924ce01dae1Theodore Ts'o	buf = get_buffer(probe, off + ((__u64) cat_block * blocksize), 0x2000);
12549c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if (!buf)
125569d742284d083c8f6ce7d9240019e21f2fbd9ed5Theodore Ts'o		return 0;
125669d742284d083c8f6ce7d9240019e21f2fbd9ed5Theodore Ts'o
12579c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	bnode = (struct hfsplus_bheader_record *)
12589c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		&buf[sizeof(struct hfsplus_bnode_descriptor)];
12599c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12609c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	leaf_node_head = blkid_be32(bnode->leaf_head);
12619c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	leaf_node_size = blkid_be16(bnode->node_size);
12629c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	leaf_node_count = blkid_be32(bnode->leaf_count);
12639c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if (leaf_node_count == 0)
12649c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		return 0;
12659c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12669c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	leaf_block = (leaf_node_head * leaf_node_size) / blocksize;
12679c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12689c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	/* get physical location */
12699c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) {
12709c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		ext_block_start = blkid_be32(extents[ext].start_block);
12719c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		ext_block_count = blkid_be32(extents[ext].block_count);
12729c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		if (ext_block_count == 0)
12739c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			return 0;
12749c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12759c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		/* this is our extent */
12769c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		if (leaf_block < ext_block_count)
12779c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o			break;
12789c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12799c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		leaf_block -= ext_block_count;
12809c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	}
12819c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if (ext == HFSPLUS_EXTENT_COUNT)
12829c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		return 0;
12839c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
1284d1da14b5b0496621046179e5644cc924ce01dae1Theodore Ts'o	leaf_off = (__u64) (ext_block_start + leaf_block) * blocksize;
12859c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12869c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	buf = get_buffer(probe, off + leaf_off, leaf_node_size);
12879c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if (!buf)
12889c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		return 0;
12899c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12909c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	descr = (struct hfsplus_bnode_descriptor *) buf;
12919c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	record_count = blkid_be16(descr->num_recs);
12929c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if (record_count == 0)
12939c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		return 0;
12949c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12959c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if (descr->type != HFS_NODE_LEAF)
12969c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		return 0;
12979c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
12989c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	key = (struct hfsplus_catalog_key *)
12999c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		&buf[sizeof(struct hfsplus_bnode_descriptor)];
13009c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
13019c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	if (blkid_be32(key->parent_id) != HFSPLUS_POR_CNID)
13029c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o		return 0;
13039c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o
13049c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	label_len = blkid_be16(key->unicode_len) * 2;
1305cf5301d7f2c3bbed3d26600335102414cbf0c4baAndreas Dilger	unicode_16be_to_utf8((unsigned char *)label, sizeof(label),
1306cf5301d7f2c3bbed3d26600335102414cbf0c4baAndreas Dilger			     key->unicode, label_len);
13079c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	blkid_set_tag(probe->dev, "LABEL", label, 0);
13089c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o	return 0;
130969d742284d083c8f6ce7d9240019e21f2fbd9ed5Theodore Ts'o}
131069d742284d083c8f6ce7d9240019e21f2fbd9ed5Theodore Ts'o
1311a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen#define LVM2_LABEL_SIZE 512
1312dd232049d19112d46d4b296c1b253ef05e9dc67cTheodore Ts'ostatic unsigned int lvm2_calc_crc(const void *buf, unsigned int size)
1313a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen{
1314dd232049d19112d46d4b296c1b253ef05e9dc67cTheodore Ts'o	static const unsigned int crctab[] = {
1315a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
1316a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
1317a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
1318a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
1319a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	};
1320dd232049d19112d46d4b296c1b253ef05e9dc67cTheodore Ts'o	unsigned int i, crc = 0xf597a6cf;
1321a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	const __u8 *data = (const __u8 *) buf;
1322a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen
1323a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	for (i = 0; i < size; i++) {
1324a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		crc ^= *data++;
1325a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		crc = (crc >> 4) ^ crctab[crc & 0xf];
1326a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		crc = (crc >> 4) ^ crctab[crc & 0xf];
1327a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	}
1328a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	return crc;
1329a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen}
1330a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen
1331a451d92f38188f7218a837a395b310354864b5a4Eric Sandeenstatic int probe_lvm2(struct blkid_probe *probe,
1332cc19b958602775ef48f347d16859ce6623a385daTheodore Ts'o			struct blkid_magic *id,
1333a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen			unsigned char *buf)
1334a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen{
13358d45e2104cdebcd509810786756cfb2e40588620Theodore Ts'o	int sector = (id->bim_kboff) << 1;
1336cc19b958602775ef48f347d16859ce6623a385daTheodore Ts'o	struct lvm2_pv_label_header *label= (struct lvm2_pv_label_header *)buf;
1337a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	char *p, *q, uuid[40];
1338a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	unsigned int i, b;
1339a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen
1340a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	/* buf is at 0k or 1k offset; find label inside */
1341a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	if (memcmp(buf, "LABELONE", 8) == 0) {
1342a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		label = (struct lvm2_pv_label_header *)buf;
1343a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	} else if (memcmp(buf + 512, "LABELONE", 8) == 0) {
1344a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		label = (struct lvm2_pv_label_header *)(buf + 512);
1345a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		sector++;
1346a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	} else {
1347a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		return 1;
1348a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	}
1349a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen
13503a538e42441afa5e5b34942062acb976e0d345f6Theodore Ts'o	if (blkid_le64(label->sector_xl) != (unsigned) sector) {
1351a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		DBG(DEBUG_PROBE,
13523a538e42441afa5e5b34942062acb976e0d345f6Theodore Ts'o		    printf("LVM2: label for sector %llu found at sector %d\n",
1353a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen			   blkid_le64(label->sector_xl), sector));
1354a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		return 1;
1355a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	}
1356a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen
1357a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	if (lvm2_calc_crc(&label->offset_xl, LVM2_LABEL_SIZE -
13583a538e42441afa5e5b34942062acb976e0d345f6Theodore Ts'o			  ((char *)&label->offset_xl - (char *)label)) !=
1359a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen			blkid_le32(label->crc_xl)) {
1360a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		DBG(DEBUG_PROBE,
1361a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		    printf("LVM2: label checksum incorrect at sector %d\n",
1362a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen			   sector));
1363a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		return 1;
1364a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	}
1365a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen
13665d5576d8bbf196835ec89f53dc919738f49e23abTheodore Ts'o	for (i=0, b=1, p=uuid, q= (char *) label->pv_uuid; i < LVM2_ID_LEN;
13673a538e42441afa5e5b34942062acb976e0d345f6Theodore Ts'o	     i++, b <<= 1) {
1368a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		if (b & 0x4444440)
1369a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen			*p++ = '-';
1370a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen		*p++ = *q++;
1371a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	}
1372a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen
1373a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	blkid_set_tag(probe->dev, "UUID", uuid, LVM2_ID_LEN+6);
1374a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen
1375a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen	return 0;
1376a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen}
1377801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen
1378801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeenstatic int probe_btrfs(struct blkid_probe *probe,
137925f291c9b32d8017e6969c72a75e37d354c0570bTheodore Ts'o			struct blkid_magic *id __BLKID_ATTR((unused)),
1380801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen			unsigned char *buf)
1381801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen{
1382801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen	struct btrfs_super_block *bs;
1383801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen	const char *label = 0;
1384801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen
1385801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen	bs = (struct btrfs_super_block *)buf;
1386801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen
1387801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen	if (strlen(bs->label))
1388801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen		label = bs->label;
1389801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen	blkid_set_tag(probe->dev, "LABEL", label, sizeof(bs->label));
1390801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen	set_uuid(probe->dev, bs->fsid, 0);
1391801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen	return 0;
1392801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen}
13937c33c8899faa9b8250d5190ca8417f47daf3ba7bJeff Sharkey
13947c33c8899faa9b8250d5190ca8417f47daf3ba7bJeff Sharkeystatic int probe_f2fs(struct blkid_probe *probe,
1395478360f50b68356849813f97db46fd156da5248eTheodore Ts'o            struct blkid_magic *id __BLKID_ATTR((unused)),
13967c33c8899faa9b8250d5190ca8417f47daf3ba7bJeff Sharkey            unsigned char *buf)
13977c33c8899faa9b8250d5190ca8417f47daf3ba7bJeff Sharkey{
13987c33c8899faa9b8250d5190ca8417f47daf3ba7bJeff Sharkey    struct f2fs_super_block *bs;
13997c33c8899faa9b8250d5190ca8417f47daf3ba7bJeff Sharkey
14007c33c8899faa9b8250d5190ca8417f47daf3ba7bJeff Sharkey    bs = (struct f2fs_super_block *)buf;
14017c33c8899faa9b8250d5190ca8417f47daf3ba7bJeff Sharkey    set_uuid(probe->dev, bs->uuid, 0);
14027c33c8899faa9b8250d5190ca8417f47daf3ba7bJeff Sharkey    return 0;
14037c33c8899faa9b8250d5190ca8417f47daf3ba7bJeff Sharkey}
14047c33c8899faa9b8250d5190ca8417f47daf3ba7bJeff Sharkey
14051206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghaostatic uint64_t exfat_block_to_offset(const struct exfat_super_block *sb,
14061206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao                                      uint64_t block)
14071206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao{
14081206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    return block << sb->block_bits;
14091206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao}
14101206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao
14111206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghaostatic uint64_t exfat_cluster_to_block(const struct exfat_super_block *sb,
14121206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao                                       uint32_t cluster)
14131206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao{
14141206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    return sb->cluster_block_start +
14151206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao            ((uint64_t)(cluster - EXFAT_FIRST_DATA_CLUSTER) << sb->bpc_bits);
14161206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao}
14171206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao
14181206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghaostatic uint64_t exfat_cluster_to_offset(const struct exfat_super_block *sb,
14191206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao                                        uint32_t cluster)
14201206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao{
14211206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    return exfat_block_to_offset(sb, exfat_cluster_to_block(sb, cluster));
14221206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao}
14231206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao
14241206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghaostatic uint32_t exfat_next_cluster(struct blkid_probe *probe,
14251206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao                                   const struct exfat_super_block *sb,
14261206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao                                   uint32_t cluster)
14271206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao{
14281206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    uint32_t *next;
14291206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    uint64_t offset;
14301206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao
14311206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    offset = exfat_block_to_offset(sb, sb->fat_block_start)
14321206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao            + (uint64_t) cluster * sizeof (cluster);
14331206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    next = (uint32_t *)get_buffer(probe, offset, sizeof (uint32_t));
14341206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao
14351206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    return next ? *next : 0;
14361206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao}
14371206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao
14381206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghaostatic struct exfat_entry_label *find_exfat_entry_label(
14391206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    struct blkid_probe *probe, const struct exfat_super_block *sb)
14401206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao{
14411206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    uint32_t cluster = sb->rootdir_cluster;
14421206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    uint64_t offset = exfat_cluster_to_offset(sb, cluster);
14431206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    uint8_t *entry;
14441206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    const size_t max_iter = 10000;
14451206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    size_t i = 0;
14461206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao
14471206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    for (; i < max_iter; ++i) {
14481206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao        entry = (uint8_t *)get_buffer(probe, offset, EXFAT_ENTRY_SIZE);
14491206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao        if (!entry)
14501206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao            return NULL;
14511206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao        if (entry[0] == EXFAT_ENTRY_EOD)
14521206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao            return NULL;
14531206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao        if (entry[0] == EXFAT_ENTRY_LABEL)
14541206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao            return (struct exfat_entry_label*) entry;
14551206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao
14561206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao        offset += EXFAT_ENTRY_SIZE;
14571206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao        if (offset % CLUSTER_SIZE(sb) == 0) {
14581206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao            cluster = exfat_next_cluster(probe, sb, cluster);
14591206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao            if (cluster < EXFAT_FIRST_DATA_CLUSTER)
14601206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao                return NULL;
14611206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao            if (cluster > EXFAT_LAST_DATA_CLUSTER)
14621206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao                return NULL;
14631206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao            offset = exfat_cluster_to_offset(sb, cluster);
14641206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao        }
14651206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    }
14661206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao
14671206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    return NULL;
14681206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao}
14691206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao
14701206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghaostatic int probe_exfat(struct blkid_probe *probe, struct blkid_magic *id,
14711206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao                       unsigned char *buf)
14721206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao{
14731206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    struct exfat_super_block *sb;
14741206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    struct exfat_entry_label *label;
14751206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    uuid_t uuid;
14761206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    sb = (struct exfat_super_block *)buf;
14771206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    if (!sb || !CLUSTER_SIZE(sb)) {
14781206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao        DBG(DEBUG_PROBE, printf("bad exfat superblock.\n"));
14791206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao        return errno ? - errno : 1;
14801206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    }
14811206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao
14821206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    label = find_exfat_entry_label(probe, sb);
14831206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    if (label) {
14841206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao        blkid_set_tag(probe->dev, "LABEL", label->name, label->length);
14851206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    } else {
14861206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao        blkid_set_tag(probe->dev, "LABEL", "disk", 4);
14871206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    }
14881206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao
14891206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    snprintf(uuid, sizeof (uuid), "%02hhX%02hhX-%02hhX%02hhX",
14901206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao             sb->volume_serial[3], sb->volume_serial[2],
14911206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao             sb->volume_serial[1], sb->volume_serial[0]);
14921206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao
14931206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    set_uuid(probe->dev, uuid, 0);
14941206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao
14951206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao    return 0;
14961206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao}
14971206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao
1498e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o/*
1499e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * Various filesystem magics that we can check for.  Note that kboff and
1500e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * sboff are in kilobytes and bytes respectively.  All magics are in
1501e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * byte strings so we don't worry about endian issues.
1502e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o */
150350b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'ostatic struct blkid_magic type_array[] = {
150450b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o/*  type     kboff   sboff len  magic			probe */
15052c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o  { "oracleasm", 0,	32,  8, "ORCLDISK",		probe_oracleasm },
1506cb0c5d701a8852f72fe75c9bd223643fb5222399Theodore Ts'o  { "ntfs",	 0,	 3,  8, "NTFS    ",		probe_ntfs },
150750b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "jbd",	 1,   0x38,  2, "\123\357",		probe_jbd },
15082921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o  { "ext4dev",	 1,   0x38,  2, "\123\357",		probe_ext4dev },
15092921332fd88b843ffb828d9c18f05bfd171ace76Theodore Ts'o  { "ext4",	 1,   0x38,  2, "\123\357",		probe_ext4 },
15102e6a9febb48ea0e57d32cacb5e67220443c0e059Theodore Ts'o  { "ext3",	 1,   0x38,  2, "\123\357",		probe_ext3 },
151150b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "ext2",	 1,   0x38,  2, "\123\357",		probe_ext2 },
151250b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "reiserfs",	 8,   0x34,  8, "ReIsErFs",		probe_reiserfs },
151350b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "reiserfs", 64,   0x34,  9, "ReIsEr2Fs",		probe_reiserfs },
151450b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "reiserfs", 64,   0x34,  9, "ReIsEr3Fs",		probe_reiserfs },
151550b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "reiserfs", 64,   0x34,  8, "ReIsErFs",		probe_reiserfs },
151650b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "reiserfs",	 8,	20,  8, "ReIsErFs",		probe_reiserfs },
1517bb626bcd546a039b39b9f25e65881b36b2abe24fTheodore Ts'o  { "reiser4",  64,	 0,  7, "ReIsEr4",		probe_reiserfs4 },
1518b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak  { "gfs2",     64,      0,  4, "\x01\x16\x19\x70",     probe_gfs2 },
1519b5517ca6678d590b52f38ad701fbaf6c9716b73dKarel Zak  { "gfs",      64,      0,  4, "\x01\x16\x19\x70",     probe_gfs },
1520038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o  { "vfat",      0,   0x52,  5, "MSWIN",                probe_fat },
1521038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o  { "vfat",      0,   0x52,  8, "FAT32   ",             probe_fat },
1522038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o  { "vfat",      0,   0x36,  5, "MSDOS",                probe_fat },
1523038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o  { "vfat",      0,   0x36,  8, "FAT16   ",             probe_fat },
1524038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o  { "vfat",      0,   0x36,  8, "FAT12   ",             probe_fat },
1525846be6db813895c354cc54beaa8fa6aba8d98085Theodore Ts'o  { "vfat",      0,      0,  1, "\353",                 probe_fat_nomagic },
1526038d2bedaad526f91c9e4f55184bcaa59e245e27Theodore Ts'o  { "vfat",      0,      0,  1, "\351",                 probe_fat_nomagic },
1527846be6db813895c354cc54beaa8fa6aba8d98085Theodore Ts'o  { "vfat",      0,  0x1fe,  2, "\125\252",             probe_fat_nomagic },
152850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "minix",     1,   0x10,  2, "\177\023",             0 },
152950b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "minix",     1,   0x10,  2, "\217\023",             0 },
153050b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "minix",	 1,   0x10,  2, "\150\044",		0 },
153150b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "minix",	 1,   0x10,  2, "\170\044",		0 },
153250b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "vxfs",	 1,	 0,  4, "\365\374\001\245",	0 },
153350b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "xfs",	 0,	 0,  4, "XFSB",			probe_xfs },
153409a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o  { "romfs",	 0,	 0,  8, "-rom1fs-",		probe_romfs },
153550b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "bfs",	 0,	 0,  4, "\316\372\173\033",	0 },
15364c4e3f784330978fa127edaa3936957d38c7e93aTheodore Ts'o  { "cramfs",	 0,	 0,  4, "E=\315\050",		probe_cramfs },
153750b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "qnx4",	 0,	 4,  6, "QNX4FS",		0 },
15383de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o  { "udf",	32,	 1,  5, "BEA01",		probe_udf },
15393de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o  { "udf",	32,	 1,  5, "BOOT2",		probe_udf },
15403de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o  { "udf",	32,	 1,  5, "CD001",		probe_udf },
15413de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o  { "udf",	32,	 1,  5, "CDW02",		probe_udf },
15423de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o  { "udf",	32,	 1,  5, "NSR02",		probe_udf },
15433de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o  { "udf",	32,	 1,  5, "NSR03",		probe_udf },
15443de5bf61060634c5c8c3a0d231e8a7246094a2c2Theodore Ts'o  { "udf",	32,	 1,  5, "TEA01",		probe_udf },
154545a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o  { "iso9660",	32,	 1,  5, "CD001",		probe_iso9660 },
154645a3fa873852ce407b5eda0f764c63bab04e4c0cTheodore Ts'o  { "iso9660",	32,	 9,  5, "CDROM",		probe_iso9660 },
154709a2ef8ddab7fed91b9ec8314e0a10e11d3c0323Theodore Ts'o  { "jfs",	32,	 0,  4, "JFS1",			probe_jfs },
1548865dc0d7534ca881dbe1e9fc9fd95792e7f3f0abAndreas Dilger  /* ZFS has 128 root blocks (#4 is the first used), check only 6 of them */
1549865dc0d7534ca881dbe1e9fc9fd95792e7f3f0abAndreas Dilger  { "zfs",     128,	 0,  8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs },
1550865dc0d7534ca881dbe1e9fc9fd95792e7f3f0abAndreas Dilger  { "zfs",     128,	 0,  8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs },
1551865dc0d7534ca881dbe1e9fc9fd95792e7f3f0abAndreas Dilger  { "zfs",     132,	 0,  8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs },
1552865dc0d7534ca881dbe1e9fc9fd95792e7f3f0abAndreas Dilger  { "zfs",     132,	 0,  8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs },
1553865dc0d7534ca881dbe1e9fc9fd95792e7f3f0abAndreas Dilger  { "zfs",     136,	 0,  8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs },
1554865dc0d7534ca881dbe1e9fc9fd95792e7f3f0abAndreas Dilger  { "zfs",     136,	 0,  8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs },
1555865dc0d7534ca881dbe1e9fc9fd95792e7f3f0abAndreas Dilger  { "zfs",     384,	 0,  8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs },
1556865dc0d7534ca881dbe1e9fc9fd95792e7f3f0abAndreas Dilger  { "zfs",     384,	 0,  8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs },
1557865dc0d7534ca881dbe1e9fc9fd95792e7f3f0abAndreas Dilger  { "zfs",     388,	 0,  8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs },
1558865dc0d7534ca881dbe1e9fc9fd95792e7f3f0abAndreas Dilger  { "zfs",     388,	 0,  8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs },
1559865dc0d7534ca881dbe1e9fc9fd95792e7f3f0abAndreas Dilger  { "zfs",     392,	 0,  8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs },
1560865dc0d7534ca881dbe1e9fc9fd95792e7f3f0abAndreas Dilger  { "zfs",     392,	 0,  8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs },
156169d742284d083c8f6ce7d9240019e21f2fbd9ed5Theodore Ts'o  { "hfsplus",	 1,	 0,  2, "BD",			probe_hfsplus },
15629c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o  { "hfsplus",	 1,	 0,  2, "H+",			probe_hfsplus },
15639c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o  { "hfsplus",	 1,	 0,  2, "HX",			probe_hfsplus },
15649c460caae3dab7803c0e7d9399b47e790cf90661Theodore Ts'o  { "hfs",	 1,	 0,  2, "BD",			probe_hfs },
156550b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "ufs",	 8,  0x55c,  4, "T\031\001\000",	0 },
156650b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "hpfs",	 8,	 0,  4, "I\350\225\371",	0 },
156750b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  { "sysv",	 0,  0x3f8,  4, "\020~\030\375",	0 },
15687369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o  { "swap",	 0,  0xff6, 10, "SWAP-SPACE",		probe_swap0 },
15697369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o  { "swap",	 0,  0xff6, 10, "SWAPSPACE2",		probe_swap1 },
1570abaa11240a742bcfc4783e2cbebb7dd0cdf17e96Karel Zak  { "swsuspend", 0,  0xff6,  9, "S1SUSPEND",		probe_swap1 },
1571abaa11240a742bcfc4783e2cbebb7dd0cdf17e96Karel Zak  { "swsuspend", 0,  0xff6,  9, "S2SUSPEND",		probe_swap1 },
157231e2a75484816db0e5e68afacb13beef7e751061Theodore Ts'o  { "swsuspend", 0,  0xff6,  9, "ULSUSPEND",		probe_swap1 },
15737369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o  { "swap",	 0, 0x1ff6, 10, "SWAP-SPACE",		probe_swap0 },
15747369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o  { "swap",	 0, 0x1ff6, 10, "SWAPSPACE2",		probe_swap1 },
1575abaa11240a742bcfc4783e2cbebb7dd0cdf17e96Karel Zak  { "swsuspend", 0, 0x1ff6,  9, "S1SUSPEND",		probe_swap1 },
1576abaa11240a742bcfc4783e2cbebb7dd0cdf17e96Karel Zak  { "swsuspend", 0, 0x1ff6,  9, "S2SUSPEND",		probe_swap1 },
157731e2a75484816db0e5e68afacb13beef7e751061Theodore Ts'o  { "swsuspend", 0, 0x1ff6,  9, "ULSUSPEND",		probe_swap1 },
15787369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o  { "swap",	 0, 0x3ff6, 10, "SWAP-SPACE",		probe_swap0 },
15797369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o  { "swap",	 0, 0x3ff6, 10, "SWAPSPACE2",		probe_swap1 },
1580abaa11240a742bcfc4783e2cbebb7dd0cdf17e96Karel Zak  { "swsuspend", 0, 0x3ff6,  9, "S1SUSPEND",		probe_swap1 },
1581abaa11240a742bcfc4783e2cbebb7dd0cdf17e96Karel Zak  { "swsuspend", 0, 0x3ff6,  9, "S2SUSPEND",		probe_swap1 },
158231e2a75484816db0e5e68afacb13beef7e751061Theodore Ts'o  { "swsuspend", 0, 0x3ff6,  9, "ULSUSPEND",		probe_swap1 },
15837369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o  { "swap",	 0, 0x7ff6, 10, "SWAP-SPACE",		probe_swap0 },
15847369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o  { "swap",	 0, 0x7ff6, 10, "SWAPSPACE2",		probe_swap1 },
1585abaa11240a742bcfc4783e2cbebb7dd0cdf17e96Karel Zak  { "swsuspend", 0, 0x7ff6,  9, "S1SUSPEND",		probe_swap1 },
1586abaa11240a742bcfc4783e2cbebb7dd0cdf17e96Karel Zak  { "swsuspend", 0, 0x7ff6,  9, "S2SUSPEND",		probe_swap1 },
158731e2a75484816db0e5e68afacb13beef7e751061Theodore Ts'o  { "swsuspend", 0, 0x7ff6,  9, "ULSUSPEND",		probe_swap1 },
15887369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o  { "swap",	 0, 0xfff6, 10, "SWAP-SPACE",		probe_swap0 },
15897369f0ce5fdde7f8a1cc6e49211469b905c2c58fTheodore Ts'o  { "swap",	 0, 0xfff6, 10, "SWAPSPACE2",		probe_swap1 },
1590abaa11240a742bcfc4783e2cbebb7dd0cdf17e96Karel Zak  { "swsuspend", 0, 0xfff6,  9, "S1SUSPEND",		probe_swap1 },
1591abaa11240a742bcfc4783e2cbebb7dd0cdf17e96Karel Zak  { "swsuspend", 0, 0xfff6,  9, "S2SUSPEND",		probe_swap1 },
159231e2a75484816db0e5e68afacb13beef7e751061Theodore Ts'o  { "swsuspend", 0, 0xfff6,  9, "ULSUSPEND",		probe_swap1 },
15932c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o  { "ocfs",	 0,	 8,  9,	"OracleCFS",		probe_ocfs },
15942c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o  { "ocfs2",	 1,	 0,  6,	"OCFSV2",		probe_ocfs2 },
15952c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o  { "ocfs2",	 2,	 0,  6,	"OCFSV2",		probe_ocfs2 },
15962c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o  { "ocfs2",	 4,	 0,  6,	"OCFSV2",		probe_ocfs2 },
15972c92375ea426768a6e37faf876b2b06f0bf781a6Theodore Ts'o  { "ocfs2",	 8,	 0,  6,	"OCFSV2",		probe_ocfs2 },
1598e382a7eaded3ec6b38114988ae9b0723bb48002aKarsten Hopp  { "crypt_LUKS", 0,	 0,  6,	"LUKS\xba\xbe",		probe_luks },
1599f493d4e0ac93a5c500a2e9360a2398a8637895b6Eric Sandeen  { "squashfs",	 0,	 0,  4,	"sqsh",			0 },
16005845efd1238081e48b0fc37e8bb55c87a0a537bfEric Sandeen  { "squashfs",	 0,	 0,  4,	"hsqs",			0 },
1601a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen  { "lvm2pv",	 0,  0x218,  8, "LVM2 001",		probe_lvm2 },
1602a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen  { "lvm2pv",	 0,  0x018,  8, "LVM2 001",		probe_lvm2 },
1603a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen  { "lvm2pv",	 1,  0x018,  8, "LVM2 001",		probe_lvm2 },
1604a451d92f38188f7218a837a395b310354864b5a4Eric Sandeen  { "lvm2pv",	 1,  0x218,  8, "LVM2 001",		probe_lvm2 },
1605801b0053336cc5fe5b3447ddad58505352a6578eEric Sandeen  { "btrfs",	 64,  0x40,  8, "_BHRfS_M",		probe_btrfs },
16067c33c8899faa9b8250d5190ca8417f47daf3ba7bJeff Sharkey  { "f2fs",	 1,      0,  4, "\x10\x20\xf5\xf2",	probe_f2fs },
16071206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cbliminghao  { "exfat",     0,      3,  8, "EXFAT   ",             probe_exfat },
160850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o  {   NULL,	 0,	 0,  0, NULL,			NULL }
1609e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o};
1610e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
1611e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o/*
1612e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * Verify that the data in dev is consistent with what is on the actual
1613e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * block device (using the devname field only).  Normally this will be
1614e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * called when finding items in the cache, but for long running processes
1615e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * is also desirable to revalidate an item before use.
1616e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o *
1617e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * If we are unable to revalidate the data, we return the old data and
1618e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * do not set the BLKID_BID_FL_VERIFIED flag on it.
1619e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o */
162018d12963335b04a402d097af1d714e8708805adaTheodore Ts'oblkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
1621e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o{
1622e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	struct blkid_magic *id;
1623ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	struct blkid_probe probe;
1624ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o	blkid_tag_iterate iter;
1625ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	unsigned char *buf;
1626ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o	const char *type, *value;
162750b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	struct stat st;
162862bc8d19bdc640fe490ce2489c14591b5d356675Jeff Sharkey	time_t now;
162962bc8d19bdc640fe490ce2489c14591b5d356675Jeff Sharkey	double diff;
1630ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	int idx;
1631e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
1632e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	if (!dev)
1633e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		return NULL;
1634e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
16357ce08064061ed66647fa2c152c65f2f28eac9a0aTheodore Ts'o	now = time(0);
163662bc8d19bdc640fe490ce2489c14591b5d356675Jeff Sharkey	diff = difftime(now, dev->bid_time);
1637e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
1638492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o	if (stat(dev->bid_name, &st) < 0) {
1639492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o		DBG(DEBUG_PROBE,
1640492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o		    printf("blkid_verify: error %s (%d) while "
1641492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o			   "trying to stat %s\n", strerror(errno), errno,
1642492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o			   dev->bid_name));
1643492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o	open_err:
1644492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o		if ((errno == EPERM) || (errno == EACCES) || (errno == ENOENT)) {
1645492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o			/* We don't have read permission, just return cache data. */
1646492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o			DBG(DEBUG_PROBE, printf("returning unverified data for %s\n",
1647492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o						dev->bid_name));
1648492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o			return dev;
1649492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o		}
1650492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o		blkid_free_dev(dev);
1651492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o		return NULL;
1652492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o	}
1653492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o
1654492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o	if ((now >= dev->bid_time) &&
1655492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o	    (st.st_mtime <= dev->bid_time) &&
1656efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	    ((diff < BLKID_PROBE_MIN) ||
1657e324b250593a32680309015eba7c6c5db7851227Theodore Ts'o	     (dev->bid_flags & BLKID_BID_FL_VERIFIED &&
1658e324b250593a32680309015eba7c6c5db7851227Theodore Ts'o	      diff < BLKID_PROBE_INTERVAL)))
1659e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		return dev;
1660e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
1661f0a22d0fd3ec3f45b562af5afba8811f72b94a28Theodore Ts'o	DBG(DEBUG_PROBE,
166279e62409b3a247e258d9e9206484ed8f193a183eEric Sandeen	    printf("need to revalidate %s (cache time %lu, stat time %lu,\n\t"
1663492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o		   "time since last check %lu)\n",
166479e62409b3a247e258d9e9206484ed8f193a183eEric Sandeen		   dev->bid_name, (unsigned long)dev->bid_time,
166579e62409b3a247e258d9e9206484ed8f193a183eEric Sandeen		   (unsigned long)st.st_mtime, (unsigned long)diff));
1666492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o
1667492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o	if ((probe.fd = open(dev->bid_name, O_RDONLY)) < 0) {
1668492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o		DBG(DEBUG_PROBE, printf("blkid_verify: error %s (%d) while "
1669efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o					"opening %s\n", strerror(errno), errno,
1670492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o					dev->bid_name));
1671492ea6556e82caf88d77c78bde2beb8849aa4eafTheodore Ts'o		goto open_err;
1672e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	}
1673e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
1674ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	probe.cache = cache;
1675ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	probe.dev = dev;
1676ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	probe.sbbuf = 0;
1677ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	probe.buf = 0;
1678ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o	probe.buf_max = 0;
1679efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
168050b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	/*
168150b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	 * Iterate over the type array.  If we already know the type,
168250b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	 * then try that first.  If it doesn't work, then blow away
168350b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	 * the type information, and try again.
1684efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	 *
168550b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	 */
168650b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'otry_again:
168750b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	type = 0;
168850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) {
168950b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		uuid_t	uuid;
169050b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o
1691ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		if (check_mdraid(probe.fd, uuid) == 0) {
1692ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o			set_uuid(dev, uuid, 0);
169350b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o			type = "mdraid";
169450b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o			goto found_type;
169550b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		}
169650b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	}
1697e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	for (id = type_array; id->bim_type; id++) {
169850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		if (dev->bid_type &&
169950b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		    strcmp(id->bim_type, dev->bid_type))
170050b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o			continue;
170150b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o
170250b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		idx = id->bim_kboff + (id->bim_sboff >> 10);
1703d1da14b5b0496621046179e5644cc924ce01dae1Theodore Ts'o		buf = get_buffer(&probe, (__u64) idx << 10, 1024);
1704ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		if (!buf)
170550b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o			continue;
1706e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
1707c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia		if (memcmp(id->bim_magic, buf + (id->bim_sboff & 0x3ff),
170850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o			   id->bim_len))
170950b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o			continue;
171050b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o
171150b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		if ((id->bim_probe == NULL) ||
1712ca7498596f80896c8c495d5b0c3f20dd12ca9336Theodore Ts'o		    (id->bim_probe(&probe, id, buf) == 0)) {
171350b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o			type = id->bim_type;
171450b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o			goto found_type;
1715e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		}
1716e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	}
1717e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
171850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	if (!id->bim_type && dev->bid_type) {
171950b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		/*
1720ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o		 * Zap the device filesystem information and try again
172150b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		 */
17220225face1bd0dddaf19ee8089dc28980a0395633Theodore Ts'o		DBG(DEBUG_PROBE,
17230225face1bd0dddaf19ee8089dc28980a0395633Theodore Ts'o		    printf("previous fs type %s not valid, "
17240225face1bd0dddaf19ee8089dc28980a0395633Theodore Ts'o			   "trying full probe\n", dev->bid_type));
1725ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o		iter = blkid_tag_iterate_begin(dev);
1726ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o		while (blkid_tag_next(iter, &type, &value) == 0)
1727ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o			blkid_set_tag(dev, type, 0, 0);
1728ba5e38494e6b42d77f76d9ad18744388958eca7cTheodore Ts'o		blkid_tag_iterate_end(iter);
172950b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		goto try_again;
173050b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	}
1731e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
173250b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	if (!dev->bid_type) {
1733e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		blkid_free_dev(dev);
1734257ace82b77a281da6d0491294eda6f0b27ef424Theodore Ts'o		dev = 0;
1735257ace82b77a281da6d0491294eda6f0b27ef424Theodore Ts'o		goto found_type;
173650b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	}
1737c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia
173850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'ofound_type:
173950b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	if (dev && type) {
174050b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		dev->bid_devno = st.st_rdev;
174150b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		dev->bid_time = time(0);
174250b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		dev->bid_flags |= BLKID_BID_FL_VERIFIED;
1743ce72b862c59da24ba16b354d687549276a24f908Theodore Ts'o		cache->bic_flags |= BLKID_BIC_FL_CHANGED;
174450b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o
174579dd234a799434b6dc8365c49e743f00eb09d2fdTheodore Ts'o		blkid_set_tag(dev, "TYPE", type, 0);
1746c9bad3ce1ac50e317adef1400458e6e30d0be20aRicardo M. Correia
174712b3c8ec1d314b8775fc7d9cefd6bfff551f1de0Theodore Ts'o		DBG(DEBUG_PROBE, printf("%s: devno 0x%04llx, type %s\n",
174812a829dcdc57fb8ddc4887b07b40136288b6e7feMatthias Andree			   dev->bid_name, (long long)st.st_rdev, type));
1749e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	}
1750e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
175145e338f5332a54295893dba2e32cc093d1316f60Jim Meyering	free(probe.sbbuf);
175245e338f5332a54295893dba2e32cc093d1316f60Jim Meyering	free(probe.buf);
1753efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	if (probe.fd >= 0)
1754257ace82b77a281da6d0491294eda6f0b27ef424Theodore Ts'o		close(probe.fd);
1755e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
1756e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	return dev;
1757e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o}
1758e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
175978e2edf796e7902b8ce615ca8388840ef1387194Theodore Ts'oint blkid_known_fstype(const char *fstype)
176078e2edf796e7902b8ce615ca8388840ef1387194Theodore Ts'o{
176178e2edf796e7902b8ce615ca8388840ef1387194Theodore Ts'o	struct blkid_magic *id;
176278e2edf796e7902b8ce615ca8388840ef1387194Theodore Ts'o
176378e2edf796e7902b8ce615ca8388840ef1387194Theodore Ts'o	for (id = type_array; id->bim_type; id++) {
176478e2edf796e7902b8ce615ca8388840ef1387194Theodore Ts'o		if (strcmp(fstype, id->bim_type) == 0)
176578e2edf796e7902b8ce615ca8388840ef1387194Theodore Ts'o			return 1;
176678e2edf796e7902b8ce615ca8388840ef1387194Theodore Ts'o	}
176778e2edf796e7902b8ce615ca8388840ef1387194Theodore Ts'o	return 0;
176878e2edf796e7902b8ce615ca8388840ef1387194Theodore Ts'o}
176978e2edf796e7902b8ce615ca8388840ef1387194Theodore Ts'o
1770e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#ifdef TEST_PROGRAM
1771e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'oint main(int argc, char **argv)
1772e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o{
17737a603aa89fcffb8798eca34ca3858db6f0393046Theodore Ts'o	blkid_dev dev;
177450b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	blkid_cache cache;
177579dd234a799434b6dc8365c49e743f00eb09d2fdTheodore Ts'o	int ret;
1776e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
1777e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	if (argc != 2) {
1778e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		fprintf(stderr, "Usage: %s device\n"
1779e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o			"Probe a single device to determine type\n", argv[0]);
1780e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		exit(1);
1781e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	}
178279dd234a799434b6dc8365c49e743f00eb09d2fdTheodore Ts'o	if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) {
178379dd234a799434b6dc8365c49e743f00eb09d2fdTheodore Ts'o		fprintf(stderr, "%s: error creating cache (%d)\n",
178479dd234a799434b6dc8365c49e743f00eb09d2fdTheodore Ts'o			argv[0], ret);
178579dd234a799434b6dc8365c49e743f00eb09d2fdTheodore Ts'o		exit(1);
178679dd234a799434b6dc8365c49e743f00eb09d2fdTheodore Ts'o	}
178798999c399d563c248728bf217467a788cb0c1aadTheodore Ts'o	dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL);
178850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	if (!dev) {
1789e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		printf("%s: %s has an unsupported type\n", argv[0], argv[1]);
179050b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o		return (1);
179150b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	}
17921e5630abab066035602437ed047e0988064687f0Theodore Ts'o	printf("TYPE='%s'\n", dev->bid_type ? dev->bid_type : "(null)");
179350b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	if (dev->bid_label)
17941e5630abab066035602437ed047e0988064687f0Theodore Ts'o		printf("LABEL='%s'\n", dev->bid_label);
179550b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	if (dev->bid_uuid)
17961e5630abab066035602437ed047e0988064687f0Theodore Ts'o		printf("UUID='%s'\n", dev->bid_uuid);
1797efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
179850b380b4d4ab668bad45033e3a8aaf93c7f42844Theodore Ts'o	blkid_free_dev(dev);
1799e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	return (0);
1800e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o}
1801e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#endif
1802