From: Theodore Ts'o Date: Mon, 21 May 2001 02:15:15 +0000 (+0000) Subject: ChangeLog, fsck.8.in, fsck.c: X-Git-Tag: E2FSPROGS-1_20~19 X-Git-Url: https://git.whamcloud.com/gitweb?a=commitdiff_plain;h=10a32f1e03b198ae408e1af6a412f993678be33d;p=tools%2Fe2fsprogs.git 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. --- diff --git a/misc/ChangeLog b/misc/ChangeLog index 47d04e4..ac3ac06 100644 --- a/misc/ChangeLog +++ b/misc/ChangeLog @@ -1,5 +1,10 @@ 2001-05-20 Theodore Tso + * 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 06a7834..7e53932 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 4a09c9c..0f233e1 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();