Used for reading and writing UTF-16 on UDF and Joliet. Signed-off-by: Vladimir Serbinenko <phcoder@xxxxxxxxx> --- fs/nls/nls_base.c | 31 +++++++++++++++++++++---------- include/linux/nls.h | 4 +++- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/fs/nls/nls_base.c b/fs/nls/nls_base.c index 0c1ad5b..e941a80 100644 --- a/fs/nls/nls_base.c +++ b/fs/nls/nls_base.c @@ -16,6 +16,7 @@ #include <linux/kmod.h> #include <linux/spinlock.h> #include <asm/byteorder.h> +#include <asm/unaligned.h> static struct nls_table default_table; static struct nls_table *tables = &default_table; @@ -114,7 +115,7 @@ int utf32_to_utf8(unicode_t u, u8 *s, int maxout) } EXPORT_SYMBOL(utf32_to_utf8); -static inline void put_utf16(wchar_t *s, unsigned c, enum utf16_endian endian) +static inline void put_utf16(u16 *s, unsigned c, enum utf16_endian endian) { switch (endian) { default: @@ -126,11 +127,17 @@ static inline void put_utf16(wchar_t *s, unsigned c, enum utf16_endian endian) case UTF16_BIG_ENDIAN: *s = __cpu_to_be16(c); break; + case UTF16_LITTLE_ENDIAN_UNALIGNED: + put_unaligned_le16 (c, s); + break; + case UTF16_BIG_ENDIAN_UNALIGNED: + put_unaligned_be16 (c, s); + break; } } int utf8s_to_utf16s(const u8 *s, int inlen, enum utf16_endian endian, - wchar_t *pwcs, int maxout) + wchar_t *pwcs, int maxout) { u16 *op; int size; @@ -197,15 +204,19 @@ int unicode_to_utf16s(unicode_t u, enum utf16_endian endian, } EXPORT_SYMBOL(unicode_to_utf16s); -static inline unsigned long get_utf16(unsigned c, enum utf16_endian endian) +static inline unsigned long get_utf16(const u16 *c, enum utf16_endian endian) { switch (endian) { default: - return c; + return *c; case UTF16_LITTLE_ENDIAN: - return __le16_to_cpu(c); + return __le16_to_cpu(*c); case UTF16_BIG_ENDIAN: - return __be16_to_cpu(c); + return __be16_to_cpu(*c); + case UTF16_LITTLE_ENDIAN_UNALIGNED: + return get_unaligned_le16 (c); + case UTF16_BIG_ENDIAN_UNALIGNED: + return get_unaligned_be16 (c); } } @@ -218,7 +229,7 @@ int utf16s_to_utf8s(const wchar_t *pwcs, int inlen, enum utf16_endian endian, op = s; while (inlen > 0 && maxout > 0) { - u = get_utf16(*pwcs, endian); + u = get_utf16(pwcs, endian); if (!u) break; pwcs++; @@ -231,7 +242,7 @@ int utf16s_to_utf8s(const wchar_t *pwcs, int inlen, enum utf16_endian endian, } if (inlen <= 0) break; - v = get_utf16(*pwcs, endian); + v = get_utf16(pwcs, endian); if ((v & SURROGATE_MASK) != SURROGATE_PAIR || !(v & SURROGATE_LOW)) { /* Ignore character and move on */ @@ -265,7 +276,7 @@ int utf16s_to_unicode(const wchar_t *pwcs, int inlen, enum utf16_endian endian, const wchar_t *pwcs0 = pwcs; while (inlen > 0) { - u = get_utf16(*pwcs, endian); + u = get_utf16(pwcs, endian); if (!u) break; pwcs++; @@ -277,7 +288,7 @@ int utf16s_to_unicode(const wchar_t *pwcs, int inlen, enum utf16_endian endian, } if (inlen <= 0) break; - v = get_utf16(*pwcs, endian); + v = get_utf16(pwcs, endian); if ((v & SURROGATE_MASK) != SURROGATE_PAIR || !(v & SURROGATE_LOW)) { /* Ignore character and move on */ diff --git a/include/linux/nls.h b/include/linux/nls.h index 7de1765..bb35d2b 100644 --- a/include/linux/nls.h +++ b/include/linux/nls.h @@ -40,7 +40,9 @@ struct nls_table { enum utf16_endian { UTF16_HOST_ENDIAN, UTF16_LITTLE_ENDIAN, - UTF16_BIG_ENDIAN + UTF16_BIG_ENDIAN, + UTF16_LITTLE_ENDIAN_UNALIGNED, + UTF16_BIG_ENDIAN_UNALIGNED }; /* nls_base.c */ -- 1.7.10 -- Regards Vladimir 'φ-coder/phcoder' Serbinenko
Attachment:
signature.asc
Description: OpenPGP digital signature