Whamcloud - gitweb
ChangeLog, Makefile.in, ext2fs.h, finddev.c:
authorTheodore Ts'o <tytso@mit.edu>
Sat, 19 Aug 2000 17:00:47 +0000 (17:00 +0000)
committerTheodore Ts'o <tytso@mit.edu>
Sat, 19 Aug 2000 17:00:47 +0000 (17:00 +0000)
  finddev.c, ext2fs.h, Makefile.in: Add new file, finddev.c, which
   provides the function ext2fs_find_block_device().  This function
   returns the pathname to a block device, given its device number.

lib/ext2fs/ChangeLog
lib/ext2fs/Makefile.in
lib/ext2fs/ext2fs.h
lib/ext2fs/finddev.c [new file with mode: 0644]

index 9a088dc..33ce94c 100644 (file)
@@ -1,3 +1,10 @@
+2000-08-19    <tytso@valinux.com>
+
+       * finddev.c, ext2fs.h, Makefile.in: Add new file, finddev.c, which
+               provides the function ext2fs_find_block_device().  This
+               function returns the pathname to a block device, given its
+               device number.
+
 2000-07-13    <tytso@valinux.com>
 
        * Release of E2fsprogs 1.19
index 7854159..428a1ee 100644 (file)
@@ -27,6 +27,7 @@ OBJS= ext2_err.o \
        dupfs.o \
        expanddir.o \
        fileio.o \
+       finddev.o \
        freefs.o \
        get_pathname.o \
        getsize.o \
@@ -75,6 +76,7 @@ SRCS= ext2_err.c \
        $(srcdir)/dupfs.c \
        $(srcdir)/expanddir.c \
        $(srcdir)/fileio.c \
+       $(srcidr)/finddev.c \
        $(srcdir)/freefs.c \
        $(srcdir)/get_pathname.c \
        $(srcdir)/getsize.c \
index ff1cb9c..7c15c4b 100644 (file)
@@ -708,6 +708,9 @@ extern errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset,
 extern ext2_off_t ext2fs_file_get_size(ext2_file_t file);
 extern errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size);
 
+/* finddev.c */
+extern char *ext2fs_find_block_device(dev_t device);
+
 /* freefs.c */
 extern void ext2fs_free(ext2_filsys fs);
 extern void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap);
