]>
git.saurik.com Git - wxWidgets.git/blob - src/common/file.cpp
cf35fd14864a9783b145cb033537bf240d7c812f
   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 licence 
  11 ///////////////////////////////////////////////////////////////////////////// 
  14     TODO: remove all the WinCE ugliness from here, implement the wxOpen(), 
  15           wxSeek(), ... functions in a separate file for WinCE instead!!! 
  18 // ---------------------------------------------------------------------------- 
  20 // ---------------------------------------------------------------------------- 
  22 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  23     #pragma implementation "file.h" 
  26 // For compilers that support precompilation, includes "wx.h". 
  27 #include "wx/wxprec.h" 
  36 #if defined(__WXMSW__) && !defined(__GNUWIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
  40     #define   WIN32_LEAN_AND_MEAN 
  62 #elif defined(__WXMSW__) && defined(__WXWINCE__) 
  63     // TODO: what to include? 
  64 #elif (defined(__OS2__)) 
  66 #elif (defined(__UNIX__) || defined(__GNUWIN32__)) 
  71         #include "wx/msw/wrapwin.h" 
  73 #elif defined(__DOS__) 
  74     #if defined(__WATCOMC__) 
  76     #elif defined(__DJGPP__) 
  81         #error  "Please specify the header with file functions declarations." 
  83 #elif (defined(__WXSTUBS__)) 
  84     // Have to ifdef this for different environments 
  86 #elif (defined(__WXMAC__)) 
  88     int access( const char *path
, int mode 
) { return 0 ; } 
  90     int _access( const char *path
, int mode 
) { return 0 ; } 
  92     char* mktemp( char * path 
) { return path 
;} 
  96     #error  "Please specify the header with file functions declarations." 
  99 #include  <stdio.h>       // SEEK_xxx constants 
 102 #include  <fcntl.h>       // O_RDONLY &c 
 107 #elif !defined(__MWERKS__) 
 108     #include  <sys/types.h>   // needed for stat 
 109     #include  <sys/stat.h>    // stat 
 110 #elif defined(__MWERKS__) && ( defined(__WXMSW__) || defined(__MACH__) ) 
 111     #include  <sys/types.h>   // needed for stat 
 112     #include  <sys/stat.h>    // stat 
 115 // Windows compilers don't have these constants 
 119         F_OK 
= 0,   // test for existence 
 120         X_OK 
= 1,   //          execute permission 
 126 // there is no distinction between text and binary files under Unix, so define 
 127 // O_BINARY as 0 if the system headers don't do it already 
 128 #if defined(__UNIX__) && !defined(O_BINARY) 
 140 // some broken compilers don't have 3rd argument in open() and creat() 
 142     #define ACCESS(access) 
 144 #else // normal compiler 
 145     #define ACCESS(access)  , (access) 
 150     #include  "wx/string.h" 
 153 #endif // !WX_PRECOMP 
 155 #include  "wx/filename.h" 
 157 #include  "wx/filefn.h" 
 160     #include "wx/msw/mslu.h" 
 164     #include "wx/msw/private.h" 
 167 // ============================================================================ 
 168 // implementation of wxFile 
 169 // ============================================================================ 
 171 // ---------------------------------------------------------------------------- 
 173 // ---------------------------------------------------------------------------- 
 175 bool wxFile::Exists(const wxChar 
*name
) 
 177     return wxFileExists(name
); 
 180 bool wxFile::Access(const wxChar 
*name
, OpenMode mode
) 
 187             wxFAIL_MSG(wxT("bad wxFile::Access mode parameter.")); 
 204     // FIXME: use CreateFile with 0 access to query the file 
 207     return wxAccess(name
, how
) == 0; 
 211 // ---------------------------------------------------------------------------- 
 213 // ---------------------------------------------------------------------------- 
 216 wxFile::wxFile(const wxChar 
*szFileName
, OpenMode mode
) 
 221     Open(szFileName
, mode
); 
 224 // create the file, fail if it already exists and bOverwrite 
 225 bool wxFile::Create(const wxChar 
*szFileName
, bool bOverwrite
, int accessMode
) 
 227     // if bOverwrite we create a new file or truncate the existing one, 
 228     // otherwise we only create the new file and fail if it already exists 
 229 #if defined(__WXMAC__) && !defined(__UNIX__) && !wxUSE_UNICODE 
 230     // Dominic Mazzoni [dmazzoni+@cs.cmu.edu] reports that open is still broken on the mac, so we replace 
 231     // int fd = open(wxUnix2MacFilename( szFileName ), O_CREAT | (bOverwrite ? O_TRUNC : O_EXCL), access); 
 232     int fd 
