]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/ffile.cpp
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / src / common / ffile.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/common/ffile.cpp
3// Purpose: wxFFile encapsulates "FILE *" IO stream
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 14.07.99
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#if wxUSE_FFILE
28
29#ifndef WX_PRECOMP
30 #include "wx/intl.h"
31 #include "wx/log.h"
32 #include "wx/crt.h"
33#endif
34
35#ifdef __WINDOWS__
36#include "wx/msw/mslu.h"
37#endif
38
39#include "wx/ffile.h"
40
41// ============================================================================
42// implementation
43// ============================================================================
44
45// ----------------------------------------------------------------------------
46// opening the file
47// ----------------------------------------------------------------------------
48
49wxFFile::wxFFile(const wxString& filename, const wxString& mode)
50{
51 Detach();
52
53 (void)Open(filename, mode);
54}
55
56bool wxFFile::Open(const wxString& filename, const wxString& mode)
57{
58 wxASSERT_MSG( !m_fp, wxT("should close or detach the old file first") );
59
60 m_fp = wxFopen(filename, mode);
61
62 if ( !m_fp )
63 {
64 wxLogSysError(_("can't open file '%s'"), filename);
65
66 return false;
67 }
68
69 m_name = filename;
70
71 return true;
72}
73
74bool wxFFile::Close()
75{
76 if ( IsOpened() )
77 {
78 if ( fclose(m_fp) != 0 )
79 {
80 wxLogSysError(_("can't close file '%s'"), m_name.c_str());
81
82 return false;
83 }
84
85 Detach();
86 }
87
88 return true;
89}
90
91// ----------------------------------------------------------------------------
92// read/write
93// ----------------------------------------------------------------------------
94
95bool wxFFile::ReadAll(wxString *str, const wxMBConv& conv)
96{
97 wxCHECK_MSG( str, false, wxT("invalid parameter") );
98 wxCHECK_MSG( IsOpened(), false, wxT("can't read from closed file") );
99 wxCHECK_MSG( Length() >= 0, false, wxT("invalid length") );
100 size_t length = wx_truncate_cast(size_t, Length());
101 wxCHECK_MSG( (wxFileOffset)length == Length(), false, wxT("huge file not supported") );
102
103 clearerr(m_fp);
104
105 wxCharBuffer buf(length + 1);
106
107 // note that real length may be less than file length for text files with DOS EOLs
108 // ('\r's get dropped by CRT when reading which means that we have
109 // realLen = fileLen - numOfLinesInTheFile)
110 length = fread(buf.data(), sizeof(char), length, m_fp);
111
112 if ( Error() )
113 {
114 wxLogSysError(_("Read error on file '%s'"), m_name.c_str());
115
116 return false;
117 }
118
119 buf.data()[length] = 0;
120
121 wxString strTmp(buf, conv);
122 str->swap(strTmp);
123
124 return true;
125}
126
127size_t wxFFile::Read(void *pBuf, size_t nCount)
128{
129 wxCHECK_MSG( pBuf, 0, wxT("invalid parameter") );
130 wxCHECK_MSG( IsOpened(), 0, wxT("can't read from closed file") );
131
132 size_t nRead = fread(pBuf, 1, nCount, m_fp);
133 if ( (nRead < nCount) && Error() )
134 {
135 wxLogSysError(_("Read error on file '%s'"), m_name.c_str());
136 }
137
138 return nRead;
139}
140
141size_t wxFFile::Write(const void *pBuf, size_t nCount)
142{
143 wxCHECK_MSG( pBuf, 0, wxT("invalid parameter") );
144 wxCHECK_MSG( IsOpened(), 0, wxT("can't write to closed file") );
145
146 size_t nWritten = fwrite(pBuf, 1, nCount, m_fp);
147 if ( nWritten < nCount )
148 {
149 wxLogSysError(_("Write error on file '%s'"), m_name.c_str());
150 }
151
152 return nWritten;
153}
154
155bool wxFFile::Write(const wxString& s, const wxMBConv& conv)
156{
157 const wxWX2MBbuf buf = s.mb_str(conv);
158 if ( !buf )
159 return false;
160
161 const size_t size = strlen(buf); // FIXME: use buf.length() when available
162 return Write(buf, size) == size;
163}
164
165bool wxFFile::Flush()
166{
167 if ( IsOpened() )
168 {
169 if ( fflush(m_fp) != 0 )
170 {
171 wxLogSysError(_("failed to flush the file '%s'"), m_name.c_str());
172
173 return false;
174 }
175 }
176
177 return true;
178}
179
180// ----------------------------------------------------------------------------
181// seeking
182// ----------------------------------------------------------------------------
183
184bool wxFFile::Seek(wxFileOffset ofs, wxSeekMode mode)
185{
186 wxCHECK_MSG( IsOpened(), false, wxT("can't seek on closed file") );
187
188 int origin;
189 switch ( mode )
190 {
191 default:
192 wxFAIL_MSG(wxT("unknown seek mode"));
193 // still fall through
194
195 case wxFromStart:
196 origin = SEEK_SET;
197 break;
198
199 case wxFromCurrent:
200 origin = SEEK_CUR;
201 break;
202
203 case wxFromEnd:
204 origin = SEEK_END;
205 break;
206 }
207
208#ifndef wxHAS_LARGE_FFILES
209 if ((long)ofs != ofs)
210 {
211 wxLogError(_("Seek error on file '%s' (large files not supported by stdio)"), m_name.c_str());
212
213 return false;
214 }
215
216 if ( wxFseek(m_fp, (long)ofs, origin) != 0 )
217#else
218 if ( wxFseek(m_fp, ofs, origin) != 0 )
219#endif
220 {
221 wxLogSysError(_("Seek error on file '%s'"), m_name.c_str());
222
223 return false;
224 }
225
226 return true;
227}
228
229wxFileOffset wxFFile::Tell() const
230{
231 wxCHECK_MSG( IsOpened(), wxInvalidOffset,
232 wxT("wxFFile::Tell(): file is closed!") );
233
234 wxFileOffset rc = wxFtell(m_fp);
235 if ( rc == wxInvalidOffset )
236 {
237 wxLogSysError(_("Can't find current position in file '%s'"),
238 m_name.c_str());
239 }
240
241 return rc;
242}
243
244wxFileOffset wxFFile::Length() const
245{
246 wxCHECK_MSG( IsOpened(), wxInvalidOffset,
247 wxT("wxFFile::Length(): file is closed!") );
248
249 wxFFile& self = *const_cast<wxFFile *>(this);
250
251 wxFileOffset posOld = Tell();
252 if ( posOld != wxInvalidOffset )
253 {
254 if ( self.SeekEnd() )
255 {
256 wxFileOffset len = Tell();
257
258 (void)self.Seek(posOld);
259
260 return len;
261 }
262 }
263
264 return wxInvalidOffset;
265}
266
267#endif // wxUSE_FFILE