#include "TZIPFile.h"
#include "TFile.h"
#include "TObjArray.h"
ClassImp(TZIPFile)
TZIPFile::TZIPFile() : TArchiveFile()
{
   
   fDirPos     = 0;
   fDirSize    = 0;
   fDirOffset  = 0;
}
TZIPFile::TZIPFile(const char *archive, const char *member, TFile *file)
   : TArchiveFile(archive, member, file)
{
   
   
   fDirPos     = 0;
   fDirSize    = 0;
   fDirOffset  = 0;
}
Int_t TZIPFile::OpenArchive()
{
   
   
   if (ReadEndHeader(FindEndHeader()) == -1)
      return -1;
   return ReadDirectory();
}
Long64_t TZIPFile::FindEndHeader()
{
   
   const Int_t kBUFSIZE = 1024;
   Long64_t    size = fFile->GetSize();
   Long64_t    limit = TMath::Min(size, Long64_t(kMAX_VAR_LEN));
   char        buf[kBUFSIZE+4];
   
   
   
   for (Long64_t offset = 4; offset < limit; ) {
      offset = TMath::Min(offset + kBUFSIZE, limit);
      Long64_t pos = size - offset;
      Int_t    n = TMath::Min(kBUFSIZE+4, Int_t(offset));
      fFile->Seek(pos);
      if (fFile->ReadBuffer(buf, n)) {
         Error("FindEndHeader", "error reading %d bytes at %ldd", n, pos);
         return 0;
      }
      for (Int_t i = n - 4; i > 0; i--)
         if (buf[i]   == 0x50 && buf[i+1] == 0x4b &&
             buf[i+2] == 0x05 && buf[i+3] == 0x06) {
            return pos + i;
         }
   }
   Error("FindEndHeader", "did not find end header in %s", fArchiveName.Data());
   return 0;
}
Int_t TZIPFile::ReadEndHeader(Long64_t pos)
{
   
   
   
   
   
   char buf[kEND_HEADER_SIZE];
   
   fFile->Seek(pos);
   if (fFile->ReadBuffer(buf, kZIP_MAGIC_LEN) ||
       Get(buf, kZIP_MAGIC_LEN) != kEND_HEADER_MAGIC) {
      Error("ReadEndHeader", "wrong end header magic in %s", fArchiveName.Data());
      return -1;
   }
   
   if (fFile->ReadBuffer(buf + kZIP_MAGIC_LEN,  kEND_HEADER_SIZE - kZIP_MAGIC_LEN)) {
      Error("ReadEndHeader", "error reading %d end header bytes from %s",
            kEND_HEADER_SIZE - kZIP_MAGIC_LEN, fArchiveName.Data());
      return -1;
   }
   UInt_t   disk    = Get(buf + kEND_DISK_OFF,       kEND_DISK_LEN);
   UInt_t   dirdisk = Get(buf + kEND_DIR_DISK_OFF,   kEND_DIR_DISK_LEN);
   UInt_t   dhdrs   = Get(buf + kEND_DISK_HDRS_OFF,  kEND_DISK_HDRS_LEN);
   UInt_t   thdrs   = Get(buf + kEND_TOTAL_HDRS_OFF, kEND_TOTAL_HDRS_LEN);
   Long64_t diroff  = Get(buf + kEND_DIR_OFFSET_OFF, kEND_DIR_OFFSET_LEN);
   Long64_t dirsz   = Get(buf + kEND_DIR_SIZE_OFF,   kEND_DIR_SIZE_LEN);
   Int_t    commlen = Get(buf + kEND_COMMENTLEN_OFF, kEND_COMMENTLEN_LEN);
   if (disk != 0 || dirdisk != 0 || dhdrs != thdrs || diroff + dirsz != pos) {
      Error("ReadEndHeader", "inconsistency in end header data in %s",
            fArchiveName.Data());
      return -1;
   }
   char *comment = new char[commlen+1];
   if (fFile->ReadBuffer(comment, commlen)) {
      Error("ReadEndHeader", "error reading %d end header comment bytes from %s",
            commlen, fArchiveName.Data());
      return -1;
   }
   comment[commlen] = '\0';
   fComment   = comment;
   fDirOffset = fDirPos = diroff;
   fDirSize   = dirsz;
   delete [] comment;
   return 0;
}
Int_t TZIPFile::ReadDirectory()
{
   
   
   char   buf[kDIR_HEADER_SIZE];
   UInt_t n, i;
   
   fFile->Seek(fDirPos);
   if (fFile->ReadBuffer(buf, kZIP_MAGIC_LEN) ||
       (n = Get(buf, kZIP_MAGIC_LEN)) != kDIR_HEADER_MAGIC) {
      Error("ReadDirectory", "wrong directory header magic in %s",
            fArchiveName.Data());
      return -1;
   }
   
   for (i = 0; n == kDIR_HEADER_MAGIC; i++) {
      
      if (fFile->ReadBuffer(buf + kZIP_MAGIC_LEN, kDIR_HEADER_SIZE - kZIP_MAGIC_LEN)) {
         Error("ReadDirectory", "error reading %d directory bytes from %s",
               kDIR_HEADER_SIZE - kZIP_MAGIC_LEN, fArchiveName.Data());
         return -1;
      }
      UInt_t   version = Get(buf + kDIR_VREQD_OFF,      kDIR_VREQD_LEN);
      UInt_t   flags   = Get(buf + kDIR_FLAG_OFF,       kDIR_FLAG_LEN);
      UInt_t   method  = Get(buf + kDIR_METHOD_OFF,     kDIR_METHOD_LEN);
      UInt_t   time    = Get(buf + kDIR_DATE_OFF,       kDIR_DATE_LEN);
      UInt_t   crc32   = Get(buf + kDIR_CRC32_OFF,      kDIR_CRC32_LEN);
      Long64_t csize   = Get(buf + kDIR_CSIZE_OFF,      kDIR_CSIZE_LEN);
      Long64_t usize   = Get(buf + kDIR_USIZE_OFF,      kDIR_USIZE_LEN);
      Int_t    namelen = Get(buf + kDIR_NAMELEN_OFF,    kDIR_NAMELEN_LEN);
      Int_t    extlen  = Get(buf + kDIR_EXTRALEN_OFF,   kDIR_EXTRALEN_LEN);
      Int_t    commlen = Get(buf + kDIR_COMMENTLEN_OFF, kDIR_COMMENTLEN_LEN);
      UInt_t   disk    = Get(buf + kDIR_DISK_START_OFF, kDIR_DISK_START_LEN);
      UInt_t   iattr   = Get(buf + kDIR_INT_ATTR_OFF,   kDIR_INT_ATTR_LEN);
      UInt_t   xattr   = Get(buf + kDIR_EXT_ATTR_OFF,   kDIR_EXT_ATTR_LEN);
      Long64_t offset  = Get(buf + kDIR_ENTRY_POS_OFF,  kDIR_ENTRY_POS_LEN);
      
      if (Get(buf + kDIR_MAGIC_OFF, kZIP_MAGIC_LEN) != kDIR_HEADER_MAGIC ||
          version > kARCHIVE_VERSION ||
          flags & 8 ||
          (method != kSTORED && method != kDEFLATED) ||
          disk != 0 ||
          csize < 0 ||
          usize < 0 ||
          csize > kMaxInt ||
          usize > kMaxInt) {
         Error("ReadDirectory", "inconsistency in directory data in %s",
               fArchiveName.Data());
         return -1;
      }
      char *name    = new char[namelen+1];
      char *extra   = new char[extlen+1];
      char *comment = new char[commlen+1];
      if (fFile->ReadBuffer(name, namelen) ||
          fFile->ReadBuffer(extra, extlen) ||
          fFile->ReadBuffer(comment, commlen)) {
         Error("ReadDirectory", "error reading additional directory data from %s",
               fArchiveName.Data());
         return -1;
      }
      name[namelen]    = '\0';
      extra[extlen]    = '\0';
      comment[commlen] = '\0';
      
      TZIPMember *m = new TZIPMember(name);
      fMembers->Add(m);
      m->fMethod = method;
      m->fLevel  = method == kSTORED ? 0
                                     : (flags & 6)/2 == 0 ? 3  
                                     : (flags & 6)/2 == 1 ? 9  
                                     : (flags & 6)/2 == 2 ? 2  
                                     : (flags & 6)/2 == 3 ? 1  
                                     : 3;                      
      m->fCsize     = csize;
      m->fDsize     = usize;
      m->fCRC32     = crc32;
      m->fModTime.Set(time, kTRUE);   
      m->fGlobalLen = extlen;
      m->fGlobal    = extra;
      m->fComment   = comment;
      m->fAttrInt   = iattr;
      m->fAttrExt   = xattr;
      m->fPosition  = offset;
      delete [] name;
      delete [] comment;
      
      if (gDebug)
         Info("ReadDirectory", "%lld  %lld  %s  %s",
              m->GetDecompressedSize(), m->GetCompressedSize(),
              m->GetModTime().AsSQLString(), m->GetName());
      
      if (fFile->ReadBuffer(buf, kZIP_MAGIC_LEN)) {
         Error("ReadDirectory", "error reading %d directory bytes from %s",
               kZIP_MAGIC_LEN, fArchiveName.Data());
         return -1;
      }
      n = Get(buf, kZIP_MAGIC_LEN);
   }
   
   if (n != kEND_HEADER_MAGIC) {
      Error("ReadDirectory", "wrong end header magic in %s", fArchiveName.Data());
      return -1;
   }
   return 0;
}
Int_t TZIPFile::ReadMemberHeader(TZIPMember *member)
{
   
   
   
   
   
   char buf[kENTRY_HEADER_SIZE];
   
   fFile->Seek(member->fPosition);
   if (fFile->ReadBuffer(buf, kZIP_MAGIC_LEN) ||
       Get(buf, kZIP_MAGIC_LEN) != kENTRY_HEADER_MAGIC) {
      Error("ReadMemberHeader", "wrong entry header magic in %s",
            fArchiveName.Data());
      return -1;
   }
   
   if (fFile->ReadBuffer(buf + kZIP_MAGIC_LEN,  kENTRY_HEADER_SIZE - kZIP_MAGIC_LEN)) {
      Error("ReadMemberHeader", "error reading %d member header bytes from %s",
            kENTRY_HEADER_SIZE - kZIP_MAGIC_LEN, fArchiveName.Data());
      return -1;
   }
   Int_t namelen = Get(buf + kENTRY_NAMELEN_OFF,  kENTRY_NAMELEN_LEN);
   Int_t extlen  = Get(buf + kENTRY_EXTRALEN_OFF, kENTRY_EXTRALEN_LEN);
   member->fFilePosition = member->fPosition + kENTRY_HEADER_SIZE +
                           namelen + extlen;
   return 0;
}
Int_t TZIPFile::SetCurrentMember()
{
   
   
   fCurMember = 0;
   if (fMemberIndex > -1) {
      fCurMember = (TZIPMember *) fMembers->At(fMemberIndex);
      if (!fCurMember)
         return -1;
      fMemberName = fCurMember->GetName();
   } else {
      for (int i = 0; i < fMembers->GetEntriesFast(); i++) {
         TZIPMember *m = (TZIPMember *) fMembers->At(i);
         if (fMemberName == m->fName) {
            fCurMember   = m;
            fMemberIndex = i;
            break;
         }
      }
      if (!fCurMember)
         return -1;
   }
   return ReadMemberHeader((TZIPMember *)fCurMember);
}
UInt_t TZIPFile::Get(const void *buffer, Int_t bytes)
{
   
   UInt_t value = 0;
#ifdef R__BYTESWAP
   memcpy(&value, buffer, bytes);
#else
   const UChar_t *buf = static_cast<const unsigned char *>(buffer);
   for (UInt_t shift = 0; bytes; shift += 8, --bytes, ++buf)
      value += *buf << shift;
#endif
   return value;
}
void TZIPFile::Print(Option_t *) const
{
   
   if (fMembers)
      fMembers->Print();
}
ClassImp(TZIPMember)
TZIPMember::TZIPMember()
{
   
   fLocal     = 0;
   fLocalLen  = 0;
   fGlobal    = 0;
   fGlobalLen = 0;
   fCRC32     = 0;
   fAttrInt   = 0;
   fAttrExt   = 0;
   fMethod    = 0;
   fLevel     = 0;
}
TZIPMember::TZIPMember(const char *name)
   : TArchiveMember(name)
{
   
   fLocal     = 0;
   fLocalLen  = 0;
   fGlobal    = 0;
   fGlobalLen = 0;
   fCRC32     = 0;
   fAttrInt   = 0;
   fAttrExt   = 0;
   fMethod    = 0;
   fLevel     = 0;
}
TZIPMember::TZIPMember(const TZIPMember &member)
   : TArchiveMember(member)
{
   
   fLocal     = 0;
   fLocalLen  = member.fLocalLen;
   fGlobal    = 0;
   fGlobalLen = member.fGlobalLen;
   fCRC32     = member.fCRC32;
   fAttrInt   = member.fAttrInt;
   fAttrExt   = member.fAttrExt;
   fMethod    = member.fMethod;
   fLevel     = member.fLevel;
   if (member.fLocal) {
      fLocal = new char [fLocalLen];
      memcpy(fLocal, member.fLocal, fLocalLen);
   }
   if (member.fGlobal) {
      fGlobal = new char [fGlobalLen];
      memcpy(fGlobal, member.fGlobal, fGlobalLen);
   }
}
TZIPMember &TZIPMember::operator=(const TZIPMember &rhs)
{
   
   if (this != &rhs) {
      TArchiveMember::operator=(rhs);
      delete [] (char*) fLocal;
      delete [] (char*) fGlobal;
      fLocal     = 0;
      fLocalLen  = rhs.fLocalLen;
      fGlobal    = 0;
      fGlobalLen = rhs.fGlobalLen;
      fCRC32     = rhs.fCRC32;
      fAttrInt   = rhs.fAttrInt;
      fAttrExt   = rhs.fAttrExt;
      fMethod    = rhs.fMethod;
      fLevel     = rhs.fLevel;
      if (rhs.fLocal) {
         fLocal = new char [fLocalLen];
         memcpy(fLocal, rhs.fLocal, fLocalLen);
      }
      if (rhs.fGlobal) {
         fGlobal = new char [fGlobalLen];
         memcpy(fGlobal, rhs.fGlobal, fGlobalLen);
      }
   }
   return *this;
}
TZIPMember::~TZIPMember()
{
   
   delete [] (char*) fLocal;
   delete [] (char*) fGlobal;
}
void TZIPMember::Print(Option_t *) const
{
   
   
   
   printf("%-20lld", fDsize);
   printf(" %s   %s\n", fModTime.AsSQLString(), fName.Data());
}
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.