Whamcloud - gitweb
ChangeLog, fsck.8.in, fsck.c:
authorTheodore Ts'o <tytso@mit.edu>
Mon, 21 May 2001 02:15:15 +0000 (02:15 +0000)
committerTheodore Ts'o <tytso@mit.edu>
Mon, 21 May 2001 02:15:15 +0000 (02:15 +0000)
  fsck.8.in, fsck.c (compile_fs_type, fs_type, ignore): Fix handling of
   -t option to be more intuitive.  Also add support for the Mandrake -t
   loop hack.  See man page for description of new -t semantics.

misc/ChangeLog
misc/fsck.8.in
misc/fsck.c

index 47d04e4..ac3ac06 100644 (file)
@@ -1,5 +1,10 @@
 2001-05-20  Theodore Tso  <tytso@valinux.com>
 
+       * fsck.8.in, fsck.c (compile_fs_type, fs_type, ignore): Fix
+               handling of -t option to be more intuitive.  Also add
+               support for the Mandrake -t loop hack.  See man page
+               for description of new -t semantics.
+
        * fsck.c (device_already_active): Fix bug in
                device_already_active which could cause infinite loops if
                we don't know the base_device of the filesystem.
index 06a7834..7e53932 100644 (file)
@@ -86,29 +86,67 @@ option, if you wish for errors to be corrected automatically, or the
 .B \-n
 option if you do not.)
 .TP
-.BI \-t " fstype"
-Specifies the type of file system to be checked.  When the
+.BI \-t " fslist"
+Specifies the type(s) of file system to be checked.  When the
 .B \-A 
 flag is specified, only filesystems that match 
-.I fstype
-are checked.  If 
-.I fstype
-is prefixed with 
-.I no
-then only filesystems whose type does not match
-.I fstype
-are checked.
+.I fslist
+are checked.  The
+.I fslist
+parameter is a comma-separated list of filesystems and options
+specifiers.  All of the filesystems in this comma-separated list may be
+prefixed by a negation operator 
+.RB ' no '
+or 
+.RB ' ! ',
+which requests that only those filesystems not listed in
+.I fslist
+will be checked.  If all of the filesystems in 
+.I fslist
+are not prefixed by a negation operator, then only those filesystems
+listed
+in
+.I fslist
+will be checked.
+.sp
+Options specifiers may be included in the comma separated
+.IR fslist .
+They must have the format 
+.BI opts= fs-option\fR,
+and may be prefixed by a negation operator.  If an options specifier is
+present, then only filesystems whose 
+.B /etc/fstab
+entry do (or do not, if the options specifier was prefixed by a negation
+operator) contain 
+.I fs-option
+in their options field of the
+.B /etc/fstab 
+file will be checked.
+.sp
+For compatibility with Mandrake distributions whose boot scripts
+depend upon an unauthorized UI change to the
+.B fsck
+program, if a filesystem type of
+.B loop
+is found in
+.IR fslist ,
+it is treated as if
+.B opts=loop
+were specified as an argument to the
+.B \-t
+option.
 .sp
 Normally, the filesystem type is deduced by searching for
 .I filesys
 in the 
 .I /etc/fstab 
 file and using the corresponding entry.
-If the type can not be deduced, 
+If the type can not be deduced, and there is only a single filesystem 
+given as an argument to the 
+.B \-t 
+option, 
 .B fsck
-will use the type specified by the 
-.B \-t
-option if it specifies a unique filesystem type.  If this type is not
+will use the specified filesystem type.  If this type is not
 available, then the default file system type (currently ext2) is used. 
 .TP
 .B \-A
index 4a09c9c..0f233e1 100644 (file)
@@ -591,7 +591,9 @@ static void fsck_device(char *device, int interactive)
        struct fs_info *fsent;
        int retval;
 
-       if (fstype && strncmp(fstype, "no", 2) && !strchr(fstype, ','))
+       if (fstype && strncmp(fstype, "no", 2) &&
+           strncmp(fstype, "opts=", 5) && strncmp(fstype, "loop", 4) && 
+           !strchr(fstype, ','))
                type = fstype;
 
        if ((fsent = lookup(device))) {
@@ -610,31 +612,145 @@ static void fsck_device(char *device, int interactive)
        }
 }
 
