--- util-linux-ng-2.13/mount/mount.c.silly 2007-09-04 16:21:08.000000000 +0200 +++ util-linux-ng-2.13/mount/mount.c 2007-09-04 16:21:23.000000000 +0200 @@ -375,6 +375,101 @@ append_context(const char *optname, char } #endif +static void remove_non_handled_options(char* options, char* fs_type) { + + static char *fs_using_iocharset[] = { "iso9660", "udf", "vfat", "msdos", "ntfs", "jfs", "smbfs", "befs", "cifs", "hfs", NULL }; + static char *fs_using_codepage[] = { "vfat", "msdos", "smbfs", "hfs", NULL }; + static char *fs_using_umask[] = { "udf", "vfat", "msdos", "ntfs", "hfs", "hfsplus", "hpfs", NULL }; + static char *fs_using_mode[] = { "iso9660", "affs", "devpts", "tmpfs", NULL }; + static char *fs_using_nls[] = { "ntfs", "hfsplus", NULL }; + static char *fs_using_utf8[] = { "iso9660", "ntfs", "udf", "vfat", NULL }; + + static struct options_handled_for_some_fs { + char *handled_option; + char **fs_using_this_option; + } list[] = { + { "iocharset=", fs_using_iocharset }, + { "codepage=", fs_using_codepage }, + { "umask=", fs_using_umask }, + { "mode=", fs_using_mode }, + { "nls=", fs_using_nls }, + { "utf8", fs_using_utf8 }, + { NULL, NULL } + }; + + struct options_conflicting_from_some_fs { + char *type; + char *kept_option; + char *conflicting_option; + int match; + } conflict_list[] = { + { "udf", "iocharset=", "utf8", 0 }, + { NULL, NULL, NULL, 0 }, + }; + + if (options) { + char * newOpts = alloca(strlen(options) + 1); + char * end; + char * start = options; + + /* tag options that can lead to conflicts */ + while (*start) { + int i; + end = strchr(start, ','); + if (end) + end++; + else + end = start + strlen(start); + for (i = 0; conflict_list[i].type; i++) + if (strcmp(fs_type, conflict_list[i].type) == 0 && + strncmp(start, conflict_list[i].kept_option, strlen(conflict_list[i].kept_option)) == 0) + conflict_list[i].match = 1; + start = end; + } + + *newOpts = '\0'; + start = options; + + while (*start) { + int i, j, skip = 0; + + end = strchr(start, ','); + if (!end) { + end = start + strlen(start); + } else { + *end = '\0'; + end++; + } + + for (i = 0; list[i].handled_option; i++) + if (strncmp(start, list[i].handled_option, strlen(list[i].handled_option)) == 0) { + char **fs = list[i].fs_using_this_option; + skip = 1; + for (j = 0; fs[j]; j++) + if (strcmp(fs[j], fs_type) == 0) { + skip = 0; + break; + } + } + + for (i = 0; conflict_list[i].type; i++) + if (conflict_list[i].match && + strcmp(fs_type, conflict_list[i].type) == 0 && + strncmp(start, conflict_list[i].conflicting_option, strlen(conflict_list[i].conflicting_option)) == 0) + skip = 1; + + if (!skip) { + if (*newOpts) strcat(newOpts, ","); + strcat(newOpts, start); + } + + start = end; + } + + strcpy(options, newOpts); + } +} + /* * Look for OPT in opt_map table and return mask value. * If OPT isn't found, tack it onto extra_opts (which is non-NULL). @@ -610,6 +705,9 @@ do_mount_syscall (struct mountargs *args static int do_mount (struct mountargs *args, int *special, int *status) { int ret; + + if (args->type) remove_non_handled_options(args->data, args->type); + if (check_special_mountprog(args->spec, args->node, args->type, args->flags, args->data, status)) { *special = 1;