summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve French <smfrench@gmail.com>2014-09-25 14:01:34 -0500
committerSteve French <smfrench@gmail.com>2014-10-16 15:20:20 -0500
commita4153cb1d3cb7d7c16968b0a9cf7c8aacf31424e (patch)
tree161e3d9ab776a5dcc6755f56defad51165bac28c
parentb693855fe67314d501aae74b9adff8788eb2fd82 (diff)
downloadlinux-a4153cb1d3cb7d7c16968b0a9cf7c8aacf31424e.tar.bz2
Allow conversion of characters in Mac remap range (part 2)
The previous patch allowed remapping reserved characters from directory listenings, this patch adds conversion the other direction, allowing opening of files with any of the seven reserved characters. Signed-off-by: Steve French <smfrench@gmail.com> Reviewed-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com>
-rw-r--r--fs/cifs/cifs_unicode.c97
-rw-r--r--fs/cifs/smb2misc.c12
2 files changed, 83 insertions, 26 deletions
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index a479cc552617..0aa2c5c2cfe2 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -319,6 +319,66 @@ cifs_strndup_from_utf16(const char *src, const int maxlen,
return dst;
}
+static __le16 convert_to_sfu_char(char src_char)
+{
+ __le16 dest_char;
+
+ switch (src_char) {
+ case ':':
+ dest_char = cpu_to_le16(UNI_COLON);
+ break;
+ case '*':
+ dest_char = cpu_to_le16(UNI_ASTERISK);
+ break;
+ case '?':
+ dest_char = cpu_to_le16(UNI_QUESTION);
+ break;
+ case '<':
+ dest_char = cpu_to_le16(UNI_LESSTHAN);
+ break;
+ case '>':
+ dest_char = cpu_to_le16(UNI_GRTRTHAN);
+ break;
+ case '|':
+ dest_char = cpu_to_le16(UNI_PIPE);
+ break;
+ default:
+ dest_char = 0;
+ }
+
+ return dest_char;
+}
+
+static __le16 convert_to_sfm_char(char src_char)
+{
+ __le16 dest_char;
+
+ switch (src_char) {
+ case ':':
+ dest_char = cpu_to_le16(SFM_COLON);
+ break;
+ case '*':
+ dest_char = cpu_to_le16(SFM_ASTERISK);
+ break;
+ case '?':
+ dest_char = cpu_to_le16(SFM_QUESTION);
+ break;
+ case '<':
+ dest_char = cpu_to_le16(SFM_LESSTHAN);
+ break;
+ case '>':
+ dest_char = cpu_to_le16(SFM_GRTRTHAN);
+ break;
+ case '|':
+ dest_char = cpu_to_le16(SFM_PIPE);
+ break;
+ default:
+ dest_char = 0;
+ }
+
+ return dest_char;
+}
+
/*
* Convert 16 bit Unicode pathname to wire format from string in current code
* page. Conversion may involve remapping up the six characters that are
@@ -327,7 +387,7 @@ cifs_strndup_from_utf16(const char *src, const int maxlen,
*/
int
cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
- const struct nls_table *cp, int mapChars)
+ const struct nls_table *cp, int map_chars)
{
int i, charlen;
int j = 0;
@@ -335,39 +395,30 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
__le16 dst_char;
wchar_t tmp;
- if (!mapChars)
+ if (map_chars == NO_MAP_UNI_RSVD)
return cifs_strtoUTF16(target, source, PATH_MAX, cp);
for (i = 0; i < srclen; j++) {
src_char = source[i];
charlen = 1;
- switch (src_char) {
- case 0:
+
+ /* check if end of string */
+ if (src_char == 0)
goto ctoUTF16_out;
- case ':':
- dst_char = cpu_to_le16(UNI_COLON);
- break;
- case '*':
- dst_char = cpu_to_le16(UNI_ASTERISK);
- break;
- case '?':
- dst_char = cpu_to_le16(UNI_QUESTION);
- break;
- case '<':
- dst_char = cpu_to_le16(UNI_LESSTHAN);
- break;
- case '>':
- dst_char = cpu_to_le16(UNI_GRTRTHAN);
- break;
- case '|':
- dst_char = cpu_to_le16(UNI_PIPE);
- break;
+
+ /* see if we must remap this char */
+ if (map_chars == SFU_MAP_UNI_RSVD)
+ dst_char = convert_to_sfu_char(src_char);
+ else if (map_chars == SFM_MAP_UNI_RSVD)
+ dst_char = convert_to_sfm_char(src_char);
+ else
+ dst_char = 0;
/*
* FIXME: We can not handle remapping backslash (UNI_SLASH)
* until all the calls to build_path_from_dentry are modified,
* as they use backslash as separator.
*/
- default:
+ if (dst_char == 0) {
charlen = cp->char2uni(source + i, srclen - i, &tmp);
dst_char = cpu_to_le16(tmp);
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index 4aa7a0f07d6e..1a08a34838fc 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -379,6 +379,14 @@ cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb)
int len;
const char *start_of_path;
__le16 *to;
+ int map_type;
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SFM_CHR)
+ map_type = SFM_MAP_UNI_RSVD;
+ else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
+ map_type = SFU_MAP_UNI_RSVD;
+ else
+ map_type = NO_MAP_UNI_RSVD;
/* Windows doesn't allow paths beginning with \ */
if (from[0] == '\\')
@@ -386,9 +394,7 @@ cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb)
else
start_of_path = from;
to = cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len,
- cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
- CIFS_MOUNT_MAP_SPECIAL_CHR);
+ cifs_sb->local_nls, map_type);
return to;
}