This commit is contained in:
King_DuckZ 2020-05-05 20:22:39 +02:00
parent 1af4b85a22
commit 0433a6bc0a
12 changed files with 4843 additions and 4686 deletions

134
UnAlz.cpp
View file

@ -87,6 +87,7 @@ static const char* errorstrtable[]=
"no error", // ERR_NOERR "no error", // ERR_NOERR
"can't open file", // ERR_CANT_OPEN_FILE "can't open file", // ERR_CANT_OPEN_FILE
"corrupted file", // ERR_CORRUPTED_FILE "corrupted file", // ERR_CORRUPTED_FILE
"not alz file", // ERR_NOT_ALZ_FILE
"can't read signature", // ERR_CANT_READ_SIG "can't read signature", // ERR_CANT_READ_SIG
"can't read file", // ERR_CANT_READ_FILE "can't read file", // ERR_CANT_READ_FILE
"error at read header", // ERR_AT_READ_HEADER "error at read header", // ERR_AT_READ_HEADER
@ -100,6 +101,9 @@ static const char* errorstrtable[]=
"memory allocation failed", // ERR_MEM_ALLOC_FAILED, "memory allocation failed", // ERR_MEM_ALLOC_FAILED,
"file read error", // ERR_FILE_READ_ERROR, "file read error", // ERR_FILE_READ_ERROR,
"inflate failed", // ERR_INFLATE_FAILED, "inflate failed", // ERR_INFLATE_FAILED,
"bzip2 decompress failed", // ERR_BZIP2_FAILED,
"invalid file CRC", // ERR_INVALID_FILE_CRC
"unknown compression method", // ERR_UNKNOWN_COMPRESSION_METHOD
"iconv-can't open iconv", // ERR_ICONV_CANT_OPEN, "iconv-can't open iconv", // ERR_ICONV_CANT_OPEN,
"iconv-invalid multisequence of characters", // ERR_ICONV_INVALID_MULTISEQUENCE_OF_CHARACTERS, "iconv-invalid multisequence of characters", // ERR_ICONV_INVALID_MULTISEQUENCE_OF_CHARACTERS,
@ -107,9 +111,9 @@ static const char* errorstrtable[]=
"iconv-not enough space of buffer to convert", // ERR_ICONV_NOT_ENOUGH_SPACE_OF_BUFFER_TO_CONVERT, "iconv-not enough space of buffer to convert", // ERR_ICONV_NOT_ENOUGH_SPACE_OF_BUFFER_TO_CONVERT,
"iconv-etc", // ERR_ICONV_ETC, "iconv-etc", // ERR_ICONV_ETC,
"password not set", //ERR_PASSWD_NOT_SET, "password was not set", // ERR_PASSWD_NOT_SET,
"invalid password", //ERR_INVALID_PASSWD, "invalid password", // ERR_INVALID_PASSWD,
"User Aborted", "user aborted",
}; };
@ -210,6 +214,8 @@ BOOL CUnAlz::Open(const char* szPathName)
return FALSE; return FALSE;
} }
BOOL bValidAlzHeader = FALSE;
// file 분석시작.. // file 분석시작..
for(;;) for(;;)
{ {
@ -225,11 +231,18 @@ BOOL CUnAlz::Open(const char* szPathName)
} }
if(sig==SIG_ERROR) if(sig==SIG_ERROR)
{ {
m_nErr = ERR_CORRUPTED_FILE; if(bValidAlzHeader)
m_nErr = ERR_CORRUPTED_FILE; // 손상된 파일
else
m_nErr = ERR_NOT_ALZ_FILE; // alz 파일이 아니다.
return FALSE; // 깨진 파일.. return FALSE; // 깨진 파일..
} }
if(sig==SIG_ALZ_FILE_HEADER) ret = ReadAlzFileHeader(); if(sig==SIG_ALZ_FILE_HEADER)
{
ret = ReadAlzFileHeader();
bValidAlzHeader = TRUE; // alz 파일은 맞다.
}
else if(sig==SIG_LOCAL_FILE_HEADER) ret = ReadLocalFileheader(); else if(sig==SIG_LOCAL_FILE_HEADER) ret = ReadLocalFileheader();
else if(sig==SIG_CENTRAL_DIRECTORY_STRUCTURE) ret = ReadCentralDirectoryStructure(); else if(sig==SIG_CENTRAL_DIRECTORY_STRUCTURE) ret = ReadCentralDirectoryStructure();
else if(sig==SIG_ENDOF_CENTRAL_DIRECTORY_RECORD) ret = ReadEndofCentralDirectoryRecord(); else if(sig==SIG_ENDOF_CENTRAL_DIRECTORY_RECORD) ret = ReadEndofCentralDirectoryRecord();
@ -340,9 +353,9 @@ BOOL CUnAlz::ReadLocalFileheader()
if(byteLen) if(byteLen)
{ {
FRead(&(zipHeader.compressionMethod), sizeof(zipHeader.compressionMethod)); FRead(&(zipHeader.compressionMethod), sizeof(zipHeader.compressionMethod));
FRead(&(zipHeader.unknown3), sizeof(zipHeader.unknown3)); FRead(&(zipHeader.unknown), sizeof(zipHeader.unknown));
FRead(&(zipHeader.unknown4), sizeof(zipHeader.unknown4)); FRead(&(zipHeader.fileCRC), sizeof(zipHeader.fileCRC));
FRead(&(zipHeader.passwordCRC), sizeof(zipHeader.passwordCRC)); // FRead(&(zipHeader.passwordCRC), sizeof(zipHeader.passwordCRC));
FRead(&(zipHeader.compressedSize), byteLen); FRead(&(zipHeader.compressedSize), byteLen);
FRead(&(zipHeader.uncompressedSize), byteLen); // 압축 사이즈가 없다. FRead(&(zipHeader.uncompressedSize), byteLen); // 압축 사이즈가 없다.
@ -354,7 +367,7 @@ BOOL CUnAlz::ReadLocalFileheader()
zipHeader.uncompressedSize = unalz_le64toh(zipHeader.uncompressedSize); zipHeader.uncompressedSize = unalz_le64toh(zipHeader.uncompressedSize);
// FILE NAME // FILE NAME
zipHeader.fileName = (char*)malloc(zipHeader.head.fileNameLength+1); zipHeader.fileName = (char*)malloc(zipHeader.head.fileNameLength+sizeof(char));
if(zipHeader.fileName==NULL) if(zipHeader.fileName==NULL)
{ {
m_nErr = ERR_INVALID_FILENAME_LENGTH; m_nErr = ERR_INVALID_FILENAME_LENGTH;
@ -415,7 +428,14 @@ BOOL CUnAlz::ReadLocalFileheader()
else else
{ {
outbuf[ICONV_BUF_SIZE-oleft] = 0; outbuf[ICONV_BUF_SIZE-oleft] = 0;
strcpy(zipHeader.fileName, outbuf); if(zipHeader.fileName) free(zipHeader.fileName);
zipHeader.fileName = strdup(outbuf);
if (zipHeader.fileName == NULL)
{
m_nErr = ERR_ICONV_ETC;
iconv_close(cd);
return FALSE;
}
// printf("\n Converted File Name : %s", outbuf); // printf("\n Converted File Name : %s", outbuf);
} }
@ -576,6 +596,11 @@ BOOL CUnAlz::SetCurrentFile(const char* szFileName)
return FALSE; return FALSE;
} }
void CUnAlz::SetCurrentFile(FileList::iterator newPos)
{
m_posCur = newPos;
}
#ifndef MAX_WBITS #ifndef MAX_WBITS
# define MAX_WBITS 15 /* 32K LZ77 window */ # define MAX_WBITS 15 /* 32K LZ77 window */
#endif #endif
@ -692,9 +717,12 @@ BOOL CUnAlz::ExtractTo(SExtractDest* dest)
{ {
ret = ExtractDeflate2(dest, *m_posCur); // deflate ret = ExtractDeflate2(dest, *m_posCur); // deflate
} }
else else // COMP_UNKNOWN
{ {
ASSERT(0); // »õ·Î¿î ¹æ¹ý ??? // alzip 5.6 부터 추가된 포맷(5.5 에서는 풀지 못한다. 영문 5.51 은 푼다 )
// 하지만 어떤 버전에서 이 포맷을 만들어 내는지 정확히 알 수 없다.
m_nErr = ERR_UNKNOWN_COMPRESSION_METHOD;
ASSERT(0);
ret = FALSE; ret = FALSE;
} }
return ret; return ret;
@ -887,6 +915,7 @@ int CUnAlz::WriteToDest(SExtractDest* dest, BYTE* buf, int nSize)
} }
else if(dest->nType==ET_MEM) else if(dest->nType==ET_MEM)
{ {
if(dest->buf==NULL) return nSize; // 대상이 NULL 이다... 압축푸는 시늉만 한다..
if(dest->bufpos+nSize >dest->bufsize) // 에러.. 버퍼가 넘쳤다. if(dest->bufpos+nSize >dest->bufsize) // 에러.. 버퍼가 넘쳤다.
{ {
ASSERT(0); ASSERT(0);
@ -1014,6 +1043,7 @@ BOOL CUnAlz::ExtractRawfile(SExtractDest* dest, SLocalFileHeader& file)
INT64 nWritten = 0; INT64 nWritten = 0;
BOOL bHalt = FALSE; BOOL bHalt = FALSE;
BOOL bIsEncrypted = IsEncryptedFile(); // 암호걸린 파일인가? BOOL bIsEncrypted = IsEncryptedFile(); // 암호걸린 파일인가?
UINT32 dwCRC32= 0;
@ -1022,6 +1052,7 @@ BOOL CUnAlz::ExtractRawfile(SExtractDest* dest, SLocalFileHeader& file)
sizeToRead = file.compressedSize; // 읽을 크기. sizeToRead = file.compressedSize; // 읽을 크기.
m_nErr = ERR_NOERR;
while(sizeToRead) while(sizeToRead)
{ {
read = min(sizeToRead, bufLen); read = min(sizeToRead, bufLen);
@ -1033,6 +1064,8 @@ BOOL CUnAlz::ExtractRawfile(SExtractDest* dest, SLocalFileHeader& file)
if(bIsEncrypted) if(bIsEncrypted)
DecryptingData((int)read, buf); // xf86 DecryptingData((int)read, buf); // xf86
dwCRC32 = crc32(dwCRC32, buf, (UINT)(read));
WriteToDest(dest, buf, (int)read); WriteToDest(dest, buf, (int)read);
//fwrite(buf, read, 1, fp); //fwrite(buf, read, 1, fp);
sizeToRead -= read; sizeToRead -= read;
@ -1051,7 +1084,20 @@ BOOL CUnAlz::ExtractRawfile(SExtractDest* dest, SLocalFileHeader& file)
} }
m_bHalt = bHalt; m_bHalt = bHalt;
if(m_nErr==ERR_NOERR) // 성공적으로 압축을 풀었다.. CRC 검사하기..
{
if(file.fileCRC==dwCRC32)
{
ret = TRUE; ret = TRUE;
}
else
{
m_nErr = ERR_INVALID_FILE_CRC;
}
}
return ret; return ret;
} }
@ -1070,9 +1116,11 @@ BOOL CUnAlz::ExtractBzip2(SExtractDest* dest, SLocalFileHeader& file)
int verbosity = 1; int verbosity = 1;
int bzerr; int bzerr;
INT64 len; INT64 len;
char buff[BZIP2_EXTRACT_BUF_SIZE]; BYTE buff[BZIP2_EXTRACT_BUF_SIZE];
INT64 nWritten = 0; INT64 nWritten = 0;
BOOL bHalt = FALSE; BOOL bHalt = FALSE;
UINT32 dwCRC32= 0;
BOOL ret = FALSE;
FSeek(file.dwFileDataPos); FSeek(file.dwFileDataPos);
@ -1080,11 +1128,15 @@ BOOL CUnAlz::ExtractBzip2(SExtractDest* dest, SLocalFileHeader& file)
if(bzfp==NULL){ASSERT(0); return FALSE;} if(bzfp==NULL){ASSERT(0); return FALSE;}
m_nErr = ERR_NOERR;
while((len=BZ2_bzread(bzfp,buff,BZIP2_EXTRACT_BUF_SIZE))>0) while((len=BZ2_bzread(bzfp,buff,BZIP2_EXTRACT_BUF_SIZE))>0)
{ {
WriteToDest(dest, (BYTE*)buff, (int)len); WriteToDest(dest, (BYTE*)buff, (int)len);
//fwrite(buff,1,len,fp_w); //fwrite(buff,1,len,fp_w);
dwCRC32 = crc32(dwCRC32,buff, (UINT)(len));
nWritten+=len; nWritten+=len;
// progress callback // progress callback
@ -1098,10 +1150,28 @@ BOOL CUnAlz::ExtractBzip2(SExtractDest* dest, SLocalFileHeader& file)
} }
} }
if(len<0) // 에러 상황..
{
m_nErr = ERR_INFLATE_FAILED;
}
BZ2_bzReadClose( &bzerr, bzfp); BZ2_bzReadClose( &bzerr, bzfp);
m_bHalt = bHalt; m_bHalt = bHalt;
if(m_nErr==ERR_NOERR) // 성공적으로 압축을 풀었다.. CRC 검사하기..
{
if(file.fileCRC==dwCRC32)
{
ret = TRUE;
}
else
{
m_nErr = ERR_INVALID_FILE_CRC;
}
}
/* /*
// FILE* 를 사용할경우 사용하던 코드. - 멀티 볼륨 지원 안함.. // FILE* 를 사용할경우 사용하던 코드. - 멀티 볼륨 지원 안함..
BZFILE *bzfp = NULL; BZFILE *bzfp = NULL;
@ -1140,7 +1210,7 @@ BOOL CUnAlz::ExtractBzip2(SExtractDest* dest, SLocalFileHeader& file)
m_bHalt = bHalt; m_bHalt = bHalt;
*/ */
return TRUE; return ret;
} }
@ -1188,6 +1258,7 @@ BOOL CUnAlz::ExtractDeflate2(SExtractDest* dest, SLocalFileHeader& file)
stream.next_out = pOutBuf; stream.next_out = pOutBuf;
stream.avail_out = OUT_BUF_SIZE; stream.avail_out = OUT_BUF_SIZE;
m_nErr = ERR_NOERR;
while(stream.avail_out>0) while(stream.avail_out>0)
{ {
if(stream.avail_in==0 && nRestReadCompressed>0) if(stream.avail_in==0 && nRestReadCompressed>0)
@ -1208,6 +1279,8 @@ BOOL CUnAlz::ExtractDeflate2(SExtractDest* dest, SLocalFileHeader& file)
if(bIsEncrypted) if(bIsEncrypted)
DecryptingData(uReadThis, pInBuf); // xf86 DecryptingData(uReadThis, pInBuf); // xf86
// dwCRC32 = crc32(dwCRC32,pInBuf, (UINT)(uReadThis));
nRestReadCompressed -= uReadThis; nRestReadCompressed -= uReadThis;
stream.next_in = pInBuf; stream.next_in = pInBuf;
stream.avail_in = uReadThis; stream.avail_in = uReadThis;
@ -1245,6 +1318,7 @@ BOOL CUnAlz::ExtractDeflate2(SExtractDest* dest, SLocalFileHeader& file)
m_pFuncCallBack(NULL, nWritten, file.uncompressedSize, m_pCallbackParam, &bHalt); m_pFuncCallBack(NULL, nWritten, file.uncompressedSize, m_pCallbackParam, &bHalt);
if(bHalt) if(bHalt)
{ {
m_nErr = ERR_USER_ABORTED;
break; break;
} }
} }
@ -1258,10 +1332,21 @@ BOOL CUnAlz::ExtractDeflate2(SExtractDest* dest, SLocalFileHeader& file)
goto END; goto END;
} }
} }
m_bHalt = bHalt; m_bHalt = bHalt;
if(m_nErr==ERR_NOERR) // 성공적으로 압축을 풀었다.. CRC 검사하기..
{
if(file.fileCRC==dwCRC32)
{
ret = TRUE; ret = TRUE;
}
else
{
m_nErr = ERR_INVALID_FILE_CRC;
}
}
END : END :
inflateEnd(&stream); inflateEnd(&stream);
@ -1497,8 +1582,8 @@ const char* CUnAlz::LastErrToStr(ERR nERR)
// by xf86 // by xf86
BOOL CUnAlz::chkValidPassword() BOOL CUnAlz::chkValidPassword()
{ {
if(IsEncryptedFile()) if(IsEncryptedFile()==FALSE) {return TRUE;}
{
if (getPasswordLen() == 0){ if (getPasswordLen() == 0){
m_nErr = ERR_PASSWD_NOT_SET; m_nErr = ERR_PASSWD_NOT_SET;
return FALSE; return FALSE;
@ -1508,7 +1593,6 @@ BOOL CUnAlz::chkValidPassword()
m_nErr = ERR_INVALID_PASSWD; m_nErr = ERR_INVALID_PASSWD;
return FALSE; return FALSE;
} }
}
return TRUE; return TRUE;
} }
@ -1638,21 +1722,25 @@ void CUnAlz::UpdateKeys(BYTE c)
/// @return /// @return
/// @date 2004-11-27 오후 11:04:24 /// @date 2004-11-27 오후 11:04:24
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CUnAlz::CryptCheck(BYTE* buf) BOOL CUnAlz::CryptCheck(const BYTE* buf)
{ {
int i; int i;
BYTE c; BYTE c;
BYTE temp[ENCR_HEADER_LEN];
memcpy(temp, buf, ENCR_HEADER_LEN); // 임시 복사.
for(i=0;i<ENCR_HEADER_LEN;i++) for(i=0;i<ENCR_HEADER_LEN;i++)
{ {
c = buf[i] ^ DecryptByte(); c = temp[i] ^ DecryptByte();
UpdateKeys(c); UpdateKeys(c);
buf[i] = c; temp[i] = c;
} }
if (IsDataDescr()) // Data descriptor present if (IsDataDescr()) // Data descriptor present
return (m_posCur->head.fileTimeDate >> 8) == c; return (m_posCur->head.fileTimeDate >> 8) == c;
else else
return (m_posCur->passwordCRC) == c; return ( ((m_posCur->fileCRC)>>24) ) == c; // 파일 crc 의 최상위 byte
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
@ -1701,3 +1789,5 @@ UINT32 CUnAlz::CRC32(UINT32 l, BYTE c)
const ULONG *CRC_TABLE = get_crc_table(); const ULONG *CRC_TABLE = get_crc_table();
return CRC_TABLE[(l ^ c) & 0xff] ^ (l >> 8); return CRC_TABLE[(l ^ c) & 0xff] ^ (l >> 8);
} }

