aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorliminghao <liminghao@xiaomi.com>2017-03-01 17:54:42 +0800
committerliminghao <liminghao@xiaomi.com>2017-03-02 17:36:10 +0800
commit1206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cb (patch)
tree2463642cd61bfbd53b132491b5443924160301df
parent98f63cd9de161ffae915910098cc0a4311e9177b (diff)
downloade2fsprogs-1206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cb.tar.gz
blkid: add support to recognize exfat to blkid.
we can now identify exfat filesystem. Change-Id: I870e59a14b6bcd8b45562cdd02c2502d60a9eeff Signed-off-by: liminghao <liminghao@xiaomi.com>
-rw-r--r--lib/blkid/probe.c101
-rw-r--r--lib/blkid/probe.h42
2 files changed, 139 insertions, 4 deletions
diff --git a/lib/blkid/probe.c b/lib/blkid/probe.c
index 66ecbc43..fae74a7f 100644
--- a/lib/blkid/probe.c
+++ b/lib/blkid/probe.c
@@ -106,7 +106,6 @@ static int check_mdraid(int fd, unsigned char *ret_uuid)
if (blkid_llseek(fd, offset, 0) < 0 ||
read(fd, buf, 4096) != 4096)
return -BLKID_ERR_IO;
-
/* Check for magic number */
if (memcmp("\251+N\374", buf, 4) && memcmp("\374N+\251", buf, 4))
return -BLKID_ERR_PARAM;
@@ -330,7 +329,7 @@ static int probe_ext4dev(struct blkid_probe *probe,
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
return -BLKID_ERR_PARAM;
- /*
+ /*
* If the filesystem does not have a journal and ext2 and ext4
* is not present, then force this to be detected as an
* ext4dev filesystem.
@@ -374,7 +373,7 @@ static int probe_ext4(struct blkid_probe *probe, struct blkid_magic *id,
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
return -BLKID_ERR_PARAM;
- /*
+ /*
* If the filesystem does not have a journal and ext2 is not
* present, then force this to be detected as an ext2
* filesystem.
@@ -452,7 +451,7 @@ static int probe_ext2(struct blkid_probe *probe, struct blkid_magic *id,
EXT2_FEATURE_INCOMPAT_UNSUPPORTED))
return -BLKID_ERR_PARAM;
- /*
+ /*
* If ext2 is not present, but ext4 or ext4dev are, then
* disclaim we are ext2
*/
@@ -1403,6 +1402,99 @@ static int probe_f2fs(struct blkid_probe *probe,
return 0;
}
+static uint64_t exfat_block_to_offset(const struct exfat_super_block *sb,
+ uint64_t block)
+{
+ return block << sb->block_bits;
+}
+
+static uint64_t exfat_cluster_to_block(const struct exfat_super_block *sb,
+ uint32_t cluster)
+{
+ return sb->cluster_block_start +
+ ((uint64_t)(cluster - EXFAT_FIRST_DATA_CLUSTER) << sb->bpc_bits);
+}
+
+static uint64_t exfat_cluster_to_offset(const struct exfat_super_block *sb,
+ uint32_t cluster)
+{
+ return exfat_block_to_offset(sb, exfat_cluster_to_block(sb, cluster));
+}
+
+static uint32_t exfat_next_cluster(struct blkid_probe *probe,
+ const struct exfat_super_block *sb,
+ uint32_t cluster)
+{
+ uint32_t *next;
+ uint64_t offset;
+
+ offset = exfat_block_to_offset(sb, sb->fat_block_start)
+ + (uint64_t) cluster * sizeof (cluster);
+ next = (uint32_t *)get_buffer(probe, offset, sizeof (uint32_t));
+
+ return next ? *next : 0;
+}
+
+static struct exfat_entry_label *find_exfat_entry_label(
+ struct blkid_probe *probe, const struct exfat_super_block *sb)
+{
+ uint32_t cluster = sb->rootdir_cluster;
+ uint64_t offset = exfat_cluster_to_offset(sb, cluster);
+ uint8_t *entry;
+ const size_t max_iter = 10000;
+ size_t i = 0;
+
+ for (; i < max_iter; ++i) {
+ entry = (uint8_t *)get_buffer(probe, offset, EXFAT_ENTRY_SIZE);
+ if (!entry)
+ return NULL;
+ if (entry[0] == EXFAT_ENTRY_EOD)
+ return NULL;
+ if (entry[0] == EXFAT_ENTRY_LABEL)
+ return (struct exfat_entry_label*) entry;
+
+ offset += EXFAT_ENTRY_SIZE;
+ if (offset % CLUSTER_SIZE(sb) == 0) {
+ cluster = exfat_next_cluster(probe, sb, cluster);
+ if (cluster < EXFAT_FIRST_DATA_CLUSTER)
+ return NULL;
+ if (cluster > EXFAT_LAST_DATA_CLUSTER)
+ return NULL;
+ offset = exfat_cluster_to_offset(sb, cluster);
+ }
+ }
+
+ return NULL;
+}
+
+static int probe_exfat(struct blkid_probe *probe, struct blkid_magic *id,
+ unsigned char *buf)
+{
+ struct exfat_super_block *sb;
+ struct exfat_entry_label *label;
+ uuid_t uuid;
+ sb = (struct exfat_super_block *)buf;
+ if (!sb || !CLUSTER_SIZE(sb)) {
+ DBG(DEBUG_PROBE, printf("bad exfat superblock.\n"));
+ return errno ? - errno : 1;
+ }
+
+ label = find_exfat_entry_label(probe, sb);
+ if (label) {
+ blkid_set_tag(probe->dev, "LABEL", label->name, label->length);
+ } else {
+ blkid_set_tag(probe->dev, "LABEL", "disk", 4);
+ }
+
+ snprintf(uuid, sizeof (uuid), "%02hhX%02hhX-%02hhX%02hhX",
+ sb->volume_serial[3], sb->volume_serial[2],
+ sb->volume_serial[1], sb->volume_serial[0]);
+
+ set_uuid(probe->dev, uuid, 0);
+
+ return 0;
+}
+
/*
* Various filesystem magics that we can check for. Note that kboff and
* sboff are in kilobytes and bytes respectively. All magics are in
@@ -1512,6 +1604,7 @@ static struct blkid_magic type_array[] = {
{ "lvm2pv", 1, 0x218, 8, "LVM2 001", probe_lvm2 },
{ "btrfs", 64, 0x40, 8, "_BHRfS_M", probe_btrfs },
{ "f2fs", 1, 0, 4, "\x10\x20\xf5\xf2", probe_f2fs },
+ { "exfat", 0, 3, 8, "EXFAT ", probe_exfat },
{ NULL, 0, 0, 0, NULL, NULL }
};
diff --git a/lib/blkid/probe.h b/lib/blkid/probe.h
index 9d026952..c46a3325 100644
--- a/lib/blkid/probe.h
+++ b/lib/blkid/probe.h
@@ -14,6 +14,8 @@
#ifndef _BLKID_PROBE_H
#define _BLKID_PROBE_H
+#include <stdint.h>
+
#include <blkid/blkid_types.h>
struct blkid_magic;
@@ -763,6 +765,46 @@ struct f2fs_super_block {
__u8 extension_list[F2FS_MAX_EXTENSION][8]; /* extension array */
} __attribute__((__packed__));
+struct exfat_super_block {
+ uint8_t jump[3];
+ uint8_t oem_name[8];
+ uint8_t __unused1[53];
+ uint64_t block_start;
+ uint64_t block_count;
+ uint32_t fat_block_start;
+ uint32_t fat_block_count;
+ uint32_t cluster_block_start;
+ uint32_t cluster_count;
+ uint32_t rootdir_cluster;
+ uint8_t volume_serial[4];
+ struct {
+ uint8_t vermin;
+ uint8_t vermaj;
+ } version;
+ uint16_t volume_state;
+ uint8_t block_bits;
+ uint8_t bpc_bits;
+ uint8_t fat_count;
+ uint8_t drive_no;
+ uint8_t allocated_percent;
+} __attribute__((__packed__));
+
+struct exfat_entry_label {
+ uint8_t type;
+ uint8_t length;
+ uint8_t name[30];
+} __attribute__((__packed__));
+
+#define BLOCK_SIZE(sb) (1 << (sb)->block_bits)
+#define CLUSTER_SIZE(sb) (BLOCK_SIZE(sb) << (sb)->bpc_bits)
+
+#define EXFAT_FIRST_DATA_CLUSTER 2
+#define EXFAT_LAST_DATA_CLUSTER 0xffffff6
+#define EXFAT_ENTRY_SIZE 32
+
+#define EXFAT_ENTRY_EOD 0x00
+#define EXFAT_ENTRY_LABEL 0x83
+
/*
* Byte swap functions
*/