00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00014
00021 #if !defined(ZIPARCHIVE_ZIPSTORAGE_DOT_H)
00022 #define ZIPARCHIVE_ZIPSTORAGE_DOT_H
00023
00024 #if _MSC_VER > 1000
00025 #pragma once
00026 #if defined ZIP_HAS_DLL
00027 #pragma warning (push)
00028 #pragma warning( disable : 4251 ) // needs to have dll-interface to be used by clients of class
00029 #endif
00030 #endif
00031
00032 #include "ZipFile.h"
00033 #include "ZipAutoBuffer.h"
00034 #include "ZipString.h"
00035 #include "ZipMemFile.h"
00036 #include "ZipExport.h"
00037 #include "ZipCallback.h"
00038 #include "BitFlag.h"
00039 #include "ZipSplitNamesHandler.h"
00040 #include "ZipException.h"
00041 #include "ZipCollections.h"
00042
00046 class ZIP_API CZipStorage
00047 {
00048 friend class CZipArchive;
00049 friend class CZipCentralDir;
00050 public:
00054 enum State
00055 {
00056 stateOpened = 0x0001,
00057 stateReadOnly = 0x0002,
00058 stateAutoClose = 0x0004,
00059 stateExisting = 0x0008,
00060 stateSegmented = 0x0010,
00061 stateSplit = stateSegmented | 0x0020,
00062 stateBinarySplit = stateSplit | 0x0040,
00063 stateSpan = stateSegmented | 0x0080
00064 };
00065
00072 enum SeekType
00073 {
00074 seekFromBeginning,
00075 seekFromEnd,
00076
00080 seekCurrent
00081 };
00082 CZipStorage();
00083 virtual ~CZipStorage();
00084
00085 void Initialize();
00090 void Open(CZipAbstractFile& af, int iMode, bool bAutoClose);
00091
00097 void Open(LPCTSTR lpszPathName, int iMode, ZIP_SIZE_TYPE uVolumeSize);
00098
00099
00105 void FinalizeSegm();
00106
00107
00114 void UpdateSegmMode(ZIP_VOLUME_TYPE uLastVolume);
00115
00126 ZIP_SIZE_TYPE AssureFree(ZIP_SIZE_TYPE uNeeded);
00127
00142 void Write(const void *pBuf, DWORD iSize, bool bAtOnce);
00143
00150 ZIP_SIZE_TYPE GetOccupiedSpace() const
00151 {
00152 return ZIP_SIZE_TYPE(m_pFile->GetLength() + m_uBytesInWriteBuffer);
00153 }
00154
00158 bool IsClosed(bool bArchive) const
00159 {
00160 if (bArchive)
00161 return !m_state.IsSetAny(stateOpened);
00162 else
00163
00164 return !m_pFile || m_state.IsSetAny(stateAutoClose) && m_pFile->IsClosed();
00165 }
00166
00181 DWORD Read(void* pBuf, DWORD iSize, bool bAtOnce);
00182
00193 ZIP_SIZE_TYPE GetPosition() const
00194 {
00195 ZIP_SIZE_TYPE uPos = (ZIP_SIZE_TYPE)(m_pFile->GetPosition()) + m_uBytesInWriteBuffer;
00196 if (m_uCurrentVolume == 0)
00197 uPos -= m_uBytesBeforeZip;
00198 else if (IsBinarySplit())
00199 {
00200 ZIP_VOLUME_TYPE uVolume = m_uCurrentVolume;
00201 ASSERT(m_pCachedSizes->GetSize() > (ZIP_ARRAY_SIZE_TYPE)(uVolume - 1));
00202 do
00203 {
00204 uVolume--;
00205 uPos += (ZIP_SIZE_TYPE)m_pCachedSizes->GetAt((ZIP_ARRAY_SIZE_TYPE)uVolume);
00206 }
00207 while (uVolume > 0);
00208 }
00209 return uPos;
00210 }
00211
00212
00217 void Flush();
00218
00219
00223 void FlushFile()
00224 {
00225 if (!IsReadOnly())
00226 m_pFile->Flush();
00227 }
00228
00229 void FlushBuffers()
00230 {
00231 Flush();
00232 FlushFile();
00233 }
00234
00242 void NextVolume(ZIP_SIZE_TYPE uNeeded);
00243
00244
00248 ZIP_VOLUME_TYPE GetCurrentVolume() const {return m_uCurrentVolume;}
00249
00250
00257 void ChangeVolume(ZIP_VOLUME_TYPE uNumber);
00258
00262 void ChangeVolume()
00263 {
00264 ChangeVolume((ZIP_VOLUME_TYPE)(m_uCurrentVolume + 1));
00265 }
00266
00270 void ChangeVolumeDec()
00271 {
00272 if (m_uCurrentVolume == 0)
00273 ThrowError(CZipException::badZipFile);
00274 ChangeVolume((ZIP_VOLUME_TYPE)(m_uCurrentVolume - 1));
00275 }
00276
00283 bool IsSplit() const
00284 {
00285 return m_state.IsSetAll(stateSplit);
00286 }
00287
00294 bool IsBinarySplit() const
00295 {
00296 return m_state.IsSetAll(stateBinarySplit);
00297 }
00298
00305 bool IsRegularSplit() const
00306 {
00307 return m_state.IsSetAll(stateSplit) && !m_state.IsSetAll(stateBinarySplit);
00308 }
00309
00316 bool IsSpanned() const
00317 {
00318 return m_state.IsSetAll(stateSpan);
00319 }
00320
00324 bool IsReadOnly() const
00325 {
00326 return m_state.IsSetAny(stateReadOnly) || IsExistingSegmented();
00327 }
00328
00335 bool IsExistingSegmented() const
00336 {
00337 return m_state.IsSetAll(stateSegmented | stateExisting);
00338 }
00339
00346 bool IsNewSegmented() const
00347 {
00348 return m_state.IsSetAny(stateSegmented) && !IsExisting();
00349 }
00350
00357 bool IsSegmented() const
00358 {
00359 return m_state.IsSetAny(stateSegmented);
00360 }
00361
00368 bool IsExisting() const
00369 {
00370 return m_state.IsSetAny(stateExisting);
00371 }
00372
00381 bool SetSplitNamesHandler(CZipSplitNamesHandler* pNames, bool bAutoDelete)
00382 {
00383 if (m_state != 0)
00384 {
00385 ZIPTRACE("%s(%i) : The archive is already opened.\n");
00386 return false;
00387 }
00388 ClearSplitNames();
00389 m_pSplitNames = pNames;
00390 m_bAutoDeleteSplitNames = bAutoDelete;
00391 return true;
00392 }
00393
00402 CZipSplitNamesHandler* GetSplitNamesHandler()
00403 {
00404 return m_pSplitNames;
00405 }
00406
00415 const CZipSplitNamesHandler* GetSplitNamesHandler() const
00416 {
00417 return m_pSplitNames;
00418 }
00419
00430 ULONGLONG Seek(ULONGLONG lOff, SeekType iSeekType = seekFromBeginning);
00431
00442 void SeekInBinary(ZIP_FILE_SIZE lOff, bool bSeekToBegin = false);
00443
00450 ZIP_SIZE_TYPE VolumeLeft() const;
00451
00465 CZipString Close(bool bWrite, bool bGetLastVolumeName);
00466
00470 CZipAbstractFile* m_pFile;
00471
00475 static char m_gszExtHeaderSignat[];
00476
00477 protected:
00478
00485 ZIP_SIZE_TYPE GetLastDataOffset()
00486 {
00487 return (ZIP_SIZE_TYPE)m_pFile->GetLength() - m_uBytesBeforeZip;
00488 }
00489
00503 ZIP_FILE_USIZE LocateSignature(char* szSignature, ZIP_SIZE_TYPE uMaxDepth);
00504
00505
00509 void EmptyWriteBuffer()
00510 {
00511 m_uBytesInWriteBuffer = 0;
00512 }
00513
00529 bool OpenFile(LPCTSTR lpszName, UINT uFlags, bool bThrow = true);
00530
00537 CZipString RenameLastFileInSplitArchive();
00538
00549 void WriteInternalBuffer(const char *pBuf, DWORD uSize);
00550
00557 ZIP_SIZE_TYPE GetFreeVolumeSpace() const;
00558
00576 void CallCallback(ZIP_SIZE_TYPE uNeeded, int iCode, CZipString szTemp);
00577
00581 CZipString ChangeSplitRead();
00582
00586 CZipString ChangeSpannedRead();
00587
00594 DWORD GetFreeInBuffer() const {return m_pWriteBuffer.GetSize() - m_uBytesInWriteBuffer;}
00595
00603 ZIP_SIZE_TYPE m_uSplitData;
00604
00608 DWORD m_uBytesInWriteBuffer;
00609
00615 ZIP_SIZE_TYPE m_uCurrentVolSize;
00616
00620 CZipAutoBuffer m_pWriteBuffer;
00621
00626 ZIP_SIZE_TYPE m_uBytesWritten;
00627
00632 ZIP_VOLUME_TYPE m_uCurrentVolume;
00633
00639 ZIP_SIZE_TYPE m_uBytesBeforeZip;
00640
00641
00648 int m_iWriteBufferSize;
00649
00656 int m_iLocateBufferSize;
00657
00665 CZipSegmCallback* m_pSpanChangeVolumeFunc;
00666
00674 CZipSegmCallback* m_pSplitChangeVolumeFunc;
00675
00676 private:
00677 ZIP_FILE_USIZE LocateSignature(char* szSignature, ZIP_SIZE_TYPE uMaxDepth, int& leftToFind, bool& found, ZIP_FILE_USIZE uFileLength);
00678 CZipString GetSplitVolumeName(bool bLast)
00679 {
00680 if (m_pSplitNames == NULL)
00681 {
00682 ThrowError(CZipException::genericError);
00683 }
00684 int flags = bLast ? CZipSplitNamesHandler::flLast : CZipSplitNamesHandler::flNone;
00685 if (IsExisting())
00686 flags |= CZipSplitNamesHandler::flExisting;
00687 return m_pSplitNames->GetVolumeName(m_szArchiveName, (ZIP_VOLUME_TYPE)(m_uCurrentVolume + 1), flags);
00688 }
00689
00690 void ClearSplitNames()
00691 {
00692 if (m_pSplitNames)
00693 {
00694 if (m_bAutoDeleteSplitNames)
00695 delete m_pSplitNames;
00696 m_pSplitNames = NULL;
00697 m_bAutoDeleteSplitNames = false;
00698 }
00699 }
00700
00701 void ClearCachedSizes()
00702 {
00703 if (m_pCachedSizes)
00704 {
00705 delete m_pCachedSizes;
00706 m_pCachedSizes = NULL;
00707 }
00708 }
00709
00710 void EnsureSplitNames()
00711 {
00712 if (IsSplit())
00713 {
00714 if (m_pSplitNames == NULL)
00715 {
00716 m_bAutoDeleteSplitNames = true;
00717 if (m_state.IsSetAll(stateBinarySplit))
00718 m_pSplitNames = new CZipBinSplitNamesHandler();
00719 else
00720 m_pSplitNames = new CZipRegularSplitNamesHandler();
00721 }
00722 m_pSplitNames->Initialize(m_szArchiveName);
00723 }
00724 }
00725
00726 ZIP_FILE_USIZE GetCachedSize(ZIP_VOLUME_TYPE uVolume)
00727 {
00728 ASSERT(m_pCachedSizes);
00729 if (m_pCachedSizes->GetSize() > (ZIP_ARRAY_SIZE_TYPE)uVolume)
00730 return m_pCachedSizes->GetAt((ZIP_ARRAY_SIZE_TYPE)uVolume);
00731 ThrowError(CZipException::genericError);
00732
00733 return 0;
00734 }
00735
00736 void CacheSizes();
00737
00738 ZipArchiveLib::CBitFlag m_state;
00739 CZipSegmCallback* m_pChangeVolumeFunc;
00740 CZipString m_szArchiveName;
00741 CZipFile m_internalfile;
00742 CZipSplitNamesHandler* m_pSplitNames;
00743 CZipArray<ZIP_FILE_USIZE>* m_pCachedSizes;
00744 bool m_bAutoDeleteSplitNames;
00745 static const ZIP_FILE_USIZE SignatureNotFound;
00746 void ThrowError(int err) const;
00747 };
00748
00749 #if (_MSC_VER > 1000) && (defined ZIP_HAS_DLL)
00750 #pragma warning (pop)
00751 #endif
00752
00753
00754 #endif // !defined(ZIPARCHIVE_ZIPSTORAGE_DOT_H)