-/* See if filesystem type matches the list. */
-static int fs_match(char *type, char *fs_type)
+
+/*
+ * Deal with the fsck -t argument.
+ */
+struct fs_type_compile {
+       char **list;
+       int *type;
+       int  negate;
+} fs_type_compiled;
+
+#define FS_TYPE_NORMAL 0
+#define FS_TYPE_OPT    1
+#define FS_TYPE_NEGOPT 2
+
+static const char *fs_type_syntax_error =
+_("Either all or none of the filesystem types passed to -t must be prefixed\n"
+  "with 'no' or '!'.\n");
+
+static void compile_fs_type(char *fs_type, struct fs_type_compile *cmp)
 {
-  int ret = 0, negate = 0;
-  char list[128];
-  char *s;
+       char    *cp, *list, *s;
+       int     num = 2;
+       int     negate, first_negate = 1;
+
+       if (fs_type) {
+               for (cp=fs_type; *cp; cp++) {
+                       if (*cp == ',')
+                               num++;
+               }
+       }
 
-  if (!fs_type) return(1);
+       cmp->list = malloc(num * sizeof(char *));
+       cmp->type = malloc(num * sizeof(int));
+       if (!cmp->list || !cmp->type) {
+               fprintf(stderr, _("Couldn't allocate memory for "
+                                 "filesystem types\n"));
+               exit(EXIT_ERROR);
+       }
+       memset(cmp->list, 0, num * sizeof(char *));
+       memset(cmp->type, 0, num * sizeof(int));
+       cmp->negate = 0;
 
-  if (strncmp(fs_type, "no", 2) == 0) {
-       fs_type += 2;
-       negate = 1;
-  }
-  strcpy(list, fs_type);
-  s = strtok(list, ",");
-  while(s) {
-       if (strcmp(s, type) == 0) {
-               ret = 1;
-               break;
-       }
-       s = strtok(NULL, ",");
-  }
-  return(negate ? !ret : ret);
+       if (!fs_type)
+               return;
+       
+       list = string_copy(fs_type);
+       num = 0;
+       s = strtok(list, ",");
+       while(s) {
+               negate = 0;
+               if (strncmp(s, "no", 2) == 0) {
+                       s += 2;
+                       negate = 1;
+               } else if (*s == '!') {
+                       s++;
+                       negate = 1;
+               }
+               if (strcmp(s, "loop") == 0)
+                       /* loop is really short-hand for opts=loop */
+                       goto loop_special_case;
+               else if (strncmp(s, "opts=", 5) == 0) {
+                       s += 5;
+               loop_special_case:
+                       cmp->type[num] = negate ? FS_TYPE_NEGOPT : FS_TYPE_OPT;
+               } else {
+                       if (first_negate) {
+                               cmp->negate = negate;
+                               first_negate = 0;
+                       }
+                       if ((negate && !cmp->negate) ||
+                           (!negate && cmp->negate)) {
+                               fprintf(stderr, fs_type_syntax_error);
+                               exit(EXIT_USAGE);
+                       }
+               }
+#if 0
+               printf("Adding %s to list (type %d).\n", s, cmp->type[num]);
+#endif
+               cmp->list[num++] = string_copy(s);
+               s = strtok(NULL, ",");
+       }
+       free(list);
+}
+
+/*
+ * This function returns true if a particular option appears in a
+ * comma-delimited options list
+ */
+static int opt_in_list(char *opt, char *optlist)
+{
+       char    *list, *s;
+
+       if (!optlist)
+               return 0;
+       list = string_copy(optlist);
+       
+       s = strtok(list, ",");
+       while(s) {
+               if (strcmp(s, opt) == 0) {
+                       free(list);
+                       return 1;
+               }
+               s = strtok(NULL, ",");
+       }
+        free(list);
+       return 0;
 }
 
+/* See if the filesystem matches the criteria given by the -t option */
+static int fs_match(struct fs_info *fs, struct fs_type_compile *cmp)
+{
+       int n, ret = 0, checked_type = 0;
+       char *cp;
+
+       if (cmp->list == 0 || cmp->list[0] == 0)
+               return 1;
+
+       for (n=0; cp = cmp->list[n]; n++) {
+               switch (cmp->type[n]) {
+               case FS_TYPE_NORMAL:
+                       checked_type++;
+                       if (strcmp(cp, fs->type) == 0) {
+                               ret = 1;
+                       }
+                       break;
+               case FS_TYPE_NEGOPT:
+                       if (opt_in_list(cp, fs->opts))
+                               return 0;
+                       break;
+               case FS_TYPE_OPT:
+                       if (!opt_in_list(cp, fs->opts))
+                               return 0;
+                       break;
+               }
+       }
+       if (checked_type == 0)
+               return 1;
+       return (cmp->negate ? !ret : ret);
+}
 
 /* Check if we should ignore this filesystem. */
 static int ignore(struct fs_info *fs)
@@ -652,7 +768,7 @@ static int ignore(struct fs_info *fs)
         * If a specific fstype is specified, and it doesn't match,
         * ignore it.
         */
-       if (!fs_match(fs->type, fstype)) return 1;
+       if (!fs_match(fs, &fs_type_compiled)) return 1;
        
        /* Are we ignoring this type? */
        for(ip = ignored_types; *ip; ip++)
@@ -894,11 +1010,13 @@ static void PRS(int argc, char *argv[])
                        case 't':
                                if (arg[j+1]) {
                                        fstype = string_copy(arg+j+1);
+                                       compile_fs_type(fstype, &fs_type_compiled);
                                        goto next_arg;
                                }
                                if ((i+1) < argc) {
                                        i++;
                                        fstype = string_copy(argv[i]);
+                                       compile_fs_type(fstype, &fs_type_compiled);
                                        goto next_arg;
                                }
                                usage();