]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blobdiff - src/nash/mount_by_label.c
GD-Graph fuer Maniac eingebaut
[people/pmueller/ipfire-2.x.git] / src / nash / mount_by_label.c
index 75ff9be4df611ee4983e109a84c07f89cdd03358..cf3c1f591eb00e12e5db57424b155681e9bc1b70 100644 (file)
-/*\r
- * taken from util-linux 2.11g and hacked into nash\r
- *\r
- * mount_by_label.c - aeb\r
- *\r
- * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>\r
- * - added Native Language Support\r
- * 2000-01-20 James Antill <james@and.org>\r
- * - Added error message if /proc/partitions cannot be opened\r
- * 2000-05-09 Erik Troan <ewt@redhat.com>\r
- * - Added cache for UUID and disk labels\r
- * 2000-11-07 Nathan Scott <nathans@sgi.com>\r
- * - Added XFS support\r
- */\r
-\r
-#include <errno.h>\r
-#include <stdio.h>\r
-#include <string.h>\r
-#include <ctype.h>\r
-#include <fcntl.h>\r
-#include <stdlib.h>\r
-#include <unistd.h>\r
-#include <sys/stat.h>\r
-#include "linux_fs.h"\r
-#include "mount_by_label.h"\r
-\r
-#define PROC_PARTITIONS "/proc/partitions"\r
-#define DEVLABELDIR    "/dev"\r
-\r
-#define _(str) (str)\r
-\r
-static struct uuidCache_s {\r
-       struct uuidCache_s *next;\r
-       char uuid[16];\r
-       char *device;\r
-       char *label;\r
-       int major, minor;\r
-} *uuidCache = NULL;\r
-\r
-/* for now, only ext2, ext3 and xfs are supported */\r
-static int\r
-get_label_uuid(const char *device, char **label, char *uuid) {\r
-\r
-       /* start with ext2/3 and xfs tests, taken from mount_guess_fstype */\r
-       /* should merge these later */\r
-       int fd;\r
-       int rv = 1;\r
-       size_t namesize;\r
-       struct ext2_super_block e2sb;\r
-       struct xfs_super_block xfsb;\r
-\r
-       fd = open(device, O_RDONLY);\r
-       if (fd < 0)\r
-               return rv;\r
-\r
-       if (lseek(fd, 1024, SEEK_SET) == 1024\r
-           && read(fd, (char *) &e2sb, sizeof(e2sb)) == sizeof(e2sb)\r
-           && (ext2magic(e2sb) == EXT2_SUPER_MAGIC)) {\r
-               memcpy(uuid, e2sb.s_uuid, sizeof(e2sb.s_uuid));\r
-               namesize = sizeof(e2sb.s_volume_name);\r
-               if ((*label = calloc(namesize + 1, 1)) != NULL)\r
-                       memcpy(*label, e2sb.s_volume_name, namesize);\r
-               rv = 0;\r
-       }\r
-       else if (lseek(fd, 0, SEEK_SET) == 0\r
-           && read(fd, (char *) &xfsb, sizeof(xfsb)) == sizeof(xfsb)\r
-           && (strncmp(xfsb.s_magic, XFS_SUPER_MAGIC, 4) == 0)) {\r
-               memcpy(uuid, xfsb.s_uuid, sizeof(xfsb.s_uuid));\r
-               namesize = sizeof(xfsb.s_fname);\r
-               if ((*label = calloc(namesize + 1, 1)) != NULL)\r
-                       memcpy(*label, xfsb.s_fname, namesize);\r
-               rv = 0;\r
-       }\r
-\r
-       close(fd);\r
-       return rv;\r
-}\r
-\r
-static void\r
-uuidcache_addentry(char * device, int major, int minor, char *label, char *uuid) {\r
-       struct uuidCache_s *last;\r
-    \r
-       if (!uuidCache) {\r
-               last = uuidCache = malloc(sizeof(*uuidCache));\r
-       } else {\r
-               for (last = uuidCache; last->next; last = last->next) ;\r
-               last->next = malloc(sizeof(*uuidCache));\r
-               last = last->next;\r
-       }\r
-       last->next = NULL;\r
-       last->label = label;\r
-       last->device = device;\r
-       last->major = major;\r
-       last->minor = minor;\r
-       memcpy(last->uuid, uuid, sizeof(last->uuid));\r
-}\r
-\r
-static void\r
-uuidcache_init(void) {\r
-       char line[100];\r
-       char *s;\r
-       int ma, mi, sz;\r
-       static char ptname[100];\r
-       FILE *procpt;\r
-       char uuid[16], *label;\r
-       char device[110];\r
-       int firstPass;\r
-       int handleOnFirst;\r
-       char * chptr, * endptr;\r
-\r
-       if (uuidCache)\r
-               return;\r
-\r
-       procpt = fopen(PROC_PARTITIONS, "r");\r
-       if (!procpt) {\r
-               static int warn = 0;\r
-               if (!warn++)\r
-                   fprintf (stderr, _("mount: could not open %s, so UUID and LABEL "\r
-                            "conversion cannot be done.\n"),\r
-                      PROC_PARTITIONS);\r
-               return;\r
-       }\r
-\r
-       for (firstPass = 1; firstPass >= 0; firstPass--) {\r
-           fseek(procpt, 0, SEEK_SET);\r
-\r
-           while (fgets(line, sizeof(line), procpt)) {\r
-               /* The original version of this code used sscanf, but\r
-                  diet's sscanf is quite limited */\r
-               chptr = line;\r
-               if (*chptr++ != ' ') continue;\r
-\r
-               ma = strtol(chptr, &endptr, 0);\r
-               if (endptr == chptr) continue;\r
-               while (isspace(*endptr)) endptr++;\r
-               chptr = endptr;\r
-\r
-               mi = strtol(chptr, &endptr, 0);\r
-               if (endptr == chptr) continue;\r
-               while (isspace(*endptr)) endptr++;\r
-               chptr = endptr;\r
-\r
-               sz = strtol(chptr, &endptr, 0);\r
-               if (endptr == chptr) continue;\r
-               while (isspace(*endptr)) endptr++;\r
-               chptr = endptr;\r
-\r
-               while (!isspace(*endptr) && *endptr != '\n') endptr++;\r
-               if (chptr == endptr) continue;\r
-               strncpy(ptname, chptr, endptr - chptr);\r
-               ptname[endptr - chptr] = '\0';\r
-\r
-               /* skip extended partitions (heuristic: size 1) */\r
-               if (sz == 1)\r
-                       continue;\r
-\r
-               /* look only at md devices on first pass */\r
-               handleOnFirst = !strncmp(ptname, "md", 2);\r
-               if (firstPass != handleOnFirst)\r
-                       continue;\r
-\r
-               /* skip entire disk (minor 0, 64, ... on ide;\r
-                  0, 16, ... on sd) */\r
-               /* heuristic: partition name ends in a digit */\r
-\r
-               for(s = ptname; *s; s++);\r
-\r
-               if (isdigit(s[-1])) {\r
-                       char * ptr;\r
-                       char * deviceDir;\r
-                       int mustRemove = 0;\r
-                       int mustRemoveDir = 0;\r
-                       int i;\r
-\r
-                       sprintf(device, "%s/%s", DEVLABELDIR, ptname);\r
-                       if (access(device, F_OK)) {\r
-                           ptr = device;\r
-                           i = 0;\r
-                           while (*ptr)\r
-                               if (*ptr++ == '/')\r
-                                   i++;\r
-                           if (i > 2) {\r
-                               deviceDir = alloca(strlen(device) + 1);\r
-                               strcpy(deviceDir, device);\r
-                               ptr = deviceDir + (strlen(device) - 1);\r
-                               while (*ptr != '/')\r
-                                   *ptr-- = '\0';\r
-                               if (mkdir(deviceDir, 0644)) {\r
-                                   printf("mkdir: cannot create directory %s: %d\n", deviceDir, errno);\r
-                               } else {\r
-                                   mustRemoveDir = 1;\r
-                               }\r
-                           }\r
-\r
-                           mknod(device, S_IFBLK | 0600, makedev(ma, mi));\r
-                           mustRemove = 1;\r
-                       }\r
-                       if (!get_label_uuid(device, &label, uuid))\r
-                               uuidcache_addentry(strdup(device), ma, mi, \r
-                                                  label, uuid);\r
-\r
-                       if (mustRemove) unlink(device);\r
-                       if (mustRemoveDir) rmdir(deviceDir);\r
-               }\r
-           }\r
-       }\r
-\r
-       fclose(procpt);\r
-}\r
-\r
-#define UUID   1\r
-#define VOL    2\r
-\r
-static char *\r
-get_spec_by_x(int n, const char *t, int * majorPtr, int * minorPtr) {\r
-       struct uuidCache_s *uc;\r
-\r
-       uuidcache_init();\r
-       uc = uuidCache;\r
-\r
-       while(uc) {\r
-               switch (n) {\r
-               case UUID:\r
-                       if (!memcmp(t, uc->uuid, sizeof(uc->uuid))) {\r
-                               *majorPtr = uc->major;\r
-                               *minorPtr = uc->minor;\r
-                               return uc->device;\r
-                       }\r
-                       break;\r
-               case VOL:\r
-                       if (!strcmp(t, uc->label)) {\r
-                               *majorPtr = uc->major;\r
-                               *minorPtr = uc->minor;\r
-                               return uc->device;\r
-                       }\r
-                       break;\r
-               }\r
-               uc = uc->next;\r
-       }\r
-       return NULL;\r
-}\r
-\r
-static unsigned char\r
-fromhex(char c) {\r
-       if (isdigit(c))\r
-               return (c - '0');\r
-       else if (islower(c))\r
-               return (c - 'a' + 10);\r
-       else\r
-               return (c - 'A' + 10);\r
-}\r
-\r
-char *\r
-get_spec_by_uuid(const char *s, int * major, int * minor) {\r
-       unsigned char uuid[16];\r
-       int i;\r
-\r
-       if (strlen(s) != 36 ||\r
-           s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-')\r
-               goto bad_uuid;\r
-       for (i=0; i<16; i++) {\r
-           if (*s == '-') s++;\r
-           if (!isxdigit(s[0]) || !isxdigit(s[1]))\r
-                   goto bad_uuid;\r
-           uuid[i] = ((fromhex(s[0])<<4) | fromhex(s[1]));\r
-           s += 2;\r
-       }\r
-       return get_spec_by_x(UUID, uuid, major, minor);\r
-\r
- bad_uuid:\r
-       fprintf(stderr, _("mount: bad UUID"));\r
-       return 0;\r
-}\r
-\r
-char *\r
-get_spec_by_volume_label(const char *s, int * major, int * minor) {\r
-       return get_spec_by_x(VOL, s, major, minor);\r
-}\r
-\r
-int display_uuid_cache(void) {\r
-       struct uuidCache_s * u;\r
-       int i;\r
-\r
-       uuidcache_init();\r
-\r
-       u = uuidCache;\r
-       while (u) {\r
-           printf("%s %s ", u->device, u->label);\r
-           for (i = 0; i < sizeof(u->uuid); i++) {\r
-               if (i == 4 || i == 6 || i == 8 || i == 10)\r
-                   printf("-");\r
-               printf("%x", u->uuid[i] & 0xff);\r
-           }\r
-           printf("\n");\r
-           u = u->next;\r
-       }\r
-\r
-       return 0;\r
-}\r
-\r
+/*
+ * taken from util-linux 2.11g and hacked into nash
+ *
+ * mount_by_label.c - aeb
+ *
+ * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
+ * - added Native Language Support
+ * 2000-01-20 James Antill <james@and.org>
+ * - Added error message if /proc/partitions cannot be opened
+ * 2000-05-09 Erik Troan <ewt@redhat.com>
+ * - Added cache for UUID and disk labels
+ * 2000-11-07 Nathan Scott <nathans@sgi.com>
+ * - Added XFS support
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include "linux_fs.h"
+#include "mount_by_label.h"
+
+#define PROC_PARTITIONS "/proc/partitions"
+#define DEVLABELDIR    "/dev"
+
+#define _(str) (str)
+
+static struct uuidCache_s {
+       struct uuidCache_s *next;
+       char uuid[16];
+       char *device;
+       char *label;
+       int major, minor;
+} *uuidCache = NULL;
+
+/* for now, only ext2, ext3 and xfs are supported */
+static int
+get_label_uuid(const char *device, char **label, char *uuid) {
+
+       /* start with ext2/3 and xfs tests, taken from mount_guess_fstype */
+       /* should merge these later */
+       int fd;
+       int rv = 1;
+       size_t namesize;
+       struct ext2_super_block e2sb;
+       struct xfs_super_block xfsb;
+
+       fd = open(device, O_RDONLY);
+       if (fd < 0)
+               return rv;
+
+       if (lseek(fd, 1024, SEEK_SET) == 1024
+           && read(fd, (char *) &e2sb, sizeof(e2sb)) == sizeof(e2sb)
+           && (ext2magic(e2sb) == EXT2_SUPER_MAGIC)) {
+               memcpy(uuid, e2sb.s_uuid, sizeof(e2sb.s_uuid));
+               namesize = sizeof(e2sb.s_volume_name);
+               if ((*label = calloc(namesize + 1, 1)) != NULL)
+                       memcpy(*label, e2sb.s_volume_name, namesize);
+               rv = 0;
+       }
+       else if (lseek(fd, 0, SEEK_SET) == 0
+           && read(fd, (char *) &xfsb, sizeof(xfsb)) == sizeof(xfsb)
+           && (strncmp((char *)xfsb.s_magic, XFS_SUPER_MAGIC, 4) == 0)) {
+               memcpy(uuid, xfsb.s_uuid, sizeof(xfsb.s_uuid));
+               namesize = sizeof(xfsb.s_fname);
+               if ((*label = calloc(namesize + 1, 1)) != NULL)
+                       memcpy(*label, xfsb.s_fname, namesize);
+               rv = 0;
+       }
+
+       close(fd);
+       return rv;
+}
+
+static void
+uuidcache_addentry(char * device, int major, int minor, char *label, char *uuid) {
+       struct uuidCache_s *last;
+    
+       if (!uuidCache) {
+               last = uuidCache = malloc(sizeof(*uuidCache));
+       } else {
+               for (last = uuidCache; last->next; last = last->next) ;
+               last->next = malloc(sizeof(*uuidCache));
+               last = last->next;
+       }
+       last->next = NULL;
+       last->label = label;
+       last->device = device;
+       last->major = major;
+       last->minor = minor;
+       memcpy(last->uuid, uuid, sizeof(last->uuid));
+}
+
+static void
+uuidcache_init(void) {
+       char line[100];
+       char *s;
+       int ma, mi, sz;
+       static char ptname[100];
+       FILE *procpt;
+       char uuid[16], *label;
+       char device[110];
+       int firstPass;
+       int handleOnFirst;
+       char * chptr, * endptr;
+
+       if (uuidCache)
+               return;
+
+       procpt = fopen(PROC_PARTITIONS, "r");
+       if (!procpt) {
+               static int warn = 0;
+               if (!warn++)
+                   fprintf (stderr, _("mount: could not open %s, so UUID and LABEL "
+                            "conversion cannot be done.\n"),
+                      PROC_PARTITIONS);
+               return;
+       }
+
+       for (firstPass = 1; firstPass >= 0; firstPass--) {
+           fseek(procpt, 0, SEEK_SET);
+
+           while (fgets(line, sizeof(line), procpt)) {
+               /* The original version of this code used sscanf, but
+                  diet's sscanf is quite limited */
+               chptr = line;
+               if (*chptr++ != ' ') continue;
+
+               ma = strtol(chptr, &endptr, 0);
+               if (endptr == chptr) continue;
+               while (isspace(*endptr)) endptr++;
+               chptr = endptr;
+
+               mi = strtol(chptr, &endptr, 0);
+               if (endptr == chptr) continue;
+               while (isspace(*endptr)) endptr++;
+               chptr = endptr;
+
+               sz = strtol(chptr, &endptr, 0);
+               if (endptr == chptr) continue;
+               while (isspace(*endptr)) endptr++;
+               chptr = endptr;
+
+               while (!isspace(*endptr) && *endptr != '\n') endptr++;
+               if (chptr == endptr) continue;
+               strncpy(ptname, chptr, endptr - chptr);
+               ptname[endptr - chptr] = '\0';
+
+               /* skip extended partitions (heuristic: size 1) */
+               if (sz == 1)
+                       continue;
+
+               /* look only at md devices on first pass */
+               handleOnFirst = !strncmp(ptname, "md", 2);
+               if (firstPass != handleOnFirst)
+                       continue;
+
+               /* skip entire disk (minor 0, 64, ... on ide;
+                  0, 16, ... on sd) */
+               /* heuristic: partition name ends in a digit */
+
+               for(s = ptname; *s; s++);
+
+               if (isdigit(s[-1])) {
+                       char * ptr;
+                       char * deviceDir = NULL;
+                       int mustRemove = 0;
+                       int mustRemoveDir = 0;
+                       int i;
+
+                       sprintf(device, "%s/%s", DEVLABELDIR, ptname);
+                       if (access(device, F_OK)) {
+                           ptr = device;
+                           i = 0;
+                           while (*ptr)
+                               if (*ptr++ == '/')
+                                   i++;
+                           if (i > 2) {
+                               deviceDir = alloca(strlen(device) + 1);
+                               strcpy(deviceDir, device);
+                               ptr = deviceDir + (strlen(device) - 1);
+                               while (*ptr != '/')
+                                   *ptr-- = '\0';
+                               if (mkdir(deviceDir, 0644)) {
+                                   printf("mkdir: cannot create directory %s: %d\n", deviceDir, errno);
+                               } else {
+                                   mustRemoveDir = 1;
+                               }
+                           }
+
+                           mknod(device, S_IFBLK | 0600, makedev(ma, mi));
+                           mustRemove = 1;
+                       }
+                       if (!get_label_uuid(device, &label, uuid))
+                               uuidcache_addentry(strdup(device), ma, mi, 
+                                                  label, uuid);
+
+                       if (mustRemove) unlink(device);
+                       if (mustRemoveDir) rmdir(deviceDir);
+               }
+           }
+       }
+
+       fclose(procpt);
+}
+
+#define UUID   1
+#define VOL    2
+
+static char *
+get_spec_by_x(int n, const char *t, int * majorPtr, int * minorPtr) {
+       struct uuidCache_s *uc;
+
+       uuidcache_init();
+       uc = uuidCache;
+
+       while(uc) {
+               switch (n) {
+               case UUID:
+                       if (!memcmp(t, uc->uuid, sizeof(uc->uuid))) {
+                               *majorPtr = uc->major;
+                               *minorPtr = uc->minor;
+                               return uc->device;
+                       }
+                       break;
+               case VOL:
+                       if (!strcmp(t, uc->label)) {
+                               *majorPtr = uc->major;
+                               *minorPtr = uc->minor;
+                               return uc->device;
+                       }
+                       break;
+               }
+               uc = uc->next;
+       }
+       return NULL;
+}
+
+static unsigned char
+fromhex(char c) {
+       if (isdigit(c))
+               return (c - '0');
+       else if (islower(c))
+               return (c - 'a' + 10);
+       else
+               return (c - 'A' + 10);
+}
+
+char *
+get_spec_by_uuid(const char *s, int * major, int * minor) {
+       unsigned char uuid[16];
+       int i;
+
+       if (strlen(s) != 36 ||
+           s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-')
+               goto bad_uuid;
+       for (i=0; i<16; i++) {
+           if (*s == '-') s++;
+           if (!isxdigit(s[0]) || !isxdigit(s[1]))
+                   goto bad_uuid;
+           uuid[i] = ((fromhex(s[0])<<4) | fromhex(s[1]));
+           s += 2;
+       }
+       return get_spec_by_x(UUID, (char *)uuid, major, minor);
+
+ bad_uuid:
+       fprintf(stderr, _("mount: bad UUID"));
+       return 0;
+}
+
+char *
+get_spec_by_volume_label(const char *s, int * major, int * minor) {
+       return get_spec_by_x(VOL, s, major, minor);
+}
+
+int display_uuid_cache(void) {
+       struct uuidCache_s * u;
+       size_t i;
+
+       uuidcache_init();
+
+       u = uuidCache;
+       while (u) {
+           printf("%s %s ", u->device, u->label);
+           for (i = 0; i < sizeof(u->uuid); i++) {
+               if (i == 4 || i == 6 || i == 8 || i == 10)
+                   printf("-");
+               printf("%x", u->uuid[i] & 0xff);
+           }
+           printf("\n");
+           u = u->next;
+       }
+
+       return 0;
+}
+