From 8954518fe88156827aa958745ba1eb9cea4b42fa Mon Sep 17 00:00:00 2001 From: Stelian Pop Date: Sun, 20 Aug 2000 19:41:23 +0000 Subject: [PATCH] Made dump understand the LABEL= and UUID= notations. --- CHANGES | 8 +- compat/include/bylabel.h | 1 + compat/lib/Makefile.in | 6 +- compat/lib/bylabel.c | 222 +++++++++++++++++++++++++++++++++++++++ compat/lib/fstab.c | 13 ++- dump.spec | 2 +- dump/main.c | 19 +++- 7 files changed, 259 insertions(+), 12 deletions(-) create mode 100644 compat/include/bylabel.h create mode 100644 compat/lib/bylabel.c diff --git a/CHANGES b/CHANGES index ae7b438..b9db81c 100644 --- 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 + 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 index 0000000..00ed284 --- /dev/null +++ b/compat/include/bylabel.h @@ -0,0 +1 @@ +const char * get_device_name(const char * item); diff --git a/compat/lib/Makefile.in b/compat/lib/Makefile.in index fe6547d..42239c9 100644 --- a/compat/lib/Makefile.in +++ b/compat/lib/Makefile.in @@ -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 index 0000000..9cdd0e5 --- /dev/null +++ b/compat/lib/bylabel.c @@ -0,0 +1,222 @@ +/* + * mount_by_label.c - aeb + * + * 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * 2000-01-20 James Antill + * - Added error message if /proc/partitions cannot be opened + * 2000-05-09 Erik Troan + * - Added cache for UUID and disk labels + * Wed Aug 16 2000 Erik Troan + * - Ported to dump/restore + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/compat/lib/fstab.c b/compat/lib/fstab.c index 088645e..b3a21f0 100644 --- a/compat/lib/fstab.c +++ b/compat/lib/fstab.c @@ -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 @@ -50,6 +50,7 @@ static const char rcsid[] = #include #include #include +#include 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; diff --git a/dump.spec b/dump.spec index c21fa8b..ea64c22 100644 --- 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 diff --git a/dump/main.c b/dump/main.c index c2e4eaf..43c3116 100644 --- a/dump/main.c +++ b/dump/main.c @@ -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 @@ -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); -- 2.39.5