]> git.wh0rd.org - dump.git/commitdiff
Made dump understand the LABEL= and UUID= notations.
authorStelian Pop <stelian@popies.net>
Sun, 20 Aug 2000 19:41:23 +0000 (19:41 +0000)
committerStelian Pop <stelian@popies.net>
Sun, 20 Aug 2000 19:41:23 +0000 (19:41 +0000)
CHANGES
compat/include/bylabel.h [new file with mode: 0644]
compat/lib/Makefile.in
compat/lib/bylabel.c [new file with mode: 0644]
compat/lib/fstab.c
dump.spec
dump/main.c

diff --git a/CHANGES b/CHANGES
index ae7b4380a6a6217c02870dd0136fbccd0ae0a767..b9db81c8acb2a95f5bed3eef2b183cc587043221 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,4 @@
-$Id: CHANGES,v 1.76 2000/08/20 16:34:00 stelian Exp $
+$Id: CHANGES,v 1.77 2000/08/20 19:41:23 stelian Exp $
 
 Changes between versions 0.4b17 and 0.4b19 (released ?????????????)
 ===================================================================
@@ -37,6 +37,12 @@ Changes between versions 0.4b17 and 0.4b19 (released ?????????????)
        before checking for libreadline, because we need this
        library in order to compile the readline support.
 
+9.     Made dump understand the LABEL= and UUID= notation
+       both in /etc/fstab and on the command line. Note that
+       you will need the /proc filesystem in order to use
+       these notations. Thanks to Erik Troan <ewt@redhat.com> 
+       for providing the patch.
+
 Changes between versions 0.4b17 and 0.4b18 (released June 30, 2000)
 ===================================================================
 
diff --git a/compat/include/bylabel.h b/compat/include/bylabel.h
new file mode 100644 (file)
index 0000000..00ed284
--- /dev/null
@@ -0,0 +1 @@
+const char * get_device_name(const char * item);
index fe6547d78ecce99e58cb713b8a4c61df41d88240..42239c96a767a2d58c6f8259adf2ba410ed0f5e9 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: Makefile.in,v 1.3 1999/10/11 13:31:10 stelian Exp $
+# $Id: Makefile.in,v 1.4 2000/08/20 19:41:24 stelian Exp $
 
 top_srcdir=    @top_srcdir@
 srcdir=                @srcdir@
@@ -7,8 +7,8 @@ srcdir=         @srcdir@
 
 INC=           -I$(top_srcdir)/compat/include
 CFLAGS=                @CCOPTS@ -pipe $(OPT) $(GINC) $(INC) $(DEFS)
-SRCS=          compaterr.c fstab.c compatglob.c
-OBJS=          compaterr.o fstab.o compatglob.o
+SRCS=          compaterr.c fstab.c compatglob.c bylabel.c
+OBJS=          compaterr.o fstab.o compatglob.o bylabel.o
 LIB=           libcompat.a
 
 all::          $(LIB)
diff --git a/compat/lib/bylabel.c b/compat/lib/bylabel.c
new file mode 100644 (file)
index 0000000..9cdd0e5
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * 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
+ * Wed Aug 16 2000 Erik Troan <ewt@redhat.com>
+ * - Ported to dump/restore
+ */
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/ext2_fs.h>
+#include <ext2fs/ext2fs.h>
+#include "bylabel.h"
+
+#define PROC_PARTITIONS "/proc/partitions"
+#define DEVLABELDIR    "/dev"
+
+void msg __P((const char *fmt, ...));
+
+static struct uuidCache_s {
+       struct uuidCache_s *next;
+       char uuid[16];
+       char *label;
+       char *device;
+} *uuidCache = NULL;
+
+/* for now, only ext2 is supported */
+static int
+get_label_uuid(const char *device, char **label, char *uuid) {
+
+       /* start with a test for ext2, taken from mount_guess_fstype */
+       /* should merge these later */
+       int fd;
+       struct ext2_super_block e2sb;
+
+       fd = open(device, O_RDONLY);
+       if (fd < 0)
+               return 1;
+
+       if (lseek(fd, 1024, SEEK_SET) != 1024
+           || read(fd, (char *) &e2sb, sizeof(e2sb)) != sizeof(e2sb)
+           || (e2sb.s_magic != EXT2_SUPER_MAGIC)) {
+               close(fd);
+               return 1;
+       }
+
+       close(fd);
+
+       /* superblock is ext2 - now what is its label? */
+       memcpy(uuid, e2sb.s_uuid, sizeof(e2sb.s_uuid));
+       *label = strdup(e2sb.s_volume_name);
+
+       return 0;
+}
+
+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)
+               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 strdup(uc->device);
+                       break;
+               case VOL:
+                       if (!strcmp(t, uc->label))
+                               return strdup(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);
+}
+
+static 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:
+       msg("mount: bad UUID\n");
+       return NULL;            /* just for gcc */
+}
+
+static char *
+get_spec_by_volume_label(const char *s) {
+       return get_spec_by_x(VOL, s);
+}
+
+const char * 
+get_device_name(const char * item) {
+       const char * rc;
+
+       if (!strncmp(item, "UUID=", 5)) {
+               rc = get_spec_by_uuid(item+5);
+       } 
+       else
+               if (!strncmp(item, "LABEL=", 6)) {
+                       rc = get_spec_by_volume_label(item+6);
+               }
+               else {
+                       rc = item;
+               }
+
+       return rc;
+}
index 088645e6d3d0540d7401cf859e2127cea1473793..b3a21f0c66c074d78e87c158cfdb53f40896f0a2 100644 (file)
@@ -40,7 +40,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: fstab.c,v 1.6 2000/01/21 10:17:41 stelian Exp $";
+       "$Id: fstab.c,v 1.7 2000/08/20 19:41:24 stelian Exp $";
 #endif /* not lint */
 
 #include <errno.h>
