home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / common / file.cpp < prev    next >
C/C++ Source or Header  |  2002-09-12  |  15KB  |  569 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        file.cpp
  3. // Purpose:     wxFile - encapsulates low-level "file descriptor"
  4. //              wxTempFile
  5. // Author:      Vadim Zeitlin
  6. // Modified by:
  7. // Created:     29/01/98
  8. // RCS-ID:      $Id: file.cpp,v 1.66 2002/09/12 19:32:29 VZ Exp $
  9. // Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
  10. // Licence:     wxWindows license
  11. /////////////////////////////////////////////////////////////////////////////
  12.  
  13. // ----------------------------------------------------------------------------
  14. // headers
  15. // ----------------------------------------------------------------------------
  16.  
  17. #ifdef __GNUG__
  18.     #pragma implementation "file.h"
  19. #endif
  20.  
  21. // For compilers that support precompilation, includes "wx.h".
  22. #include "wx/wxprec.h"
  23.  
  24. #ifdef __BORLANDC__
  25.   #pragma hdrstop
  26. #endif
  27.  
  28. #if wxUSE_FILE
  29.  
  30. // standard
  31. #if defined(__WXMSW__) && !defined(__GNUWIN32__) && !defined(__WXWINE__) && !defined(__WXMICROWIN__)
  32.   #include  <io.h>
  33.  
  34. #ifndef __SALFORDC__
  35.     #define   WIN32_LEAN_AND_MEAN
  36.     #define   NOSERVICE
  37.     #define   NOIME
  38.     #define   NOATOM
  39.     #define   NOGDI
  40.     #define   NOGDICAPMASKS
  41.     #define   NOMETAFILE
  42.     #define   NOMINMAX
  43.     #define   NOMSG
  44.     #define   NOOPENFILE
  45.     #define   NORASTEROPS
  46.     #define   NOSCROLL
  47.     #define   NOSOUND
  48.     #define   NOSYSMETRICS
  49.     #define   NOTEXTMETRIC
  50.     #define   NOWH
  51.     #define   NOCOMM
  52.     #define   NOKANJI
  53.     #define   NOCRYPT
  54.     #define   NOMCX
  55. #endif
  56.  
  57. #elif (defined(__UNIX__) || defined(__GNUWIN32__))
  58.     #include  <unistd.h>
  59.     #ifdef __GNUWIN32__
  60.         #include <windows.h>
  61.     #endif
  62. #elif defined(__DOS__)
  63.     #if defined(__WATCOMC__)
  64.        #include <io.h>
  65.     #elif defined(__DJGPP__)
  66.        #include <io.h>
  67.        #include <unistd.h>
  68.        #include <stdio.h>
  69.     #else
  70.         #error  "Please specify the header with file functions declarations."
  71.     #endif
  72. #elif (defined(__WXPM__))
  73.     #include <io.h>
  74. #elif (defined(__WXSTUBS__))
  75.     // Have to ifdef this for different environments
  76.     #include <io.h>
  77. #elif (defined(__WXMAC__))
  78. #if __MSL__ < 0x6000
  79.     int access( const char *path, int mode ) { return 0 ; }
  80. #else
  81.     int _access( const char *path, int mode ) { return 0 ; }
  82. #endif
  83.     char* mktemp( char * path ) { return path ;}
  84.     #include <stat.h>
  85.     #include  <unistd.h>
  86. #else
  87.     #error  "Please specify the header with file functions declarations."
  88. #endif  //Win/UNIX
  89.  
  90. #include  <stdio.h>       // SEEK_xxx constants
  91. #include  <fcntl.h>       // O_RDONLY &c
  92.  
  93. #if !defined(__MWERKS__) || defined(__WXMSW__)
  94.     #include  <sys/types.h>   // needed for stat
  95.     #include  <sys/stat.h>    // stat
  96. #endif
  97.  
  98. // Windows compilers don't have these constants
  99. #ifndef W_OK
  100.     enum
  101.     {
  102.         F_OK = 0,   // test for existence
  103.         X_OK = 1,   //          execute permission
  104.         W_OK = 2,   //          write
  105.         R_OK = 4    //          read
  106.     };
  107. #endif // W_OK
  108.  
  109. // there is no distinction between text and binary files under Unix, so define
  110. // O_BINARY as 0 if the system headers don't do it already
  111. #if defined(__UNIX__) && !defined(O_BINARY)
  112.     #define   O_BINARY    (0)
  113. #endif  //__UNIX__
  114.  
  115. #ifdef __SALFORDC__
  116.     #include <unix.h>
  117. #endif
  118.  
  119. #ifndef MAX_PATH
  120.     #define MAX_PATH 512
  121. #endif
  122.  
  123. // some broken compilers don't have 3rd argument in open() and creat()
  124. #ifdef __SALFORDC__
  125.     #define ACCESS(access)
  126.     #define stat    _stat
  127. #else // normal compiler
  128.     #define ACCESS(access)  , (access)
  129. #endif // Salford C
  130.  
  131. // wxWindows
  132. #ifndef WX_PRECOMP
  133.     #include  "wx/string.h"
  134.     #include  "wx/intl.h"
  135.     #include  "wx/log.h"
  136. #endif // !WX_PRECOMP
  137.  
  138. #include  "wx/filename.h"
  139. #include  "wx/file.h"
  140. #include  "wx/filefn.h"
  141.  
  142. #ifdef __WXMSW__
  143.     #include "wx/msw/mslu.h"
  144. #endif
  145.  
  146. // ============================================================================
  147. // implementation of wxFile
  148. // ============================================================================
  149.  
  150. // ----------------------------------------------------------------------------
  151. // static functions
  152. // ----------------------------------------------------------------------------
  153.  
  154. bool wxFile::Exists(const wxChar *name)
  155. {
  156.     return wxFileExists(name);
  157. }
  158.  
  159. bool wxFile::Access(const wxChar *name, OpenMode mode)
  160. {
  161.     int how;
  162.  
  163.     switch ( mode )
  164.     {
  165.         default:
  166.             wxFAIL_MSG(wxT("bad wxFile::Access mode parameter."));
  167.             // fall through
  168.  
  169.         case read:
  170.             how = R_OK;
  171.             break;
  172.  
  173.         case write:
  174.             how = W_OK;
  175.             break;
  176.  
  177.         case read_write:
  178.             how = R_OK | W_OK;
  179.             break;
  180.     }
  181.  
  182.     return wxAccess(name, how) == 0;
  183. }
  184.  
  185. // ----------------------------------------------------------------------------
  186. // opening/closing
  187. // ----------------------------------------------------------------------------
  188.  
  189. // ctors
  190. wxFile::wxFile(const wxChar *szFileName, OpenMode mode)
  191. {
  192.     m_fd = fd_invalid;
  193.     m_error = FALSE;
  194.  
  195.     Open(szFileName, mode);
  196. }
  197.  
  198. // create the file, fail if it already exists and bOverwrite
  199. bool wxFile::Create(const wxChar *szFileName, bool bOverwrite, int accessMode)
  200. {
  201.     // if bOverwrite we create a new file or truncate the existing one,
  202.     // otherwise we only create the new file and fail if it already exists
  203. #if defined(__WXMAC__) && !defined(__UNIX__)
  204.     // Dominic Mazzoni [dmazzoni+@cs.cmu.edu] reports that open is still broken on the mac, so we replace
  205.     // int fd = open(wxUnix2MacFilename( szFileName ), O_CREAT | (bOverwrite ? O_TRUNC : O_EXCL), access);
  206.     int fd = creat( szFileName , accessMode);
  207. #else
  208.     int fd = wxOpen( szFileName,
  209.                      O_BINARY | O_WRONLY | O_CREAT |
  210.                      (bOverwrite ? O_TRUNC : O_EXCL)
  211.                      ACCESS(accessMode) );
  212. #endif
  213.     if ( fd == -1 )
  214.     {
  215.         wxLogSysError(_("can't create file '%s'"), szFileName);
  216.         return FALSE;
  217.     }
  218.     else
  219.     {
  220.         Attach(fd);
  221.         return TRUE;
  222.     }
  223. }
  224.  
  225. // open the file
  226. bool wxFile::Open(const wxChar *szFileName, OpenMode mode, int accessMode)
  227. {
  228.     int flags = O_BINARY;
  229.  
  230.     switch ( mode )
  231.     {
  232.         case read:
  233.             flags |= O_RDONLY;
  234.             break;
  235.  
  236.         case write_append:
  237.             if ( wxFile::Exists(szFileName) )
  238.             {
  239.                 flags |= O_WRONLY | O_APPEND;
  240.                 break;
  241.             }
  242.             //else: fall through as write_append is the same as write if the
  243.             //      file doesn't exist
  244.  
  245.         case write:
  246.             flags |= O_WRONLY | O_CREAT | O_TRUNC;
  247.             break;
  248.  
  249.         case write_excl:
  250.             flags |= O_WRONLY | O_CREAT | O_EXCL;
  251.             break;
  252.  
  253.         case read_write:
  254.             flags |= O_RDWR;
  255.             break;
  256.     }
  257.  
  258.     int fd = wxOpen( szFileName, flags ACCESS(accessMode));
  259.     if ( fd == -1 )
  260.     {
  261.         wxLogSysError(_("can't open file '%s'"), szFileName);
  262.         return FALSE;
  263.     }
  264.     else {
  265.         Attach(fd);
  266.         return TRUE;
  267.     }
  268. }
  269.  
  270. // close
  271. bool wxFile::Close()
  272. {
  273.     if ( IsOpened() ) {
  274.         if ( close(m_fd) == -1 ) {
  275.             wxLogSysError(_("can't close file descriptor %d"), m_fd);
  276.             m_fd = fd_invalid;
  277.             return FALSE;
  278.         }
  279.         else
  280.             m_fd = fd_invalid;
  281.     }
  282.  
  283.     return TRUE;
  284. }
  285.  
  286. // ----------------------------------------------------------------------------
  287. // read/write
  288. // ----------------------------------------------------------------------------
  289.  
  290. // read
  291. off_t wxFile::Read(void *pBuf, off_t nCount)
  292. {
  293.     wxCHECK( (pBuf != NULL) && IsOpened(), 0 );
  294.  
  295. #ifdef __MWERKS__
  296.     int iRc = ::read(m_fd, (char*) pBuf, nCount);
  297. #else
  298.     int iRc = ::read(m_fd, pBuf, nCount);
  299. #endif
  300.     if ( iRc == -1 ) {
  301.         wxLogSysError(_("can't read from file descriptor %d"), m_fd);
  302.         return wxInvalidOffset;
  303.     }
  304.     else
  305.         return (size_t)iRc;
  306. }
  307.  
  308. // write
  309. size_t wxFile::Write(const void *pBuf, size_t nCount)
  310. {
  311.     wxCHECK( (pBuf != NULL) && IsOpened(), 0 );
  312.  
  313. #ifdef __MWERKS__
  314. #if __MSL__ >= 0x6000
  315.     int iRc = ::write(m_fd, (void*) pBuf, nCount);
  316. #else
  317.     int iRc = ::write(m_fd, (const char*) pBuf, nCount);
  318. #endif
  319. #else
  320.     int iRc = ::write(m_fd, pBuf, nCount);
  321. #endif
  322.     if ( iRc == -1 ) {
  323.         wxLogSysError(_("can't write to file descriptor %d"), m_fd);
  324.         m_error = TRUE;
  325.         return 0;
  326.     }
  327.     else
  328.         return iRc;
  329. }
  330.  
  331. // flush
  332. bool wxFile::Flush()
  333. {
  334.     if ( IsOpened() ) {
  335. #if defined(__VISUALC__) || wxHAVE_FSYNC
  336.         if ( wxFsync(m_fd) == -1 )
  337.         {
  338.             wxLogSysError(_("can't flush file descriptor %d"), m_fd);
  339.             return FALSE;
  340.         }
  341. #else // no fsync
  342.         // just do nothing
  343. #endif // fsync
  344.     }
  345.  
  346.     return TRUE;
  347. }
  348.  
  349. // ----------------------------------------------------------------------------
  350. // seek
  351. // ----------------------------------------------------------------------------
  352.  
  353. // seek
  354. off_t wxFile::Seek(off_t ofs, wxSeekMode mode)
  355. {
  356.     wxASSERT( IsOpened() );
  357.  
  358.     int origin;
  359.     switch ( mode ) {
  360.         default:
  361.             wxFAIL_MSG(_("unknown seek origin"));
  362.  
  363.         case wxFromStart:
  364.             origin = SEEK_SET;
  365.             break;
  366.  
  367.         case wxFromCurrent:
  368.             origin = SEEK_CUR;
  369.             break;
  370.  
  371.         case wxFromEnd:
  372.             origin = SEEK_END;
  373.             break;
  374.     }
  375.  
  376.     int iRc = lseek(m_fd, ofs, origin);
  377.     if ( iRc == -1 ) {
  378.         wxLogSysError(_("can't seek on file descriptor %d"), m_fd);
  379.         return wxInvalidOffset;
  380.     }
  381.     else
  382.         return (off_t)iRc;
  383. }
  384.  
  385. // get current off_t
  386. off_t wxFile::Tell() const
  387. {
  388.     wxASSERT( IsOpened() );
  389.  
  390.     int iRc = wxTell(m_fd);
  391.     if ( iRc == -1 ) {
  392.         wxLogSysError(_("can't get seek position on file descriptor %d"), m_fd);
  393.         return wxInvalidOffset;
  394.     }
  395.     else
  396.         return (off_t)iRc;
  397. }
  398.  
  399. // get current file length
  400. off_t wxFile::Length() const
  401. {
  402.     wxASSERT( IsOpened() );
  403.  
  404. #ifdef __VISUALC__
  405.     int iRc = _filelength(m_fd);
  406. #else // !VC++
  407.     int iRc = wxTell(m_fd);
  408.     if ( iRc != -1 ) {
  409.         // @ have to use const_cast :-(
  410.         int iLen = ((wxFile *)this)->SeekEnd();
  411.         if ( iLen != -1 ) {
  412.             // restore old position
  413.             if ( ((wxFile *)this)->Seek(iRc) == -1 ) {
  414.                 // error
  415.                 iLen = -1;
  416.             }
  417.         }
  418.  
  419.         iRc = iLen;
  420.     }
  421. #endif  // VC++
  422.  
  423.     if ( iRc == -1 ) {
  424.         wxLogSysError(_("can't find length of file on file descriptor %d"), m_fd);
  425.         return wxInvalidOffset;
  426.     }
  427.     else
  428.         return (off_t)iRc;
  429. }
  430.  
  431. // is end of file reached?
  432. bool wxFile::Eof() const
  433. {
  434.     wxASSERT( IsOpened() );
  435.  
  436.     int iRc;
  437.  
  438. #if defined(__DOS__) || defined(__UNIX__) || defined(__GNUWIN32__) || defined( __MWERKS__ ) || defined(__SALFORDC__)
  439.     // @@ this doesn't work, of course, on unseekable file descriptors
  440.     off_t ofsCur = Tell(),
  441.     ofsMax = Length();
  442.     if ( ofsCur == wxInvalidOffset || ofsMax == wxInvalidOffset )
  443.         iRc = -1;
  444.     else
  445.         iRc = ofsCur == ofsMax;
  446. #else  // Windows and "native" compiler
  447.     iRc = eof(m_fd);
  448. #endif // Windows/Unix
  449.  
  450.     switch ( iRc ) {
  451.         case 1:
  452.             break;
  453.  
  454.         case 0:
  455.             return FALSE;
  456.  
  457.         case -1:
  458.             wxLogSysError(_("can't determine if the end of file is reached on descriptor %d"), m_fd);
  459.                 break;
  460.  
  461.         default:
  462.             wxFAIL_MSG(_("invalid eof() return value."));
  463.     }
  464.  
  465.     return TRUE;
  466. }
  467.  
  468. // ============================================================================
  469. // implementation of wxTempFile
  470. // ============================================================================
  471.  
  472. // ----------------------------------------------------------------------------
  473. // construction
  474. // ----------------------------------------------------------------------------
  475.  
  476. wxTempFile::wxTempFile(const wxString& strName)
  477. {
  478.     Open(strName);
  479. }
  480.  
  481. bool wxTempFile::Open(const wxString& strName)
  482. {
  483.     // we must have an absolute filename because otherwise CreateTempFileName()
  484.     // would create the temp file in $TMP (i.e. the system standard location
  485.     // for the temp files) which might be on another volume/drive/mount and
  486.     // wxRename()ing it later to m_strName from Commit() would then fail
  487.     //
  488.     // with the absolute filename, the temp file is created in the same
  489.     // directory as this one which ensures that wxRename() may work later
  490.     wxFileName fn(strName);
  491.     if ( !fn.IsAbsolute() )
  492.     {
  493.         fn.Normalize(wxPATH_NORM_ABSOLUTE);
  494.     }
  495.  
  496.     m_strName = fn.GetFullPath();
  497.  
  498.     m_strTemp = wxFileName::CreateTempFileName(m_strName, &m_file);
  499.  
  500.     if ( m_strTemp.empty() )
  501.     {
  502.         // CreateTempFileName() failed
  503.         return FALSE;
  504.     }
  505.  
  506. #ifdef __UNIX__
  507.     // the temp file should have the same permissions as the original one
  508.     mode_t mode;
  509.     
  510.     wxStructStat st;
  511.     if ( stat( (const char*) m_strName.fn_str(), &st) == 0 )
  512.     {
  513.         mode = st.st_mode;
  514.     }
  515.     else
  516.     {
  517.         // file probably didn't exist, just give it the default mode _using_
  518.         // user's umask (new files creation should respect umask)
  519.         mode_t mask = umask(0777);
  520.         mode = 0666 & ~mask;
  521.         umask(mask);
  522.     }
  523.  
  524.     if ( chmod( (const char*) m_strTemp.fn_str(), mode) == -1 )
  525.     {
  526.         wxLogSysError(_("Failed to set temporary file permissions"));
  527.     }
  528. #endif // Unix
  529.  
  530.     return TRUE;
  531. }
  532.  
  533. // ----------------------------------------------------------------------------
  534. // destruction
  535. // ----------------------------------------------------------------------------
  536.  
  537. wxTempFile::~wxTempFile()
  538. {
  539.     if ( IsOpened() )
  540.         Discard();
  541. }
  542.  
  543. bool wxTempFile::Commit()
  544. {
  545.     m_file.Close();
  546.  
  547.     if ( wxFile::Exists(m_strName) && wxRemove(m_strName) != 0 ) {
  548.         wxLogSysError(_("can't remove file '%s'"), m_strName.c_str());
  549.         return FALSE;
  550.     }
  551.  
  552.     if ( wxRename(m_strTemp, m_strName) != 0 ) {
  553.         wxLogSysError(_("can't commit changes to file '%s'"), m_strName.c_str());
  554.         return FALSE;
  555.     }
  556.  
  557.     return TRUE;
  558. }
  559.  
  560. void wxTempFile::Discard()
  561. {
  562.     m_file.Close();
  563.     if ( wxRemove(m_strTemp) != 0 )
  564.         wxLogSysError(_("can't remove temporary file '%s'"), m_strTemp.c_str());
  565. }
  566.  
  567. #endif // wxUSE_FILE
  568.  
  569.