home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 18.ddi / MFC / SRC / FILECORE.CP_ / FILECORE.CP
Encoding:
Text File  |  1993-02-08  |  11.2 KB  |  557 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and Microsoft
  7. // QuickHelp and/or WinHelp documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12. #include <errno.h>
  13. #include <io.h>
  14. #include <limits.h>
  15. #include <malloc.h>
  16.  
  17. #include <sys\types.h>
  18. #include <sys\stat.h>
  19. #ifdef _PORTABLE
  20. #include <sys\locking.h>
  21. #endif
  22.  
  23. #ifdef AFX_CORE2_SEG
  24. #pragma code_seg(AFX_CORE2_SEG)
  25. #endif
  26.  
  27. #ifdef _DEBUG
  28. #undef THIS_FILE
  29. static char BASED_CODE THIS_FILE[] = __FILE__;
  30. #endif
  31.  
  32. #define new DEBUG_NEW
  33.  
  34. ////////////////////////////////////////////////////////////////////////////
  35. // Low level File i/o portability layer
  36. // DOS functions not provided by C Runtimes
  37.  
  38.  
  39. #include <dos.h>
  40. #ifdef _WINDOWS
  41. extern "C" void FAR PASCAL DOS3Call();
  42. #define DOSCALL call DOS3Call
  43. #else // _DOS
  44. #define DOSCALL int 21h
  45. #endif // _WINDOWS
  46.  
  47. #ifndef _PORTABLE
  48. // Non-Portable, DOSCALL specific implementation
  49. //  Most efficient and gives most accurate failure codes
  50.  
  51. #pragma optimize("qgel", off) // assembler cannot be globally optimized
  52.  
  53. static UINT PASCAL _Afx_seek(UINT hFile, LONG lOff, UINT nMode, 
  54.             DWORD FAR* lpdwNew)
  55.     UINT res;
  56.     *lpdwNew = -1;
  57.     _asm { 
  58.             mov     bx, hFile
  59.             mov     ax, nMode
  60.             mov     ah, 42h
  61.             mov     dx, word ptr lOff
  62.             mov     cx, word ptr lOff+2
  63.             DOSCALL
  64.             jc      __seek_err
  65.             les     bx, lpdwNew
  66.             mov     word ptr es:[bx], ax
  67.             mov     word ptr es:[bx+2], dx
  68.             xor     ax, ax
  69.     __seek_err:
  70.             mov     res, ax
  71.     }
  72.     return res;
  73. }
  74.         
  75. static UINT PASCAL _Afx_rename(LPCSTR lpszOld, LPCSTR lpszNew)
  76.     UINT res;
  77.     _asm { 
  78.             mov     bx, ds
  79.             lds     dx, lpszOld
  80.             les     di, lpszNew
  81.             mov     ax, 5600h
  82.             DOSCALL
  83.             jc      __rename_err
  84.             xor     ax, ax
  85.     __rename_err:
  86.             mov     res, ax
  87.             mov     ds, bx
  88.     }
  89.     return res;
  90. }
  91.  
  92. static UINT PASCAL _Afx_remove(LPCSTR lpsz)  
  93.     UINT res;
  94.     _asm { 
  95.             mov     bx, ds
  96.             lds     dx, lpsz
  97.             mov     ax, 4100h
  98.             DOSCALL
  99.             jc      __remove_err
  100.             xor     ax, ax
  101.     __remove_err:
  102.             mov     res, ax
  103.             mov     ds, bx
  104.     }
  105.     return res;
  106. }
  107.  
  108. static UINT PASCAL _Afx_lock(UINT hFile, DWORD dwStart, DWORD dwLen, BOOL bUnlock)
  109.     UINT res;
  110.     _asm { 
  111.             mov     ax, bUnlock
  112.             mov     ah, 5ch
  113.             mov     bx, hFile
  114.             mov     dx, word ptr dwStart
  115.             mov     cx, word ptr dwStart+2
  116.             mov     di, word ptr dwLen
  117.             mov     si, word ptr dwLen+2
  118.             DOSCALL
  119.             jc      __lock_err1
  120.             xor     ax, ax
  121.     __lock_err1:
  122.             mov     res, ax
  123.             
  124.     }
  125.     return res;
  126. }
  127.  
  128. #pragma optimize("", on)    // return to default optimizations
  129.  
  130. #else   // _PORTABLE implementations
  131.  
  132. // Portable, C-Runtime implementation
  133. //  More portable but can gives less accurate failure codes
  134. static UINT PASCAL _Afx_seek(UINT hFile, LONG lOff, UINT nMode, 
  135.             DWORD FAR* lpdwNew)
  136. {
  137.     *lpdwNew = (DWORD)_lseek((int)hFile, lOff, (int)nMode);
  138.     if (*lpdwNew == (DWORD)-1L)
  139.     {
  140.         if (errno == EBADF)
  141.             return 0x6; // invalid file
  142.         else
  143.             return 0x19; // bad seek
  144.     }
  145.     return 0;
  146. }
  147.  
  148. static UINT PASCAL _Afx_rename(LPCSTR lpszOld, LPCSTR lpszNew)
  149. {
  150.     char* pszOld;
  151.     char* pszNew;
  152. #ifdef _NEARDATA
  153.     char szOld[_MAX_PATH];
  154.     char szNew[_MAX_PATH];
  155.     lstrcpy(szOld, lpszOld);
  156.     lstrcpy(szNew, lpszNew);
  157.     pszOld = szOld;
  158.     pszNew = szNew;
  159. #else
  160.     pszOld = (LPSTR)lpszOld;
  161.     pszNew = (LPSTR)lpszNew;
  162. #endif
  163.     if (rename(pszOld, pszNew) != 0)
  164.     {
  165.         if (errno == EACCES)
  166.             return 0x5; // access denied
  167.         else
  168.             return 0x2; // file not found
  169.     }
  170.     return 0;
  171. }
  172.  
  173. static UINT PASCAL _Afx_remove(LPCSTR lpsz)  
  174. {
  175.     char* psz;
  176. #ifdef _NEARDATA
  177.     char sz[_MAX_PATH];
  178.     lstrcpy(sz, lpsz);
  179.     psz = sz;
  180. #else
  181.     psz = (LPSTR)lpsz;
  182. #endif
  183.     if (remove(psz) != 0)
  184.     {
  185.         if (errno == EACCES)
  186.             return 0x5; // access denied
  187.         else
  188.             return 0x2; // file not found
  189.     }
  190.     return 0;
  191. }
  192.  
  193. static UINT PASCAL _Afx_lock(UINT hFile, DWORD dwStart, DWORD dwLen, BOOL bUnlock)
  194.     DWORD dwPos;
  195.     DWORD dw;
  196.     UINT nErr;
  197.  
  198.     if (_Afx_seek(hFile, 0, 0, &dwPos) != 0)
  199.         return 0;
  200.     if ((nErr = _Afx_seek(hFile, (LONG)dwStart, 0, &dw)) != 0)
  201.     {
  202.         _Afx_seek(hFile, dwPos, 0, &dw);
  203.         return nErr;
  204.     }
  205.     if (_locking(hFile, bUnlock ? _LK_UNLCK : _LK_NBLCK, dwLen) != 0)
  206.     {
  207.         switch (errno)
  208.         {
  209.         case EACCES:
  210.             return 0x21; // lock violation
  211.         case EBADF:
  212.             return 0x6; // bad file handle
  213.         default:
  214.             return 0x1;
  215.         }
  216.     }
  217.     _Afx_seek(hFile, dwPos, 0, &dw);
  218.     return 0;
  219. }
  220.  
  221. #endif // _PORTABLE
  222.  
  223. ////////////////////////////////////////////////////////////////////////////
  224. // CFile implementation
  225. IMPLEMENT_DYNAMIC(CFile, CObject)
  226.  
  227.  
  228. CFile::CFile()
  229. {
  230.     m_hFile = hFileNull;
  231.     m_bCloseOnDelete = FALSE;
  232. }
  233.  
  234. CFile::CFile(int hFile)
  235. {
  236.     m_hFile = hFile;
  237.     m_bCloseOnDelete = FALSE;
  238. }
  239.  
  240. CFile::CFile(const char* pszFileName, UINT nOpenFlags)
  241. {
  242.     ASSERT(AfxIsValidString(pszFileName));
  243.  
  244.     CFileException e;
  245.     if (!Open(pszFileName, nOpenFlags, &e))
  246.         AfxThrowFileException(e.m_cause, e.m_lOsError);
  247. }
  248.  
  249. CFile::~CFile()
  250. {   
  251.     if (m_hFile != (UINT)hFileNull && m_bCloseOnDelete)
  252.         Close();
  253. }
  254.  
  255. CFile*
  256. CFile::Duplicate() const
  257. {
  258.     ASSERT_VALID(this);
  259.     ASSERT(m_hFile != (UINT)hFileNull);
  260.  
  261.     CFile* pFile = new CFile(hFileNull);
  262.     pFile->m_hFile = (UINT) _dup((int)m_hFile);
  263.     ASSERT(((int)(pFile->m_hFile)) != -1);
  264.     pFile->m_bCloseOnDelete = m_bCloseOnDelete;
  265.     return pFile;
  266. }
  267.  
  268.  
  269. BOOL
  270. CFile::Open(const char* pszFileName, UINT nOpenFlags, 
  271.     CFileException* pException /* = NULL */)
  272. {
  273.     ASSERT(AfxIsValidString(pszFileName));
  274.     ASSERT(pException == NULL || AfxIsValidAddress(pException, sizeof(CFileException)));
  275.     ASSERT((nOpenFlags & typeText) == 0);
  276.  
  277.     // CFile objects are always binary and _dos_open does not need flag
  278.     nOpenFlags &= ~(UINT)CFile::typeBinary;
  279.  
  280.     m_bCloseOnDelete = FALSE;
  281.     m_hFile = (UINT)hFileNull;
  282.  
  283.     ASSERT_VALID(this);
  284.  
  285.     char szOemPath[_MAX_PATH];
  286.     UINT nErr;
  287.  
  288.     AnsiToOem(pszFileName, szOemPath);
  289.  
  290.     if (nOpenFlags & (UINT)CFile::modeCreate)
  291.     {
  292.         if ((nErr = _dos_creat(szOemPath, CFile::normal, (int*)&m_hFile)) != 0)
  293.         {
  294.             if (pException != NULL)
  295.             {
  296.                 pException->m_lOsError = nErr;
  297.                 pException->m_cause = CFileException::OsErrorToException(nErr);
  298.                 return FALSE; // file was not created
  299.             }
  300.         }
  301.         if ((nErr = _dos_close(m_hFile)) != 0)
  302.         {
  303.             // try to delete the file and throw modeCreate exception
  304.             _Afx_remove(szOemPath);
  305.             if (pException != NULL)
  306.             {
  307.                 pException->m_lOsError = nErr;
  308.                 pException->m_cause = CFileException::OsErrorToException(nErr);
  309.             }
  310.             return FALSE;
  311.         }
  312.     }
  313.  
  314.     // the file has been modeCreated if needed, now open it
  315.     if ((nErr = _dos_open(szOemPath, nOpenFlags & ~(UINT)CFile::modeCreate, (int*)&m_hFile)) != 0)
  316.     {
  317.         // throw open exception if requested
  318.         if (pException != NULL)
  319.         {
  320.             pException->m_lOsError = nErr;
  321.             pException->m_cause = CFileException::OsErrorToException(nErr);
  322.         }
  323.         return FALSE;
  324.     }
  325.     m_bCloseOnDelete = TRUE;
  326.     return TRUE;
  327. }
  328.  
  329.  
  330. UINT
  331. CFile::Read(void FAR* lpBuf, UINT nCount)
  332. {
  333.     ASSERT_VALID(this);
  334.     ASSERT(m_hFile != (UINT)hFileNull);
  335.     ASSERT(lpBuf != NULL);
  336.     ASSERT(AfxIsValidAddress(lpBuf, nCount));
  337.  
  338.     UINT nRead = 0;
  339.     UINT nErr;
  340.  
  341.     if ((nErr = _dos_read(m_hFile, lpBuf, nCount, &nRead)) != 0)
  342.         CFileException::ThrowOsError(nErr);
  343.         
  344.     return nRead;
  345. }
  346.  
  347. void
  348. CFile::Write(const void FAR* lpBuf, UINT nCount)
  349. {
  350.     ASSERT_VALID(this);
  351.     ASSERT(m_hFile != (UINT)hFileNull);
  352.     ASSERT(lpBuf != NULL);
  353.     ASSERT(AfxIsValidAddress(lpBuf, nCount, FALSE));
  354.  
  355.     UINT nWritten = 0;
  356.     UINT nErr;
  357.  
  358.     if ((nErr = _dos_write(m_hFile, lpBuf, nCount, &nWritten)) != 0)
  359.         CFileException::ThrowOsError(nErr);
  360.     
  361.     if (nCount != nWritten)
  362.         AfxThrowFileException(CFileException::diskFull);
  363. }
  364.  
  365.  
  366. LONG
  367. CFile::Seek(LONG lOff, UINT nFrom)
  368. {
  369.     ASSERT_VALID(this);
  370.     ASSERT(m_hFile != (UINT)hFileNull);
  371.     ASSERT(nFrom == CFile::begin || nFrom == CFile::end || nFrom == CFile::current);
  372.  
  373.     DWORD dwNew;
  374.     UINT nErr;
  375.  
  376.     if ((nErr = _Afx_seek(m_hFile, lOff, nFrom, &dwNew)) != 0)
  377.         CFileException::ThrowOsError(nErr);
  378.     
  379.     return dwNew;
  380. }
  381.  
  382.  
  383. DWORD
  384. CFile::GetPosition() const
  385. {
  386.     ASSERT_VALID(this);
  387.     ASSERT(m_hFile != (UINT)hFileNull);
  388.  
  389.     DWORD dwPos;
  390.     UINT nErr;
  391.  
  392.     if ((nErr = _Afx_seek(m_hFile, 0, CFile::current, &dwPos)) != 0)
  393.         CFileException::ThrowOsError(nErr);
  394.     
  395.     return dwPos;
  396. }
  397.  
  398.  
  399. #pragma optimize("qgel", off) // assembler cannot be globally optimized
  400. void
  401. CFile::Flush()
  402. {
  403.     ASSERT_VALID(this);
  404.     
  405.     UINT nErr;
  406.  
  407.     if (m_hFile == (UINT)hFileNull)
  408.         return;
  409.  
  410. #ifndef _PORTABLE
  411.     // SmartDrive 4.0 workaround, carry flag incorrectly propogated
  412.     _asm { CLC }
  413. #endif
  414.  
  415.     if ((nErr = _dos_commit(m_hFile)) != 0)
  416.         CFileException::ThrowOsError(nErr);
  417. }
  418. #pragma optimize("", on)    // return to default optimizations
  419.  
  420. void
  421. CFile::Close()
  422. {
  423.     ASSERT_VALID(this);
  424.     ASSERT(m_hFile != (UINT)hFileNull);
  425.  
  426.     UINT nErr = 0;
  427.  
  428.     if (m_hFile != (UINT)hFileNull)
  429.         nErr = _dos_close(m_hFile);
  430.  
  431.     m_hFile = hFileNull;
  432.     m_bCloseOnDelete = FALSE;
  433.  
  434.     if (nErr != 0)
  435.         CFileException::ThrowOsError(nErr);
  436. }
  437.  
  438. void
  439. CFile::Abort()
  440. {
  441.     ASSERT_VALID(this);
  442.     if (m_hFile != (UINT)hFileNull)
  443.     {
  444.         // close but ignore errors
  445.         _dos_close(m_hFile);
  446.         m_hFile = (UINT)hFileNull;
  447.     }
  448. }
  449.  
  450. void
  451. CFile::LockRange(DWORD dwPos, DWORD dwCount)
  452. {
  453.     ASSERT_VALID(this);
  454.     ASSERT(m_hFile != (UINT)hFileNull);
  455.  
  456.     UINT nErr;
  457.  
  458.     if ((nErr = _Afx_lock(m_hFile, dwPos, dwCount, FALSE)) != 0)
  459.         CFileException::ThrowOsError(nErr);
  460. }
  461.  
  462.  
  463. void
  464. CFile::UnlockRange(DWORD dwPos, DWORD dwCount)
  465. {
  466.     ASSERT_VALID(this);
  467.     ASSERT(m_hFile != (UINT)hFileNull);
  468.  
  469.     UINT nErr;
  470.  
  471.     if ((nErr = _Afx_lock(m_hFile, dwPos, dwCount, TRUE)) != 0)
  472.         CFileException::ThrowOsError(nErr);
  473. }
  474.  
  475.  
  476. void
  477. CFile::SetLength(DWORD dwNewLen)
  478. {
  479.     ASSERT_VALID(this);
  480.     ASSERT(m_hFile != (UINT)hFileNull);
  481.  
  482.     UINT nErr;
  483.     UINT nWritten = 0;
  484.  
  485.     Seek(dwNewLen, CFile::begin);
  486.  
  487.     if ((nErr = _dos_write(m_hFile, NULL, 0, &nWritten)) != 0)
  488.         CFileException::ThrowOsError(nErr);
  489. }
  490.  
  491. DWORD
  492. CFile::GetLength() const
  493. {
  494.     ASSERT_VALID(this);
  495.  
  496.     DWORD dwLen, dwCur;
  497.     
  498.     // Seek is a non const operation 
  499.     dwCur = ((CFile*)this)->Seek(0L, CFile::current);
  500.     dwLen = ((CFile*)this)->SeekToEnd();
  501.     VERIFY(dwCur == (DWORD)(((CFile*)this)->Seek(dwCur, CFile::begin)));
  502.  
  503.     return dwLen;
  504. }
  505.  
  506. void PASCAL
  507. CFile::Rename(const char* pszOldName, const char* pszNewName)
  508. {
  509.     char szOld[_MAX_PATH];
  510.     char szNew[_MAX_PATH];
  511.     UINT nErr;
  512.  
  513.     AnsiToOem(pszOldName, szOld);
  514.     AnsiToOem(pszNewName, szNew);
  515.  
  516.     if ((nErr = _Afx_rename(szOld, szNew)) != 0)
  517.         CFileException::ThrowOsError(nErr);
  518.  
  519. }
  520.  
  521. void PASCAL
  522. CFile::Remove(const char* pszFileName)
  523. {
  524.     UINT nErr;
  525.     char sz[_MAX_PATH];
  526.  
  527.     AnsiToOem(pszFileName, sz);
  528.  
  529.     if ((nErr = _Afx_remove(sz)) != 0)
  530.         CFileException::ThrowOsError(nErr);
  531. }
  532.  
  533.  
  534. #ifdef _DEBUG
  535. void
  536. CFile::AssertValid() const
  537. {
  538.     CObject::AssertValid();
  539.     // we permit the descriptor m_hFile to be any value for derived classes
  540. }
  541.  
  542. void
  543. CFile::Dump(CDumpContext& dc) const
  544. {
  545.     ASSERT_VALID(this);
  546.  
  547.     CObject::Dump(dc);
  548.     AFX_DUMP1(dc, " with handle ", (UINT)m_hFile);
  549. }
  550.  
  551. #endif
  552.