diff options
author | Steve French <sfrench@us.ibm.com> | 2008-02-14 01:38:30 -0500 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2008-02-14 01:38:30 -0500 |
commit | 03a143c909b808759f188a45c75acb8f043cb209 (patch) | |
tree | c530f351a3bff2997b68009bec280c92eb7098c7 | |
parent | c1ce264470f000ccd5965d3718f7d905d559fd64 (diff) |
[CIFS] fixup prefixpaths which contain multiple path components
Currently, when we get a prefixpath as part of mount, the kernel only
changes the first character to be a '/' or '\' depending on whether
posix extensions are enabled. This is problematic as it expects
mount.cifs to pass in the correct delimiter in the rest of the
prefixpath. But, mount.cifs may not know *what* the correct delimiter
is. It's a chicken and egg problem.
Note that mount.cifs should not do conversion of the
prefixpath - if we want posix behavior then '\' is legal in a path
(and we have had bugs in the distant path to prove to me that
customers sometimes have apps that require '\'). The kernel code
assumes that the path passed in is posix (and current code will handle
the first path component fine but was broken for Windows mounts
for "deep" prefixpaths unless the user specified a prefixpath with '\'
deep in it. So e.g. with current kernel code:
1) mount to //server/share/dir1 will work to all server types
2) mount to //server/share/dir1/subdir1 will work to Samba
3) mount to //server/share/dir1\\subdir1 will work to Windows
But case two would fail to Windows without the fix.
With the kernel cifs module fix case two now works.
First analyzed by Jeff Layton and Simo Sorce
CC: Jeff Layton <jlayton@redhat.com>
CC: Simo Sorce <simo@samba.org>
Signed-off-by: Steve French <sfrench@us.ibm.com>
-rw-r--r-- | fs/cifs/CHANGES | 4 | ||||
-rw-r--r-- | fs/cifs/connect.c | 23 |
2 files changed, 25 insertions, 2 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index edd248367b36..dbd91461853c 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -6,7 +6,9 @@ and sync so that events like out of disk space get reported properly on | |||
6 | cached files. Fix setxattr failure to certain Samba versions. Fix mount | 6 | cached files. Fix setxattr failure to certain Samba versions. Fix mount |
7 | of second share to disconnected server session (autoreconnect on this). | 7 | of second share to disconnected server session (autoreconnect on this). |
8 | Add ability to modify cifs acls for handling chmod (when mounted with | 8 | Add ability to modify cifs acls for handling chmod (when mounted with |
9 | cifsacl flag). | 9 | cifsacl flag). Fix prefixpath path separator so we can handle mounts |
10 | with prefixpaths longer than one directory (one path component) when | ||
11 | mounted to Windows servers. | ||
10 | 12 | ||
11 | Version 1.51 | 13 | Version 1.51 |
12 | ------------ | 14 | ------------ |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 5ccd8b710cc5..e111c69139b7 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -1791,6 +1791,20 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon, | |||
1791 | } | 1791 | } |
1792 | } | 1792 | } |
1793 | 1793 | ||
1794 | static void | ||
1795 | convert_delimiter(char *path, char delim) | ||
1796 | { | ||
1797 | int i; | ||
1798 | |||
1799 | if (path == NULL) | ||
1800 | return; | ||
1801 | |||
1802 | for (i = 0; path[i] != '\0'; i++) { | ||
1803 | if ((path[i] == '/') || (path[i] == '\\')) | ||
1804 | path[i] = delim; | ||
1805 | } | ||
1806 | } | ||
1807 | |||
1794 | int | 1808 | int |
1795 | cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | 1809 | cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, |
1796 | char *mount_data, const char *devname) | 1810 | char *mount_data, const char *devname) |
@@ -2056,7 +2070,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2056 | cifs_sb->prepath = volume_info.prepath; | 2070 | cifs_sb->prepath = volume_info.prepath; |
2057 | if (cifs_sb->prepath) { | 2071 | if (cifs_sb->prepath) { |
2058 | cifs_sb->prepathlen = strlen(cifs_sb->prepath); | 2072 | cifs_sb->prepathlen = strlen(cifs_sb->prepath); |
2059 | cifs_sb->prepath[0] = CIFS_DIR_SEP(cifs_sb); | 2073 | /* we can not convert the / to \ in the path |
2074 | separators in the prefixpath yet because we do not | ||
2075 | know (until reset_cifs_unix_caps is called later) | ||
2076 | whether POSIX PATH CAP is available. We normalize | ||
2077 | the / to \ after reset_cifs_unix_caps is called */ | ||
2060 | volume_info.prepath = NULL; | 2078 | volume_info.prepath = NULL; |
2061 | } else | 2079 | } else |
2062 | cifs_sb->prepathlen = 0; | 2080 | cifs_sb->prepathlen = 0; |
@@ -2224,6 +2242,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2224 | else | 2242 | else |
2225 | tcon->unix_ext = 0; /* server does not support them */ | 2243 | tcon->unix_ext = 0; /* server does not support them */ |
2226 | 2244 | ||
2245 | /* convert forward to back slashes in prepath here if needed */ | ||
2246 | convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb)); | ||
2247 | |||
2227 | if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) { | 2248 | if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) { |
2228 | cifs_sb->rsize = 1024 * 127; | 2249 | cifs_sb->rsize = 1024 * 127; |
2229 | cFYI(DBG2, | 2250 | cFYI(DBG2, |