]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/wfstream.cpp
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / src / common / wfstream.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/common/wfstream.cpp
3// Purpose: "File stream" classes
4// Author: Julian Smart
5// Modified by:
6// Created: 11/07/98
7// RCS-ID: $Id$
8// Copyright: (c) Guilhem Lavaux
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16 #pragma hdrstop
17#endif
18
19#if wxUSE_STREAMS
20
21#include "wx/wfstream.h"
22
23#ifndef WX_PRECOMP
24 #include "wx/stream.h"
25#endif
26
27#include <stdio.h>
28
29#if wxUSE_FILE
30
31// ----------------------------------------------------------------------------
32// wxFileInputStream
33// ----------------------------------------------------------------------------
34
35wxFileInputStream::wxFileInputStream(const wxString& fileName)
36 : wxInputStream()
37{
38 m_file = new wxFile(fileName, wxFile::read);
39 m_file_destroy = true;
40 if ( !m_file->IsOpened() )
41 m_lasterror = wxSTREAM_READ_ERROR;
42}
43
44wxFileInputStream::wxFileInputStream()
45 : wxInputStream()
46{
47 m_file_destroy = false;
48 m_file = NULL;
49}
50
51wxFileInputStream::wxFileInputStream(wxFile& file)
52{
53 m_file = &file;
54 m_file_destroy = false;
55}
56
57wxFileInputStream::wxFileInputStream(int fd)
58{
59 m_file = new wxFile(fd);
60 m_file_destroy = true;
61}
62
63wxFileInputStream::~wxFileInputStream()
64{
65 if (m_file_destroy)
66 delete m_file;
67}
68
69wxFileOffset wxFileInputStream::GetLength() const
70{
71 return m_file->Length();
72}
73
74size_t wxFileInputStream::OnSysRead(void *buffer, size_t size)
75{
76 ssize_t ret = m_file->Read(buffer, size);
77
78 // NB: we can't use a switch here because HP-UX CC doesn't allow
79 // switching over long long (which size_t is in 64bit mode)
80
81 if ( !ret )
82 {
83 // nothing read, so nothing more to read
84 m_lasterror = wxSTREAM_EOF;
85 }
86 else if ( ret == wxInvalidOffset )
87 {
88 m_lasterror = wxSTREAM_READ_ERROR;
89 ret = 0;
90 }
91 else
92 {
93 // normal case
94 m_lasterror = wxSTREAM_NO_ERROR;
95 }
96
97 return ret;
98}
99
100wxFileOffset wxFileInputStream::OnSysSeek(wxFileOffset pos, wxSeekMode mode)
101{
102 return m_file->Seek(pos, mode);
103}
104
105wxFileOffset wxFileInputStream::OnSysTell() const
106{
107 return m_file->Tell();
108}
109
110bool wxFileInputStream::IsOk() const
111{
112 return wxInputStream::IsOk() && m_file->IsOpened();
113}
114
115// ----------------------------------------------------------------------------
116// wxFileOutputStream
117// ----------------------------------------------------------------------------
118
119wxFileOutputStream::wxFileOutputStream(const wxString& fileName)
120{
121 m_file = new wxFile(fileName, wxFile::write);
122 m_file_destroy = true;
123
124 if (!m_file->IsOpened())
125 m_lasterror = wxSTREAM_WRITE_ERROR;
126}
127
128wxFileOutputStream::wxFileOutputStream(wxFile& file)
129{
130 m_file = &file;
131 m_file_destroy = false;
132}
133
134wxFileOutputStream::wxFileOutputStream()
135 : wxOutputStream()
136{
137 m_file_destroy = false;
138 m_file = NULL;
139}
140
141wxFileOutputStream::wxFileOutputStream(int fd)
142{
143 m_file = new wxFile(fd);
144 m_file_destroy = true;
145}
146
147wxFileOutputStream::~wxFileOutputStream()
148{
149 if (m_file_destroy)
150 {
151 Sync();
152 delete m_file;
153 }
154}
155
156size_t wxFileOutputStream::OnSysWrite(const void *buffer, size_t size)
157{
158 size_t ret = m_file->Write(buffer, size);
159
160 m_lasterror = m_file->Error() ? wxSTREAM_WRITE_ERROR : wxSTREAM_NO_ERROR;
161
162 return ret;
163}
164
165wxFileOffset wxFileOutputStream::OnSysTell() const
166{
167 return m_file->Tell();
168}
169
170wxFileOffset wxFileOutputStream::OnSysSeek(wxFileOffset pos, wxSeekMode mode)
171{
172 return m_file->Seek(pos, mode);
173}
174
175void wxFileOutputStream::Sync()
176{
177 wxOutputStream::Sync();
178 m_file->Flush();
179}
180
181wxFileOffset wxFileOutputStream::GetLength() const
182{
183 return m_file->Length();
184}
185
186bool wxFileOutputStream::IsOk() const
187{
188 return wxOutputStream::IsOk() && m_file->IsOpened();
189}
190
191// ----------------------------------------------------------------------------
192// wxTempFileOutputStream
193// ----------------------------------------------------------------------------
194
195wxTempFileOutputStream::wxTempFileOutputStream(const wxString& fileName)
196{
197 m_file = new wxTempFile(fileName);
198
199 if (!m_file->IsOpened())
200 m_lasterror = wxSTREAM_WRITE_ERROR;
201}
202
203wxTempFileOutputStream::~wxTempFileOutputStream()
204{
205 if (m_file->IsOpened())
206 Discard();
207 delete m_file;
208}
209
210size_t wxTempFileOutputStream::OnSysWrite(const void *buffer, size_t size)
211{
212 if (IsOk() && m_file->Write(buffer, size))
213 return size;
214 m_lasterror = wxSTREAM_WRITE_ERROR;
215 return 0;
216}
217
218// ----------------------------------------------------------------------------
219// wxFileStream
220// ----------------------------------------------------------------------------
221
222wxFileStream::wxFileStream(const wxString& fileName)
223 : wxFileInputStream(),
224 wxFileOutputStream()
225{
226 wxFileOutputStream::m_file =
227 wxFileInputStream::m_file = new wxFile(fileName, wxFile::read_write);
228
229 // this is a bit ugly as streams are symmetric but we still have to delete
230 // the file we created above exactly once so we decide to (arbitrarily) do
231 // it in wxFileInputStream
232 wxFileInputStream::m_file_destroy = true;
233}
234
235bool wxFileStream::IsOk() const
236{
237 return wxFileOutputStream::IsOk() && wxFileInputStream::IsOk();
238}
239
240#endif // wxUSE_FILE
241
242#if wxUSE_FFILE
243
244// ----------------------------------------------------------------------------
245// wxFFileInputStream
246// ----------------------------------------------------------------------------
247
248wxFFileInputStream::wxFFileInputStream(const wxString& fileName,
249 const wxString& mode)
250 : wxInputStream()
251{
252 m_file = new wxFFile(fileName, mode);
253 m_file_destroy = true;
254
255 if (!m_file->IsOpened())
256 m_lasterror = wxSTREAM_WRITE_ERROR;
257}
258
259wxFFileInputStream::wxFFileInputStream()
260 : wxInputStream()
261{
262 m_file = NULL;
263 m_file_destroy = false;
264}
265
266wxFFileInputStream::wxFFileInputStream(wxFFile& file)
267{
268 m_file = &file;
269 m_file_destroy = false;
270}
271
272wxFFileInputStream::wxFFileInputStream(FILE *file)
273{
274 m_file = new wxFFile(file);
275 m_file_destroy = true;
276}
277
278wxFFileInputStream::~wxFFileInputStream()
279{
280 if (m_file_destroy)
281 delete m_file;
282}
283
284wxFileOffset wxFFileInputStream::GetLength() const
285{
286 return m_file->Length();
287}
288
289size_t wxFFileInputStream::OnSysRead(void *buffer, size_t size)
290{
291 ssize_t ret = m_file->Read(buffer, size);
292
293 // It is not safe to call Eof() if the file is not opened.
294 if (!m_file->IsOpened() || m_file->Eof())
295 m_lasterror = wxSTREAM_EOF;
296 if (ret == wxInvalidOffset)
297 {
298 m_lasterror = wxSTREAM_READ_ERROR;
299 ret = 0;
300 }
301
302 return ret;
303}
304
305wxFileOffset wxFFileInputStream::OnSysSeek(wxFileOffset pos, wxSeekMode mode)
306{
307 return m_file->Seek(pos, mode) ? m_file->Tell() : wxInvalidOffset;
308}
309
310wxFileOffset wxFFileInputStream::OnSysTell() const
311{
312 return m_file->Tell();
313}
314
315bool wxFFileInputStream::IsOk() const
316{
317 return wxStreamBase::IsOk() && m_file->IsOpened();
318}
319
320// ----------------------------------------------------------------------------
321// wxFFileOutputStream
322// ----------------------------------------------------------------------------
323
324wxFFileOutputStream::wxFFileOutputStream(const wxString& fileName,
325 const wxString& mode)
326{
327 m_file = new wxFFile(fileName, mode);
328 m_file_destroy = true;
329
330 if (!m_file->IsOpened())
331 {
332 m_lasterror = wxSTREAM_WRITE_ERROR;
333 }
334 else
335 {
336 if (m_file->Error())
337 m_lasterror = wxSTREAM_WRITE_ERROR;
338 }
339}
340
341wxFFileOutputStream::wxFFileOutputStream(wxFFile& file)
342{
343 m_file = &file;
344 m_file_destroy = false;
345}
346
347wxFFileOutputStream::wxFFileOutputStream()
348 : wxOutputStream()
349{
350 m_file = NULL;
351 m_file_destroy = false;
352}
353
354wxFFileOutputStream::wxFFileOutputStream(FILE *file)
355{
356 m_file = new wxFFile(file);
357 m_file_destroy = true;
358}
359
360wxFFileOutputStream::~wxFFileOutputStream()
361{
362 if (m_file_destroy)
363 {
364 Sync();
365 delete m_file;
366 }
367}
368
369size_t wxFFileOutputStream::OnSysWrite(const void *buffer, size_t size)
370{
371 size_t ret = m_file->Write(buffer, size);
372 // It is not safe to call Error() if the file is not opened.
373 if (!m_file->IsOpened() || m_file->Error())
374 m_lasterror = wxSTREAM_WRITE_ERROR;
375 else
376 m_lasterror = wxSTREAM_NO_ERROR;
377 return ret;
378}
379
380wxFileOffset wxFFileOutputStream::OnSysTell() const
381{
382 return m_file->Tell();
383}
384
385wxFileOffset wxFFileOutputStream::OnSysSeek(wxFileOffset pos, wxSeekMode mode)
386{
387 return m_file->Seek(pos, mode) ? m_file->Tell() : wxInvalidOffset;
388}
389
390void wxFFileOutputStream::Sync()
391{
392 wxOutputStream::Sync();
393 m_file->Flush();
394}
395
396wxFileOffset wxFFileOutputStream::GetLength() const
397{
398 return m_file->Length();
399}
400
401bool wxFFileOutputStream::IsOk() const
402{
403 return wxStreamBase::IsOk() && m_file->IsOpened();
404}
405
406// ----------------------------------------------------------------------------
407// wxFFileStream
408// ----------------------------------------------------------------------------
409
410wxFFileStream::wxFFileStream(const wxString& fileName, const wxString& mode)
411 : wxFFileInputStream(),
412 wxFFileOutputStream()
413{
414 wxASSERT_MSG( mode.find_first_of('+') != wxString::npos,
415 "must be opened in read-write mode for this class to work" );
416
417 wxFFileOutputStream::m_file =
418 wxFFileInputStream::m_file = new wxFFile(fileName, mode);
419
420 // see comment in wxFileStream ctor
421 wxFFileInputStream::m_file_destroy = true;
422}
423
424bool wxFFileStream::IsOk() const
425{
426 return wxFFileOutputStream::IsOk() && wxFFileInputStream::IsOk();
427}
428
429#endif //wxUSE_FFILE
430
431#endif // wxUSE_STREAMS