Собственно, функция, которая получает сабж (любой код можно оптимизировать, не забывайте):
#include <stdio.h>
#include <stdlib.h>
//---------------------------------------------------------------------------
// Функция, которая будет вызываться для каждого файла в архиве
typedef void (*FLAMER_ARJ_PROC)(const char* FileName, unsigned int CompressedSize, unsigned int UnCompressedSize);
//---------------------------------------------------------------------------
#pragma pack(push,1) // выравнивание на границу 1 байт
typedef struct {
unsigned short hID; // header id (main and local file) = 0x60 0xEA
unsigned short bSize; // basic header size
unsigned char fhSize; // first_hdr_size
unsigned char vNumber; // archiver version number
unsigned char vntExtract; // minimum archiver version to extract
unsigned char hostOS; // host OS
unsigned char aFlags; // arj flags
unsigned char secVersion; // security version
unsigned char fType; // file type (must equal 2)
unsigned char reserved; // reserved
unsigned int arcDateTime; // date time when original archive was created
unsigned int arcModified; // date time when archive was last modified
unsigned int arcSize; // archive size (currently used only for secured archives)
unsigned int secEnvelope; // security envelope file position
unsigned short fspecPosition; // filespec position in filename
unsigned short envLength; // length in bytes of security envelope data
unsigned char notUsed; // (currently not used)
char* fName; // filename of archive when created (null-terminated string)
char* fComment; // archive comment (null-terminated string)
unsigned int headerCRC; // basic header CRC
unsigned short extHeader; // 1st extended header size (0 if none)
unsigned int exthCRC; // 1st extended header's CRC (not present when 0 extended header size)
}TArjHeader;
#pragma pack(pop) // отмена выравнивания
//---------------------------------------------------------------------------
#define ARJ_HEADER_SIZE 45 // size of arj header
//---------------------------------------------------------------------------
#pragma pack(push,1) // выравнивание на границу 1 байт
typedef struct {
unsigned short hID; // header id (main and local file) = 0x60 0xEA
unsigned short bSize; // basic header size - 0 if end of archive
unsigned char fHdrSize; // first_hdr_size (size up to and including 'extra data')
unsigned char vNumber; // archiver version number
unsigned char vntExtract; // minimum archiver version to extract
unsigned char hostOS; // host OS
unsigned char aFlags; // arj flags
unsigned char cMethod; // compression method
unsigned char fType; // file type (0 = binary, 1 = 7-bit text)
// (3 = directory, 4 = volume label)
unsigned char reserved; // reserved
unsigned int dtModified; // date time modified
unsigned int cSize; // compressed size
unsigned int uSize; // original size
unsigned int fCRC; // original file's CRC
unsigned short fSpecPos; // filespec position in filename
unsigned short fMode; // file access mode
unsigned short hData; // host data (currently not used)
unsigned int extData; // extra data - present if (aFlags & 0x08)!=0
char* fName; // filename (null-terminated string)
char* fComment; // comment (null-terminated string)
unsigned int bhCRC; // basic header CRC
unsigned short extHdrSize; // 1st extended header size (0 if none)
unsigned int extHdrCRC; // 1st extended header's CRC (not present when 0 extended header size)
}TArjFileHeader;
#pragma pack(pop) // отмена выравнивания
//---------------------------------------------------------------------------
#define ARJ_FILE_HEADER_SIZE 50 // size of TArjFileHeader
//---------------------------------------------------------------------------
// прототип функции
bool GetFilesInARJ(const char* FileName,FLAMER_ARJ_PROC pFunc = NULL);
//---------------------------------------------------------------------------
bool GetFilesInARJ(const char* FileName,FLAMER_ARJ_PROC pFunc)
{
FILE* hFile = fopen(FileName, "rb");
if(!hFile) return false;
TArjHeader FArjHeader = {0};
TArjFileHeader FArjFileHeader = {0};
FArjFileHeader.fName = NULL;
if(fread(&FArjHeader,1,34,hFile)!=34) {
fclose(hFile); return false;
}
if(FArjHeader.hID!= 0xEA60 || FArjHeader.fType!=2 ||
FArjHeader.bSize > 2600) { // bad file format
fclose(hFile); return false;
}
char cCh = '1';
// skip archive name
while(cCh!='\0') {
if(fread(&cCh,1,1,hFile)!=1)
break;
}
cCh = '1';
// skip archive comment
while(cCh!='\0') {
if(fread(&cCh,1,1,hFile)!=1)
break;
}
fread(&FArjHeader.headerCRC,1,4,hFile);
fread(&FArjHeader.extHeader,1,2,hFile);
if(FArjHeader.extHeader!=0)
fread(&FArjHeader.exthCRC,1,4,hFile);
while(!feof(hFile)) {
if(FArjFileHeader.fName) {
delete [] FArjFileHeader.fName;
FArjFileHeader.fName = NULL;
}
memset(&FArjFileHeader,0,ARJ_FILE_HEADER_SIZE);
FArjFileHeader.fName = NULL;
FArjFileHeader.fComment = NULL;
if(fread(&FArjFileHeader,1,4,hFile)!=4) {
if(feof(hFile)) break;
else {
if(FArjFileHeader.fName)
delete [] FArjFileHeader.fName;
fclose(hFile); return false;
}
}
if(FArjFileHeader.hID!=0xEA60 || FArjFileHeader.bSize > 2600) {
if(FArjFileHeader.fName)
delete [] FArjFileHeader.fName;
fclose(hFile); return false;
}
if(FArjFileHeader.bSize==0) {
// end of archive
break;
}
fseek(hFile,-4,SEEK_CUR);
if(fread(&FArjFileHeader,1,34,hFile)!=34) {
if(FArjFileHeader.fName)
delete [] FArjFileHeader.fName;
fclose(hFile); return false;
}
if(FArjFileHeader.aFlags & 0x08)
fread(&FArjFileHeader.extData,1,4,hFile);
// read file name
while(1) {
if(fread(&cCh,1,1,hFile)!=1) break;
if(!FArjFileHeader.fName) {
FArjFileHeader.fName = new char[2];
FArjFileHeader.fName[0] = cCh;
FArjFileHeader.fName[1] = '\0';
}
else {
int len = strlen(FArjFileHeader.fName);
char* cNew = new char[len+2];
memset(cNew,0,len+2);
strcpy(cNew,FArjFileHeader.fName);
cNew[len] = cCh;
delete [] FArjFileHeader.fName;
FArjFileHeader.fName = cNew;
}
if(cCh=='\0') break;
}
cCh = '1';
// skip file comment
while(cCh!='\0') {
if(fread(&cCh,1,1,hFile)!=1)
break;
}
fread(&FArjFileHeader.bhCRC,1,4,hFile);
fread(&FArjFileHeader.extHdrSize,1,2,hFile);
if(FArjFileHeader.extHdrSize!=0)
fread(&FArjFileHeader.extHdrCRC,1,4,hFile);
fseek(hFile,FArjFileHeader.cSize,SEEK_CUR);
if((FArjFileHeader.aFlags & 0x10) && FArjFileHeader.fName) { // '/' slashes in file name
for(unsigned int i=0;i<strlen(FArjFileHeader.fName);i++) {
if(FArjFileHeader.fName[i]=='/') FArjFileHeader.fName[i]='\\';
}
}
if(pFunc) pFunc(FArjFileHeader.fName,FArjFileHeader.cSize,FArjFileHeader.uSize);
} // while
if(FArjFileHeader.fName)
delete [] FArjFileHeader.fName;
fclose(hFile);
return true;
}
//---------------------------------------------------------------------------
Пример использования:
//---------------------------------------------------------------------------
void ProgressFunc(const char* FileName, unsigned int CompressedSize, unsigned int UnCompressedSize)
{
printf("%s\t%i\t%i %s", FileName, CompressedSize, UnCompressedSize, "\r\n");
}
//---------------------------------------------------------------------------
int main(int argc, char **argv)
{
GetFilesInARJ("C:\\test.arj",ProgressFunc);
}
//---------------------------------------------------------------------------