Signed-off-by: Vladimir Serbinenko <phcoder@xxxxxxxxx> --- fs/fat/dir.c | 18 ++++++++++++++++-- fs/fat/namei_vfat.c | 23 ++++++++++++++++++++--- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 9bb16f3..d14ac9e 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c @@ -149,10 +149,24 @@ static int uni16_to_x8(struct super_block *sb, unsigned char *ascii, op = ascii; while (*ip && ((len - NLS_MAX_CHARSET_SIZE) > 0)) { - ec = *ip++; - if ((charlen = nls->uni2char(ec, op, NLS_MAX_CHARSET_SIZE)) > 0) { + unicode_t uni; + int is_sur = 0; + + uni = ec = *ip++; + + if ((ec & 0xfc00) == 0xd800 + || (*ip & 0xfc00) == 0xdc00) { + is_sur = 1; + uni = ((ec & 0x3ff) << 10) | (*ip & 0x3ff); + uni += 0x10000; + } + + charlen = nls->uni2char(uni, op, NLS_MAX_CHARSET_SIZE); + if (charlen > 0) { op += charlen; len -= charlen; + if (is_sur) + ip++; } else { if (uni_xlate == 1) { *op++ = ':'; diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index 6b9caa5..ad5abfd 100644 --- a/fs/fat/namei_vfat.c +++ b/fs/fat/namei_vfat.c @@ -552,12 +552,29 @@ xlate_to_uni(const unsigned char *name, int len, unsigned char *outname, } else { unicode_t t; charlen = nls->char2uni(ip, len - i, &t); - if (charlen < 0 || t > 0xffff) + if (charlen < 0) return -EINVAL; - *(wchar_t *)op = t; + if (t > 0xffff) { + u16 h, l; + + if (*outlen + 1 >= FAT_LFN_LEN) + break; + + h = (((t - 0x10000) >> 10) & 0x3ff) + | 0xd800; + l = ((t - 0x10000) & 0x3ff) + | 0xdc00; + *(wchar_t *)op = h; + op += 2; + *(wchar_t *)op = l; + op += 2; + *outlen += 1; + } else { + *(wchar_t *)op = t; + op += 2; + } ip += charlen; i += charlen; - op += 2; } } if (i < len) -- 1.7.10 -- Regards Vladimir 'φ-coder/phcoder' Serbinenko
Attachment:
signature.asc
Description: OpenPGP digital signature