1*86d7f5d3SJohn Marino /*
2*86d7f5d3SJohn Marino * Various routines from the OSTA 2.01 specs. Copyrights are included with
3*86d7f5d3SJohn Marino * each code segment. Slight whitespace modifications have been made for
4*86d7f5d3SJohn Marino * formatting purposes. Typos/bugs have been fixed.
5*86d7f5d3SJohn Marino *
6*86d7f5d3SJohn Marino * $FreeBSD: src/sys/fs/udf/osta.c,v 1.3 2003/11/05 06:55:23 scottl Exp $
7*86d7f5d3SJohn Marino * $DragonFly: src/sys/vfs/udf/osta.c,v 1.3 2006/12/23 00:41:30 swildner Exp $
8*86d7f5d3SJohn Marino */
9*86d7f5d3SJohn Marino
10*86d7f5d3SJohn Marino #include <vfs/udf/osta.h>
11*86d7f5d3SJohn Marino
12*86d7f5d3SJohn Marino /*****************************************************************************/
13*86d7f5d3SJohn Marino /***********************************************************************
14*86d7f5d3SJohn Marino * OSTA compliant Unicode compression, uncompression routines.
15*86d7f5d3SJohn Marino * Copyright 1995 Micro Design International, Inc.
16*86d7f5d3SJohn Marino * Written by Jason M. Rinn.
17*86d7f5d3SJohn Marino * Micro Design International gives permission for the free use of the
18*86d7f5d3SJohn Marino * following source code.
19*86d7f5d3SJohn Marino */
20*86d7f5d3SJohn Marino
21*86d7f5d3SJohn Marino /***********************************************************************
22*86d7f5d3SJohn Marino * Takes an OSTA CS0 compressed unicode name, and converts
23*86d7f5d3SJohn Marino * it to Unicode.
24*86d7f5d3SJohn Marino * The Unicode output will be in the byte order
25*86d7f5d3SJohn Marino * that the local compiler uses for 16-bit values.
26*86d7f5d3SJohn Marino * NOTE: This routine only performs error checking on the compID.
27*86d7f5d3SJohn Marino * It is up to the user to ensure that the unicode buffer is large
28*86d7f5d3SJohn Marino * enough, and that the compressed unicode name is correct.
29*86d7f5d3SJohn Marino *
30*86d7f5d3SJohn Marino * RETURN VALUE
31*86d7f5d3SJohn Marino *
32*86d7f5d3SJohn Marino * The number of unicode characters which were uncompressed.
33*86d7f5d3SJohn Marino * A -1 is returned if the compression ID is invalid.
34*86d7f5d3SJohn Marino */
35*86d7f5d3SJohn Marino int
udf_UncompressUnicode(int numberOfBytes,byte * UDFCompressed,unicode_t * unicode)36*86d7f5d3SJohn Marino udf_UncompressUnicode(
37*86d7f5d3SJohn Marino int numberOfBytes, /* (Input) number of bytes read from media. */
38*86d7f5d3SJohn Marino byte *UDFCompressed, /* (Input) bytes read from media. */
39*86d7f5d3SJohn Marino unicode_t *unicode) /* (Output) uncompressed unicode characters. */
40*86d7f5d3SJohn Marino {
41*86d7f5d3SJohn Marino unsigned int compID;
42*86d7f5d3SJohn Marino int returnValue, unicodeIndex, byteIndex;
43*86d7f5d3SJohn Marino
44*86d7f5d3SJohn Marino /* Use UDFCompressed to store current byte being read. */
45*86d7f5d3SJohn Marino compID = UDFCompressed[0];
46*86d7f5d3SJohn Marino
47*86d7f5d3SJohn Marino /* First check for valid compID. */
48*86d7f5d3SJohn Marino if (compID != 8 && compID != 16) {
49*86d7f5d3SJohn Marino returnValue = -1;
50*86d7f5d3SJohn Marino } else {
51*86d7f5d3SJohn Marino unicodeIndex = 0;
52*86d7f5d3SJohn Marino byteIndex = 1;
53*86d7f5d3SJohn Marino
54*86d7f5d3SJohn Marino /* Loop through all the bytes. */
55*86d7f5d3SJohn Marino while (byteIndex < numberOfBytes) {
56*86d7f5d3SJohn Marino if (compID == 16) {
57*86d7f5d3SJohn Marino /* Move the first byte to the high bits of the
58*86d7f5d3SJohn Marino * unicode char.
59*86d7f5d3SJohn Marino */
60*86d7f5d3SJohn Marino unicode[unicodeIndex] =
61*86d7f5d3SJohn Marino UDFCompressed[byteIndex++] << 8;
62*86d7f5d3SJohn Marino } else {
63*86d7f5d3SJohn Marino unicode[unicodeIndex] = 0;
64*86d7f5d3SJohn Marino }
65*86d7f5d3SJohn Marino if (byteIndex < numberOfBytes) {
66*86d7f5d3SJohn Marino /*Then the next byte to the low bits. */
67*86d7f5d3SJohn Marino unicode[unicodeIndex] |=
68*86d7f5d3SJohn Marino UDFCompressed[byteIndex++];
69*86d7f5d3SJohn Marino }
70*86d7f5d3SJohn Marino unicodeIndex++;
71*86d7f5d3SJohn Marino }
72*86d7f5d3SJohn Marino returnValue = unicodeIndex;
73*86d7f5d3SJohn Marino }
74*86d7f5d3SJohn Marino return(returnValue);
75*86d7f5d3SJohn Marino }
76*86d7f5d3SJohn Marino
77*86d7f5d3SJohn Marino /*
78*86d7f5d3SJohn Marino * Almost same as udf_UncompressUnicode(). The difference is that
79*86d7f5d3SJohn Marino * it keeps byte order of unicode string.
80*86d7f5d3SJohn Marino */
81*86d7f5d3SJohn Marino int
udf_UncompressUnicodeByte(int numberOfBytes,byte * UDFCompressed,byte * unicode)82*86d7f5d3SJohn Marino udf_UncompressUnicodeByte(
83*86d7f5d3SJohn Marino int numberOfBytes, /* (Input) number of bytes read from media. */
84*86d7f5d3SJohn Marino byte *UDFCompressed, /* (Input) bytes read from media. */
85*86d7f5d3SJohn Marino byte *unicode) /* (Output) uncompressed unicode characters. */
86*86d7f5d3SJohn Marino {
87*86d7f5d3SJohn Marino unsigned int compID;
88*86d7f5d3SJohn Marino int returnValue, unicodeIndex, byteIndex;
89*86d7f5d3SJohn Marino
90*86d7f5d3SJohn Marino /* Use UDFCompressed to store current byte being read. */
91*86d7f5d3SJohn Marino compID = UDFCompressed[0];
92*86d7f5d3SJohn Marino
93*86d7f5d3SJohn Marino /* First check for valid compID. */
94*86d7f5d3SJohn Marino if (compID != 8 && compID != 16) {
95*86d7f5d3SJohn Marino returnValue = -1;
96*86d7f5d3SJohn Marino } else {
97*86d7f5d3SJohn Marino unicodeIndex = 0;
98*86d7f5d3SJohn Marino byteIndex = 1;
99*86d7f5d3SJohn Marino
100*86d7f5d3SJohn Marino /* Loop through all the bytes. */
101*86d7f5d3SJohn Marino while (byteIndex < numberOfBytes) {
102*86d7f5d3SJohn Marino if (compID == 16) {
103*86d7f5d3SJohn Marino /* Move the first byte to the high bits of the
104*86d7f5d3SJohn Marino * unicode char.
105*86d7f5d3SJohn Marino */
106*86d7f5d3SJohn Marino unicode[unicodeIndex++] =
107*86d7f5d3SJohn Marino UDFCompressed[byteIndex++];
108*86d7f5d3SJohn Marino } else {
109*86d7f5d3SJohn Marino unicode[unicodeIndex++] = 0;
110*86d7f5d3SJohn Marino }
111*86d7f5d3SJohn Marino if (byteIndex < numberOfBytes) {
112*86d7f5d3SJohn Marino /*Then the next byte to the low bits. */
113*86d7f5d3SJohn Marino unicode[unicodeIndex++] =
114*86d7f5d3SJohn Marino UDFCompressed[byteIndex++];
115*86d7f5d3SJohn Marino }
116*86d7f5d3SJohn Marino }
117*86d7f5d3SJohn Marino returnValue = unicodeIndex;
118*86d7f5d3SJohn Marino }
119*86d7f5d3SJohn Marino return(returnValue);
120*86d7f5d3SJohn Marino }
121*86d7f5d3SJohn Marino
122*86d7f5d3SJohn Marino /***********************************************************************
123*86d7f5d3SJohn Marino * DESCRIPTION:
124*86d7f5d3SJohn Marino * Takes a string of unicode wide characters and returns an OSTA CS0
125*86d7f5d3SJohn Marino * compressed unicode string. The unicode MUST be in the byte order of
126*86d7f5d3SJohn Marino * the compiler in order to obtain correct results. Returns an error
127*86d7f5d3SJohn Marino * if the compression ID is invalid.
128*86d7f5d3SJohn Marino *
129*86d7f5d3SJohn Marino * NOTE: This routine assumes the implementation already knows, by
130*86d7f5d3SJohn Marino * the local environment, how many bits are appropriate and
131*86d7f5d3SJohn Marino * therefore does no checking to test if the input characters fit
132*86d7f5d3SJohn Marino * into that number of bits or not.
133*86d7f5d3SJohn Marino *
134*86d7f5d3SJohn Marino * RETURN VALUE
135*86d7f5d3SJohn Marino *
136*86d7f5d3SJohn Marino * The total number of bytes in the compressed OSTA CS0 string,
137*86d7f5d3SJohn Marino * including the compression ID.
138*86d7f5d3SJohn Marino * A -1 is returned if the compression ID is invalid.
139*86d7f5d3SJohn Marino */
140*86d7f5d3SJohn Marino int
udf_CompressUnicode(int numberOfChars,int compID,unicode_t * unicode,byte * UDFCompressed)141*86d7f5d3SJohn Marino udf_CompressUnicode(
142*86d7f5d3SJohn Marino int numberOfChars, /* (Input) number of unicode characters. */
143*86d7f5d3SJohn Marino int compID, /* (Input) compression ID to be used. */
144*86d7f5d3SJohn Marino unicode_t *unicode, /* (Input) unicode characters to compress. */
145*86d7f5d3SJohn Marino byte *UDFCompressed) /* (Output) compressed string, as bytes. */
146*86d7f5d3SJohn Marino {
147*86d7f5d3SJohn Marino int byteIndex, unicodeIndex;
148*86d7f5d3SJohn Marino
149*86d7f5d3SJohn Marino if (compID != 8 && compID != 16) {
150*86d7f5d3SJohn Marino byteIndex = -1; /* Unsupported compression ID ! */
151*86d7f5d3SJohn Marino } else {
152*86d7f5d3SJohn Marino /* Place compression code in first byte. */
153*86d7f5d3SJohn Marino UDFCompressed[0] = compID;
154*86d7f5d3SJohn Marino
155*86d7f5d3SJohn Marino byteIndex = 1;
156*86d7f5d3SJohn Marino unicodeIndex = 0;
157*86d7f5d3SJohn Marino while (unicodeIndex < numberOfChars) {
158*86d7f5d3SJohn Marino if (compID == 16) {
159*86d7f5d3SJohn Marino /* First, place the high bits of the char
160*86d7f5d3SJohn Marino * into the byte stream.
161*86d7f5d3SJohn Marino */
162*86d7f5d3SJohn Marino UDFCompressed[byteIndex++] =
163*86d7f5d3SJohn Marino (unicode[unicodeIndex] & 0xFF00) >> 8;
164*86d7f5d3SJohn Marino }
165*86d7f5d3SJohn Marino /*Then place the low bits into the stream. */
166*86d7f5d3SJohn Marino UDFCompressed[byteIndex++] =
167*86d7f5d3SJohn Marino unicode[unicodeIndex] & 0x00FF;
168*86d7f5d3SJohn Marino unicodeIndex++;
169*86d7f5d3SJohn Marino }
170*86d7f5d3SJohn Marino }
171*86d7f5d3SJohn Marino return(byteIndex);
172*86d7f5d3SJohn Marino }
173*86d7f5d3SJohn Marino
174*86d7f5d3SJohn Marino /*****************************************************************************/
175*86d7f5d3SJohn Marino /*
176*86d7f5d3SJohn Marino * CRC 010041
177*86d7f5d3SJohn Marino */
178*86d7f5d3SJohn Marino static unsigned short crc_table[256] = {
179*86d7f5d3SJohn Marino 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
180*86d7f5d3SJohn Marino 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
181*86d7f5d3SJohn Marino 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
182*86d7f5d3SJohn Marino 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
183*86d7f5d3SJohn Marino 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
184*86d7f5d3SJohn Marino 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
185*86d7f5d3SJohn Marino 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
186*86d7f5d3SJohn Marino 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
187*86d7f5d3SJohn Marino 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
188*86d7f5d3SJohn Marino 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
189*86d7f5d3SJohn Marino 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
190*86d7f5d3SJohn Marino 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
191*86d7f5d3SJohn Marino 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
192*86d7f5d3SJohn Marino 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
193*86d7f5d3SJohn Marino 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
194*86d7f5d3SJohn Marino 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
195*86d7f5d3SJohn Marino 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
196*86d7f5d3SJohn Marino 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
197*86d7f5d3SJohn Marino 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
198*86d7f5d3SJohn Marino 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
199*86d7f5d3SJohn Marino 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
200*86d7f5d3SJohn Marino 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
201*86d7f5d3SJohn Marino 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
202*86d7f5d3SJohn Marino 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
203*86d7f5d3SJohn Marino 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
204*86d7f5d3SJohn Marino 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
205*86d7f5d3SJohn Marino 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
206*86d7f5d3SJohn Marino 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
207*86d7f5d3SJohn Marino 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
208*86d7f5d3SJohn Marino 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
209*86d7f5d3SJohn Marino 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
210*86d7f5d3SJohn Marino 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
211*86d7f5d3SJohn Marino };
212*86d7f5d3SJohn Marino
213*86d7f5d3SJohn Marino unsigned short
udf_cksum(unsigned char * s,int n)214*86d7f5d3SJohn Marino udf_cksum(unsigned char *s, int n)
215*86d7f5d3SJohn Marino {
216*86d7f5d3SJohn Marino unsigned short crc=0;
217*86d7f5d3SJohn Marino
218*86d7f5d3SJohn Marino while (n-- > 0)
219*86d7f5d3SJohn Marino crc = crc_table[(crc>>8 ^ *s++) & 0xff] ^ (crc<<8);
220*86d7f5d3SJohn Marino return crc;
221*86d7f5d3SJohn Marino }
222*86d7f5d3SJohn Marino
223*86d7f5d3SJohn Marino /* UNICODE Checksum */
224*86d7f5d3SJohn Marino unsigned short
udf_unicode_cksum(unsigned short * s,int n)225*86d7f5d3SJohn Marino udf_unicode_cksum(unsigned short *s, int n)
226*86d7f5d3SJohn Marino {
227*86d7f5d3SJohn Marino unsigned short crc=0;
228*86d7f5d3SJohn Marino
229*86d7f5d3SJohn Marino while (n-- > 0) {
230*86d7f5d3SJohn Marino /* Take high order byte first--corresponds to a big endian
231*86d7f5d3SJohn Marino * byte stream.
232*86d7f5d3SJohn Marino */
233*86d7f5d3SJohn Marino crc = crc_table[(crc>>8 ^ (*s>>8)) & 0xff] ^ (crc<<8);
234*86d7f5d3SJohn Marino crc = crc_table[(crc>>8 ^ (*s++ & 0xff)) & 0xff] ^ (crc<<8);
235*86d7f5d3SJohn Marino }
236*86d7f5d3SJohn Marino return crc;
237*86d7f5d3SJohn Marino }
238*86d7f5d3SJohn Marino
239*86d7f5d3SJohn Marino #ifdef MAIN
240*86d7f5d3SJohn Marino unsigned char bytes[] = { 0x70, 0x6A, 0x77 };
241*86d7f5d3SJohn Marino
242*86d7f5d3SJohn Marino int
main(void)243*86d7f5d3SJohn Marino main(void)
244*86d7f5d3SJohn Marino {
245*86d7f5d3SJohn Marino unsigned short x;
246*86d7f5d3SJohn Marino
247*86d7f5d3SJohn Marino x = cksum(bytes, sizeof bytes);
248*86d7f5d3SJohn Marino kprintf("checksum: calculated=%4.4x, correct=%4.4x\en", x, 0x3299);
249*86d7f5d3SJohn Marino exit(0);
250*86d7f5d3SJohn Marino }
251*86d7f5d3SJohn Marino #endif
252*86d7f5d3SJohn Marino
253*86d7f5d3SJohn Marino /*****************************************************************************/
254*86d7f5d3SJohn Marino #ifdef NEEDS_ISPRINT
255*86d7f5d3SJohn Marino /***********************************************************************
256*86d7f5d3SJohn Marino * OSTA UDF compliant file name translation routine for OS/2,
257*86d7f5d3SJohn Marino * Windows 95, Windows NT, Macintosh and UNIX.
258*86d7f5d3SJohn Marino * Copyright 1995 Micro Design International, Inc.
259*86d7f5d3SJohn Marino * Written by Jason M. Rinn.
260*86d7f5d3SJohn Marino * Micro Design International gives permission for the free use of the
261*86d7f5d3SJohn Marino * following source code.
262*86d7f5d3SJohn Marino */
263*86d7f5d3SJohn Marino
264*86d7f5d3SJohn Marino /***********************************************************************
265*86d7f5d3SJohn Marino * To use these routines with different operating systems.
266*86d7f5d3SJohn Marino *
267*86d7f5d3SJohn Marino * OS/2
268*86d7f5d3SJohn Marino * Define OS2
269*86d7f5d3SJohn Marino * Define MAXLEN = 254
270*86d7f5d3SJohn Marino *
271*86d7f5d3SJohn Marino * Windows 95
272*86d7f5d3SJohn Marino * Define WIN_95
273*86d7f5d3SJohn Marino * Define MAXLEN = 255
274*86d7f5d3SJohn Marino *
275*86d7f5d3SJohn Marino * Windows NT
276*86d7f5d3SJohn Marino * Define WIN_NT
277*86d7f5d3SJohn Marino * Define MAXLEN = 255
278*86d7f5d3SJohn Marino *
279*86d7f5d3SJohn Marino * Macintosh:
280*86d7f5d3SJohn Marino * Define MAC.
281*86d7f5d3SJohn Marino * Define MAXLEN = 31.
282*86d7f5d3SJohn Marino *
283*86d7f5d3SJohn Marino * UNIX
284*86d7f5d3SJohn Marino * Define UNIX.
285*86d7f5d3SJohn Marino * Define MAXLEN as specified by unix version.
286*86d7f5d3SJohn Marino */
287*86d7f5d3SJohn Marino
288*86d7f5d3SJohn Marino #define ILLEGAL_CHAR_MARK 0x005F
289*86d7f5d3SJohn Marino #define CRC_MARK 0x0023
290*86d7f5d3SJohn Marino #define EXT_SIZE 5
291*86d7f5d3SJohn Marino #define TRUE 1
292*86d7f5d3SJohn Marino #define FALSE 0
293*86d7f5d3SJohn Marino #define PERIOD 0x002E
294*86d7f5d3SJohn Marino #define SPACE 0x0020
295*86d7f5d3SJohn Marino
296*86d7f5d3SJohn Marino /*** PROTOTYPES ***/
297*86d7f5d3SJohn Marino int IsIllegal(unicode_t ch);
298*86d7f5d3SJohn Marino
299*86d7f5d3SJohn Marino /* Define a function or macro which determines if a Unicode character is
300*86d7f5d3SJohn Marino * printable under your implementation.
301*86d7f5d3SJohn Marino */
302*86d7f5d3SJohn Marino int UnicodeIsPrint(unicode_t);
303*86d7f5d3SJohn Marino
304*86d7f5d3SJohn Marino /***********************************************************************
305*86d7f5d3SJohn Marino * Translates a long file name to one using a MAXLEN and an illegal
306*86d7f5d3SJohn Marino * char set in accord with the OSTA requirements. Assumes the name has
307*86d7f5d3SJohn Marino * already been translated to Unicode.
308*86d7f5d3SJohn Marino *
309*86d7f5d3SJohn Marino * RETURN VALUE
310*86d7f5d3SJohn Marino *
311*86d7f5d3SJohn Marino * Number of unicode characters in translated name.
312*86d7f5d3SJohn Marino */
UDFTransName(unicode_t * newName,unicode_t * udfName,int udfLen)313*86d7f5d3SJohn Marino int UDFTransName(
314*86d7f5d3SJohn Marino unicode_t *newName, /* (Output)Translated name. Must be of length
315*86d7f5d3SJohn Marino * MAXLEN */
316*86d7f5d3SJohn Marino unicode_t *udfName, /* (Input) Name from UDF volume.*/
317*86d7f5d3SJohn Marino int udfLen) /* (Input) Length of UDF Name. */
318*86d7f5d3SJohn Marino {
319*86d7f5d3SJohn Marino int index, newIndex = 0, needsCRC = FALSE;
320*86d7f5d3SJohn Marino int extIndex = 0, newExtIndex = 0, hasExt = FALSE;
321*86d7f5d3SJohn Marino #if defined OS2 || defined WIN_95 || defined WIN_NT
322*86d7f5d3SJohn Marino int trailIndex = 0;
323*86d7f5d3SJohn Marino #endif
324*86d7f5d3SJohn Marino unsigned short valueCRC;
325*86d7f5d3SJohn Marino unicode_t current;
326*86d7f5d3SJohn Marino const char hexChar[] = "0123456789ABCDEF";
327*86d7f5d3SJohn Marino
328*86d7f5d3SJohn Marino for (index = 0; index < udfLen; index++) {
329*86d7f5d3SJohn Marino current = udfName[index];
330*86d7f5d3SJohn Marino
331*86d7f5d3SJohn Marino if (IsIllegal(current) || !UnicodeIsPrint(current)) {
332*86d7f5d3SJohn Marino needsCRC = TRUE;
333*86d7f5d3SJohn Marino /* Replace Illegal and non-displayable chars with
334*86d7f5d3SJohn Marino * underscore.
335*86d7f5d3SJohn Marino */
336*86d7f5d3SJohn Marino current = ILLEGAL_CHAR_MARK;
337*86d7f5d3SJohn Marino /* Skip any other illegal or non-displayable
338*86d7f5d3SJohn Marino * characters.
339*86d7f5d3SJohn Marino */
340*86d7f5d3SJohn Marino while(index+1 < udfLen && (IsIllegal(udfName[index+1])
341*86d7f5d3SJohn Marino || !UnicodeIsPrint(udfName[index+1]))) {
342*86d7f5d3SJohn Marino index++;
343*86d7f5d3SJohn Marino }
344*86d7f5d3SJohn Marino }
345*86d7f5d3SJohn Marino
346*86d7f5d3SJohn Marino /* Record position of extension, if one is found. */
347*86d7f5d3SJohn Marino if (current == PERIOD && (udfLen - index -1) <= EXT_SIZE) {
348*86d7f5d3SJohn Marino if (udfLen == index + 1) {
349*86d7f5d3SJohn Marino /* A trailing period is NOT an extension. */
350*86d7f5d3SJohn Marino hasExt = FALSE;
351*86d7f5d3SJohn Marino } else {
352*86d7f5d3SJohn Marino hasExt = TRUE;
353*86d7f5d3SJohn Marino extIndex = index;
354*86d7f5d3SJohn Marino newExtIndex = newIndex;
355*86d7f5d3SJohn Marino }
356*86d7f5d3SJohn Marino }
357*86d7f5d3SJohn Marino
358*86d7f5d3SJohn Marino #if defined OS2 || defined WIN_95 || defined WIN_NT
359*86d7f5d3SJohn Marino /* Record position of last char which is NOT period or space. */
360*86d7f5d3SJohn Marino else if (current != PERIOD && current != SPACE) {
361*86d7f5d3SJohn Marino trailIndex = newIndex;
362*86d7f5d3SJohn Marino }
363*86d7f5d3SJohn Marino #endif
364*86d7f5d3SJohn Marino
365*86d7f5d3SJohn Marino if (newIndex < MAXLEN) {
366*86d7f5d3SJohn Marino newName[newIndex++] = current;
367*86d7f5d3SJohn Marino } else {
368*86d7f5d3SJohn Marino needsCRC = TRUE;
369*86d7f5d3SJohn Marino }
370*86d7f5d3SJohn Marino }
371*86d7f5d3SJohn Marino
372*86d7f5d3SJohn Marino #if defined OS2 || defined WIN_95 || defined WIN_NT
373*86d7f5d3SJohn Marino /* For OS2, 95 & NT, truncate any trailing periods and\or spaces. */
374*86d7f5d3SJohn Marino if (trailIndex != newIndex - 1) {
375*86d7f5d3SJohn Marino newIndex = trailIndex + 1;
376*86d7f5d3SJohn Marino needsCRC = TRUE;
377*86d7f5d3SJohn Marino hasExt = FALSE; /* Trailing period does not make an
378*86d7f5d3SJohn Marino * extension. */
379*86d7f5d3SJohn Marino }
380*86d7f5d3SJohn Marino #endif
381*86d7f5d3SJohn Marino
382*86d7f5d3SJohn Marino if (needsCRC) {
383*86d7f5d3SJohn Marino unicode_t ext[EXT_SIZE];
384*86d7f5d3SJohn Marino int localExtIndex = 0;
385*86d7f5d3SJohn Marino if (hasExt) {
386*86d7f5d3SJohn Marino int maxFilenameLen;
387*86d7f5d3SJohn Marino /* Translate extension, and store it in ext. */
388*86d7f5d3SJohn Marino for(index = 0; index<EXT_SIZE &&
389*86d7f5d3SJohn Marino extIndex + index +1 < udfLen; index++ ) {
390*86d7f5d3SJohn Marino current = udfName[extIndex + index + 1];
391*86d7f5d3SJohn Marino if (IsIllegal(current) ||
392*86d7f5d3SJohn Marino !UnicodeIsPrint(current)) {
393*86d7f5d3SJohn Marino needsCRC = 1;
394*86d7f5d3SJohn Marino /* Replace Illegal and non-displayable
395*86d7f5d3SJohn Marino * chars with underscore.
396*86d7f5d3SJohn Marino */
397*86d7f5d3SJohn Marino current = ILLEGAL_CHAR_MARK;
398*86d7f5d3SJohn Marino /* Skip any other illegal or
399*86d7f5d3SJohn Marino * non-displayable characters.
400*86d7f5d3SJohn Marino */
401*86d7f5d3SJohn Marino while(index + 1 < EXT_SIZE
402*86d7f5d3SJohn Marino && (IsIllegal(udfName[extIndex +
403*86d7f5d3SJohn Marino index + 2]) ||
404*86d7f5d3SJohn Marino !isprint(udfName[extIndex +
405*86d7f5d3SJohn Marino index + 2]))) {
406*86d7f5d3SJohn Marino index++;
407*86d7f5d3SJohn Marino }
408*86d7f5d3SJohn Marino }
409*86d7f5d3SJohn Marino ext[localExtIndex++] = current;
410*86d7f5d3SJohn Marino }
411*86d7f5d3SJohn Marino
412*86d7f5d3SJohn Marino /* Truncate filename to leave room for extension and
413*86d7f5d3SJohn Marino * CRC.
414*86d7f5d3SJohn Marino */
415*86d7f5d3SJohn Marino maxFilenameLen = ((MAXLEN - 5) - localExtIndex - 1);
416*86d7f5d3SJohn Marino if (newIndex > maxFilenameLen) {
417*86d7f5d3SJohn Marino newIndex = maxFilenameLen;
418*86d7f5d3SJohn Marino } else {
419*86d7f5d3SJohn Marino newIndex = newExtIndex;
420*86d7f5d3SJohn Marino }
421*86d7f5d3SJohn Marino } else if (newIndex > MAXLEN - 5) {
422*86d7f5d3SJohn Marino /*If no extension, make sure to leave room for CRC. */
423*86d7f5d3SJohn Marino newIndex = MAXLEN - 5;
424*86d7f5d3SJohn Marino }
425*86d7f5d3SJohn Marino newName[newIndex++] = CRC_MARK; /* Add mark for CRC. */
426*86d7f5d3SJohn Marino
427*86d7f5d3SJohn Marino /*Calculate CRC from original filename from FileIdentifier. */
428*86d7f5d3SJohn Marino valueCRC = udf_unicode_cksum(udfName, udfLen);
429*86d7f5d3SJohn Marino /* Convert 16-bits of CRC to hex characters. */
430*86d7f5d3SJohn Marino newName[newIndex++] = hexChar[(valueCRC & 0xf000) >> 12];
431*86d7f5d3SJohn Marino newName[newIndex++] = hexChar[(valueCRC & 0x0f00) >> 8];
432*86d7f5d3SJohn Marino newName[newIndex++] = hexChar[(valueCRC & 0x00f0) >> 4];
433*86d7f5d3SJohn Marino newName[newIndex++] = hexChar[(valueCRC & 0x000f)];
434*86d7f5d3SJohn Marino
435*86d7f5d3SJohn Marino /* Place a translated extension at end, if found. */
436*86d7f5d3SJohn Marino if (hasExt) {
437*86d7f5d3SJohn Marino newName[newIndex++] = PERIOD;
438*86d7f5d3SJohn Marino for (index = 0;index < localExtIndex ;index++ ) {
439*86d7f5d3SJohn Marino newName[newIndex++] = ext[index];
440*86d7f5d3SJohn Marino }
441*86d7f5d3SJohn Marino }
442*86d7f5d3SJohn Marino }
443*86d7f5d3SJohn Marino return(newIndex);
444*86d7f5d3SJohn Marino }
445*86d7f5d3SJohn Marino
446*86d7f5d3SJohn Marino #if defined OS2 || defined WIN_95 || defined WIN_NT
447*86d7f5d3SJohn Marino /***********************************************************************
448*86d7f5d3SJohn Marino * Decides if a Unicode character matches one of a list
449*86d7f5d3SJohn Marino * of ASCII characters.
450*86d7f5d3SJohn Marino * Used by OS2 version of IsIllegal for readability, since all of the
451*86d7f5d3SJohn Marino * illegal characters above 0x0020 are in the ASCII subset of Unicode.
452*86d7f5d3SJohn Marino * Works very similarly to the standard C function strchr().
453*86d7f5d3SJohn Marino *
454*86d7f5d3SJohn Marino * RETURN VALUE
455*86d7f5d3SJohn Marino *
456*86d7f5d3SJohn Marino * Non-zero if the Unicode character is in the given ASCII string.
457*86d7f5d3SJohn Marino */
UnicodeInString(unsigned char * string,unicode_t ch)458*86d7f5d3SJohn Marino int UnicodeInString(
459*86d7f5d3SJohn Marino unsigned char *string, /* (Input) String to search through. */
460*86d7f5d3SJohn Marino unicode_t ch) /* (Input) Unicode char to search for. */
461*86d7f5d3SJohn Marino {
462*86d7f5d3SJohn Marino int found = FALSE;
463*86d7f5d3SJohn Marino while (*string != '\0' && found == FALSE) {
464*86d7f5d3SJohn Marino /* These types should compare, since both are unsigned
465*86d7f5d3SJohn Marino * numbers. */
466*86d7f5d3SJohn Marino if (*string == ch) {
467*86d7f5d3SJohn Marino found = TRUE;
468*86d7f5d3SJohn Marino }
469*86d7f5d3SJohn Marino string++;
470*86d7f5d3SJohn Marino }
471*86d7f5d3SJohn Marino return(found);
472*86d7f5d3SJohn Marino }
473*86d7f5d3SJohn Marino #endif /* OS2 */
474*86d7f5d3SJohn Marino
475*86d7f5d3SJohn Marino /***********************************************************************
476*86d7f5d3SJohn Marino * Decides whether the given character is illegal for a given OS.
477*86d7f5d3SJohn Marino *
478*86d7f5d3SJohn Marino * RETURN VALUE
479*86d7f5d3SJohn Marino *
480*86d7f5d3SJohn Marino * Non-zero if char is illegal.
481*86d7f5d3SJohn Marino */
IsIllegal(unicode_t ch)482*86d7f5d3SJohn Marino int IsIllegal(unicode_t ch)
483*86d7f5d3SJohn Marino {
484*86d7f5d3SJohn Marino #ifdef MAC
485*86d7f5d3SJohn Marino /* Only illegal character on the MAC is the colon. */
486*86d7f5d3SJohn Marino if (ch == 0x003A) {
487*86d7f5d3SJohn Marino return(1);
488*86d7f5d3SJohn Marino } else {
489*86d7f5d3SJohn Marino return(0);
490*86d7f5d3SJohn Marino }
491*86d7f5d3SJohn Marino
492*86d7f5d3SJohn Marino #elif defined UNIX
493*86d7f5d3SJohn Marino /* Illegal UNIX characters are NULL and slash. */
494*86d7f5d3SJohn Marino if (ch == 0x0000 || ch == 0x002F) {
495*86d7f5d3SJohn Marino return(1);
496*86d7f5d3SJohn Marino } else {
497*86d7f5d3SJohn Marino return(0);
498*86d7f5d3SJohn Marino }
499*86d7f5d3SJohn Marino
500*86d7f5d3SJohn Marino #elif defined OS2 || defined WIN_95 || defined WIN_NT
501*86d7f5d3SJohn Marino /* Illegal char's for OS/2 according to WARP toolkit. */
502*86d7f5d3SJohn Marino if (ch < 0x0020 || UnicodeInString("\\/:*?\"<>|", ch)) {
503*86d7f5d3SJohn Marino return(1);
504*86d7f5d3SJohn Marino } else {
505*86d7f5d3SJohn Marino return(0);
506*86d7f5d3SJohn Marino }
507*86d7f5d3SJohn Marino #endif
508*86d7f5d3SJohn Marino }
509*86d7f5d3SJohn Marino #endif
510