summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--collage/Makefile2
-rw-r--r--collage/commands.c7
-rw-r--r--collage/linux_fs.h151
-rw-r--r--collage/mount_by_label.c236
-rw-r--r--collage/mount_by_label.h3
5 files changed, 398 insertions, 1 deletions
diff --git a/collage/Makefile b/collage/Makefile
index 47ce210f8..47648588d 100644
--- a/collage/Makefile
+++ b/collage/Makefile
@@ -14,7 +14,7 @@ everything: $(TARGET)
all: collage
-collage: collage.o commands.o idmap.o ls.o
+collage: collage.o commands.o idmap.o ls.o mount_by_label.o
install:
mkdir -p $(DESTDIR)/$(RUNTIMEDIR)
diff --git a/collage/commands.c b/collage/commands.c
index 211b344e7..c6cae1c94 100644
--- a/collage/commands.c
+++ b/collage/commands.c
@@ -18,6 +18,7 @@
#include "commands.h"
#include "idmap.h"
#include "ls.h"
+#include "mount_by_label.h"
#include "popt.h"
#include "../isys/cpio.h"
@@ -113,6 +114,12 @@ int mountCommand(int argc, char ** argv) {
dir = argv[4];
}
+ if (!strncmp(dev, "LABEL=", 6)) {
+ dev = get_spec_by_volume_label(dev + 6);
+ } else if (!strncmp(dev, "UUID=", 5)) {
+ dev = get_spec_by_uuid(dev + 5);
+ }
+
if (!strncmp(dev, "/dev/", 5) && access(dev, X_OK)) {
dev += 5;
buf = alloca(strlen(dev) + 10);
diff --git a/collage/linux_fs.h b/collage/linux_fs.h
new file mode 100644
index 000000000..043ac16a7
--- /dev/null
+++ b/collage/linux_fs.h
@@ -0,0 +1,151 @@
+/* Including <linux/fs.h> became more and more painful.
+ Below a very abbreviated version of some declarations,
+ only designed to be able to check a magic number
+ in case no filesystem type was given. */
+
+#ifndef BLKGETSIZE
+#ifndef _IO
+/* pre-1.3.45 */
+#define BLKGETSIZE 0x1260 /* return device size */
+#else
+/* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */
+#define BLKGETSIZE _IO(0x12,96)
+#endif
+#endif
+
+#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */
+#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */
+struct minix_super_block {
+ u_char s_dummy[16];
+ u_char s_magic[2];
+};
+#define minixmagic(s) ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8))
+
+#define ISODCL(from, to) (to - from + 1)
+#define ISO_STANDARD_ID "CD001"
+struct iso_volume_descriptor {
+ char type[ISODCL(1,1)]; /* 711 */
+ char id[ISODCL(2,6)];
+ char version[ISODCL(7,7)];
+ char data[ISODCL(8,2048)];
+};
+
+#define HS_STANDARD_ID "CDROM"
+struct hs_volume_descriptor {
+ char foo[ISODCL ( 1, 8)]; /* 733 */
+ char type[ISODCL ( 9, 9)]; /* 711 */
+ char id[ISODCL ( 10, 14)];
+ char version[ISODCL ( 15, 15)]; /* 711 */
+ char data[ISODCL(16,2048)];
+};
+
+#define EXT_SUPER_MAGIC 0x137D
+struct ext_super_block {
+ u_char s_dummy[56];
+ u_char s_magic[2];
+};
+#define extmagic(s) ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8))
+
+#define EXT2_PRE_02B_MAGIC 0xEF51
+#define EXT2_SUPER_MAGIC 0xEF53
+struct ext2_super_block {
+ u_char s_dummy1[56];
+ u_char s_magic[2];
+ u_char s_dummy2[46];
+ u_char s_uuid[16];
+ u_char s_volume_name[16];
+};
+#define ext2magic(s) ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8))
+
+#define _XIAFS_SUPER_MAGIC 0x012FD16D
+struct xiafs_super_block {
+ u_char s_boot_segment[512]; /* 1st sector reserved for boot */
+ u_char s_dummy[60];
+ u_char s_magic[4];
+};
+#define xiafsmagic(s) ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8) + \
+ (((uint) s.s_magic[2]) << 16) + \
+ (((uint) s.s_magic[3]) << 24))
+
+/* From jj@sunsite.ms.mff.cuni.cz Mon Mar 23 15:19:05 1998 */
+#define UFS_SUPER_MAGIC 0x00011954
+struct ufs_super_block {
+ u_char s_dummy[0x55c];
+ u_char s_magic[4];
+};
+#define ufsmagic(s) ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8) + \
+ (((uint) s.s_magic[2]) << 16) + \
+ (((uint) s.s_magic[3]) << 24))
+
+/* From Richard.Russon@ait.co.uk Wed Feb 24 08:05:27 1999 */
+#define NTFS_SUPER_MAGIC "NTFS"
+struct ntfs_super_block {
+ u_char s_dummy[3];
+ u_char s_magic[4];
+};
+
+/* From inspection of a few FAT filesystems - aeb */
+/* Unfortunately I find almost the same thing on an extended partition;
+ it looks like a primary has some directory entries where the extended
+ has a partition table: IO.SYS, MSDOS.SYS, WINBOOT.SYS */
+struct fat_super_block {
+ u_char s_dummy[3];
+ u_char s_os[8]; /* "MSDOS5.0" or "MSWIN4.0" or "MSWIN4.1" */
+ /* mtools-3.9.4 writes "MTOOL394" */
+ u_char s_dummy2[32];
+ u_char s_label[11]; /* for DOS? */
+ u_char s_fs[8]; /* "FAT12 " or "FAT16 " or all zero */
+ /* OS/2 BM has "FAT " here. */
+ u_char s_dummy3[9];
+ u_char s_label2[11]; /* for Windows? */
+ u_char s_fs2[8]; /* garbage or "FAT32 " */
+};
+
+#define XFS_SUPER_MAGIC "XFSB"
+#define XFS_SUPER_MAGIC2 "BSFX"
+struct xfs_super_block {
+ u_char s_magic[4];
+ u_char s_dummy[28];
+ u_char s_uuid[16];
+ u_char s_dummy2[60];
+ u_char s_fname[12];
+};
+
+#define CRAMFS_SUPER_MAGIC 0x28cd3d45
+struct cramfs_super_block {
+ u_char s_magic[4];
+ u_char s_dummy[12];
+ u_char s_id[16];
+};
+#define cramfsmagic(s) ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8) + \
+ (((uint) s.s_magic[2]) << 16) + \
+ (((uint) s.s_magic[3]) << 24))
+
+#define HFS_SUPER_MAGIC 0x4244
+struct hfs_super_block {
+ u_char s_magic[2];
+ u_char s_dummy[18];
+ u_char s_blksize[4];
+};
+#define hfsmagic(s) ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8))
+#define hfsblksize(s) ((uint) s.s_blksize[0] + \
+ (((uint) s.s_blksize[1]) << 8) + \
+ (((uint) s.s_blksize[2]) << 16) + \
+ (((uint) s.s_blksize[3]) << 24))
+
+#define HPFS_SUPER_MAGIC 0xf995e849
+struct hpfs_super_block {
+ u_char s_magic[4];
+ u_char s_magic2[4];
+};
+#define hpfsmagic(s) ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8) + \
+ (((uint) s.s_magic[2]) << 16) + \
+ (((uint) s.s_magic[3]) << 24))
+
+struct adfs_super_block {
+ u_char s_dummy[448];
+ u_char s_blksize[1];
+ u_char s_dummy2[62];
+ u_char s_checksum[1];
+};
+#define adfsblksize(s) ((uint) s.s_blksize[0])
diff --git a/collage/mount_by_label.c b/collage/mount_by_label.c
new file mode 100644
index 000000000..b806accd9
--- /dev/null
+++ b/collage/mount_by_label.c
@@ -0,0 +1,236 @@
+/*
+ * mount_by_label.c - aeb
+ *
+ * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
+ * - 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 <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "linux_fs.h"
+#include "mount_by_label.h"
+
+#define xstrdup strdup
+
+#define PROC_PARTITIONS "/proc/partitions"
+#define DEVLABELDIR "/dev"
+
+static struct uuidCache_s {
+ struct uuidCache_s *next;
+ char uuid[16];
+ char *label;
+ char *device;
+} *uuidCache = NULL;
+
+/* for now, only ext2 and xfs are supported */
+static int
+get_label_uuid(const char *device, char **label, char *uuid) {
+
+ /* start with ext2 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 ||
+ strncmp((char *) &xfsb.s_magic, XFS_SUPER_MAGIC2,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, 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->device = device;
+ last->label = label;
+ 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;
+
+ 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)) {
+ if (sscanf (line, " %d %d %d %[^\n ]",
+ &ma, &mi, &sz, ptname) != 4)
+ continue;
+
+ /* 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])) {
+ /*
+ * Note: this is a heuristic only - there is no reason
+ * why these devices should live in /dev.
+ * Perhaps this directory should be specifiable by option.
+ * One might for example have /devlabel with links to /dev
+ * for the devices that may be accessed in this way.
+ * (This is useful, if the cdrom on /dev/hdc must not
+ * be accessed.)
+ */
+ sprintf(device, "%s/%s", DEVLABELDIR, ptname);
+ if (!get_label_uuid(device, &label, uuid))
+ uuidcache_addentry(strdup(device), label, uuid);
+ }
+ }
+ }
+
+ fclose(procpt);
+}
+
+#define UUID 1
+#define VOL 2
+
+static char *
+get_spec_by_x(int n, const char *t) {
+ struct uuidCache_s *uc;
+
+ uuidcache_init();
+ uc = uuidCache;
+
+ while(uc) {
+ switch (n) {
+ case UUID:
+ if (!memcmp(t, uc->uuid, sizeof(uc->uuid)))
+ return xstrdup(uc->device);
+ break;
+ case VOL:
+ if (!strcmp(t, uc->label))
+ return xstrdup(uc->device);
+ break;
+ }
+ uc = uc->next;
+ }
+ return NULL;
+}
+
+static u_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) {
+ u_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, uuid);
+
+ bad_uuid:
+ fprintf(stderr, "mount: bad UUID\n");
+ exit(1);
+ return NULL; /* just for gcc */
+}
+
+char *
+get_spec_by_volume_label(const char *s) {
+ return get_spec_by_x(VOL, s);
+}
+
+const char *
+get_volume_label_by_spec(const char *spec) {
+ struct uuidCache_s *uc;
+
+ uuidcache_init();
+ uc = uuidCache;
+
+ while(uc) {
+ if (!strcmp(spec, uc->device))
+ return uc->label;
+ uc = uc->next;
+ }
+ return NULL;
+}
diff --git a/collage/mount_by_label.h b/collage/mount_by_label.h
new file mode 100644
index 000000000..64bbbfa7d
--- /dev/null
+++ b/collage/mount_by_label.h
@@ -0,0 +1,3 @@
+char *get_spec_by_uuid(const char *uuid);
+char *get_spec_by_volume_label(const char *volumelabel);
+const char *get_volume_label_by_spec(const char *spec);