]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - util.c
Avoid possible null dereference in Assemble.
[thirdparty/mdadm.git] / util.c
diff --git a/util.c b/util.c
index dd8b176ab43558f6f47fc15520bcc8cde206ced8..108f3c168d2414aa1e0473d7d0042a1933935584 100644 (file)
--- a/util.c
+++ b/util.c
@@ -730,7 +730,7 @@ struct supertype *super_by_fd(int fd)
        int minor;
        struct supertype *st = NULL;
        struct mdinfo *sra;
-       char *verstr = NULL;
+       char *verstr;
        char version[20];
        int i;
 
@@ -739,11 +739,13 @@ struct supertype *super_by_fd(int fd)
        if (sra) {
                vers = sra->array.major_version;
                minor = sra->array.minor_version;
+               verstr = sra->text_version;
        } else {
                if (ioctl(fd, GET_ARRAY_INFO, &array))
                        array.major_version = array.minor_version = 0;
                vers = array.major_version;
                minor = array.minor_version;
+               verstr = "";
        }
 
        if (vers != -1) {
@@ -816,7 +818,7 @@ struct supertype *guess_super(int fd)
                st->ss = NULL;
                rv = superlist[bestsuper]->load_super(st, fd, NULL);
                if (rv == 0) {
-                       ss->free_super(st);
+                       superlist[bestsuper]->free_super(st);
                        return st;
                }
        }
@@ -828,6 +830,11 @@ struct supertype *guess_super(int fd)
 int get_dev_size(int fd, char *dname, unsigned long long *sizep)
 {
        unsigned long long ldsize;
+       struct stat st;
+
+       if (fstat(fd, &st) != -1 && S_ISREG(st.st_mode))
+               ldsize = (unsigned long long)st.st_size;
+       else
 #ifdef BLKGETSIZE64
        if (ioctl(fd, BLKGETSIZE64, &ldsize) != 0)
 #endif
@@ -855,6 +862,46 @@ void get_one_disk(int mdfd, mdu_array_info_t *ainf, mdu_disk_info_t *disk)
                if (ioctl(mdfd, GET_DISK_INFO, disk) == 0)
                        return;
 }
+
+static int dev2major(int d)
+{
+       if (d >= 0)
+               return MD_MAJOR;
+       else
+               return get_mdp_major();
+}
+
+static int dev2minor(int d)
+{
+       if (d >= 0)
+               return d;
+       return (-1-d) << MdpMinorShift;
+}
+
+int find_free_devnum(int use_partitions)
+{
+       int devnum;
+       for (devnum = 127; devnum != 128;
+            devnum = devnum ? devnum-1 : (1<<22)-1) {
+               char *dn;
+               int _devnum;
+
+               _devnum = use_partitions ? (-1-devnum) : devnum;
+               if (mddev_busy(_devnum))
+                       continue;
+               /* make sure it is new to /dev too, at least as a
+                * non-standard */
+               dn = map_dev(dev2major(_devnum), dev2minor(_devnum), 0);
+               if (dn && ! is_standard(dn, NULL))
+                       continue;
+               break;
+       }
+       if (devnum == 128)
+               return NoMdDev;
+       return use_partitions ? (-1-devnum) : devnum;
+}
+
+
 #ifdef __TINYC__
 /* tinyc doesn't optimize this check in ioctl.h out ... */
 unsigned int __invalid_size_argument_for_IOC = 0;