xref: /dflybsd-src/sys/vfs/udf/osta.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
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