diff options
Diffstat (limited to 'fs/udf/unicode.c')
-rw-r--r-- | fs/udf/unicode.c | 146 |
1 files changed, 45 insertions, 101 deletions
diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c index 5599e7535401..dc5990f4c952 100644 --- a/fs/udf/unicode.c +++ b/fs/udf/unicode.c @@ -28,53 +28,8 @@ #include "udf_sb.h" -static int udf_translate_to_linux(uint8_t *, int, uint8_t *, int, uint8_t *, - int); - -static int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen) -{ - if ((!dest) || (!src) || (!strlen) || (strlen > UDF_NAME_LEN)) - return 0; - - memset(dest, 0, sizeof(struct ustr)); - memcpy(dest->u_name, src, strlen); - dest->u_cmpID = 0x08; - dest->u_len = strlen; - - return strlen; -} - -/* - * udf_build_ustr - */ -int udf_build_ustr(struct ustr *dest, dstring *ptr, int size) -{ - int usesize; - - if (!dest || !ptr || !size) - return -1; - BUG_ON(size < 2); - - usesize = min_t(size_t, ptr[size - 1], sizeof(dest->u_name)); - usesize = min(usesize, size - 2); - dest->u_cmpID = ptr[0]; - dest->u_len = usesize; - memcpy(dest->u_name, ptr + 1, usesize); - memset(dest->u_name + usesize, 0, sizeof(dest->u_name) - usesize); - - return 0; -} - -/* - * udf_build_ustr_exact - */ -static void udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize) -{ - memset(dest, 0, sizeof(struct ustr)); - dest->u_cmpID = ptr[0]; - dest->u_len = exactsize - 1; - memcpy(dest->u_name, ptr + 1, exactsize - 1); -} +static int udf_translate_to_linux(uint8_t *, int, const uint8_t *, int, + const uint8_t *, int); static int udf_uni2char_utf8(wchar_t uni, unsigned char *out, @@ -159,53 +114,50 @@ static int udf_char2uni_utf8(const unsigned char *in, return u_len; } -static int udf_name_from_CS0(struct ustr *utf_o, - const struct ustr *ocu_i, +static int udf_name_from_CS0(uint8_t *str_o, int str_max_len, + const uint8_t *ocu, int ocu_len, int (*conv_f)(wchar_t, unsigned char *, int)) { - const uint8_t *ocu; - uint8_t cmp_id, ocu_len; + uint8_t cmp_id; int i, len; + int str_o_len = 0; + if (str_max_len <= 0) + return 0; - ocu_len = ocu_i->u_len; if (ocu_len == 0) { - memset(utf_o, 0, sizeof(struct ustr)); + memset(str_o, 0, str_max_len); return 0; } - cmp_id = ocu_i->u_cmpID; + cmp_id = ocu[0]; if (cmp_id != 8 && cmp_id != 16) { - memset(utf_o, 0, sizeof(struct ustr)); - pr_err("unknown compression code (%d) stri=%s\n", - cmp_id, ocu_i->u_name); + memset(str_o, 0, str_max_len); + pr_err("unknown compression code (%d) stri=%s\n", cmp_id, ocu); return -EINVAL; } - ocu = ocu_i->u_name; - utf_o->u_len = 0; - for (i = 0; (i < ocu_len) && (utf_o->u_len < UDF_NAME_LEN);) { + for (i = 1; (i < ocu_len) && (str_o_len < str_max_len);) { /* Expand OSTA compressed Unicode to Unicode */ uint32_t c = ocu[i++]; if (cmp_id == 16) c = (c << 8) | ocu[i++]; - len = conv_f(c, &utf_o->u_name[utf_o->u_len], - UDF_NAME_LEN - utf_o->u_len); + len = conv_f(c, &str_o[str_o_len], str_max_len - str_o_len); /* Valid character? */ if (len >= 0) - utf_o->u_len += len; + str_o_len += len; else if (len == -ENAMETOOLONG) break; else - utf_o->u_name[utf_o->u_len++] = '?'; + str_o[str_o_len++] = '?'; } - utf_o->u_cmpID = 8; - return utf_o->u_len; + return str_o_len; } -static int udf_name_to_CS0(dstring *ocu, struct ustr *uni, int length, +static int udf_name_to_CS0(uint8_t *ocu, int ocu_max_len, + const uint8_t *str_i, int str_len, int (*conv_f)(const unsigned char *, int, wchar_t *)) { int i, len; @@ -213,18 +165,21 @@ static int udf_name_to_CS0(dstring *ocu, struct ustr *uni, int length, wchar_t uni_char; int u_len, u_ch; - memset(ocu, 0, sizeof(dstring) * length); + if (ocu_max_len <= 0) + return 0; + + memset(ocu, 0, ocu_max_len); ocu[0] = 8; max_val = 0xff; u_ch = 1; try_again: - u_len = 0; - for (i = 0; i < uni->u_len; i++) { + u_len = 1; + for (i = 0; i < str_len; i++) { /* Name didn't fit? */ - if (u_len + 1 + u_ch >= length) + if (u_len + u_ch > ocu_max_len) return 0; - len = conv_f(&uni->u_name[i], uni->u_len - i, &uni_char); + len = conv_f(&str_i[i], str_len - i, &uni_char); if (!len) continue; /* Invalid character, deal with it */ @@ -241,41 +196,37 @@ try_again: } if (max_val == 0xffff) - ocu[++u_len] = (uint8_t)(uni_char >> 8); - ocu[++u_len] = (uint8_t)(uni_char & 0xff); + ocu[u_len++] = (uint8_t)(uni_char >> 8); + ocu[u_len++] = (uint8_t)(uni_char & 0xff); i += len - 1; } - ocu[length - 1] = (uint8_t)u_len + 1; - return u_len + 1; + return u_len; } -int udf_CS0toUTF8(struct ustr *utf_o, const struct ustr *ocu_i) +int udf_CS0toUTF8(uint8_t *utf_o, int o_len, const uint8_t *ocu_i, int i_len) { - return udf_name_from_CS0(utf_o, ocu_i, udf_uni2char_utf8); + return udf_name_from_CS0(utf_o, o_len, ocu_i, i_len, + udf_uni2char_utf8); } -int udf_get_filename(struct super_block *sb, uint8_t *sname, int slen, +int udf_get_filename(struct super_block *sb, const uint8_t *sname, int slen, uint8_t *dname, int dlen) { - struct ustr *filename, *unifilename; + uint8_t *filename; int (*conv_f)(wchar_t, unsigned char *, int); int ret; if (!slen) return -EIO; - filename = kmalloc(sizeof(struct ustr), GFP_NOFS); + if (dlen <= 0) + return 0; + + filename = kmalloc(dlen, GFP_NOFS); if (!filename) return -ENOMEM; - unifilename = kmalloc(sizeof(struct ustr), GFP_NOFS); - if (!unifilename) { - ret = -ENOMEM; - goto out1; - } - - udf_build_ustr_exact(unifilename, sname, slen); if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) { conv_f = udf_uni2char_utf8; } else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) { @@ -283,21 +234,18 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, int slen, } else BUG(); - ret = udf_name_from_CS0(filename, unifilename, conv_f); + ret = udf_name_from_CS0(filename, dlen, sname, slen, conv_f); if (ret < 0) { udf_debug("Failed in udf_get_filename: sname = %s\n", sname); goto out2; } - ret = udf_translate_to_linux(dname, dlen, - filename->u_name, filename->u_len, - unifilename->u_name, unifilename->u_len); + ret = udf_translate_to_linux(dname, dlen, filename, dlen, + sname + 1, slen - 1); /* Zero length filename isn't valid... */ if (ret == 0) ret = -EINVAL; out2: - kfree(unifilename); -out1: kfree(filename); return ret; } @@ -305,12 +253,8 @@ out1: int udf_put_filename(struct super_block *sb, const uint8_t *sname, int slen, uint8_t *dname, int dlen) { - struct ustr unifilename; int (*conv_f)(const unsigned char *, int, wchar_t *); - if (!udf_char_to_ustr(&unifilename, sname, slen)) - return 0; - if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) { conv_f = udf_char2uni_utf8; } else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) { @@ -318,7 +262,7 @@ int udf_put_filename(struct super_block *sb, const uint8_t *sname, int slen, } else BUG(); - return udf_name_to_CS0(dname, &unifilename, dlen, conv_f); + return udf_name_to_CS0(dname, dlen, sname, slen, conv_f); } #define ILLEGAL_CHAR_MARK '_' @@ -329,8 +273,8 @@ int udf_put_filename(struct super_block *sb, const uint8_t *sname, int slen, #define CRC_LEN 5 static int udf_translate_to_linux(uint8_t *newName, int newLen, - uint8_t *udfName, int udfLen, - uint8_t *fidName, int fidNameLen) + const uint8_t *udfName, int udfLen, + const uint8_t *fidName, int fidNameLen) { int index, newIndex = 0, needsCRC = 0; int extIndex = 0, newExtIndex = 0, hasExt = 0; |