72
UnAlz.h
View file

@ -1,6 +1,6 @@
/* /*
COPYRIGHT(C) 2004 hardkoder@gmail.com / http://www.kipple.pe.kr COPYRIGHT(C) 2004-2005 hardkoder , http://www.kipple.pe.kr
: ( BSD License ) : ( BSD License )
- // . - // .
@ -33,26 +33,39 @@
- 2GB (WINDOWS ONLY) - 2GB (WINDOWS ONLY)
2004/10/22 - (BSD/LINUX) 2004/10/22 - (BSD/LINUX)
( BSD/LINUX 2GB ) ( BSD/LINUX 2GB )
- unalz 0.20
2004/10/23 - by xxfree86 : DARWIN , "\\" 2004/10/23 - by xxfree86 : DARWIN , "\\"
2004/10/24 - by aqua0125 : , 64bit 2004/10/24 - by aqua0125 : , 64bit
- , - ,
2004/10/25 - by yongari : __LP64__ , (le64toh/le132oh/le16toh) 2004/10/25 - by yongari : __LP64__ , (le64toh/le132oh/le16toh)
2004/10/26 - BSD/LINUX : byte-order, libiconv 2004/10/26 - BSD/LINUX : byte-order, libiconv
- unalz 0.22
2004/10/30 - & .. 2004/10/30 - & ..
- unalz 0.23
2004/11/14 - by xxfre86 : 2004/11/14 - by xxfre86 :
- unalz 0.30
2004/11/27 - cygwin에서 2004/11/27 - cygwin에서
- GPL CZipArchive "ZIP File Format Specification version 4.5" & - GPL CZipArchive "ZIP File Format Specification version 4.5" &
- -
- -
- unalz 0.31
2005/01/08 -
2005/02/05 - deflate CRC
2005/03/07 - bzip2, raw CRC
2005/03/13 - ALZ (ERR_NOT_ALZ_FILE)
2005/06/16 - GetFileList() ( )
2005/06/18 - by goweol : utf-8
- unalz 0.4
: ( * ) :
- bzip2 * - alz ( deflate/ bzip2/raw )
- UI ( PROGRESS, , ) * - (alz, a00, a01.. )
- * - (Win32/POSIX(BSD/LINUX/DARWIN))
- * -
- -> -
- CRC -> alz CRC . OTL - CRC
( -DXXXX ) ( -DXXXX )
- _WIN32 : WIN32 - _WIN32 : WIN32
@ -149,8 +162,8 @@ namespace UNALZ
# pragma pack(1) # pragma pack(1)
#endif #endif
static const char UNALZ_VERSION[] = "CUnAlz0.31"; static const char UNALZ_VERSION[] = "CUnAlz0.4";
static const char UNALZ_COPYRIGHT[] = "Copyright(C) 2004 hardkoder@gmail.com"; static const char UNALZ_COPYRIGHT[] = "Copyright(C) 2004-2005 by hardkoder ( http://www.kipple.pe.kr ) ";
enum {ENCR_HEADER_LEN=12}; // xf86 enum {ENCR_HEADER_LEN=12}; // xf86
// 맨 파일 앞.. // 맨 파일 앞..
@ -180,12 +193,20 @@ enum COMPRESSION_METHOD ///<
COMP_NOCOMP = 0, COMP_NOCOMP = 0,
COMP_BZIP2 = 1, COMP_BZIP2 = 1,
COMP_DEFLATE = 2, COMP_DEFLATE = 2,
COMP_UNKNOWN = 3, // unknown!
};
enum FILE_ATTRIBUTE
{
FILEATTR_FILE = 0x1,
FILEATTR_FOLDER = 0x10,
FILEATTR_FILE2 = 0x20, /// FILEATTR_FILE 과 FILEATTR_FILE2 의 차이는 모르겠다..
}; };
struct _SLocalFileHeaderHead ///< 고정 헤더. struct _SLocalFileHeaderHead ///< 고정 헤더.
{ {
SHORT fileNameLength; SHORT fileNameLength;
BYTE fileAttribute; // from http://www.zap.pe.kr BYTE fileAttribute; // from http://www.zap.pe.kr, FILE_ATTRIBUE 참고
UINT32 fileTimeDate; UINT32 fileTimeDate;
BYTE fileDescriptor; ///< 파일 크기 필드의 크기 : 0x10, 0x20, 0x40, 0x80 각각 1byte, 2byte, 4byte, 8byte. BYTE fileDescriptor; ///< 파일 크기 필드의 크기 : 0x10, 0x20, 0x40, 0x80 각각 1byte, 2byte, 4byte, 8byte.
@ -206,12 +227,14 @@ struct _SLocalFileHeaderHead ///<
*/ */
}; };
/*
struct _SDataDescriptor struct _SDataDescriptor
{ {
UINT32 crc32; UINT32 crc32;
UINT32 compressed; UINT32 compressed;
UINT32 uncompressed; UINT32 uncompressed;
}; };
*/
struct SLocalFileHeader struct SLocalFileHeader
{ {
@ -221,16 +244,16 @@ struct SLocalFileHeader
_SLocalFileHeaderHead head; _SLocalFileHeaderHead head;
BYTE compressionMethod; ///< 압축 방법 : 2 - deflate, 1 - 변형 bzip2, 0 - 압축 안함. BYTE compressionMethod; ///< 압축 방법 : 2 - deflate, 1 - 변형 bzip2, 0 - 압축 안함.
BYTE unknown3[1]; ///< ??? BYTE unknown;
BYTE unknown4[3]; ///< 아마도 crc? UINT32 fileCRC; ///< 파일의 CRC, 최상위 바이트는 암호 체크용으로도 사용된다.
BYTE passwordCRC; ///< 암호 체크를 위한 1byte crc //BYTE passwordCRC; ///< 암호 체크를 위한 1byte crc
INT64 compressedSize; INT64 compressedSize;
INT64 uncompressedSize; INT64 uncompressedSize;
CHAR* fileName; CHAR* fileName;
BYTE* extraField; BYTE* extraField;
_SDataDescriptor dataDescriptor; // _SDataDescriptor dataDescriptor;
INT64 dwFileDataPos; ///< file data 가 저장된 위치.. INT64 dwFileDataPos; ///< file data 가 저장된 위치..
BYTE encChk[ENCR_HEADER_LEN]; // xf86 BYTE encChk[ENCR_HEADER_LEN]; // xf86
@ -321,11 +344,12 @@ public:
void Close(); void Close();
BOOL SetCurrentFile(const char* szFileName); BOOL SetCurrentFile(const char* szFileName);
BOOL ExtractCurrentFile(const char* szDestPathName, const char* szDestFileName=NULL); BOOL ExtractCurrentFile(const char* szDestPathName, const char* szDestFileName=NULL);
BOOL ExtractCurrentFileToBuf(BYTE* pDestBuf, int nBufSize); BOOL ExtractCurrentFileToBuf(BYTE* pDestBuf, int nBufSize); // pDestBuf=NULL 일 경우 테스트만 수행한다.
BOOL ExtractAll(const char* szDestPathName); BOOL ExtractAll(const char* szDestPathName);
void SetCallback(_UnAlzCallback* pFunc, void* param=NULL); void SetCallback(_UnAlzCallback* pFunc, void* param=NULL);
void setPassword(char *passwd) { if(strlen(passwd) == 0) return; strcpy(m_szPasswd, passwd); }; // xf86 void setPassword(char *passwd) { if(strlen(passwd) == 0) return; strcpy(m_szPasswd, passwd); }; // xf86
BOOL chkValidPassword(); // xf86
BOOL IsEncrypted() { return m_bIsEncrypted; }; BOOL IsEncrypted() { return m_bIsEncrypted; };
#ifdef _UNALZ_ICONV #ifdef _UNALZ_ICONV
@ -347,9 +371,9 @@ public : ///< WIN32
public : public :
typedef vector<SLocalFileHeader> FileList; ///< 파일 목록. typedef vector<SLocalFileHeader> FileList; ///< 파일 목록.
const FileList& GetFileList() { return m_fileList; }; ///< file 목록 리턴 FileList* GetFileList() { return &m_fileList; }; ///< file 목록 리턴
void SetCurrentFile(FileList::iterator newPos); ///< low level 접근..
FileList::iterator GetCurFileHeader() { return m_posCur; }; ///< 현재 (SetCurrentFile() 로 세팅된) 파일 정보 FileList::iterator GetCurFileHeader() { return m_posCur; }; ///< 현재 (SetCurrentFile() 로 세팅된) 파일 정보
// const SLocalFileHeader* GetCurFileHeader() { return m_posCur; }; ///< 현재 (SetCurrentFile() 로 세팅된) 파일 정보
public : public :
enum ERR ///< 에러 코드 - 정리 필요.. enum ERR ///< 에러 코드 - 정리 필요..
@ -357,6 +381,7 @@ public :
ERR_NOERR, ERR_NOERR,
ERR_CANT_OPEN_FILE, ///< 파일 열기 실패 ERR_CANT_OPEN_FILE, ///< 파일 열기 실패
ERR_CORRUPTED_FILE, ///< 깨진 파일? ERR_CORRUPTED_FILE, ///< 깨진 파일?
ERR_NOT_ALZ_FILE, ///< ALZ 파일이 아니다.
ERR_CANT_READ_SIG, ///< signature 읽기 실패 ERR_CANT_READ_SIG, ///< signature 읽기 실패
ERR_CANT_READ_FILE, ERR_CANT_READ_FILE,
@ -371,6 +396,9 @@ public :
ERR_MEM_ALLOC_FAILED, ERR_MEM_ALLOC_FAILED,
ERR_FILE_READ_ERROR, ERR_FILE_READ_ERROR,
ERR_INFLATE_FAILED, ERR_INFLATE_FAILED,
ERR_BZIP2_FAILED,
ERR_INVALID_FILE_CRC,
ERR_UNKNOWN_COMPRESSION_METHOD,
ERR_ICONV_CANT_OPEN, ERR_ICONV_CANT_OPEN,
ERR_ICONV_INVALID_MULTISEQUENCE_OF_CHARACTERS, ERR_ICONV_INVALID_MULTISEQUENCE_OF_CHARACTERS,
@ -474,11 +502,10 @@ private : //
BOOL m_bIsEncrypted; // xf86 BOOL m_bIsEncrypted; // xf86
BOOL m_bIsDataDescr; BOOL m_bIsDataDescr;
char m_szPasswd[256]; char m_szPasswd[512];
UINT32 m_keys[3];
private : private :
/* /* from CZipArchive
void CryptDecodeBuffer(UINT32 uCount, CHAR *buf); void CryptDecodeBuffer(UINT32 uCount, CHAR *buf);
void CryptInitKeys(); void CryptInitKeys();
void CryptUpdateKeys(CHAR c); void CryptUpdateKeys(CHAR c);
@ -489,12 +516,11 @@ private :
*/ */
private : // encryption 처리 private : // encryption 처리
BOOL chkValidPassword(); // xf86
BOOL IsEncryptedFile(BYTE fileDescriptor); BOOL IsEncryptedFile(BYTE fileDescriptor);
BOOL IsEncryptedFile(); BOOL IsEncryptedFile();
void InitCryptKeys(const CHAR* szPassword); void InitCryptKeys(const CHAR* szPassword);
void UpdateKeys(BYTE c); void UpdateKeys(BYTE c);
BOOL CryptCheck(BYTE* buf); BOOL CryptCheck(const BYTE* buf);
BYTE DecryptByte(); BYTE DecryptByte();
void DecryptingData(int nSize, BYTE* data); void DecryptingData(int nSize, BYTE* data);
UINT32 CRC32(UINT32 l, BYTE c); UINT32 CRC32(UINT32 l, BYTE c);

View file

@ -71,8 +71,9 @@ int main(int argc, char* argv[])
// printf("unalz v0.20 (2004/10/22) \n"); // printf("unalz v0.20 (2004/10/22) \n");
// printf("unalz v0.22 (2004/10/27) \n"); // printf("unalz v0.22 (2004/10/27) \n");
// printf("unalz v0.23 (2004/10/30) \n"); // printf("unalz v0.23 (2004/10/30) \n");
printf("unalz v0.31 (2004/11/27) \n"); // printf("unalz v0.31 (2004/11/27) \n");
printf("Copyright(C) 2004 koder (http://www.kipple.pe.kr) \n"); printf("unalz v0.4 (2005/06/18) \n");
printf("Copyright(C) 2004-2005 by hardkoder (http://www.kipple.pe.kr) \n");
if(argc<2) if(argc<2)
{ {

View file

@ -179,10 +179,6 @@ SOURCE=.\zlib\zconf.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\zlib\zconf.in.h
# End Source File
# Begin Source File
SOURCE=.\zlib\zlib.h SOURCE=.\zlib\zlib.h
# End Source File # End Source File
# Begin Source File # Begin Source File

View file

@ -11,6 +11,14 @@
/* @(#) $Id$ */ /* @(#) $Id$ */
/*
Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
protection on the static variables used to control the first-use generation
of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
first call get_crc_table() to initialize the tables before allowing more than
one thread to use crc32().
*/
#ifdef MAKECRCH #ifdef MAKECRCH
# include <stdio.h> # include <stdio.h>
# ifndef DYNAMIC_CRC_TABLE # ifndef DYNAMIC_CRC_TABLE
@ -58,7 +66,7 @@
#ifdef DYNAMIC_CRC_TABLE #ifdef DYNAMIC_CRC_TABLE
local int crc_table_empty = 1; local volatile int crc_table_empty = 1;
local unsigned long FAR crc_table[TBLS][256]; local unsigned long FAR crc_table[TBLS][256];
local void make_crc_table OF((void)); local void make_crc_table OF((void));
#ifdef MAKECRCH #ifdef MAKECRCH
@ -97,8 +105,15 @@ local void make_crc_table()
int n, k; int n, k;
unsigned long poly; /* polynomial exclusive-or pattern */ unsigned long poly; /* polynomial exclusive-or pattern */
/* terms of polynomial defining this crc (except x^32): */ /* terms of polynomial defining this crc (except x^32): */
static volatile int first = 1; /* flag to limit concurrent making */
static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
/* See if another task is already doing this (not thread-safe, but better
than nothing -- significantly reduces duration of vulnerability in
case the advice about DYNAMIC_CRC_TABLE is ignored) */
if (first) {
first = 0;
/* make exclusive-or pattern from polynomial (0xedb88320UL) */ /* make exclusive-or pattern from polynomial (0xedb88320UL) */
poly = 0UL; poly = 0UL;
for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
@ -113,8 +128,8 @@ local void make_crc_table()
} }
#ifdef BYFOUR #ifdef BYFOUR
/* generate crc for each value followed by one, two, and three zeros, and /* generate crc for each value followed by one, two, and three zeros,
then the byte reversal of those as well as the first table */ and then the byte reversal of those as well as the first table */
for (n = 0; n < 256; n++) { for (n = 0; n < 256; n++) {
c = crc_table[0][n]; c = crc_table[0][n];
crc_table[4][n] = REV(c); crc_table[4][n] = REV(c);
@ -127,6 +142,12 @@ local void make_crc_table()
#endif /* BYFOUR */ #endif /* BYFOUR */
crc_table_empty = 0; crc_table_empty = 0;
}
else { /* not first */
/* wait for the other guy to finish (not efficient, but rare) */
while (crc_table_empty)
;
}
#ifdef MAKECRCH #ifdef MAKECRCH
/* write out CRC tables to crc32.h */ /* write out CRC tables to crc32.h */
@ -180,7 +201,8 @@ local void write_table(out, table)
const unsigned long FAR * ZEXPORT get_crc_table() const unsigned long FAR * ZEXPORT get_crc_table()
{ {
#ifdef DYNAMIC_CRC_TABLE #ifdef DYNAMIC_CRC_TABLE
if (crc_table_empty) make_crc_table(); if (crc_table_empty)
make_crc_table();
#endif /* DYNAMIC_CRC_TABLE */ #endif /* DYNAMIC_CRC_TABLE */
return (const unsigned long FAR *)crc_table; return (const unsigned long FAR *)crc_table;
} }

View file

@ -434,6 +434,9 @@ void FAR *out_desc;
} }
} }
/* handle error breaks in while */
if (state->mode == BAD) break;
/* build code tables */ /* build code tables */
state->next = state->codes; state->next = state->codes;
state->lencode = (code const FAR *)(state->next); state->lencode = (code const FAR *)(state->next);

