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