65 TZIPFile::TZIPFile() : TArchiveFile()
 
   76 TZIPFile::TZIPFile(
const char *archive, 
const char *member, TFile *file)
 
   77    : TArchiveFile(archive, member, file)
 
   88 Int_t TZIPFile::OpenArchive()
 
   90    if (ReadEndHeader(FindEndHeader()) == -1)
 
   92    return ReadDirectory();
 
   98 Long64_t TZIPFile::FindEndHeader()
 
  100    const Int_t kBUFSIZE = 1024;
 
  101    Long64_t    size = fFile->GetSize();
 
  102    Long64_t    limit = TMath::Min(size, Long64_t(kMAX_VAR_LEN));
 
  103    char        buf[kBUFSIZE+4];
 
  108    for (Long64_t offset = 4; offset < limit; ) {
 
  109       offset = TMath::Min(offset + kBUFSIZE, limit);
 
  111       Long64_t pos = size - offset;
 
  112       Int_t    n = TMath::Min(kBUFSIZE+4, Int_t(offset));
 
  115       if (fFile->ReadBuffer(buf, n)) {
 
  116          Error(
"FindEndHeader", 
"error reading %d bytes at %lld", n, pos);
 
  120       for (Int_t i = n - 4; i > 0; i--)
 
  121          if (buf[i]   == 0x50 && buf[i+1] == 0x4b &&
 
  122              buf[i+2] == 0x05 && buf[i+3] == 0x06) {
 
  127    Error(
"FindEndHeader", 
"did not find end header in %s", fArchiveName.Data());
 
  139 Int_t TZIPFile::ReadEndHeader(Long64_t pos)
 
  141    char buf[kEND_HEADER_SIZE];
 
  145    if (fFile->ReadBuffer(buf, kZIP_MAGIC_LEN) ||
 
  146        Get(buf, kZIP_MAGIC_LEN) != kEND_HEADER_MAGIC) {
 
  147       Error(
"ReadEndHeader", 
"wrong end header magic in %s", fArchiveName.Data());
 
  152    if (fFile->ReadBuffer(buf + kZIP_MAGIC_LEN,  kEND_HEADER_SIZE - kZIP_MAGIC_LEN)) {
 
  153       Error(
"ReadEndHeader", 
"error reading %d end header bytes from %s",
 
  154             kEND_HEADER_SIZE - kZIP_MAGIC_LEN, fArchiveName.Data());
 
  158    UInt_t   disk    = Get(buf + kEND_DISK_OFF,       kEND_DISK_LEN);
 
  159    UInt_t   dirdisk = Get(buf + kEND_DIR_DISK_OFF,   kEND_DIR_DISK_LEN);
 
  160    UInt_t   dhdrs   = Get(buf + kEND_DISK_HDRS_OFF,  kEND_DISK_HDRS_LEN);
 
  161    UInt_t   thdrs   = Get(buf + kEND_TOTAL_HDRS_OFF, kEND_TOTAL_HDRS_LEN);
 
  162    Long64_t dirsz   = Get(buf + kEND_DIR_SIZE_OFF,   kEND_DIR_SIZE_LEN);
 
  163    Long64_t diroff  = Get(buf + kEND_DIR_OFFSET_OFF, kEND_DIR_OFFSET_LEN);
 
  164    Int_t    commlen = Get(buf + kEND_COMMENTLEN_OFF, kEND_COMMENTLEN_LEN);
 
  166    if (disk != 0 || dirdisk != 0) {
 
  167       Error(
"ReadHeader", 
"only single disk archives are supported in %s",
 
  168             fArchiveName.Data());
 
  171    if (dhdrs != thdrs) {
 
  172       Error(
"ReadEndHeader", 
"inconsistency in end header data in %s",
 
  173             fArchiveName.Data());
 
  177    char *comment = 
new char[commlen+1];
 
  178    if (fFile->ReadBuffer(comment, commlen)) {
 
  179       Error(
"ReadEndHeader", 
"error reading %d end header comment bytes from %s",
 
  180             commlen, fArchiveName.Data());
 
  184    comment[commlen] = 
'\0';
 
  187    fDirOffset = fDirPos = diroff;
 
  193    Long64_t recoff = ReadZip64EndLocator(pos - kZIP64_EDL_HEADER_SIZE);
 
  200    if (ReadZip64EndRecord(recoff) < 0)
 
  211 Long64_t TZIPFile::ReadZip64EndLocator(Long64_t pos)
 
  213    char buf[kZIP64_EDL_HEADER_SIZE];
 
  217    if (fFile->ReadBuffer(buf, kZIP_MAGIC_LEN) ||
 
  218        Get(buf, kZIP_MAGIC_LEN) != kZIP64_EDL_HEADER_MAGIC) {
 
  223    if (fFile->ReadBuffer(buf + kZIP_MAGIC_LEN,  kZIP64_EDL_HEADER_SIZE - kZIP_MAGIC_LEN)) {
 
  224       Error(
"ReadZip64EndLocator", 
"error reading %d Zip64 end locator header bytes from %s",
 
  225             kZIP64_EDL_HEADER_SIZE - kZIP_MAGIC_LEN, fArchiveName.Data());
 
  229    UInt_t   dirdisk = Get(  buf + kZIP64_EDL_DISK_OFF,       kZIP64_EDL_DISK_LEN);
 
  230    Long64_t recoff  = Get64(buf + kZIP64_EDL_REC_OFFSET_OFF, kZIP64_EDL_REC_OFFSET_LEN);
 
  231    UInt_t   totdisk = Get(  buf + kZIP64_EDL_TOTAL_DISK_OFF, kZIP64_EDL_TOTAL_DISK_LEN);
 
  233    if (dirdisk != 0 || totdisk != 1) {
 
  234       Error(
"ReadZip64EndLocator", 
"only single disk archives are supported in %s",
 
  235             fArchiveName.Data());
 
  246 Int_t TZIPFile::ReadZip64EndRecord(Long64_t pos)
 
  248    char buf[kZIP64_EDR_HEADER_SIZE];
 
  252    if (fFile->ReadBuffer(buf, kZIP_MAGIC_LEN) ||
 
  253        Get(buf, kZIP_MAGIC_LEN) != kZIP64_EDR_HEADER_MAGIC) {
 
  254       Error(
"ReadZip64EndRecord", 
"no Zip64 end of directory record\n");
 
  259    if (fFile->ReadBuffer(buf + kZIP_MAGIC_LEN,  kZIP64_EDR_HEADER_SIZE - kZIP_MAGIC_LEN)) {
 
  260       Error(
"ReadZip64EndRecord", 
"error reading %d Zip64 end record header bytes from %s",
 
  261             kZIP64_EDR_HEADER_SIZE - kZIP_MAGIC_LEN, fArchiveName.Data());
 
  265    Long64_t dirsz  = Get64(buf + kZIP64_EDR_DIR_SIZE_OFF,   kZIP64_EDR_DIR_SIZE_LEN);
 
  266    Long64_t diroff = Get64(buf + kZIP64_EDR_DIR_OFFSET_OFF, kZIP64_EDR_DIR_OFFSET_LEN);
 
  268    fDirOffset = fDirPos = diroff;
 
  278 Int_t TZIPFile::ReadDirectory()
 
  280    char   buf[kDIR_HEADER_SIZE];
 
  284    fFile->Seek(fDirPos);
 
  285    if (fFile->ReadBuffer(buf, kZIP_MAGIC_LEN) ||
 
  286        (n = Get(buf, kZIP_MAGIC_LEN)) != kDIR_HEADER_MAGIC) {
 
  287       Error(
"ReadDirectory", 
"wrong directory header magic in %s",
 
  288             fArchiveName.Data());
 
  293    for (i = 0; n == kDIR_HEADER_MAGIC; i++) {
 
  295       if (fFile->ReadBuffer(buf + kZIP_MAGIC_LEN, kDIR_HEADER_SIZE - kZIP_MAGIC_LEN)) {
 
  296          Error(
"ReadDirectory", 
"error reading %d directory bytes from %s",
 
  297                kDIR_HEADER_SIZE - kZIP_MAGIC_LEN, fArchiveName.Data());
 
  301       UInt_t   version = Get(buf + kDIR_VREQD_OFF,      kDIR_VREQD_LEN);
 
  302       UInt_t   flags   = Get(buf + kDIR_FLAG_OFF,       kDIR_FLAG_LEN);
 
  303       UInt_t   method  = Get(buf + kDIR_METHOD_OFF,     kDIR_METHOD_LEN);
 
  304       UInt_t   time    = Get(buf + kDIR_DATE_OFF,       kDIR_DATE_LEN);
 
  305       UInt_t   crc32   = Get(buf + kDIR_CRC32_OFF,      kDIR_CRC32_LEN);
 
  306       Long64_t csize   = Get(buf + kDIR_CSIZE_OFF,      kDIR_CSIZE_LEN);
 
  307       Long64_t usize   = Get(buf + kDIR_USIZE_OFF,      kDIR_USIZE_LEN);
 
  308       Int_t    namelen = Get(buf + kDIR_NAMELEN_OFF,    kDIR_NAMELEN_LEN);
 
  309       Int_t    extlen  = Get(buf + kDIR_EXTRALEN_OFF,   kDIR_EXTRALEN_LEN);
 
  310       Int_t    commlen = Get(buf + kDIR_COMMENTLEN_OFF, kDIR_COMMENTLEN_LEN);
 
  311       UInt_t   disk    = Get(buf + kDIR_DISK_START_OFF, kDIR_DISK_START_LEN);
 
  312       UInt_t   iattr   = Get(buf + kDIR_INT_ATTR_OFF,   kDIR_INT_ATTR_LEN);
 
  313       UInt_t   xattr   = Get(buf + kDIR_EXT_ATTR_OFF,   kDIR_EXT_ATTR_LEN);
 
  314       Long64_t offset  = Get(buf + kDIR_ENTRY_POS_OFF,  kDIR_ENTRY_POS_LEN);
 
  317       if (Get(buf + kDIR_MAGIC_OFF, kZIP_MAGIC_LEN) != kDIR_HEADER_MAGIC ||
 
  318           version > kARCHIVE_VERSION ||
 
  320           (method != kSTORED && method != kDEFLATED) ||
 
  326          Error(
"ReadDirectory", 
"inconsistency in directory data in %s",
 
  327                fArchiveName.Data());
 
  331       char *name    = 
new char[namelen+1];
 
  332       char *extra   = 
new char[extlen];
 
  333       char *comment = 
new char[commlen+1];
 
  334       if (fFile->ReadBuffer(name, namelen) ||
 
  335           fFile->ReadBuffer(extra, extlen) ||
 
  336           fFile->ReadBuffer(comment, commlen)) {
 
  337          Error(
"ReadDirectory", 
"error reading additional directory data from %s",
 
  338                fArchiveName.Data());
 
  344       name[namelen]    = 
'\0';
 
  345       comment[commlen] = 
'\0';
 
  348       TZIPMember *m = 
new TZIPMember(name);
 
  352       m->fLevel  = method == kSTORED ? 0
 
  353                                      : (flags & 6)/2 == 0 ? 3  
 
  354                                      : (flags & 6)/2 == 1 ? 9  
 
  355                                      : (flags & 6)/2 == 2 ? 2  
 
  356                                      : (flags & 6)/2 == 3 ? 1  
 
  361       m->fModTime.Set(time, kTRUE);   
 
  362       m->fGlobalLen = extlen;
 
  364       m->fComment   = comment;
 
  367       m->fPosition  = offset;
 
  373       if (DecodeZip64ExtendedExtraField(m) == -1)
 
  377          Info(
"ReadDirectory", 
"%lld  %lld  %s  %s",
 
  378               m->GetDecompressedSize(), m->GetCompressedSize(),
 
  379               m->GetModTime().AsSQLString(), m->GetName());
 
  382       if (fFile->ReadBuffer(buf, kZIP_MAGIC_LEN)) {
 
  383          Error(
"ReadDirectory", 
"error reading %d directory bytes from %s",
 
  384                kZIP_MAGIC_LEN, fArchiveName.Data());
 
  387       n = Get(buf, kZIP_MAGIC_LEN);
 
  391    if (n != kEND_HEADER_MAGIC && n != kZIP64_EDR_HEADER_MAGIC) {
 
  392       Error(
"ReadDirectory", 
"wrong end header magic in %s", fArchiveName.Data());
 
  404 Int_t TZIPFile::ReadMemberHeader(TZIPMember *member)
 
  408    char buf[kENTRY_HEADER_SIZE];
 
  411    fFile->Seek(member->fPosition);
 
  412    if (fFile->ReadBuffer(buf, kZIP_MAGIC_LEN) ||
 
  413        Get(buf, kZIP_MAGIC_LEN) != kENTRY_HEADER_MAGIC) {
 
  414       Error(
"ReadMemberHeader", 
"wrong entry header magic in %s",
 
  415             fArchiveName.Data());
 
  420    if (fFile->ReadBuffer(buf + kZIP_MAGIC_LEN,  kENTRY_HEADER_SIZE - kZIP_MAGIC_LEN)) {
 
  421       Error(
"ReadMemberHeader", 
"error reading %d member header bytes from %s",
 
  422             kENTRY_HEADER_SIZE - kZIP_MAGIC_LEN, fArchiveName.Data());
 
  425    Int_t namelen = Get(buf + kENTRY_NAMELEN_OFF,  kENTRY_NAMELEN_LEN);
 
  426    Int_t extlen  = Get(buf + kENTRY_EXTRALEN_OFF, kENTRY_EXTRALEN_LEN);
 
  428    member->fFilePosition = member->fPosition + kENTRY_HEADER_SIZE +
 
  441 Int_t TZIPFile::DecodeZip64ExtendedExtraField(TZIPMember *m, Bool_t global)
 
  448       buf = (
char *) m->fGlobal;
 
  451       buf = (
char *) m->fLocal;
 
  461       UInt_t   tag  = Get(buf + off + kZIP64_EXTENDED_MAGIC_OFF, kZIP64_EXTENDED_MAGIC_LEN);
 
  462       UInt_t   size = Get(buf + off + kZIP64_EXTENDED_SIZE_OFF,  kZIP64_EXTENDED_SIZE_LEN);
 
  463       if (tag == kZIP64_EXTENDED_MAGIC) {
 
  464          Long64_t usize = Get64(buf + off + kZIP64_EXTENDED_USIZE_OFF,      kZIP64_EXTENDED_USIZE_LEN);
 
  465          Long64_t csize = Get64(buf + off + kZIP64_EXTENTED_CSIZE_OFF,      kZIP64_EXTENDED_CSIZE_LEN);
 
  469             Long64_t offset = Get64(buf + off + kZIP64_EXTENDED_HDR_OFFSET_OFF, kZIP64_EXTENDED_HDR_OFFSET_LEN);
 
  470             m->fPosition = offset;
 
  475       len -= (Int_t)size + kZIP64_EXTENDED_MAGIC_LEN + kZIP64_EXTENDED_MAGIC_LEN;
 
  476       off += (Int_t)size + kZIP64_EXTENDED_MAGIC_LEN + kZIP64_EXTENDED_MAGIC_LEN;
 
  486 Int_t TZIPFile::SetCurrentMember()
 
  490    if (fMemberIndex > -1) {
 
  491       fCurMember = (TZIPMember *) fMembers->At(fMemberIndex);
 
  494       fMemberName = fCurMember->GetName();
 
  496       for (
int i = 0; i < fMembers->GetEntriesFast(); i++) {
 
  497          TZIPMember *m = (TZIPMember *) fMembers->At(i);
 
  498          if (fMemberName == m->fName) {
 
  508    return ReadMemberHeader((TZIPMember *)fCurMember);
 
  514 UInt_t TZIPFile::Get(
const void *buffer, Int_t bytes)
 
  519       Error(
"Get", 
"can not read > 4 byte integers, use Get64");
 
  523    memcpy(&value, buffer, bytes);
 
  525    const UChar_t *buf = 
static_cast<const unsigned char *
>(buffer);
 
  526    for (UInt_t shift = 0; bytes; shift += 8, --bytes, ++buf)
 
  527       value += *buf << shift;
 
  535 ULong64_t TZIPFile::Get64(
const void *buffer, Int_t bytes)
 
  540       Error(
"Get64", 
"bytes must be 8 (asked for %d)", bytes);
 
  545    memcpy(&value, buffer, bytes);
 
  547    const UChar_t *buf = 
static_cast<const unsigned char *
>(buffer);
 
  548    for (UInt_t shift = 0; bytes; shift += 8, --bytes, ++buf)
 
  549       value += *buf << shift;
 
  557 void TZIPFile::Print(Option_t *)
 const 
  564 ClassImp(TZIPMember);
 
  569 TZIPMember::TZIPMember()
 
  585 TZIPMember::TZIPMember(
const char *name)
 
  586    : TArchiveMember(name)
 
  602 TZIPMember::TZIPMember(
const TZIPMember &member)
 
  603    : TArchiveMember(member)
 
  606    fLocalLen  = member.fLocalLen;
 
  608    fGlobalLen = member.fGlobalLen;
 
  609    fCRC32     = member.fCRC32;
 
  610    fAttrInt   = member.fAttrInt;
 
  611    fAttrExt   = member.fAttrExt;
 
  612    fMethod    = member.fMethod;
 
  613    fLevel     = member.fLevel;
 
  616       fLocal = 
new char [fLocalLen];
 
  617       memcpy(fLocal, member.fLocal, fLocalLen);
 
  619    if (member.fGlobal) {
 
  620       fGlobal = 
new char [fGlobalLen];
 
  621       memcpy(fGlobal, member.fGlobal, fGlobalLen);
 
  628 TZIPMember &TZIPMember::operator=(
const TZIPMember &rhs)
 
  631       TArchiveMember::operator=(rhs);
 
  633       delete [] (
char*) fLocal;
 
  634       delete [] (
char*) fGlobal;
 
  637       fLocalLen  = rhs.fLocalLen;
 
  639       fGlobalLen = rhs.fGlobalLen;
 
  641       fAttrInt   = rhs.fAttrInt;
 
  642       fAttrExt   = rhs.fAttrExt;
 
  643       fMethod    = rhs.fMethod;
 
  647          fLocal = 
new char [fLocalLen];
 
  648          memcpy(fLocal, rhs.fLocal, fLocalLen);
 
  651          fGlobal = 
new char [fGlobalLen];
 
  652          memcpy(fGlobal, rhs.fGlobal, fGlobalLen);
 
  661 TZIPMember::~TZIPMember()
 
  663    delete [] (
char*) fLocal;
 
  664    delete [] (
char*) fGlobal;
 
  670 void TZIPMember::Print(Option_t *)
 const 
  672    printf(
"%-20lld", fDsize);
 
  673    printf(
" %s   %s\n", fModTime.AsSQLString(), fName.Data());