162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * unicode.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * PURPOSE 662306a36Sopenharmony_ci * Routines for converting between UTF-8 and OSTA Compressed Unicode. 762306a36Sopenharmony_ci * Also handles filename mangling 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * DESCRIPTION 1062306a36Sopenharmony_ci * OSTA Compressed Unicode is explained in the OSTA UDF specification. 1162306a36Sopenharmony_ci * http://www.osta.org/ 1262306a36Sopenharmony_ci * UTF-8 is explained in the IETF RFC XXXX. 1362306a36Sopenharmony_ci * ftp://ftp.internic.net/rfc/rfcxxxx.txt 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include "udfdecl.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include <linux/kernel.h> 2062306a36Sopenharmony_ci#include <linux/string.h> /* for memset */ 2162306a36Sopenharmony_ci#include <linux/nls.h> 2262306a36Sopenharmony_ci#include <linux/crc-itu-t.h> 2362306a36Sopenharmony_ci#include <linux/slab.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#include "udf_sb.h" 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#define PLANE_SIZE 0x10000 2862306a36Sopenharmony_ci#define UNICODE_MAX 0x10ffff 2962306a36Sopenharmony_ci#define SURROGATE_MASK 0xfffff800 3062306a36Sopenharmony_ci#define SURROGATE_PAIR 0x0000d800 3162306a36Sopenharmony_ci#define SURROGATE_LOW 0x00000400 3262306a36Sopenharmony_ci#define SURROGATE_CHAR_BITS 10 3362306a36Sopenharmony_ci#define SURROGATE_CHAR_MASK ((1 << SURROGATE_CHAR_BITS) - 1) 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#define ILLEGAL_CHAR_MARK '_' 3662306a36Sopenharmony_ci#define EXT_MARK '.' 3762306a36Sopenharmony_ci#define CRC_MARK '#' 3862306a36Sopenharmony_ci#define EXT_SIZE 5 3962306a36Sopenharmony_ci/* Number of chars we need to store generated CRC to make filename unique */ 4062306a36Sopenharmony_ci#define CRC_LEN 5 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic unicode_t get_utf16_char(const uint8_t *str_i, int str_i_max_len, 4362306a36Sopenharmony_ci int str_i_idx, int u_ch, unicode_t *ret) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci unicode_t c; 4662306a36Sopenharmony_ci int start_idx = str_i_idx; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci /* Expand OSTA compressed Unicode to Unicode */ 4962306a36Sopenharmony_ci c = str_i[str_i_idx++]; 5062306a36Sopenharmony_ci if (u_ch > 1) 5162306a36Sopenharmony_ci c = (c << 8) | str_i[str_i_idx++]; 5262306a36Sopenharmony_ci if ((c & SURROGATE_MASK) == SURROGATE_PAIR) { 5362306a36Sopenharmony_ci unicode_t next; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci /* Trailing surrogate char */ 5662306a36Sopenharmony_ci if (str_i_idx >= str_i_max_len) { 5762306a36Sopenharmony_ci c = UNICODE_MAX + 1; 5862306a36Sopenharmony_ci goto out; 5962306a36Sopenharmony_ci } 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci /* Low surrogate must follow the high one... */ 6262306a36Sopenharmony_ci if (c & SURROGATE_LOW) { 6362306a36Sopenharmony_ci c = UNICODE_MAX + 1; 6462306a36Sopenharmony_ci goto out; 6562306a36Sopenharmony_ci } 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci WARN_ON_ONCE(u_ch != 2); 6862306a36Sopenharmony_ci next = str_i[str_i_idx++] << 8; 6962306a36Sopenharmony_ci next |= str_i[str_i_idx++]; 7062306a36Sopenharmony_ci if ((next & SURROGATE_MASK) != SURROGATE_PAIR || 7162306a36Sopenharmony_ci !(next & SURROGATE_LOW)) { 7262306a36Sopenharmony_ci c = UNICODE_MAX + 1; 7362306a36Sopenharmony_ci goto out; 7462306a36Sopenharmony_ci } 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci c = PLANE_SIZE + 7762306a36Sopenharmony_ci ((c & SURROGATE_CHAR_MASK) << SURROGATE_CHAR_BITS) + 7862306a36Sopenharmony_ci (next & SURROGATE_CHAR_MASK); 7962306a36Sopenharmony_ci } 8062306a36Sopenharmony_ciout: 8162306a36Sopenharmony_ci *ret = c; 8262306a36Sopenharmony_ci return str_i_idx - start_idx; 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic int udf_name_conv_char(uint8_t *str_o, int str_o_max_len, 8762306a36Sopenharmony_ci int *str_o_idx, 8862306a36Sopenharmony_ci const uint8_t *str_i, int str_i_max_len, 8962306a36Sopenharmony_ci int *str_i_idx, 9062306a36Sopenharmony_ci int u_ch, int *needsCRC, 9162306a36Sopenharmony_ci int (*conv_f)(wchar_t, unsigned char *, int), 9262306a36Sopenharmony_ci int translate) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci unicode_t c; 9562306a36Sopenharmony_ci int illChar = 0; 9662306a36Sopenharmony_ci int len, gotch = 0; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci while (!gotch && *str_i_idx < str_i_max_len) { 9962306a36Sopenharmony_ci if (*str_o_idx >= str_o_max_len) { 10062306a36Sopenharmony_ci *needsCRC = 1; 10162306a36Sopenharmony_ci return gotch; 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci len = get_utf16_char(str_i, str_i_max_len, *str_i_idx, u_ch, 10562306a36Sopenharmony_ci &c); 10662306a36Sopenharmony_ci /* These chars cannot be converted. Replace them. */ 10762306a36Sopenharmony_ci if (c == 0 || c > UNICODE_MAX || (conv_f && c > MAX_WCHAR_T) || 10862306a36Sopenharmony_ci (translate && c == '/')) { 10962306a36Sopenharmony_ci illChar = 1; 11062306a36Sopenharmony_ci if (!translate) 11162306a36Sopenharmony_ci gotch = 1; 11262306a36Sopenharmony_ci } else if (illChar) 11362306a36Sopenharmony_ci break; 11462306a36Sopenharmony_ci else 11562306a36Sopenharmony_ci gotch = 1; 11662306a36Sopenharmony_ci *str_i_idx += len; 11762306a36Sopenharmony_ci } 11862306a36Sopenharmony_ci if (illChar) { 11962306a36Sopenharmony_ci *needsCRC = 1; 12062306a36Sopenharmony_ci c = ILLEGAL_CHAR_MARK; 12162306a36Sopenharmony_ci gotch = 1; 12262306a36Sopenharmony_ci } 12362306a36Sopenharmony_ci if (gotch) { 12462306a36Sopenharmony_ci if (conv_f) { 12562306a36Sopenharmony_ci len = conv_f(c, &str_o[*str_o_idx], 12662306a36Sopenharmony_ci str_o_max_len - *str_o_idx); 12762306a36Sopenharmony_ci } else { 12862306a36Sopenharmony_ci len = utf32_to_utf8(c, &str_o[*str_o_idx], 12962306a36Sopenharmony_ci str_o_max_len - *str_o_idx); 13062306a36Sopenharmony_ci if (len < 0) 13162306a36Sopenharmony_ci len = -ENAMETOOLONG; 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci /* Valid character? */ 13462306a36Sopenharmony_ci if (len >= 0) 13562306a36Sopenharmony_ci *str_o_idx += len; 13662306a36Sopenharmony_ci else if (len == -ENAMETOOLONG) { 13762306a36Sopenharmony_ci *needsCRC = 1; 13862306a36Sopenharmony_ci gotch = 0; 13962306a36Sopenharmony_ci } else { 14062306a36Sopenharmony_ci str_o[(*str_o_idx)++] = ILLEGAL_CHAR_MARK; 14162306a36Sopenharmony_ci *needsCRC = 1; 14262306a36Sopenharmony_ci } 14362306a36Sopenharmony_ci } 14462306a36Sopenharmony_ci return gotch; 14562306a36Sopenharmony_ci} 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic int udf_name_from_CS0(struct super_block *sb, 14862306a36Sopenharmony_ci uint8_t *str_o, int str_max_len, 14962306a36Sopenharmony_ci const uint8_t *ocu, int ocu_len, 15062306a36Sopenharmony_ci int translate) 15162306a36Sopenharmony_ci{ 15262306a36Sopenharmony_ci uint32_t c; 15362306a36Sopenharmony_ci uint8_t cmp_id; 15462306a36Sopenharmony_ci int idx, len; 15562306a36Sopenharmony_ci int u_ch; 15662306a36Sopenharmony_ci int needsCRC = 0; 15762306a36Sopenharmony_ci int ext_i_len, ext_max_len; 15862306a36Sopenharmony_ci int str_o_len = 0; /* Length of resulting output */ 15962306a36Sopenharmony_ci int ext_o_len = 0; /* Extension output length */ 16062306a36Sopenharmony_ci int ext_crc_len = 0; /* Extension output length if used with CRC */ 16162306a36Sopenharmony_ci int i_ext = -1; /* Extension position in input buffer */ 16262306a36Sopenharmony_ci int o_crc = 0; /* Rightmost possible output pos for CRC+ext */ 16362306a36Sopenharmony_ci unsigned short valueCRC; 16462306a36Sopenharmony_ci uint8_t ext[EXT_SIZE * NLS_MAX_CHARSET_SIZE + 1]; 16562306a36Sopenharmony_ci uint8_t crc[CRC_LEN]; 16662306a36Sopenharmony_ci int (*conv_f)(wchar_t, unsigned char *, int); 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci if (str_max_len <= 0) 16962306a36Sopenharmony_ci return 0; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci if (ocu_len == 0) { 17262306a36Sopenharmony_ci memset(str_o, 0, str_max_len); 17362306a36Sopenharmony_ci return 0; 17462306a36Sopenharmony_ci } 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci if (UDF_SB(sb)->s_nls_map) 17762306a36Sopenharmony_ci conv_f = UDF_SB(sb)->s_nls_map->uni2char; 17862306a36Sopenharmony_ci else 17962306a36Sopenharmony_ci conv_f = NULL; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci cmp_id = ocu[0]; 18262306a36Sopenharmony_ci if (cmp_id != 8 && cmp_id != 16) { 18362306a36Sopenharmony_ci memset(str_o, 0, str_max_len); 18462306a36Sopenharmony_ci pr_err("unknown compression code (%u)\n", cmp_id); 18562306a36Sopenharmony_ci return -EINVAL; 18662306a36Sopenharmony_ci } 18762306a36Sopenharmony_ci u_ch = cmp_id >> 3; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci ocu++; 19062306a36Sopenharmony_ci ocu_len--; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci if (ocu_len % u_ch) { 19362306a36Sopenharmony_ci pr_err("incorrect filename length (%d)\n", ocu_len + 1); 19462306a36Sopenharmony_ci return -EINVAL; 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci if (translate) { 19862306a36Sopenharmony_ci /* Look for extension */ 19962306a36Sopenharmony_ci for (idx = ocu_len - u_ch, ext_i_len = 0; 20062306a36Sopenharmony_ci (idx >= 0) && (ext_i_len < EXT_SIZE); 20162306a36Sopenharmony_ci idx -= u_ch, ext_i_len++) { 20262306a36Sopenharmony_ci c = ocu[idx]; 20362306a36Sopenharmony_ci if (u_ch > 1) 20462306a36Sopenharmony_ci c = (c << 8) | ocu[idx + 1]; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci if (c == EXT_MARK) { 20762306a36Sopenharmony_ci if (ext_i_len) 20862306a36Sopenharmony_ci i_ext = idx; 20962306a36Sopenharmony_ci break; 21062306a36Sopenharmony_ci } 21162306a36Sopenharmony_ci } 21262306a36Sopenharmony_ci if (i_ext >= 0) { 21362306a36Sopenharmony_ci /* Convert extension */ 21462306a36Sopenharmony_ci ext_max_len = min_t(int, sizeof(ext), str_max_len); 21562306a36Sopenharmony_ci ext[ext_o_len++] = EXT_MARK; 21662306a36Sopenharmony_ci idx = i_ext + u_ch; 21762306a36Sopenharmony_ci while (udf_name_conv_char(ext, ext_max_len, &ext_o_len, 21862306a36Sopenharmony_ci ocu, ocu_len, &idx, 21962306a36Sopenharmony_ci u_ch, &needsCRC, 22062306a36Sopenharmony_ci conv_f, translate)) { 22162306a36Sopenharmony_ci if ((ext_o_len + CRC_LEN) < str_max_len) 22262306a36Sopenharmony_ci ext_crc_len = ext_o_len; 22362306a36Sopenharmony_ci } 22462306a36Sopenharmony_ci } 22562306a36Sopenharmony_ci } 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci idx = 0; 22862306a36Sopenharmony_ci while (1) { 22962306a36Sopenharmony_ci if (translate && (idx == i_ext)) { 23062306a36Sopenharmony_ci if (str_o_len > (str_max_len - ext_o_len)) 23162306a36Sopenharmony_ci needsCRC = 1; 23262306a36Sopenharmony_ci break; 23362306a36Sopenharmony_ci } 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci if (!udf_name_conv_char(str_o, str_max_len, &str_o_len, 23662306a36Sopenharmony_ci ocu, ocu_len, &idx, 23762306a36Sopenharmony_ci u_ch, &needsCRC, conv_f, translate)) 23862306a36Sopenharmony_ci break; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci if (translate && 24162306a36Sopenharmony_ci (str_o_len <= (str_max_len - ext_o_len - CRC_LEN))) 24262306a36Sopenharmony_ci o_crc = str_o_len; 24362306a36Sopenharmony_ci } 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci if (translate) { 24662306a36Sopenharmony_ci if (str_o_len > 0 && str_o_len <= 2 && str_o[0] == '.' && 24762306a36Sopenharmony_ci (str_o_len == 1 || str_o[1] == '.')) 24862306a36Sopenharmony_ci needsCRC = 1; 24962306a36Sopenharmony_ci if (needsCRC) { 25062306a36Sopenharmony_ci str_o_len = o_crc; 25162306a36Sopenharmony_ci valueCRC = crc_itu_t(0, ocu, ocu_len); 25262306a36Sopenharmony_ci crc[0] = CRC_MARK; 25362306a36Sopenharmony_ci crc[1] = hex_asc_upper_hi(valueCRC >> 8); 25462306a36Sopenharmony_ci crc[2] = hex_asc_upper_lo(valueCRC >> 8); 25562306a36Sopenharmony_ci crc[3] = hex_asc_upper_hi(valueCRC); 25662306a36Sopenharmony_ci crc[4] = hex_asc_upper_lo(valueCRC); 25762306a36Sopenharmony_ci len = min_t(int, CRC_LEN, str_max_len - str_o_len); 25862306a36Sopenharmony_ci memcpy(&str_o[str_o_len], crc, len); 25962306a36Sopenharmony_ci str_o_len += len; 26062306a36Sopenharmony_ci ext_o_len = ext_crc_len; 26162306a36Sopenharmony_ci } 26262306a36Sopenharmony_ci if (ext_o_len > 0) { 26362306a36Sopenharmony_ci memcpy(&str_o[str_o_len], ext, ext_o_len); 26462306a36Sopenharmony_ci str_o_len += ext_o_len; 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci return str_o_len; 26962306a36Sopenharmony_ci} 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_cistatic int udf_name_to_CS0(struct super_block *sb, 27262306a36Sopenharmony_ci uint8_t *ocu, int ocu_max_len, 27362306a36Sopenharmony_ci const uint8_t *str_i, int str_len) 27462306a36Sopenharmony_ci{ 27562306a36Sopenharmony_ci int i, len; 27662306a36Sopenharmony_ci unsigned int max_val; 27762306a36Sopenharmony_ci int u_len, u_ch; 27862306a36Sopenharmony_ci unicode_t uni_char; 27962306a36Sopenharmony_ci int (*conv_f)(const unsigned char *, int, wchar_t *); 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci if (ocu_max_len <= 0) 28262306a36Sopenharmony_ci return 0; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci if (UDF_SB(sb)->s_nls_map) 28562306a36Sopenharmony_ci conv_f = UDF_SB(sb)->s_nls_map->char2uni; 28662306a36Sopenharmony_ci else 28762306a36Sopenharmony_ci conv_f = NULL; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci memset(ocu, 0, ocu_max_len); 29062306a36Sopenharmony_ci ocu[0] = 8; 29162306a36Sopenharmony_ci max_val = 0xff; 29262306a36Sopenharmony_ci u_ch = 1; 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_citry_again: 29562306a36Sopenharmony_ci u_len = 1; 29662306a36Sopenharmony_ci for (i = 0; i < str_len; i += len) { 29762306a36Sopenharmony_ci /* Name didn't fit? */ 29862306a36Sopenharmony_ci if (u_len + u_ch > ocu_max_len) 29962306a36Sopenharmony_ci return 0; 30062306a36Sopenharmony_ci if (conv_f) { 30162306a36Sopenharmony_ci wchar_t wchar; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci len = conv_f(&str_i[i], str_len - i, &wchar); 30462306a36Sopenharmony_ci if (len > 0) 30562306a36Sopenharmony_ci uni_char = wchar; 30662306a36Sopenharmony_ci } else { 30762306a36Sopenharmony_ci len = utf8_to_utf32(&str_i[i], str_len - i, 30862306a36Sopenharmony_ci &uni_char); 30962306a36Sopenharmony_ci } 31062306a36Sopenharmony_ci /* Invalid character, deal with it */ 31162306a36Sopenharmony_ci if (len <= 0 || uni_char > UNICODE_MAX) { 31262306a36Sopenharmony_ci len = 1; 31362306a36Sopenharmony_ci uni_char = '?'; 31462306a36Sopenharmony_ci } 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci if (uni_char > max_val) { 31762306a36Sopenharmony_ci unicode_t c; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci if (max_val == 0xff) { 32062306a36Sopenharmony_ci max_val = 0xffff; 32162306a36Sopenharmony_ci ocu[0] = 0x10; 32262306a36Sopenharmony_ci u_ch = 2; 32362306a36Sopenharmony_ci goto try_again; 32462306a36Sopenharmony_ci } 32562306a36Sopenharmony_ci /* 32662306a36Sopenharmony_ci * Use UTF-16 encoding for chars outside we 32762306a36Sopenharmony_ci * cannot encode directly. 32862306a36Sopenharmony_ci */ 32962306a36Sopenharmony_ci if (u_len + 2 * u_ch > ocu_max_len) 33062306a36Sopenharmony_ci return 0; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci uni_char -= PLANE_SIZE; 33362306a36Sopenharmony_ci c = SURROGATE_PAIR | 33462306a36Sopenharmony_ci ((uni_char >> SURROGATE_CHAR_BITS) & 33562306a36Sopenharmony_ci SURROGATE_CHAR_MASK); 33662306a36Sopenharmony_ci ocu[u_len++] = (uint8_t)(c >> 8); 33762306a36Sopenharmony_ci ocu[u_len++] = (uint8_t)(c & 0xff); 33862306a36Sopenharmony_ci uni_char = SURROGATE_PAIR | SURROGATE_LOW | 33962306a36Sopenharmony_ci (uni_char & SURROGATE_CHAR_MASK); 34062306a36Sopenharmony_ci } 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci if (max_val == 0xffff) 34362306a36Sopenharmony_ci ocu[u_len++] = (uint8_t)(uni_char >> 8); 34462306a36Sopenharmony_ci ocu[u_len++] = (uint8_t)(uni_char & 0xff); 34562306a36Sopenharmony_ci } 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci return u_len; 34862306a36Sopenharmony_ci} 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci/* 35162306a36Sopenharmony_ci * Convert CS0 dstring to output charset. Warning: This function may truncate 35262306a36Sopenharmony_ci * input string if it is too long as it is used for informational strings only 35362306a36Sopenharmony_ci * and it is better to truncate the string than to refuse mounting a media. 35462306a36Sopenharmony_ci */ 35562306a36Sopenharmony_ciint udf_dstrCS0toChar(struct super_block *sb, uint8_t *utf_o, int o_len, 35662306a36Sopenharmony_ci const uint8_t *ocu_i, int i_len) 35762306a36Sopenharmony_ci{ 35862306a36Sopenharmony_ci int s_len = 0; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci if (i_len > 0) { 36162306a36Sopenharmony_ci s_len = ocu_i[i_len - 1]; 36262306a36Sopenharmony_ci if (s_len >= i_len) { 36362306a36Sopenharmony_ci pr_warn("incorrect dstring lengths (%d/%d)," 36462306a36Sopenharmony_ci " truncating\n", s_len, i_len); 36562306a36Sopenharmony_ci s_len = i_len - 1; 36662306a36Sopenharmony_ci /* 2-byte encoding? Need to round properly... */ 36762306a36Sopenharmony_ci if (ocu_i[0] == 16) 36862306a36Sopenharmony_ci s_len -= (s_len - 1) & 2; 36962306a36Sopenharmony_ci } 37062306a36Sopenharmony_ci } 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci return udf_name_from_CS0(sb, utf_o, o_len, ocu_i, s_len, 0); 37362306a36Sopenharmony_ci} 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ciint udf_get_filename(struct super_block *sb, const uint8_t *sname, int slen, 37662306a36Sopenharmony_ci uint8_t *dname, int dlen) 37762306a36Sopenharmony_ci{ 37862306a36Sopenharmony_ci int ret; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci if (!slen) 38162306a36Sopenharmony_ci return -EIO; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci if (dlen <= 0) 38462306a36Sopenharmony_ci return 0; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci ret = udf_name_from_CS0(sb, dname, dlen, sname, slen, 1); 38762306a36Sopenharmony_ci /* Zero length filename isn't valid... */ 38862306a36Sopenharmony_ci if (ret == 0) 38962306a36Sopenharmony_ci ret = -EINVAL; 39062306a36Sopenharmony_ci return ret; 39162306a36Sopenharmony_ci} 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ciint udf_put_filename(struct super_block *sb, const uint8_t *sname, int slen, 39462306a36Sopenharmony_ci uint8_t *dname, int dlen) 39562306a36Sopenharmony_ci{ 39662306a36Sopenharmony_ci return udf_name_to_CS0(sb, dname, dlen, sname, slen); 39762306a36Sopenharmony_ci} 39862306a36Sopenharmony_ci 399