]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/file.cpp
wxFileSystem w/o wxUSE_MIMETYPE fixes
[wxWidgets.git] / src / common / file.cpp
... / ...
CommitLineData
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
24#ifdef __BORLANDC__
25 #pragma hdrstop
26#endif
27
28#if wxUSE_FILE
29
30// standard
31#if defined(__WXMSW__) && !defined(__GNUWIN32__) && !defined(__WXWINE__) && !defined(__WXMICROWIN__)
32 #include <io.h>
33
34#ifndef __SALFORDC__
35 #define WIN32_LEAN_AND_MEAN
36 #define NOSERVICE
37 #define NOIME
38 #define NOATOM
39 #define NOGDI
40 #define NOGDICAPMASKS
41 #define NOMETAFILE
42 #define NOMINMAX
43 #define NOMSG
44 #define NOOPENFILE
45 #define NORASTEROPS
46 #define NOSCROLL
47 #define NOSOUND
48 #define NOSYSMETRICS
49 #define NOTEXTMETRIC
50 #define NOWH
51 #define NOCOMM
52 #define NOKANJI
53 #define NOCRYPT
54 #define NOMCX
55#endif
56
57#elif (defined(__UNIX__) || defined(__GNUWIN32__))
58 #include <unistd.h>
59 #ifdef __GNUWIN32__
60 #include <windows.h>
61 #endif
62#elif defined(__DOS__) && defined(__WATCOMC__)
63 #include <io.h>
64 char* mktemp(char *path) { return _mktemp(path); }
65#elif (defined(__WXPM__))
66 #include <io.h>
67 #define W_OK 2
68 #define R_OK 4
69#elif (defined(__WXSTUBS__))
70 // Have to ifdef this for different environments
71 #include <io.h>
72#elif (defined(__WXMAC__))
73#if __MSL__ < 0x6000
74 int access( const char *path, int mode ) { return 0 ; }
75#else
76 int _access( const char *path, int mode ) { return 0 ; }
77#endif
78 char* mktemp( char * path ) { return path ;}
79 #include <stat.h>
80 #define W_OK 2
81 #define R_OK 4
82 #include <unistd.h>
83#else
84 #error "Please specify the header with file functions declarations."
85#endif //Win/UNIX
86
87#include <stdio.h> // SEEK_xxx constants
88#include <fcntl.h> // O_RDONLY &c
89
90#ifndef __MWERKS__
91 #include <sys/types.h> // needed for stat
92 #include <sys/stat.h> // stat
93#elif ( defined(__MWERKS__) && defined(__WXMSW__) )
94 #include <sys/types.h> // needed for stat
95 #include <sys/stat.h> // stat
96#endif
97
98#if defined(__BORLANDC__) || defined(_MSC_VER)
99 #define W_OK 2
100 #define R_OK 4
101#endif
102
103// there is no distinction between text and binary files under Unix, so define
104// O_BINARY as 0 if the system headers don't do it already
105#if defined(__UNIX__) && !defined(O_BINARY)
106 #define O_BINARY (0)
107#endif //__UNIX__
108
109#ifdef __SALFORDC__
110 #include <unix.h>
111#endif
112
113#ifndef MAX_PATH
114 #define MAX_PATH 512
115#endif
116
117// some broken compilers don't have 3rd argument in open() and creat()
118#ifdef __SALFORDC__
119 #define ACCESS(access)
120 #define stat _stat
121#else // normal compiler
122 #define ACCESS(access) , (access)
123#endif // Salford C
124
125// wxWindows
126#ifndef WX_PRECOMP
127 #include "wx/string.h"
128 #include "wx/intl.h"
129 #include "wx/log.h"
130#endif // !WX_PRECOMP
131
132#include "wx/filename.h"
133#include "wx/file.h"
134
135// ============================================================================
136// implementation of wxFile
137// ============================================================================
138
139// ----------------------------------------------------------------------------
140// static functions
141// ----------------------------------------------------------------------------
142bool wxFile::Exists(const wxChar *name)
143{
144 wxStructStat st;
145#if wxUSE_UNICODE && wxMBFILES
146 wxCharBuffer fname = wxConvFile.cWC2MB(name);
147
148 return !wxAccess(fname, 0) &&
149 !wxStat(wxMBSTRINGCAST fname, &st) &&
150 (st.st_mode & S_IFREG);
151
152#else
153 return !wxAccess(name, 0) &&
154 !wxStat(name, &st) &&
155 (st.st_mode & S_IFREG);
156#endif
157}
158
159bool wxFile::Access(const wxChar *name, OpenMode mode)
160{
161 int how = 0;
162
163 switch ( mode ) {
164 case read:
165 how = R_OK;
166 break;
167
168 case write:
169 how = W_OK;
170 break;
171
172 default:
173 wxFAIL_MSG(wxT("bad wxFile::Access mode parameter."));
174 }
175
176 return wxAccess(wxFNCONV(name), how) == 0;
177}
178
179// ----------------------------------------------------------------------------
180// opening/closing
181// ----------------------------------------------------------------------------
182
183// ctors
184wxFile::wxFile(const wxChar *szFileName, OpenMode mode)
185{
186 m_fd = fd_invalid;
187 m_error = FALSE;
188
189 Open(szFileName, mode);
190}
191
192// create the file, fail if it already exists and bOverwrite
193bool wxFile::Create(const wxChar *szFileName, bool bOverwrite, int accessMode)
194{
195 // if bOverwrite we create a new file or truncate the existing one,
196 // otherwise we only create the new file and fail if it already exists
197#if defined(__WXMAC__) && !defined(__UNIX__)
198 // Dominic Mazzoni [dmazzoni+@cs.cmu.edu] reports that open is still broken on the mac, so we replace
199 // int fd = open(wxUnix2MacFilename( szFileName ), O_CREAT | (bOverwrite ? O_TRUNC : O_EXCL), access);
200 int fd = creat( szFileName , accessMode);
201#else
202 int fd = wxOpen(wxFNCONV(szFileName),
203 O_BINARY | O_WRONLY | O_CREAT |
204 (bOverwrite ? O_TRUNC : O_EXCL)
205 ACCESS(accessMode));
206#endif
207 if ( fd == -1 ) {
208 wxLogSysError(_("can't create file '%s'"), szFileName);
209 return FALSE;
210 }
211 else {
212 Attach(fd);
213 return TRUE;
214 }
215}
216
217// open the file
218bool wxFile::Open(const wxChar *szFileName, OpenMode mode, int accessMode)
219{
220 int flags = O_BINARY;
221
222 switch ( mode ) {
223 case read:
224 flags |= O_RDONLY;
225 break;
226
227 case write_append:
228 if ( wxFile::Exists(szFileName) )
229 {
230 flags |= O_WRONLY | O_APPEND;
231 break;
232 }
233 //else: fall through as write_append is the same as write if the
234 // file doesn't exist
235
236 case write:
237 flags |= O_WRONLY | O_CREAT | O_TRUNC;
238 break;
239
240 case write_excl:
241 flags |= O_WRONLY | O_CREAT | O_EXCL;
242 break;
243
244 case read_write:
245 flags |= O_RDWR;
246 break;
247 }
248
249 int fd = wxOpen(wxFNCONV(szFileName), flags ACCESS(accessMode));
250 if ( fd == -1 ) {
251 wxLogSysError(_("can't open file '%s'"), szFileName);
252 return FALSE;
253 }
254 else {
255 Attach(fd);
256 return TRUE;
257 }
258}
259
260// close
261bool wxFile::Close()
262{
263 if ( IsOpened() ) {
264 if ( close(m_fd) == -1 ) {
265 wxLogSysError(_("can't close file descriptor %d"), m_fd);
266 m_fd = fd_invalid;
267 return FALSE;
268 }
269 else
270 m_fd = fd_invalid;
271 }
272
273 return TRUE;
274}
275
276// ----------------------------------------------------------------------------
277// read/write
278// ----------------------------------------------------------------------------
279
280// read
281off_t wxFile::Read(void *pBuf, off_t nCount)
282{
283 wxCHECK( (pBuf != NULL) && IsOpened(), 0 );
284
285#ifdef __MWERKS__
286 int iRc = ::read(m_fd, (char*) pBuf, nCount);
287#else
288 int iRc = ::read(m_fd, pBuf, nCount);
289#endif
290 if ( iRc == -1 ) {
291 wxLogSysError(_("can't read from file descriptor %d"), m_fd);
292 return wxInvalidOffset;
293 }
294 else
295 return (size_t)iRc;
296}
297
298// write
299size_t wxFile::Write(const void *pBuf, size_t nCount)
300{
301 wxCHECK( (pBuf != NULL) && IsOpened(), 0 );
302
303#ifdef __MWERKS__
304#if __MSL__ >= 0x6000
305 int iRc = ::write(m_fd, (void*) pBuf, nCount);
306#else
307 int iRc = ::write(m_fd, (const char*) pBuf, nCount);
308#endif
309#else
310 int iRc = ::write(m_fd, pBuf, nCount);
311#endif
312 if ( iRc == -1 ) {
313 wxLogSysError(_("can't write to file descriptor %d"), m_fd);
314 m_error = TRUE;
315 return 0;
316 }
317 else
318 return iRc;
319}
320
321// flush
322bool wxFile::Flush()
323{
324 if ( IsOpened() ) {
325#if defined(__VISUALC__) || wxHAVE_FSYNC
326 if ( wxFsync(m_fd) == -1 )
327 {
328 wxLogSysError(_("can't flush file descriptor %d"), m_fd);
329 return FALSE;
330 }
331#else // no fsync
332 // just do nothing
333#endif // fsync
334 }
335
336 return TRUE;
337}
338
339// ----------------------------------------------------------------------------
340// seek
341// ----------------------------------------------------------------------------
342
343// seek
344off_t wxFile::Seek(off_t ofs, wxSeekMode mode)
345{
346 wxASSERT( IsOpened() );
347
348 int origin;
349 switch ( mode ) {
350 default:
351 wxFAIL_MSG(_("unknown seek origin"));
352
353 case wxFromStart:
354 origin = SEEK_SET;
355 break;
356
357 case wxFromCurrent:
358 origin = SEEK_CUR;
359 break;
360
361 case wxFromEnd:
362 origin = SEEK_END;
363 break;
364 }
365
366 int iRc = lseek(m_fd, ofs, origin);
367 if ( iRc == -1 ) {
368 wxLogSysError(_("can't seek on file descriptor %d"), m_fd);
369 return wxInvalidOffset;
370 }
371 else
372 return (off_t)iRc;
373}
374
375// get current off_t
376off_t wxFile::Tell() const
377{
378 wxASSERT( IsOpened() );
379
380 int iRc = wxTell(m_fd);
381 if ( iRc == -1 ) {
382 wxLogSysError(_("can't get seek position on file descriptor %d"), m_fd);
383 return wxInvalidOffset;
384 }
385 else
386 return (off_t)iRc;
387}
388
389// get current file length
390off_t wxFile::Length() const
391{
392 wxASSERT( IsOpened() );
393
394#ifdef __VISUALC__
395 int iRc = _filelength(m_fd);
396#else // !VC++
397 int iRc = wxTell(m_fd);
398 if ( iRc != -1 ) {
399 // @ have to use const_cast :-(
400 int iLen = ((wxFile *)this)->SeekEnd();
401 if ( iLen != -1 ) {
402 // restore old position
403 if ( ((wxFile *)this)->Seek(iRc) == -1 ) {
404 // error
405 iLen = -1;
406 }
407 }
408
409 iRc = iLen;
410 }
411#endif // VC++
412
413 if ( iRc == -1 ) {
414 wxLogSysError(_("can't find length of file on file descriptor %d"), m_fd);
415 return wxInvalidOffset;
416 }
417 else
418 return (off_t)iRc;
419}
420
421// is end of file reached?
422bool wxFile::Eof() const
423{
424 wxASSERT( IsOpened() );
425
426 int iRc;
427
428#if defined(__UNIX__) || defined(__GNUWIN32__) || defined( __MWERKS__ ) || defined(__SALFORDC__)
429 // @@ this doesn't work, of course, on unseekable file descriptors
430 off_t ofsCur = Tell(),
431 ofsMax = Length();
432 if ( ofsCur == wxInvalidOffset || ofsMax == wxInvalidOffset )
433 iRc = -1;
434 else
435 iRc = ofsCur == ofsMax;
436#else // Windows and "native" compiler
437 iRc = eof(m_fd);
438#endif // Windows/Unix
439
440 switch ( iRc ) {
441 case 1:
442 break;
443
444 case 0:
445 return FALSE;
446
447 case -1:
448 wxLogSysError(_("can't determine if the end of file is reached on descriptor %d"), m_fd);
449 break;
450
451 default:
452 wxFAIL_MSG(_("invalid eof() return value."));
453 }
454
455 return TRUE;
456}
457
458// ============================================================================
459// implementation of wxTempFile
460// ============================================================================
461
462// ----------------------------------------------------------------------------
463// construction
464// ----------------------------------------------------------------------------
465wxTempFile::wxTempFile(const wxString& strName)
466{
467 Open(strName);
468}
469
470bool wxTempFile::Open(const wxString& strName)
471{
472 m_strName = strName;
473
474 m_strTemp = wxFileName::CreateTempFileName(strName);
475
476 if ( m_strTemp.empty() )
477 {
478 // CreateTempFileName() failed
479 return FALSE;
480 }
481
482 // actually open the file now (it must already exist)
483 if ( !m_file.Open(m_strTemp, wxFile::write) )
484 {
485 // opening existing file failed?
486 return FALSE;
487 }
488
489#ifdef __UNIX__
490 // the temp file should have the same permissions as the original one
491 mode_t mode;
492
493 wxStructStat st;
494 if ( stat(strName.fn_str(), &st) == 0 )
495 {
496 mode = st.st_mode;
497 }
498 else
499 {
500 // file probably didn't exist, just give it the default mode _using_
501 // user's umask (new files creation should respect umask)
502 mode_t mask = umask(0777);
503 mode = 0666 & ~mask;
504 umask(mask);
505 }
506
507 if ( chmod(m_strTemp.mb_str(), mode) == -1 )
508 {
509 wxLogSysError(_("Failed to set temporary file permissions"));
510 }
511#endif // Unix
512
513 return TRUE;
514}
515
516// ----------------------------------------------------------------------------
517// destruction
518// ----------------------------------------------------------------------------
519
520wxTempFile::~wxTempFile()
521{
522 if ( IsOpened() )
523 Discard();
524}
525
526bool wxTempFile::Commit()
527{
528 m_file.Close();
529
530 if ( wxFile::Exists(m_strName) && wxRemove(m_strName) != 0 ) {
531 wxLogSysError(_("can't remove file '%s'"), m_strName.c_str());
532 return FALSE;
533 }
534
535 if ( wxRename(m_strTemp, m_strName) != 0 ) {
536 wxLogSysError(_("can't commit changes to file '%s'"), m_strName.c_str());
537 return FALSE;
538 }
539
540 return TRUE;
541}
542
543void wxTempFile::Discard()
544{
545 m_file.Close();
546 if ( wxRemove(m_strTemp) != 0 )
547 wxLogSysError(_("can't remove temporary file '%s'"), m_strTemp.c_str());
548}
549
550#endif // wxUSE_FILE
551