VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / fs / fat / inode.c
index 0da65be..c0fc6b7 100644 (file)
 #include <linux/parser.h>
 #include <asm/unaligned.h>
 
+#ifndef CONFIG_FAT_DEFAULT_IOCHARSET
+/* if user don't select VFAT, this is undefined. */
+#define CONFIG_FAT_DEFAULT_IOCHARSET   ""
+#endif
+
+static int fat_default_codepage = CONFIG_FAT_DEFAULT_CODEPAGE;
+static char fat_default_iocharset[] = CONFIG_FAT_DEFAULT_IOCHARSET;
+
 /*
  * New FAT inode stuff. We do the following:
  *     a) i_ino is constant and has nothing with on-disk location.
@@ -166,20 +174,17 @@ void fat_put_super(struct super_block *sb)
        if (sbi->nls_disk) {
                unload_nls(sbi->nls_disk);
                sbi->nls_disk = NULL;
-               sbi->options.codepage = 0;
+               sbi->options.codepage = fat_default_codepage;
        }
        if (sbi->nls_io) {
                unload_nls(sbi->nls_io);
                sbi->nls_io = NULL;
        }
-       /*
-        * Note: the iocharset option might have been specified
-        * without enabling nls_io, so check for it here.
-        */
-       if (sbi->options.iocharset) {
+       if (sbi->options.iocharset != fat_default_iocharset) {
                kfree(sbi->options.iocharset);
-               sbi->options.iocharset = NULL;
+               sbi->options.iocharset = fat_default_iocharset;
        }
+
        sb->s_fs_info = NULL;
        kfree(sbi);
 }
@@ -196,11 +201,11 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt)
                seq_printf(m, ",gid=%u", opts->fs_gid);
        seq_printf(m, ",fmask=%04o", opts->fs_fmask);
        seq_printf(m, ",dmask=%04o", opts->fs_dmask);
