1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        wx/tarstrm.h
3 // Purpose:     Streams for Tar files
4 // Author:      Mike Wetherell
5 // RCS-ID:      $Id: tarstrm.h 43887 2006-12-09 22:28:11Z MW $
6 // Copyright:   (c) 2004 Mike Wetherell
7 // Licence:     wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9 
10 #ifndef _WX_WXTARSTREAM_H__
11 #define _WX_WXTARSTREAM_H__
12 
13 #include "wx/defs.h"
14 
15 #if wxUSE_TARSTREAM
16 
17 #include "wx/archive.h"
18 #include "wx/hashmap.h"
19 
20 
21 /////////////////////////////////////////////////////////////////////////////
22 // Constants
23 
24 // TypeFlag values
25 enum {
26     wxTAR_REGTYPE   = '0',      // regular file
27     wxTAR_LNKTYPE   = '1',      // hard link
28     wxTAR_SYMTYPE   = '2',      // symbolic link
29     wxTAR_CHRTYPE   = '3',      // character special
30     wxTAR_BLKTYPE   = '4',      // block special
31     wxTAR_DIRTYPE   = '5',      // directory
32     wxTAR_FIFOTYPE  = '6',      // named pipe
33     wxTAR_CONTTYPE  = '7'       // contiguous file
34 };
35 
36 // Archive Formats (use wxTAR_PAX, it's backward compatible)
37 enum wxTarFormat
38 {
39     wxTAR_USTAR,                // POSIX.1-1990 tar format
40     wxTAR_PAX                   // POSIX.1-2001 tar format
41 };
42 
43 
44 /////////////////////////////////////////////////////////////////////////////
45 // wxTarNotifier
46 
47 class WXDLLIMPEXP_BASE wxTarNotifier
48 {
49 public:
~wxTarNotifier()50     virtual ~wxTarNotifier() { }
51 
52     virtual void OnEntryUpdated(class wxTarEntry& entry) = 0;
53 };
54 
55 
56 /////////////////////////////////////////////////////////////////////////////
57 // Tar Entry - hold the meta data for a file in the tar
58 
59 class WXDLLIMPEXP_BASE wxTarEntry : public wxArchiveEntry
60 {
61 public:
62     wxTarEntry(const wxString& name = wxEmptyString,
63                const wxDateTime& dt = wxDateTime::Now(),
64                wxFileOffset size = wxInvalidOffset);
65     virtual ~wxTarEntry();
66 
67     wxTarEntry(const wxTarEntry& entry);
68     wxTarEntry& operator=(const wxTarEntry& entry);
69 
70     // Get accessors
71     wxString     GetName(wxPathFormat format = wxPATH_NATIVE) const;
GetInternalName()72     wxString     GetInternalName() const        { return m_Name; }
GetInternalFormat()73     wxPathFormat GetInternalFormat() const      { return wxPATH_UNIX; }
74     int          GetMode() const;
GetUserId()75     int          GetUserId() const              { return m_UserId; }
GetGroupId()76     int          GetGroupId() const             { return m_GroupId; }
GetSize()77     wxFileOffset GetSize() const                { return m_Size; }
GetOffset()78     wxFileOffset GetOffset() const              { return m_Offset; }
GetDateTime()79     wxDateTime   GetDateTime() const            { return m_ModifyTime; }
GetAccessTime()80     wxDateTime   GetAccessTime() const          { return m_AccessTime; }
GetCreateTime()81     wxDateTime   GetCreateTime() const          { return m_CreateTime; }
GetTypeFlag()82     int          GetTypeFlag() const            { return m_TypeFlag; }
GetLinkName()83     wxString     GetLinkName() const            { return m_LinkName; }
GetUserName()84     wxString     GetUserName() const            { return m_UserName; }
GetGroupName()85     wxString     GetGroupName() const           { return m_GroupName; }
GetDevMajor()86     int          GetDevMajor() const            { return m_DevMajor; }
GetDevMinor()87     int          GetDevMinor() const            { return m_DevMinor; }
88 
89     // is accessors
90     bool IsDir() const;
IsReadOnly()91     bool IsReadOnly() const                     { return !(m_Mode & 0222); }
92 
93     // set accessors
94     void SetName(const wxString& name, wxPathFormat format = wxPATH_NATIVE);
SetUserId(int id)95     void SetUserId(int id)                      { m_UserId = id; }
SetGroupId(int id)96     void SetGroupId(int id)                     { m_GroupId = id; }
97     void SetMode(int mode);
SetSize(wxFileOffset size)98     void SetSize(wxFileOffset size)             { m_Size = size; }
SetDateTime(const wxDateTime & dt)99     void SetDateTime(const wxDateTime& dt)      { m_ModifyTime = dt; }
SetAccessTime(const wxDateTime & dt)100     void SetAccessTime(const wxDateTime& dt)    { m_AccessTime = dt; }
SetCreateTime(const wxDateTime & dt)101     void SetCreateTime(const wxDateTime& dt)    { m_CreateTime = dt; }
SetTypeFlag(int type)102     void SetTypeFlag(int type)                  { m_TypeFlag = type; }
SetLinkName(const wxString & link)103     void SetLinkName(const wxString& link)      { m_LinkName = link; }
SetUserName(const wxString & user)104     void SetUserName(const wxString& user)      { m_UserName = user; }
SetGroupName(const wxString & group)105     void SetGroupName(const wxString& group)    { m_GroupName = group; }
SetDevMajor(int dev)106     void SetDevMajor(int dev)                   { m_DevMajor = dev; }
SetDevMinor(int dev)107     void SetDevMinor(int dev)                   { m_DevMinor = dev; }
108 
109     // set is accessors
110     void SetIsDir(bool isDir = true);
111     void SetIsReadOnly(bool isReadOnly = true);
112 
113     static wxString GetInternalName(const wxString& name,
114                                     wxPathFormat format = wxPATH_NATIVE,
115                                     bool *pIsDir = NULL);
116 
Clone()117     wxTarEntry *Clone() const { return new wxTarEntry(*this); }
118 
SetNotifier(wxTarNotifier & WXUNUSED (notifier))119     void SetNotifier(wxTarNotifier& WXUNUSED(notifier)) { }
120 
121 private:
SetOffset(wxFileOffset offset)122     void SetOffset(wxFileOffset offset)         { m_Offset = offset; }
123 
DoClone()124     virtual wxArchiveEntry* DoClone() const     { return Clone(); }
125 
126     wxString     m_Name;
127     int          m_Mode;
128     bool         m_IsModeSet;
129     int          m_UserId;
130     int          m_GroupId;
131     wxFileOffset m_Size;
132     wxFileOffset m_Offset;
133     wxDateTime   m_ModifyTime;
134     wxDateTime   m_AccessTime;
135     wxDateTime   m_CreateTime;
136     int          m_TypeFlag;
137     wxString     m_LinkName;
138     wxString     m_UserName;
139     wxString     m_GroupName;
140     int          m_DevMajor;
141     int          m_DevMinor;
142 
143     friend class wxTarInputStream;
144 
145     DECLARE_DYNAMIC_CLASS(wxTarEntry)
146 };
147 
148 
149 /////////////////////////////////////////////////////////////////////////////
150 // wxTarInputStream
151 
152 WX_DECLARE_STRING_HASH_MAP(wxString, wxTarHeaderRecords);
153 
154 class WXDLLIMPEXP_BASE wxTarInputStream : public wxArchiveInputStream
155 {
156 public:
157     typedef wxTarEntry entry_type;
158 
159     wxTarInputStream(wxInputStream& stream, wxMBConv& conv = wxConvLocal);
160     wxTarInputStream(wxInputStream *stream, wxMBConv& conv = wxConvLocal);
161     virtual ~wxTarInputStream();
162 
163     bool OpenEntry(wxTarEntry& entry);
164     bool CloseEntry();
165 
166     wxTarEntry *GetNextEntry();
167 
GetLength()168     wxFileOffset GetLength() const      { return m_size; }
IsSeekable()169     bool IsSeekable() const { return m_parent_i_stream->IsSeekable(); }
170 
171 protected:
172     size_t OnSysRead(void *buffer, size_t size);
OnSysTell()173     wxFileOffset OnSysTell() const      { return m_pos; }
174     wxFileOffset OnSysSeek(wxFileOffset seek, wxSeekMode mode);
175 
176 private:
177     void Init();
178 
DoGetNextEntry()179     wxArchiveEntry *DoGetNextEntry()    { return GetNextEntry(); }
180     bool OpenEntry(wxArchiveEntry& entry);
IsOpened()181     bool IsOpened() const               { return m_pos != wxInvalidOffset; }
182 
183     wxStreamError ReadHeaders();
184     bool ReadExtendedHeader(wxTarHeaderRecords*& recs);
185 
186     wxString GetExtendedHeader(const wxString& key) const;
187     wxString GetHeaderPath() const;
188     wxFileOffset GetHeaderNumber(int id) const;
189     wxString GetHeaderString(int id) const;
190     wxDateTime GetHeaderDate(const wxString& key) const;
191 
192     wxFileOffset m_pos;     // position within the current entry
193     wxFileOffset m_offset;  // offset to the start of the entry's data
194     wxFileOffset m_size;    // size of the current entry's data
195 
196     int m_sumType;
197     int m_tarType;
198     class wxTarHeaderBlock *m_hdr;
199     wxTarHeaderRecords *m_HeaderRecs;
200     wxTarHeaderRecords *m_GlobalHeaderRecs;
201 
202     DECLARE_NO_COPY_CLASS(wxTarInputStream)
203 };
204 
205 
206 /////////////////////////////////////////////////////////////////////////////
207 // wxTarOutputStream
208 
209 class WXDLLIMPEXP_BASE wxTarOutputStream : public wxArchiveOutputStream
210 {
211 public:
212     wxTarOutputStream(wxOutputStream& stream,
213                       wxTarFormat format = wxTAR_PAX,
214                       wxMBConv& conv = wxConvLocal);
215     wxTarOutputStream(wxOutputStream *stream,
216                       wxTarFormat format = wxTAR_PAX,
217                       wxMBConv& conv = wxConvLocal);
218     virtual ~wxTarOutputStream();
219 
220     bool PutNextEntry(wxTarEntry *entry);
221 
222     bool PutNextEntry(const wxString& name,
223                       const wxDateTime& dt = wxDateTime::Now(),
224                       wxFileOffset size = wxInvalidOffset);
225 
226     bool PutNextDirEntry(const wxString& name,
227                          const wxDateTime& dt = wxDateTime::Now());
228 
229     bool CopyEntry(wxTarEntry *entry, wxTarInputStream& inputStream);
CopyArchiveMetaData(wxTarInputStream & WXUNUSED (s))230     bool CopyArchiveMetaData(wxTarInputStream& WXUNUSED(s)) { return true; }
231 
232     void Sync();
233     bool CloseEntry();
234     bool Close();
235 
IsSeekable()236     bool IsSeekable() const { return m_parent_o_stream->IsSeekable(); }
237 
SetBlockingFactor(int factor)238     void SetBlockingFactor(int factor)  { m_BlockingFactor = factor; }
GetBlockingFactor()239     int GetBlockingFactor() const       { return m_BlockingFactor; }
240 
241 protected:
242     size_t OnSysWrite(const void *buffer, size_t size);
OnSysTell()243     wxFileOffset OnSysTell() const      { return m_pos; }
244     wxFileOffset OnSysSeek(wxFileOffset pos, wxSeekMode mode);
245 
246 private:
247     void Init(wxTarFormat format);
248 
249     bool PutNextEntry(wxArchiveEntry *entry);
250     bool CopyEntry(wxArchiveEntry *entry, wxArchiveInputStream& stream);
CopyArchiveMetaData(wxArchiveInputStream & WXUNUSED (s))251     bool CopyArchiveMetaData(wxArchiveInputStream& WXUNUSED(s)) { return true; }
IsOpened()252     bool IsOpened() const               { return m_pos != wxInvalidOffset; }
253 
254     bool WriteHeaders(wxTarEntry& entry);
255     bool ModifyHeader();
256     wxString PaxHeaderPath(const wxString& format, const wxString& path);
257 
258     void SetExtendedHeader(const wxString& key, const wxString& value);
259     void SetHeaderPath(const wxString& name);
260     bool SetHeaderNumber(int id, wxFileOffset n);
261     void SetHeaderString(int id, const wxString& str);
262     void SetHeaderDate(const wxString& key, const wxDateTime& datetime);
263 
264     wxFileOffset m_pos;     // position within the current entry
265     wxFileOffset m_maxpos;  // max pos written
266     wxFileOffset m_size;    // expected entry size
267 
268     wxFileOffset m_headpos; // offset within the file to the entry's header
269     wxFileOffset m_datapos; // offset within the file to the entry's data
270 
271     wxFileOffset m_tarstart;// offset within the file to the tar
272     wxFileOffset m_tarsize; // size of tar so far
273 
274     bool m_pax;
275     int m_BlockingFactor;
276     wxUint32 m_chksum;
277     bool m_large;
278     class wxTarHeaderBlock *m_hdr;
279     class wxTarHeaderBlock *m_hdr2;
280     char *m_extendedHdr;
281     size_t m_extendedSize;
282     wxString m_badfit;
283 
284     DECLARE_NO_COPY_CLASS(wxTarOutputStream)
285 };
286 
287 
288 /////////////////////////////////////////////////////////////////////////////
289 // Iterators
290 
291 #if wxUSE_STL || defined WX_TEST_ARCHIVE_ITERATOR
292 typedef wxArchiveIterator<wxTarInputStream> wxTarIter;
293 typedef wxArchiveIterator<wxTarInputStream,
294          std::pair<wxString, wxTarEntry*> > wxTarPairIter;
295 #endif
296 
297 
298 /////////////////////////////////////////////////////////////////////////////
299 // wxTarClassFactory
300 
301 class WXDLLIMPEXP_BASE wxTarClassFactory : public wxArchiveClassFactory
302 {
303 public:
304     typedef wxTarEntry        entry_type;
305     typedef wxTarInputStream  instream_type;
306     typedef wxTarOutputStream outstream_type;
307     typedef wxTarNotifier     notifier_type;
308 #if wxUSE_STL || defined WX_TEST_ARCHIVE_ITERATOR
309     typedef wxTarIter         iter_type;
310     typedef wxTarPairIter     pairiter_type;
311 #endif
312 
313     wxTarClassFactory();
314 
NewEntry()315     wxTarEntry *NewEntry() const
316         { return new wxTarEntry; }
NewStream(wxInputStream & stream)317     wxTarInputStream *NewStream(wxInputStream& stream) const
318         { return new wxTarInputStream(stream, GetConv()); }
NewStream(wxOutputStream & stream)319     wxTarOutputStream *NewStream(wxOutputStream& stream) const
320         { return new wxTarOutputStream(stream, wxTAR_PAX, GetConv()); }
NewStream(wxInputStream * stream)321     wxTarInputStream *NewStream(wxInputStream *stream) const
322         { return new wxTarInputStream(stream, GetConv()); }
NewStream(wxOutputStream * stream)323     wxTarOutputStream *NewStream(wxOutputStream *stream) const
324         { return new wxTarOutputStream(stream, wxTAR_PAX, GetConv()); }
325 
326     wxString GetInternalName(const wxString& name,
327                              wxPathFormat format = wxPATH_NATIVE) const
328         { return wxTarEntry::GetInternalName(name, format); }
329 
330     const wxChar * const *GetProtocols(wxStreamProtocolType type
331                                        = wxSTREAM_PROTOCOL) const;
332 
333 protected:
DoNewEntry()334     wxArchiveEntry *DoNewEntry() const
335         { return NewEntry(); }
DoNewStream(wxInputStream & stream)336     wxArchiveInputStream *DoNewStream(wxInputStream& stream) const
337         { return NewStream(stream); }
DoNewStream(wxOutputStream & stream)338     wxArchiveOutputStream *DoNewStream(wxOutputStream& stream) const
339         { return NewStream(stream); }
DoNewStream(wxInputStream * stream)340     wxArchiveInputStream *DoNewStream(wxInputStream *stream) const
341         { return NewStream(stream); }
DoNewStream(wxOutputStream * stream)342     wxArchiveOutputStream *DoNewStream(wxOutputStream *stream) const
343         { return NewStream(stream); }
344 
345 private:
346     DECLARE_DYNAMIC_CLASS(wxTarClassFactory)
347 };
348 
349 
350 #endif // wxUSE_TARSTREAM
351 
352 #endif // _WX_WXTARSTREAM_H__
353