fsid - Add to tree but don't build
authorAlex Hornung <ahornung@gmail.com>
Mon, 15 Nov 2010 17:57:19 +0000 (17:57 +0000)
committerAlex Hornung <ahornung@gmail.com>
Mon, 15 Nov 2010 18:04:34 +0000 (18:04 +0000)
* Add 'fsid', a proof-of-concept for now that reads volume names from
  hammer and ufs volumes (so far) and creates links to the devices with
  fs volumes in a /dev directory.

sbin/fsid/Makefile [new file with mode: 0644]
sbin/fsid/fsid.c [new file with mode: 0644]
sbin/fsid/fsid.h [new file with mode: 0644]
sbin/fsid/hammer.c [new file with mode: 0644]
sbin/fsid/ufs.c [new file with mode: 0644]

diff --git a/sbin/fsid/Makefile b/sbin/fsid/Makefile
new file mode 100644 (file)
index 0000000..e46291c
--- /dev/null
@@ -0,0 +1,6 @@
+PROG=  fsid
+SRCS=  fsid.c ufs.c hammer.c
+LDADD= -ldevattr -lprop
+NOMAN=
+
+.include <bsd.prog.mk>
diff --git a/sbin/fsid/fsid.c b/sbin/fsid/fsid.c
new file mode 100644 (file)
index 0000000..3ee49a8
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2010 The DragonFly Project.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Alex Hornung <ahornung@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/stat.h>
+#include <devattr.h>
+#include <errno.h>
+#include "fsid.h"
+
+static struct fs_type fs_types[] = {
+       { "HAMMER",     hammer_probe,   hammer_volname  },
+       { "UFS",        ufs_probe,      ufs_volname     },
+       { NULL,         NULL,           NULL            }
+};
+
+
+static struct fsid_head fsid_list =
+               TAILQ_HEAD_INITIALIZER(fsid_list);
+
+static int
+fsid_alias_exists(const char *dev)
+{
+       struct fsid_entry *fsid;
+       int exists = 0;
+
+       if (TAILQ_EMPTY(&fsid_list))
+               return 0;
+
+       TAILQ_FOREACH(fsid, &fsid_list, link) {
+               if (strcmp(fsid->dev_path, dev) == 0) {
+                       exists = 1;
+                       break;
+               }
+       }
+
+       return exists;
+}
+
+static int
+fsid_check_create_alias(const char *dev)
+{
+       struct fsid_entry *fsid;
+       char full_path[MAXPATHLEN];
+       char link_path[MAXPATHLEN];
+       char *volname;
+       int i;
+
+       if (fsid_alias_exists(dev))
+               return EEXIST;
+
+       sprintf(full_path, "/dev/%s", dev);
+       for (i = 0; fs_types[i].fs_name != NULL; i++) {
+               volname = fs_types[i].fs_volname(full_path);
+               if (volname == NULL)
+                       continue;
+
+               printf("Volume name for %s is %s\n", dev, volname);
+               fsid = malloc(sizeof(struct fsid_entry));
+               if (fsid == NULL)
+                       return ENOMEM;
+#if 1
+               sprintf(link_path, "/dev/vol-by-name/%s", volname);
+
+               fsid->dev_path = strdup(dev);
+               fsid->link_path = strdup(link_path);
+               if ((fsid->dev_path == NULL) || (fsid->link_path == NULL)) {
+                       free(fsid);
+                       return ENOMEM;
+               }
+
+               mkdir("/dev/vol-by-name", 0755);
+               symlink(full_path, link_path);
+
+               TAILQ_INSERT_TAIL(&fsid_list, fsid, link);
+#endif
+               break;
+       }
+
+       return 0;
+}
+
+static int
+fsid_check_remove_alias(const char *dev)
+{
+       struct fsid_entry *fsid, *fsid2;
+
+       if (!fsid_alias_exists(dev))
+               return 0;
+
+       TAILQ_FOREACH_MUTABLE(fsid, &fsid_list, link, fsid2) {
+               if (strcmp(fsid->dev_path, dev) != 0)
+                       continue;
+
+               TAILQ_REMOVE(&fsid_list, fsid, link);
+
+               unlink(fsid->link_path);
+
+               free(fsid->dev_path);
+               free(fsid->link_path);
+               free(fsid);
+       }
+
+       return 0;
+}
+
+static
+void
+usage(void)
+{
+       fprintf(stderr, "usage: fsid [-d]\n");
+       exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+       struct udev *udev;
+       struct udev_enumerate *udev_enum;
+       struct udev_list_entry *udev_le, *udev_le_first;
+       struct udev_monitor *udev_monitor;
+       struct udev_device *udev_dev;
+       int ch;
+#if 0
+       prop_dictionary_t *dict;
+#endif
+       int ret, daemon_flag = 0;
+       const char *prop, *dev_path;
+
+       while ((ch = getopt(argc, argv, "d")) != -1) {
+               switch(ch) {
+               case 'd':
+                       daemon_flag = 1;
+                       break;
+               default:
+                       usage();
+                       /* NOT REACHED */
+               }
+       }
+       argc -= optind;
+       argv += optind;
+
+       udev = udev_new();
+       if (udev == NULL)
+               err(1, "udev_new");
+
+       udev_enum = udev_enumerate_new(udev);
+       if (udev_enum == NULL)
+               err(1, "udev_enumerate_new");
+
+       ret = udev_enumerate_add_match_property(udev_enum, "subsystem", "disk");
+       if (ret != 0)
+               err(1, "udev_enumerate_add_match_property, out, ret=%d\n", ret);
+#if 1
+       ret = udev_enumerate_add_match_property(udev_enum, "alias", "0");
+       if (ret != 0)
+               err(1, "udev_enumerate_add_match_property, out, ret=%d\n", ret);
+
+       ret = udev_enumerate_add_nomatch_property(udev_enum, "disk-type", "memory");
+       if (ret != 0)
+               err(1, "udev_enumerate_add_match_property, out, ret=%d\n", ret);
+#endif
+
+       ret = udev_enumerate_scan_devices(udev_enum);
+       if (ret != 0)
+               err(1, "udev_enumerate_scan_device ret = %d", ret);
+
+       udev_le_first = udev_enumerate_get_list_entry(udev_enum);
+       if (udev_le_first == NULL)
+               err(1, "udev_enumerate_get_list_entry error");
+
+       udev_list_entry_foreach(udev_le, udev_le_first) {
+               udev_dev = udev_list_entry_get_device(udev_le);
+               dev_path = udev_device_get_devnode(udev_dev);
+#if 0
+               dict = udev_device_get_dictionary(udev_dev);
+               printf("xml of new device: %s\n", prop_dictionary_externalize(dict));
+#endif
+               fsid_check_create_alias(dev_path);
+       }
+
+       udev_enumerate_unref(udev_enum);
+
+       if (daemon_flag) {
+#if 0
+               if (daemon(0, 0) == -1)
+                       err(1, "daemon");
+#endif
+
+               udev_monitor = udev_monitor_new(udev);
+               ret = udev_monitor_filter_add_match_property(udev_monitor, "subsystem", "disk");
+               if (ret != 0)
+                       err(1, "udev_monitor_filter_add_match_property, out, ret=%d\n", ret);
+
+               ret = udev_monitor_filter_add_match_property(udev_monitor, "alias", "0");
+               if (ret != 0)
+                       err(1, "udev_monitor_filter_add_match_property, out, ret=%d\n", ret);
+
+               ret = udev_monitor_filter_add_nomatch_property(udev_monitor, "disk-type", "memory");
+               if (ret != 0)
+                       err(1, "udev_monitor_filter_add_nomatch_property, out, ret=%d\n", ret);
+
+               ret = udev_monitor_enable_receiving(udev_monitor);
+               if (ret != 0)
+                       err(1, "udev_monitor_enable_receiving ret = %d", ret);
+
+               while ((udev_dev = udev_monitor_receive_device(udev_monitor))) {
+                       if (udev_dev == NULL)
+                               err(1, "udev_monitor_receive_device failed");
+
+                       dev_path = udev_device_get_devnode(udev_dev);
+                       prop = udev_device_get_action(udev_dev);
+
+                       if (strcmp(prop, "attach") == 0)
+                               fsid_check_create_alias(dev_path);
+                       else if (strcmp(prop, "detach") == 0)
+                               fsid_check_remove_alias(dev_path);
+               }
+
+               udev_monitor_unref(udev_monitor);
+       }
+
+       udev_unref(udev);
+
+       return 0;
+}
+
diff --git a/sbin/fsid/fsid.h b/sbin/fsid/fsid.h
new file mode 100644 (file)
index 0000000..8022abc
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2010 The DragonFly Project.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Alex Hornung <ahornung@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/uio.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+typedef int (probe_func_t)(const char *);
+typedef char *(volname_func_t)(const char *);
+
+struct fs_type {
+       const char *fs_name;
+       probe_func_t    *fs_probe;
+       volname_func_t  *fs_volname;
+};
+
+struct fsid_entry {
+       char    *dev_path;
+       char    *link_path;
+
+       TAILQ_ENTRY(fsid_entry)         link;
+};
+
+TAILQ_HEAD(fsid_head, fsid_entry);
+
+probe_func_t hammer_probe;
+probe_func_t ufs_probe;
+volname_func_t hammer_volname;
+volname_func_t ufs_volname;
+
diff --git a/sbin/fsid/hammer.c b/sbin/fsid/hammer.c
new file mode 100644 (file)
index 0000000..9c9943f
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2010 The DragonFly Project.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Alex Hornung <ahornung@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "fsid.h"
+#include <vfs/hammer/hammer_disk.h>
+
+static char buffer[16384];
+
+int
+hammer_probe(const char *dev)
+{
+       static struct hammer_volume_ondisk *fs;
+       int ret, fd;
+
+       fd = open(dev, O_RDONLY);
+       if (fd < 0) {
+               perror("open in hammer_probe failed");
+               return 0;
+       }
+
+       ret = read(fd, &buffer, sizeof(buffer));
+       if (ret < 0) {
+               close(fd);
+               perror("read in hammer_probe failed");
+               return 0;
+       }
+
+       close(fd);
+       fs = (struct hammer_volume_ondisk *)&buffer;
+
+       if (fs->vol_signature != HAMMER_FSBUF_VOLUME) {
+               return 0;
+       }
+
+       return 1;
+}
+
+char *
+hammer_volname(const char *dev)
+{
+       static struct hammer_volume_ondisk *fs;
+       int ret, fd;
+
+       fd = open(dev, O_RDONLY);
+       if (fd < 0) {
+               perror("open in hammer_volname failed");
+               return NULL;
+       }
+
+       ret = read(fd, &buffer, sizeof(buffer));
+       if (ret < 0) {
+               close(fd);
+               perror("read in hammer_volname failed");
+               return NULL;
+       }
+
+       close(fd);
+       fs = (struct hammer_volume_ondisk *)&buffer;
+
+       if (fs->vol_signature != HAMMER_FSBUF_VOLUME) {
+               return NULL;
+       }
+
+       if (fs->vol_name[0] == '\0')
+               return NULL;
+
+       fs->vol_name[63] = '\0';
+       return fs->vol_name;
+}
+
diff --git a/sbin/fsid/ufs.c b/sbin/fsid/ufs.c
new file mode 100644 (file)
index 0000000..3e85b8a
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2010 The DragonFly Project.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Alex Hornung <ahornung@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "fsid.h"
+#include <vfs/ufs/ufs_types.h>
+#include <vfs/ufs/fs.h>
+
+static char buffer[MAXBSIZE];
+
+int
+ufs_probe(const char *dev)
+{
+       static struct fs *fs;
+       int ret, fd;
+
+       fd = open(dev, O_RDONLY);
+       if (fd < 0) {
+               return 0;
+       }
+
+       ret = lseek(fd, SBOFF, SEEK_SET);
+       if (ret < 0)
+               return 0;
+
+       ret = read(fd, &buffer, SBSIZE);
+       if (ret < 0) {
+               close(fd);
+               return 0;
+       }
+
+       close(fd);
+       fs = (struct fs *)&buffer;
+
+       if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
+               (unsigned)fs->fs_bsize < sizeof(struct fs)) {
+               return 0;
+       }
+
+       return 1;
+}
+
+char *
+ufs_volname(const char *dev)
+{
+       static struct fs *fs;
+       int ret, fd;
+
+       fd = open(dev, O_RDONLY);
+       if (fd < 0) {
+               return NULL;
+       }
+
+       ret = lseek(fd, SBOFF, SEEK_SET);
+       if (ret < 0)
+               return NULL;
+
+       ret = read(fd, &buffer, SBSIZE);
+       if (ret < 0) {
+               close(fd);
+               return NULL;
+       }
+
+       close(fd);
+       fs = (struct fs *)&buffer;
+
+       if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
+               (unsigned)fs->fs_bsize < sizeof(struct fs)) {
+               return NULL;
+       }
+
+       if (fs->fs_volname[0] == '\0')
+               return NULL;
+
+       fs->fs_volname[MAXVOLLEN - 1] = '\0';
+       return fs->fs_volname;
+}
+