]>
git.saurik.com Git - wxWidgets.git/blob - src/common/file.cpp
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxFile - encapsulates low-level "file descriptor"
5 // Author: Vadim Zeitlin
9 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
10 // Licence: wxWindows license
11 /////////////////////////////////////////////////////////////////////////////
13 // ----------------------------------------------------------------------------
15 // ----------------------------------------------------------------------------
18 #pragma implementation "file.h"
21 // For compilers that support precompilation, includes "wx.h".
22 #include "wx/wxprec.h"
30 #if defined(__WINDOWS__) && !defined(__GNUWIN32__)
32 #elif (defined(__UNIX__) || defined(__GNUWIN32__))
35 #error "Please specify the header with file functions declarations."
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
43 // Microsoft compiler loves underscores, feed them to it
52 #define access _access
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
66 #define S_IFDIR _S_IFDIR
67 #define S_IFREG _S_IFREG
69 #define S_IREAD _S_IREAD
70 #define S_IWRITE _S_IWRITE
72 #define tell(fd) lseek(fd, 0, SEEK_CUR)
75 // there is no distinction between text and binary files under Unix
81 #include <wx/string.h>
87 // ============================================================================
88 // implementation of wxFile
89 // ============================================================================
91 // ----------------------------------------------------------------------------
93 // ----------------------------------------------------------------------------
94 bool wxFile::Exists(const char *sz
)
97 return !access(sz
, 0) && !stat(sz
, &st
) && (st
.st_mode
& S_IFREG
);
100 // ----------------------------------------------------------------------------
102 // ----------------------------------------------------------------------------
105 wxFile::wxFile(const char *szFileName
, OpenMode mode
)
109 Open(szFileName
, mode
);
118 // create the file, fail if it already exists and bOverwrite
119 bool wxFile::Create(const char *szFileName
, bool bOverwrite
)
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
= open(szFileName
, O_CREAT
| (bOverwrite
? O_TRUNC
: O_EXCL
));
126 wxLogSysError("can't create file '%s'", szFileName
);
136 bool wxFile::Open(const char *szFileName
, OpenMode mode
)
138 int flags
= O_BINARY
;
146 flags
|= O_WRONLY
| O_CREAT
| O_TRUNC
;
150 flags
|= O_WRONLY
| O_APPEND
;
158 int fd
= open(szFileName
, flags
, S_IREAD
| S_IWRITE
);
161 wxLogSysError("can't open file '%s'", szFileName
);
174 if ( close(m_fd
) == -1 ) {
175 wxLogSysError("can't close file descriptor %d", m_fd
);
186 // ----------------------------------------------------------------------------
188 // ----------------------------------------------------------------------------
191 off_t
wxFile::Read(void *pBuf
, off_t nCount
)
193 wxCHECK_RET( (pBuf
!= NULL
) && IsOpened(), 0 );
195 int iRc
= ::read(m_fd
, pBuf
, nCount
);
197 wxLogSysError("can't read from file descriptor %d", m_fd
);
205 bool wxFile::Write(const void *pBuf
, uint nCount
)
207 wxCHECK_RET( (pBuf
!= NULL
) && IsOpened(), 0 );
209 int iRc
= ::write(m_fd
, pBuf
, nCount
);
211 wxLogSysError("can't write to file descriptor %d", m_fd
);
222 // @@@ fsync() is not ANSI (BSDish)
223 // if ( fsync(m_fd) == -1 ) { // TODO
225 wxLogSysError("can't flush file descriptor %d", m_fd
);
233 // ----------------------------------------------------------------------------
235 // ----------------------------------------------------------------------------
238 off_t
wxFile::Seek(off_t ofs
, SeekMode mode
)
240 wxASSERT( IsOpened() );
257 wxFAIL_MSG("unknown seek origin");
260 int iRc
= lseek(m_fd
, ofs
, flag
);
262 wxLogSysError("can't seek on file descriptor %d", m_fd
);
270 off_t
wxFile::Tell() const
272 wxASSERT( IsOpened() );
274 int iRc
= tell(m_fd
);
276 wxLogSysError("can't get seek position on file descriptor %d", m_fd
);
283 // get current file length
284 off_t
wxFile::Length() const
286 wxASSERT( IsOpened() );
289 int iRc
= _filelength(m_fd
);
291 int iRc
= tell(m_fd
);
293 // @ have to use const_cast :-(
294 int iLen
= ((wxFile
*)this)->SeekEnd();
296 // restore old position
297 if ( ((wxFile
*)this)->Seek(iRc
) == -1 ) {
309 wxLogSysError("can't find length of file on file descriptor %d", m_fd
);
316 // is end of file reached?
317 bool wxFile::Eof() const
319 wxASSERT( IsOpened() );
323 #if defined(__UNIX__) || defined(__GNUWIN32__)
324 // @@ this doesn't work, of course, on unseekable file descriptors
325 off_t ofsCur
= Tell(),
327 if ( ofsCur
== ofsInvalid
|| ofsMax
== ofsInvalid
)
330 iRc
= ofsCur
== ofsMax
;
331 #else // Windows and "native" compiler
333 #endif // Windows/Unix
343 wxLogSysError("can't determine if the end of file is reached on "
344 "descriptor %d", m_fd
);
348 wxFAIL_MSG("invalid eof() return value.");
354 // ============================================================================
355 // implementation of wxTempFile
356 // ============================================================================
358 // ----------------------------------------------------------------------------
360 // ----------------------------------------------------------------------------
361 wxTempFile::wxTempFile(const wxString
& strName
)
366 bool wxTempFile::Open(const wxString
& strName
)
370 // we want to create the file in the same directory as strName because
371 // otherwise rename() in Commit() might not work (if the files are on
372 // different partitions for example). Unfortunately, the only standard
373 // (POSIX) temp file creation function tmpnam() can't do it.
375 static const char *szMktempSuffix
= "XXXXXX";
376 m_strTemp
<< strName
<< szMktempSuffix
;
377 mktemp((char *)m_strTemp
.c_str()); // @@@ even if the length doesn't change
378 //m_strTemp.UngetWriteBuf();
380 m_strTemp
= tmpnam(NULL
);
381 #endif // Windows/Unix
383 return m_file
.Open(m_strTemp
, wxFile::write
);
386 // ----------------------------------------------------------------------------
388 // ----------------------------------------------------------------------------
390 wxTempFile::~wxTempFile()
396 bool wxTempFile::Commit()
400 if ( wxFile::Exists(m_strName
) && remove(m_strName
) != 0 ) {
401 wxLogSysError("can't remove file '%s'", m_strName
.c_str());
405 if ( rename(m_strTemp
, m_strName
) != 0 ) {
406 wxLogSysError("can't commit changes to file '%s'", m_strName
.c_str());
413 void wxTempFile::Discard()
416 if ( remove(m_strTemp
) != 0 )
417 wxLogSysError("can't remove temporary file '%s'", m_strTemp
.c_str());