unicode.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:11k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * unicode.c
  3.  *
  4.  * PURPOSE
  5.  * Routines for converting between UTF-8 and OSTA Compressed Unicode.
  6.  *      Also handles filename mangling
  7.  *
  8.  * DESCRIPTION
  9.  * OSTA Compressed Unicode is explained in the OSTA UDF specification.
  10.  * http://www.osta.org/
  11.  * UTF-8 is explained in the IETF RFC XXXX.
  12.  * ftp://ftp.internic.net/rfc/rfcxxxx.txt
  13.  *
  14.  * CONTACTS
  15.  * E-mail regarding any portion of the Linux UDF file system should be
  16.  * directed to the development team's mailing list (run by majordomo):
  17.  * linux_udf@hpesjro.fc.hp.com
  18.  *
  19.  * COPYRIGHT
  20.  * This file is distributed under the terms of the GNU General Public
  21.  * License (GPL). Copies of the GPL can be obtained from:
  22.  * ftp://prep.ai.mit.edu/pub/gnu/GPL
  23.  * Each contributing author retains all rights to their own work.
  24.  */
  25. #include "udfdecl.h"
  26. #include <linux/kernel.h>
  27. #include <linux/string.h> /* for memset */
  28. #include <linux/nls.h>
  29. #include <linux/udf_fs.h>
  30. #include "udf_sb.h"
  31. int udf_ustr_to_dchars(uint8_t *dest, const struct ustr *src, int strlen)
  32. {
  33. if ( (!dest) || (!src) || (!strlen) || (src->u_len > strlen) )
  34. return 0;
  35. memcpy(dest+1, src->u_name, src->u_len);
  36. dest[0] = src->u_cmpID;
  37. return src->u_len + 1;
  38. }
  39. int udf_ustr_to_char(uint8_t *dest, const struct ustr *src, int strlen)
  40. {
  41. if ( (!dest) || (!src) || (!strlen) || (src->u_len >= strlen) )
  42. return 0;
  43. memcpy(dest, src->u_name, src->u_len);
  44. return src->u_len;
  45. }
  46. int udf_ustr_to_dstring(dstring *dest, const struct ustr *src, int dlength)
  47. {
  48. if ( udf_ustr_to_dchars(dest, src, dlength-1) )
  49. {
  50. dest[dlength-1] = src->u_len + 1;
  51. return dlength;
  52. }
  53. else
  54. return 0;
  55. }
  56. int udf_dchars_to_ustr(struct ustr *dest, const uint8_t *src, int strlen)
  57. {
  58. if ( (!dest) || (!src) || (!strlen) || (strlen > UDF_NAME_LEN) )
  59. return 0;
  60. memset(dest, 0, sizeof(struct ustr));
  61. memcpy(dest->u_name, src+1, strlen-1);
  62. dest->u_cmpID = src[0];
  63. dest->u_len = strlen-1;
  64. return strlen-1;
  65. }
  66. int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen)
  67. {
  68. if ( (!dest) || (!src) || (!strlen) || (strlen >= UDF_NAME_LEN) )
  69. return 0;
  70. memset(dest, 0, sizeof(struct ustr));
  71. memcpy(dest->u_name, src, strlen);
  72. dest->u_cmpID = 0x08;
  73. dest->u_len = strlen;
  74. return strlen;
  75. }
  76. int udf_dstring_to_ustr(struct ustr *dest, const dstring *src, int dlength)
  77. {
  78. if ( dlength && udf_dchars_to_ustr(dest, src, src[dlength-1]) )
  79. return dlength;
  80. else
  81. return 0;
  82. }
  83. /*
  84.  * udf_build_ustr
  85.  */
  86. int udf_build_ustr(struct ustr *dest, dstring *ptr, int size)
  87. {
  88. int usesize;
  89. if ( (!dest) || (!ptr) || (!size) )
  90. return -1;
  91. memset(dest, 0, sizeof(struct ustr));
  92. usesize= (size > UDF_NAME_LEN) ? UDF_NAME_LEN : size;
  93. dest->u_cmpID=ptr[0];
  94. dest->u_len=ptr[size-1];
  95. memcpy(dest->u_name, ptr+1, usesize-1);
  96. return 0;
  97. }
  98. /*
  99.  * udf_build_ustr_exact
  100.  */
  101. int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
  102. {
  103. if ( (!dest) || (!ptr) || (!exactsize) )
  104. return -1;
  105. memset(dest, 0, sizeof(struct ustr));
  106. dest->u_cmpID=ptr[0];
  107. dest->u_len=exactsize-1;
  108. memcpy(dest->u_name, ptr+1, exactsize-1);
  109. return 0;
  110. }
  111. /*
  112.  * udf_ocu_to_utf8
  113.  *
  114.  * PURPOSE
  115.  * Convert OSTA Compressed Unicode to the UTF-8 equivalent.
  116.  *
  117.  * DESCRIPTION
  118.  * This routine is only called by udf_filldir().
  119.  *
  120.  * PRE-CONDITIONS
  121.  * utf Pointer to UTF-8 output buffer.
  122.  * ocu Pointer to OSTA Compressed Unicode input buffer
  123.  * of size UDF_NAME_LEN bytes.
  124.  *  both of type "struct ustr *"
  125.  *
  126.  * POST-CONDITIONS
  127.  * <return> Zero on success.
  128.  *
  129.  * HISTORY
  130.  * November 12, 1997 - Andrew E. Mileski
  131.  * Written, tested, and released.
  132.  */
  133. int udf_CS0toUTF8(struct ustr *utf_o, struct ustr *ocu_i)
  134. {
  135. uint8_t *ocu;
  136. uint32_t c;
  137. uint8_t cmp_id, ocu_len;
  138. int i;
  139. ocu = ocu_i->u_name;
  140. ocu_len = ocu_i->u_len;
  141. cmp_id = ocu_i->u_cmpID;
  142. utf_o->u_len = 0;
  143. if (ocu_len == 0)
  144. {
  145. memset(utf_o, 0, sizeof(struct ustr));
  146. utf_o->u_cmpID = 0;
  147. utf_o->u_len = 0;
  148. return 0;
  149. }
  150. if ((cmp_id != 8) && (cmp_id != 16))
  151. {
  152. printk(KERN_ERR "udf: unknown compression code (%d) stri=%sn", cmp_id, ocu_i->u_name);
  153. return 0;
  154. }
  155. for (i = 0; (i < ocu_len) && (utf_o->u_len <= (UDF_NAME_LEN-3)) ;)
  156. {
  157. /* Expand OSTA compressed Unicode to Unicode */
  158. c = ocu[i++];
  159. if (cmp_id == 16)
  160. c = (c << 8) | ocu[i++];
  161. /* Compress Unicode to UTF-8 */
  162. if (c < 0x80U)
  163. utf_o->u_name[utf_o->u_len++] = (uint8_t)c;
  164. else if (c < 0x800U)
  165. {
  166. utf_o->u_name[utf_o->u_len++] = (uint8_t)(0xc0 | (c >> 6));
  167. utf_o->u_name[utf_o->u_len++] = (uint8_t)(0x80 | (c & 0x3f));
  168. }
  169. else
  170. {
  171. utf_o->u_name[utf_o->u_len++] = (uint8_t)(0xe0 | (c >> 12));
  172. utf_o->u_name[utf_o->u_len++] = (uint8_t)(0x80 | ((c >> 6) & 0x3f));
  173. utf_o->u_name[utf_o->u_len++] = (uint8_t)(0x80 | (c & 0x3f));
  174. }
  175. }
  176. utf_o->u_cmpID=8;
  177. return utf_o->u_len;
  178. }
  179. /*
  180.  *
  181.  * udf_utf8_to_ocu
  182.  *
  183.  * PURPOSE
  184.  * Convert UTF-8 to the OSTA Compressed Unicode equivalent.
  185.  *
  186.  * DESCRIPTION
  187.  * This routine is only called by udf_lookup().
  188.  *
  189.  * PRE-CONDITIONS
  190.  * ocu Pointer to OSTA Compressed Unicode output
  191.  * buffer of size UDF_NAME_LEN bytes.
  192.  * utf Pointer to UTF-8 input buffer.
  193.  * utf_len Length of UTF-8 input buffer in bytes.
  194.  *
  195.  * POST-CONDITIONS
  196.  * <return> Zero on success.
  197.  *
  198.  * HISTORY
  199.  * November 12, 1997 - Andrew E. Mileski
  200.  * Written, tested, and released.
  201.  */
  202. int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length)
  203. {
  204. unsigned c, i, max_val, utf_char;
  205. int utf_cnt;
  206. int u_len = 0;
  207. memset(ocu, 0, sizeof(dstring) * length);
  208. ocu[0] = 8;
  209. max_val = 0xffU;
  210. try_again:
  211. utf_char = 0U;
  212. utf_cnt = 0U;
  213. for (i = 0U; i < utf->u_len; i++)
  214. {
  215. c = (uint8_t)utf->u_name[i];
  216. /* Complete a multi-byte UTF-8 character */
  217. if (utf_cnt)
  218. {
  219. utf_char = (utf_char << 6) | (c & 0x3fU);
  220. if (--utf_cnt)
  221. continue;
  222. }
  223. else
  224. {
  225. /* Check for a multi-byte UTF-8 character */
  226. if (c & 0x80U)
  227. {
  228. /* Start a multi-byte UTF-8 character */
  229. if ((c & 0xe0U) == 0xc0U)
  230. {
  231. utf_char = c & 0x1fU;
  232. utf_cnt = 1;
  233. }
  234. else if ((c & 0xf0U) == 0xe0U)
  235. {
  236. utf_char = c & 0x0fU;
  237. utf_cnt = 2;
  238. }
  239. else if ((c & 0xf8U) == 0xf0U)
  240. {
  241. utf_char = c & 0x07U;
  242. utf_cnt = 3;
  243. }
  244. else if ((c & 0xfcU) == 0xf8U)
  245. {
  246. utf_char = c & 0x03U;
  247. utf_cnt = 4;
  248. }
  249. else if ((c & 0xfeU) == 0xfcU)
  250. {
  251. utf_char = c & 0x01U;
  252. utf_cnt = 5;
  253. }
  254. else
  255. goto error_out;
  256. continue;
  257. } else
  258. /* Single byte UTF-8 character (most common) */
  259. utf_char = c;
  260. }
  261. /* Choose no compression if necessary */
  262. if (utf_char > max_val)
  263. {
  264. if ( 0xffU == max_val )
  265. {
  266. max_val = 0xffffU;
  267. ocu[0] = (uint8_t)0x10U;
  268. goto try_again;
  269. }
  270. goto error_out;
  271. }
  272. if (max_val == 0xffffU)
  273. {
  274. ocu[++u_len] = (uint8_t)(utf_char >> 8);
  275. }
  276. ocu[++u_len] = (uint8_t)(utf_char & 0xffU);
  277. }
  278. if (utf_cnt)
  279. {
  280. error_out:
  281. printk(KERN_ERR "udf: bad UTF-8 charactern");
  282. return 0;
  283. }
  284. ocu[length - 1] = (uint8_t)u_len + 1;
  285. return u_len + 1;
  286. }
  287. int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, struct ustr *ocu_i)
  288. {
  289. uint8_t *ocu;
  290. uint32_t c;
  291. uint8_t cmp_id, ocu_len;
  292. int i;
  293. ocu = ocu_i->u_name;
  294. ocu_len = ocu_i->u_len;
  295. cmp_id = ocu_i->u_cmpID;
  296. utf_o->u_len = 0;
  297. if (ocu_len == 0)
  298. {
  299. memset(utf_o, 0, sizeof(struct ustr));
  300. utf_o->u_cmpID = 0;
  301. utf_o->u_len = 0;
  302. return 0;
  303. }
  304. if ((cmp_id != 8) && (cmp_id != 16))
  305. {
  306. printk(KERN_ERR "udf: unknown compression code (%d) stri=%sn", cmp_id, ocu_i->u_name);
  307. return 0;
  308. }
  309. for (i = 0; (i < ocu_len) && (utf_o->u_len <= (UDF_NAME_LEN-3)) ;)
  310. {
  311. /* Expand OSTA compressed Unicode to Unicode */
  312. c = ocu[i++];
  313. if (cmp_id == 16)
  314. c = (c << 8) | ocu[i++];
  315. utf_o->u_len += nls->uni2char(c, &utf_o->u_name[utf_o->u_len], 
  316. UDF_NAME_LEN - utf_o->u_len);
  317. }
  318. utf_o->u_cmpID=8;
  319. return utf_o->u_len;
  320. }
  321. int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni, int length)
  322. {
  323. unsigned len, i, max_val;
  324. uint16_t uni_char;
  325. int uni_cnt;
  326. int u_len = 0;
  327. memset(ocu, 0, sizeof(dstring) * length);
  328. ocu[0] = 8;
  329. max_val = 0xffU;
  330. try_again:
  331. uni_char = 0U;
  332. uni_cnt = 0U;
  333. for (i = 0U; i < uni->u_len; i++)
  334. {
  335. len = nls->char2uni(&uni->u_name[i], uni->u_len-i, &uni_char);
  336. if (len == 2 && max_val == 0xff)
  337. {
  338. max_val = 0xffffU;
  339. ocu[0] = (uint8_t)0x10U;
  340. goto try_again;
  341. }
  342. if (max_val == 0xffffU)
  343. {
  344. ocu[++u_len] = (uint8_t)(uni_char >> 8);
  345. i++;
  346. }
  347. ocu[++u_len] = (uint8_t)(uni_char & 0xffU);
  348. }
  349. ocu[length - 1] = (uint8_t)u_len + 1;
  350. return u_len + 1;
  351. }
  352. int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, int flen)
  353. {
  354. struct ustr filename, unifilename;
  355. int len;
  356. if (udf_build_ustr_exact(&unifilename, sname, flen))
  357. {
  358. return 0;
  359. }
  360. if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8))
  361. {
  362. if (!udf_CS0toUTF8(&filename, &unifilename) )
  363. {
  364. udf_debug("Failed in udf_get_filename: sname = %sn", sname);
  365. return 0;
  366. }
  367. }
  368. else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
  369. {
  370. if (!udf_CS0toNLS(UDF_SB(sb)->s_nls_map, &filename, &unifilename) )
  371. {
  372. udf_debug("Failed in udf_get_filename: sname = %sn", sname);
  373. return 0;
  374. }
  375. }
  376. else
  377. return 0;
  378. if ((len = udf_translate_to_linux(dname, filename.u_name, filename.u_len,
  379. unifilename.u_name, unifilename.u_len)))
  380. {
  381. return len;
  382. }
  383. return 0;
  384. }
  385. #define ILLEGAL_CHAR_MARK '_'
  386. #define EXT_MARK '.'
  387. #define CRC_MARK '#'
  388. #define EXT_SIZE 5
  389. int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, int udfLen, uint8_t *fidName, int fidNameLen)
  390. {
  391. int index, newIndex = 0, needsCRC = 0;
  392. int extIndex = 0, newExtIndex = 0, hasExt = 0;
  393. unsigned short valueCRC;
  394. uint8_t curr;
  395. const uint8_t hexChar[] = "0123456789ABCDEF";
  396. if (udfName[0] == '.' && (udfLen == 1 ||
  397. (udfLen == 2 && udfName[1] == '.')))
  398. {
  399. needsCRC = 1;
  400. newIndex = udfLen;
  401. memcpy(newName, udfName, udfLen);
  402. }
  403. else
  404. {
  405. for (index = 0; index < udfLen; index++)
  406. {
  407. curr = udfName[index];
  408. if (curr == '/' || curr == 0)
  409. {
  410. needsCRC = 1;
  411. curr = ILLEGAL_CHAR_MARK;
  412. while (index+1 < udfLen && (udfName[index+1] == '/' ||
  413. udfName[index+1] == 0))
  414. index++;
  415. }
  416. if (curr == EXT_MARK && (udfLen - index - 1) <= EXT_SIZE)
  417. {
  418. if (udfLen == index + 1)
  419. hasExt = 0;
  420. else
  421. {
  422. hasExt = 1;
  423. extIndex = index;
  424. newExtIndex = newIndex;
  425. }
  426. }
  427. if (newIndex < 256)
  428. newName[newIndex++] = curr;
  429. else
  430. needsCRC = 1;
  431. }
  432. }
  433. if (needsCRC)
  434. {
  435. uint8_t ext[EXT_SIZE];
  436. int localExtIndex = 0;
  437. if (hasExt)
  438. {
  439. int maxFilenameLen;
  440. for(index = 0; index<EXT_SIZE && extIndex + index +1 < udfLen;
  441. index++ )
  442. {
  443. curr = udfName[extIndex + index + 1];
  444. if (curr == '/' || curr == 0)
  445. {
  446. needsCRC = 1;
  447. curr = ILLEGAL_CHAR_MARK;
  448. while(extIndex + index + 2 < udfLen && (index + 1 < EXT_SIZE
  449. && (udfName[extIndex + index + 2] == '/' ||
  450. udfName[extIndex + index + 2] == 0)))
  451. index++;
  452. }
  453. ext[localExtIndex++] = curr;
  454. }
  455. maxFilenameLen = 250 - localExtIndex;
  456. if (newIndex > maxFilenameLen)
  457. newIndex = maxFilenameLen;
  458. else
  459. newIndex = newExtIndex;
  460. }
  461. else if (newIndex > 250)
  462. newIndex = 250;
  463. newName[newIndex++] = CRC_MARK;
  464. valueCRC = udf_crc(fidName, fidNameLen, 0);
  465. newName[newIndex++] = hexChar[(valueCRC & 0xf000) >> 12];
  466. newName[newIndex++] = hexChar[(valueCRC & 0x0f00) >> 8];
  467. newName[newIndex++] = hexChar[(valueCRC & 0x00f0) >> 4];
  468. newName[newIndex++] = hexChar[(valueCRC & 0x000f)];
  469. if (hasExt)
  470. {
  471. newName[newIndex++] = EXT_MARK;
  472. for (index = 0;index < localExtIndex ;index++ )
  473. newName[newIndex++] = ext[index];
  474. }
  475. }
  476. return newIndex;
  477. }