hxbufdataf.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:23k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: hxbufdataf.cpp,v 1.1.32.3 2004/07/09 01:44:17 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #include "hlxclib/sys/types.h"
  50. #include "hlxclib/sys/stat.h"
  51. #include "hlxclib/fcntl.h"
  52. #include "hlxclib/errno.h"
  53. #include "hxtypes.h"
  54. #include "hxcom.h"
  55. #include "hxresult.h"
  56. #include "ihxpckts.h"
  57. #include "hxbuffer.h"
  58. #include "debug.h"
  59. #include "hxbufdataf.h"
  60. #include "op_fs.h"
  61. /////////////////////////////////////////////////////////////////////////
  62. //
  63. //  Method:
  64. //      HXBufferedDataFile::QueryInterface
  65. //  Purpose:
  66. //      Implement this to export the interfaces supported by your
  67. //      object.
  68. //
  69. STDMETHODIMP
  70. HXBufferedDataFile::QueryInterface(REFIID riid, void** ppvObj)
  71. {
  72.     if (IsEqualIID(riid, IID_IHXDataFile))
  73.     {
  74.         AddRef();
  75.         *ppvObj = (IHXDataFile*)this;
  76.         return HXR_OK;
  77.     }
  78.     
  79.     *ppvObj = NULL;
  80.     return HXR_NOINTERFACE;
  81. }   
  82. /////////////////////////////////////////////////////////////////////////
  83. //
  84. //  Method:
  85. //      HXBufferedDataFile::AddRef
  86. //  Purpose:
  87. //      Everyone usually implements this the same... feel free to use
  88. //      this implementation.
  89. //
  90. STDMETHODIMP_(ULONG32)
  91. HXBufferedDataFile::AddRef()
  92. {
  93.     return InterlockedIncrement(&m_lRefCount);
  94. }   
  95. /////////////////////////////////////////////////////////////////////////
  96. //
  97. //  Method:
  98. //      HXBufferedDataFile::Release
  99. //  Purpose:
  100. //      Everyone usually implements this the same... feel free to use
  101. //      this implementation.
  102. //
  103. STDMETHODIMP_(ULONG32)
  104. HXBufferedDataFile::Release()
  105. {
  106.     if (InterlockedDecrement(&m_lRefCount) > 0)
  107.     {
  108.         return m_lRefCount;
  109.     }
  110.     
  111.     delete this;
  112.     return 0;
  113. }   
  114. HXBufferedDataFile::HXBufferedDataFile()
  115.     : m_lRefCount(0),
  116.       m_LastError(0),
  117.       m_pFileName(0),
  118.       m_Fd(-1),
  119.       m_Flags(0),
  120.       m_Begin(0),
  121.       m_BufSize(0),
  122.       m_BufFill(0),
  123.       m_Offset(0),
  124.       m_FileOffset(0),
  125.       m_FlushSize(0),
  126.       m_pBuf(0),
  127.       m_Dirty(0)
  128. {
  129.     m_pFileName = new CHXBuffer;
  130.     m_pFileName->AddRef();
  131.     m_BufSize = GetPageSize();
  132. }
  133. HXBufferedDataFile::~HXBufferedDataFile()
  134. {
  135.     Close();
  136.     FreeBuf();
  137.     HX_RELEASE(m_pFileName);
  138.     m_pFileName = 0;
  139. }
  140. /////////////////////////////////////////////////////////////////////////
  141. //
  142. // Method:
  143. //     HXBufferedDataFile::Bind:
  144. // Purpose:
  145. //     Cache the file name for opening.
  146. //     If file already open, close it.
  147. //
  148. STDMETHODIMP_(void)
  149. HXBufferedDataFile::Bind(const char* pFileName)
  150. {
  151.     if (m_Fd >= 0)
  152. Close();
  153.     m_pFileName->Set((BYTE *)pFileName, ::strlen(pFileName)+1);
  154. }
  155. /////////////////////////////////////////////////////////////////////////
  156. //
  157. // Method:
  158. //     HXBufferedDataFile::Create
  159. // Purpose:
  160. //     Creates a datafile using the specified mode
  161. //     uOpenMode - File Open mode - HX_FILEFLAG_READ/HX_FILEFLAG_WRITE/HX_FILEFLAG_BINARY
  162. //
  163. STDMETHODIMP
  164. HXBufferedDataFile::Create(UINT16 uOpenMode)
  165. {
  166.     return HXR_NOTIMPL;
  167. }
  168. /////////////////////////////////////////////////////////////////////////
  169. //
  170. //  Method:
  171. //      HXBufferedDatatFile::Open
  172. //  Purpose:
  173. //      Open for buffered i/o.  If file is already open, ignore this
  174. //      open and return HXR_OK status.  Flags can have 3 possible values
  175. //
  176. //    HX_FILEFLAG_READ:     Open file read only
  177. //
  178. //    HX_FILEFLAG_WRITE:    Open file for writing.  If file does not
  179. //      exists, it is created.
  180. //
  181. //    HX_FILEFLAG_READ|HX_FILEFLAG_WRITE:                
  182. //                           Open file for both read and writing.
  183. //
  184. //  Note:
  185. //      HX_FILEFLAG_WRITE implies both reads and writes to the file.  It
  186. //      also implies the file can be randomly updated any where in the
  187. //      file as well as appended onto the end. If the file exists,
  188. //      then the file contents are buffered in before updating.  As a
  189. //      result, writing implies both system reads and writes.
  190. //
  191. //      If open succeeds, returns HXR_OK, otherwise HXR_FAIL.
  192. //
  193. STDMETHODIMP
  194. HXBufferedDataFile::Open(UINT16 flags)
  195. {
  196. // flags don't match close and reopen
  197.     if (m_Fd >= 0 && flags != m_Flags)
  198.     {
  199. Close();
  200.     }
  201.     int status = HXR_OK;
  202.     if (m_Fd < 0)
  203.     {
  204. int oflags = 0;
  205. m_Flags = flags;
  206. m_LastError = 0;
  207. if (m_Flags & HX_FILEFLAG_WRITE)
  208. {
  209.     oflags = (O_CREAT|O_RDWR);
  210.     if (!(m_Flags & HX_FILEFLAG_NOTRUNC))
  211.     {
  212. oflags |= O_TRUNC;
  213.     }
  214. }
  215. else if (m_Flags & HX_FILEFLAG_READ)
  216.     oflags = O_RDONLY;
  217. else
  218.     return HXR_FAIL;
  219. if ((m_Fd =
  220.      //::open((const char*) m_pFileName->GetBuffer(), oflags, 0644)) < 0)
  221.              OpFsOpen((const char*) m_pFileName->GetBuffer(), oflags, 0)) == kOpFsErrAny)
  222. {
  223.     status = HXR_FAIL;
  224.     m_LastError = errno;
  225. }
  226. else // open ok: initialize
  227. {
  228.     if (m_pBuf == 0)
  229. AllocBuf();
  230.     m_Begin = 0;
  231.     m_BufFill = 0;
  232.     m_Offset = 0;
  233.     m_FileOffset = 0;
  234.     m_FlushSize = 0;
  235.     m_LastError = 0;
  236.     m_Dirty = 0;
  237. }
  238.     }
  239.     return status;
  240. }
  241. /////////////////////////////////////////////////////////////////////////
  242. //
  243. // Method:
  244. //     HXBufferedDataFile::Close:
  245. //  Purpose:
  246. //     Flush the file buffer (if open of writing and close the file.
  247. //     Note that file is not closed when there are multiple references
  248. //     to this object.
  249. //
  250. STDMETHODIMP
  251. HXBufferedDataFile::Close()
  252. {
  253.     int status = HXR_OK;
  254.     if (m_Fd >= 0 && m_lRefCount <= 1)
  255.     {
  256. if (m_Flags & HX_FILEFLAG_WRITE)
  257.     FlushBuf();
  258. //if (::close(m_Fd) == -1)
  259. if (OpFsClose( m_Fd ) != kOpFsErrOk )
  260. {
  261.     status = HXR_FAIL;
  262.     m_LastError = errno;
  263. }
  264. m_Fd = -1;
  265.     }
  266.     return status;
  267. }
  268. /////////////////////////////////////////////////////////////////////////
  269. //
  270. // Method:
  271. //     HXBufferedDataFile::Name
  272. // Purpose:
  273. //     Name returns the currently bound file name in FileName.
  274. //     and returns TRUE, if the a name has been bound.  Otherwise
  275. //     FALSE is returned.
  276. //
  277. STDMETHODIMP_(BOOL)
  278. HXBufferedDataFile::Name(REF(IHXBuffer*) pFileName)
  279. {
  280.     if (m_pFileName && m_pFileName->GetSize())
  281.     {
  282. pFileName = m_pFileName;
  283. pFileName->AddRef();
  284. return TRUE;
  285.     }
  286.     return FALSE;
  287. }
  288. /////////////////////////////////////////////////////////////////////////
  289. //
  290. // Method:
  291. //     HXBufferedDataFile::IsOpen()
  292. // Purpose:
  293. //     IsOpen returns TRUE if file is open.  Otherwise FALSE.
  294. //
  295. BOOL
  296. HXBufferedDataFile::IsOpen()
  297. {
  298.     return (m_Fd >= 0 ? TRUE : FALSE);
  299. }
  300. /////////////////////////////////////////////////////////////////////////
  301. //
  302. // Method
  303. //     HXBufferedDataFile::Seek:
  304. // Purpose:
  305. //     Just move the seek offset according to the value of whense.
  306. //     This only sets the local idea of the current offset, no system
  307. //     level seek is performed.  If seek is ok, the current value of
  308. //     seek offset is returned.  Otherwise -1 is returned.
  309. //
  310. //     XXXBH:  24-Mar-99
  311. //       Note that most of callers expect HXR_OK as return value, not
  312. //       the current offset.  So the above comment is a noop.   Also
  313. //       the offset is passed in as an unsigned, it should be signed to
  314. //       allow seeks in both directions.  Right now we do the ugly cast.
  315. //
  316. STDMETHODIMP
  317. HXBufferedDataFile::Seek(ULONG32 offset, UINT16 whense)
  318. {
  319.     ULONG32 size = 0;
  320.     LONG32 signed_offset = (LONG32) offset;
  321.     if (whense == SEEK_SET && signed_offset >= 0)
  322. m_Offset = signed_offset;
  323.     else if (whense == SEEK_CUR && (LONG32) m_Offset + signed_offset >= 0)
  324. m_Offset += signed_offset;
  325.     else if (whense == SEEK_END &&
  326.      (LONG32) (size = LogicalSize()) + signed_offset >= 0)
  327. m_Offset = size + signed_offset;
  328.     else
  329. return HXR_FAIL;
  330.     return HXR_OK;
  331. }
  332. /////////////////////////////////////////////////////////////////////////
  333. //
  334. // Method:
  335. //     HXBufferedDataFile::Tell()
  336. // Purpose:
  337. //      Tell returns the current (logical) file position in the file
  338. //
  339. STDMETHODIMP_(ULONG32)
  340. HXBufferedDataFile::Tell()
  341. {
  342.     return m_Offset;
  343. }
  344. /////////////////////////////////////////////////////////////////////////
  345. //
  346. // Method:
  347. //     HXBufferedDataFile::Read:
  348. // Purpose
  349. //     Read nbytes into the supplied buffer.  Values returned:
  350. //
  351. //        Actual bytes read.  The smaller of the number bytes requested
  352. //        and  the number of bytes between the current seek offset and the
  353. //        end of file is returned.
  354. //
  355. //        0, if the current seek pointer is at or beyond the end of file.
  356. //      
  357. //        -1, if errors occure.  The LastError() member function returns
  358. //        the errno of the last system request.
  359. //
  360. STDMETHODIMP_(ULONG32)
  361. HXBufferedDataFile::Read(REF(IHXBuffer *) pBuf, ULONG32 count)
  362. {
  363.     if (m_Fd >= 0)
  364.     {
  365. pBuf->AddRef();
  366. ULONG32 nleft = count;
  367. INT32 rval = 0;
  368. unsigned char* buf = pBuf->GetBuffer();
  369. while (nleft > 0)
  370. {
  371. // If we enter this block, m_Offset
  372. // lies within the mapped buffer.
  373.     if (m_Begin <= m_Offset && m_Offset < m_Begin + m_BufFill ||
  374. (m_Offset < FlushSize() && (rval = NewBuf()) > 0))
  375.     {
  376. UINT32 off = m_Offset - m_Begin;  // offset within buffer
  377.  // and how much to copy
  378. UINT32 ncopy = m_Begin + m_BufFill - m_Offset;
  379. if (nleft < ncopy)
  380.     ncopy = nleft;
  381. ::memcpy((void*) buf, (const void*) (m_pBuf+off), ncopy); /* Flawfinder: ignore */
  382. nleft -= ncopy;
  383. m_Offset += ncopy;
  384. buf += ncopy;
  385.     }
  386. // NewBuf() could not make the above
  387. // assertion, true.  m_Offset is either
  388. // at or beyond EOF, or an error occured.
  389.     else
  390. break;
  391. }
  392. pBuf->Release();
  393. return rval >= 0 ? count - nleft : HXR_FAIL;
  394.     }
  395.     return HXR_FAIL;
  396. }
  397. /////////////////////////////////////////////////////////////////////////
  398. //
  399. // Method:
  400. //     HXBufferedDataFile::Write:
  401. // Purpose:
  402. //      Write the requested number of bytes.  The number of bytes
  403. //      written are return.  If errors occur, -1 is returned.  The
  404. //      LastError() member function returns the value of errno from
  405. //      the last system request.
  406. //
  407. STDMETHODIMP_(ULONG32)
  408. HXBufferedDataFile::Write(REF(IHXBuffer *) pBuf)
  409. {
  410.     if (m_Fd >= 0)
  411.     {
  412. pBuf->AddRef();
  413. ULONG32 count = pBuf->GetSize();
  414. ULONG32 nleft = count;
  415. INT32 rval = 0;
  416. const unsigned char* buf = pBuf->GetBuffer();
  417. while (nleft > 0)
  418. {
  419. // If we enter this block, m_Offset
  420. // lies within the current buffer.
  421.     if (m_Begin <= m_Offset && m_Offset < m_Begin + m_BufSize ||
  422. (rval = NewBuf()) >= 0)
  423.     {
  424. UINT32 off = m_Offset - m_Begin;  // offset within buffer
  425.   // and how much to copy
  426. UINT32 ncopy = m_Begin + m_BufSize - m_Offset;
  427. if (nleft < ncopy)
  428.     ncopy = nleft;
  429. ::memcpy((void*) (m_pBuf+off), (const void*) buf, ncopy); /* Flawfinder: ignore */
  430. m_Dirty = 1;
  431. nleft -= ncopy;
  432. m_Offset += ncopy;
  433. buf += ncopy;
  434. // data extend beyond what was read in
  435. if (m_Offset-m_Begin > m_BufFill)
  436.     m_BufFill = m_Offset-m_Begin;
  437.     }
  438. // NewBuf() could not make the above
  439. // assertion, true because an error occured.
  440.     else
  441. break;
  442. }
  443. pBuf->Release();
  444. return rval >= 0 ? count - nleft : HXR_FAIL;
  445.     }
  446.     return HXR_FAIL;
  447. }
  448. /////////////////////////////////////////////////////////////////////////
  449. //
  450. // Method:
  451. //     HXBufferedDataFile::Flush()
  452. // Purpose:
  453. //     Flush out the data in case of buffered I/O
  454. //  
  455. STDMETHODIMP
  456. HXBufferedDataFile::Flush()
  457. {
  458.     if (m_Flags & HX_FILEFLAG_WRITE)
  459. return FlushBuf() > 0 ? HXR_OK : HXR_FAIL;
  460.     return HXR_OK;
  461. }
  462. /////////////////////////////////////////////////////////////////////////
  463. //
  464. // Method:
  465. //     HXBufferedDataFile::Stat
  466. // Purpose:
  467. //     Return info about the data file such as permissions, time of
  468. //     creation size in bytes, etc.  Note that if this method is
  469. //     called with unflushed extensions to the file, the st_size field
  470. //     will not be correct.  We could Flush before filling in the stat
  471. //     data, but this is a const function.  The other alternative is
  472. //     to set the st.st_size field to the value returned by
  473. //     LogicalSize() (which includes unflushed extensions to the
  474. //     file).
  475. //
  476. STDMETHODIMP
  477. HXBufferedDataFile::Stat(struct stat* buf)
  478. {
  479.     return GetFileStat(buf);
  480. }
  481. STDMETHODIMP_(INT16)
  482. HXBufferedDataFile::GetFd()
  483. {   
  484.     return m_Fd;
  485. }
  486. /////////////////////////////////////////////////////////////////////////
  487. //
  488. // Method:
  489. //     HXBufferedDataFile::GetLastError:
  490. // Purpose:
  491. //     Returns the value of errno from the last system request.
  492. //
  493. STDMETHODIMP
  494. HXBufferedDataFile::GetLastError()
  495. {
  496.     return m_LastError;
  497. }
  498. STDMETHODIMP_(void) 
  499. HXBufferedDataFile::GetLastError(REF(IHXBuffer*) err)
  500. {
  501.     char* str = ::strerror(m_LastError);
  502.     err = new CHXBuffer;
  503.     err->Set((BYTE*) str, ::strlen(str)+1);
  504.     err->AddRef();
  505. }
  506. /////////////////////////////////////////////////////////////////////////
  507. //
  508. //  Method:
  509. //      HXBufferedDataFile::FlushSize():
  510. //  Purpose:
  511. //       Return flushed file size.  We assume that only this object
  512. //       has changed the size of the file.  The size returned does NOT
  513. //       include bytes in the buffer not yet flushed to the file.
  514. //
  515. ULONG32
  516. HXBufferedDataFile::FlushSize()
  517. {
  518.     if (m_FlushSize == 0)
  519.     {
  520. struct stat st;
  521. if (GetFileStat(&st) == HXR_OK)
  522.     m_FlushSize = st.st_size;
  523.     }
  524.     return m_FlushSize;
  525. }
  526. /////////////////////////////////////////////////////////////////////////
  527. //
  528. //  Method:
  529. //      HXBufferedDataFile::LogicalSize():
  530. //  Purpose:
  531. //       Return logical file size.  We assume that only this object
  532. //       has changed the size of the file.  The size returned includes
  533. //       bytes in the buffer not yet flushed to the file.
  534. //
  535. ULONG32
  536. HXBufferedDataFile::LogicalSize()
  537. {
  538. // If the flushed size is <= the
  539. // beginning of the current buffer,
  540. // we have extended the file, but
  541. // have not flushed it.
  542.     ULONG32 size = FlushSize();
  543.     if (size <= m_Begin)
  544.     {
  545. size = m_Begin + m_BufFill;
  546.     }
  547.     return size;
  548. }
  549. /////////////////////////////////////////////////////////////////////////
  550. //
  551. // Method:
  552. //     HXBufferedDataFile::NewBuf:
  553. //  Purpose:
  554. //      Utility method.
  555. //      Request an new i/o buffer.  If the file is open for writing,
  556. //      the buffer is flushed if marked dirty.  If the file is open
  557. //      for reading a new buffer containing the current seek offset is
  558. //      read in from the file.  Note for files open for writing, the
  559. //      current buffer is flushed, before the new buffer is read in.
  560. //      Returns vales:
  561. //
  562. //         1       Buffer was successfully refreshed.
  563. //         0       If file is open for reading, cureent seek offset
  564. //                 is at or beyond EOF.
  565. //        -1       Error occured during flushing or filling.
  566. //
  567. INT32 HXBufferedDataFile::NewBuf()
  568. {
  569.     int status = 1;
  570. // if writing flush the current buffer 
  571.     if (m_Flags & HX_FILEFLAG_WRITE)
  572.     {
  573. status = FlushBuf();
  574.     }
  575. // fill buffer from file
  576.     if (status > 0)
  577.     {
  578. status = FillBuf();
  579.     }
  580.     return status;
  581. }
  582. /////////////////////////////////////////////////////////////////////////
  583. //
  584. // Method:
  585. //     HXBufferedDataFile::FillBuf:
  586. //
  587. // Purpose   
  588. //      Utility method:
  589. //      Fill buffer with file contents at current offset.
  590. //      Returns:
  591. //         1   Buffer filled.  If End of Buffer is beyond EOF,
  592. //             buffer is partially filled.  m_BufFill is set
  593. //             to how much of buffer is filled.
  594. //         0   End of File
  595. //        -1   Read or seek error, or file not open
  596. //
  597. INT32
  598. HXBufferedDataFile::FillBuf()
  599. {
  600.     int status = -1;
  601.     m_LastError = 0;
  602.     if (m_Fd >= 0)
  603.     {
  604. // Get beginning of buffer on a
  605. // m_BufSize boundry.  If the beginning
  606. // of the buffer is less then the current
  607. // flushed file size, seek and read it in.
  608. m_Begin = (m_Offset/m_BufSize)*m_BufSize;
  609. m_BufFill = 0;
  610. if (m_Begin < FlushSize())
  611. {
  612.     INT32 rval = -1;
  613.     m_BufFill = 0;
  614.     if ((rval = Pread((void*) m_pBuf, m_BufSize, m_Begin)) > 0)
  615.     {
  616. m_BufFill = rval;
  617. status = 1;
  618.     }
  619.     else if (rval < 0) // lseek or read error
  620.     {
  621. m_LastError = errno;
  622. status = -1;
  623.     }
  624.     else // EOF: zero buffer
  625.     {
  626. ::memset((void*) m_pBuf, 0, m_BufSize);
  627. status = 0;
  628.     }
  629. }
  630. else // m_Begin is beyond EOF: zero buffer
  631. {
  632.     ::memset((void*) m_pBuf, 0, m_BufSize);
  633.     status = 0;
  634. }
  635.     }
  636.     return status;
  637. }
  638. /////////////////////////////////////////////////////////////////////////
  639. //
  640. // Method:
  641. //     HXBufferedDataFile::FlushBuf:
  642. // Purpose:
  643. //    Utility method:
  644. //    If file is open for writing and the current i/o buffer is dirty,
  645. //    write the contents to the file.
  646. //    Returns:
  647. //         1   Buffer Flushed.
  648. //        -1   Read or seek error, or file not open or read only.
  649. //
  650. INT32
  651. HXBufferedDataFile::FlushBuf()
  652. {
  653.     int status = -1;
  654.     m_LastError = 0;
  655.     if (m_Fd >= 0 && (m_Flags & HX_FILEFLAG_WRITE))
  656.     {
  657. // buffer has been scribbled on.
  658. if (m_Dirty && m_BufFill > 0)
  659. {
  660.     int rval = -1;
  661.     if ((rval = Pwrite((const void*) m_pBuf, m_BufFill, m_Begin)) > 0)
  662.     {
  663. status = 1;
  664. m_Dirty = 0;
  665.     }
  666.     else
  667.     {
  668. status = -1;
  669. m_LastError = errno;
  670.     }
  671. }
  672. else // already flushed.
  673.     status = 1;
  674.     }
  675.     return status;
  676. }
  677. /////////////////////////////////////////////////////////////////////////
  678. //
  679. // Method:
  680. //     HXBufferedDataFile::AllocBuf:
  681. // Purpose:
  682. //     Allocate  the i/o buffer off of heap.
  683. //
  684. void
  685. HXBufferedDataFile::AllocBuf()
  686. {
  687.     if (m_pBuf == 0)
  688.     {
  689. m_pBuf = new char[m_BufSize];
  690.     }
  691. }
  692. /////////////////////////////////////////////////////////////////////////
  693. //
  694. // Method:
  695. //     HXBufferedDataFile::FreeBuf:
  696. //  Purpose:
  697. //     Free the i/o buffer.
  698. //
  699. void
  700. HXBufferedDataFile::FreeBuf()
  701. {
  702.     delete [] m_pBuf;
  703.     m_pBuf = 0;
  704.     m_BufFill = 0;
  705.     m_Begin = 0;
  706. }
  707. /////////////////////////////////////////////////////////////////////////
  708. //
  709. // Method:
  710. //     HXBufferedDataFile::Pread:
  711. // Purpose:
  712. //     Read data at requrested position.
  713. //     Number of bytes read is returned 0 if at EOF, or -1 on error
  714. //
  715. INT32
  716. HXBufferedDataFile::Pread(void* buf, INT32 nbytes, ULONG32 offset)
  717. {
  718.     //INT32 nread = -1;
  719. OpFsSize nread = kOpFsErrAny;
  720.     m_LastError = 0;
  721.     if (m_Fd >= 0)
  722.     {
  723. if (m_FileOffset == offset ||
  724.    // ::lseek(m_Fd, offset, SEEK_SET) != -1)
  725.    OpFsSeek( m_Fd, (OpFsSize)offset, SEEK_SET) != kOpFsErrAny)
  726. {
  727.     m_FileOffset = offset;
  728.     //if ((nread = ::read(m_Fd, buf, nbytes)) > 0)
  729. if ((nread = OpFsRead( m_Fd, buf, nbytes)) != kOpFsErrAny)
  730. m_FileOffset += nread;
  731.     else if (nread < 0)
  732. m_LastError = errno;
  733. }
  734.     }
  735.     return nread;
  736. }
  737. /////////////////////////////////////////////////////////////////////////
  738. //
  739. // Method:
  740. //     HXBufferedDataFile::Pwrite:
  741. // Purpose:
  742. //     Write data at requrested position.
  743. //     Number of bytes read is returned, or -1 on error
  744. //
  745. INT32
  746. HXBufferedDataFile::Pwrite(const void* buf, INT32 nbytes, ULONG32 offset)
  747. {
  748.     //INT32 nwrite = -1;
  749. OpFsSize nwrite = kOpFsErrAny;
  750.     m_LastError = 0;
  751.     if (m_Fd >= 0)
  752.     {
  753. if (m_FileOffset == offset ||
  754.     //::lseek(m_Fd, offset, SEEK_SET) != -1)
  755. OpFsSeek( m_Fd, (OpFsSize)offset, SEEK_SET) != kOpFsErrAny)
  756. {
  757.     m_FileOffset = offset;
  758.     //if ((nwrite = ::write(m_Fd, buf, nbytes)) > 0)
  759. if (( nwrite = OpFsWrite( m_Fd, buf, nbytes)) != kOpFsErrAny)
  760.     {
  761. m_FileOffset += nwrite;
  762. if (m_FileOffset > m_FlushSize)
  763. m_FlushSize = m_FileOffset;
  764.     }
  765.     else
  766. m_LastError = errno;
  767. }
  768.     }
  769.     return nwrite;
  770. }
  771. /////////////////////////////////////////////////////////////////////////
  772. //
  773. // Method:
  774. //     HXBufferedDataFile::GetFileStat
  775. //  Purpose
  776. //   Get file stat. If all is of HXR_OK is returned otherwise HXR_FAIL
  777. //
  778. INT32
  779. HXBufferedDataFile::GetFileStat(struct stat* st) const
  780. {
  781.     INT32 status = HXR_FAIL;
  782.     if ((m_Fd >= 0 && ::fstat(m_Fd, st) == 0) ||
  783. (m_pFileName->GetSize() &&
  784.  ::stat((const char*) m_pFileName->GetBuffer(), st) == 0))
  785.     {
  786. status = HXR_OK;
  787.     }
  788. // cast to get around const
  789.     ((HXBufferedDataFile*) this)->m_LastError = status == HXR_OK ? 0 : errno;
  790.     return status;
  791. }
  792. /////////////////////////////////////////////////////////////////////////
  793. //
  794. // Method:
  795. //     HXBufferedDataFile::GetPageSize:
  796. // Purpose:
  797. //    Get the system page size.
  798. INT32
  799. HXBufferedDataFile::GetPageSize() const
  800. {
  801. #if defined(_FREEBSD)
  802.     return getpagesize();
  803. #else
  804.     //return ::sysconf(_SC_PAGE_SIZE);
  805. return 0;  // On Openwave platform, pages service not available
  806. #endif
  807. }