]>
git.saurik.com Git - wxWidgets.git/blob - src/common/file.cpp
07c0f058fa2595d43273976d0a076a9100c5fc91
   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(__WXMSW__) && !defined(__GNUWIN32__) && !defined(__WXWINE__) 
  34     #define   WIN32_LEAN_AND_MEAN 
  56     #include  <windows.h>     // for GetTempFileName 
  57 #elif (defined(__UNIX__) || defined(__GNUWIN32__)) 
  62 #elif (defined(__WXSTUBS__)) 
  63     // Have to ifdef this for different environments 
  65 #elif (defined(__WXMAC__)) 
  66     int access( const char *path
, int mode 
) { return 0 ; } 
  67     char* mktemp( char * path 
) { return path 
;} 
  73     #error  "Please specify the header with file functions declarations." 
  76 #include  <stdio.h>       // SEEK_xxx constants 
  77 #include  <fcntl.h>       // O_RDONLY &c 
  80     #include  <sys/types.h>   // needed for stat 
  81     #include  <sys/stat.h>    // stat 
  84 // Microsoft compiler loves underscores, feed them to it 
  93     #define   access      _access 
 101     #define   O_RDONLY    _O_RDONLY 
 102     #define   O_WRONLY    _O_WRONLY 
 103     #define   O_RDWR      _O_RDWR 
 104     #define   O_EXCL      _O_EXCL 
 105     #define   O_CREAT     _O_CREAT 
 106     #define   O_BINARY    _O_BINARY 
 108     #define   S_IFDIR     _S_IFDIR 
 109     #define   S_IFREG     _S_IFREG 
 111     #define   tell(fd)    lseek(fd, 0, SEEK_CUR) 
 114 #if defined(__BORLANDC__) || defined(_MSC_VER) 
 119 // there is no distinction between text and binary files under Unix 
 129 #include  <wx/string.h> 
 139     char gwxMacFileName
[ MAX_PATH 
] ; 
 140     char gwxMacFileName2
[ MAX_PATH 
] ; 
 141     char gwxMacFileName3
[ MAX_PATH 
] ; 
 144 // some broken compilers don't have 3rd argument in open() and creat() 
 146     #define ACCESS(access) 
 148 #else // normal compiler 
 149     #define ACCESS(access)  , (access) 
 152 // ============================================================================ 
 153 // implementation of wxFile 
 154 // ============================================================================ 
 156 // ---------------------------------------------------------------------------- 
 158 // ---------------------------------------------------------------------------- 
 159 bool wxFile::Exists(const wxChar 
*name
) 
 162 #if wxUSE_UNICODE && wxMBFILES 
 163     wxCharBuffer fname 
= wxConvFile
.cWC2MB(name
); 
 165     return !access(fname
, 0) && 
 166            !stat(MBSTRINGCAST fname
, &st
) && 
 167            (st
.st_mode 
& S_IFREG
); 
 169     return !access(name
, 0) && 
 170            !stat((wxChar
*) name
, &st
) && 
 171            (st
.st_mode 
& S_IFREG
); 
 175 bool wxFile::Access(const wxChar 
*name
, OpenMode mode
) 
 189             wxFAIL_MSG(_T("bad wxFile::Access mode parameter.")); 
 192     return access(wxFNCONV(name
), how
) == 0; 
 195 // ---------------------------------------------------------------------------- 
 197 // ---------------------------------------------------------------------------- 
 200 wxFile::wxFile(const wxChar 
*szFileName
, OpenMode mode
) 
 205     Open(szFileName
, mode
); 
 214 // create the file, fail if it already exists and bOverwrite 
 215 bool wxFile::Create(const wxChar 
*szFileName
, bool bOverwrite
, int accessMode
) 
 217     // if bOverwrite we create a new file or truncate the existing one, 
 218     // otherwise we only create the new file and fail if it already exists 
 219     int fd 
