joliet.c 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /*
  2. * linux/fs/isofs/joliet.c
  3. *
  4. * (C) 1996 Gordon Chaffee
  5. *
  6. * Joliet: Microsoft's Unicode extensions to iso9660
  7. */
  8. #include <linux/types.h>
  9. #include <linux/nls.h>
  10. #include "isofs.h"
  11. /*
  12. * Convert Unicode 16 to UTF-8 or ASCII.
  13. */
  14. static int
  15. uni16_to_x8(unsigned char *ascii, u16 *uni, int len, struct nls_table *nls)
  16. {
  17. wchar_t *ip, ch;
  18. unsigned char *op;
  19. ip = uni;
  20. op = ascii;
  21. while ((ch = get_unaligned(ip)) && len) {
  22. int llen;
  23. ch = be16_to_cpu(ch);
  24. if ((llen = nls->uni2char(ch, op, NLS_MAX_CHARSET_SIZE)) > 0)
  25. op += llen;
  26. else
  27. *op++ = '?';
  28. ip++;
  29. len--;
  30. }
  31. *op = 0;
  32. return (op - ascii);
  33. }
  34. /* Convert big endian wide character string to utf8 */
  35. static int
  36. wcsntombs_be(__u8 *s, const __u8 *pwcs, int inlen, int maxlen)
  37. {
  38. const __u8 *ip;
  39. __u8 *op;
  40. int size;
  41. __u16 c;
  42. op = s;
  43. ip = pwcs;
  44. while ((*ip || ip[1]) && (maxlen > 0) && (inlen > 0)) {
  45. c = (*ip << 8) | ip[1];
  46. if (c > 0x7f) {
  47. size = utf8_wctomb(op, c, maxlen);
  48. if (size == -1) {
  49. /* Ignore character and move on */
  50. maxlen--;
  51. } else {
  52. op += size;
  53. maxlen -= size;
  54. }
  55. } else {
  56. *op++ = (__u8) c;
  57. }
  58. ip += 2;
  59. inlen--;
  60. }
  61. return (op - s);
  62. }
  63. int
  64. get_joliet_filename(struct iso_directory_record * de, unsigned char *outname, struct inode * inode)
  65. {
  66. unsigned char utf8;
  67. struct nls_table *nls;
  68. unsigned char len = 0;
  69. utf8 = ISOFS_SB(inode->i_sb)->s_utf8;
  70. nls = ISOFS_SB(inode->i_sb)->s_nls_iocharset;
  71. if (utf8) {
  72. len = wcsntombs_be(outname, de->name,
  73. de->name_len[0] >> 1, PAGE_SIZE);
  74. } else {
  75. len = uni16_to_x8(outname, (u16 *) de->name,
  76. de->name_len[0] >> 1, nls);
  77. }
  78. if ((len > 2) && (outname[len-2] == ';') && (outname[len-1] == '1')) {
  79. len -= 2;
  80. }
  81. /*
  82. * Windows doesn't like periods at the end of a name,
  83. * so neither do we
  84. */
  85. while (len >= 2 && (outname[len-1] == '.')) {
  86. len--;
  87. }
  88. return len;
  89. }