[linux-cifs-client] [PATCH 3/7] [CIFS] add codepage= mount option
and have it set up remote_nls
Jeff Layton
jlayton at redhat.com
Fri Jul 25 15:23:16 GMT 2008
For non-ASCII, non-UTF8 legacy servers, we need to be able to translate
to and from their codepage. Add a "codepage" mount option that performs
a similar function to the one used in smbfs. The idea is to translate
strings to and from our local character set from and to the remote one.
Signed-off-by: Jeff Layton <jlayton at redhat.com>
---
fs/cifs/cifs_fs_sb.h | 1 +
fs/cifs/cifsfs.c | 4 ++++
fs/cifs/connect.c | 29 +++++++++++++++++++++++++++++
3 files changed, 34 insertions(+), 0 deletions(-)
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index 877c854..41e46b9 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -36,6 +36,7 @@ struct cifs_sb_info {
struct cifsTconInfo *tcon; /* primary mount */
struct list_head nested_tcon_q;
struct nls_table *local_nls;
+ struct nls_table *remote_nls;
unsigned int rsize;
unsigned int wsize;
uid_t mnt_uid;
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 22857c6..0fb9ff2 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -185,6 +185,8 @@ out_mount_failed:
#endif
if (cifs_sb->local_nls)
unload_nls(cifs_sb->local_nls);
+ if (cifs_sb->remote_nls)
+ unload_nls(cifs_sb->remote_nls);
kfree(cifs_sb);
}
return rc;
@@ -213,6 +215,8 @@ cifs_put_super(struct super_block *sb)
#endif
unload_nls(cifs_sb->local_nls);
+ if (cifs_sb->remote_nls)
+ unload_nls(cifs_sb->remote_nls);
kfree(cifs_sb);
return;
}
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 0332961..f4cff66 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -62,6 +62,7 @@ struct smb_vol {
char *UNCip;
char *in6_addr; /* ipv6 address as human readable form of in6_addr */
char *iocharset; /* local code page for mapping to and from Unicode */
+ char *codepage; /* remote code page in use by server */
char source_rfc1001_name[16]; /* netbios name of client */
char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */
uid_t linux_uid;
@@ -1086,6 +1087,21 @@ cifs_parse_mount_options(char *options, const char *devname,
"too long.\n");
return 1;
}
+ } else if (strnicmp(data, "codepage", 8) == 0) {
+ if (!value || !*value) {
+ printk(KERN_WARNING "CIFS: invalid codepage "
+ "specified\n");
+ return 1; /* needs_arg; */
+ }
+ if (strnlen(value, 65) < 65) {
+ if (strnicmp(value, "default", 7))
+ vol->codepage = value;
+ cFYI(1, ("codepage set to %s", value));
+ } else {
+ printk(KERN_WARNING "CIFS: codepage name "
+ "too long.\n");
+ return 1;
+ }
} else if (strnicmp(data, "uid", 3) == 0) {
if (value && *value) {
vol->linux_uid =
@@ -1941,6 +1957,19 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
}
}
+ /* this is needed when non-ascii/non-utf8 codepage in use on server */
+ if (volume_info.codepage == NULL) {
+ cifs_sb->remote_nls = NULL;
+ } else {
+ cifs_sb->remote_nls = load_nls(volume_info.codepage);
+ if (cifs_sb->remote_nls == NULL) {
+ cERROR(1, ("CIFS mount error: codepage %s not found",
+ volume_info.codepage));
+ rc = -ELIBACC;
+ goto out;
+ }
+ }
+
if (address_type == AF_INET)
existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
NULL /* no ipv6 addr */,
More information about the linux-cifs-client
mailing list