Whamcloud - gitweb
ChangeLog, Makefile.in, fsck.c, get_device_by_label.c, get_device_by_label.h:
authorTheodore Ts'o <tytso@mit.edu>
Sat, 3 Jul 1999 01:59:42 +0000 (01:59 +0000)
committerTheodore Ts'o <tytso@mit.edu>
Sat, 3 Jul 1999 01:59:42 +0000 (01:59 +0000)
  fsck.c: Added support for LABEL= and UUID= specifications for the
   filesystem's device, to match what recent mount programs can support.
   Also, close stdin when doing fsck -A or when checking more than one
   filesystem at a time, so that e2fsck doesn't try to ask interactive
   questions if the filesystem appears to be mounted.
  get_device_by_label.c: New file added to support LABEL=foo and
   UUID=bar type specifications.

misc/ChangeLog
misc/Makefile.in
misc/fsck.c
misc/get_device_by_label.c [new file with mode: 0644]
misc/get_device_by_label.h [new file with mode: 0644]

index da3c7bb..9d7f372 100644 (file)
@@ -1,3 +1,15 @@
+1999-07-02    <tytso@rsts-11.mit.edu>
+
+       * fsck.c: Added support for LABEL= and UUID= specifications for
+               the filesystem's device, to match what recent mount
+               programs can support.  Also, close stdin when doing fsck
+               -A or when checking more than one filesystem at a time, so
+               that e2fsck doesn't try to ask interactive questions if
+               the filesystem appears to be mounted.
+
+       * get_device_by_label.c: New file added to support LABEL=foo and
+               UUID=bar type specifications.
+
 1999-07-01    <tytso@valinux.com>
 
        * badblocks.c:  Make the "done" string include enough spaces to
index e140db6..175201b 100644 (file)
@@ -28,7 +28,7 @@ UUIDGEN_OBJS= uuidgen.o
 DUMPE2FS_OBJS= dumpe2fs.o
 BADBLOCKS_OBJS=        badblocks.o
 E2LABEL_OBJS=  e2label.o
-FSCK_OBJS=     fsck.o
+FSCK_OBJS=     fsck.o get_device_by_label.o
 
 SRCS=  $(srcdir)/tune2fs.c $(srcdir)/mklost+found.c $(srcdir)/mke2fs.c \
                $(srcdir)/chattr.c $(srcdir)/lsattr.c $(srcdir)/dumpe2fs.c \
index 669e307..db86f56 100644 (file)
@@ -52,6 +52,7 @@
 
 #include "../version.h"
 #include "fsck.h"
+#include "get_device_by_label.h"
 
 #ifndef _PATH_MNTTAB
 #define        _PATH_MNTTAB    "/etc/fstab"
@@ -242,6 +243,24 @@ int parse_fstab_line(char *line, struct fs_info **ret_fs)
 }
 
 /*
+ * Interpret the device name if necessary 
+ */
+static char *interpret_device(char *spec)
+{
+       char *dev = NULL;
+       
+       if (!strncmp(spec, "UUID=", 5))
+               dev = get_spec_by_uuid(spec+5);
+       else if (!strncmp(spec, "LABEL=", 6))
+               dev = get_spec_by_volume_label(spec+6);
+       if (dev) {
+               free(spec);
+               spec = dev;
+       }
+       return spec;
+}
+
+/*
  * Load the filesystem database from /etc/fstab
  */
 static void load_fs_info(char *filename)
@@ -270,6 +289,7 @@ static void load_fs_info(char *filename)
                }
                if (!fs)
                        continue;
+               fs->device = interpret_device(fs->device);
                if (!filesys_info)
                        filesys_info = fs;
                else
@@ -339,7 +359,7 @@ static char *find_fsck(char *type)
  * Execute a particular fsck program, and link it into the list of
  * child processes we are waiting for.
  */
