trans.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:16k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * linux/fs/hfs/trans.c
  3.  *
  4.  * Copyright (C) 1995-1997  Paul H. Hargrove
  5.  * This file may be distributed under the terms of the GNU General Public License.
  6.  *
  7.  * This file contains routines for converting between the Macintosh
  8.  * character set and various other encodings.  This includes dealing
  9.  * with ':' vs. '/' as the path-element separator.
  10.  *
  11.  * Latin-1 translation based on code contributed by Holger Schemel
  12.  * (aeglos@valinor.owl.de).
  13.  *
  14.  * The '8-bit', '7-bit ASCII' and '7-bit alphanumeric' encodings are
  15.  * implementations of the three encodings recommended by Apple in the
  16.  * document "AppleSingle/AppleDouble Formats: Developer's Note
  17.  * (9/94)".  This document is available from Apple's Technical
  18.  * Information Library from the World Wide Web server
  19.  * www.info.apple.com.
  20.  *
  21.  * The 'CAP' encoding is an implementation of the naming scheme used
  22.  * by the Columbia AppleTalk Package, available for anonymous FTP from
  23.  * ????.
  24.  *
  25.  * "XXX" in a comment is a note to myself to consider changing something.
  26.  *
  27.  * In function preconditions the term "valid" applied to a pointer to
  28.  * a structure means that the pointer is non-NULL and the structure it
  29.  * points to has all fields initialized to consistent values.
  30.  */
  31. #include "hfs.h"
  32. #include <linux/hfs_fs_sb.h>
  33. #include <linux/hfs_fs_i.h>
  34. #include <linux/hfs_fs.h>
  35. /*================ File-local variables ================*/
  36. /* int->ASCII map for a single hex digit */
  37. static char hex[16] = {'0','1','2','3','4','5','6','7',
  38.        '8','9','a','b','c','d','e','f'};
  39. /*
  40.  * Latin-1 to Mac character set map
  41.  *
  42.  * For the sake of consistency this map is generated from the Mac to
  43.  * Latin-1 map the first time it is needed.  This means there is just
  44.  * one map to maintain.
  45.  */
  46. static unsigned char latin2mac_map[128]; /* initially all zero */
  47. /*
  48.  * Mac to Latin-1 map for the upper 128 characters (both have ASCII in
  49.  * the lower 128 positions)
  50.  */
  51. static unsigned char mac2latin_map[128] = {
  52. 0xC4, 0xC5, 0xC7, 0xC9, 0xD1, 0xD6, 0xDC, 0xE1,
  53. 0xE0, 0xE2, 0xE4, 0xE3, 0xE5, 0xE7, 0xE9, 0xE8,
  54. 0xEA, 0xEB, 0xED, 0xEC, 0xEE, 0xEF, 0xF1, 0xF3,
  55. 0xF2, 0xF4, 0xF6, 0xF5, 0xFA, 0xF9, 0xFB, 0xFC,
  56. 0x00, 0xB0, 0xA2, 0xA3, 0xA7, 0xB7, 0xB6, 0xDF,
  57. 0xAE, 0xA9, 0x00, 0xB4, 0xA8, 0x00, 0xC6, 0xD8,
  58. 0x00, 0xB1, 0x00, 0x00, 0xA5, 0xB5, 0xF0, 0x00, 
  59. 0x00, 0x00, 0x00, 0xAA, 0xBA, 0x00, 0xE6, 0xF8,
  60. 0xBF, 0xA1, 0xAC, 0x00, 0x00, 0x00, 0x00, 0xAB,
  61. 0xBB, 0x00, 0xA0, 0xC0, 0xC3, 0xD5, 0x00, 0x00, 
  62. 0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7, 0x00, 
  63. 0xFF, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x00, 0x00, 
  64. 0x00, 0x00, 0xB8, 0x00, 0x00, 0xC2, 0xCA, 0xC1,
  65. 0xCB, 0xC8, 0xCD, 0xCE, 0xCF, 0xCC, 0xD3, 0xD4,
  66. 0x00, 0xD2, 0xDA, 0xDB, 0xD9, 0x00, 0x00, 0x00,
  67. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  68. };
  69. /*================ File-local functions ================*/
  70. /*
  71.  * dehex()
  72.  *
  73.  * Given a hexadecimal digit in ASCII, return the integer representation.
  74.  */
  75. static inline const unsigned char dehex(char c) {
  76. if ((c>='0')&&(c<='9')) {
  77. return c-'0';
  78. }
  79. if ((c>='a')&&(c<='f')) {
  80. return c-'a'+10;
  81. }
  82. if ((c>='A')&&(c<='F')) {
  83. return c-'A'+10;
  84. }
  85. return 0xff;
  86. }
  87. /*================ Global functions ================*/
  88. /*
  89.  * hfs_mac2nat()
  90.  *
  91.  * Given a 'Pascal String' (a string preceded by a length byte) in
  92.  * the Macintosh character set produce the corresponding filename using
  93.  * the Netatalk name-mangling scheme, returning the length of the
  94.  * mangled filename.  Note that the output string is not NULL terminated.
  95.  *
  96.  * The name-mangling works as follows:
  97.  * Characters 32-126 (' '-'~') except '/' and any initial '.' are passed
  98.  * unchanged from input to output.  The remaining characters are replaced
  99.  * by three characters: ':xx' where xx is the hexadecimal representation
  100.  * of the character, using lowercase 'a' through 'f'.
  101.  */
  102. int hfs_mac2nat(char *out, const struct hfs_name *in) {
  103. unsigned char c;
  104. const unsigned char *p = in->Name;
  105. int len = in->Len;
  106. int count = 0;
  107. /* Special case for .AppleDesktop which in the
  108.    distant future may be a pseudodirectory. */
  109. if (strncmp(".AppleDesktop", p, len) == 0) {
  110. strncpy(out, p, 13);
  111. return 13;
  112. }
  113. while (len--) {
  114. c = *p++;
  115. if ((c<32) || (c=='/') || (c>126) || (!count && (c=='.'))) {
  116. *out++ = ':';
  117. *out++ = hex[(c>>4) & 0xf];
  118. *out++ = hex[c & 0xf];
  119. count += 3;
  120. } else {
  121. *out++ = c;
  122. count++;
  123. }
  124. }
  125. return count;
  126. }
  127. /*
  128.  * hfs_mac2cap()
  129.  *
  130.  * Given a 'Pascal String' (a string preceded by a length byte) in
  131.  * the Macintosh character set produce the corresponding filename using
  132.  * the CAP name-mangling scheme, returning the length of the mangled
  133.  * filename.  Note that the output string is not NULL terminated.
  134.  *
  135.  * The name-mangling works as follows:
  136.  * Characters 32-126 (' '-'~') except '/' are passed unchanged from
  137.  * input to output.  The remaining characters are replaced by three
  138.  * characters: ':xx' where xx is the hexadecimal representation of the
  139.  * character, using lowercase 'a' through 'f'.
  140.  */
  141. int hfs_mac2cap(char *out, const struct hfs_name *in) {
  142. unsigned char c;
  143. const unsigned char *p = in->Name;
  144. int len = in->Len;
  145. int count = 0;
  146. while (len--) {
  147. c = *p++;
  148. if ((c<32) || (c=='/') || (c>126)) {
  149. *out++ = ':';
  150. *out++ = hex[(c>>4) & 0xf];
  151. *out++ = hex[c & 0xf];
  152. count += 3;
  153. } else {
  154. *out++ = c;
  155. count++;
  156. }
  157. }
  158. return count;
  159. }
  160. /*
  161.  * hfs_mac2eight()
  162.  *
  163.  * Given a 'Pascal String' (a string preceded by a length byte) in
  164.  * the Macintosh character set produce the corresponding filename using
  165.  * the '8-bit' name-mangling scheme, returning the length of the
  166.  * mangled filename.  Note that the output string is not NULL
  167.  * terminated.
  168.  *
  169.  * This is one of the three recommended naming conventions described
  170.  * in Apple's document "AppleSingle/AppleDouble Formats: Developer's
  171.  * Note (9/94)"
  172.  *
  173.  * The name-mangling works as follows:
  174.  * Characters 0, '%' and '/' are replaced by three characters: '%xx'
  175.  * where xx is the hexadecimal representation of the character, using
  176.  * lowercase 'a' through 'f'.  All other characters are passed
  177.  * unchanged from input to output.  Note that this format is mainly
  178.  * implemented for completeness and is rather hard to read.
  179.  */
  180. int hfs_mac2eight(char *out, const struct hfs_name *in) {
  181. unsigned char c;
  182. const unsigned char *p = in->Name;
  183. int len = in->Len;
  184. int count = 0;
  185. while (len--) {
  186. c = *p++;
  187. if (!c || (c=='/') || (c=='%')) {
  188. *out++ = '%';
  189. *out++ = hex[(c>>4) & 0xf];
  190. *out++ = hex[c & 0xf];
  191. count += 3;
  192. } else {
  193. *out++ = c;
  194. count++;
  195. }
  196. }
  197. return count;
  198. }
  199. /*
  200.  * hfs_mac2seven()
  201.  *
  202.  * Given a 'Pascal String' (a string preceded by a length byte) in
  203.  * the Macintosh character set produce the corresponding filename using
  204.  * the '7-bit ASCII' name-mangling scheme, returning the length of the
  205.  * mangled filename.  Note that the output string is not NULL
  206.  * terminated.
  207.  *
  208.  * This is one of the three recommended naming conventions described
  209.  * in Apple's document "AppleSingle/AppleDouble Formats: Developer's
  210.  * Note (9/94)"
  211.  *
  212.  * The name-mangling works as follows:
  213.  * Characters 0, '%', '/' and 128-255 are replaced by three
  214.  * characters: '%xx' where xx is the hexadecimal representation of the
  215.  * character, using lowercase 'a' through 'f'. All other characters
  216.  * are passed unchanged from input to output.  Note that control
  217.  * characters (including newline) and space are unchanged make reading
  218.  * these filenames difficult.
  219.  */
  220. int hfs_mac2seven(char *out, const struct hfs_name *in) {
  221. unsigned char c;
  222. const unsigned char *p = in->Name;
  223. int len = in->Len;
  224. int count = 0;
  225. while (len--) {
  226. c = *p++;
  227. if (!c || (c=='/') || (c=='%') || (c&0x80)) {
  228. *out++ = '%';
  229. *out++ = hex[(c>>4) & 0xf];
  230. *out++ = hex[c & 0xf];
  231. count += 3;
  232. } else {
  233. *out++ = c;
  234. count++;
  235. }
  236. }
  237. return count;
  238. }
  239. /*
  240.  * hfs_mac2alpha()
  241.  *
  242.  * Given a 'Pascal String' (a string preceded by a length byte) in
  243.  * the Macintosh character set produce the corresponding filename using
  244.  * the '7-bit alphanumeric' name-mangling scheme, returning the length
  245.  * of the mangled filename.  Note that the output string is not NULL
  246.  * terminated.
  247.  *
  248.  * This is one of the three recommended naming conventions described
  249.  * in Apple's document "AppleSingle/AppleDouble Formats: Developer's
  250.  * Note (9/94)"
  251.  *
  252.  * The name-mangling works as follows:
  253.  * The characters 'a'-'z', 'A'-'Z', '0'-'9', '_' and the last '.' in
  254.  * the filename are passed unchanged from input to output.  All
  255.  * remaining characters (including any '.'s other than the last) are
  256.  * replaced by three characters: '%xx' where xx is the hexadecimal
  257.  * representation of the character, using lowercase 'a' through 'f'.
  258.  */
  259. int hfs_mac2alpha(char *out, const struct hfs_name *in) {
  260. unsigned char c;
  261. const unsigned char *p = in->Name;
  262. int len = in->Len;
  263. int count = 0;
  264. const unsigned char *lp; /* last period */
  265. /* strrchr() would be good here, but 'in' is not null-terminated */
  266. for (lp=p+len-1; (lp>=p)&&(*lp!='.'); --lp) {}
  267. ++lp;
  268. while (len--) {
  269. c = *p++;
  270. if ((p==lp) || ((c>='0')&&(c<='9')) || ((c>='A')&&(c<='Z')) ||
  271. ((c>='a')&&(c<='z')) || (c=='_')) {
  272. *out++ = c;
  273. count++;
  274. } else {
  275. *out++ = '%';
  276. *out++ = hex[(c>>4) & 0xf];
  277. *out++ = hex[c & 0xf];
  278. count += 3;
  279. }
  280. }
  281. return count;
  282. }
  283. /*
  284.  * hfs_mac2triv()
  285.  *
  286.  * Given a 'Pascal String' (a string preceded by a length byte) in
  287.  * the Macintosh character set produce the corresponding filename using
  288.  * the 'trivial' name-mangling scheme, returning the length of the
  289.  * mangled filename.  Note that the output string is not NULL
  290.  * terminated.
  291.  *
  292.  * The name-mangling works as follows:
  293.  * The character '/', which is illegal in Linux filenames is replaced
  294.  * by ':' which never appears in HFS filenames.  All other characters
  295.  * are passed unchanged from input to output.
  296.  */
  297. int hfs_mac2triv(char *out, const struct hfs_name *in) {
  298. unsigned char c;
  299. const unsigned char *p = in->Name;
  300. int len = in->Len;
  301. int count = 0;
  302. while (len--) {
  303. c = *p++;
  304. if (c=='/') {
  305. *out++ = ':';
  306. } else {
  307. *out++ = c;
  308. }
  309. count++;
  310. }
  311. return count;
  312. }
  313. /*
  314.  * hfs_mac2latin()
  315.  *
  316.  * Given a 'Pascal String' (a string preceded by a length byte) in
  317.  * the Macintosh character set produce the corresponding filename using
  318.  * the 'Latin-1' name-mangling scheme, returning the length of the
  319.  * mangled filename.  Note that the output string is not NULL
  320.  * terminated.
  321.  *
  322.  * The Macintosh character set and Latin-1 are both extensions of the
  323.  * ASCII character set.  Some, but certainly not all, of the characters
  324.  * in the Macintosh character set are also in Latin-1 but not with the
  325.  * same encoding.  This name-mangling scheme replaces the characters in
  326.  * the Macintosh character set that have Latin-1 equivalents by those
  327.  * equivalents; the characters 32-126, excluding '/' and '%', are
  328.  * passed unchanged from input to output.  The remaining characters
  329.  * are replaced by three characters: '%xx' where xx is the hexadecimal
  330.  * representation of the character, using lowercase 'a' through 'f'.
  331.  *
  332.  * The array mac2latin_map[] indicates the correspondence between the
  333.  * two character sets. The byte in element x-128 gives the Latin-1
  334.  * encoding of the character with encoding x in the Macintosh
  335.  * character set.  A value of zero indicates Latin-1 has no
  336.  * corresponding character.
  337.  */
  338. int hfs_mac2latin(char *out, const struct hfs_name *in) {
  339. unsigned char c;
  340. const unsigned char *p = in->Name;
  341. int len = in->Len;
  342. int count = 0;
  343. while (len--) {
  344. c = *p++;
  345. if ((c & 0x80) && mac2latin_map[c & 0x7f]) {
  346. *out++ = mac2latin_map[c & 0x7f];
  347. count++;
  348. } else if ((c>=32) && (c<=126) && (c!='/') && (c!='%')) {
  349. *out++ =  c;
  350. count++;
  351. } else {
  352. *out++ = '%';
  353. *out++ = hex[(c>>4) & 0xf];
  354. *out++ = hex[c & 0xf];
  355. count += 3;
  356. }
  357. }
  358. return count;
  359. }
  360. /*
  361.  * hfs_colon2mac()
  362.  *
  363.  * Given an ASCII string (not null-terminated) and its length,
  364.  * generate the corresponding filename in the Macintosh character set
  365.  * using the 'CAP' name-mangling scheme, returning the length of the
  366.  * mangled filename.  Note that the output string is not NULL
  367.  * terminated.
  368.  *
  369.  * This routine is a inverse to hfs_mac2cap() and hfs_mac2nat().
  370.  * A ':' not followed by a 2-digit hexadecimal number (or followed
  371.  * by the codes for NULL or ':') is replaced by a '|'.
  372.  */
  373. void hfs_colon2mac(struct hfs_name *out, const char *in, int len) {
  374. int hi, lo;
  375. unsigned char code, c, *count;
  376. unsigned char *p = out->Name;
  377. out->Len = 0;
  378. count = &out->Len;
  379. while (len-- && (*count < HFS_NAMELEN)) {
  380. c = *in++;
  381. (*count)++;
  382. if (c!=':') {
  383. *p++ = c;
  384. } else if ((len<2) ||
  385.    ((hi=dehex(in[0])) & 0xf0) ||
  386.    ((lo=dehex(in[1])) & 0xf0) ||
  387.    !(code = (hi << 4) | lo) ||
  388.    (code == ':')) {
  389. *p++ = '|';
  390. } else {
  391. *p++ = code;
  392. len -= 2;
  393. in += 2;
  394. }
  395. }
  396. }
  397. /*
  398.  * hfs_prcnt2mac()
  399.  *
  400.  * Given an ASCII string (not null-terminated) and its length,
  401.  * generate the corresponding filename in the Macintosh character set
  402.  * using Apple's three recommended name-mangling schemes, returning
  403.  * the length of the mangled filename. Note that the output string is
  404.  * not NULL terminated.
  405.  *
  406.  * This routine is a inverse to hfs_mac2alpha(), hfs_mac2seven() and
  407.  * hfs_mac2eight().
  408.  * A '%' not followed by a 2-digit hexadecimal number (or followed
  409.  * by the code for NULL or ':') is unchanged.
  410.  * A ':' is replaced by a '|'.
  411.  */
  412. void hfs_prcnt2mac(struct hfs_name *out, const char *in, int len) {
  413. int hi, lo;
  414. unsigned char code, c, *count;
  415. unsigned char *p = out->Name;
  416. out->Len = 0;
  417. count = &out->Len;
  418. while (len-- && (*count < HFS_NAMELEN)) {
  419. c = *in++;
  420. (*count)++;
  421. if (c==':') {
  422. *p++ = '|';
  423. } else if (c!='%') {
  424. *p++ = c;
  425. } else if ((len<2) ||
  426.    ((hi=dehex(in[0])) & 0xf0) ||
  427.    ((lo=dehex(in[1])) & 0xf0) ||
  428.    !(code = (hi << 4) | lo) ||
  429.    (code == ':')) {
  430. *p++ = '%';
  431. } else {
  432. *p++ = code;
  433. len -= 2;
  434. in += 2;
  435. }
  436. }
  437. }
  438. /*
  439.  * hfs_triv2mac()
  440.  *
  441.  * Given an ASCII string (not null-terminated) and its length,
  442.  * generate the corresponding filename in the Macintosh character set
  443.  * using the 'trivial' name-mangling scheme, returning the length of
  444.  * the mangled filename.  Note that the output string is not NULL
  445.  * terminated.
  446.  *
  447.  * This routine is a inverse to hfs_mac2triv().
  448.  * A ':' is replaced by a '/'.
  449.  */
  450. void hfs_triv2mac(struct hfs_name *out, const char *in, int len) {
  451. unsigned char c, *count;
  452. unsigned char *p = out->Name;
  453. out->Len = 0;
  454. count = &out->Len;
  455. while (len-- && (*count < HFS_NAMELEN)) {
  456. c = *in++;
  457. (*count)++;
  458. if (c==':') {
  459. *p++ = '/';
  460. } else {
  461. *p++ = c;
  462. }
  463. }
  464. }
  465. /*
  466.  * hfs_latin2mac()
  467.  *
  468.  * Given an Latin-1 string (not null-terminated) and its length,
  469.  * generate the corresponding filename in the Macintosh character set
  470.  * using the 'Latin-1' name-mangling scheme, returning the length of
  471.  * the mangled filename.  Note that the output string is not NULL
  472.  * terminated.
  473.  *
  474.  * This routine is a inverse to hfs_latin2cap().
  475.  * A '%' not followed by a 2-digit hexadecimal number (or followed
  476.  * by the code for NULL or ':') is unchanged.
  477.  * A ':' is replaced by a '|'.
  478.  *
  479.  * Note that the character map is built the first time it is needed.
  480.  */
  481. void hfs_latin2mac(struct hfs_name *out, const char *in, int len)
  482. {
  483. int hi, lo;
  484. unsigned char code, c, *count;
  485. unsigned char *p = out->Name;
  486. static int map_initialized;
  487. if (!map_initialized) {
  488. int i;
  489. /* build the inverse mapping at run time */
  490. for (i = 0; i < 128; i++) {
  491. if ((c = mac2latin_map[i])) {
  492. latin2mac_map[(int)c - 128] = i + 128;
  493. }
  494. }
  495. map_initialized = 1;
  496. }
  497. out->Len = 0;
  498. count = &out->Len;
  499. while (len-- && (*count < HFS_NAMELEN)) {
  500. c = *in++;
  501. (*count)++;
  502. if (c==':') {
  503. *p++ = '|';
  504. } else if (c!='%') {
  505. if (c<128 || !(*p = latin2mac_map[c-128])) {
  506. *p = c;
  507. }
  508. p++;
  509. } else if ((len<2) ||
  510.    ((hi=dehex(in[0])) & 0xf0) ||
  511.    ((lo=dehex(in[1])) & 0xf0) ||
  512.    !(code = (hi << 4) | lo) ||
  513.    (code == ':')) {
  514. *p++ = '%';
  515. } else {
  516. *p++ = code;
  517. len -= 2;
  518. in += 2;
  519. }
  520. }
  521. }