[Linux-cluster] [PATCH] iddev - convert to general purpose device identifier
Bastian Blank
bastian at waldi.eu.org
Fri Apr 1 14:20:31 UTC 2005
Hi folks
iddev currently only returns a human readable string of the device
content. This makes it rather unusable in contexts where you need to
have to do decitions on the content.
Changes:
- Add three enums which describe the content.
- identify_device get a struct which contains the enums and the human
readable text.
- Get the block size. The struct also contains a field for the uuid, but
it is not set yet.
- Add xfs support.
- Make the ext2/3 check differ between ext2 and ext3.
I currently try to do some cleanups in lvm2/fsadm. This tool currently
relies on an entry in /etc/fstab to get the filesystem type and a
temporary mount to get the block size. With this changes I can just use
iddev to gather the informations.
Bastian
--
Conquest is easy. Control is not.
-- Kirk, "Mirror, Mirror", stardate unknown
-------------- next part --------------
Index: lib/iddev.h
===================================================================
--- lib/iddev.h (revision 413)
+++ lib/iddev.h (working copy)
@@ -16,19 +16,64 @@
/**
+ * device_info -
+ */
+
+enum device_info_family
+{
+ DEVICE_INFO_UNDEFINED_FAMILY = 0,
+ DEVICE_INFO_CONTAINER,
+ DEVICE_INFO_FILESYSTEM,
+ DEVICE_INFO_SWAP,
+};
+
+enum device_info_type
+{
+ DEVICE_INFO_UNDEFINED_TYPE = 0,
+ DEVICE_INFO_CONTAINER_CCA,
+ DEVICE_INFO_CONTAINER_CIDEV,
+ DEVICE_INFO_CONTAINER_LVM1,
+ DEVICE_INFO_CONTAINER_LVM2,
+ DEVICE_INFO_CONTAINER_PARTITION,
+ DEVICE_INFO_CONTAINER_POOL,
+ DEVICE_INFO_FILESYSTEM_EXT23,
+ DEVICE_INFO_FILESYSTEM_GFS,
+ DEVICE_INFO_FILESYSTEM_REISERFS,
+ DEVICE_INFO_FILESYSTEM_XFS,
+};
+
+enum device_info_subtype
+{
+ DEVICE_INFO_UNDEFINED_SUBTYPE = 0,
+ DEVICE_INFO_CONTAINER_PARTITION_MSDOS,
+ DEVICE_INFO_FILESYSTEM_EXT2,
+ DEVICE_INFO_FILESYSTEM_EXT3,
+};
+
+struct device_info
+{
+ enum device_info_family family;
+ enum device_info_type type;
+ enum device_info_subtype subtype;
+
+ char display[128];
+ unsigned char uuid[16];
+ size_t block_size;
+};
+
+/**
* indentify_device - figure out what's on a device
* @fd: a file descriptor open on a device open for (at least) reading
- * @type: a buffer that contains the type of filesystem
- * @type_len: the amount of space pointed to by @type
+ * @info: a buffer
*
* The offset of @fd will be changed by the function.
* This routine will not write to this device.
*
* Returns: -1 on error (with errno set), 1 if unabled to identify,
- * 0 if device identified (with @type set)
+ * 0 if device identified (with @info set)
*/
-int identify_device(int fd, char *type, unsigned type_len);
+int identify_device(int fd, struct device_info *info);
/**
Index: lib/identify_device.c
===================================================================
--- lib/identify_device.c (revision 413)
+++ lib/identify_device.c (working copy)
@@ -50,7 +50,7 @@
int main(int argc, char *argv[])
{
int fd;
- char buf[BUFSIZE];
+ struct device_info info;
uint64 bytes;
int error;
@@ -63,18 +63,18 @@
if (fd < 0)
die("can't open %s: %s\n", argv[1], strerror(errno));
- error = identify_device(fd, buf, BUFSIZE);
+ error = identify_device(fd, &info);
if (error < 0)
die("error identifying the contents of %s: %s\n", argv[1], strerror(errno));
else if (error)
- strcpy(buf, "unknown");
+ strcpy(info.display, "unknown");
error = device_size(fd, &bytes);
if (error < 0)
die("error determining the size of %s: %s\n", argv[1], strerror(errno));
printf("%s:\n%-15s%s\n%-15s%"PRIu64"\n",
- argv[1], " contents:", buf, " bytes:", bytes);
+ argv[1], " contents:", info.display, " bytes:", bytes);
close(fd);
Index: lib/iddev.c
===================================================================
--- lib/iddev.c (revision 413)
+++ lib/iddev.c (working copy)
@@ -25,24 +25,37 @@
#include "iddev.h"
+static void info_set_display(struct device_info *info, const char *display)
+{
+ snprintf(info->display, sizeof (info->display), display);
+}
+static inline void info_set(struct device_info *info, const enum device_info_family family, const enum device_info_type type, const enum device_info_subtype subtype, const char *display)
+{
+ info->family = family;
+ info->type = type;
+ info->subtype = subtype;
+ info_set_display(info, display);
+}
+static inline void info_set_container(struct device_info *info, const enum device_info_type type, const enum device_info_subtype subtype, const char *display)
+{
+ info_set(info, DEVICE_INFO_CONTAINER, type, subtype, display);
+}
+static inline void info_set_filesystem(struct device_info *info, const enum device_info_type type, const enum device_info_subtype subtype, const char *display)
+{
+ info_set(info, DEVICE_INFO_FILESYSTEM, type, subtype, display);
+}
+typedef int check(int fd, struct device_info *info);
+
/**
* check_for_gfs - check to see if GFS is on this device
- * @fd: a file descriptor open on a device open for (at least) reading
- * @type: a buffer that contains the type of filesystem
- * @type_len: the amount of space pointed to by @type
- *
- * An EINVAL returned from lseek means that the device was too
- * small -- at least on Linux.
- *
- * Returns: -1 on error (with errno set), 1 if not GFS,
- * 0 if GFS found (with type set)
*/
-static int check_for_gfs(int fd, char *type, unsigned type_len)
+static check check_for_gfs;
+static int check_for_gfs(int fd, struct device_info *info)
{
unsigned char buf[512];
uint32 *p = (uint32 *)buf;
@@ -66,7 +79,7 @@
if (osi_be32_to_cpu(*p) != 0x01161970 || osi_be32_to_cpu(*(p + 1)) != 1)
return 1;
- snprintf(type, type_len, "GFS filesystem");
+ info_set_filesystem(info, DEVICE_INFO_FILESYSTEM_GFS, 0, "GFS filesystem");
return 0;
}
@@ -74,15 +87,10 @@
/**
* check_for_pool - check to see if Pool is on this device
- * @fd: a file descriptor open on a device open for (at least) reading
- * @type: a buffer that contains the type of filesystem
- * @type_len: the amount of space pointed to by @type
- *
- * Returns: -1 on error (with errno set), 1 if not Pool,
- * 0 if Pool found (with type set)
*/
-static int check_for_pool(int fd, char *type, unsigned type_len)
+static check check_for_pool;
+static int check_for_pool(int fd, struct device_info *info)
{
unsigned char buf[512];
uint64 *p = (uint64 *)buf;
@@ -106,23 +114,18 @@
if (osi_be64_to_cpu(*p) != 0x11670)
return 1;
- snprintf(type, type_len, "Pool subdevice");
+ info_set_container(info, DEVICE_INFO_CONTAINER_POOL, 0, "Pool subdevice");
return 0;
}
/**
- * check_for_paritition - check to see if Partition is on this device
- * @fd: a file descriptor open on a device open for (at least) reading
- * @type: a buffer that contains the type of filesystem
- * @type_len: the amount of space pointed to by @type
- *
- * Returns: -1 on error (with errno set), 1 if not Partition,
- * 0 if Partition found (with type set)
+ * check_for_msdos - check to see if Partition is on this device
*/
-static int check_for_partition(int fd, char *type, unsigned type_len)
+static check check_for_partition_msdos;
+static int check_for_partition_msdos(int fd, struct device_info *info)
{
unsigned char buf[512];
int error;
@@ -145,29 +148,42 @@
if (buf[510] != 0x55 || buf[511] != 0xAA)
return 1;
- snprintf(type, type_len, "partition information");
+ info_set_container(info, DEVICE_INFO_CONTAINER_PARTITION, DEVICE_INFO_CONTAINER_PARTITION_MSDOS, "MSDOS partition information");
return 0;
}
+enum
+{
+ BLOCK_SIZE_BITS = 10,
+ BLOCK_SIZE = (1 << BLOCK_SIZE_BITS),
+ EXT3_SUPER_MAGIC = 0xEF53,
+ EXT23_FEATURE_COMPAT_HAS_JOURNAL = 0x4,
+};
+struct ext23_superblock
+{
+ uint32_t _r1[6]; /**< 0x00 - 0x14 */
+ uint32_t s_log_block_size; /**< 0x18 */
+ uint32_t _r2[7]; /**< 0x1c - 0x34 */
+ uint16_t s_magic; /**< 0x38 */
+ uint16_t s_state; /**< 0x3a */
+ uint32_t _r3[8]; /**< 0x3c - 0x58 */
+ uint32_t s_feature_compat; /**< 0x5c */
+ uint32_t s_feature_incompat; /**< 0x60 */
+ uint32_t s_feature_ro_compat; /**< 0x64 */
+ uint8_t s_uuid[16]; /**< 0x68 - 0x77 */
+};
+
/**
* check_for_ext23 - check to see if EXT23 is on this device
- * @fd: a file descriptor open on a device open for (at least) reading
- * @type: a buffer that contains the type of filesystem
- * @type_len: the amount of space pointed to by @type
- *
- * An EINVAL returned from lseek means that the device was too
- * small -- at least on Linux.
- *
- * Returns: -1 on error (with errno set), 1 if not EXT23,
- * 0 if EXT23 found (with type set)
*/
-static int check_for_ext23(int fd, char *type, unsigned type_len)
+static check check_for_ext23;
+static int check_for_ext23(int fd, struct device_info *info)
{
unsigned char buf[512];
- uint16 *p = (uint16 *)buf;
+ struct ext23_superblock *p = (struct ext23_superblock *)buf;
int error;
error = lseek(fd, 1024, SEEK_SET);
@@ -185,26 +201,78 @@
else if (error < 58)
return 1;
- if (osi_le16_to_cpu(p[28]) != 0xEF53)
+ if (osi_le16_to_cpu(p->s_magic) != EXT3_SUPER_MAGIC)
return 1;
- snprintf(type, type_len, "EXT2/3 filesystem");
+ info->block_size = (BLOCK_SIZE << osi_le32_to_cpu(p->s_log_block_size));
+ if (osi_le16_to_cpu(p->s_feature_compat) & EXT23_FEATURE_COMPAT_HAS_JOURNAL)
+ info_set_filesystem(info, DEVICE_INFO_FILESYSTEM_EXT23, DEVICE_INFO_FILESYSTEM_EXT3, "EXT3 filesystem");
+ else
+ info_set_filesystem(info, DEVICE_INFO_FILESYSTEM_EXT23, DEVICE_INFO_FILESYSTEM_EXT2, "EXT2 filesystem");
+
return 0;
}
+enum
+{
+ XFS_SB_MAGIC = 0x58465342,
+};
+
+struct xfs_superblock
+{
+ uint32_t sb_magicnum;
+ uint32_t sb_blocksize;
+ uint64_t sb_dblocks;
+ uint64_t sb_rblocks;
+ uint64_t sb_rextents;
+ uint8_t sb_uuid[16];
+};
+
/**
+ * check_for_xfs - check to see if XFS is on this device
+ */
+
+static check check_for_xfs;
+static int check_for_xfs(int fd, struct device_info *info)
+{
+ unsigned char buf[512];
+ struct xfs_superblock *p = (struct xfs_superblock *)buf;
+ int error;
+
+ error = lseek(fd, 0, SEEK_SET);
+ if (error < 0)
+ return (errno == EINVAL) ? 1 : error;
+ else if (error != 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ error = read(fd, buf, 512);
+ if (error < 0)
+ return error;
+ else if (error < 58)
+ return 1;
+
+ if (osi_be32_to_cpu(p->sb_magicnum) != XFS_SB_MAGIC)
+ return 1;
+
+ info->block_size = osi_be32_to_cpu(p->sb_blocksize);
+
+ info_set_filesystem(info, DEVICE_INFO_FILESYSTEM_XFS, 0, "XFS filesystem");
+
+ return 0;
+}
+
+
+/**
* check_for_swap - check to see if SWAP is on this device
- * @fd: a file descriptor open on a device open for (at least) reading
- * @type: a buffer that contains the type of filesystem
- * @type_len: the amount of space pointed to by @type
- *
- * Returns: -1 on error (with errno set), 1 if not SWAP,
- * 0 if SWAP found (with type set)
*/
-static int check_for_swap(int fd, char *type, unsigned type_len)
+static check check_for_swap;
+static int check_for_swap(int fd, struct device_info *info)
{
unsigned char buf[8192];
int error;
@@ -227,7 +295,7 @@
if (memcmp(buf + 4086, "SWAP-SPACE", 10) && memcmp(buf + 4086, "SWAPSPACE2", 10))
return 1;
- snprintf(type, type_len, "swap device");
+ info_set(info, DEVICE_INFO_SWAP, 0, 0, "swap device");
return 0;
}
@@ -235,15 +303,10 @@
/**
* check_for_lvm1 - check to see if LVM1 is on this device
- * @fd: a file descriptor open on a device open for (at least) reading
- * @type: a buffer that contains the type of filesystem
- * @type_len: the amount of space pointed to by @type
- *
- * Returns: -1 on error (with errno set), 1 if not LVM1,
- * 0 if LVM1 found (with type set)
*/
-static int check_for_lvm1(int fd, char *type, unsigned type_len)
+static check check_for_lvm1;
+static int check_for_lvm1(int fd, struct device_info *info)
{
unsigned char buf[512];
int error;
@@ -266,7 +329,7 @@
if (buf[0] != 'H' || buf[1] != 'M')
return 1;
- snprintf(type, type_len, "lvm1 subdevice");
+ info_set_container(info, DEVICE_INFO_CONTAINER_LVM1, 0, "LVM1 subdevice");
return 0;
}
@@ -274,15 +337,10 @@
/**
* check_for_lvm2 - check to see if LVM2 is on this device
- * @fd: a file descriptor open on a device open for (at least) reading
- * @type: a buffer that contains the type of filesystem
- * @type_len: the amount of space pointed to by @type
- *
- * Returns: -1 on error (with errno set), 1 if not LVM2,
- * 0 if LVM1 found (with type set)
*/
-static int check_for_lvm2(int fd, char *type, unsigned type_len)
+static check check_for_lvm2;
+static int check_for_lvm2(int fd, struct device_info *info)
{
unsigned char buf[512];
int error;
@@ -315,7 +373,7 @@
if (strncmp(&buf[24], "LVM2 001", 8) != 0)
continue;
- snprintf(type, type_len, "lvm2 subdevice");
+ info_set_container(info, DEVICE_INFO_CONTAINER_LVM2, 0, "LVM1 subdevice");
return 0;
}
@@ -326,15 +384,10 @@
/**
* check_for_cidev - check to see if CIDEV is on this device
- * @fd: a file descriptor open on a device open for (at least) reading
- * @type: a buffer that contains the type of filesystem
- * @type_len: the amount of space pointed to by @type
- *
- * Returns: -1 on error (with errno set), 1 if not CIDEV,
- * 0 if CIDEV found (with type set)
*/
-static int check_for_cidev(int fd, char *type, unsigned type_len)
+static check check_for_cidev;
+static int check_for_cidev(int fd, struct device_info *info)
{
unsigned char buf[512];
uint32 *p = (uint32 *)buf;
@@ -358,7 +411,7 @@
if (osi_be32_to_cpu(*p) != 0x47465341)
return 1;
- snprintf(type, type_len, "CIDEV");
+ info_set_container(info, DEVICE_INFO_CONTAINER_CIDEV, 0, "CIDEV");
return 0;
}
@@ -366,15 +419,10 @@
/**
* check_for_cca - check to see if CCA is on this device
- * @fd: a file descriptor open on a device open for (at least) reading
- * @type: a buffer that contains the type of filesystem
- * @type_len: the amount of space pointed to by @type
- *
- * Returns: -1 on error (with errno set), 1 if not CCA,
- * 0 if CCA found (with type set)
*/
-static int check_for_cca(int fd, char *type, unsigned type_len)
+static check check_for_cca;
+static int check_for_cca(int fd, struct device_info *info)
{
unsigned char buf[512];
uint32 *p = (uint32 *)buf;
@@ -398,7 +446,7 @@
if (osi_be32_to_cpu(*p) != 0x122473)
return 1;
- snprintf(type, type_len, "CCA device");
+ info_set_container(info, DEVICE_INFO_CONTAINER_CCA, 0, "CCA device");
return 0;
}
@@ -406,15 +454,10 @@
/**
* check_for_reiserfs - check to see if reisterfs is on this device
- * @fd: a file descriptor open on a device open for (at least) reading
- * @type: a buffer that contains the type of filesystem
- * @type_len: the amount of space pointed to by @type
- *
- * Returns: -1 on error (with errno set), 1 if not reiserfs,
- * 0 if CCA found (with type set)
*/
-static int check_for_reiserfs(int fd, char *type, unsigned type_len)
+static check check_for_reiserfs;
+static int check_for_reiserfs(int fd, struct device_info *info)
{
unsigned int pass;
uint64 offset;
@@ -444,7 +487,7 @@
strncmp(buf + 52, "ReIsEr2Fs", 9) == 0 ||
strncmp(buf + 52, "ReIsEr3Fs", 9) == 0)
{
- snprintf(type, type_len, "Reiserfs filesystem");
+ info_set_filesystem(info, DEVICE_INFO_FILESYSTEM_REISERFS, 0, "ReiserFS filesystem");
return 0;
}
}
@@ -453,69 +496,40 @@
}
-/**
- * identify_device - figure out what's on a device
- * @fd: a file descriptor open on a device open for (at least) reading
- * @type: a buffer that contains the type of filesystem
- * @type_len: the amount of space pointed to by @type
- *
- * The offset of @fd will be changed by this function.
- * This routine will not write to the device.
- *
- * Returns: -1 on error (with errno set), 1 if unabled to identify,
- * 0 if device identified (with type set)
- */
+static check *checks[] =
+{
+ check_for_partition_msdos,
+ check_for_pool,
+ check_for_lvm1,
+ check_for_lvm2,
+ check_for_cidev,
+ check_for_cca,
+ check_for_ext23,
+ check_for_gfs,
+ check_for_reiserfs,
+ check_for_xfs,
+ check_for_swap,
+};
-int identify_device(int fd, char *type, unsigned type_len)
+int identify_device(int fd, struct device_info *info)
{
- int error;
+ int i;
- if (!type || !type_len)
+ if (!info)
{
errno = EINVAL;
return -1;
}
- error = check_for_pool(fd, type, type_len);
- if (error <= 0)
- return error;
+ memset(info, sizeof (struct device_info), 0);
- error = check_for_lvm1(fd, type, type_len);
- if (error <= 0)
- return error;
+ for (i = 0; i < sizeof (checks) / sizeof (*checks); ++i)
+ {
+ int error = checks[i](fd, info);
+ if (error <= 0)
+ return error;
+ }
- error = check_for_lvm2(fd, type, type_len);
- if(error <= 0)
- return error;
-
- error = check_for_cidev(fd, type, type_len);
- if (error <= 0)
- return error;
-
- error = check_for_cca(fd, type, type_len);
- if (error <= 0)
- return error;
-
- error = check_for_gfs(fd, type, type_len);
- if (error <= 0)
- return error;
-
- error = check_for_ext23(fd, type, type_len);
- if (error <= 0)
- return error;
-
- error = check_for_reiserfs(fd, type, type_len);
- if (error <= 0)
- return error;
-
- error = check_for_swap(fd, type, type_len);
- if (error <= 0)
- return error;
-
- error = check_for_partition(fd, type, type_len);
- if (error <= 0)
- return error;
-
return 1;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
URL: <http://listman.redhat.com/archives/linux-cluster/attachments/20050401/da52aee0/attachment.sig>
More information about the Linux-cluster
mailing list