Bruce Dubbs wrote:
Alexander E. Patrakov wrote:

2) make a kernel patch (only 11 added or changed lines) that makes this setting available as a module parameter for nls_base.ko (thus also allowing modification at runtime via sysfs) -

Do this.  Even if they don't accept it, the issue is valid and the
kernel devs will probably fix it.

Here is a preliminary version of the patch. Everyone with experience in kernel development is welcome to look before I submit this to LKML.

The user-visible results of this patch are:

* Reworded the description of CONFIG_NLS_DEFAULT, because at some point in the past it confused Jim Gifford. * Removed CONFIG_FAT_DEFAULT_IOCHARSET, now CONFIG_NLS_DEFAULT is used for this purpose * Merged the two CONFIG_SMB_NLS_REMOTE and CONFIG_FAT_DEFAULT_CODEPAGE options into one, named CONFIG_CODEPAGE_DEFAULT * Made the FAT filesystem accept both the old-style "codepage=866" mount option (which is inconsistent with other filesystems requiring a codepage option) and the new-style "codepage=cp866" option. * Made CONFIG_NLS_DEFAULT and CONFIG_CODEPAGE_DEFAULT effectively adjustable at runtime via the following mechanisms:

* If the nls_base.ko module is really a module, it is sufficient to write in modprobe.conf something like this:

options nls_base iocharset=koi8-r codepage=cp866

   * If it is not a module, add this to the kernel command line in GRUB:

nls_base.iocharset=koi8-r nls_base.codepage=cp866

   * In both cases, writing into sysfs also works:

echo -n koi8-r >/sys/module/nls_base/parameters/iocharset
echo -n cp866 >/sys/module/nls_base/parameters/codepage

(of course, for the LKML submission, I will convert module_param_string to module_param_call, so that the final newline in the third case is stripped automatically and the -n switch is not needed)

--
Alexander E. Patrakov
diff -ur linux-2.6.20.1/include/linux/msdos_fs.h linux-2.6.20.1.new/include/linux/msdos_fs.h
--- linux-2.6.20.1/include/linux/msdos_fs.h	2007-02-20 11:34:32.000000000 +0500
+++ linux-2.6.20.1.new/include/linux/msdos_fs.h	2007-03-15 20:58:37.000000000 +0500
@@ -191,7 +191,7 @@
 	gid_t fs_gid;
 	unsigned short fs_fmask;
 	unsigned short fs_dmask;
-	unsigned short codepage;  /* Codepage for shortname conversions */
+	char *codepage;           /* Codepage for shortname conversions */
 	char *iocharset;          /* Charset used for filename input/display */
 	unsigned short shortname; /* flags for shortname display/create rule */
 	unsigned char name_check; /* r = relaxed, n = normal, s = strict */
diff -ur linux-2.6.20.1/include/linux/nls.h linux-2.6.20.1.new/include/linux/nls.h
--- linux-2.6.20.1/include/linux/nls.h	2007-02-20 11:34:32.000000000 +0500
+++ linux-2.6.20.1.new/include/linux/nls.h	2007-03-15 19:44:40.000000000 +0500
@@ -3,6 +3,11 @@
 
 #include <linux/init.h>
 
+#define NLS_MAXNAMELEN 20
+
+extern char default_iocharset[NLS_MAXNAMELEN];
+extern char default_codepage[NLS_MAXNAMELEN];
+
 /* unicode character */
 typedef __u16 wchar_t;
 
diff -ur linux-2.6.20.1/include/linux/smb.h linux-2.6.20.1.new/include/linux/smb.h
--- linux-2.6.20.1/include/linux/smb.h	2007-02-20 11:34:32.000000000 +0500
+++ linux-2.6.20.1.new/include/linux/smb.h	2007-03-15 19:44:16.000000000 +0500
@@ -11,6 +11,7 @@
 
 #include <linux/types.h>
 #include <linux/magic.h>
