]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - util.c
Handles spaces in array names better.
[thirdparty/mdadm.git] / util.c
diff --git a/util.c b/util.c
index ad3c1502fcdbaccc654cc09b7b2a90460e2c1d6b..fad72cc951ecad77ce17a44f4575420452d5b4ee 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1,7 +1,7 @@
 /*
  * mdadm - manage Linux "md" devices aka RAID arrays.
  *
- * Copyright (C) 2001-2009 Neil Brown <neilb@suse.de>
+ * Copyright (C) 2001-2012 Neil Brown <neilb@suse.de>
  *
  *
  *    This program is free software; you can redistribute it and/or modify
@@ -89,15 +89,16 @@ int parse_uuid(char *str, int uuid[4])
        int hit = 0; /* number of Hex digIT */
        int i;
        char c;
-       for (i=0; i<4; i++) uuid[i]=0;
+       for (i = 0; i < 4; i++)
+               uuid[i] = 0;
 
-       while ((c= *str++)) {
+       while ((c = *str++) != 0) {
                int n;
-               if (c>='0' && c<='9')
+               if (c >= '0' && c <= '9')
                        n = c-'0';
-               else if (c>='a' && c <= 'f')
+               else if (c >= 'a' && c <= 'f')
                        n = 10 + c - 'a';
-               else if (c>='A' && c <= 'F')
+               else if (c >= 'A' && c <= 'F')
                        n = 10 + c - 'A';
                else if (strchr(":. -", c))
                        continue;
@@ -114,7 +115,6 @@ int parse_uuid(char *str, int uuid[4])
        return 0;
 }
 
-
 /*
  * Get the md version number.
  * We use the RAID_VERSION ioctl if it is supported
@@ -188,13 +188,13 @@ int mdadm_version(char *version)
        return (a*1000000)+(b*1000)+c;
 }
 
-long long parse_size(char *size)
+unsigned long long parse_size(char *size)
 {
        /* parse 'size' which should be a number optionally
         * followed by 'K', 'M', or 'G'.
         * Without a suffix, K is assumed.
         * Number returned is in sectors (half-K)
-        * -1 returned on error.
+        * 0 returned on error.
         */
        char *c;
        long long s = strtoll(size, &c, 10);
@@ -214,9 +214,10 @@ long long parse_size(char *size)
                        s *= 1024 * 1024 * 2;
                        break;
                }
-       }
+       } else
+               s = 0;
        if (*c)
-               s = -1;
+               s = 0;
        return s;
 }
 
@@ -280,7 +281,7 @@ void remove_partitions(int fd)
        a.datalen = sizeof(p);
        a.flags = 0;
        memset(a.data, 0, a.datalen);
-       for (p.pno=0; p.pno < 16; p.pno++)
+       for (p.pno = 0; p.pno < 16; p.pno++)
                ioctl(fd, BLKPG, &a);
 #endif
 }
@@ -338,19 +339,20 @@ int enough(int level, int raid_disks, int layout, int clean, char *avail)
                 * which actual disks are present.
                 */
                copies = (layout&255)* ((layout>>8) & 255);
-               first=0;
+               first = 0;
                do {
                        /* there must be one of the 'copies' form 'first' */
                        int n = copies;
-                       int cnt=0;
+                       int cnt = 0;
+                       int this = first;
                        while (n--) {
-                               if (avail[first])
+                               if (avail[this])
                                        cnt++;
-                               first = (first+1) % raid_disks;
+                               this = (this+1) % raid_disks;
                        }
                        if (cnt == 0)
                                return 0;
-
+                       first = (first+(layout&255)) % raid_disks;
                } while (first != 0);
                return 1;
 
@@ -389,7 +391,7 @@ int enough_fd(int fd)
            array.raid_disks <= 0)
                return 0;
        avail = xcalloc(array.raid_disks, 1);
