]> git.saurik.com Git - wxWidgets.git/blob - src/common/file.cpp
6c6ae4acc553a189c3bfd92bc01dcaa30e43fa5f
[wxWidgets.git] / src / common / file.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: file.cpp
3 // Purpose: wxFile - encapsulates low-level "file descriptor"
4 // wxTempFile
5 // Author: Vadim Zeitlin
6 // Modified by:
7 // Created: 29/01/98
8 // RCS-ID: $Id$
9 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
10 // Licence: wxWindows license
11 /////////////////////////////////////////////////////////////////////////////
12
13 // ----------------------------------------------------------------------------
14 // headers
15 // ----------------------------------------------------------------------------
16
17 #ifdef __GNUG__
18 #pragma implementation "file.h"
19 #endif
20
21 // For compilers that support precompilation, includes "wx.h".
22 #include "wx/wxprec.h"
23 #include "wx/defs.h"
24
25 #ifdef __BORLANDC__
26 #pragma hdrstop
27 #endif
28
29 // standard
30 #if defined(__WINDOWS__) && !defined(__GNUWIN32__)
31 #include <io.h>
32 #elif (defined(__UNIX__) || defined(__GNUWIN32__))
33 #include <unistd.h>
34 #else
35 #error "Please specify the header with file functions declarations."
36 #endif //Win/UNIX
37
38 #include <stdio.h> // SEEK_xxx constants
39 #include <fcntl.h> // O_RDONLY &c
40 #include <sys/types.h> // needed for stat
41 #include <sys/stat.h> // stat
42
43 // Microsoft compiler loves underscores, feed them to it
44 #ifdef _MSC_VER
45 // functions
46 #define open _open
47 #define close _close
48 #define read _read
49 #define write _write
50 #define lseek _lseek
51 #define fsync _commit
52 #define access _access
53 #define eof _eof
54
55 // types
56 #define stat _stat
57
58 // constants
59 #define O_RDONLY _O_RDONLY
60 #define O_WRONLY _O_WRONLY
61 #define O_RDWR _O_RDWR
62 #define O_EXCL _O_EXCL
63 #define O_CREAT _O_CREAT
64 #define O_BINARY _O_BINARY
65
66 #define S_IFDIR _S_IFDIR
67 #define S_IFREG _S_IFREG
68
69 #define S_IREAD _S_IREAD
70 #define S_IWRITE _S_IWRITE
71 #else
72 #define tell(fd) lseek(fd, 0, SEEK_CUR)
73 #endif //_MSC_VER
74
75 // there is no distinction between text and binary files under Unix
76 #ifdef __UNIX__
77 #define O_BINARY (0)
78 #endif //__UNIX__
79
80 // wxWindows
81 #include <wx/string.h>
82 #include <wx/intl.h>
83 #include <wx/file.h>
84 #include <wx/log.h>
85
86
87 // ============================================================================
88 // implementation of wxFile
89 // ============================================================================
90
91 // ----------------------------------------------------------------------------
92 // static functions
93 // ----------------------------------------------------------------------------
94 bool wxFile::Exists(const char *sz)
95 {
96 struct stat st;
97 return !access(sz, 0) && !stat(sz, &st) && (st.st_mode & S_IFREG);
98 }
99
100 // ----------------------------------------------------------------------------
101 // opening/closing
102 // ----------------------------------------------------------------------------
103
104 // ctors
105 wxFile::wxFile(const char *szFileName, OpenMode mode)
106 {
107 m_fd = fd_invalid;
108
109 Open(szFileName, mode);
110 }
111
112 // dtor
113 wxFile::~wxFile()
114 {
115 Close();
116 }
117
118 // create the file, fail if it already exists and bOverwrite
119 bool wxFile::Create(const char *szFileName, bool bOverwrite)
120 {
121 // if bOverwrite we create a new file or truncate the existing one,
122 // otherwise we only create the new file and fail if it already exists
123 int fd = bOverwrite ? creat(szFileName, 0)
124 : open(szFileName, O_CREAT | O_EXCL);
125
126 if ( fd == -1 ) {
127 wxLogSysError("can't create file '%s'", szFileName);
128 return FALSE;
129 }
130 else {
131 Attach(fd);
132 return TRUE;
133 }
134 }
135
136 // open the file
137 bool wxFile::Open(const char *szFileName, OpenMode mode)
138 {
139 int flags = O_BINARY;
140
141 switch ( mode ) {
142 case read:
143 flags |= O_RDONLY;
144 break;
145
146 case write:
147 flags |= O_WRONLY | O_CREAT;
148 break;
149
150 case read_write:
151 flags |= O_RDWR;
152 break;
153 }
154
155 int fd = open(szFileName, flags, S_IREAD | S_IWRITE);
156
157 if ( fd == -1 ) {
158 wxLogSysError("can't open file '%s'", szFileName);
159 return FALSE;
160 }
161 else {
162 Attach(fd);
163 return TRUE;
164 }
165 }
166
167 // close
168 void wxFile::Close()
169 {
170 if ( IsOpened() ) {
171 if ( close(m_fd) == -1 )
172 wxLogSysError("can't close file descriptor %d", m_fd);
173
174 m_fd = fd_invalid;
175 }
176 }
177
178 // ----------------------------------------------------------------------------
179 // read/write
180 // ----------------------------------------------------------------------------
181
182 // read
183 off_t wxFile::Read(void *pBuf, off_t nCount)
184 {
185 wxCHECK_RET( (pBuf != NULL) && IsOpened(), 0 );
186
187 int iRc = ::read(m_fd, pBuf, nCount);
188 if ( iRc == -1 ) {
189 wxLogSysError("can't read from file descriptor %d", m_fd);
190 return ofsInvalid;
191 }
192 else
193 return (uint)iRc;
194 }
195
196 // write
197 bool wxFile::Write(const void *pBuf, uint nCount)
198 {
199 wxCHECK_RET( (pBuf != NULL) && IsOpened(), 0 );
200
201 int iRc = ::write(m_fd, pBuf, nCount);
202 if ( iRc == -1 ) {
203 wxLogSysError("can't write to file descriptor %d", m_fd);
204 return FALSE;
205 }
206 else
207 return TRUE;
208 }
209
210 // flush
211 bool wxFile::Flush()
212 {
213 if ( IsOpened() ) {
214 // ## fsync() is not ANSI (BSDish)
215 // if ( fsync(m_fd) == -1 ) { // TODO
216 if (TRUE) {
217 wxLogSysError("can't flush file descriptor %d", m_fd);
218 return FALSE;
219 }
220 }
221
222 return TRUE;
223 }
224
225 // ----------------------------------------------------------------------------
226 // seek
227 // ----------------------------------------------------------------------------
228
229 // seek
230 off_t wxFile::Seek(off_t ofs, SeekMode mode)
231 {
232 wxASSERT( IsOpened() );
233
234 int flag = -1;
235 switch ( mode ) {
236 case FromStart:
237 flag = SEEK_SET;
238 break;
239
240 case FromCurrent:
241 flag = SEEK_CUR;
242 break;
243
244 case FromEnd:
245 flag = SEEK_END;
246 break;
247
248 default:
249 wxFAIL_MSG("unknown seek origin");
250 }
251
252 int iRc = lseek(m_fd, ofs, flag);
253 if ( iRc == -1 ) {
254 wxLogSysError("can't seek on file descriptor %d", m_fd);
255 return ofsInvalid;
256 }
257 else
258 return (off_t)iRc;
259 }
260
261 // get current off_t
262 off_t wxFile::Tell() const
263 {
264 wxASSERT( IsOpened() );
265
266 int iRc = tell(m_fd);
267 if ( iRc == -1 ) {
268 wxLogSysError("can't get seek position on file descriptor %d", m_fd);
269 return ofsInvalid;
270 }
271 else
272 return (off_t)iRc;
273 }
274
275 // get current file length
276 off_t wxFile::Length() const
277 {
278 wxASSERT( IsOpened() );
279
280 #ifdef _MSC_VER
281 int iRc = _filelength(m_fd);
282 #else
283 int iRc = tell(m_fd);
284 if ( iRc != -1 ) {
285 // # have to use const_cast :-(
286 int iLen = ((wxFile *)this)->SeekEnd();
287 if ( iLen != -1 ) {
288 // restore old position
289 if ( ((wxFile *)this)->Seek(iRc) == -1 ) {
290 // error
291 iLen = -1;
292 }
293 }
294
295 iRc = iLen;
296 }
297
298 #endif //_MSC_VER
299
300 if ( iRc == -1 ) {
301 wxLogSysError("can't find length of file on file descriptor %d", m_fd);
302 return ofsInvalid;
303 }
304 else
305 return (off_t)iRc;
306 }
307
308 // is end of file reached?
309 bool wxFile::Eof() const
310 {
311 wxASSERT( IsOpened() );
312
313 // TODO: no eof in GnuWin32
314
315 #ifdef __LINUX__
316
317 int iRc = Tell() == Length();
318
319 #else
320
321 #if defined(__GNUWIN32__)
322 int iRc = -1;
323 #else
324 int iRc = eof(m_fd);
325 #endif
326
327 #endif
328
329 switch ( iRc ) {
330 case 1:
331 break;
332
333 case 0:
334 return FALSE;
335
336 case -1:
337 wxLogSysError("can't determine if the end of file is reached on "
338 "descriptor %d", m_fd);
339 break;
340
341 default:
342 wxFAIL_MSG("invalid eof() return value.");
343 }
344
345 return TRUE;
346 }
347
348 // ============================================================================
349 // implementation of wxTempFile
350 // ============================================================================
351
352 // ----------------------------------------------------------------------------
353 // construction
354 // ----------------------------------------------------------------------------
355 wxTempFile::wxTempFile(const wxString& strName)
356 {
357 Open(strName);
358 }
359
360 bool wxTempFile::Open(const wxString& strName)
361 {
362 m_strName = strName;
363 m_strTemp = tmpnam(NULL);
364 return m_file.Open(m_strTemp, wxFile::write);
365 }
366
367 // ----------------------------------------------------------------------------
368 // destruction
369 // ----------------------------------------------------------------------------
370
371 wxTempFile::~wxTempFile()
372 {
373 if ( IsOpened() )
374 Discard();
375 }
376
377 bool wxTempFile::Commit()
378 {
379 m_file.Close();
380
381 if ( wxFile::Exists(m_strName) && remove(m_strName) != 0 ) {
382 wxLogSysError("can't remove file '%s'", m_strName.c_str());
383 return FALSE;
384 }
385
386 if ( rename(m_strTemp, m_strName) != 0 ) {
387 wxLogSysError("can't commit changes to file '%s'", m_strName.c_str());
388 return FALSE;
389 }
390
391 return TRUE;
392 }
393
394 void wxTempFile::Discard()
395 {
396 m_file.Close();
397 if ( remove(m_strTemp) != 0 )
398 wxLogSysError("can't remove temporary file '%s'", m_strTemp.c_str());
399 }