diff --git a/lib/ext2fs/finddev.c b/lib/ext2fs/finddev.c
new file mode 100644 (file)
index 0000000..940108e
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * finddev.c -- this routine attempts to find a particular device in
+ *     /dev
+ * 
+ * Copyright (C) 2000 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#include <dirent.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#if HAVE_SYS_MKDEV_H
+#include <sys/mkdev.h>
+#endif
+
+struct dir_list {
+       char    *name;
+       struct dir_list *next;
+};
+
+#ifdef sun
+#define DEVDIR "/devices"
+#else
+#define DEVDIR "/dev"
+#endif
+
+/*
+ * This function adds an entry to the directory list
+ */
+static void add_to_dirlist(char *name, struct dir_list **list)
+{
+       struct dir_list *dp;
+
+       dp = malloc(sizeof(struct dir_list));
+       if (!dp)
+               return;
+       dp->name = malloc(strlen(name)+1);
+       if (!dp->name) {
+               free(dp);
+               return;
+       }
+       strcpy(dp->name, name);
+       dp->next = *list;
+       *list = dp;
+}
+
+/*
+ * This function frees a directory list
+ */
+static void free_dirlist(struct dir_list **list)
+{
+       struct dir_list *dp, *next;
+
+       for (dp = *list; dp; dp = next) {
+               next = dp->next;
+               free(dp->name);
+               free(dp);
+       }
+       *list = 0;
+}
+
+static int scan_dir(char *dirname, dev_t device, struct dir_list **list,
+                   char **ret_path)
+{
+       DIR     *dir;
+       struct dirent *dp;
+       char    path[1024], *cp;
+       int     dirlen;
+       struct stat st;
+
+       dirlen = strlen(dirname);
+       if ((dir = opendir(dirname)) == NULL)
+               return errno;
+       dp = readdir(dir);
+       while (dp) {
+               if (dirlen + strlen(dp->d_name) + 2 >= sizeof(path))
+                       goto skip_to_next;
+               if (dp->d_name[0] == '.' &&
+                   ((dp->d_name[1] == 0) ||
+                    (dp->d_name[1] == '.') && (dp->d_name[2] == 0)))
+                       goto skip_to_next;
+               sprintf(path, "%s/%s", dirname, dp->d_name);
+               if (stat(path, &st) < 0)
+                       continue;
+               if (S_ISDIR(st.st_mode))
+                       add_to_dirlist(path, list);
+               if (S_ISBLK(st.st_mode) && st.st_rdev == device) {
+                       cp = malloc(strlen(path)+1);
+                       if (!cp)
+                               return ENOMEM;
+                       strcpy(cp, path);
+                       *ret_path = cp;
+                       return 0;
+               }
+       skip_to_next:
+               dp = readdir(dir);
+       }
+       closedir(dir);
+       return 0;
+}
+
+/*
+ * This function finds the pathname to a block device with a given
+ * device number.  It returns a pointer to allocated memory to the
+ * pathname on success, and NULL on failure.
+ */
+char *ext2fs_find_block_device(dev_t device)
+{
+       struct dir_list *list = 0, *new_list = 0;
+       struct dir_list *current;
+       char    *ret_path = 0;
+
+       /*
+        * Add the starting directories to search...
+        */
+       add_to_dirlist("/devices", &list);
+       add_to_dirlist("/devfs", &list);
+       add_to_dirlist("/dev", &list);
+       
+       while (list) {
+               current = list;
+               list = list->next;
+#ifdef DEBUG
+               printf("Scanning directory %s\n", current->name);
+#endif
+               scan_dir(current->name, device, &new_list, &ret_path);
+               free(current->name);
+               free(current);
+               if (ret_path)
+                       break;
+               /*
+                * If we're done checking at this level, descend to
+                * the next level of subdirectories. (breadth-first)
+                */
+               if (list == 0) {
+                       list = new_list;
+                       new_list = 0;
+               }
+       }
+found_it:
+       free_dirlist(&list);
+       free_dirlist(&new_list);
+       return ret_path;
+}
+
+       
+#ifdef DEBUG
+int main(int argc, char** argv)
+{
+       char    *devname, *tmp;
+       int     major, minor;
+       dev_t   device;
+       const char *errmsg = "Couldn't parse %s: %s\n";
+
+       if ((argc != 2) && (argc != 3)) {
+               fprintf(stderr, "Usage: %s device_number\n", argv[0]);
+               fprintf(stderr, "\t: %s major minor\n", argv[0]);
+               exit(1);
+       }
+       if (argc == 2) {
+               device = strtoul(argv[1], &tmp, 0);
+               if (*tmp) {
+                       fprintf(stderr, errmsg, "device number", argv[1]);
+                       exit(1);
+               }
+       } else {
+               major = strtoul(argv[1], &tmp, 0);
+               if (*tmp) {
+                       fprintf(stderr, errmsg, "major number", argv[1]);
+                       exit(1);
+               }
+               minor = strtoul(argv[2], &tmp, 0);
+               if (*tmp) {
+                       fprintf(stderr, errmsg, "minor number", argv[2]);
+                       exit(1);
+               }
+               device = makedev(major, minor);
+               printf("Looking for device 0x%04x (%d:%d)\n", device,
+                      major, minor);
+       }
+       devname = ext2fs_find_block_device(device);
+       if (devname) {
+               printf("Found device!  %s\n", devname);
+               free(devname);
+       } else {
+               printf("Couldn't find device.\n");
+       }
+       return 0;
+}
+       
+#endif