151a7b740SScott Long /* 251a7b740SScott Long * Various routines from the OSTA 2.01 specs. Copyrights are included with 351a7b740SScott Long * each code segment. Slight whitespace modifications have been made for 451a7b740SScott Long * formatting purposes. Typos/bugs have been fixed. 551a7b740SScott Long * 651a7b740SScott Long * $FreeBSD$ 751a7b740SScott Long */ 851a7b740SScott Long 951a7b740SScott Long #include <fs/udf/osta.h> 1051a7b740SScott Long 1151a7b740SScott Long /*****************************************************************************/ 12d167cf6fSWarner Losh /*- 13d167cf6fSWarner Losh ********************************************************************** 1451a7b740SScott Long * OSTA compliant Unicode compression, uncompression routines. 1551a7b740SScott Long * Copyright 1995 Micro Design International, Inc. 1651a7b740SScott Long * Written by Jason M. Rinn. 1751a7b740SScott Long * Micro Design International gives permission for the free use of the 1851a7b740SScott Long * following source code. 1951a7b740SScott Long */ 2051a7b740SScott Long 2151a7b740SScott Long /*********************************************************************** 2251a7b740SScott Long * Takes an OSTA CS0 compressed unicode name, and converts 2351a7b740SScott Long * it to Unicode. 2451a7b740SScott Long * The Unicode output will be in the byte order 2551a7b740SScott Long * that the local compiler uses for 16-bit values. 2651a7b740SScott Long * NOTE: This routine only performs error checking on the compID. 2751a7b740SScott Long * It is up to the user to ensure that the unicode buffer is large 2851a7b740SScott Long * enough, and that the compressed unicode name is correct. 2951a7b740SScott Long * 3051a7b740SScott Long * RETURN VALUE 3151a7b740SScott Long * 3251a7b740SScott Long * The number of unicode characters which were uncompressed. 3351a7b740SScott Long * A -1 is returned if the compression ID is invalid. 3451a7b740SScott Long */ 3551a7b740SScott Long int 3651a7b740SScott Long udf_UncompressUnicode( 3751a7b740SScott Long int numberOfBytes, /* (Input) number of bytes read from media. */ 3851a7b740SScott Long byte *UDFCompressed, /* (Input) bytes read from media. */ 3951a7b740SScott Long unicode_t *unicode) /* (Output) uncompressed unicode characters. */ 4051a7b740SScott Long { 4151a7b740SScott Long unsigned int compID; 4251a7b740SScott Long int returnValue, unicodeIndex, byteIndex; 4351a7b740SScott Long 4451a7b740SScott Long /* Use UDFCompressed to store current byte being read. */ 4551a7b740SScott Long compID = UDFCompressed[0]; 4651a7b740SScott Long 4751a7b740SScott Long /* First check for valid compID. */ 4851a7b740SScott Long if (compID != 8 && compID != 16) { 4951a7b740SScott Long returnValue = -1; 5051a7b740SScott Long } else { 5151a7b740SScott Long unicodeIndex = 0; 5251a7b740SScott Long byteIndex = 1; 5351a7b740SScott Long 5451a7b740SScott Long /* Loop through all the bytes. */ 5551a7b740SScott Long while (byteIndex < numberOfBytes) { 5651a7b740SScott Long if (compID == 16) { 5751a7b740SScott Long /* Move the first byte to the high bits of the 5851a7b740SScott Long * unicode char. 5951a7b740SScott Long */ 6051a7b740SScott Long unicode[unicodeIndex] = 6151a7b740SScott Long UDFCompressed[byteIndex++] << 8; 6251a7b740SScott Long } else { 6351a7b740SScott Long unicode[unicodeIndex] = 0; 6451a7b740SScott Long } 6551a7b740SScott Long if (byteIndex < numberOfBytes) { 6651a7b740SScott Long /*Then the next byte to the low bits. */ 6751a7b740SScott Long unicode[unicodeIndex] |= 6851a7b740SScott Long UDFCompressed[byteIndex++]; 6951a7b740SScott Long } 7051a7b740SScott Long unicodeIndex++; 7151a7b740SScott Long } 7251a7b740SScott Long returnValue = unicodeIndex; 7351a7b740SScott Long } 7451a7b740SScott Long return(returnValue); 7551a7b740SScott Long } 7651a7b740SScott Long 77c5a1bf1bSScott Long /* 78c5a1bf1bSScott Long * Almost same as udf_UncompressUnicode(). The difference is that 79c5a1bf1bSScott Long * it keeps byte order of unicode string. 80c5a1bf1bSScott Long */ 81c5a1bf1bSScott Long int 82c5a1bf1bSScott Long udf_UncompressUnicodeByte( 83c5a1bf1bSScott Long int numberOfBytes, /* (Input) number of bytes read from media. */ 84c5a1bf1bSScott Long byte *UDFCompressed, /* (Input) bytes read from media. */ 85c5a1bf1bSScott Long byte *unicode) /* (Output) uncompressed unicode characters. */ 86c5a1bf1bSScott Long { 87c5a1bf1bSScott Long unsigned int compID; 88c5a1bf1bSScott Long int returnValue, unicodeIndex, byteIndex; 89c5a1bf1bSScott Long 90c5a1bf1bSScott Long /* Use UDFCompressed to store current byte being read. */ 91c5a1bf1bSScott Long compID = UDFCompressed[0]; 92c5a1bf1bSScott Long 93c5a1bf1bSScott Long /* First check for valid compID. */ 94c5a1bf1bSScott Long if (compID != 8 && compID != 16) { 95c5a1bf1bSScott Long returnValue = -1; 96c5a1bf1bSScott Long } else { 97c5a1bf1bSScott Long unicodeIndex = 0; 98c5a1bf1bSScott Long byteIndex = 1; 99c5a1bf1bSScott Long 100c5a1bf1bSScott Long /* Loop through all the bytes. */ 101c5a1bf1bSScott Long while (byteIndex < numberOfBytes) { 102c5a1bf1bSScott Long if (compID == 16) { 103c5a1bf1bSScott Long /* Move the first byte to the high bits of the 104c5a1bf1bSScott Long * unicode char. 105c5a1bf1bSScott Long */ 106c5a1bf1bSScott Long unicode[unicodeIndex++] = 107c5a1bf1bSScott Long UDFCompressed[byteIndex++]; 108c5a1bf1bSScott Long } else { 109c5a1bf1bSScott Long unicode[unicodeIndex++] = 0; 110c5a1bf1bSScott Long } 111c5a1bf1bSScott Long if (byteIndex < numberOfBytes) { 112c5a1bf1bSScott Long /*Then the next byte to the low bits. */ 113c5a1bf1bSScott Long unicode[unicodeIndex++] = 114c5a1bf1bSScott Long UDFCompressed[byteIndex++]; 115c5a1bf1bSScott Long } 116c5a1bf1bSScott Long } 117c5a1bf1bSScott Long returnValue = unicodeIndex; 118c5a1bf1bSScott Long } 119c5a1bf1bSScott Long return(returnValue); 120c5a1bf1bSScott Long } 121c5a1bf1bSScott Long 12251a7b740SScott Long /*********************************************************************** 12351a7b740SScott Long * DESCRIPTION: 12451a7b740SScott Long * Takes a string of unicode wide characters and returns an OSTA CS0 12551a7b740SScott Long * compressed unicode string. The unicode MUST be in the byte order of 12651a7b740SScott Long * the compiler in order to obtain correct results. Returns an error 12751a7b740SScott Long * if the compression ID is invalid. 12851a7b740SScott Long * 12951a7b740SScott Long * NOTE: This routine assumes the implementation already knows, by 13051a7b740SScott Long * the local environment, how many bits are appropriate and 13151a7b740SScott Long * therefore does no checking to test if the input characters fit 13251a7b740SScott Long * into that number of bits or not. 13351a7b740SScott Long * 13451a7b740SScott Long * RETURN VALUE 13551a7b740SScott Long * 13651a7b740SScott Long * The total number of bytes in the compressed OSTA CS0 string, 13751a7b740SScott Long * including the compression ID. 13851a7b740SScott Long * A -1 is returned if the compression ID is invalid. 13951a7b740SScott Long */ 14051a7b740SScott Long int 14151a7b740SScott Long udf_CompressUnicode( 14251a7b740SScott Long int numberOfChars, /* (Input) number of unicode characters. */ 14351a7b740SScott Long int compID, /* (Input) compression ID to be used. */ 14451a7b740SScott Long unicode_t *unicode, /* (Input) unicode characters to compress. */ 14551a7b740SScott Long byte *UDFCompressed) /* (Output) compressed string, as bytes. */ 14651a7b740SScott Long { 14751a7b740SScott Long int byteIndex, unicodeIndex; 14851a7b740SScott Long 14951a7b740SScott Long if (compID != 8 && compID != 16) { 15051a7b740SScott Long byteIndex = -1; /* Unsupported compression ID ! */ 15151a7b740SScott Long } else { 15251a7b740SScott Long /* Place compression code in first byte. */ 15351a7b740SScott Long UDFCompressed[0] = compID; 15451a7b740SScott Long 15551a7b740SScott Long byteIndex = 1; 15651a7b740SScott Long unicodeIndex = 0; 15751a7b740SScott Long while (unicodeIndex < numberOfChars) { 15851a7b740SScott Long if (compID == 16) { 15951a7b740SScott Long /* First, place the high bits of the char 16051a7b740SScott Long * into the byte stream. 16151a7b740SScott Long */ 16251a7b740SScott Long UDFCompressed[byteIndex++] = 16351a7b740SScott Long (unicode[unicodeIndex] & 0xFF00) >> 8; 16451a7b740SScott Long } 16551a7b740SScott Long /*Then place the low bits into the stream. */ 16651a7b740SScott Long UDFCompressed[byteIndex++] = 16751a7b740SScott Long unicode[unicodeIndex] & 0x00FF; 16851a7b740SScott Long unicodeIndex++; 16951a7b740SScott Long } 17051a7b740SScott Long } 17151a7b740SScott Long return(byteIndex); 17251a7b740SScott Long } 17351a7b740SScott Long 17451a7b740SScott Long /*****************************************************************************/ 17551a7b740SScott Long /* 17651a7b740SScott Long * CRC 010041 17751a7b740SScott Long */ 17851a7b740SScott Long static unsigned short crc_table[256] = { 17951a7b740SScott Long 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 18051a7b740SScott Long 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 18151a7b740SScott Long 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 18251a7b740SScott Long 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 18351a7b740SScott Long 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 18451a7b740SScott Long 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 18551a7b740SScott Long 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, 18651a7b740SScott Long 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 18751a7b740SScott Long 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 18851a7b740SScott Long 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 18951a7b740SScott Long 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 19051a7b740SScott Long 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 19151a7b740SScott Long 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 19251a7b740SScott Long 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 19351a7b740SScott Long 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 19451a7b740SScott Long 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, 19551a7b740SScott Long 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 19651a7b740SScott Long 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, 19751a7b740SScott Long 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 19851a7b740SScott Long 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 19951a7b740SScott Long 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 20051a7b740SScott Long 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 20151a7b740SScott Long 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, 20251a7b740SScott Long 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 20351a7b740SScott Long 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, 20451a7b740SScott Long 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, 20551a7b740SScott Long 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 20651a7b740SScott Long 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 20751a7b740SScott Long 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 20851a7b740SScott Long 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 20951a7b740SScott Long 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 21051a7b740SScott Long 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 21151a7b740SScott Long }; 21251a7b740SScott Long 21351a7b740SScott Long unsigned short 21451a7b740SScott Long udf_cksum(s, n) 21551a7b740SScott Long unsigned char *s; 21651a7b740SScott Long int n; 21751a7b740SScott Long { 21851a7b740SScott Long unsigned short crc=0; 21951a7b740SScott Long 22051a7b740SScott Long while (n-- > 0) 22151a7b740SScott Long crc = crc_table[(crc>>8 ^ *s++) & 0xff] ^ (crc<<8); 22251a7b740SScott Long return crc; 22351a7b740SScott Long } 22451a7b740SScott Long 22551a7b740SScott Long /* UNICODE Checksum */ 22651a7b740SScott Long unsigned short 22751a7b740SScott Long udf_unicode_cksum(s, n) 22851a7b740SScott Long unsigned short *s; 22951a7b740SScott Long int n; 23051a7b740SScott Long { 23151a7b740SScott Long unsigned short crc=0; 23251a7b740SScott Long 23351a7b740SScott Long while (n-- > 0) { 23451a7b740SScott Long /* Take high order byte first--corresponds to a big endian 23551a7b740SScott Long * byte stream. 23651a7b740SScott Long */ 23751a7b740SScott Long crc = crc_table[(crc>>8 ^ (*s>>8)) & 0xff] ^ (crc<<8); 23851a7b740SScott Long crc = crc_table[(crc>>8 ^ (*s++ & 0xff)) & 0xff] ^ (crc<<8); 23951a7b740SScott Long } 24051a7b740SScott Long return crc; 24151a7b740SScott Long } 24251a7b740SScott Long 24351a7b740SScott Long #ifdef MAIN 24451a7b740SScott Long unsigned char bytes[] = { 0x70, 0x6A, 0x77 }; 24551a7b740SScott Long 24651a7b740SScott Long main() 24751a7b740SScott Long { 24851a7b740SScott Long unsigned short x; 24951a7b740SScott Long x = cksum(bytes, sizeof bytes); 25051a7b740SScott Long printf("checksum: calculated=%4.4x, correct=%4.4x\en", x, 0x3299); 25151a7b740SScott Long exit(0); 25251a7b740SScott Long } 25351a7b740SScott Long #endif 25451a7b740SScott Long 25551a7b740SScott Long /*****************************************************************************/ 25651a7b740SScott Long #ifdef NEEDS_ISPRINT 257d167cf6fSWarner Losh /*- 258d167cf6fSWarner Losh ********************************************************************** 25951a7b740SScott Long * OSTA UDF compliant file name translation routine for OS/2, 26051a7b740SScott Long * Windows 95, Windows NT, Macintosh and UNIX. 26151a7b740SScott Long * Copyright 1995 Micro Design International, Inc. 26251a7b740SScott Long * Written by Jason M. Rinn. 26351a7b740SScott Long * Micro Design International gives permission for the free use of the 26451a7b740SScott Long * following source code. 26551a7b740SScott Long */ 26651a7b740SScott Long 26751a7b740SScott Long /*********************************************************************** 26851a7b740SScott Long * To use these routines with different operating systems. 26951a7b740SScott Long * 27051a7b740SScott Long * OS/2 27151a7b740SScott Long * Define OS2 27251a7b740SScott Long * Define MAXLEN = 254 27351a7b740SScott Long * 27451a7b740SScott Long * Windows 95 27551a7b740SScott Long * Define WIN_95 27651a7b740SScott Long * Define MAXLEN = 255 27751a7b740SScott Long * 27851a7b740SScott Long * Windows NT 27951a7b740SScott Long * Define WIN_NT 28051a7b740SScott Long * Define MAXLEN = 255 28151a7b740SScott Long * 28251a7b740SScott Long * Macintosh: 283dde155e9SRobert Watson * Define APPLE_MAC. 28451a7b740SScott Long * Define MAXLEN = 31. 28551a7b740SScott Long * 28651a7b740SScott Long * UNIX 28751a7b740SScott Long * Define UNIX. 28851a7b740SScott Long * Define MAXLEN as specified by unix version. 28951a7b740SScott Long */ 29051a7b740SScott Long 29151a7b740SScott Long #define ILLEGAL_CHAR_MARK 0x005F 29251a7b740SScott Long #define CRC_MARK 0x0023 29351a7b740SScott Long #define EXT_SIZE 5 29451a7b740SScott Long #define TRUE 1 29551a7b740SScott Long #define FALSE 0 29651a7b740SScott Long #define PERIOD 0x002E 29751a7b740SScott Long #define SPACE 0x0020 29851a7b740SScott Long 29951a7b740SScott Long /*** PROTOTYPES ***/ 30051a7b740SScott Long int IsIllegal(unicode_t ch); 30151a7b740SScott Long 30251a7b740SScott Long /* Define a function or macro which determines if a Unicode character is 30351a7b740SScott Long * printable under your implementation. 30451a7b740SScott Long */ 30551a7b740SScott Long int UnicodeIsPrint(unicode_t); 30651a7b740SScott Long 30751a7b740SScott Long /*********************************************************************** 30851a7b740SScott Long * Translates a long file name to one using a MAXLEN and an illegal 30951a7b740SScott Long * char set in accord with the OSTA requirements. Assumes the name has 31051a7b740SScott Long * already been translated to Unicode. 31151a7b740SScott Long * 31251a7b740SScott Long * RETURN VALUE 31351a7b740SScott Long * 31451a7b740SScott Long * Number of unicode characters in translated name. 31551a7b740SScott Long */ 31651a7b740SScott Long int UDFTransName( 31751a7b740SScott Long unicode_t *newName, /* (Output)Translated name. Must be of length 31851a7b740SScott Long * MAXLEN */ 31951a7b740SScott Long unicode_t *udfName, /* (Input) Name from UDF volume.*/ 32051a7b740SScott Long int udfLen) /* (Input) Length of UDF Name. */ 32151a7b740SScott Long { 32251a7b740SScott Long int index, newIndex = 0, needsCRC = FALSE; 32351a7b740SScott Long int extIndex = 0, newExtIndex = 0, hasExt = FALSE; 32451a7b740SScott Long #if defined OS2 || defined WIN_95 || defined WIN_NT 32551a7b740SScott Long int trailIndex = 0; 32651a7b740SScott Long #endif 32751a7b740SScott Long unsigned short valueCRC; 32851a7b740SScott Long unicode_t current; 32951a7b740SScott Long const char hexChar[] = "0123456789ABCDEF"; 33051a7b740SScott Long 33151a7b740SScott Long for (index = 0; index < udfLen; index++) { 33251a7b740SScott Long current = udfName[index]; 33351a7b740SScott Long 33451a7b740SScott Long if (IsIllegal(current) || !UnicodeIsPrint(current)) { 33551a7b740SScott Long needsCRC = TRUE; 33651a7b740SScott Long /* Replace Illegal and non-displayable chars with 33751a7b740SScott Long * underscore. 33851a7b740SScott Long */ 33951a7b740SScott Long current = ILLEGAL_CHAR_MARK; 34051a7b740SScott Long /* Skip any other illegal or non-displayable 34151a7b740SScott Long * characters. 34251a7b740SScott Long */ 34351a7b740SScott Long while(index+1 < udfLen && (IsIllegal(udfName[index+1]) 34451a7b740SScott Long || !UnicodeIsPrint(udfName[index+1]))) { 34551a7b740SScott Long index++; 34651a7b740SScott Long } 34751a7b740SScott Long } 34851a7b740SScott Long 34951a7b740SScott Long /* Record position of extension, if one is found. */ 35051a7b740SScott Long if (current == PERIOD && (udfLen - index -1) <= EXT_SIZE) { 35151a7b740SScott Long if (udfLen == index + 1) { 35251a7b740SScott Long /* A trailing period is NOT an extension. */ 35351a7b740SScott Long hasExt = FALSE; 35451a7b740SScott Long } else { 35551a7b740SScott Long hasExt = TRUE; 35651a7b740SScott Long extIndex = index; 35751a7b740SScott Long newExtIndex = newIndex; 35851a7b740SScott Long } 35951a7b740SScott Long } 36051a7b740SScott Long 36151a7b740SScott Long #if defined OS2 || defined WIN_95 || defined WIN_NT 36251a7b740SScott Long /* Record position of last char which is NOT period or space. */ 36351a7b740SScott Long else if (current != PERIOD && current != SPACE) { 36451a7b740SScott Long trailIndex = newIndex; 36551a7b740SScott Long } 36651a7b740SScott Long #endif 36751a7b740SScott Long 36851a7b740SScott Long if (newIndex < MAXLEN) { 36951a7b740SScott Long newName[newIndex++] = current; 37051a7b740SScott Long } else { 37151a7b740SScott Long needsCRC = TRUE; 37251a7b740SScott Long } 37351a7b740SScott Long } 37451a7b740SScott Long 37551a7b740SScott Long #if defined OS2 || defined WIN_95 || defined WIN_NT 37651a7b740SScott Long /* For OS2, 95 & NT, truncate any trailing periods and\or spaces. */ 37751a7b740SScott Long if (trailIndex != newIndex - 1) { 37851a7b740SScott Long newIndex = trailIndex + 1; 37951a7b740SScott Long needsCRC = TRUE; 38051a7b740SScott Long hasExt = FALSE; /* Trailing period does not make an 38151a7b740SScott Long * extension. */ 38251a7b740SScott Long } 38351a7b740SScott Long #endif 38451a7b740SScott Long 38551a7b740SScott Long if (needsCRC) { 38651a7b740SScott Long unicode_t ext[EXT_SIZE]; 38751a7b740SScott Long int localExtIndex = 0; 38851a7b740SScott Long if (hasExt) { 38951a7b740SScott Long int maxFilenameLen; 39051a7b740SScott Long /* Translate extension, and store it in ext. */ 39151a7b740SScott Long for(index = 0; index<EXT_SIZE && 39251a7b740SScott Long extIndex + index +1 < udfLen; index++ ) { 39351a7b740SScott Long current = udfName[extIndex + index + 1]; 39451a7b740SScott Long if (IsIllegal(current) || 39551a7b740SScott Long !UnicodeIsPrint(current)) { 39651a7b740SScott Long needsCRC = 1; 39751a7b740SScott Long /* Replace Illegal and non-displayable 39851a7b740SScott Long * chars with underscore. 39951a7b740SScott Long */ 40051a7b740SScott Long current = ILLEGAL_CHAR_MARK; 40151a7b740SScott Long /* Skip any other illegal or 40251a7b740SScott Long * non-displayable characters. 40351a7b740SScott Long */ 40451a7b740SScott Long while(index + 1 < EXT_SIZE 40551a7b740SScott Long && (IsIllegal(udfName[extIndex + 40651a7b740SScott Long index + 2]) || 40751a7b740SScott Long !isprint(udfName[extIndex + 40851a7b740SScott Long index + 2]))) { 40951a7b740SScott Long index++; 41051a7b740SScott Long } 41151a7b740SScott Long } 41251a7b740SScott Long ext[localExtIndex++] = current; 41351a7b740SScott Long } 41451a7b740SScott Long 41551a7b740SScott Long /* Truncate filename to leave room for extension and 41651a7b740SScott Long * CRC. 41751a7b740SScott Long */ 41851a7b740SScott Long maxFilenameLen = ((MAXLEN - 5) - localExtIndex - 1); 41951a7b740SScott Long if (newIndex > maxFilenameLen) { 42051a7b740SScott Long newIndex = maxFilenameLen; 42151a7b740SScott Long } else { 42251a7b740SScott Long newIndex = newExtIndex; 42351a7b740SScott Long } 42451a7b740SScott Long } else if (newIndex > MAXLEN - 5) { 42551a7b740SScott Long /*If no extension, make sure to leave room for CRC. */ 42651a7b740SScott Long newIndex = MAXLEN - 5; 42751a7b740SScott Long } 42851a7b740SScott Long newName[newIndex++] = CRC_MARK; /* Add mark for CRC. */ 42951a7b740SScott Long 43051a7b740SScott Long /*Calculate CRC from original filename from FileIdentifier. */ 43151a7b740SScott Long valueCRC = udf_unicode_cksum(udfName, udfLen); 43251a7b740SScott Long /* Convert 16-bits of CRC to hex characters. */ 43351a7b740SScott Long newName[newIndex++] = hexChar[(valueCRC & 0xf000) >> 12]; 43451a7b740SScott Long newName[newIndex++] = hexChar[(valueCRC & 0x0f00) >> 8]; 43551a7b740SScott Long newName[newIndex++] = hexChar[(valueCRC & 0x00f0) >> 4]; 43651a7b740SScott Long newName[newIndex++] = hexChar[(valueCRC & 0x000f)]; 43751a7b740SScott Long 43851a7b740SScott Long /* Place a translated extension at end, if found. */ 43951a7b740SScott Long if (hasExt) { 44051a7b740SScott Long newName[newIndex++] = PERIOD; 44151a7b740SScott Long for (index = 0;index < localExtIndex ;index++ ) { 44251a7b740SScott Long newName[newIndex++] = ext[index]; 44351a7b740SScott Long } 44451a7b740SScott Long } 44551a7b740SScott Long } 44651a7b740SScott Long return(newIndex); 44751a7b740SScott Long } 44851a7b740SScott Long 44951a7b740SScott Long #if defined OS2 || defined WIN_95 || defined WIN_NT 45051a7b740SScott Long /*********************************************************************** 45151a7b740SScott Long * Decides if a Unicode character matches one of a list 45251a7b740SScott Long * of ASCII characters. 45351a7b740SScott Long * Used by OS2 version of IsIllegal for readability, since all of the 45451a7b740SScott Long * illegal characters above 0x0020 are in the ASCII subset of Unicode. 45551a7b740SScott Long * Works very similarly to the standard C function strchr(). 45651a7b740SScott Long * 45751a7b740SScott Long * RETURN VALUE 45851a7b740SScott Long * 45951a7b740SScott Long * Non-zero if the Unicode character is in the given ASCII string. 46051a7b740SScott Long */ 46151a7b740SScott Long int UnicodeInString( 46251a7b740SScott Long unsigned char *string, /* (Input) String to search through. */ 46351a7b740SScott Long unicode_t ch) /* (Input) Unicode char to search for. */ 46451a7b740SScott Long { 46551a7b740SScott Long int found = FALSE; 46651a7b740SScott Long while (*string != '\0' && found == FALSE) { 46751a7b740SScott Long /* These types should compare, since both are unsigned 46851a7b740SScott Long * numbers. */ 46951a7b740SScott Long if (*string == ch) { 47051a7b740SScott Long found = TRUE; 47151a7b740SScott Long } 47251a7b740SScott Long string++; 47351a7b740SScott Long } 47451a7b740SScott Long return(found); 47551a7b740SScott Long } 47651a7b740SScott Long #endif /* OS2 */ 47751a7b740SScott Long 47851a7b740SScott Long /*********************************************************************** 47951a7b740SScott Long * Decides whether the given character is illegal for a given OS. 48051a7b740SScott Long * 48151a7b740SScott Long * RETURN VALUE 48251a7b740SScott Long * 48351a7b740SScott Long * Non-zero if char is illegal. 48451a7b740SScott Long */ 48551a7b740SScott Long int IsIllegal(unicode_t ch) 48651a7b740SScott Long { 487dde155e9SRobert Watson #ifdef APPLE_MAC 48851a7b740SScott Long /* Only illegal character on the MAC is the colon. */ 48951a7b740SScott Long if (ch == 0x003A) { 49051a7b740SScott Long return(1); 49151a7b740SScott Long } else { 49251a7b740SScott Long return(0); 49351a7b740SScott Long } 49451a7b740SScott Long 49551a7b740SScott Long #elif defined UNIX 49651a7b740SScott Long /* Illegal UNIX characters are NULL and slash. */ 49751a7b740SScott Long if (ch == 0x0000 || ch == 0x002F) { 49851a7b740SScott Long return(1); 49951a7b740SScott Long } else { 50051a7b740SScott Long return(0); 50151a7b740SScott Long } 50251a7b740SScott Long 50351a7b740SScott Long #elif defined OS2 || defined WIN_95 || defined WIN_NT 50451a7b740SScott Long /* Illegal char's for OS/2 according to WARP toolkit. */ 50551a7b740SScott Long if (ch < 0x0020 || UnicodeInString("\\/:*?\"<>|", ch)) { 50651a7b740SScott Long return(1); 50751a7b740SScott Long } else { 50851a7b740SScott Long return(0); 50951a7b740SScott Long } 51051a7b740SScott Long #endif 51151a7b740SScott Long } 51251a7b740SScott Long #endif 513