]> git.saurik.com Git - wxWidgets.git/blame - src/common/file.cpp
no real changes
[wxWidgets.git] / src / common / file.cpp
CommitLineData
c801d85f
KB
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>
246037e2 10// Licence: wxWindows license
c801d85f
KB
11/////////////////////////////////////////////////////////////////////////////
12
13// ----------------------------------------------------------------------------
14// headers
15// ----------------------------------------------------------------------------
16
17#ifdef __GNUG__
3f4a0c5b 18 #pragma implementation "file.h"
c801d85f
KB
19#endif
20
21// For compilers that support precompilation, includes "wx.h".
22#include "wx/wxprec.h"
c801d85f
KB
23
24#ifdef __BORLANDC__
ce4169a4 25 #pragma hdrstop
c801d85f
KB
26#endif
27
ce4169a4
RR
28#if wxUSE_FILE
29
c801d85f 30// standard
fac3b423 31#if defined(__WXMSW__) && !defined(__GNUWIN32__) && !defined(__WXWINE__) && !defined(__WXMICROWIN__)
c801d85f 32 #include <io.h>
30a5be97 33
a3ef5bf5 34#ifndef __SALFORDC__
49d5d881
VZ
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
a3ef5bf5
JS
55#endif
56
c801d85f 57#elif (defined(__UNIX__) || defined(__GNUWIN32__))
3f4a0c5b
VZ
58 #include <unistd.h>
59 #ifdef __GNUWIN32__
60 #include <windows.h>
61 #endif
b7f411dd
VS
62#elif defined(__DOS__) && defined(__WATCOMC__)
63 #include <io.h>
64 char* mktemp(char *path) { return _mktemp(path); }
c2ff79b1
DW
65#elif (defined(__WXPM__))
66 #include <io.h>
c2ff79b1
DW
67 #define W_OK 2
68 #define R_OK 4
34138703 69#elif (defined(__WXSTUBS__))
3f4a0c5b
VZ
70 // Have to ifdef this for different environments
71 #include <io.h>
17dff81c 72#elif (defined(__WXMAC__))
5b781a67 73#if __MSL__ < 0x6000
3f4a0c5b 74 int access( const char *path, int mode ) { return 0 ; }
5b781a67
SC
75#else
76 int _access( const char *path, int mode ) { return 0 ; }
77#endif
3f4a0c5b 78 char* mktemp( char * path ) { return path ;}
5b781a67 79 #include <stat.h>
3f4a0c5b
VZ
80 #define W_OK 2
81 #define R_OK 4
5b781a67 82 #include <unistd.h>
c801d85f 83#else
3f4a0c5b 84 #error "Please specify the header with file functions declarations."
c801d85f
KB
85#endif //Win/UNIX
86
87#include <stdio.h> // SEEK_xxx constants
88#include <fcntl.h> // O_RDONLY &c
a3ef5bf5 89
469e1e5c 90#ifndef __MWERKS__
3f4a0c5b
VZ
91 #include <sys/types.h> // needed for stat
92 #include <sys/stat.h> // stat
de85a884
VZ
93#elif ( defined(__MWERKS__) && defined(__WXMSW__) )
94 #include <sys/types.h> // needed for stat
95 #include <sys/stat.h> // stat
469e1e5c 96#endif
c801d85f 97
3f4a0c5b 98#if defined(__BORLANDC__) || defined(_MSC_VER)
49d5d881
VZ
99 #define W_OK 2
100 #define R_OK 4
34138703
JS
101#endif
102
b12915c1
VZ
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)
49d5d881 106 #define O_BINARY (0)
246037e2 107#endif //__UNIX__
c801d85f 108
a3ef5bf5 109#ifdef __SALFORDC__
3f4a0c5b 110 #include <unix.h>
a3ef5bf5
JS
111#endif
112
81d66cf3 113#ifndef MAX_PATH
3f4a0c5b 114 #define MAX_PATH 512
81d66cf3 115#endif
c801d85f 116
49d5d881
VZ
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
f6bcfd97 125// wxWindows
ade35f11
VZ
126#ifndef WX_PRECOMP
127 #include "wx/string.h"
128 #include "wx/intl.h"
ade35f11
VZ
129 #include "wx/log.h"
130#endif // !WX_PRECOMP
131
132#include "wx/filename.h"
44d568b6 133#include "wx/file.h"
f6bcfd97 134
c801d85f
KB
135// ============================================================================
136// implementation of wxFile
137// ============================================================================
138
139// ----------------------------------------------------------------------------
140// static functions
141// ----------------------------------------------------------------------------
50920146 142bool wxFile::Exists(const wxChar *name)
246037e2 143{
f6bcfd97 144 wxStructStat st;
50920146 145#if wxUSE_UNICODE && wxMBFILES
dcf924a3 146 wxCharBuffer fname = wxConvFile.cWC2MB(name);
a3ef5bf5 147
f6bcfd97
BP
148 return !wxAccess(fname, 0) &&
149 !wxStat(wxMBSTRINGCAST fname, &st) &&
50920146 150 (st.st_mode & S_IFREG);
bedaf53e 151
50920146 152#else
f6bcfd97
BP
153 return !wxAccess(name, 0) &&
154 !wxStat(name, &st) &&
49d5d881 155 (st.st_mode & S_IFREG);
50920146 156#endif
d1427b70
VZ
157}
158
50920146 159bool wxFile::Access(const wxChar *name, OpenMode mode)
d1427b70 160{
49d5d881 161 int how = 0;
d1427b70 162
49d5d881
VZ
163 switch ( mode ) {
164 case read:
165 how = R_OK;
166 break;
d1427b70 167
49d5d881
VZ
168 case write:
169 how = W_OK;
170 break;
d1427b70 171
49d5d881 172 default:
223d09f6 173 wxFAIL_MSG(wxT("bad wxFile::Access mode parameter."));
49d5d881 174 }
d1427b70 175
f6bcfd97 176 return wxAccess(wxFNCONV(name), how) == 0;
c801d85f
KB
177}
178
179// ----------------------------------------------------------------------------
180// opening/closing
181// ----------------------------------------------------------------------------
182
183// ctors
50920146 184wxFile::wxFile(const wxChar *szFileName, OpenMode mode)
c801d85f 185{
49d5d881
VZ
186 m_fd = fd_invalid;
187 m_error = FALSE;
c801d85f 188
49d5d881 189 Open(szFileName, mode);
c801d85f
KB
190}
191
c801d85f 192// create the file, fail if it already exists and bOverwrite
50920146 193bool wxFile::Create(const wxChar *szFileName, bool bOverwrite, int accessMode)
c801d85f 194{
49d5d881
VZ
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
5fde6fcc 197#if defined(__WXMAC__) && !defined(__UNIX__)
5b781a67
SC
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);
bedaf53e 200 int fd = creat( szFileName , accessMode);
7c74e7fe 201#else
f6bcfd97
BP
202 int fd = wxOpen(wxFNCONV(szFileName),
203 O_BINARY | O_WRONLY | O_CREAT |
204 (bOverwrite ? O_TRUNC : O_EXCL)
205 ACCESS(accessMode));
7c74e7fe 206#endif
49d5d881
VZ
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 }
c801d85f
KB
215}
216
217// open the file
50920146 218bool wxFile::Open(const wxChar *szFileName, OpenMode mode, int accessMode)
c801d85f 219{
49d5d881 220 int flags = O_BINARY;
c801d85f 221
49d5d881
VZ
222 switch ( mode ) {
223 case read:
224 flags |= O_RDONLY;
225 break;
c801d85f 226
f6bcfd97
BP
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
49d5d881
VZ
236 case write:
237 flags |= O_WRONLY | O_CREAT | O_TRUNC;
238 break;
61b02744 239
68164137
RL
240 case write_excl:
241 flags |= O_WRONLY | O_CREAT | O_EXCL;
242 break;
243
49d5d881
VZ
244 case read_write:
245 flags |= O_RDWR;
246 break;
247 }
c801d85f 248
f6bcfd97 249 int fd = wxOpen(wxFNCONV(szFileName), flags ACCESS(accessMode));
49d5d881
VZ
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 }
c801d85f
KB
258}
259
260// close
61b02744 261bool wxFile::Close()
c801d85f 262{
49d5d881
VZ
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;
61b02744 271 }
61b02744 272
49d5d881 273 return TRUE;
c801d85f
KB
274}
275
276// ----------------------------------------------------------------------------
277// read/write
278// ----------------------------------------------------------------------------
279
280// read
281off_t wxFile::Read(void *pBuf, off_t nCount)
282{
49d5d881 283 wxCHECK( (pBuf != NULL) && IsOpened(), 0 );
c801d85f 284
469e1e5c 285#ifdef __MWERKS__
49d5d881 286 int iRc = ::read(m_fd, (char*) pBuf, nCount);
469e1e5c 287#else
49d5d881 288 int iRc = ::read(m_fd, pBuf, nCount);
469e1e5c 289#endif
49d5d881
VZ
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;
c801d85f
KB
296}
297
298// write
c86f1403 299size_t wxFile::Write(const void *pBuf, size_t nCount)
c801d85f 300{
49d5d881 301 wxCHECK( (pBuf != NULL) && IsOpened(), 0 );
c801d85f 302
469e1e5c 303#ifdef __MWERKS__
5b781a67
SC
304#if __MSL__ >= 0x6000
305 int iRc = ::write(m_fd, (void*) pBuf, nCount);
306#else
49d5d881 307 int iRc = ::write(m_fd, (const char*) pBuf, nCount);
5b781a67 308#endif
469e1e5c 309#else
49d5d881 310 int iRc = ::write(m_fd, pBuf, nCount);
469e1e5c 311#endif
49d5d881
VZ
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;
c801d85f
KB
319}
320
321// flush
322bool wxFile::Flush()
323{
49d5d881
VZ
324 if ( IsOpened() ) {
325#if defined(__VISUALC__) || wxHAVE_FSYNC
f6bcfd97 326 if ( wxFsync(m_fd) == -1 )
09914df7
VZ
327 {
328 wxLogSysError(_("can't flush file descriptor %d"), m_fd);
329 return FALSE;
330 }
49d5d881 331#else // no fsync
09914df7 332 // just do nothing
49d5d881
VZ
333#endif // fsync
334 }
c801d85f 335
49d5d881 336 return TRUE;
c801d85f
KB
337}
338
339// ----------------------------------------------------------------------------
340// seek
341// ----------------------------------------------------------------------------
342
343// seek
79c3e0e1 344off_t wxFile::Seek(off_t ofs, wxSeekMode mode)
c801d85f 345{
49d5d881
VZ
346 wxASSERT( IsOpened() );
347
a1b82138 348 int origin;
49d5d881 349 switch ( mode ) {
a1b82138
VZ
350 default:
351 wxFAIL_MSG(_("unknown seek origin"));
352
49d5d881 353 case wxFromStart:
a1b82138 354 origin = SEEK_SET;
49d5d881
VZ
355 break;
356
357 case wxFromCurrent:
a1b82138 358 origin = SEEK_CUR;
49d5d881
VZ
359 break;
360
361 case wxFromEnd:
a1b82138 362 origin = SEEK_END;
49d5d881 363 break;
49d5d881
VZ
364 }
365
a1b82138 366 int iRc = lseek(m_fd, ofs, origin);
49d5d881
VZ
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;
c801d85f
KB
373}
374
375// get current off_t
376off_t wxFile::Tell() const
377{
49d5d881
VZ
378 wxASSERT( IsOpened() );
379
f6bcfd97 380 int iRc = wxTell(m_fd);
49d5d881
VZ
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;
c801d85f
KB
387}
388
389// get current file length
390off_t wxFile::Length() const
391{
49d5d881 392 wxASSERT( IsOpened() );
c801d85f 393
49d5d881 394#ifdef __VISUALC__
c801d85f 395 int iRc = _filelength(m_fd);
49d5d881 396#else // !VC++
f6bcfd97 397 int iRc = wxTell(m_fd);
c801d85f 398 if ( iRc != -1 ) {
49d5d881
VZ
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 }
c801d85f 407 }
c801d85f 408
49d5d881
VZ
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;
c801d85f 416 }
49d5d881
VZ
417 else
418 return (off_t)iRc;
c801d85f
KB
419}
420
421// is end of file reached?
422bool wxFile::Eof() const
423{
49d5d881 424 wxASSERT( IsOpened() );
c801d85f 425
49d5d881 426 int iRc;
61b02744 427
49d5d881 428#if defined(__UNIX__) || defined(__GNUWIN32__) || defined( __MWERKS__ ) || defined(__SALFORDC__)
61b02744
VZ
429 // @@ this doesn't work, of course, on unseekable file descriptors
430 off_t ofsCur = Tell(),
49d5d881 431 ofsMax = Length();
1678ad78 432 if ( ofsCur == wxInvalidOffset || ofsMax == wxInvalidOffset )
49d5d881 433 iRc = -1;
61b02744 434 else
49d5d881
VZ
435 iRc = ofsCur == ofsMax;
436#else // Windows and "native" compiler
61b02744 437 iRc = eof(m_fd);
49d5d881 438#endif // Windows/Unix
c801d85f 439
49d5d881
VZ
440 switch ( iRc ) {
441 case 1:
442 break;
c801d85f 443
49d5d881
VZ
444 case 0:
445 return FALSE;
c801d85f 446
49d5d881 447 case -1:
8e3f1261 448 wxLogSysError(_("can't determine if the end of file is reached on descriptor %d"), m_fd);
49d5d881 449 break;
c801d85f 450
49d5d881
VZ
451 default:
452 wxFAIL_MSG(_("invalid eof() return value."));
453 }
c801d85f 454
49d5d881 455 return TRUE;
c801d85f
KB
456}
457
458// ============================================================================
459// implementation of wxTempFile
460// ============================================================================
461
462// ----------------------------------------------------------------------------
463// construction
464// ----------------------------------------------------------------------------
465wxTempFile::wxTempFile(const wxString& strName)
466{
49d5d881 467 Open(strName);
c801d85f
KB
468}
469
470bool wxTempFile::Open(const wxString& strName)
471{
49d5d881 472 m_strName = strName;
246037e2 473
ade35f11
VZ
474 m_strTemp = wxFileName::CreateTempFileName(strName);
475
476 if ( m_strTemp.empty() )
477 {
478 // CreateTempFileName() failed
479 return FALSE;
480 }
49d5d881 481
3f247475
VZ
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
49d5d881 489#ifdef __UNIX__
ade35f11
VZ
490 // the temp file should have the same permissions as the original one
491 mode_t mode;
fe99e285 492
f6bcfd97 493 wxStructStat st;
50920146 494 if ( stat(strName.fn_str(), &st) == 0 )
49d5d881 495 {
ade35f11 496 mode = st.st_mode;
49d5d881
VZ
497 }
498 else
499 {
ade35f11 500 // file probably didn't exist, just give it the default mode _using_
68164137 501 // user's umask (new files creation should respect umask)
ade35f11
VZ
502 mode_t mask = umask(0777);
503 mode = 0666 & ~mask;
504 umask(mask);
49d5d881 505 }
49d5d881 506
ade35f11 507 if ( chmod(m_strTemp.mb_str(), mode) == -1 )
fe99e285 508 {
ade35f11 509 wxLogSysError(_("Failed to set temporary file permissions"));
fe99e285 510 }
49d5d881 511#endif // Unix
246037e2 512
ade35f11 513 return TRUE;
c801d85f
KB
514}
515
516// ----------------------------------------------------------------------------
517// destruction
518// ----------------------------------------------------------------------------
519
520wxTempFile::~wxTempFile()
521{
49d5d881
VZ
522 if ( IsOpened() )
523 Discard();
c801d85f
KB
524}
525
526bool wxTempFile::Commit()
527{
49d5d881 528 m_file.Close();
c801d85f 529
f6bcfd97 530 if ( wxFile::Exists(m_strName) && wxRemove(m_strName) != 0 ) {
49d5d881
VZ
531 wxLogSysError(_("can't remove file '%s'"), m_strName.c_str());
532 return FALSE;
533 }
c801d85f 534
f6bcfd97 535 if ( wxRename(m_strTemp, m_strName) != 0 ) {
49d5d881
VZ
536 wxLogSysError(_("can't commit changes to file '%s'"), m_strName.c_str());
537 return FALSE;
538 }
c801d85f 539
49d5d881 540 return TRUE;
c801d85f
KB
541}
542
543void wxTempFile::Discard()
544{
49d5d881 545 m_file.Close();
f6bcfd97 546 if ( wxRemove(m_strTemp) != 0 )
49d5d881 547 wxLogSysError(_("can't remove temporary file '%s'"), m_strTemp.c_str());
c801d85f 548}
ce4169a4 549
ade35f11 550#endif // wxUSE_FILE
cc985fac 551