+#include <linux/nls.h>
 
 enum smb_protocol { 
 	SMB_PROTOCOL_NONE, 
@@ -63,10 +64,9 @@
 
 #ifdef __KERNEL__
 
-#define SMB_NLS_MAXNAMELEN 20
 struct smb_nls_codepage {
-	char local_name[SMB_NLS_MAXNAMELEN];
-	char remote_name[SMB_NLS_MAXNAMELEN];
+	char local_name[NLS_MAXNAMELEN];
+	char remote_name[NLS_MAXNAMELEN];
 };
 
 
diff -ur linux-2.6.20.1/fs/fat/inode.c linux-2.6.20.1.new/fs/fat/inode.c
--- linux-2.6.20.1/fs/fat/inode.c	2007-02-20 11:34:32.000000000 +0500
+++ linux-2.6.20.1.new/fs/fat/inode.c	2007-03-15 21:49:09.000000000 +0500
@@ -27,15 +27,6 @@
 #include <linux/writeback.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;
-
-
 static int fat_add_cluster(struct inode *inode)
 {
 	int err, cluster;
@@ -462,15 +453,18 @@
 	if (sbi->nls_disk) {
 		unload_nls(sbi->nls_disk);
 		sbi->nls_disk = NULL;
-		sbi->options.codepage = fat_default_codepage;
 	}
 	if (sbi->nls_io) {
 		unload_nls(sbi->nls_io);
 		sbi->nls_io = NULL;
 	}
-	if (sbi->options.iocharset != fat_default_iocharset) {
+	if (sbi->options.iocharset != default_iocharset) {
 		kfree(sbi->options.iocharset);
-		sbi->options.iocharset = fat_default_iocharset;
+		sbi->options.iocharset = default_iocharset;
+	}
+	if (sbi->options.codepage != default_codepage) {
+		kfree(sbi->options.codepage);
+		sbi->options.codepage = default_codepage;
 	}
 
 	sb->s_fs_info = NULL;
@@ -869,7 +863,7 @@
 	{Opt_umask, "umask=%o"},
 	{Opt_dmask, "dmask=%o"},
 	{Opt_fmask, "fmask=%o"},
-	{Opt_codepage, "codepage=%u"},
+	{Opt_codepage, "codepage=%s"},
 	{Opt_nocase, "nocase"},
 	{Opt_quiet, "quiet"},
 	{Opt_showexec, "showexec"},
@@ -933,14 +927,15 @@
 	substring_t args[MAX_OPT_ARGS];
 	int option;
 	char *iocharset;
+	char *codepage;
 
 	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 = fat_default_codepage;
-	opts->iocharset = fat_default_iocharset;
+	opts->codepage = default_codepage;
+	opts->iocharset = default_iocharset;
 	if (is_vfat)
 		opts->shortname = VFAT_SFN_DISPLAY_LOWER|VFAT_SFN_CREATE_WIN95;
 	else
@@ -1024,9 +1019,12 @@
 			opts->fs_fmask = option;
 			break;
 		case Opt_codepage:
-			if (match_int(&args[0], &option))
-				return 0;
-			opts->codepage = option;
+			if (opts->codepage != default_codepage)
+				kfree(opts->codepage);
+			codepage = match_strdup(&args[0]);
+			if (!codepage)
+				return -ENOMEM;
+			opts->codepage = codepage;
 			break;
 		case Opt_flush:
 			opts->flush = 1;
@@ -1042,7 +1040,7 @@
 
 		/* vfat specific */
 		case Opt_charset:
-			if (opts->iocharset != fat_default_iocharset)
+			if (opts->iocharset != default_iocharset)
 				kfree(opts->iocharset);
 			iocharset = match_strdup(&args[0]);
 			if (!iocharset)
@@ -1101,8 +1099,8 @@
 	}
 	/* UTF-8 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");
+		printk(KERN_INFO "FAT: utf8 IO charset"
+		       " is used, filesystem will be case sensitive!\n");
 	}
 
 	if (opts->unicode_xlate)
@@ -1162,7 +1160,6 @@
 	int debug;
 	unsigned int media;
 	long error;
-	char buf[50];
 
 	sbi = kzalloc(sizeof(struct msdos_sb_info), GFP_KERNEL);
 	if (!sbi)
@@ -1372,10 +1369,18 @@
 	 */
 
 	error = -EINVAL;
-	sprintf(buf, "cp%d", sbi->options.codepage);
-	sbi->nls_disk = load_nls(buf);
+	
+	sbi->nls_disk = load_nls(sbi->options.codepage);
+	if (!sbi->nls_disk) {
+		/* Maybe the old non-standard codepage specification is used */
+		char buf[NLS_MAXNAMELEN];
+		snprintf(buf, sizeof(buf), "cp%s", sbi->options.codepage);
+		buf[sizeof(buf) - 1] = 0;
+		sbi->nls_disk = load_nls(buf);
+	}
+
 	if (!sbi->nls_disk) {
-		printk(KERN_ERR "FAT: codepage %s not found\n", buf);
+		printk(KERN_ERR "FAT: codepage %s not found\n", sbi->options.codepage);
 		goto out_fail;
 	}
 
@@ -1421,8 +1426,10 @@
 		unload_nls(sbi->nls_io);
 	if (sbi->nls_disk)
 		unload_nls(sbi->nls_disk);
-	if (sbi->options.iocharset != fat_default_iocharset)
+	if (sbi->options.iocharset != default_iocharset)
 		kfree(sbi->options.iocharset);
+	if (sbi->options.codepage != default_codepage)
+		kfree(sbi->options.codepage);
 	sb->s_fs_info = NULL;
 	kfree(sbi);
 	return error;
diff -ur linux-2.6.20.1/fs/isofs/inode.c linux-2.6.20.1.new/fs/isofs/inode.c
--- linux-2.6.20.1/fs/isofs/inode.c	2007-02-20 11:34:32.000000000 +0500
+++ linux-2.6.20.1.new/fs/isofs/inode.c	2007-03-15 19:34:11.000000000 +0500
@@ -773,7 +773,7 @@
 
 #ifdef CONFIG_JOLIET
 	if (joliet_level && opt.utf8 == 0) {
-		char * p = opt.iocharset ? opt.iocharset : CONFIG_NLS_DEFAULT;
+		char * p = opt.iocharset ? opt.iocharset : default_iocharset;
 		sbi->s_nls_iocharset = load_nls(p);
 		if (! sbi->s_nls_iocharset) {
 			/* Fail only if explicit charset specified */
diff -ur linux-2.6.20.1/fs/Kconfig linux-2.6.20.1.new/fs/Kconfig
--- linux-2.6.20.1/fs/Kconfig	2007-02-20 11:34:32.000000000 +0500
+++ linux-2.6.20.1.new/fs/Kconfig	2007-03-15 21:34:17.000000000 +0500
@@ -785,28 +785,6 @@
 	  To compile this as a module, choose M here: the module will be called
 	  vfat.
 
-config FAT_DEFAULT_CODEPAGE
-	int "Default codepage for FAT"
-	depends on MSDOS_FS || VFAT_FS
-	default 437
-	help
-	  This option should be set to the codepage of your FAT filesystems.
-	  It can be overridden with the "codepage" mount option.
-	  See <file:Documentation/filesystems/vfat.txt> for more information.
-
-config FAT_DEFAULT_IOCHARSET
-	string "Default iocharset for FAT"
-	depends on VFAT_FS
-	default "iso8859-1"
-	help
-	  Set this to the default input/output character set you'd
-	  like FAT to use. It should probably match the character set
-	  that most of your FAT filesystems use, and can be overridden
-	  with the "iocharset" mount option for FAT filesystems.
-	  Note that "utf8" is not recommended for FAT filesystems.
-	  If unsure, you shouldn't set "utf8" here.
-	  See <file:Documentation/filesystems/vfat.txt> for more information.
-
 config NTFS_FS
 	tristate "NTFS file system support"
 	select NLS
@@ -1844,21 +1822,6 @@
 
 	  smbmount from samba 2.2.0 or later supports this.
 
-config SMB_NLS_REMOTE
-	string "Default Remote NLS Option"
-	depends on SMB_NLS_DEFAULT
-	default "cp437"
-	help
-	  This setting allows you to specify a default value for which
-	  codepage the server uses. If this field is left blank no
-	  translations will be done by default. The local codepage/charset
-	  default to CONFIG_NLS_DEFAULT.
-
-	  The nls settings can be changed at mount time, if your smbmount
-	  supports that, using the codepage and iocharset parameters.
-
-	  smbmount from samba 2.2.0 or later supports this.
-
 config CIFS
 	tristate "CIFS support (advanced network filesystem for Samba, Window and other CIFS compliant servers)"
 	depends on INET
diff -ur linux-2.6.20.1/fs/nls/Kconfig linux-2.6.20.1.new/fs/nls/Kconfig
--- linux-2.6.20.1/fs/nls/Kconfig	2007-02-20 11:34:32.000000000 +0500
+++ linux-2.6.20.1.new/fs/nls/Kconfig	2007-03-15 20:04:38.000000000 +0500
@@ -18,13 +18,13 @@
 	  will be called nls_base.
 
 config NLS_DEFAULT
-	string "Default NLS Option"
+	string "Default UNIX NLS Option"
 	depends on NLS
 	default "iso8859-1"
 	---help---
-	  The default NLS used when mounting file system. Note, that this is
-	  the NLS used by your console, not the NLS used by a specific file
-	  system (if different) to store data (filenames) on a disk.
+	  The default UNIX NLS used when mounting file system. Note, that
+	  this is the NLS expected by the "ls" command, ot the NLS used
+	  internally by a specific file system to store filenames on a disk.
 	  Currently, the valid values are:
 	  big5, cp437, cp737, cp775, cp850, cp852, cp855, cp857, cp860, cp861,
 	  cp862, cp863, cp864, cp865, cp866, cp869, cp874, cp932, cp936,
@@ -37,6 +37,26 @@
 
 	  If unsure, specify it as "iso8859-1".
 
+config CODEPAGE_DEFAULT
+	string "Default MS-DOS NLS Option"
+	depends on NLS
+	default "cp437"
+	---help---
+	  The default MS-DOS NLS used when mounting file systems with MS-DOS
+	  origin. Note, that this is the NLS used internally by these file
+	  systems to store filenames on a disk or for transmission over a
+	  network, not the NLS expected by the "ls"  command.
+	  Currently, the valid values are:
+	  big5, cp437, cp737, cp775, cp850, cp852, cp855, cp857, cp860, cp861,
+	  cp862, cp863, cp864, cp865, cp866, cp869, cp874, cp932, cp936,
+	  cp949, cp950, cp1251, cp1255, euc-jp, euc-kr, gb2312, iso8859-1,
+	  iso8859-2, iso8859-3, iso8859-4, iso8859-5, iso8859-6, iso8859-7,
+	  iso8859-8, iso8859-9, iso8859-13, iso8859-14, iso8859-15,
+	  koi8-r, koi8-ru, koi8-u, sjis, tis-620, utf8.
+	  If you specify a wrong value, mounting will fail.
+
+	  If unsure, specify it as "cp437".
+
 config NLS_CODEPAGE_437
 	tristate "Codepage 437 (United States, Canada)"
 	depends on NLS
diff -ur linux-2.6.20.1/fs/nls/nls_base.c linux-2.6.20.1.new/fs/nls/nls_base.c
--- linux-2.6.20.1/fs/nls/nls_base.c	2007-02-20 11:34:32.000000000 +0500
+++ linux-2.6.20.1.new/fs/nls/nls_base.c	2007-03-15 19:45:59.000000000 +0500
@@ -18,6 +18,9 @@
 #endif
 #include <linux/spinlock.h>
 
+char default_iocharset[NLS_MAXNAMELEN];
+char default_codepage[NLS_MAXNAMELEN];
+
 static struct nls_table default_table;
 static struct nls_table *tables = &default_table;
 static DEFINE_SPINLOCK(nls_lock);
@@ -474,13 +477,27 @@
 {
 	struct nls_table *default_nls;
 	
-	default_nls = load_nls(CONFIG_NLS_DEFAULT);
+	default_nls = load_nls(default_iocharset);
 	if (default_nls != NULL)
 		return default_nls;
 	else
 		return &default_table;
 }
 
+static int __init nls_init(void)
+{
+	strcpy(default_iocharset, CONFIG_NLS_DEFAULT);
+	strcpy(default_codepage, CONFIG_CODEPAGE_DEFAULT);
+	return 0;
+}
+
+static void __exit nls_exit(void)
+{
+}
+
+module_init(nls_init);
+module_exit(nls_exit);
+
 EXPORT_SYMBOL(register_nls);
 EXPORT_SYMBOL(unregister_nls);
 EXPORT_SYMBOL(unload_nls);
@@ -490,5 +507,13 @@
 EXPORT_SYMBOL(utf8_mbstowcs);
 EXPORT_SYMBOL(utf8_wctomb);
 EXPORT_SYMBOL(utf8_wcstombs);
+EXPORT_SYMBOL(default_iocharset);
+EXPORT_SYMBOL(default_codepage);
+
+module_param_string(iocharset, default_iocharset, NLS_MAXNAMELEN, 0644);
+MODULE_PARM_DESC(iocharset, "Default UNIX filename charset");
+
+module_param_string(codepage, default_codepage, NLS_MAXNAMELEN, 0644);
+MODULE_PARM_DESC(codepage, "Default MS-DOS filename charset");
 
 MODULE_LICENSE("Dual BSD/GPL");
diff -ur linux-2.6.20.1/fs/smbfs/inode.c linux-2.6.20.1.new/fs/smbfs/inode.c
--- linux-2.6.20.1/fs/smbfs/inode.c	2007-02-20 11:34:32.000000000 +0500
+++ linux-2.6.20.1.new/fs/smbfs/inode.c	2007-03-15 19:57:42.000000000 +0500
@@ -36,13 +36,6 @@
 #include "getopt.h"
 #include "proto.h"
 
-/* Always pick a default string */
-#ifdef CONFIG_SMB_NLS_REMOTE
-#define SMB_NLS_REMOTE CONFIG_SMB_NLS_REMOTE
-#else
-#define SMB_NLS_REMOTE ""
-#endif
-
 #define SMB_TTL_DEFAULT 1000
 
 static void smb_delete_inode(struct inode *);
@@ -396,11 +389,11 @@
 			break;
 		case 'i':
 			strlcpy(mnt->codepage.local_name, optarg, 
-				SMB_NLS_MAXNAMELEN);
+				NLS_MAXNAMELEN);
 			break;
 		case 'c':
 			strlcpy(mnt->codepage.remote_name, optarg,
-				SMB_NLS_MAXNAMELEN);
+				NLS_MAXNAMELEN);
 			break;
 		case 't':
 			mnt->ttl = value;
@@ -446,10 +439,8 @@
 	if (mnt->flags & SMB_MOUNT_DMODE)
 		seq_printf(s, ",dir_mode=%04o", mnt->dir_mode & S_IRWXUGO);
 
-	if (strcmp(mnt->codepage.local_name, CONFIG_NLS_DEFAULT))
-		seq_printf(s, ",iocharset=%s", mnt->codepage.local_name);
-	if (strcmp(mnt->codepage.remote_name, SMB_NLS_REMOTE))
-		seq_printf(s, ",codepage=%s", mnt->codepage.remote_name);
+	seq_printf(s, ",iocharset=%s", mnt->codepage.local_name);
+	seq_printf(s, ",codepage=%s", mnt->codepage.remote_name);
 
 	if (mnt->ttl != SMB_TTL_DEFAULT)
 		seq_printf(s, ",ttl=%d", mnt->ttl);
@@ -555,10 +546,10 @@
 	mnt = server->mnt;
 
 	memset(mnt, 0, sizeof(struct smb_mount_data_kernel));
-	strlcpy(mnt->codepage.local_name, CONFIG_NLS_DEFAULT,
-		SMB_NLS_MAXNAMELEN);
-	strlcpy(mnt->codepage.remote_name, SMB_NLS_REMOTE,
-		SMB_NLS_MAXNAMELEN);
+	strlcpy(mnt->codepage.local_name, default_iocharset,
+		NLS_MAXNAMELEN);
+	strlcpy(mnt->codepage.remote_name, default_codepage,
+		NLS_MAXNAMELEN);
 
 	mnt->ttl = SMB_TTL_DEFAULT;
 	if (ver == SMB_MOUNT_OLDVERSION) {
-- 
http://linuxfromscratch.org/mailman/listinfo/blfs-dev
FAQ: http://www.linuxfromscratch.org/blfs/faq.html
Unsubscribe: See the above information page

Reply via email to