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
25enum {
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)
37enum 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
47class WXDLLIMPEXP_BASE wxTarNotifier
48{
49public:
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
59class WXDLLIMPEXP_BASE wxTarEntry : public wxArchiveEntry
60{
61public:
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;
72    wxString     GetInternalName() const        { return m_Name; }
73    wxPathFormat GetInternalFormat() const      { return wxPATH_UNIX; }
74    int          GetMode() const;
75    int          GetUserId() const              { return m_UserId; }
76    int          GetGroupId() const             { return m_GroupId; }
77    wxFileOffset GetSize() const                { return m_Size; }
78    wxFileOffset GetOffset() const              { return m_Offset; }
79    wxDateTime   GetDateTime() const            { return m_ModifyTime; }
80    wxDateTime   GetAccessTime() const          { return m_AccessTime; }
81    wxDateTime   GetCreateTime() const          { return m_CreateTime; }
82    int          GetTypeFlag() const            { return m_TypeFlag; }
83    wxString     GetLinkName() const            { return m_LinkName; }
84    wxString     GetUserName() const            { return m_UserName; }
85    wxString     GetGroupName() const           { return m_GroupName; }
86    int          GetDevMajor() const            { return m_DevMajor; }
87    int          GetDevMinor() const            { return m_DevMinor; }
88
89    // is accessors
90    bool IsDir() const;
91    bool IsReadOnly() const                     { return !(m_Mode & 0222); }
92
93    // set accessors
94    void SetName(const wxString& name, wxPathFormat format = wxPATH_NATIVE);
95    void SetUserId(int id)                      { m_UserId = id; }
96    void SetGroupId(int id)                     { m_GroupId = id; }
97    void SetMode(int mode);
98    void SetSize(wxFileOffset size)             { m_Size = size; }
99    void SetDateTime(const wxDateTime& dt)      { m_ModifyTime = dt; }
100    void SetAccessTime(const wxDateTime& dt)    { m_AccessTime = dt; }
101    void SetCreateTime(const wxDateTime& dt)    { m_CreateTime = dt; }
102    void SetTypeFlag(int type)                  { m_TypeFlag = type; }
103    void SetLinkName(const wxString& link)      { m_LinkName = link; }
104    void SetUserName(const wxString& user)      { m_UserName = user; }
105    void SetGroupName(const wxString& group)    { m_GroupName = group; }
106    void SetDevMajor(int dev)                   { m_DevMajor = 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
117    wxTarEntry *Clone() const { return new wxTarEntry(*this); }
118
119    void SetNotifier(wxTarNotifier& WXUNUSED(notifier)) { }
120
121private:
122    void SetOffset(wxFileOffset offset)         { m_Offset = offset; }
123
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
152WX_DECLARE_STRING_HASH_MAP(wxString, wxTarHeaderRecords);
153
154class WXDLLIMPEXP_BASE wxTarInputStream : public wxArchiveInputStream
155{
156public:
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
168    wxFileOffset GetLength() const      { return m_size; }
169    bool IsSeekable() const { return m_parent_i_stream->IsSeekable(); }
170
171protected:
172    size_t OnSysRead(void *buffer, size_t size);
173    wxFileOffset OnSysTell() const      { return m_pos; }
174    wxFileOffset OnSysSeek(wxFileOffset seek, wxSeekMode mode);
175
176private:
177    void Init();
178
179    wxArchiveEntry *DoGetNextEntry()    { return GetNextEntry(); }
180    bool OpenEntry(wxArchiveEntry& entry);
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
209class WXDLLIMPEXP_BASE wxTarOutputStream : public wxArchiveOutputStream
210{
211public:
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);
230    bool CopyArchiveMetaData(wxTarInputStream& WXUNUSED(s)) { return true; }
231
232    void Sync();
233    bool CloseEntry();
234    bool Close();
235
236    bool IsSeekable() const { return m_parent_o_stream->IsSeekable(); }
237
238    void SetBlockingFactor(int factor)  { m_BlockingFactor = factor; }
239    int GetBlockingFactor() const       { return m_BlockingFactor; }
240
241protected:
242    size_t OnSysWrite(const void *buffer, size_t size);
243    wxFileOffset OnSysTell() const      { return m_pos; }
244    wxFileOffset OnSysSeek(wxFileOffset pos, wxSeekMode mode);
245
246private:
247    void Init(wxTarFormat format);
248
249    bool PutNextEntry(wxArchiveEntry *entry);
250    bool CopyEntry(wxArchiveEntry *entry, wxArchiveInputStream& stream);
251    bool CopyArchiveMetaData(wxArchiveInputStream& WXUNUSED(s)) { return true; }
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
292typedef wxArchiveIterator<wxTarInputStream> wxTarIter;
293typedef wxArchiveIterator<wxTarInputStream,
294         std::pair<wxString, wxTarEntry*> > wxTarPairIter;
295#endif
296
297
298/////////////////////////////////////////////////////////////////////////////
299// wxTarClassFactory
300
301class WXDLLIMPEXP_BASE wxTarClassFactory : public wxArchiveClassFactory
302{
303public:
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
315    wxTarEntry *NewEntry() const
316        { return new wxTarEntry; }
317    wxTarInputStream *NewStream(wxInputStream& stream) const
318        { return new wxTarInputStream(stream, GetConv()); }
319    wxTarOutputStream *NewStream(wxOutputStream& stream) const
320        { return new wxTarOutputStream(stream, wxTAR_PAX, GetConv()); }
321    wxTarInputStream *NewStream(wxInputStream *stream) const
322        { return new wxTarInputStream(stream, GetConv()); }
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
333protected:
334    wxArchiveEntry *DoNewEntry() const
335        { return NewEntry(); }
336    wxArchiveInputStream *DoNewStream(wxInputStream& stream) const
337        { return NewStream(stream); }
338    wxArchiveOutputStream *DoNewStream(wxOutputStream& stream) const
339        { return NewStream(stream); }
340    wxArchiveInputStream *DoNewStream(wxInputStream *stream) const
341        { return NewStream(stream); }
342    wxArchiveOutputStream *DoNewStream(wxOutputStream *stream) const
343        { return NewStream(stream); }
344
345private:
346    DECLARE_DYNAMIC_CLASS(wxTarClassFactory)
347};
348
349
350#endif // wxUSE_TARSTREAM
351
352#endif // _WX_WXTARSTREAM_H__
353