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>
This commit is contained in:
Steve French 2014-09-25 14:01:34 -05:00
parent b693855fe6
commit a4153cb1d3
2 changed files with 83 additions and 26 deletions

View File

@ -319,6 +319,66 @@ cifs_strndup_from_utf16(const char *src, const int maxlen,
return dst; 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 * Convert 16 bit Unicode pathname to wire format from string in current code
* page. Conversion may involve remapping up the six characters that are * 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 int
cifsConvertToUTF16(__le16 *target, const char *source, int srclen, 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 i, charlen;
int j = 0; int j = 0;
@ -335,39 +395,30 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
__le16 dst_char; __le16 dst_char;
wchar_t tmp; wchar_t tmp;
if (!mapChars) if (map_chars == NO_MAP_UNI_RSVD)
return cifs_strtoUTF16(target, source, PATH_MAX, cp); return cifs_strtoUTF16(target, source, PATH_MAX, cp);
for (i = 0; i < srclen; j++) { for (i = 0; i < srclen; j++) {
src_char = source[i]; src_char = source[i];
charlen = 1; charlen = 1;
switch (src_char) {
case 0: /* check if end of string */
if (src_char == 0)
goto ctoUTF16_out; goto ctoUTF16_out;
case ':':
dst_char = cpu_to_le16(UNI_COLON); /* see if we must remap this char */
break; if (map_chars == SFU_MAP_UNI_RSVD)
case '*': dst_char = convert_to_sfu_char(src_char);
dst_char = cpu_to_le16(UNI_ASTERISK); else if (map_chars == SFM_MAP_UNI_RSVD)
break; dst_char = convert_to_sfm_char(src_char);
case '?': else
dst_char = cpu_to_le16(UNI_QUESTION); dst_char = 0;
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;
/* /*
* FIXME: We can not handle remapping backslash (UNI_SLASH) * FIXME: We can not handle remapping backslash (UNI_SLASH)
* until all the calls to build_path_from_dentry are modified, * until all the calls to build_path_from_dentry are modified,
* as they use backslash as separator. * as they use backslash as separator.
*/ */
default: if (dst_char == 0) {
charlen = cp->char2uni(source + i, srclen - i, &tmp); charlen = cp->char2uni(source + i, srclen - i, &tmp);
dst_char = cpu_to_le16(tmp); dst_char = cpu_to_le16(tmp);

View File

@ -379,6 +379,14 @@ cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb)
int len; int len;
const char *start_of_path; const char *start_of_path;
__le16 *to; __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 \ */ /* Windows doesn't allow paths beginning with \ */
if (from[0] == '\\') if (from[0] == '\\')
@ -386,9 +394,7 @@ cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb)
else else
start_of_path = from; start_of_path = from;
to = cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len, to = cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len,
cifs_sb->local_nls, cifs_sb->local_nls, map_type);
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
return to; return to;
} }