1 #ifndef UTIL_COMPRESS__ARCHIVE___HPP 2 #define UTIL_COMPRESS__ARCHIVE___HPP 3 4 /* $Id: archive_.hpp 575071 2018-11-23 13:23:52Z ivanov $ 5 * =========================================================================== 6 * 7 * PUBLIC DOMAIN NOTICE 8 * National Center for Biotechnology Information 9 * 10 * This software/database is a "United States Government Work" under the 11 * terms of the United States Copyright Act. It was written as part of 12 * the author's official duties as a United States Government employee and 13 * thus cannot be copyrighted. This software/database is freely available 14 * to the public for use. The National Library of Medicine and the U.S. 15 * Government have not placed any restriction on its use or reproduction. 16 * 17 * Although all reasonable efforts have been taken to ensure the accuracy 18 * and reliability of the software and data, the NLM and the U.S. 19 * Government do not and cannot warrant the performance or results that 20 * may be obtained by using this software or data. The NLM and the U.S. 21 * Government disclaim all warranties, express or implied, including 22 * warranties of performance, merchantability or fitness for any particular 23 * purpose. 24 * 25 * Please cite the author in any work or product based on this material. 26 * 27 * =========================================================================== 28 * 29 * Authors: Vladimir Ivanov, Anton Lavrentiev 30 * 31 * File Description: 32 * Compression archive API - Common base classes and interfaces. 33 * 34 */ 35 36 /// @file archive_.hpp 37 /// Archive API. 38 39 #include <corelib/ncbifile.hpp> 40 #include <util/compress/compress.hpp> 41 42 43 /** @addtogroup Compression 44 * 45 * @{ 46 */ 47 48 49 BEGIN_NCBI_SCOPE 50 51 52 ///////////////////////////////////////////////////////////////////////////// 53 /// 54 /// CArchiveException -- 55 /// 56 /// Define exceptions generated by the API. 57 /// CArchiveException inherits its basic functionality from CCoreException 58 /// and defines additional error codes for archive operations. 59 60 class NCBI_XUTIL_EXPORT CArchiveException : public CCoreException 61 { 62 public: 63 /// Error types that file operations can generate. 64 enum EErrCode { 65 eUnsupported, 66 eMemory, 67 eUnsupportedEntryType, 68 eBadName, 69 eCreate, 70 eOpen, 71 eClose, 72 eList, 73 eExtract, 74 eAppend, 75 eWrite, 76 eBackup, 77 eRestoreAttrs 78 }; 79 80 /// Translate from an error code value to its string representation. GetErrCodeString(void) const81 virtual const char* GetErrCodeString(void) const override 82 { 83 switch (GetErrCode()) { 84 case eUnsupported: return "eUnsupported"; 85 case eMemory: return "eMemory"; 86 case eUnsupportedEntryType: return "eUnsupportedEntryType"; 87 case eBadName: return "eBadName"; 88 case eCreate: return "eCreate"; 89 case eOpen: return "eOpen"; 90 case eClose: return "eClose"; 91 case eList: return "eList"; 92 case eExtract: return "eExtract"; 93 case eAppend: return "eAppend"; 94 case eWrite: return "eWrite"; 95 case eBackup: return "eBackup"; 96 case eRestoreAttrs: return "eRestoreAttrs"; 97 default: return CException::GetErrCodeString(); 98 } 99 } 100 // Standard exception boilerplate code. 101 NCBI_EXCEPTION_DEFAULT(CArchiveException, CCoreException); 102 }; 103 104 105 ////////////////////////////////////////////////////////////////////////////// 106 /// 107 /// CArchiveEntryInfo class 108 /// 109 /// Information about an archive entry. 110 111 class NCBI_XUTIL_EXPORT CArchiveEntryInfo 112 { 113 public: 114 /// Archive entry type (the same as directory entry type). 115 typedef CDirEntry::EType EType; 116 117 // Constructor. CArchiveEntryInfo()118 CArchiveEntryInfo() 119 { 120 Reset(); 121 } 122 Reset(void)123 void Reset(void) 124 { 125 memset(&m_Stat, 0, sizeof(m_Stat)); 126 m_Index = 0; 127 m_Type = CDirEntry::eUnknown; 128 m_CompressedSize = 0; 129 } 130 131 // No setters -- they are not needed for access by the user, and 132 // thus are done directly from CArchive for the sake of performance. 133 134 // Getters only! GetType(void) const135 CDirEntry::EType GetType(void) const { return m_Type; } GetName(void) const136 const string& GetName(void) const { return m_Name; } GetLinkName(void) const137 const string& GetLinkName(void) const { return m_LinkName; } GetUserName(void) const138 const string& GetUserName(void) const { return m_UserName; } GetGroupName(void) const139 const string& GetGroupName(void) const { return m_GroupName; } GetComment(void) const140 const string& GetComment(void) const { return m_Comment; } GetIndex(void) const141 size_t GetIndex(void) const { return m_Index; } GetModificationTime(void) const142 time_t GetModificationTime(void) const { return m_Stat.st_mtime; } GetLastAccessTime(void) const143 time_t GetLastAccessTime(void) const { return m_Stat.st_atime; } GetCreationTime(void) const144 time_t GetCreationTime(void) const { return m_Stat.st_ctime; } GetSize(void) const145 Uint8 GetSize(void) const { return m_Stat.st_size; } 146 mode_t GetMode(void) const; // Raw mode as stored in archive 147 void GetMode(CDirEntry::TMode* user_mode, 148 CDirEntry::TMode* group_mode = 0, 149 CDirEntry::TMode* other_mode = 0, 150 CDirEntry::TSpecialModeBits* special_bits = 0) const; 151 unsigned int GetMajor(void) const; 152 unsigned int GetMinor(void) const; GetUserId(void) const153 unsigned int GetUserId(void) const { return m_Stat.st_uid; } GetGroupId(void) const154 unsigned int GetGroupId(void) const { return m_Stat.st_gid; } 155 156 // Comparison operator 157 bool operator == (const CArchiveEntryInfo& info) const; 158 159 protected: 160 size_t m_Index; ///< Entry index in the archive 161 TNcbiSys_stat m_Stat; ///< Direntry-compatible info (as applicable) 162 CDirEntry::EType m_Type; ///< Type 163 string m_Name; ///< Entry name 164 string m_LinkName; ///< Link name if type is eLink 165 string m_UserName; ///< User name 166 string m_GroupName; ///< Group name 167 string m_Comment; ///< Entry comment 168 Uint8 m_CompressedSize; ///< Compressed size 169 170 friend class CArchive; // Setter 171 friend class CArchiveZip; // Setter 172 }; 173 174 175 /// Nice TOC (table of contents) printout 176 NCBI_XUTIL_EXPORT ostream& operator << (ostream&, const CArchiveEntryInfo&); 177 178 179 180 ////////////////////////////////////////////////////////////////////////////// 181 /// 182 /// IArchive -- abstract interface class for archive formats. 183 /// 184 185 class NCBI_XUTIL_EXPORT IArchive 186 { 187 public: 188 // Type definitions. 189 typedef CCompression::ELevel ELevel; 190 191 /// Processing direction. 192 enum EDirection { 193 eRead, ///< Reading from archive 194 eWrite ///< Writing into archive 195 }; 196 /// Archive location. 197 enum ELocation { 198 eFile, ///< File-based archive 199 eMemory ///< Memory-based archive 200 }; 201 202 /// Type of user-defined callback for extraction from archive. 203 /// 204 /// It can be used to extract data from a single archive entry on the fly. 205 /// @param info 206 /// A current entry that is processed. 207 /// @param buf 208 /// Pointer to buffer with data. 209 /// @param n 210 /// Size of data in the buffer. 211 /// @return 212 /// The callback function should process all incoming data and return 213 /// 'n' for success. If returning value don't equal the number of bytes 214 /// in the incoming buffer, that extraction fail. 215 typedef size_t (*Callback_Write)(const CArchiveEntryInfo& info, const void* buf, size_t n); 216 217 public: 218 // Dummy virtual destructor, just to avoid compilation warnings. ~IArchive(void)219 virtual ~IArchive(void) {}; 220 221 /// Create new archive file. 222 /// 223 /// @param filename 224 /// File name of the archive to create. 225 /// @note 226 /// File can be overwritten if exists. 227 /// @sa 228 /// CreateMemory, AddEntryFromFile, AddEntryFromMemory 229 virtual void CreateFile(const string& filename) = 0; 230 231 /// Create new archive located in memory. 232 /// 233 /// @param initial_allocation_size 234 /// Estimated size of the archive, if known. 235 /// Bigger size allow to avoid extra memory reallocations. 236 /// @sa 237 /// FinalizeMemory, AddEntryFromFile, AddEntryFromMemory 238 virtual void CreateMemory(size_t initial_allocation_size = 0) = 0; 239 240 /// Open archive file for reading. 241 /// 242 /// @param filename 243 /// File name of the existing archive to open. 244 /// @sa 245 /// CreateFile, OpenMemory, ExtractEntryToFileSystem, ExtractEntryToMemory 246 virtual void OpenFile(const string& filename) = 0; 247 248 /// Open archive located in memory for reading. 249 /// @param buf 250 /// Pointer to an archive located in memory. Used only to open already 251 /// existed archive for reading. 252 /// @param size 253 /// Size of the archive. 254 /// @sa 255 /// CreateMemory, OpenFile, ExtractEntryToFileSystem, ExtractEntryToMemory 256 virtual void OpenMemory(const void* buf, size_t size) = 0; 257 258 /// Close the archive. 259 /// 260 /// For file-based archives it flushes all pending output. 261 /// All added entries will appears in the archive only after this call. 262 /// This method will be automatically called from destructor 263 /// if you forgot to call it directly. But note, that if the archive 264 /// is created in memory, it will be lost. You should call 265 /// FinalizeMemory() to get it. 266 /// @sa 267 /// FinalizeMemory, OpenFile, OpenMemory 268 virtual void Close(void) = 0; 269 270 /// Finalize the archive created in memory. 271 /// 272 /// Return pointer to buffer with created archive and its size. 273 /// The only valid operation after this call is Close(). 274 /// @param buf 275 /// Pointer to an archive located in memory. 276 /// @param size 277 /// Size of the newly created archive. 278 /// @note 279 /// Do not forget to deallocate memory buffer after usage. 280 /// @sa 281 /// CreateMemory, Close 282 virtual void FinalizeMemory(void** buf, size_t* size) = 0; 283 284 /// Returns the total number of entries in the archive. 285 virtual size_t GetNumEntries(void) = 0; 286 287 /// Get detailed information about an archive entry by index. 288 /// 289 /// @param index 290 /// Zero-based index of entry in the archive. 291 /// @param info 292 /// Pointer to entry information structure that will be filled with 293 /// information about entry with specified index. 294 /// @note 295 /// Note that the archive can contain multiple versions of the same entry 296 /// (in case if an update was done on it), all of which but the last one 297 /// are to be ignored. 298 /// @sa 299 /// CArchiveEntryInfo 300 virtual void GetEntryInfo(size_t index, CArchiveEntryInfo* info) = 0; 301 302 /// Check that current archive format have support for specific feature. 303 /// @sa CArchive 304 virtual bool HaveSupport_Type(CDirEntry::EType type) = 0; 305 virtual bool HaveSupport_AbsolutePath(void) = 0; 306 307 /// Extracts an archive entry to file system. 308 /// 309 /// @param info 310 /// Entry to extract. 311 /// @param dst_path 312 /// Destination path for extracted entry. 313 /// @note 314 /// This method do not set last accessed and modified times. 315 /// See CArchive. 316 /// @sa 317 /// ExtractEntryToMemory, ExtractEntryToCallback, CArchiveEntryInfo::GetSize 318 virtual void ExtractEntryToFileSystem(const CArchiveEntryInfo& info, 319 const string& dst_path) = 0; 320 321 /// Extracts an archive file to a memory buffer. 322 /// 323 /// Do nothing for entries of other types. 324 /// @param info 325 /// Entry to extract. 326 /// @param buf 327 /// Memory buffer for extracted data. 328 /// @param size 329 /// Size of memory buffer. 330 /// Note, that the buffer size should be big enough to fit whole extracted file. 331 /// @sa 332 /// ExtractEntryToFileSystem, ExtractEntryToCallback, CArchiveEntryInfo::GetSize 333 virtual void ExtractEntryToMemory(const CArchiveEntryInfo& info, 334 void* buf, size_t size) = 0; 335 336 /// Extracts an archive file using user-defined callback to process extracted data. 337 /// 338 /// Do nothing for entries of other types. 339 /// @param info 340 /// Entry to extract. 341 /// @param callback 342 /// User callback for processing extracted data on the fly. 343 /// @sa 344 /// ExtractEntryToFileSystem, ExtractEntryToMemory, CArchiveEntryInfo::GetSize 345 virtual void ExtractEntryToCallback(const CArchiveEntryInfo& info, 346 Callback_Write callback) = 0; 347 348 /// Verify entry integrity. 349 /// 350 /// @param info 351 /// Entry to verify. 352 virtual void TestEntry(const CArchiveEntryInfo& info) = 0; 353 354 /// Don't need to be implemented for ZIP format. 355 virtual void SkipEntry(const CArchiveEntryInfo& info) = 0; 356 357 /// Add single entry to newly created archive from file system. 358 /// 359 /// @param info 360 /// Entry information to add. It should have name and type of adding entry at least. 361 /// If added entry is a directory, just add an information about it to archive. 362 /// CArchive process all directories recursively. 363 /// @param src_path 364 /// Path to file system object to add. 365 /// @param level 366 /// Compression level used to compress file . 367 /// @sa 368 /// CreateFile, CreateMemory, AddEntryFromMemory 369 virtual void AddEntryFromFileSystem(const CArchiveEntryInfo& info, 370 const string& src_path, ELevel level) = 0; 371 372 /// Add entry to newly created archive from memory buffer. 373 /// 374 /// @param info 375 /// Entry information to add. It should have name and type of adding entry at least. 376 /// @param buf 377 /// Memory buffer with data to add. 378 /// @param size 379 /// Size of data in memory buffer. 380 /// @param level 381 /// Compression level for added data. 382 /// @sa 383 /// CreateFile, CreateMemory, AddEntryFromFileSystem 384 virtual void AddEntryFromMemory(const CArchiveEntryInfo& info, 385 void* buf, size_t size, ELevel level) = 0; 386 387 protected: 388 EDirection m_Mode; ///< Processing direction (read/write) 389 ELocation m_Location; ///< Archive location (file/memory) 390 }; 391 392 393 END_NCBI_SCOPE 394 395 396 /* @} */ 397 398 #endif /* UTIL_COMPRESS__ARCHIVE___HPP */ 399