]> git.saurik.com Git - wxWidgets.git/blame - src/common/wfstream.cpp
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / src / common / wfstream.cpp
CommitLineData
3d4c6a21 1/////////////////////////////////////////////////////////////////////////////
80fdcdb9 2// Name: src/common/wfstream.cpp
3d4c6a21
GL
3// Purpose: "File stream" classes
4// Author: Julian Smart
5// Modified by:
6// Created: 11/07/98
7// RCS-ID: $Id$
f6bcfd97 8// Copyright: (c) Guilhem Lavaux
65571936 9// Licence: wxWindows licence
3d4c6a21
GL
10/////////////////////////////////////////////////////////////////////////////
11
79c3e0e1
GL
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
3d4c6a21 14
79c3e0e1 15#ifdef __BORLANDC__
530ecef0 16 #pragma hdrstop
79c3e0e1
GL
17#endif
18
85990624 19#if wxUSE_STREAMS
ce4169a4 20
d1af991f 21#include "wx/wfstream.h"
ce4169a4 22
530ecef0
WS
23#ifndef WX_PRECOMP
24 #include "wx/stream.h"
25#endif
26
27#include <stdio.h>
28
85990624
RN
29#if wxUSE_FILE
30
79c3e0e1
GL
31// ----------------------------------------------------------------------------
32// wxFileInputStream
33// ----------------------------------------------------------------------------
34
35wxFileInputStream::wxFileInputStream(const wxString& fileName)
25c70b07 36 : wxInputStream()
3d4c6a21 37{
9adf4299 38 m_file = new wxFile(fileName, wxFile::read);
cab1a605 39 m_file_destroy = true;
b9698194
VZ
40 if ( !m_file->IsOpened() )
41 m_lasterror = wxSTREAM_READ_ERROR;
3d4c6a21
GL
42}
43
25c70b07
GL
44wxFileInputStream::wxFileInputStream()
45 : wxInputStream()
46{
cab1a605 47 m_file_destroy = false;
f6bcfd97 48 m_file = NULL;
25c70b07
GL
49}
50
0aca1ded
GL
51wxFileInputStream::wxFileInputStream(wxFile& file)
52{
f6bcfd97 53 m_file = &file;
cab1a605 54 m_file_destroy = false;
0aca1ded
GL
55}
56
57wxFileInputStream::wxFileInputStream(int fd)
58{
f6bcfd97 59 m_file = new wxFile(fd);
cab1a605 60 m_file_destroy = true;
0aca1ded
GL
61}
62
79c3e0e1 63wxFileInputStream::~wxFileInputStream()
3d4c6a21 64{
f6bcfd97
BP
65 if (m_file_destroy)
66 delete m_file;
3d4c6a21
GL
67}
68
588066b7 69wxFileOffset wxFileInputStream::GetLength() const
84b46c35 70{
f6bcfd97 71 return m_file->Length();
84b46c35
GL
72}
73
75ed1d15 74size_t wxFileInputStream::OnSysRead(void *buffer, size_t size)
6d44bf31 75{
f8a586e0 76 ssize_t ret = m_file->Read(buffer, size);
fae05df5 77
e69a1ea8 78 // NB: we can't use a switch here because HP-UX CC doesn't allow
30984dea 79 // switching over long long (which size_t is in 64bit mode)
9a26db9e 80
e69a1ea8
VZ
81 if ( !ret )
82 {
83 // nothing read, so nothing more to read
84 m_lasterror = wxSTREAM_EOF;
85 }
f8a586e0 86 else if ( ret == wxInvalidOffset )
e69a1ea8
VZ
87 {
88 m_lasterror = wxSTREAM_READ_ERROR;
89 ret = 0;
90 }
91 else
92 {
93 // normal case
94 m_lasterror = wxSTREAM_NO_ERROR;
f6bcfd97 95 }
fae05df5 96
f6bcfd97 97 return ret;
6d44bf31
GL
98}
99
4004775e 100wxFileOffset wxFileInputStream::OnSysSeek(wxFileOffset pos, wxSeekMode mode)
3d4c6a21 101{
9a26db9e 102 return m_file->Seek(pos, mode);
79c3e0e1
GL
103}
104
4004775e 105wxFileOffset wxFileInputStream::OnSysTell() const
79c3e0e1 106{
f6bcfd97 107 return m_file->Tell();
79c3e0e1
GL
108}
109
a6ac8d75
VZ
110bool wxFileInputStream::IsOk() const
111{
92bf6cc1 112 return wxInputStream::IsOk() && m_file->IsOpened();
f02f4d43
SC
113}
114
79c3e0e1
GL
115// ----------------------------------------------------------------------------
116// wxFileOutputStream
117// ----------------------------------------------------------------------------
118
119wxFileOutputStream::wxFileOutputStream(const wxString& fileName)
25c70b07 120{
9adf4299 121 m_file = new wxFile(fileName, wxFile::write);
cab1a605 122 m_file_destroy = true;
9a26db9e 123
942bef71 124 if (!m_file->IsOpened())
942bef71 125 m_lasterror = wxSTREAM_WRITE_ERROR;
25c70b07
GL
126}
127
84b46c35
GL
128wxFileOutputStream::wxFileOutputStream(wxFile& file)
129{
f6bcfd97 130 m_file = &file;
cab1a605 131 m_file_destroy = false;
84b46c35
GL
132}
133
25c70b07 134wxFileOutputStream::wxFileOutputStream()
9a26db9e 135 : wxOutputStream()
79c3e0e1 136{
cab1a605 137 m_file_destroy = false;
f6bcfd97 138 m_file = NULL;
3d4c6a21
GL
139}
140
0aca1ded
GL
141wxFileOutputStream::wxFileOutputStream(int fd)
142{
f6bcfd97 143 m_file = new wxFile(fd);
cab1a605 144 m_file_destroy = true;
0aca1ded
GL
145}
146
79c3e0e1 147wxFileOutputStream::~wxFileOutputStream()
3d4c6a21 148{
9a26db9e 149 if (m_file_destroy)
f6bcfd97
BP
150 {
151 Sync();
152 delete m_file;
153 }
79c3e0e1 154}
3d4c6a21 155
75ed1d15 156size_t wxFileOutputStream::OnSysWrite(const void *buffer, size_t size)
79c3e0e1 157{
f6bcfd97 158 size_t ret = m_file->Write(buffer, size);
9a26db9e
VZ
159
160 m_lasterror = m_file->Error() ? wxSTREAM_WRITE_ERROR : wxSTREAM_NO_ERROR;
161
f6bcfd97 162 return ret;
79c3e0e1 163}
3d4c6a21 164
4004775e 165wxFileOffset wxFileOutputStream::OnSysTell() const
79c3e0e1 166{
f6bcfd97 167 return m_file->Tell();
3d4c6a21
GL
168}
169
4004775e 170wxFileOffset wxFileOutputStream::OnSysSeek(wxFileOffset pos, wxSeekMode mode)
3d4c6a21 171{
f6bcfd97 172 return m_file->Seek(pos, mode);
3d4c6a21
GL
173}
174
79c3e0e1 175void wxFileOutputStream::Sync()
3d4c6a21 176{
f6bcfd97
BP
177 wxOutputStream::Sync();
178 m_file->Flush();
3d4c6a21 179}
84b46c35 180
588066b7 181wxFileOffset wxFileOutputStream::GetLength() const
84b46c35 182{
f6bcfd97 183 return m_file->Length();
84b46c35
GL
184}
185
a6ac8d75
VZ
186bool wxFileOutputStream::IsOk() const
187{
92bf6cc1 188 return wxOutputStream::IsOk() && m_file->IsOpened();
f02f4d43
SC
189}
190
84b46c35 191// ----------------------------------------------------------------------------
e1265174
MW
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// ----------------------------------------------------------------------------
84b46c35
GL
219// wxFileStream
220// ----------------------------------------------------------------------------
f6bcfd97 221
84b46c35 222wxFileStream::wxFileStream(const wxString& fileName)
02e22828
VZ
223 : wxFileInputStream(),
224 wxFileOutputStream()
84b46c35 225{
02e22828
VZ
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;
84b46c35 233}
ce4169a4 234
a6ac8d75
VZ
235bool wxFileStream::IsOk() const
236{
92bf6cc1 237 return wxFileOutputStream::IsOk() && wxFileInputStream::IsOk();
a6ac8d75
VZ
238}
239
92bf6cc1 240#endif // wxUSE_FILE
85990624
RN
241
242#if wxUSE_FFILE
243
65045edd
RR
244// ----------------------------------------------------------------------------
245// wxFFileInputStream
246// ----------------------------------------------------------------------------
247
5fec5bb6 248wxFFileInputStream::wxFFileInputStream(const wxString& fileName,
dc65c743 249 const wxString& mode)
5fec5bb6 250 : wxInputStream()
65045edd 251{
5fec5bb6 252 m_file = new wxFFile(fileName, mode);
cab1a605 253 m_file_destroy = true;
ecc20148
MW
254
255 if (!m_file->IsOpened())
256 m_lasterror = wxSTREAM_WRITE_ERROR;
65045edd
RR
257}
258
259wxFFileInputStream::wxFFileInputStream()
5fec5bb6 260 : wxInputStream()
65045edd 261{
f6bcfd97 262 m_file = NULL;
5fec5bb6 263 m_file_destroy = false;
65045edd
RR
264}
265
266wxFFileInputStream::wxFFileInputStream(wxFFile& file)
267{
f6bcfd97 268 m_file = &file;
cab1a605 269 m_file_destroy = false;
65045edd
RR
270}
271
272wxFFileInputStream::wxFFileInputStream(FILE *file)
273{
f6bcfd97 274 m_file = new wxFFile(file);
cab1a605 275 m_file_destroy = true;
65045edd
RR
276}
277
278wxFFileInputStream::~wxFFileInputStream()
279{
f6bcfd97
BP
280 if (m_file_destroy)
281 delete m_file;
65045edd
RR
282}
283
588066b7 284wxFileOffset wxFFileInputStream::GetLength() const
65045edd 285{
f6bcfd97 286 return m_file->Length();
65045edd
RR
287}
288
289size_t wxFFileInputStream::OnSysRead(void *buffer, size_t size)
290{
f8a586e0 291 ssize_t ret = m_file->Read(buffer, size);
65045edd 292
b9d84e4c
DE
293 // It is not safe to call Eof() if the file is not opened.
294 if (!m_file->IsOpened() || m_file->Eof())
2b5f62a0 295 m_lasterror = wxSTREAM_EOF;
f8a586e0 296 if (ret == wxInvalidOffset)
f6bcfd97 297 {
2b5f62a0 298 m_lasterror = wxSTREAM_READ_ERROR;
f6bcfd97
BP
299 ret = 0;
300 }
65045edd 301
f6bcfd97 302 return ret;
65045edd
RR
303}
304
4004775e 305wxFileOffset wxFFileInputStream::OnSysSeek(wxFileOffset pos, wxSeekMode mode)
65045edd 306{
70a7bd90 307 return m_file->Seek(pos, mode) ? m_file->Tell() : wxInvalidOffset;
65045edd
RR
308}
309
4004775e 310wxFileOffset wxFFileInputStream::OnSysTell() const
65045edd 311{
f6bcfd97 312 return m_file->Tell();
65045edd
RR
313}
314
a6ac8d75
VZ
315bool wxFFileInputStream::IsOk() const
316{
317 return wxStreamBase::IsOk() && m_file->IsOpened();
f02f4d43
SC
318}
319
65045edd
RR
320// ----------------------------------------------------------------------------
321// wxFFileOutputStream
322// ----------------------------------------------------------------------------
323
5fec5bb6 324wxFFileOutputStream::wxFFileOutputStream(const wxString& fileName,
dc65c743 325 const wxString& mode)
65045edd 326{
5fec5bb6 327 m_file = new wxFFile(fileName, mode);
cab1a605 328 m_file_destroy = true;
9a26db9e 329
942bef71
RR
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 }
65045edd
RR
339}
340
341wxFFileOutputStream::wxFFileOutputStream(wxFFile& file)
342{
f6bcfd97 343 m_file = &file;
cab1a605 344 m_file_destroy = false;
65045edd
RR
345}
346
347wxFFileOutputStream::wxFFileOutputStream()
5fec5bb6 348 : wxOutputStream()
65045edd 349{
f6bcfd97 350 m_file = NULL;
5fec5bb6 351 m_file_destroy = false;
65045edd
RR
352}
353
354wxFFileOutputStream::wxFFileOutputStream(FILE *file)
355{
f6bcfd97 356 m_file = new wxFFile(file);
cab1a605 357 m_file_destroy = true;
65045edd
RR
358}
359
360wxFFileOutputStream::~wxFFileOutputStream()
361{
9a26db9e 362 if (m_file_destroy)
f6bcfd97
BP
363 {
364 Sync();
365 delete m_file;
366 }
65045edd
RR
367}
368
369size_t wxFFileOutputStream::OnSysWrite(const void *buffer, size_t size)
370{
f6bcfd97 371 size_t ret = m_file->Write(buffer, size);
b9d84e4c
DE
372 // It is not safe to call Error() if the file is not opened.
373 if (!m_file->IsOpened() || m_file->Error())
2b5f62a0 374 m_lasterror = wxSTREAM_WRITE_ERROR;
f6bcfd97 375 else
2b5f62a0 376 m_lasterror = wxSTREAM_NO_ERROR;
f6bcfd97 377 return ret;
65045edd
RR
378}
379
4004775e 380wxFileOffset wxFFileOutputStream::OnSysTell() const
65045edd 381{
f6bcfd97 382 return m_file->Tell();
65045edd
RR
383}
384
4004775e 385wxFileOffset wxFFileOutputStream::OnSysSeek(wxFileOffset pos, wxSeekMode mode)
65045edd 386{
70a7bd90 387 return m_file->Seek(pos, mode) ? m_file->Tell() : wxInvalidOffset;
65045edd
RR
388}
389
390void wxFFileOutputStream::Sync()
391{
f6bcfd97
BP
392 wxOutputStream::Sync();
393 m_file->Flush();
65045edd
RR
394}
395
588066b7 396wxFileOffset wxFFileOutputStream::GetLength() const
65045edd 397{
f6bcfd97 398 return m_file->Length();
65045edd
RR
399}
400
a6ac8d75
VZ
401bool wxFFileOutputStream::IsOk() const
402{
403 return wxStreamBase::IsOk() && m_file->IsOpened();
f02f4d43
SC
404}
405
65045edd
RR
406// ----------------------------------------------------------------------------
407// wxFFileStream
408// ----------------------------------------------------------------------------
f6bcfd97 409
02e22828
VZ
410wxFFileStream::wxFFileStream(const wxString& fileName, const wxString& mode)
411 : wxFFileInputStream(),
412 wxFFileOutputStream()
65045edd 413{
02e22828
VZ
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;
65045edd 422}
f6bcfd97 423
92bf6cc1
VZ
424bool wxFFileStream::IsOk() const
425{
426 return wxFFileOutputStream::IsOk() && wxFFileInputStream::IsOk();
427}
428
85990624
RN
429#endif //wxUSE_FFILE
430
431#endif // wxUSE_STREAMS