@@ -50,6 +50,7 @@ static const char rcsid[] =
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <bylabel.h>
 
 static FILE *_fs_fp;
 static struct fstab _fs_fstab;
@@ -57,6 +58,8 @@ static struct fstab _fs_fstab;
 static void error __P((int));
 static int fstabscan __P((void));
 
+void msg __P((const char *fmt, ...));
+
 static
 int fstabscan(void)
 {
@@ -65,12 +68,18 @@ int fstabscan(void)
        int typexx;
 #define        MAXLINELENGTH   1024
        char subline[MAXLINELENGTH];
+       char *device_name;
 
        for (;;) {
                if (!(mnt = getmntent(_fs_fp)))
                        return 0;
 
-               _fs_fstab.fs_spec = mnt->mnt_fsname;
+               device_name = get_device_name(mnt->mnt_fsname);
+               if (!device_name) {
+                       msg("Warning: unable to translate %s\n", mnt->mnt_fsname);
+                       continue;
+               }
+               _fs_fstab.fs_spec = device_name;
                _fs_fstab.fs_file = mnt->mnt_dir;
                _fs_fstab.fs_vfstype = mnt->mnt_type;
                _fs_fstab.fs_mntops = mnt->mnt_opts;
index c21fa8befbefed1de88989eea5ccab397174a1b3..ea64c22b628eb2f453c17110215fe94bce318821 100644 (file)
--- a/dump.spec
+++ b/dump.spec
@@ -34,7 +34,7 @@ like dump (a filesystem backup program), restore (a program for
 restoring files from a backup) and tar (an archiving program).
 
 %package -n dump-static
-Summary: Programs for backing up and restoring filesystems.
+Summary: Statically linked versions of dump and restore.
 Group: Applications/Archiving
 
 %description -n dump-static
index c2e4eaf329c94e77e671c50915ec4e027313d792..43c31168f070429dbb8f7a3d7830c15d6ec20e7b 100644 (file)
@@ -40,7 +40,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: main.c,v 1.23 2000/08/19 23:48:10 stelian Exp $";
+       "$Id: main.c,v 1.24 2000/08/20 19:41:50 stelian Exp $";
 #endif /* not lint */
 
 #include <sys/param.h>
@@ -79,6 +79,7 @@ static const char rcsid[] =
 
 #include "dump.h"
 #include "pathnames.h"
+#include "bylabel.h"
 
 #ifndef SBOFF
 #define SBOFF (SBLOCK * DEV_BSIZE)
@@ -126,6 +127,7 @@ main(int argc, char *argv[])
 #endif
        time_t tnow;
        char labelstr[LBLSIZE];
+       char *diskparam;
 
        spcl.c_date = 0;
 #ifdef __linux__
@@ -287,9 +289,9 @@ main(int argc, char *argv[])
                (void)fprintf(stderr, "Must specify disk or filesystem\n");
                exit(X_STARTUP);
        }
-       disk = *argv++;
-       if (strlen(disk) >= MAXPATHLEN) {
-               (void)fprintf(stderr, "Disk or filesystem name too long: %s\n", disk);
+       diskparam = *argv++;
+       if (strlen(diskparam) >= MAXPATHLEN) {
+               (void)fprintf(stderr, "Disk or filesystem name too long: %s\n", diskparam);
                exit(X_STARTUP);
        }
        argc--;
@@ -363,6 +365,14 @@ main(int argc, char *argv[])
                signal(SIGINT, SIG_IGN);
        set_operators();        /* /etc/group snarfed */
        getfstab();             /* /etc/fstab snarfed */
+
+       disk = get_device_name(diskparam);
+       if (!disk) {            /* null means the disk is some form
+                                  of LABEL= or UID= but it was not
+                                  found */
+               msg("Cannot find a disk having %s\n", diskparam);
+               exit(X_STARTUP);
+       }
        /*
         *      disk may end in / and this can confuse
         *      fstabsearch.
@@ -421,7 +431,6 @@ main(int argc, char *argv[])
                        exit(X_STARTUP);
                }
        }
-
        spcl.c_dev[NAMELEN-1]='\0';
        spcl.c_filesys[NAMELEN-1]='\0';
        (void)strncpy(spcl.c_label, labelstr, sizeof(spcl.c_label) - 1);