aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/connect.c
diff options
context:
space:
mode:
authorSteve French <smfrench@gmail.com>2014-09-27 03:19:01 -0400
committerSteve French <smfrench@gmail.com>2014-10-16 16:20:20 -0400
commit2baa2682531ff02928e2d3904800696d9e7193db (patch)
tree5da390e5e3d825b085481529205e5ca171ec9f38 /fs/cifs/connect.c
parenta4153cb1d3cb7d7c16968b0a9cf7c8aacf31424e (diff)
Remap reserved posix characters by default (part 3/3)
This is a bigger patch, but its size is mostly due to a single change for how we check for remapping illegal characters in file names - a lot of repeated, small changes to the way callers request converting file names. The final patch in the series does the following: 1) changes default behavior for cifs to be more intuitive. Currently we do not map by default to seven reserved characters, ie those valid in POSIX but not in NTFS/CIFS/SMB3/Windows, unless a mount option (mapchars) is specified. Change this to by default always map and map using the SFM maping (like the Mac uses) unless the server negotiates the CIFS Unix Extensions (like Samba does when mounting with the cifs protocol) when the remapping of the characters is unnecessary. This should help SMB3 mounts in particular since Samba will likely be able to implement this mapping with its new "vfs_fruit" module as it will be doing for the Mac. 2) if the user specifies the existing "mapchars" mount option then use the "SFU" (Microsoft Services for Unix, SUA) style mapping of the seven characters instead. 3) if the user specifies "nomapposix" then disable SFM/MAC style mapping (so no character remapping would be used unless the user specifies "mapchars" on mount as well, as above). 4) change all the places in the code that check for the superblock flag on the mount which is set by mapchars and passed in on all path based operation and change it to use a small function call instead to set the mapping type properly (and check for the mapping type in the cifs unicode functions) Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r--fs/cifs/connect.c30
1 files changed, 25 insertions, 5 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index d8eb6a74b211..24fa08d261fb 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -70,6 +70,7 @@ enum {
70 Opt_forcegid, Opt_noforcegid, 70 Opt_forcegid, Opt_noforcegid,
71 Opt_noblocksend, Opt_noautotune, 71 Opt_noblocksend, Opt_noautotune,
72 Opt_hard, Opt_soft, Opt_perm, Opt_noperm, 72 Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
73 Opt_mapposix, Opt_nomapposix,
73 Opt_mapchars, Opt_nomapchars, Opt_sfu, 74 Opt_mapchars, Opt_nomapchars, Opt_sfu,
74 Opt_nosfu, Opt_nodfs, Opt_posixpaths, 75 Opt_nosfu, Opt_nodfs, Opt_posixpaths,
75 Opt_noposixpaths, Opt_nounix, 76 Opt_noposixpaths, Opt_nounix,
@@ -124,8 +125,10 @@ static const match_table_t cifs_mount_option_tokens = {
124 { Opt_soft, "soft" }, 125 { Opt_soft, "soft" },
125 { Opt_perm, "perm" }, 126 { Opt_perm, "perm" },
126 { Opt_noperm, "noperm" }, 127 { Opt_noperm, "noperm" },
127 { Opt_mapchars, "mapchars" }, 128 { Opt_mapchars, "mapchars" }, /* SFU style */
128 { Opt_nomapchars, "nomapchars" }, 129 { Opt_nomapchars, "nomapchars" },
130 { Opt_mapposix, "mapposix" }, /* SFM style */
131 { Opt_nomapposix, "nomapposix" },
129 { Opt_sfu, "sfu" }, 132 { Opt_sfu, "sfu" },
130 { Opt_nosfu, "nosfu" }, 133 { Opt_nosfu, "nosfu" },
131 { Opt_nodfs, "nodfs" }, 134 { Opt_nodfs, "nodfs" },
@@ -1231,6 +1234,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
1231 vol->linux_uid = current_uid(); 1234 vol->linux_uid = current_uid();
1232 vol->linux_gid = current_gid(); 1235 vol->linux_gid = current_gid();
1233 1236
1237 /*
1238 * default to SFM style remapping of seven reserved characters
1239 * unless user overrides it or we negotiate CIFS POSIX where
1240 * it is unnecessary. Can not simultaneously use more than one mapping
1241 * since then readdir could list files that open could not open
1242 */
1243 vol->remap = true;
1244
1234 /* default to only allowing write access to owner of the mount */ 1245 /* default to only allowing write access to owner of the mount */
1235 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR; 1246 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
1236 1247
@@ -1338,10 +1349,18 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
1338 vol->noperm = 1; 1349 vol->noperm = 1;
1339 break; 1350 break;
1340 case Opt_mapchars: 1351 case Opt_mapchars:
1341 vol->remap = 1; 1352 vol->sfu_remap = true;
1353 vol->remap = false; /* disable SFM mapping */
1342 break; 1354 break;
1343 case Opt_nomapchars: 1355 case Opt_nomapchars:
1344 vol->remap = 0; 1356 vol->sfu_remap = false;
1357 break;
1358 case Opt_mapposix:
1359 vol->remap = true;
1360 vol->sfu_remap = false; /* disable SFU mapping */
1361 break;
1362 case Opt_nomapposix:
1363 vol->remap = false;
1345 break; 1364 break;
1346 case Opt_sfu: 1365 case Opt_sfu:
1347 vol->sfu_emul = 1; 1366 vol->sfu_emul = 1;
@@ -3197,6 +3216,8 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
3197 if (pvolume_info->server_ino) 3216 if (pvolume_info->server_ino)
3198 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM; 3217 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
3199 if (pvolume_info->remap) 3218 if (pvolume_info->remap)
3219 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
3220 if (pvolume_info->sfu_remap)
3200 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; 3221 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
3201 if (pvolume_info->no_xattr) 3222 if (pvolume_info->no_xattr)
3202 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; 3223 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
@@ -3340,8 +3361,7 @@ expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
3340 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1; 3361 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
3341 3362
3342 rc = get_dfs_path(xid, ses, ref_path, cifs_sb->local_nls, 3363 rc = get_dfs_path(xid, ses, ref_path, cifs_sb->local_nls,
3343 &num_referrals, &referrals, 3364 &num_referrals, &referrals, cifs_remap(cifs_sb));
3344 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
3345 3365
3346 if (!rc && num_referrals > 0) { 3366 if (!rc && num_referrals > 0) {
3347 char *fake_devname = NULL; 3367 char *fake_devname = NULL;