View file

@ -1,5 +1,5 @@
/* inffast.c -- fast decoding /* inffast.c -- fast decoding
* Copyright (C) 1995-2003 Mark Adler * Copyright (C) 1995-2004 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -19,7 +19,7 @@
- none - none
No measurable difference: No measurable difference:
- Pentium III (Anderson) - Pentium III (Anderson)
- 68060 (Nikl) - M68060 (Nikl)
*/ */
#ifdef POSTINC #ifdef POSTINC
# define OFF 0 # define OFF 0

View file

@ -109,6 +109,7 @@ z_streamp strm;
state = (struct inflate_state FAR *)strm->state; state = (struct inflate_state FAR *)strm->state;
strm->total_in = strm->total_out = state->total = 0; strm->total_in = strm->total_out = state->total = 0;
strm->msg = Z_NULL; strm->msg = Z_NULL;
strm->adler = 1; /* to support ill-conceived Java test suite */
state->mode = HEAD; state->mode = HEAD;
state->last = 0; state->last = 0;
state->havedict = 0; state->havedict = 0;
@ -861,6 +862,9 @@ int flush;
} }
} }
/* handle error breaks in while */
if (state->mode == BAD) break;
/* build code tables */ /* build code tables */
state->next = state->codes; state->next = state->codes;
state->lencode = (code const FAR *)(state->next); state->lencode = (code const FAR *)(state->next);

