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 "rest" argument to wxString::Before{First,Last}().
- Added wxThread::OnKill() and OnDelete() callbacks.
- Added wxFile::GetLastError() and ClearLastError() (ryazanov).
All (GUI):

View File

@ -49,11 +49,11 @@ public:
// ctors
// -----
// 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())
wxFile(const wxString& fileName, OpenMode mode = read);
// 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
// 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
// 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; }
int fd() const { return m_fd; }
@ -95,10 +95,15 @@ public:
// is end of file reached?
bool Eof() const;
// 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
wxFileKind GetKind() const { return wxGetFileKind(m_fd); }
// dtor closes the file if opened
~wxFile() { Close(); }
@ -109,8 +114,16 @@ private:
wxFile(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
bool m_error; // error memory
int m_lasterror; // errno value of last error
};
// ----------------------------------------------------------------------------

View File

@ -231,6 +231,32 @@ public:
*/
~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.
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
#ifndef __WXWINCE__
#include <errno.h>
#endif
// Windows compilers don't have these constants
#ifndef W_OK
enum
@ -176,11 +180,27 @@ bool wxFile::Access(const wxString& name, OpenMode mode)
wxFile::wxFile(const wxString& fileName, OpenMode mode)
{
m_fd = fd_invalid;
m_error = false;
m_lasterror = 0;
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
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 |
(bOverwrite ? O_TRUNC : O_EXCL),
accessMode );
if ( fd == -1 )
if ( CheckForError(fd) )
{
wxLogSysError(_("can't create file '%s'"), fileName);
return false;
@ -242,7 +262,7 @@ bool wxFile::Open(const wxString& fileName, OpenMode mode, int accessMode)
int fd = wxOpen( fileName, flags, accessMode);
if ( fd == -1 )
if ( CheckForError(fd) )
{
wxLogSysError(_("can't open file '%s'"), fileName);
return false;
@ -256,7 +276,7 @@ bool wxFile::Open(const wxString& fileName, OpenMode mode, int accessMode)
bool wxFile::Close()
{
if ( IsOpened() ) {
if (wxClose(m_fd) == -1)
if ( CheckForError(wxClose(m_fd)) )
{
wxLogSysError(_("can't close file descriptor %d"), m_fd);
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);
if ( iRc == -1 )
if ( CheckForError(iRc) )
{
wxLogSysError(_("can't read from file descriptor %d"), m_fd);
return wxInvalidOffset;
@ -296,10 +316,9 @@ size_t wxFile::Write(const void *pBuf, size_t 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);
m_error = true;
iRc = 0;
}
@ -329,7 +348,7 @@ bool wxFile::Flush()
// call it then
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);
return false;
@ -371,7 +390,7 @@ wxFileOffset wxFile::Seek(wxFileOffset ofs, wxSeekMode mode)
}
wxFileOffset iRc = wxSeek(m_fd, ofs, origin);
if ( iRc == wxInvalidOffset )
if ( CheckForError(iRc) )
{
wxLogSysError(_("can't seek on file descriptor %d"), m_fd);
}
@ -385,7 +404,7 @@ wxFileOffset wxFile::Tell() const
wxASSERT( IsOpened() );
wxFileOffset iRc = wxTell(m_fd);
if ( iRc == wxInvalidOffset )
if ( CheckForError(iRc) )
{
wxLogSysError(_("can't get seek position on file descriptor %d"), m_fd);
}
@ -429,6 +448,7 @@ wxFileOffset wxFile::Length() const
if ( iRc == wxInvalidOffset )
{
// last error was already set by Tell()
wxLogSysError(_("can't find length of file on file descriptor %d"), m_fd);
}