]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - util.c
Stop map_dev from returning [0:0]
[thirdparty/mdadm.git] / util.c
diff --git a/util.c b/util.c
index 873deba67eacdb434e7a5c272d1182ddebc5f3ef..2cb6dd316f8e173ab913e54a778e96110a450524 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1,7 +1,7 @@
 /*
  * mdadm - manage Linux "md" devices aka RAID arrays.
  *
- * Copyright (C) 2001-2002 Neil Brown <neilb@cse.unsw.edu.au>
+ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
  *
  *
  *    This program is free software; you can redistribute it and/or modify
@@ -357,6 +357,7 @@ int devlist_ready = 0;
 #ifdef UCLIBC
 int add_dev(const char *name, const struct stat *stb, int flag, struct FTW *s)
 {
+       return 0;
 }
 char *map_dev(int major, int minor, int create)
 {
@@ -375,26 +376,32 @@ int add_dev_1(const char *name, const struct stat *stb, int flag)
 }
 int nftw(const char *path, int (*han)(const char *name, const struct stat *stb, int flag, struct FTW *s), int nopenfd, int flags)
 {
-       ftw(path, add_dev_1, nopenfd);
+       return ftw(path, add_dev_1, nopenfd);
 }
 #endif
 
 int add_dev(const char *name, const struct stat *stb, int flag, struct FTW *s)
 {
-    if ((stb->st_mode&S_IFMT)== S_IFBLK) {
-       char *n = strdup(name);
-       struct devmap *dm = malloc(sizeof(*dm));
-       if (strncmp(n, "/dev/.", 6)==0)
-               strcpy(n+4, name+6);
-       if (dm) {
-           dm->major = major(stb->st_rdev);
-           dm->minor = minor(stb->st_rdev);
-           dm->name = n;
-           dm->next = devlist;
-           devlist = dm;
+       struct stat st;
+       if (S_ISLNK(stb->st_mode)) {
+               stat(name, &st);
+               stb = &st;
        }
-    }
-    return 0;
+
+       if ((stb->st_mode&S_IFMT)== S_IFBLK) {
+               char *n = strdup(name);
+               struct devmap *dm = malloc(sizeof(*dm));
+               if (strncmp(n, "/dev/./", 7)==0)
+                       strcpy(n+4, name+6);
+               if (dm) {
+                       dm->major = major(stb->st_rdev);
+                       dm->minor = minor(stb->st_rdev);
+                       dm->name = n;
+                       dm->next = devlist;
+                       devlist = dm;
+               }
+       }
+       return 0;
 }
 
 /*
@@ -408,14 +415,27 @@ char *map_dev(int major, int minor, int create)
 {
        struct devmap *p;
        char *std = NULL, *nonstd=NULL;
+       int did_check = 0;
+
+       if (major == 0 && minor == 0)
+                       return NULL;
+
+ retry:
        if (!devlist_ready) {
                char *dev = "/dev";
                struct stat stb;
+               while(devlist) {
+                       struct devmap *d = devlist;
+                       devlist = d->next;
+                       free(d->name);
+                       free(d);
+               }
                if (lstat(dev, &stb)==0 &&
                    S_ISLNK(stb.st_mode))
                        dev = "/dev/.";
                nftw(dev, add_dev, 10, FTW_PHYS);
                devlist_ready=1;
+               did_check = 1;
        }
 
        for (p=devlist; p; p=p->next)
@@ -431,9 +451,13 @@ char *map_dev(int major, int minor, int create)
                                        nonstd = p->name;
                        }
                }
+       if (!std && !nonstd && !did_check) {
+               devlist_ready = 0;
+               goto retry;
+       }
        if (create && !std && !nonstd) {
                static char buf[30];
-               snprintf(buf, 1024, "%d:%d", major, minor);
+               snprintf(buf, sizeof(buf), "%d:%d", major, minor);
                nonstd = buf;
        }
 
@@ -609,8 +633,12 @@ int dev_open(char *dev, int flags)
        char *e;
        int fd = -1;
        char devname[32];
-       int major = strtoul(dev, &e, 0);
+       int major;
        int minor;
+
+       if (!dev) return -1;
+
+       major = strtoul(dev, &e, 0);
        if (e > dev && *e == ':' && e[1] &&
            (minor = strtoul(e+1, &e, 0)) >= 0 &&
            *e == 0) {