Add support for adfs to blkid.
ADFS discs do not have a magic number, so I verify the checksum of the
512-byte boot block, and do a sanity check on the sector size and disc size.
If a disc name is present in the disc record, it is used as the label.
Signed-off-by: Richard Fearn<richardfearn@xxxxxxxxx>
diff --git a/shlibs/blkid/src/superblocks/Makefile.am
b/shlibs/blkid/src/superblocks/Makefile.am
index a7c4a23..89354f7 100644
--- a/shlibs/blkid/src/superblocks/Makefile.am
+++ b/shlibs/blkid/src/superblocks/Makefile.am
@@ -43,4 +43,5 @@ libblkid_superblocks_la_SOURCES = \
lvm.c \
zfs.c \
ubifs.c \
- bfs.c
+ bfs.c \
+ adfs.c
diff --git a/shlibs/blkid/src/superblocks/adfs.c
b/shlibs/blkid/src/superblocks/adfs.c
new file mode 100644
index 0000000..54e6402
--- /dev/null
+++ b/shlibs/blkid/src/superblocks/adfs.c
@@ -0,0 +1,69 @@
+/*
+ * util-linux-ng/shlibs/blkid/src/superblocks/adfs.c
+ *
+ * Copyright (C) 2009 Richard Fearn <richardfearn@xxxxxxxxx>
+ *
+ * Sanity checks based on ADFS code from the Linux kernel, written
+ * by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <string.h>
+#include "superblocks.h"
+#include "adfs.h"
+
+#define IS_ADFS 0
+#define NOT_ADFS -1
+
+#define BOOT_BLOCK_OFFSET 0xC00
+#define BOOT_BLOCK_SIZE 512
+
+#define DISC_RECORD_OFFSET 0x1C0
+
+static int probe_adfs(blkid_probe pr, const struct blkid_idmag *mag)
+{
+ unsigned char *as;
+ uint8_t *dr;
+ long int disc_size;
+ unsigned char disc_name[11];
+
+ /* read superblock */
+ as = blkid_probe_get_buffer(pr, BOOT_BLOCK_OFFSET,
BOOT_BLOCK_SIZE);
+ if (!as)
+ return NOT_ADFS;
+
+ /* verify boot block checksum */
+ if (adfs_checkbblk(as))
+ return NOT_ADFS;
+
+ dr = as + DISC_RECORD_OFFSET;
+
+ /* check log2secsize */
+ if (dr[0] != 8 && dr[0] != 9 && dr[0] != 10)
+ return NOT_ADFS;
+
+ /* check disc size is non-zero */
+ disc_size = dr[16] + (dr[17] << 8) + (dr[18] << 16) + (dr[19]
<< 24);
+ if (disc_size == 0)
+ return NOT_ADFS;
+
+ /* set label, if disc has a name */
+ if (dr[22]) {
+ disc_name[10] = '\0';
+ strncpy(disc_name, dr + 22, 10);
+ *strchrnul(disc_name, '\r') = '\0';
+ blkid_probe_set_label(pr, disc_name, strlen(disc_name));
+ }
+
+ return IS_ADFS;
+}
+
+const struct blkid_idinfo adfs_idinfo = {
+ .name = "adfs",
+ .usage = BLKID_USAGE_FILESYSTEM,
+ .probefunc = probe_adfs,
+ .flags = BLKID_IDINFO_TOLERANT
+};
diff --git a/shlibs/blkid/src/superblocks/adfs.h
b/shlibs/blkid/src/superblocks/adfs.h
new file mode 100644
index 0000000..c910aba
--- /dev/null
+++ b/shlibs/blkid/src/superblocks/adfs.h
@@ -0,0 +1,29 @@
+/*
+ * util-linux-ng/shlibs/blkid/src/superblocks/adfs.h
+ *
+ * The adfs_checkbblk function is from include/linux/adfs_fs.h in the Linux
+ * kernel.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Calculate the boot block checksum on an ADFS drive. Note that this will
+ * appear to be correct if the sector contains all zeros, so also check
that
+ * the disk size is non-zero!!!
+ */
+static inline int adfs_checkbblk(unsigned char *ptr)
+{
+ unsigned int result = 0;
+ unsigned char *p = ptr + 511;
+
+ do {
+ result = (result & 0xff) + (result >> 8);
+ result = result + *--p;
+ } while (p != ptr);
+
+ return (result & 0xff) != ptr[511];
+}
+
diff --git a/shlibs/blkid/src/superblocks/superblocks.c
b/shlibs/blkid/src/superblocks/superblocks.c
index d2c7825..8cb8a58 100644
--- a/shlibs/blkid/src/superblocks/superblocks.c
+++ b/shlibs/blkid/src/superblocks/superblocks.c
@@ -132,7 +132,8 @@ static const struct blkid_idinfo *idinfos[] =
&netware_idinfo,
&btrfs_idinfo,
&ubifs_idinfo,
- &bfs_idinfo
+ &bfs_idinfo,
+ &adfs_idinfo
};
/*
diff --git a/shlibs/blkid/src/superblocks/superblocks.h
b/shlibs/blkid/src/superblocks/superblocks.h
index 641397a..537d88f 100644
--- a/shlibs/blkid/src/superblocks/superblocks.h
+++ b/shlibs/blkid/src/superblocks/superblocks.h
@@ -61,6 +61,7 @@ extern const struct blkid_idinfo btrfs_idinfo;
extern const struct blkid_idinfo ubifs_idinfo;
extern const struct blkid_idinfo zfs_idinfo;
extern const struct blkid_idinfo bfs_idinfo;
+extern const struct blkid_idinfo adfs_idinfo;
/*
* superblock functions
--
To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html