-       if (sbi->nls_disk)
+       if (sbi->nls_disk && opts->codepage != fat_default_codepage)
                seq_printf(m, ",codepage=%s", sbi->nls_disk->charset);
        if (isvfat) {
-               if (sbi->nls_io
-                   && strcmp(sbi->nls_io->charset, CONFIG_NLS_DEFAULT))
+               if (sbi->nls_io &&
+                   strcmp(opts->iocharset, fat_default_iocharset))
                        seq_printf(m, ",iocharset=%s", sbi->nls_io->charset);
 
                switch (opts->shortname) {
@@ -331,14 +336,15 @@ static int parse_options(char *options, int is_vfat, int *debug,
        char *p;
        substring_t args[MAX_OPT_ARGS];
        int option;
+       char *iocharset;
 
        opts->isvfat = is_vfat;
 
        opts->fs_uid = current->uid;
        opts->fs_gid = current->gid;
        opts->fs_fmask = opts->fs_dmask = current->fs->umask;
-       opts->codepage = 0;
-       opts->iocharset = NULL;
+       opts->codepage = fat_default_codepage;
+       opts->iocharset = fat_default_iocharset;
        if (is_vfat)
                opts->shortname = VFAT_SFN_DISPLAY_LOWER|VFAT_SFN_CREATE_WIN95;
        else
@@ -351,7 +357,7 @@ static int parse_options(char *options, int is_vfat, int *debug,
        *debug = 0;
 
        if (!options)
-               return 1;
+               return 0;
 
        while ((p = strsep(&options, ",")) != NULL) {
                int token;
@@ -437,10 +443,12 @@ static int parse_options(char *options, int is_vfat, int *debug,
 
                /* vfat specific */
                case Opt_charset:
-                       kfree(opts->iocharset);
-                       opts->iocharset = match_strdup(&args[0]);
-                       if (!opts->iocharset)
-                               return 0;
+                       if (opts->iocharset != fat_default_iocharset)
+                               kfree(opts->iocharset);
+                       iocharset = match_strdup(&args[0]);
+                       if (!iocharset)
+                               return -ENOMEM;
+                       opts->iocharset = iocharset;
                        break;
                case Opt_shortname_lower:
                        opts->shortname = VFAT_SFN_DISPLAY_LOWER
@@ -486,14 +494,19 @@ static int parse_options(char *options, int is_vfat, int *debug,
                default:
                        printk(KERN_ERR "FAT: Unrecognized mount option \"%s\" "
                               "or missing value\n", p);
-                       return 0;
+                       return -EINVAL;
                }
        }
+       /* UTF8 doesn't provide FAT semantics */
+       if (!strcmp(opts->iocharset, "utf8")) {
+               printk(KERN_ERR "FAT: utf8 is not a recommended IO charset"
+                      " for FAT filesystems, filesystem will be case sensitive!\n");
+       }
 
        if (opts->unicode_xlate)
                opts->utf8 = 0;
        
-       return 1;
+       return 0;
 }
 
 static int fat_calc_dir_size(struct inode *inode)
@@ -784,7 +797,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
        struct msdos_sb_info *sbi;
        u16 logical_sector_size;
        u32 total_sectors, total_clusters, fat_clusters, rootdir_sectors;
-       int debug, cp, first;
+       int debug, first;
        unsigned int media;
        long error;
        char buf[50];
@@ -801,8 +814,8 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
        sb->s_export_op = &fat_export_ops;
        sbi->dir_ops = fs_dir_inode_ops;
 
-       error = -EINVAL;
-       if (!parse_options(data, isvfat, &debug, &sbi->options))
+       error = parse_options(data, isvfat, &debug, &sbi->options);
+       if (error)
                goto out_fail;
 
        fat_cache_init(sb);
@@ -830,18 +843,12 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
                brelse(bh);
                goto out_invalid;
        }
-       if (!b->secs_track) {
-               if (!silent)
-                       printk(KERN_ERR "FAT: bogus sectors-per-track value\n");
-               brelse(bh);
-               goto out_invalid;
-       }
-       if (!b->heads) {
-               if (!silent)
-                       printk(KERN_ERR "FAT: bogus number-of-heads value\n");
-               brelse(bh);
-               goto out_invalid;
-       }
+
+       /*
+        * Earlier we checked here that b->secs_track and b->head are nonzero,
+        * but it turns out valid FAT filesystems can have zero there.
+        */
+
        media = b->media;
        if (!FAT_VALID_MEDIA(media)) {
                if (!silent)
@@ -1009,31 +1016,21 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
        }
 
        error = -EINVAL;
-       cp = sbi->options.codepage ? sbi->options.codepage : 437;
-       sprintf(buf, "cp%d", cp);
+       sprintf(buf, "cp%d", sbi->options.codepage);
        sbi->nls_disk = load_nls(buf);
        if (!sbi->nls_disk) {
-               /* Fail only if explicit charset specified */
-               if (sbi->options.codepage != 0) {
-                       printk(KERN_ERR "FAT: codepage %s not found\n", buf);
-                       goto out_fail;
-               }
-               sbi->options.codepage = 0; /* already 0?? */
-               sbi->nls_disk = load_nls_default();
+               printk(KERN_ERR "FAT: codepage %s not found\n", buf);
+               goto out_fail;
        }
 
        /* FIXME: utf8 is using iocharset for upper/lower conversion */
        if (sbi->options.isvfat) {
-               if (sbi->options.iocharset != NULL) {
-                       sbi->nls_io = load_nls(sbi->options.iocharset);
-                       if (!sbi->nls_io) {
-                               printk(KERN_ERR
-                                      "FAT: IO charset %s not found\n",
-                                      sbi->options.iocharset);
-                               goto out_fail;
-                       }
-               } else
-                       sbi->nls_io = load_nls_default();
+               sbi->nls_io = load_nls(sbi->options.iocharset);
+               if (!sbi->nls_io) {
+                       printk(KERN_ERR "FAT: IO charset %s not found\n",
+                              sbi->options.iocharset);
+                       goto out_fail;
+               }
        }
 
        error = -ENOMEM;
@@ -1068,7 +1065,7 @@ out_fail:
                unload_nls(sbi->nls_io);
        if (sbi->nls_disk)
                unload_nls(sbi->nls_disk);
-       if (sbi->options.iocharset)
+       if (sbi->options.iocharset != fat_default_iocharset)
                kfree(sbi->options.iocharset);
        sb->s_fs_info = NULL;
        kfree(sbi);