summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2001-05-21 02:15:15 +0000
committerTheodore Ts'o <tytso@mit.edu>2001-05-21 02:15:15 +0000
commit10a32f1e03b198ae408e1af6a412f993678be33d (patch)
tree215529448dc09afe5ddfe7577cf9fbde383adec6
parent9164b862ff73810e045c7499a15f87ca1b578cfb (diff)
downloade2fsprogs-10a32f1e03b198ae408e1af6a412f993678be33d.tar.gz
ChangeLog, fsck.8.in, fsck.c:
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.
-rw-r--r--misc/ChangeLog5
-rw-r--r--misc/fsck.8.in66
-rw-r--r--misc/fsck.c162
3 files changed, 197 insertions, 36 deletions
diff --git a/misc/ChangeLog b/misc/ChangeLog
index 47d04e4c..ac3ac067 100644
--- a/misc/ChangeLog
+++ b/misc/ChangeLog
@@ -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.
diff --git a/misc/fsck.8.in b/misc/fsck.8.in
index 06a78342..7e539329 100644
--- a/misc/fsck.8.in
+++ b/misc/fsck.8.in
@@ -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
diff --git a/misc/fsck.c b/misc/fsck.c
index 4a09c9c3..0f233e1b 100644
--- a/misc/fsck.c
+++ b/misc/fsck.c
@@ -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();