= open(wxFNCONV(szFileName
), 
 220                   O_WRONLY 
| O_CREAT 
| (bOverwrite 
? O_TRUNC 
: O_EXCL
) 
 224         wxLogSysError(_("can't create file '%s'"), szFileName
); 
 234 bool wxFile::Open(const wxChar 
*szFileName
, OpenMode mode
, int accessMode
) 
 236     int flags 
= O_BINARY
; 
 244             flags 
|= O_WRONLY 
| O_CREAT 
| O_TRUNC
; 
 248             flags 
|= O_WRONLY 
| O_APPEND
; 
 256     int fd 
= open(wxFNCONV(szFileName
), flags 
ACCESS(accessMode
)); 
 259         wxLogSysError(_("can't open file '%s'"), szFileName
); 
 272         if ( close(m_fd
) == -1 ) { 
 273             wxLogSysError(_("can't close file descriptor %d"), m_fd
); 
 284 // ---------------------------------------------------------------------------- 
 286 // ---------------------------------------------------------------------------- 
 289 off_t 
wxFile::Read(void *pBuf
, off_t nCount
) 
 291     wxCHECK( (pBuf 
!= NULL
) && IsOpened(), 0 ); 
 294     int iRc 
= ::read(m_fd
, (char*) pBuf
, nCount
); 
 296     int iRc 
= ::read(m_fd
, pBuf
, nCount
); 
 299         wxLogSysError(_("can't read from file descriptor %d"), m_fd
); 
 300         return wxInvalidOffset
; 
 307 size_t wxFile::Write(const void *pBuf
, size_t nCount
) 
 309     wxCHECK( (pBuf 
!= NULL
) && IsOpened(), 0 ); 
 312     int iRc 
= ::write(m_fd
, (const char*) pBuf
, nCount
); 
 314     int iRc 
= ::write(m_fd
, pBuf
, nCount
); 
 317         wxLogSysError(_("can't write to file descriptor %d"), m_fd
); 
 329 #if defined(__VISUALC__) || wxHAVE_FSYNC 
 330         if ( fsync(m_fd
) == -1 ) 
 332             wxLogSysError(_("can't flush file descriptor %d"), m_fd
); 
 343 // ---------------------------------------------------------------------------- 
 345 // ---------------------------------------------------------------------------- 
 348 off_t 
wxFile::Seek(off_t ofs
, wxSeekMode mode
) 
 350     wxASSERT( IsOpened() ); 
 367             wxFAIL_MSG(_("unknown seek origin")); 
 370     int iRc 
= lseek(m_fd
, ofs
, flag
); 
 372         wxLogSysError(_("can't seek on file descriptor %d"), m_fd
); 
 373         return wxInvalidOffset
; 
 380 off_t 
wxFile::Tell() const 
 382     wxASSERT( IsOpened() ); 
 384     int iRc 
= tell(m_fd
); 
 386         wxLogSysError(_("can't get seek position on file descriptor %d"), m_fd
); 
 387         return wxInvalidOffset
; 
 393 // get current file length 
 394 off_t 
wxFile::Length() const 
 396     wxASSERT( IsOpened() ); 
 399     int iRc 
= _filelength(m_fd
); 
 401     int iRc 
= tell(m_fd
); 
 403         // @ have to use const_cast :-( 
 404         int iLen 
= ((wxFile 
*)this)->SeekEnd(); 
 406             // restore old position 
 407             if ( ((wxFile 
*)this)->Seek(iRc
) == -1 ) { 
 418         wxLogSysError(_("can't find length of file on file descriptor %d"), m_fd
); 
 419         return wxInvalidOffset
; 
 425 // is end of file reached? 
 426 bool wxFile::Eof() const 
 428     wxASSERT( IsOpened() ); 
 432 #if defined(__UNIX__) || defined(__GNUWIN32__) || defined( __MWERKS__ ) || defined(__SALFORDC__) 
 433     // @@ this doesn't work, of course, on unseekable file descriptors 
 434     off_t ofsCur 
= Tell(), 
 436     if ( ofsCur 
== wxInvalidOffset 
|| ofsMax 
== wxInvalidOffset 
) 
 439         iRc 
= ofsCur 
== ofsMax
; 
 440 #else  // Windows and "native" compiler 
 442 #endif // Windows/Unix 
 452             wxLogSysError(_("can't determine if the end of file is reached on \ 
 453                 descriptor %d"), m_fd
); 
 457             wxFAIL_MSG(_("invalid eof() return value.")); 
 463 // ============================================================================ 
 464 // implementation of wxTempFile 
 465 // ============================================================================ 
 467 // ---------------------------------------------------------------------------- 
 469 // ---------------------------------------------------------------------------- 
 470 wxTempFile::wxTempFile(const wxString
& strName
) 
 475 bool wxTempFile::Open(const wxString
& strName
) 
 479     // we want to create the file in the same directory as strName because 
 480     // otherwise rename() in Commit() might not work (if the files are on 
 481     // different partitions for example). Unfortunately, the only standard 
 482     // (POSIX) temp file creation function tmpnam() can't do it. 
 483 #if defined(__UNIX__) || defined(__WXSTUBS__)|| defined( __WXMAC__ ) 
 484     static const wxChar 
*szMktempSuffix 
= _T("XXXXXX"); 
 485     m_strTemp 
<< strName 
<< szMktempSuffix
; 
 486     mktemp(MBSTRINGCAST m_strTemp
.mb_str()); // will do because length doesn't change 
 489     wxSplitPath(strName
, &strPath
, NULL
, NULL
); 
 490     if ( strPath
.IsEmpty() ) 
 491         strPath 
= _T('.');  // GetTempFileName will fail if we give it empty string 
 493     if ( !GetTempFileName(strPath
, _T("wx_"),0, m_strTemp
.GetWriteBuf(MAX_PATH
)) ) 
 495         // Not sure why MSVC++ 1.5 header defines first param as BYTE - bug? 
 496         if ( !GetTempFileName((BYTE
) (const wxChar
*) strPath
, _T("wx_"),0, m_strTemp
.GetWriteBuf(MAX_PATH
)) ) 
 498             wxLogLastError(_T("GetTempFileName")); 
 499     m_strTemp
.UngetWriteBuf(); 
 500 #endif  // Windows/Unix 
 502     int access 
= wxS_DEFAULT
; 
 504     // create the file with the same mode as the original one under Unix 
 505     mode_t umaskOld 
= 0; // just to suppress compiler warning 
 509     if ( stat(strName
.fn_str(), &st
) == 0 ) 
 511         // this assumes that only lower bits of st_mode contain the access 
 512         // rights, but it's true for at least all Unices which have S_IXXXX() 
 513         // macros, so should not be less portable than using (not POSIX) 
 515         access 
= st
.st_mode 
& 0777; 
 517         // we want to create the file with exactly the same access rights as 
 518         // the original one, so disable the user's umask for the moment 
 524         // file probably didn't exist, just create with default mode _using_ 
 525         // user's umask (new files creation should respet umask) 
 526         changedUmask 
= FALSE
; 
 530     bool ok 
= m_file
.Open(m_strTemp
, wxFile::write
, access
); 
 535         // restore umask now that the file is created 
 536         (void)umask(umaskOld
); 
 543 // ---------------------------------------------------------------------------- 
 545 // ---------------------------------------------------------------------------- 
 547 wxTempFile::~wxTempFile() 
 553 bool wxTempFile::Commit() 
 557     if ( wxFile::Exists(m_strName
) && remove(m_strName
.fn_str()) != 0 ) { 
 558         wxLogSysError(_("can't remove file '%s'"), m_strName
.c_str()); 
 562     if ( rename(m_strTemp
.fn_str(), m_strName
.fn_str()) != 0 ) { 
 563         wxLogSysError(_("can't commit changes to file '%s'"), m_strName
.c_str()); 
 570 void wxTempFile::Discard() 
 573     if ( remove(m_strTemp
.fn_str()) != 0 ) 
 574         wxLogSysError(_("can't remove temporary file '%s'"), m_strTemp
.c_str());