View file

@ -1,5 +1,5 @@
/* inftrees.c -- generate Huffman trees for efficient decoding /* inftrees.c -- generate Huffman trees for efficient decoding
* Copyright (C) 1995-2003 Mark Adler * Copyright (C) 1995-2004 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -9,7 +9,7 @@
#define MAXBITS 15 #define MAXBITS 15
const char inflate_copyright[] = const char inflate_copyright[] =
" inflate 1.2.1 Copyright 1995-2003 Mark Adler "; " inflate 1.2.2 Copyright 1995-2004 Mark Adler ";
/* /*
If you use the zlib library in a product, an acknowledgment is welcome If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot in the documentation of your product. If for some reason you cannot
@ -62,7 +62,7 @@ unsigned short FAR *work;
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
static const unsigned short lext[31] = { /* Length codes 257..285 extra */ static const unsigned short lext[31] = { /* Length codes 257..285 extra */
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 76, 66}; 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 199, 198};
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
@ -114,7 +114,15 @@ unsigned short FAR *work;
for (max = MAXBITS; max >= 1; max--) for (max = MAXBITS; max >= 1; max--)
if (count[max] != 0) break; if (count[max] != 0) break;
if (root > max) root = max; if (root > max) root = max;
if (max == 0) return -1; /* no codes! */ if (max == 0) { /* no symbols to code at all */
this.op = (unsigned char)64; /* invalid code marker */
this.bits = (unsigned char)1;
this.val = (unsigned short)0;
*(*table)++ = this; /* make a table to force an error */
*(*table)++ = this;
*bits = 1;
return 0; /* no symbols, but wait for decoding to report error */
}
for (min = 1; min <= MAXBITS; min++) for (min = 1; min <= MAXBITS; min++)
if (count[min] != 0) break; if (count[min] != 0) break;
if (root < min) root = min; if (root < min) root = min;
@ -295,7 +303,6 @@ unsigned short FAR *work;
drop = 0; drop = 0;
len = root; len = root;
next = *table; next = *table;
curr = root;
this.bits = (unsigned char)len; this.bits = (unsigned char)len;
} }

