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