ntfs-3g supports non-BMP characters just fine. This patch make standard read-only driver work as well. Patch is bigger than required since checkpatch.pl asked me to restructure the code to avoid overlong lines. Signed-off-by: Vladimir Serbinenko <phcoder@xxxxxxxxx> --- fs/ntfs/unistr.c | 70 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 29 deletions(-) diff --git a/fs/ntfs/unistr.c b/fs/ntfs/unistr.c index 0d371e7..79f82d2 100644 --- a/fs/ntfs/unistr.c +++ b/fs/ntfs/unistr.c @@ -265,33 +265,35 @@ int ntfs_nlstoucs(const ntfs_volume *vol, const char *ins, int i, o, wc_len; /* We do not trust outside sources. */ - if (likely(ins)) { - ucs = kmem_cache_alloc(ntfs_name_cache, GFP_NOFS); - if (likely(ucs)) { - for (i = o = 0; i < ins_len; i += wc_len) { - wc_len = nls->char2uni(ins + i, ins_len - i, - &wc); - if (likely(wc_len >= 0 && wc <= 0xffff - && o < NTFS_MAX_NAME_LEN)) { - if (likely(wc)) { - ucs[o++] = cpu_to_le16(wc); - continue; - } /* else if (!wc) */ - break; - } /* else if (wc_len < 0 || - o >= NTFS_MAX_NAME_LEN) */ - goto name_err; - } - ucs[o] = 0; - *outs = ucs; - return o; - } /* else if (!ucs) */ - ntfs_error(vol->sb, "Failed to allocate buffer for converted " - "name from ntfs_name_cache."); + if (unlikely(!ins)) { + ntfs_error(vol->sb, "Received NULL pointer."); + return -EINVAL; + } + + ucs = kmem_cache_alloc(ntfs_name_cache, GFP_NOFS); + if (unlikely(!ucs)) { + ntfs_error(vol->sb, + "Failed to allocate buffer for converted " + "name from ntfs_name_cache."); return -ENOMEM; - } /* else if (!ins) */ - ntfs_error(vol->sb, "Received NULL pointer."); - return -EINVAL; + } + + for (i = o = 0; i < ins_len; i += wc_len) { + int s; + wc_len = nls->char2uni(ins + i, ins_len - i, &wc); + if (unlikely(wc_len < 0 || o >= NTFS_MAX_NAME_LEN)) + goto name_err; + if (unlikely(!wc)) + break; + s = unicode_to_utf16s(wc, UTF16_LITTLE_ENDIAN, ucs + o, + NTFS_MAX_NAME_LEN - o); + if (s <= 0) + break; + o += s; + } + ucs[o] = 0; + *outs = ucs; + return o; name_err: kmem_cache_free(ntfs_name_cache, ucs); if (wc_len < 0) { @@ -342,6 +344,7 @@ int ntfs_ucstonls(const ntfs_volume *vol, const ntfschar *ins, /* We don't trust outside sources. */ if (ins) { + int step; ns = *outs; ns_len = outs_len; if (ns && !ns_len) { @@ -354,9 +357,18 @@ int ntfs_ucstonls(const ntfs_volume *vol, const ntfschar *ins, if (!ns) goto mem_err_out; } - for (i = o = 0; i < ins_len; i++) { -retry: wc = nls->uni2char(le16_to_cpu(ins[i]), ns + o, - ns_len - o); + for (i = o = 0; i < ins_len; i += step) { + unicode_t uni; +retry: + step = utf16s_to_unicode(ins + i, ins_len - i, + UTF16_LITTLE_ENDIAN, + &uni); + if (step <= 0) { + uni = le16_to_cpu(ins[i]); + step = 1; + } + + wc = nls->uni2char(uni, ns + o, ns_len - o); if (wc > 0) { o += wc; continue; -- 1.7.10 -- Regards Vladimir 'φ-coder/phcoder' Serbinenko
Attachment:
signature.asc
Description: OpenPGP digital signature