-static int execute(char *prog, char *device, char *mntpt)
+static int execute(char *prog, char *device, char *mntpt, int interactive)
 {
        char *s, *argv[80];
        int  argc, i;
@@ -375,6 +395,8 @@ static int execute(char *prog, char *device, char *mntpt)
                perror("fork");
                return errno;
        } else if (pid == 0) {
+               if (!interactive)
+                       close(0);
                (void) execv(s, argv);
                perror(argv[0]);
                exit(EXIT_ERROR);
@@ -492,7 +514,7 @@ static int wait_all(NOARGS)
  * If the type isn't specified by the user, then use either the type
  * specified in /etc/fstab, or DEFAULT_FSTYPE.
  */
-static void fsck_device(char *device)
+static void fsck_device(char *device, int interactive)
 {
        const char      *type = 0;
        struct fs_info *fsent;
@@ -507,17 +529,12 @@ static void fsck_device(char *device)
                if (!type)
                        type = fsent->type;
        }
-       if (!fsent) {
-               fprintf(stderr,
-                       "Error: no entry found the fstab file for %s.\n",
-                       device);
-               exit(1);
-       }
        if (!type)
                type = DEFAULT_FSTYPE;
 
        sprintf(prog, "fsck.%s", type);
-       retval = execute(prog, device, fsent ? fsent->mountpt : 0);
+       retval = execute(prog, device, fsent ? fsent->mountpt : 0,
+                        interactive);
        if (retval) {
                fprintf(stderr, "%s: Error %d while executing %s for %s\n",
                        progname, retval, prog, device);
@@ -649,7 +666,7 @@ static int check_all(NOARGS)
                                break;
                }
                if (fs && !skip_root && !ignore(fs)) {
-                       fsck_device(fs->device);
+                       fsck_device(fs->device, 0);
                        fs->flags |= FLAG_DONE;
                        status |= wait_all();
                        if (status > EXIT_NONDESTRUCT)
@@ -694,7 +711,7 @@ static int check_all(NOARGS)
                        /*
                         * Spawn off the fsck process
                         */
-                       fsck_device(fs->device);
+                       fsck_device(fs->device, 0);
                        fs->flags |= FLAG_DONE;
 
                        if (serialize) {
@@ -747,16 +764,19 @@ static void PRS(int argc, char *argv[])
                arg = argv[i];
                if (!arg)
                        continue;
-               if (arg[0] == '/') {
+               if ((arg[0] == '/' && !opts_for_fsck) ||
+                   (strncmp(arg, "LABEL=", 6) == 0) ||
+                   (strncmp(arg, "UUID=", 5) == 0)) {
                        if (num_devices >= MAX_DEVICES) {
                                fprintf(stderr, "%s: too many devices\n",
                                        progname);
                                exit(1);
                        }
-                       devices[num_devices++] = string_copy(arg);
+                       devices[num_devices++] =
+                               interpret_device(string_copy(arg));
                        continue;
                }
-               if (arg[0] != '-') {
+               if (arg[0] != '-' || opts_for_fsck) {
                        if (num_args >= MAX_ARGS) {
                                fprintf(stderr, "%s: too many arguments\n",
                                        progname);
@@ -835,6 +855,7 @@ int main(int argc, char *argv[])
 {
        int i;
        int status = 0;
+       int interactive = 0;
        char *oldpath = getenv("PATH");
        char *fstab;
 
@@ -864,8 +885,11 @@ int main(int argc, char *argv[])
        if (doall)
                return check_all();
 
+       if ((num_devices == 1) || (serialize))
+               interactive = 1;
+
        for (i = 0 ; i < num_devices; i++) {
-               fsck_device(devices[i]);
+               fsck_device(devices[i], interactive);
                if (serialize) {
                        struct fsck_instance *inst;
 
diff --git a/misc/get_device_by_label.c b/misc/get_device_by_label.c
new file mode 100644 (file)
index 0000000..64bda02
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * get_device_by_label.h
+ *
+ * Copyright 1999 by Andries Brouwer and Theodore Ts'o
+ *
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ *
+ * Taken from aeb's mount, 990619
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "get_device_by_label.h"
+
+#define PROC_PARTITIONS "/proc/partitions"
+#define DEVLABELDIR    "/dev"
+
+#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))
+
+
+static FILE *procpt;
+
+static void
+procptclose(void) {
+    if (procpt)
+        fclose (procpt);
+    procpt = 0;
+}
+
+static int
+procptopen(void) {
+    return ((procpt = fopen(PROC_PARTITIONS, "r")) != NULL);
+}
+
+static char *
+procptnext(void) {
+   char line[100];
+   char *s;
+   int ma, mi, sz;
+   static char ptname[100];
+
+   while (fgets(line, sizeof(line), procpt)) {
+      if (sscanf (line, " %d %d %d %[^\n]\n", &ma, &mi, &sz, ptname) != 4)
+             continue;
+
+      /* skip extended partitions (heuristic: size 1) */
+      if (sz == 1)
+             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]))
+             return ptname;
+   }
+   return 0;
+}
+
+#define UUID   1
+#define VOL    2
+
+/* for now, only ext2 is supported */
+static int
+has_right_label(const char *device, int n, const char *label) {
+
+       /* start with a test for ext2, taken from mount_guess_fstype */
+       int fd;
+       char *s;
+       struct ext2_super_block e2sb;
+
+       fd = open(device, O_RDONLY);
+       if (fd < 0)
+               return 0;
+
+       if (lseek(fd, 1024, SEEK_SET) != 1024
+           || read(fd, (char *) &e2sb, sizeof(e2sb)) != sizeof(e2sb)
+           || (ext2magic(e2sb) != EXT2_SUPER_MAGIC)) {
+               close(fd);
+               return 0;
+       }
+
+       close(fd);
+
+       /* superblock is ext2 - now what is its label? */
+       s = ((n == UUID) ? e2sb.s_uuid : e2sb.s_volume_name);
+       return (strncmp(s, label, 16) == 0);
+}
+
+static char *
+get_spec_by_x(int n, const char *t) {
+       char *pt;
+       char device[110];
+
+       if(!procptopen())
+               return NULL;
+       while((pt = procptnext()) != NULL) {
+               /* 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, pt);
+               if (has_right_label(device, n, t)) {
+                       procptclose();
+                       return strdup(device);
+               }
+       }
+       procptclose();
+       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 *s0) {
+       u_char uuid[16];
+       int i;
+       const char *s = s0;
+
+       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, "WARNING: %s: bad UUID", s0);
+       return NULL;
+}
+
+char *
+get_spec_by_volume_label(const char *s) {
+       return get_spec_by_x(VOL, s);
+}
diff --git a/misc/get_device_by_label.h b/misc/get_device_by_label.h
new file mode 100644 (file)
index 0000000..f87b27f
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * get_device_by_label.h
+ *
+ * Copyright 1999 by Andries Brouwer and Theodore Ts'o
+ *
+ * This file may be redistributed under the terms of the GNU Public
+ * License. 
+ */
+char *get_spec_by_uuid(const char *uuid);
+char *get_spec_by_volume_label(const char *volumelabel);