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