--- /dev/null
+/*\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