= creat( szFileName 
, accessMode
); 
 235     HANDLE fileHandle 
= ::CreateFile(szFileName
, GENERIC_WRITE
, 0, NULL
, 
 236         bOverwrite 
? CREATE_ALWAYS 
: CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, 
 239     if (fileHandle 
== INVALID_HANDLE_VALUE
) 
 240         fd 
= (int) fileHandle
; 
 244     int fd 
= wxOpen( szFileName
, 
 245                      O_BINARY 
| O_WRONLY 
| O_CREAT 
| 
 246                      (bOverwrite 
? O_TRUNC 
: O_EXCL
) 
 247                      ACCESS(accessMode
) ); 
 252         wxLogSysError(_("can't create file '%s'"), szFileName
); 
 263 bool wxFile::Open(const wxChar 
*szFileName
, OpenMode mode
, int accessMode
) 
 268     DWORD disposition 
= 0; 
 270     int flags 
= O_BINARY
; 
 275             access 
= GENERIC_READ
; 
 276             shareMode 
= FILE_SHARE_READ
|FILE_SHARE_WRITE
; 
 277             disposition 
= OPEN_EXISTING
; 
 281             if ( wxFile::Exists(szFileName
) ) 
 283                 access 
= GENERIC_READ
|GENERIC_WRITE
; 
 284                 shareMode 
= FILE_SHARE_READ
; 
 288             //else: fall through as write_append is the same as write if the 
 289             //      file doesn't exist 
 292             access 
= GENERIC_WRITE
; 
 294             disposition 
= TRUNCATE_EXISTING
; 
 298             access 
= GENERIC_WRITE
; 
 300             disposition 
= TRUNCATE_EXISTING
; 
 304             access 
= GENERIC_READ
|GENERIC_WRITE
; 
 311     HANDLE fileHandle 
= ::CreateFile(szFileName
, access
, shareMode
, NULL
, 
 312         disposition
, FILE_ATTRIBUTE_NORMAL
, 0); 
 313     if (fileHandle 
== INVALID_HANDLE_VALUE
) 
 316         fd 
= (int) fileHandle
; 
 318     int flags 
= O_BINARY
; 
 327             if ( wxFile::Exists(szFileName
) ) 
 329                 flags 
|= O_WRONLY 
| O_APPEND
; 
 332             //else: fall through as write_append is the same as write if the 
 333             //      file doesn't exist 
 336             flags 
|= O_WRONLY 
| O_CREAT 
| O_TRUNC
; 
 340             flags 
|= O_WRONLY 
| O_CREAT 
| O_EXCL
; 
 348     int fd 
= wxOpen( szFileName
, flags 
ACCESS(accessMode
)); 
 352         wxLogSysError(_("can't open file '%s'"), szFileName
); 
 366         if (!CloseHandle((HANDLE
) m_fd
)) 
 368         if ( close(m_fd
) == -1 ) 
 371             wxLogSysError(_("can't close file descriptor %d"), m_fd
); 
 382 // ---------------------------------------------------------------------------- 
 384 // ---------------------------------------------------------------------------- 
 387 off_t 
wxFile::Read(void *pBuf
, off_t nCount
) 
 389     wxCHECK( (pBuf 
!= NULL
) && IsOpened(), 0 ); 
 394     if (ReadFile((HANDLE
) m_fd
, pBuf
, (DWORD
) nCount
, & bytesRead
, NULL
)) 
 398 #elif defined(__MWERKS__) 
 399     int iRc 
= ::read(m_fd
, (char*) pBuf
, nCount
); 
 401     int iRc 
= ::read(m_fd
, pBuf
, nCount
); 
 404         wxLogSysError(_("can't read from file descriptor %d"), m_fd
); 
 405         return wxInvalidOffset
; 
 412 size_t wxFile::Write(const void *pBuf
, size_t nCount
) 
 414     wxCHECK( (pBuf 
!= NULL
) && IsOpened(), 0 ); 
 417     DWORD bytesWritten 
= 0; 
 419     if (WriteFile((HANDLE
) m_fd
, pBuf
, (DWORD
) nCount
, & bytesWritten
, NULL
)) 
 423 #elif defined(__MWERKS__) 
 424 #if __MSL__ >= 0x6000 
 425     int iRc 
= ::write(m_fd
, (void*) pBuf
, nCount
); 
 427     int iRc 
= ::write(m_fd
, (const char*) pBuf
, nCount
); 
 430     int iRc 
= ::write(m_fd
, pBuf
, nCount
); 
 433         wxLogSysError(_("can't write to file descriptor %d"), m_fd
); 
 447 #elif defined(__VISUALC__) || wxHAVE_FSYNC 
 448         if ( wxFsync(m_fd
) == -1 ) 
 450             wxLogSysError(_("can't flush file descriptor %d"), m_fd
); 
 461 // ---------------------------------------------------------------------------- 
 463 // ---------------------------------------------------------------------------- 
 466 off_t 
wxFile::Seek(off_t ofs
, wxSeekMode mode
) 
 468     wxASSERT( IsOpened() ); 
 474             wxFAIL_MSG(_("unknown seek origin")); 
 481             origin 
= FILE_CURRENT
; 
 489     DWORD res 
= SetFilePointer((HANDLE
) m_fd
, ofs
, 0, origin
) ; 
 490     if (res 
== 0xFFFFFFFF && GetLastError() != NO_ERROR
) 
 492         wxLogSysError(_("can't seek on file descriptor %d"), m_fd
); 
 493         return wxInvalidOffset
; 
 501             wxFAIL_MSG(_("unknown seek origin")); 
 516     int iRc 
= lseek(m_fd
, ofs
, origin
); 
 518         wxLogSysError(_("can't seek on file descriptor %d"), m_fd
); 
 519         return wxInvalidOffset
; 
 527 off_t 
wxFile::Tell() const 
 529     wxASSERT( IsOpened() ); 
 532     DWORD res 
= SetFilePointer((HANDLE
) m_fd
, 0, 0, FILE_CURRENT
) ; 
 533     if (res 
== 0xFFFFFFFF && GetLastError() != NO_ERROR
) 
 535         wxLogSysError(_("can't get seek position on file descriptor %d"), m_fd
); 
 536         return wxInvalidOffset
; 
 541     int iRc 
= wxTell(m_fd
); 
 543         wxLogSysError(_("can't get seek position on file descriptor %d"), m_fd
); 
 544         return wxInvalidOffset
; 
 551 // get current file length 
 552 off_t 
wxFile::Length() const 
 554     wxASSERT( IsOpened() ); 
 557     DWORD off0 
= SetFilePointer((HANDLE
) m_fd
, 0, 0, FILE_CURRENT
); 
 558     DWORD off1 
= SetFilePointer((HANDLE
) m_fd
, 0, 0, FILE_END
); 
 562     SetFilePointer((HANDLE
) m_fd
, off0
, 0, FILE_BEGIN
); 
 566     int iRc 
= _filelength(m_fd
); 
 568     int iRc 
= wxTell(m_fd
); 
 570         // @ have to use const_cast :-( 
 571         int iLen 
= ((wxFile 
*)this)->SeekEnd(); 
 573             // restore old position 
 574             if ( ((wxFile 
*)this)->Seek(iRc
) == -1 ) { 
 585         wxLogSysError(_("can't find length of file on file descriptor %d"), m_fd
); 
 586         return wxInvalidOffset
; 
 593 // is end of file reached? 
 594 bool wxFile::Eof() const 
 596     wxASSERT( IsOpened() ); 
 599     DWORD off0 
= SetFilePointer((HANDLE
) m_fd
, 0, 0, FILE_CURRENT
); 
 600     DWORD off1 
= SetFilePointer((HANDLE
) m_fd
, 0, 0, FILE_END
); 
 605         SetFilePointer((HANDLE
) m_fd
, off0
, 0, FILE_BEGIN
); 
 611 #if defined(__DOS__) || defined(__UNIX__) || defined(__GNUWIN32__) || defined( __MWERKS__ ) || defined(__SALFORDC__) 
 612     // @@ this doesn't work, of course, on unseekable file descriptors 
 613     off_t ofsCur 
= Tell(), 
 615     if ( ofsCur 
== wxInvalidOffset 
|| ofsMax 
== wxInvalidOffset 
) 
 618         iRc 
= ofsCur 
== ofsMax
; 
 619 #else  // Windows and "native" compiler 
 621 #endif // Windows/Unix 
 631             wxLogSysError(_("can't determine if the end of file is reached on descriptor %d"), m_fd
); 
 635             wxFAIL_MSG(_("invalid eof() return value.")); 
 642 // ============================================================================ 
 643 // implementation of wxTempFile 
 644 // ============================================================================ 
 646 // ---------------------------------------------------------------------------- 
 648 // ---------------------------------------------------------------------------- 
 650 wxTempFile::wxTempFile(const wxString
& strName
) 
 655 bool wxTempFile::Open(const wxString
& strName
) 
 657     // we must have an absolute filename because otherwise CreateTempFileName() 
 658     // would create the temp file in $TMP (i.e. the system standard location 
 659     // for the temp files) which might be on another volume/drive/mount and 
 660     // wxRename()ing it later to m_strName from Commit() would then fail 
 662     // with the absolute filename, the temp file is created in the same 
 663     // directory as this one which ensures that wxRename() may work later 
 664     wxFileName 
fn(strName
); 
 665     if ( !fn
.IsAbsolute() ) 
 667         fn
.Normalize(wxPATH_NORM_ABSOLUTE
); 
 670     m_strName 
= fn
.GetFullPath(); 
 672     m_strTemp 
= wxFileName::CreateTempFileName(m_strName
, &m_file
); 
 674     if ( m_strTemp
.empty() ) 
 676         // CreateTempFileName() failed 
 681     // the temp file should have the same permissions as the original one 
 685     if ( stat( (const char*) m_strName
.fn_str(), &st
) == 0 ) 
 691         // file probably didn't exist, just give it the default mode _using_ 
 692         // user's umask (new files creation should respect umask) 
 693         mode_t mask 
= umask(0777); 
 698     if ( chmod( (const char*) m_strTemp
.fn_str(), mode
) == -1 ) 
 701         wxLogSysError(_("Failed to set temporary file permissions")); 
 709 // ---------------------------------------------------------------------------- 
 711 // ---------------------------------------------------------------------------- 
 713 wxTempFile::~wxTempFile() 
 719 bool wxTempFile::Commit() 
 723     if ( wxFile::Exists(m_strName
) && wxRemove(m_strName
) != 0 ) { 
 724         wxLogSysError(_("can't remove file '%s'"), m_strName
.c_str()); 
 728     if ( !wxRenameFile(m_strTemp
, m_strName
)  ) { 
 729         wxLogSysError(_("can't commit changes to file '%s'"), m_strName
.c_str()); 
 736 void wxTempFile::Discard() 
 739     if ( wxRemove(m_strTemp
) != 0 ) 
 740         wxLogSysError(_("can't remove temporary file '%s'"), m_strTemp
.c_str());