-       for (i=0; i < MAX_DISKS && array.nr_disks > 0; i++) {
+       for (i = 0; i < MAX_DISKS && array.nr_disks > 0; i++) {
                disk.number = i;
                if (ioctl(fd, GET_DISK_INFO, &disk) != 0)
                        continue;
@@ -411,7 +413,6 @@ int enough_fd(int fd)
        return rv;
 }
 
-
 const int uuid_zero[4] = { 0, 0, 0, 0 };
 
 int same_uuid(int a[4], int b[4], int swapuuid)
@@ -424,7 +425,7 @@ int same_uuid(int a[4], int b[4], int swapuuid)
                unsigned char *ac = (unsigned char *)a;
                unsigned char *bc = (unsigned char *)b;
                int i;
-               for (i=0; i<16; i+= 4) {
+               for (i = 0; i < 16; i += 4) {
                        if (ac[i+0] != bc[i+3] ||
                            ac[i+1] != bc[i+2] ||
                            ac[i+2] != bc[i+1] ||
@@ -441,6 +442,7 @@ int same_uuid(int a[4], int b[4], int swapuuid)
                return 0;
        }
 }
+
 void copy_uuid(void *a, int b[4], int swapuuid)
 {
        if (swapuuid) {
@@ -451,7 +453,7 @@ void copy_uuid(void *a, int b[4], int swapuuid)
                unsigned char *ac = (unsigned char *)a;
                unsigned char *bc = (unsigned char *)b;
                int i;
-               for (i=0; i<16; i+= 4) {
+               for (i = 0; i < 16; i += 4) {
                        ac[i+0] = bc[i+3];
                        ac[i+1] = bc[i+2];
                        ac[i+2] = bc[i+1];
@@ -537,8 +539,8 @@ int check_reiser(int fd, char *name)
                return 0;
        if (read(fd, sb, 1024) != 1024)
                return 0;
-       if (strncmp((char*)sb+52, "ReIsErFs",8)!=0 &&
-           strncmp((char*)sb+52, "ReIsEr2Fs",9)!=0)
+       if (strncmp((char*)sb+52, "ReIsErFs",8) != 0 &&
+           strncmp((char*)sb+52, "ReIsEr2Fs",9) != 0)
                return 0;
        pr_err("%s appears to contain a reiserfs file system\n",name);
        size = sb[0]|(sb[1]|(sb[2]|sb[3]<<8)<<8)<<8;
@@ -574,7 +576,7 @@ int ask(char *mesg)
 {
        char *add = "";
        int i;
-       for (i=0; i<5; i++) {
+       for (i = 0; i < 5; i++) {
                char buf[100];
                fprintf(stderr, "%s%s", mesg, add);
                fflush(stderr);
@@ -601,18 +603,18 @@ int is_standard(char *dev, int *nump)
         *   0 if not a standard name.
         */
        char *d = strrchr(dev, '/');
-       int type=0;
+       int type = 0;
        int num;
        if (!d)
                return 0;
-       if (strncmp(d, "/d",2)==0)
-               d += 2, type=1; /* /dev/md/dN{pM} */
-       else if (strncmp(d, "/md_d", 5)==0)
-               d += 5, type=1; /* /dev/md_dN{pM} */
-       else if (strncmp(d, "/md", 3)==0)
-               d += 3, type=-1; /* /dev/mdN */
-       else if (d-dev > 3 && strncmp(d-2, "md/", 3)==0)
-               d += 1, type=-1; /* /dev/md/N */
+       if (strncmp(d, "/d",2) == 0)
+               d += 2, type = 1; /* /dev/md/dN{pM} */
+       else if (strncmp(d, "/md_d", 5) == 0)
+               d += 5, type = 1; /* /dev/md_dN{pM} */
+       else if (strncmp(d, "/md", 3) == 0)
+               d += 3, type = -1; /* /dev/mdN */
+       else if (d-dev > 3 && strncmp(d-2, "md/", 3) == 0)
+               d += 1, type = -1; /* /dev/md/N */
        else
                return 0;
        if (!*d)
@@ -634,13 +636,13 @@ unsigned long calc_csum(void *super, int bytes)
        unsigned int csum;
        unsigned int *superc = (unsigned int*) super;
 
-       for(i=0; i<bytes/4; i++)
-               newcsum+= superc[i];
+       for(i = 0; i < bytes/4; i++)
+               newcsum += superc[i];
        csum = (newcsum& 0xffffffff) + (newcsum>>32);
 #ifdef __alpha__
 /* The in-kernel checksum calculation is always 16bit on
  * the alpha, though it is 32 bit on i386...
- * I wonder what it is elsewhere... (it uses and API in
+ * I wonder what it is elsewhere... (it uses an API in
  * a way that it shouldn't).
  */
        csum = (csum & 0xffff) + (csum >> 16);
@@ -664,7 +666,7 @@ char *human_size(long long bytes)
         */
 
        if (bytes < 5000*1024)
-               buf[0]=0;
+               buf[0] = 0;
        else if (bytes < 2*1024LL*1024LL*1024LL) {
                long cMiB = (bytes / ( (1LL<<20) / 200LL ) +1) /2;
                long cMB  = (bytes / ( 1000000LL / 200LL ) +1) /2;
@@ -681,24 +683,49 @@ char *human_size(long long bytes)
        return buf;
 }
 
-char *human_size_brief(long long bytes)
+char *human_size_brief(long long bytes, int prefix)
 {
        static char buf[30];
 
+       /* We convert bytes to either centi-M{ega,ibi}bytes or
+        * centi-G{igi,ibi}bytes, with appropriate rounding,
+        * and then print 1/100th of those as a decimal.
+        * We allow upto 2048Megabytes before converting to
+        * gigabytes, as that shows more precision and isn't
+        * too large a number.
+        * Terabytes are not yet handled.
+        *
+        * If prefix == IEC, we mean prefixes like kibi,mebi,gibi etc.
+        * If prefix == JEDEC, we mean prefixes like kilo,mega,giga etc.
+        */
+
        if (bytes < 5000*1024)
-               snprintf(buf, sizeof(buf), "%ld.%02ldKiB",
-                       (long)(bytes>>10), (long)(((bytes&1023)*100+512)/1024)
-                       );
-       else if (bytes < 2*1024LL*1024LL*1024LL)
-               snprintf(buf, sizeof(buf), "%ld.%02ldMiB",
-                       (long)(bytes>>20),
-                       (long)((bytes&0xfffff)+0x100000/200)/(0x100000/100)
-                       );
+               buf[0] = 0;
+       else if (prefix == IEC) {
+               if (bytes < 2*1024LL*1024LL*1024LL) {
+                       long cMiB = (bytes / ( (1LL<<20) / 200LL ) +1) /2;
+                       snprintf(buf, sizeof(buf), "%ld.%02ldMiB",
+                               cMiB/100 , cMiB % 100);
+               } else {
+                       long cGiB = (bytes / ( (1LL<<30) / 200LL ) +1) /2;
+                       snprintf(buf, sizeof(buf), "%ld.%02ldGiB",
+                                       cGiB/100 , cGiB % 100);
+               }
+       }
+       else if (prefix == JEDEC) {
+               if (bytes < 2*1024LL*1024LL*1024LL) {
+                       long cMB  = (bytes / ( 1000000LL / 200LL ) +1) /2;
+                       snprintf(buf, sizeof(buf), "%ld.%02ldMB",
+                                       cMB/100, cMB % 100);
+               } else {
+                       long cGB  = (bytes / (1000000000LL/200LL ) +1) /2;
+                       snprintf(buf, sizeof(buf), "%ld.%02ldGB",
+                                       cGB/100 , cGB % 100);
+               }
+       }
        else
-               snprintf(buf, sizeof(buf), "%ld.%02ldGiB",
-                       (long)(bytes>>30),
-                       (long)(((bytes>>10)&0xfffff)+0x100000/200)/(0x100000/100)
-                       );
+               buf[0] = 0;
+
        return buf;
 }
 
@@ -733,11 +760,15 @@ int get_data_disks(int level, int layout, int raid_disks)
 {
        int data_disks = 0;
        switch (level) {
-       case 0: data_disks = raid_disks; break;
-       case 1: data_disks = 1; break;
+       case 0: data_disks = raid_disks;
+               break;
+       case 1: data_disks = 1;
+               break;
        case 4:
-       case 5: data_disks = raid_disks - 1; break;
-       case 6: data_disks = raid_disks - 2; break;
+       case 5: data_disks = raid_disks - 1;
+               break;
+       case 6: data_disks = raid_disks - 2;
+               break;
        case 10: data_disks = raid_disks / (layout & 255) / ((layout>>8)&255);
                break;
        }
@@ -796,7 +827,7 @@ char *get_md_name(int dev)
 
 void put_md_name(char *name)
 {
-       if (strncmp(name, "/dev/.tmp.md", 12)==0)
+       if (strncmp(name, "/dev/.tmp.md", 12) == 0)
                unlink(name);
 }
 
@@ -807,10 +838,14 @@ int find_free_devnum(int use_partitions)
             devnum = devnum ? devnum-1 : (1<<20)-1) {
                char *dn;
                int _devnum;
+               char nbuf[50];
 
                _devnum = use_partitions ? (-1-devnum) : devnum;
                if (mddev_busy(_devnum))
                        continue;
+               sprintf(nbuf, "%s%d", use_partitions?"mdp":"md", devnum);
+               if (!conf_name_is_free(nbuf))
+                       continue;
                /* make sure it is new to /dev too, at least as a
                 * non-standard */
                dn = map_dev(dev2major(_devnum), dev2minor(_devnum), 0);
@@ -848,7 +883,7 @@ int dev_open(char *dev, int flags)
                if (fd < 0) {
                        snprintf(devname, sizeof(devname), "/dev/.tmp.md.%d:%d:%d",
                                 (int)getpid(), major, minor);
-                       if (mknod(devname, S_IFBLK|0600, makedev(major, minor))==0) {
+                       if (mknod(devname, S_IFBLK|0600, makedev(major, minor)) == 0) {
                                fd = open(devname, flags);
                                unlink(devname);
                        }
@@ -856,7 +891,7 @@ int dev_open(char *dev, int flags)
                if (fd < 0) {
                        snprintf(devname, sizeof(devname), "/tmp/.tmp.md.%d:%d:%d",
                                 (int)getpid(), major, minor);
-                       if (mknod(devname, S_IFBLK|0600, makedev(major, minor))==0) {
+                       if (mknod(devname, S_IFBLK|0600, makedev(major, minor)) == 0) {
                                fd = open(devname, flags);
                                unlink(devname);
                        }
@@ -886,7 +921,7 @@ int open_dev_excl(int devnum)
        int flags = O_RDWR;
 
        sprintf(buf, "%d:%d", dev2major(devnum), dev2minor(devnum));
-       for (i=0 ; i<25 ; i++) {
+       for (i = 0 ; i < 25 ; i++) {
                int fd = dev_open(buf, flags|O_EXCL);
                if (fd >= 0)
                        return fd;
@@ -924,7 +959,7 @@ void wait_for(char *dev, int fd)
            (stb_want.st_mode & S_IFMT) != S_IFBLK)
                return;
 
-       for (i=0 ; i<25 ; i++) {
+       for (i = 0 ; i < 25 ; i++) {
                struct stat stb;
                if (stat(dev, &stb) == 0 &&
                    (stb.st_mode & S_IFMT) == S_IFBLK &&
@@ -1058,7 +1093,7 @@ struct supertype *guess_super_type(int fd, enum guess_types guess_type)
        st = xcalloc(1, sizeof(*st));
        st->container_dev = NoMdDev;
 
-       for (i=0 ; superlist[i]; i++) {
+       for (i = 0 ; superlist[i]; i++) {
                int rv;
                ss = superlist[i];
                if (guess_type == guess_array && ss->add_to_super == NULL)
@@ -1176,7 +1211,7 @@ static int get_gpt_last_partition_end(int fd, unsigned long long *endofpart)
 
        part = (struct GPT_part_entry *)buf;
 
-       for (part_nr=0; part_nr < all_partitions; part_nr++) {
+       for (part_nr = 0; part_nr < all_partitions; part_nr++) {
                /* read partition entry */
                if (read(fd, buf, entry_size) != (ssize_t)entry_size)
                        return 0;
@@ -1220,7 +1255,7 @@ static int get_last_partition_end(int fd, unsigned long long *endofpart)
                /* found the correct signature */
                part = boot_sect.parts;
 
-               for (part_nr=0; part_nr < MBR_PARTITIONS; part_nr++) {
+               for (part_nr = 0; part_nr < MBR_PARTITIONS; part_nr++) {
                        /* check for GPT type */
                        if (part->part_type == MBR_GPT_PARTITION_TYPE) {
                                retval = get_gpt_last_partition_end(fd, endofpart);
@@ -1598,7 +1633,7 @@ int start_mdmon(int devnum)
 {
        int i, skipped;
        int len;
-       pid_t pid;      
+       pid_t pid;
        int status;
        char pathbuf[1024];
        char *paths[4] = {
@@ -1628,13 +1663,13 @@ int start_mdmon(int devnum)
        case 0:
                /* FIXME yuk. CLOSE_EXEC?? */
                skipped = 0;
-               for (i=3; skipped < 20; i++)
+               for (i = 3; skipped < 20; i++)
                        if (close(i) < 0)
                                skipped++;
                        else
                                skipped = 0;
 
-               for (i=0; paths[i]; i++)
+               for (i = 0; paths[i]; i++)
                        if (paths[i][0]) {
                                if (__offroot) {
                                        execl(paths[i], "mdmon", "--offroot",
@@ -1800,42 +1835,23 @@ struct mdinfo *container_choose_spares(struct supertype *st,
        return disks;
 }
 
-void *xmalloc(size_t len)
-{
-       void *rv = malloc(len);
-       char *msg;
-       if (rv)
-               return rv;
-       msg = Name ": memory allocation failure - aborting\n";
-       exit(4+!!write(2, msg, strlen(msg)));
-}
-
-void *xrealloc(void *ptr, size_t len)
-{
-       void *rv = realloc(ptr, len);
-       char *msg;
-       if (rv)
-               return rv;
-       msg = Name ": memory allocation failure - aborting\n";
-       exit(4+!!write(2, msg, strlen(msg)));
-}
-
-void *xcalloc(size_t num, size_t size)
+/* Checks if paths point to the same device
+ * Returns 0 if they do.
+ * Returns 1 if they don't.
+ * Returns -1 if something went wrong,
+ * e.g. paths are empty or the files
+ * they point to don't exist */
+int compare_paths (char* path1, char* path2)
 {
-       void *rv = calloc(num, size);
-       char *msg;
-       if (rv)
-               return rv;
-       msg = Name ": memory allocation failure - aborting\n";
-       exit(4+!!write(2, msg, strlen(msg)));
-}
+       struct stat st1,st2;
 
-char *xstrdup(const char *str)
-{
-       char *rv = strdup(str);
-       char *msg;
-       if (rv)
-               return rv;
-       msg = Name ": memory allocation failure - aborting\n";
-       exit(4+!!write(2, msg, strlen(msg)));
+       if (path1 == NULL || path2 == NULL)
+               return -1;
+       if (stat(path1,&st1) != 0)
+               return -1;
+       if (stat(path2,&st2) != 0)
+               return -1;
+       if ((st1.st_ino == st2.st_ino) && (st1.st_dev == st2.st_dev))
+               return 0;
+       return 1;
 }