Add wxFile::{Get,Clear}LastError() functions.

Remember the errno of the last file operation instead of just remembering
whether there was an error or not.

See #12636.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@66150 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin 2010-11-14 12:09:59 +00:00
parent 0547ad09cc
commit 65fe93d8a5
4 changed files with 75 additions and 15 deletions

View File

@ -408,6 +408,7 @@ All:
- Added cwd and env arguments to wxExecute() (Emilien Kia). - Added cwd and env arguments to wxExecute() (Emilien Kia).
- Added "rest" argument to wxString::Before{First,Last}(). - Added "rest" argument to wxString::Before{First,Last}().
- Added wxThread::OnKill() and OnDelete() callbacks. - Added wxThread::OnKill() and OnDelete() callbacks.
- Added wxFile::GetLastError() and ClearLastError() (ryazanov).
All (GUI): All (GUI):

View File

@ -49,11 +49,11 @@ public:
// ctors // ctors
// ----- // -----
// def ctor // def ctor
wxFile() { m_fd = fd_invalid; m_error = false; } wxFile() { m_fd = fd_invalid; m_lasterror = 0; }
// open specified file (may fail, use IsOpened()) // open specified file (may fail, use IsOpened())
wxFile(const wxString& fileName, OpenMode mode = read); wxFile(const wxString& fileName, OpenMode mode = read);
// attach to (already opened) file // attach to (already opened) file
wxFile(int lfd) { m_fd = lfd; m_error = false; } wxFile(int lfd) { m_fd = lfd; m_lasterror = 0; }
// open/close // open/close
// create a new file (with the default value of bOverwrite, it will fail if // create a new file (with the default value of bOverwrite, it will fail if
@ -65,7 +65,7 @@ public:
bool Close(); // Close is a NOP if not opened bool Close(); // Close is a NOP if not opened
// assign an existing file descriptor and get it back from wxFile object // assign an existing file descriptor and get it back from wxFile object
void Attach(int lfd) { Close(); m_fd = lfd; m_error = false; } void Attach(int lfd) { Close(); m_fd = lfd; m_lasterror = 0; }
void Detach() { m_fd = fd_invalid; } void Detach() { m_fd = fd_invalid; }
int fd() const { return m_fd; } int fd() const { return m_fd; }
@ -95,10 +95,15 @@ public:
// is end of file reached? // is end of file reached?
bool Eof() const; bool Eof() const;
// has an error occurred? // has an error occurred?
bool Error() const { return m_error; } bool Error() const { return m_lasterror != 0; }
// get last errno
int GetLastError() const { return m_lasterror; }
// reset error state
void ClearLastError() { m_lasterror = 0; }
// type such as disk or pipe // type such as disk or pipe
wxFileKind GetKind() const { return wxGetFileKind(m_fd); } wxFileKind GetKind() const { return wxGetFileKind(m_fd); }
// dtor closes the file if opened // dtor closes the file if opened
~wxFile() { Close(); } ~wxFile() { Close(); }
@ -109,8 +114,16 @@ private:
wxFile(const wxFile&); wxFile(const wxFile&);
wxFile& operator=(const wxFile&); wxFile& operator=(const wxFile&);
// Copy the value of errno into m_lasterror if rc == -1 and return true in
// this case (indicating that we've got an error). Otherwise return false.
//
// Notice that we use the possibly 64 bit wxFileOffset instead of int here so
// that it works for checking the result of functions such as tell() too.
bool CheckForError(wxFileOffset rc) const;
int m_fd; // file descriptor or INVALID_FD if not opened int m_fd; // file descriptor or INVALID_FD if not opened
bool m_error; // error memory int m_lasterror; // errno value of last error
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@ -231,6 +231,32 @@ public:
*/ */
~wxFile(); ~wxFile();
/**
Returns the error code for the last unsuccessful operation.
The error code is system-dependent and corresponds to the value of the
standard @c errno variable when the last error occurred.
Notice that only simple accessors such as IsOpened() and Eof() (and
this method itself) don't modify the last error value, all other
methods can potentially change it if an error occurs, including the
const ones such as Tell() or Length().
@since 2.9.2
@see ClearLastError()
*/
int GetLastError() const;
/**
Resets the error code.
GetLastError() will return 0 until the next error occurs.
@since 2.9.2
*/
void ClearLastError();
/** /**
This function verifies if we may access the given file in specified mode. This function verifies if we may access the given file in specified mode.
Only values of @c wxFile::read or @c wxFile::write really make sense here. Only values of @c wxFile::read or @c wxFile::write really make sense here.

View File

@ -88,6 +88,10 @@
#include <stdio.h> // SEEK_xxx constants #include <stdio.h> // SEEK_xxx constants
#ifndef __WXWINCE__
#include <errno.h>
#endif
// Windows compilers don't have these constants // Windows compilers don't have these constants
#ifndef W_OK #ifndef W_OK
enum enum
@ -176,11 +180,27 @@ bool wxFile::Access(const wxString& name, OpenMode mode)
wxFile::wxFile(const wxString& fileName, OpenMode mode) wxFile::wxFile(const wxString& fileName, OpenMode mode)
{ {
m_fd = fd_invalid; m_fd = fd_invalid;
m_error = false; m_lasterror = 0;
Open(fileName, mode); Open(fileName, mode);
} }
bool wxFile::CheckForError(wxFileOffset rc) const
{
if ( rc != -1 )
return false;
const_cast<wxFile *>(this)->m_lasterror =
#ifndef __WXWINCE__
errno
#else
::GetLastError()
#endif
;
return true;
}
// create the file, fail if it already exists and bOverwrite // create the file, fail if it already exists and bOverwrite
bool wxFile::Create(const wxString& fileName, bool bOverwrite, int accessMode) bool wxFile::Create(const wxString& fileName, bool bOverwrite, int accessMode)
{ {
@ -190,7 +210,7 @@ bool wxFile::Create(const wxString& fileName, bool bOverwrite, int accessMode)
O_BINARY | O_WRONLY | O_CREAT | O_BINARY | O_WRONLY | O_CREAT |
(bOverwrite ? O_TRUNC : O_EXCL), (bOverwrite ? O_TRUNC : O_EXCL),
accessMode ); accessMode );
if ( fd == -1 ) if ( CheckForError(fd) )
{ {
wxLogSysError(_("can't create file '%s'"), fileName); wxLogSysError(_("can't create file '%s'"), fileName);
return false; return false;
@ -242,7 +262,7 @@ bool wxFile::Open(const wxString& fileName, OpenMode mode, int accessMode)
int fd = wxOpen( fileName, flags, accessMode); int fd = wxOpen( fileName, flags, accessMode);
if ( fd == -1 ) if ( CheckForError(fd) )
{ {
wxLogSysError(_("can't open file '%s'"), fileName); wxLogSysError(_("can't open file '%s'"), fileName);
return false; return false;
@ -256,7 +276,7 @@ bool wxFile::Open(const wxString& fileName, OpenMode mode, int accessMode)
bool wxFile::Close() bool wxFile::Close()
{ {
if ( IsOpened() ) { if ( IsOpened() ) {
if (wxClose(m_fd) == -1) if ( CheckForError(wxClose(m_fd)) )
{ {
wxLogSysError(_("can't close file descriptor %d"), m_fd); wxLogSysError(_("can't close file descriptor %d"), m_fd);
m_fd = fd_invalid; m_fd = fd_invalid;
@ -280,7 +300,7 @@ ssize_t wxFile::Read(void *pBuf, size_t nCount)
ssize_t iRc = wxRead(m_fd, pBuf, nCount); ssize_t iRc = wxRead(m_fd, pBuf, nCount);
if ( iRc == -1 ) if ( CheckForError(iRc) )
{ {
wxLogSysError(_("can't read from file descriptor %d"), m_fd); wxLogSysError(_("can't read from file descriptor %d"), m_fd);
return wxInvalidOffset; return wxInvalidOffset;
@ -296,10 +316,9 @@ size_t wxFile::Write(const void *pBuf, size_t nCount)
ssize_t iRc = wxWrite(m_fd, pBuf, nCount); ssize_t iRc = wxWrite(m_fd, pBuf, nCount);
if ( iRc == -1 ) if ( CheckForError(iRc) )
{ {
wxLogSysError(_("can't write to file descriptor %d"), m_fd); wxLogSysError(_("can't write to file descriptor %d"), m_fd);
m_error = true;
iRc = 0; iRc = 0;
} }
@ -329,7 +348,7 @@ bool wxFile::Flush()
// call it then // call it then
if ( IsOpened() && GetKind() == wxFILE_KIND_DISK ) if ( IsOpened() && GetKind() == wxFILE_KIND_DISK )
{ {
if ( wxFsync(m_fd) == -1 ) if ( CheckForError(wxFsync(m_fd)) )
{ {
wxLogSysError(_("can't flush file descriptor %d"), m_fd); wxLogSysError(_("can't flush file descriptor %d"), m_fd);
return false; return false;
@ -371,7 +390,7 @@ wxFileOffset wxFile::Seek(wxFileOffset ofs, wxSeekMode mode)
} }
wxFileOffset iRc = wxSeek(m_fd, ofs, origin); wxFileOffset iRc = wxSeek(m_fd, ofs, origin);
if ( iRc == wxInvalidOffset ) if ( CheckForError(iRc) )
{ {
wxLogSysError(_("can't seek on file descriptor %d"), m_fd); wxLogSysError(_("can't seek on file descriptor %d"), m_fd);
} }
@ -385,7 +404,7 @@ wxFileOffset wxFile::Tell() const
wxASSERT( IsOpened() ); wxASSERT( IsOpened() );
wxFileOffset iRc = wxTell(m_fd); wxFileOffset iRc = wxTell(m_fd);
if ( iRc == wxInvalidOffset ) if ( CheckForError(iRc) )
{ {
wxLogSysError(_("can't get seek position on file descriptor %d"), m_fd); wxLogSysError(_("can't get seek position on file descriptor %d"), m_fd);
} }
@ -429,6 +448,7 @@ wxFileOffset wxFile::Length() const
if ( iRc == wxInvalidOffset ) if ( iRc == wxInvalidOffset )
{ {
// last error was already set by Tell()
wxLogSysError(_("can't find length of file on file descriptor %d"), m_fd); wxLogSysError(_("can't find length of file on file descriptor %d"), m_fd);
} }