SRC: Список файлов в ARJ-архиве
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 30.08.02 07:18
Оценка: 12 (2)
Собственно, функция, которая получает сабж (любой код можно оптимизировать, не забывайте):


#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);
}
//---------------------------------------------------------------------------
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.