162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * unistr.c - NTFS Unicode string handling. Part of the Linux-NTFS project. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2001-2006 Anton Altaparmakov 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/slab.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include "types.h" 1162306a36Sopenharmony_ci#include "debug.h" 1262306a36Sopenharmony_ci#include "ntfs.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci/* 1562306a36Sopenharmony_ci * IMPORTANT 1662306a36Sopenharmony_ci * ========= 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * All these routines assume that the Unicode characters are in little endian 1962306a36Sopenharmony_ci * encoding inside the strings!!! 2062306a36Sopenharmony_ci */ 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/* 2362306a36Sopenharmony_ci * This is used by the name collation functions to quickly determine what 2462306a36Sopenharmony_ci * characters are (in)valid. 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_cistatic const u8 legal_ansi_char_array[0x40] = { 2762306a36Sopenharmony_ci 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 2862306a36Sopenharmony_ci 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 3162306a36Sopenharmony_ci 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci 0x17, 0x07, 0x18, 0x17, 0x17, 0x17, 0x17, 0x17, 3462306a36Sopenharmony_ci 0x17, 0x17, 0x18, 0x16, 0x16, 0x17, 0x07, 0x00, 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 3762306a36Sopenharmony_ci 0x17, 0x17, 0x04, 0x16, 0x18, 0x16, 0x18, 0x18, 3862306a36Sopenharmony_ci}; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci/** 4162306a36Sopenharmony_ci * ntfs_are_names_equal - compare two Unicode names for equality 4262306a36Sopenharmony_ci * @s1: name to compare to @s2 4362306a36Sopenharmony_ci * @s1_len: length in Unicode characters of @s1 4462306a36Sopenharmony_ci * @s2: name to compare to @s1 4562306a36Sopenharmony_ci * @s2_len: length in Unicode characters of @s2 4662306a36Sopenharmony_ci * @ic: ignore case bool 4762306a36Sopenharmony_ci * @upcase: upcase table (only if @ic == IGNORE_CASE) 4862306a36Sopenharmony_ci * @upcase_size: length in Unicode characters of @upcase (if present) 4962306a36Sopenharmony_ci * 5062306a36Sopenharmony_ci * Compare the names @s1 and @s2 and return 'true' (1) if the names are 5162306a36Sopenharmony_ci * identical, or 'false' (0) if they are not identical. If @ic is IGNORE_CASE, 5262306a36Sopenharmony_ci * the @upcase table is used to performa a case insensitive comparison. 5362306a36Sopenharmony_ci */ 5462306a36Sopenharmony_cibool ntfs_are_names_equal(const ntfschar *s1, size_t s1_len, 5562306a36Sopenharmony_ci const ntfschar *s2, size_t s2_len, const IGNORE_CASE_BOOL ic, 5662306a36Sopenharmony_ci const ntfschar *upcase, const u32 upcase_size) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci if (s1_len != s2_len) 5962306a36Sopenharmony_ci return false; 6062306a36Sopenharmony_ci if (ic == CASE_SENSITIVE) 6162306a36Sopenharmony_ci return !ntfs_ucsncmp(s1, s2, s1_len); 6262306a36Sopenharmony_ci return !ntfs_ucsncasecmp(s1, s2, s1_len, upcase, upcase_size); 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci/** 6662306a36Sopenharmony_ci * ntfs_collate_names - collate two Unicode names 6762306a36Sopenharmony_ci * @name1: first Unicode name to compare 6862306a36Sopenharmony_ci * @name2: second Unicode name to compare 6962306a36Sopenharmony_ci * @err_val: if @name1 contains an invalid character return this value 7062306a36Sopenharmony_ci * @ic: either CASE_SENSITIVE or IGNORE_CASE 7162306a36Sopenharmony_ci * @upcase: upcase table (ignored if @ic is CASE_SENSITIVE) 7262306a36Sopenharmony_ci * @upcase_len: upcase table size (ignored if @ic is CASE_SENSITIVE) 7362306a36Sopenharmony_ci * 7462306a36Sopenharmony_ci * ntfs_collate_names collates two Unicode names and returns: 7562306a36Sopenharmony_ci * 7662306a36Sopenharmony_ci * -1 if the first name collates before the second one, 7762306a36Sopenharmony_ci * 0 if the names match, 7862306a36Sopenharmony_ci * 1 if the second name collates before the first one, or 7962306a36Sopenharmony_ci * @err_val if an invalid character is found in @name1 during the comparison. 8062306a36Sopenharmony_ci * 8162306a36Sopenharmony_ci * The following characters are considered invalid: '"', '*', '<', '>' and '?'. 8262306a36Sopenharmony_ci */ 8362306a36Sopenharmony_ciint ntfs_collate_names(const ntfschar *name1, const u32 name1_len, 8462306a36Sopenharmony_ci const ntfschar *name2, const u32 name2_len, 8562306a36Sopenharmony_ci const int err_val, const IGNORE_CASE_BOOL ic, 8662306a36Sopenharmony_ci const ntfschar *upcase, const u32 upcase_len) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci u32 cnt, min_len; 8962306a36Sopenharmony_ci u16 c1, c2; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci min_len = name1_len; 9262306a36Sopenharmony_ci if (name1_len > name2_len) 9362306a36Sopenharmony_ci min_len = name2_len; 9462306a36Sopenharmony_ci for (cnt = 0; cnt < min_len; ++cnt) { 9562306a36Sopenharmony_ci c1 = le16_to_cpu(*name1++); 9662306a36Sopenharmony_ci c2 = le16_to_cpu(*name2++); 9762306a36Sopenharmony_ci if (ic) { 9862306a36Sopenharmony_ci if (c1 < upcase_len) 9962306a36Sopenharmony_ci c1 = le16_to_cpu(upcase[c1]); 10062306a36Sopenharmony_ci if (c2 < upcase_len) 10162306a36Sopenharmony_ci c2 = le16_to_cpu(upcase[c2]); 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci if (c1 < 64 && legal_ansi_char_array[c1] & 8) 10462306a36Sopenharmony_ci return err_val; 10562306a36Sopenharmony_ci if (c1 < c2) 10662306a36Sopenharmony_ci return -1; 10762306a36Sopenharmony_ci if (c1 > c2) 10862306a36Sopenharmony_ci return 1; 10962306a36Sopenharmony_ci } 11062306a36Sopenharmony_ci if (name1_len < name2_len) 11162306a36Sopenharmony_ci return -1; 11262306a36Sopenharmony_ci if (name1_len == name2_len) 11362306a36Sopenharmony_ci return 0; 11462306a36Sopenharmony_ci /* name1_len > name2_len */ 11562306a36Sopenharmony_ci c1 = le16_to_cpu(*name1); 11662306a36Sopenharmony_ci if (c1 < 64 && legal_ansi_char_array[c1] & 8) 11762306a36Sopenharmony_ci return err_val; 11862306a36Sopenharmony_ci return 1; 11962306a36Sopenharmony_ci} 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci/** 12262306a36Sopenharmony_ci * ntfs_ucsncmp - compare two little endian Unicode strings 12362306a36Sopenharmony_ci * @s1: first string 12462306a36Sopenharmony_ci * @s2: second string 12562306a36Sopenharmony_ci * @n: maximum unicode characters to compare 12662306a36Sopenharmony_ci * 12762306a36Sopenharmony_ci * Compare the first @n characters of the Unicode strings @s1 and @s2, 12862306a36Sopenharmony_ci * The strings in little endian format and appropriate le16_to_cpu() 12962306a36Sopenharmony_ci * conversion is performed on non-little endian machines. 13062306a36Sopenharmony_ci * 13162306a36Sopenharmony_ci * The function returns an integer less than, equal to, or greater than zero 13262306a36Sopenharmony_ci * if @s1 (or the first @n Unicode characters thereof) is found, respectively, 13362306a36Sopenharmony_ci * to be less than, to match, or be greater than @s2. 13462306a36Sopenharmony_ci */ 13562306a36Sopenharmony_ciint ntfs_ucsncmp(const ntfschar *s1, const ntfschar *s2, size_t n) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci u16 c1, c2; 13862306a36Sopenharmony_ci size_t i; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci for (i = 0; i < n; ++i) { 14162306a36Sopenharmony_ci c1 = le16_to_cpu(s1[i]); 14262306a36Sopenharmony_ci c2 = le16_to_cpu(s2[i]); 14362306a36Sopenharmony_ci if (c1 < c2) 14462306a36Sopenharmony_ci return -1; 14562306a36Sopenharmony_ci if (c1 > c2) 14662306a36Sopenharmony_ci return 1; 14762306a36Sopenharmony_ci if (!c1) 14862306a36Sopenharmony_ci break; 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci return 0; 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci/** 15462306a36Sopenharmony_ci * ntfs_ucsncasecmp - compare two little endian Unicode strings, ignoring case 15562306a36Sopenharmony_ci * @s1: first string 15662306a36Sopenharmony_ci * @s2: second string 15762306a36Sopenharmony_ci * @n: maximum unicode characters to compare 15862306a36Sopenharmony_ci * @upcase: upcase table 15962306a36Sopenharmony_ci * @upcase_size: upcase table size in Unicode characters 16062306a36Sopenharmony_ci * 16162306a36Sopenharmony_ci * Compare the first @n characters of the Unicode strings @s1 and @s2, 16262306a36Sopenharmony_ci * ignoring case. The strings in little endian format and appropriate 16362306a36Sopenharmony_ci * le16_to_cpu() conversion is performed on non-little endian machines. 16462306a36Sopenharmony_ci * 16562306a36Sopenharmony_ci * Each character is uppercased using the @upcase table before the comparison. 16662306a36Sopenharmony_ci * 16762306a36Sopenharmony_ci * The function returns an integer less than, equal to, or greater than zero 16862306a36Sopenharmony_ci * if @s1 (or the first @n Unicode characters thereof) is found, respectively, 16962306a36Sopenharmony_ci * to be less than, to match, or be greater than @s2. 17062306a36Sopenharmony_ci */ 17162306a36Sopenharmony_ciint ntfs_ucsncasecmp(const ntfschar *s1, const ntfschar *s2, size_t n, 17262306a36Sopenharmony_ci const ntfschar *upcase, const u32 upcase_size) 17362306a36Sopenharmony_ci{ 17462306a36Sopenharmony_ci size_t i; 17562306a36Sopenharmony_ci u16 c1, c2; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci for (i = 0; i < n; ++i) { 17862306a36Sopenharmony_ci if ((c1 = le16_to_cpu(s1[i])) < upcase_size) 17962306a36Sopenharmony_ci c1 = le16_to_cpu(upcase[c1]); 18062306a36Sopenharmony_ci if ((c2 = le16_to_cpu(s2[i])) < upcase_size) 18162306a36Sopenharmony_ci c2 = le16_to_cpu(upcase[c2]); 18262306a36Sopenharmony_ci if (c1 < c2) 18362306a36Sopenharmony_ci return -1; 18462306a36Sopenharmony_ci if (c1 > c2) 18562306a36Sopenharmony_ci return 1; 18662306a36Sopenharmony_ci if (!c1) 18762306a36Sopenharmony_ci break; 18862306a36Sopenharmony_ci } 18962306a36Sopenharmony_ci return 0; 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_civoid ntfs_upcase_name(ntfschar *name, u32 name_len, const ntfschar *upcase, 19362306a36Sopenharmony_ci const u32 upcase_len) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci u32 i; 19662306a36Sopenharmony_ci u16 u; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci for (i = 0; i < name_len; i++) 19962306a36Sopenharmony_ci if ((u = le16_to_cpu(name[i])) < upcase_len) 20062306a36Sopenharmony_ci name[i] = upcase[u]; 20162306a36Sopenharmony_ci} 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_civoid ntfs_file_upcase_value(FILE_NAME_ATTR *file_name_attr, 20462306a36Sopenharmony_ci const ntfschar *upcase, const u32 upcase_len) 20562306a36Sopenharmony_ci{ 20662306a36Sopenharmony_ci ntfs_upcase_name((ntfschar*)&file_name_attr->file_name, 20762306a36Sopenharmony_ci file_name_attr->file_name_length, upcase, upcase_len); 20862306a36Sopenharmony_ci} 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ciint ntfs_file_compare_values(FILE_NAME_ATTR *file_name_attr1, 21162306a36Sopenharmony_ci FILE_NAME_ATTR *file_name_attr2, 21262306a36Sopenharmony_ci const int err_val, const IGNORE_CASE_BOOL ic, 21362306a36Sopenharmony_ci const ntfschar *upcase, const u32 upcase_len) 21462306a36Sopenharmony_ci{ 21562306a36Sopenharmony_ci return ntfs_collate_names((ntfschar*)&file_name_attr1->file_name, 21662306a36Sopenharmony_ci file_name_attr1->file_name_length, 21762306a36Sopenharmony_ci (ntfschar*)&file_name_attr2->file_name, 21862306a36Sopenharmony_ci file_name_attr2->file_name_length, 21962306a36Sopenharmony_ci err_val, ic, upcase, upcase_len); 22062306a36Sopenharmony_ci} 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci/** 22362306a36Sopenharmony_ci * ntfs_nlstoucs - convert NLS string to little endian Unicode string 22462306a36Sopenharmony_ci * @vol: ntfs volume which we are working with 22562306a36Sopenharmony_ci * @ins: input NLS string buffer 22662306a36Sopenharmony_ci * @ins_len: length of input string in bytes 22762306a36Sopenharmony_ci * @outs: on return contains the allocated output Unicode string buffer 22862306a36Sopenharmony_ci * 22962306a36Sopenharmony_ci * Convert the input string @ins, which is in whatever format the loaded NLS 23062306a36Sopenharmony_ci * map dictates, into a little endian, 2-byte Unicode string. 23162306a36Sopenharmony_ci * 23262306a36Sopenharmony_ci * This function allocates the string and the caller is responsible for 23362306a36Sopenharmony_ci * calling kmem_cache_free(ntfs_name_cache, *@outs); when finished with it. 23462306a36Sopenharmony_ci * 23562306a36Sopenharmony_ci * On success the function returns the number of Unicode characters written to 23662306a36Sopenharmony_ci * the output string *@outs (>= 0), not counting the terminating Unicode NULL 23762306a36Sopenharmony_ci * character. *@outs is set to the allocated output string buffer. 23862306a36Sopenharmony_ci * 23962306a36Sopenharmony_ci * On error, a negative number corresponding to the error code is returned. In 24062306a36Sopenharmony_ci * that case the output string is not allocated. Both *@outs and *@outs_len 24162306a36Sopenharmony_ci * are then undefined. 24262306a36Sopenharmony_ci * 24362306a36Sopenharmony_ci * This might look a bit odd due to fast path optimization... 24462306a36Sopenharmony_ci */ 24562306a36Sopenharmony_ciint ntfs_nlstoucs(const ntfs_volume *vol, const char *ins, 24662306a36Sopenharmony_ci const int ins_len, ntfschar **outs) 24762306a36Sopenharmony_ci{ 24862306a36Sopenharmony_ci struct nls_table *nls = vol->nls_map; 24962306a36Sopenharmony_ci ntfschar *ucs; 25062306a36Sopenharmony_ci wchar_t wc; 25162306a36Sopenharmony_ci int i, o, wc_len; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci /* We do not trust outside sources. */ 25462306a36Sopenharmony_ci if (likely(ins)) { 25562306a36Sopenharmony_ci ucs = kmem_cache_alloc(ntfs_name_cache, GFP_NOFS); 25662306a36Sopenharmony_ci if (likely(ucs)) { 25762306a36Sopenharmony_ci for (i = o = 0; i < ins_len; i += wc_len) { 25862306a36Sopenharmony_ci wc_len = nls->char2uni(ins + i, ins_len - i, 25962306a36Sopenharmony_ci &wc); 26062306a36Sopenharmony_ci if (likely(wc_len >= 0 && 26162306a36Sopenharmony_ci o < NTFS_MAX_NAME_LEN)) { 26262306a36Sopenharmony_ci if (likely(wc)) { 26362306a36Sopenharmony_ci ucs[o++] = cpu_to_le16(wc); 26462306a36Sopenharmony_ci continue; 26562306a36Sopenharmony_ci } /* else if (!wc) */ 26662306a36Sopenharmony_ci break; 26762306a36Sopenharmony_ci } /* else if (wc_len < 0 || 26862306a36Sopenharmony_ci o >= NTFS_MAX_NAME_LEN) */ 26962306a36Sopenharmony_ci goto name_err; 27062306a36Sopenharmony_ci } 27162306a36Sopenharmony_ci ucs[o] = 0; 27262306a36Sopenharmony_ci *outs = ucs; 27362306a36Sopenharmony_ci return o; 27462306a36Sopenharmony_ci } /* else if (!ucs) */ 27562306a36Sopenharmony_ci ntfs_error(vol->sb, "Failed to allocate buffer for converted " 27662306a36Sopenharmony_ci "name from ntfs_name_cache."); 27762306a36Sopenharmony_ci return -ENOMEM; 27862306a36Sopenharmony_ci } /* else if (!ins) */ 27962306a36Sopenharmony_ci ntfs_error(vol->sb, "Received NULL pointer."); 28062306a36Sopenharmony_ci return -EINVAL; 28162306a36Sopenharmony_ciname_err: 28262306a36Sopenharmony_ci kmem_cache_free(ntfs_name_cache, ucs); 28362306a36Sopenharmony_ci if (wc_len < 0) { 28462306a36Sopenharmony_ci ntfs_error(vol->sb, "Name using character set %s contains " 28562306a36Sopenharmony_ci "characters that cannot be converted to " 28662306a36Sopenharmony_ci "Unicode.", nls->charset); 28762306a36Sopenharmony_ci i = -EILSEQ; 28862306a36Sopenharmony_ci } else /* if (o >= NTFS_MAX_NAME_LEN) */ { 28962306a36Sopenharmony_ci ntfs_error(vol->sb, "Name is too long (maximum length for a " 29062306a36Sopenharmony_ci "name on NTFS is %d Unicode characters.", 29162306a36Sopenharmony_ci NTFS_MAX_NAME_LEN); 29262306a36Sopenharmony_ci i = -ENAMETOOLONG; 29362306a36Sopenharmony_ci } 29462306a36Sopenharmony_ci return i; 29562306a36Sopenharmony_ci} 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci/** 29862306a36Sopenharmony_ci * ntfs_ucstonls - convert little endian Unicode string to NLS string 29962306a36Sopenharmony_ci * @vol: ntfs volume which we are working with 30062306a36Sopenharmony_ci * @ins: input Unicode string buffer 30162306a36Sopenharmony_ci * @ins_len: length of input string in Unicode characters 30262306a36Sopenharmony_ci * @outs: on return contains the (allocated) output NLS string buffer 30362306a36Sopenharmony_ci * @outs_len: length of output string buffer in bytes 30462306a36Sopenharmony_ci * 30562306a36Sopenharmony_ci * Convert the input little endian, 2-byte Unicode string @ins, of length 30662306a36Sopenharmony_ci * @ins_len into the string format dictated by the loaded NLS. 30762306a36Sopenharmony_ci * 30862306a36Sopenharmony_ci * If *@outs is NULL, this function allocates the string and the caller is 30962306a36Sopenharmony_ci * responsible for calling kfree(*@outs); when finished with it. In this case 31062306a36Sopenharmony_ci * @outs_len is ignored and can be 0. 31162306a36Sopenharmony_ci * 31262306a36Sopenharmony_ci * On success the function returns the number of bytes written to the output 31362306a36Sopenharmony_ci * string *@outs (>= 0), not counting the terminating NULL byte. If the output 31462306a36Sopenharmony_ci * string buffer was allocated, *@outs is set to it. 31562306a36Sopenharmony_ci * 31662306a36Sopenharmony_ci * On error, a negative number corresponding to the error code is returned. In 31762306a36Sopenharmony_ci * that case the output string is not allocated. The contents of *@outs are 31862306a36Sopenharmony_ci * then undefined. 31962306a36Sopenharmony_ci * 32062306a36Sopenharmony_ci * This might look a bit odd due to fast path optimization... 32162306a36Sopenharmony_ci */ 32262306a36Sopenharmony_ciint ntfs_ucstonls(const ntfs_volume *vol, const ntfschar *ins, 32362306a36Sopenharmony_ci const int ins_len, unsigned char **outs, int outs_len) 32462306a36Sopenharmony_ci{ 32562306a36Sopenharmony_ci struct nls_table *nls = vol->nls_map; 32662306a36Sopenharmony_ci unsigned char *ns; 32762306a36Sopenharmony_ci int i, o, ns_len, wc; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci /* We don't trust outside sources. */ 33062306a36Sopenharmony_ci if (ins) { 33162306a36Sopenharmony_ci ns = *outs; 33262306a36Sopenharmony_ci ns_len = outs_len; 33362306a36Sopenharmony_ci if (ns && !ns_len) { 33462306a36Sopenharmony_ci wc = -ENAMETOOLONG; 33562306a36Sopenharmony_ci goto conversion_err; 33662306a36Sopenharmony_ci } 33762306a36Sopenharmony_ci if (!ns) { 33862306a36Sopenharmony_ci ns_len = ins_len * NLS_MAX_CHARSET_SIZE; 33962306a36Sopenharmony_ci ns = kmalloc(ns_len + 1, GFP_NOFS); 34062306a36Sopenharmony_ci if (!ns) 34162306a36Sopenharmony_ci goto mem_err_out; 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci for (i = o = 0; i < ins_len; i++) { 34462306a36Sopenharmony_ciretry: wc = nls->uni2char(le16_to_cpu(ins[i]), ns + o, 34562306a36Sopenharmony_ci ns_len - o); 34662306a36Sopenharmony_ci if (wc > 0) { 34762306a36Sopenharmony_ci o += wc; 34862306a36Sopenharmony_ci continue; 34962306a36Sopenharmony_ci } else if (!wc) 35062306a36Sopenharmony_ci break; 35162306a36Sopenharmony_ci else if (wc == -ENAMETOOLONG && ns != *outs) { 35262306a36Sopenharmony_ci unsigned char *tc; 35362306a36Sopenharmony_ci /* Grow in multiples of 64 bytes. */ 35462306a36Sopenharmony_ci tc = kmalloc((ns_len + 64) & 35562306a36Sopenharmony_ci ~63, GFP_NOFS); 35662306a36Sopenharmony_ci if (tc) { 35762306a36Sopenharmony_ci memcpy(tc, ns, ns_len); 35862306a36Sopenharmony_ci ns_len = ((ns_len + 64) & ~63) - 1; 35962306a36Sopenharmony_ci kfree(ns); 36062306a36Sopenharmony_ci ns = tc; 36162306a36Sopenharmony_ci goto retry; 36262306a36Sopenharmony_ci } /* No memory so goto conversion_error; */ 36362306a36Sopenharmony_ci } /* wc < 0, real error. */ 36462306a36Sopenharmony_ci goto conversion_err; 36562306a36Sopenharmony_ci } 36662306a36Sopenharmony_ci ns[o] = 0; 36762306a36Sopenharmony_ci *outs = ns; 36862306a36Sopenharmony_ci return o; 36962306a36Sopenharmony_ci } /* else (!ins) */ 37062306a36Sopenharmony_ci ntfs_error(vol->sb, "Received NULL pointer."); 37162306a36Sopenharmony_ci return -EINVAL; 37262306a36Sopenharmony_ciconversion_err: 37362306a36Sopenharmony_ci ntfs_error(vol->sb, "Unicode name contains characters that cannot be " 37462306a36Sopenharmony_ci "converted to character set %s. You might want to " 37562306a36Sopenharmony_ci "try to use the mount option nls=utf8.", nls->charset); 37662306a36Sopenharmony_ci if (ns != *outs) 37762306a36Sopenharmony_ci kfree(ns); 37862306a36Sopenharmony_ci if (wc != -ENAMETOOLONG) 37962306a36Sopenharmony_ci wc = -EILSEQ; 38062306a36Sopenharmony_ci return wc; 38162306a36Sopenharmony_cimem_err_out: 38262306a36Sopenharmony_ci ntfs_error(vol->sb, "Failed to allocate name!"); 38362306a36Sopenharmony_ci return -ENOMEM; 38462306a36Sopenharmony_ci} 385