/src/wxwidgets/include/wx/tarstrm.h
Line | Count | Source |
1 | | ///////////////////////////////////////////////////////////////////////////// |
2 | | // Name: wx/tarstrm.h |
3 | | // Purpose: Streams for Tar files |
4 | | // Author: Mike Wetherell |
5 | | // Copyright: (c) 2004 Mike Wetherell |
6 | | // Licence: wxWindows licence |
7 | | ///////////////////////////////////////////////////////////////////////////// |
8 | | |
9 | | #ifndef _WX_WXTARSTREAM_H__ |
10 | | #define _WX_WXTARSTREAM_H__ |
11 | | |
12 | | #include "wx/defs.h" |
13 | | |
14 | | #if wxUSE_TARSTREAM |
15 | | |
16 | | #include "wx/archive.h" |
17 | | |
18 | | #include <unordered_map> |
19 | | |
20 | | ///////////////////////////////////////////////////////////////////////////// |
21 | | // Constants |
22 | | |
23 | | // TypeFlag values |
24 | | enum wxTarType |
25 | | { |
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: |
50 | | virtual ~wxTarNotifier() = default; |
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 override; |
72 | 0 | wxString GetInternalName() const override { return m_Name; } |
73 | 0 | wxPathFormat GetInternalFormat() const override { return wxPATH_UNIX; } |
74 | | int GetMode() const; |
75 | 0 | int GetUserId() const { return m_UserId; } |
76 | 0 | int GetGroupId() const { return m_GroupId; } |
77 | 8.74k | wxFileOffset GetSize() const override { return m_Size; } |
78 | 6.31k | wxFileOffset GetOffset() const override { return m_Offset; } |
79 | 0 | wxDateTime GetDateTime() const override { return m_ModifyTime; } |
80 | 0 | wxDateTime GetAccessTime() const { return m_AccessTime; } |
81 | 0 | wxDateTime GetCreateTime() const { return m_CreateTime; } |
82 | 12.1k | int GetTypeFlag() const { return m_TypeFlag; } |
83 | 0 | wxString GetLinkName() const { return m_LinkName; } |
84 | 0 | wxString GetUserName() const { return m_UserName; } |
85 | 0 | wxString GetGroupName() const { return m_GroupName; } |
86 | 0 | int GetDevMajor() const { return m_DevMajor; } |
87 | 0 | int GetDevMinor() const { return m_DevMinor; } |
88 | | |
89 | | // is accessors |
90 | | bool IsDir() const override; |
91 | 0 | bool IsReadOnly() const override { return !(m_Mode & 0222); } |
92 | | |
93 | | // set accessors |
94 | | void SetName(const wxString& name, wxPathFormat format = wxPATH_NATIVE) override; |
95 | 6.31k | void SetUserId(int id) { m_UserId = id; } |
96 | 6.31k | void SetGroupId(int id) { m_GroupId = id; } |
97 | | void SetMode(int mode); |
98 | 6.31k | void SetSize(wxFileOffset size) override { m_Size = size; } |
99 | 6.31k | void SetDateTime(const wxDateTime& dt) override { m_ModifyTime = dt; } |
100 | 6.31k | void SetAccessTime(const wxDateTime& dt) { m_AccessTime = dt; } |
101 | 6.31k | void SetCreateTime(const wxDateTime& dt) { m_CreateTime = dt; } |
102 | 6.31k | void SetTypeFlag(int type) { m_TypeFlag = type; } |
103 | 6.31k | void SetLinkName(const wxString& link) { m_LinkName = link; } |
104 | 3.51k | void SetUserName(const wxString& user) { m_UserName = user; } |
105 | 3.51k | void SetGroupName(const wxString& group) { m_GroupName = group; } |
106 | 3.51k | void SetDevMajor(int dev) { m_DevMajor = dev; } |
107 | 3.51k | void SetDevMinor(int dev) { m_DevMinor = dev; } |
108 | | |
109 | | // set is accessors |
110 | | void SetIsDir(bool isDir = true) override; |
111 | | void SetIsReadOnly(bool isReadOnly = true) override; |
112 | | |
113 | | static wxString GetInternalName(const wxString& name, |
114 | | wxPathFormat format = wxPATH_NATIVE, |
115 | | bool *pIsDir = nullptr); |
116 | | |
117 | 0 | wxNODISCARD wxTarEntry *Clone() const { return new wxTarEntry(*this); } |
118 | | |
119 | 0 | void SetNotifier(wxTarNotifier& WXUNUSED(notifier)) { } |
120 | | |
121 | | private: |
122 | 6.31k | void SetOffset(wxFileOffset offset) override { m_Offset = offset; } |
123 | | |
124 | 0 | virtual wxArchiveEntry* DoClone() const override { 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 | | wxDECLARE_DYNAMIC_CLASS(wxTarEntry); |
146 | | }; |
147 | | |
148 | | |
149 | | ///////////////////////////////////////////////////////////////////////////// |
150 | | // wxTarInputStream |
151 | | |
152 | | class WXDLLIMPEXP_BASE wxTarInputStream : public wxArchiveInputStream |
153 | | { |
154 | | public: |
155 | | typedef wxTarEntry entry_type; |
156 | | |
157 | | wxTarInputStream(wxInputStream& stream, wxMBConv& conv = wxConvLocal); |
158 | | wxTarInputStream(wxInputStream *stream, wxMBConv& conv = wxConvLocal); |
159 | | virtual ~wxTarInputStream(); |
160 | | |
161 | | bool OpenEntry(wxTarEntry& entry); |
162 | | bool CloseEntry() override; |
163 | | |
164 | | wxTarEntry *GetNextEntry(); |
165 | | |
166 | 0 | wxFileOffset GetLength() const override { return m_size; } |
167 | 0 | bool IsSeekable() const override { return m_parent_i_stream->IsSeekable(); } |
168 | | |
169 | | // Limit on the extended header size, to avoid excessive allocation. |
170 | 2.57k | static size_t GetMaxExtendedHeaderSize() { return sm_maxExtendedHeaderSize; } |
171 | 0 | static void SetMaxExtendedHeaderSize(size_t size) { sm_maxExtendedHeaderSize = size; } |
172 | | |
173 | | protected: |
174 | | size_t OnSysRead(void *buffer, size_t size) override; |
175 | 0 | wxFileOffset OnSysTell() const override { return m_pos; } |
176 | | wxFileOffset OnSysSeek(wxFileOffset seek, wxSeekMode mode) override; |
177 | | |
178 | | private: |
179 | | using wxTarHeaderRecords = std::unordered_map<wxString, wxString>; |
180 | | |
181 | | void Init(); |
182 | | |
183 | 0 | wxArchiveEntry *DoGetNextEntry() override { return GetNextEntry(); } |
184 | | bool OpenEntry(wxArchiveEntry& entry) override; |
185 | 19.6k | bool IsOpened() const { return m_pos != wxInvalidOffset; } |
186 | | |
187 | | wxStreamError ReadHeaders(); |
188 | | bool ReadExtendedHeader(wxTarHeaderRecords*& recs); |
189 | | |
190 | | wxString GetExtendedHeader(const wxString& key) const; |
191 | | wxString GetHeaderPath() const; |
192 | | wxFileOffset GetHeaderNumber(int id) const; |
193 | | wxString GetHeaderString(int id) const; |
194 | | wxDateTime GetHeaderDate(const wxString& key) const; |
195 | | |
196 | | wxFileOffset m_pos; // position within the current entry |
197 | | wxFileOffset m_offset; // offset to the start of the entry's data |
198 | | wxFileOffset m_size; // size of the current entry's data |
199 | | |
200 | | int m_sumType; |
201 | | int m_tarType; |
202 | | class wxTarHeaderBlock *m_hdr; |
203 | | wxTarHeaderRecords *m_HeaderRecs; |
204 | | wxTarHeaderRecords *m_GlobalHeaderRecs; |
205 | | |
206 | | static size_t sm_maxExtendedHeaderSize; |
207 | | |
208 | | wxDECLARE_NO_COPY_CLASS(wxTarInputStream); |
209 | | }; |
210 | | |
211 | | |
212 | | ///////////////////////////////////////////////////////////////////////////// |
213 | | // wxTarOutputStream |
214 | | |
215 | | class WXDLLIMPEXP_BASE wxTarOutputStream : public wxArchiveOutputStream |
216 | | { |
217 | | public: |
218 | | wxTarOutputStream(wxOutputStream& stream, |
219 | | wxTarFormat format = wxTAR_PAX, |
220 | | wxMBConv& conv = wxConvLocal); |
221 | | wxTarOutputStream(wxOutputStream *stream, |
222 | | wxTarFormat format = wxTAR_PAX, |
223 | | wxMBConv& conv = wxConvLocal); |
224 | | virtual ~wxTarOutputStream(); |
225 | | |
226 | | bool PutNextEntry(wxTarEntry *entry); |
227 | | |
228 | | bool PutNextEntry(const wxString& name, |
229 | | const wxDateTime& dt = wxDateTime::Now(), |
230 | | wxFileOffset size = wxInvalidOffset) override; |
231 | | |
232 | | bool PutNextDirEntry(const wxString& name, |
233 | | const wxDateTime& dt = wxDateTime::Now()) override; |
234 | | |
235 | | bool CopyEntry(wxTarEntry *entry, wxTarInputStream& inputStream); |
236 | 0 | bool CopyArchiveMetaData(wxTarInputStream& WXUNUSED(s)) { return true; } |
237 | | |
238 | | void Sync() override; |
239 | | bool CloseEntry() override; |
240 | | bool Close() override; |
241 | | |
242 | 0 | bool IsSeekable() const override { return m_parent_o_stream->IsSeekable(); } |
243 | | |
244 | 0 | void SetBlockingFactor(int factor) { m_BlockingFactor = factor; } |
245 | 0 | int GetBlockingFactor() const { return m_BlockingFactor; } |
246 | | |
247 | | protected: |
248 | | size_t OnSysWrite(const void *buffer, size_t size) override; |
249 | 0 | wxFileOffset OnSysTell() const override { return m_pos; } |
250 | | wxFileOffset OnSysSeek(wxFileOffset pos, wxSeekMode mode) override; |
251 | | |
252 | | private: |
253 | | void Init(wxTarFormat format); |
254 | | |
255 | | bool PutNextEntry(wxArchiveEntry *entry) override; |
256 | | bool CopyEntry(wxArchiveEntry *entry, wxArchiveInputStream& stream) override; |
257 | 0 | bool CopyArchiveMetaData(wxArchiveInputStream& WXUNUSED(s)) override { return true; } |
258 | 0 | bool IsOpened() const { return m_pos != wxInvalidOffset; } |
259 | | |
260 | | bool WriteHeaders(wxTarEntry& entry); |
261 | | bool ModifyHeader(); |
262 | | wxString PaxHeaderPath(const wxString& format, const wxString& path); |
263 | | |
264 | | void SetExtendedHeader(const wxString& key, const wxString& value); |
265 | | void SetHeaderPath(const wxString& name); |
266 | | bool SetHeaderNumber(int id, wxFileOffset n); |
267 | | void SetHeaderString(int id, const wxString& str); |
268 | | void SetHeaderDate(const wxString& key, const wxDateTime& datetime); |
269 | | |
270 | | wxFileOffset m_pos; // position within the current entry |
271 | | wxFileOffset m_maxpos; // max pos written |
272 | | wxFileOffset m_size; // expected entry size |
273 | | |
274 | | wxFileOffset m_headpos; // offset within the file to the entry's header |
275 | | wxFileOffset m_datapos; // offset within the file to the entry's data |
276 | | |
277 | | wxFileOffset m_tarstart;// offset within the file to the tar |
278 | | wxFileOffset m_tarsize; // size of tar so far |
279 | | |
280 | | bool m_pax; |
281 | | int m_BlockingFactor; |
282 | | wxUint32 m_chksum; |
283 | | bool m_large; |
284 | | class wxTarHeaderBlock *m_hdr; |
285 | | class wxTarHeaderBlock *m_hdr2; |
286 | | char *m_extendedHdr; |
287 | | size_t m_extendedSize; |
288 | | wxString m_badfit; |
289 | | bool m_endrecWritten; |
290 | | |
291 | | wxDECLARE_NO_COPY_CLASS(wxTarOutputStream); |
292 | | }; |
293 | | |
294 | | |
295 | | ///////////////////////////////////////////////////////////////////////////// |
296 | | // Iterators |
297 | | |
298 | | typedef wxArchiveIterator<wxTarInputStream> wxTarIter; |
299 | | typedef wxArchiveIterator<wxTarInputStream, |
300 | | std::pair<wxString, wxTarEntry*> > wxTarPairIter; |
301 | | |
302 | | |
303 | | ///////////////////////////////////////////////////////////////////////////// |
304 | | // wxTarClassFactory |
305 | | |
306 | | class WXDLLIMPEXP_BASE wxTarClassFactory : public wxArchiveClassFactory |
307 | | { |
308 | | public: |
309 | | typedef wxTarEntry entry_type; |
310 | | typedef wxTarInputStream instream_type; |
311 | | typedef wxTarOutputStream outstream_type; |
312 | | typedef wxTarNotifier notifier_type; |
313 | | typedef wxTarIter iter_type; |
314 | | typedef wxTarPairIter pairiter_type; |
315 | | |
316 | | wxTarClassFactory(); |
317 | | |
318 | | wxTarEntry *NewEntry() const |
319 | 0 | { return new wxTarEntry; } |
320 | | wxTarInputStream *NewStream(wxInputStream& stream) const |
321 | 0 | { return new wxTarInputStream(stream, GetConv()); } |
322 | | wxTarOutputStream *NewStream(wxOutputStream& stream) const |
323 | 0 | { return new wxTarOutputStream(stream, wxTAR_PAX, GetConv()); } |
324 | | wxTarInputStream *NewStream(wxInputStream *stream) const |
325 | 0 | { return new wxTarInputStream(stream, GetConv()); } |
326 | | wxTarOutputStream *NewStream(wxOutputStream *stream) const |
327 | 0 | { return new wxTarOutputStream(stream, wxTAR_PAX, GetConv()); } |
328 | | |
329 | | wxString GetInternalName(const wxString& name, |
330 | | wxPathFormat format = wxPATH_NATIVE) const override |
331 | 0 | { return wxTarEntry::GetInternalName(name, format); } |
332 | | |
333 | | const wxChar * const *GetProtocols(wxStreamProtocolType type |
334 | | = wxSTREAM_PROTOCOL) const override; |
335 | | |
336 | | protected: |
337 | | wxArchiveEntry *DoNewEntry() const override |
338 | 0 | { return NewEntry(); } |
339 | | wxArchiveInputStream *DoNewStream(wxInputStream& stream) const override |
340 | 0 | { return NewStream(stream); } |
341 | | wxArchiveOutputStream *DoNewStream(wxOutputStream& stream) const override |
342 | 0 | { return NewStream(stream); } |
343 | | wxArchiveInputStream *DoNewStream(wxInputStream *stream) const override |
344 | 0 | { return NewStream(stream); } |
345 | | wxArchiveOutputStream *DoNewStream(wxOutputStream *stream) const override |
346 | 0 | { return NewStream(stream); } |
347 | | |
348 | | private: |
349 | | wxDECLARE_DYNAMIC_CLASS(wxTarClassFactory); |
350 | | }; |
351 | | |
352 | | |
353 | | #endif // wxUSE_TARSTREAM |
354 | | |
355 | | #endif // _WX_WXTARSTREAM_H__ |