View file

@ -1,5 +1,5 @@
/* zconf.h -- configuration of the zlib compression library /* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995-2003 Jean-loup Gailly. * Copyright (C) 1995-2004 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -23,15 +23,17 @@
# define deflateSetDictionary z_deflateSetDictionary # define deflateSetDictionary z_deflateSetDictionary
# define deflateCopy z_deflateCopy # define deflateCopy z_deflateCopy
# define deflateReset z_deflateReset # define deflateReset z_deflateReset
# define deflatePrime z_deflatePrime
# define deflateParams z_deflateParams # define deflateParams z_deflateParams
# define deflateBound z_deflateBound # define deflateBound z_deflateBound
# define deflatePrime z_deflatePrime
# define inflateInit2_ z_inflateInit2_ # define inflateInit2_ z_inflateInit2_
# define inflateSetDictionary z_inflateSetDictionary # define inflateSetDictionary z_inflateSetDictionary
# define inflateSync z_inflateSync # define inflateSync z_inflateSync
# define inflateSyncPoint z_inflateSyncPoint # define inflateSyncPoint z_inflateSyncPoint
# define inflateCopy z_inflateCopy # define inflateCopy z_inflateCopy
# define inflateReset z_inflateReset # define inflateReset z_inflateReset
# define inflateBack z_inflateBack
# define inflateBackEnd z_inflateBackEnd
# define compress z_compress # define compress z_compress
# define compress2 z_compress2 # define compress2 z_compress2
# define compressBound z_compressBound # define compressBound z_compressBound
@ -39,6 +41,7 @@
# define adler32 z_adler32 # define adler32 z_adler32
# define crc32 z_crc32 # define crc32 z_crc32
# define get_crc_table z_get_crc_table # define get_crc_table z_get_crc_table
# define zError z_zError
# define Byte z_Byte # define Byte z_Byte
# define uInt z_uInt # define uInt z_uInt
@ -293,7 +296,7 @@ typedef uLong FAR uLongf;
#endif #endif
#if defined(__OS400__) #if defined(__OS400__)
#define NO_vsnprintf # define NO_vsnprintf
#endif #endif
#if defined(__MVS__) #if defined(__MVS__)

View file

@ -1,7 +1,7 @@
/* zlib.h -- interface of the 'zlib' general purpose compression library /* zlib.h -- interface of the 'zlib' general purpose compression library
version 1.2.1, November 17th, 2003 version 1.2.2, October 3rd, 2004
Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler Copyright (C) 1995-2004 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
@ -37,8 +37,8 @@
extern "C" { extern "C" {
#endif #endif
#define ZLIB_VERSION "1.2.1" #define ZLIB_VERSION "1.2.2"
#define ZLIB_VERNUM 0x1210 #define ZLIB_VERNUM 0x1220
/* /*
The 'zlib' compression library provides in-memory compression and The 'zlib' compression library provides in-memory compression and
@ -53,24 +53,22 @@ extern "C" {
application must provide more input and/or consume the output application must provide more input and/or consume the output
(providing more output space) before each call. (providing more output space) before each call.
The compressed data format used by the in-memory functions is the zlib The compressed data format used by default by the in-memory functions is
format, which is a zlib wrapper documented in RFC 1950, wrapped around a the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
deflate stream, which is itself documented in RFC 1951. around a deflate stream, which is itself documented in RFC 1951.
The library also supports reading and writing files in gzip (.gz) format The library also supports reading and writing files in gzip (.gz) format
with an interface similar to that of stdio using the functions that start with an interface similar to that of stdio using the functions that start
with "gz". The gzip format is different from the zlib format. gzip is a with "gz". The gzip format is different from the zlib format. gzip is a
gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
This library can optionally read and write gzip streams in memory as well.
The zlib format was designed to be compact and fast for use in memory The zlib format was designed to be compact and fast for use in memory
and on communications channels. The gzip format was designed for single- and on communications channels. The gzip format was designed for single-
file compression on file systems, has a larger header than zlib to maintain file compression on file systems, has a larger header than zlib to maintain
directory information, and uses a different, slower check method than zlib. directory information, and uses a different, slower check method than zlib.
This library does not provide any functions to write gzip files in memory.
However such functions could be easily written using zlib's deflate function,
the documentation in the gzip RFC, and the examples in gzio.c.
The library does not install any signal handler. The decoder checks The library does not install any signal handler. The decoder checks
the consistency of the compressed data, so the library should never the consistency of the compressed data, so the library should never
crash even in case of corrupted input. crash even in case of corrupted input.
@ -401,7 +399,7 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
because Z_BLOCK is used. because Z_BLOCK is used.
If a preset dictionary is needed after this call (see inflateSetDictionary If a preset dictionary is needed after this call (see inflateSetDictionary
below), inflate sets strm-adler to the adler32 checksum of the dictionary below), inflate sets strm->adler to the adler32 checksum of the dictionary
chosen by the compressor and returns Z_NEED_DICT; otherwise it sets chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
strm->adler to the adler32 checksum of all output produced so far (that is, strm->adler to the adler32 checksum of all output produced so far (that is,
total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
@ -478,7 +476,8 @@ ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
16 to windowBits to write a simple gzip header and trailer around the 16 to windowBits to write a simple gzip header and trailer around the
compressed data instead of a zlib wrapper. The gzip header will have no compressed data instead of a zlib wrapper. The gzip header will have no
file name, no extra data, no comment, no modification time (set to zero), file name, no extra data, no comment, no modification time (set to zero),
no header crc, and the operating system will be set to 255 (unknown). no header crc, and the operating system will be set to 255 (unknown). If a
gzip stream is being written, strm->adler is a crc32 instead of an adler32.
The memLevel parameter specifies how much memory should be allocated The memLevel parameter specifies how much memory should be allocated
for the internal compression state. memLevel=1 uses minimum memory but for the internal compression state. memLevel=1 uses minimum memory but
@ -649,7 +648,8 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
windowBits can also be greater than 15 for optional gzip decoding. Add windowBits can also be greater than 15 for optional gzip decoding. Add
32 to windowBits to enable zlib and gzip decoding with automatic header 32 to windowBits to enable zlib and gzip decoding with automatic header
detection, or add 16 to decode only the gzip format (the zlib format will detection, or add 16 to decode only the gzip format (the zlib format will
return a Z_DATA_ERROR). return a Z_DATA_ERROR. If a gzip stream is being decoded, strm->adler is
a crc32 instead of an adler32.
inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
@ -1189,7 +1189,7 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_stream FAR *strm, int windowBits,
struct internal_state {int dummy;}; /* hack for buggy compilers */ struct internal_state {int dummy;}; /* hack for buggy compilers */
#endif #endif
ZEXTERN const char * ZEXPORT zError OF((int err)); ZEXTERN const char * ZEXPORT zError OF((int));
ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z));
ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void));

View file

@ -189,9 +189,14 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
# define NO_vsnprintf # define NO_vsnprintf
# endif # endif
#endif #endif
#ifdef VMS
# define NO_vsnprintf
#endif
#ifdef HAVE_STRERROR #ifdef HAVE_STRERROR
# ifndef VMS
extern char *strerror OF((int)); extern char *strerror OF((int));
# endif
# define zstrerror(errnum) strerror(errnum) # define zstrerror(errnum) strerror(errnum)
#else #else
# define zstrerror(errnum) "" # define zstrerror(errnum) ""