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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: hxbufdataf.cpp,v 1.8.2.3 2004/07/09 01:44:23 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 <sys/types.h>
  50. #include <sys/stat.h>
  51. #include <unistd.h>
  52. #include <fcntl.h>
  53. #include <errno.h>
  54. #include "hxtypes.h"
  55. #include "hxcom.h"
  56. #include "hxresult.h"
  57. #include "ihxpckts.h"
  58. #include "hxbuffer.h"
  59. #include "debug.h"
  60. #include "hxbufdataf.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. {
  222.     status = HXR_FAIL;
  223.     m_LastError = errno;
  224. }
  225. else // open ok: initialize
  226. {
  227.     if (m_pBuf == 0)
  228. AllocBuf();
  229.     m_Begin = 0;
  230.     m_BufFill = 0;
  231.     m_Offset = 0;
  232.     m_FileOffset = 0;
  233.     m_FlushSize = 0;
  234.     m_LastError = 0;
  235.     m_Dirty = 0;
  236. }
  237.     }
  238.     return status;
  239. }
  240. /////////////////////////////////////////////////////////////////////////
  241. //
  242. // Method:
  243. //     HXBufferedDataFile::Close:
  244. //  Purpose:
  245. //     Flush the file buffer (if open of writing and close the file.
  246. //     Note that file is not closed when there are multiple references
  247. //     to this object.
  248. //
  249. STDMETHODIMP
  250. HXBufferedDataFile::Close()
  251. {
  252.     int status = HXR_OK;
  253.     if (m_Fd >= 0 && m_lRefCount <= 1)
  254.     {
  255. if (m_Flags & HX_FILEFLAG_WRITE)
  256.     FlushBuf();
  257. if (::close(m_Fd) == -1)
  258. {
  259.     status = HXR_FAIL;
  260.     m_LastError = errno;
  261. }
  262. m_Fd = -1;
  263.     }
  264.     return status;
  265. }
  266. /////////////////////////////////////////////////////////////////////////
  267. //
  268. // Method:
  269. //     HXBufferedDataFile::Name
  270. // Purpose:
  271. //     Name returns the currently bound file name in FileName.
  272. //     and returns TRUE, if the a name has been bound.  Otherwise
  273. //     FALSE is returned.
  274. //
  275. STDMETHODIMP_(BOOL)
  276. HXBufferedDataFile::Name(REF(IHXBuffer*) pFileName)
  277. {
  278.     if (m_pFileName && m_pFileName->GetSize())
  279.     {
  280. pFileName = m_pFileName;
  281. pFileName->AddRef();
  282. return TRUE;
  283.     }
  284.     return FALSE;
  285. }
  286. /////////////////////////////////////////////////////////////////////////
  287. //
  288. // Method:
  289. //     HXBufferedDataFile::IsOpen()
  290. // Purpose:
  291. //     IsOpen returns TRUE if file is open.  Otherwise FALSE.
  292. //
  293. BOOL
  294. HXBufferedDataFile::IsOpen()
  295. {
  296.     return (m_Fd >= 0 ? TRUE : FALSE);
  297. }
  298. /////////////////////////////////////////////////////////////////////////
  299. //
  300. // Method
  301. //     HXBufferedDataFile::Seek:
  302. // Purpose:
  303. //     Just move the seek offset according to the value of whense.
  304. //     This only sets the local idea of the current offset, no system
  305. //     level seek is performed.  If seek is ok, the current value of
  306. //     seek offset is returned.  Otherwise -1 is returned.
  307. //
  308. //     XXXBH:  24-Mar-99
  309. //       Note that most of callers expect HXR_OK as return value, not
  310. //       the current offset.  So the above comment is a noop.   Also
  311. //       the offset is passed in as an unsigned, it should be signed to
  312. //       allow seeks in both directions.  Right now we do the ugly cast.
  313. //
  314. STDMETHODIMP
  315. HXBufferedDataFile::Seek(ULONG32 offset, UINT16 whense)
  316. {
  317.     ULONG32 size = 0;
  318.     LONG32 signed_offset = (LONG32) offset;
  319.     if (whense == SEEK_SET && signed_offset >= 0)
  320. m_Offset = signed_offset;
  321.     else if (whense == SEEK_CUR && (LONG32) m_Offset + signed_offset >= 0)
  322. m_Offset += signed_offset;
  323.     else if (whense == SEEK_END &&
  324.      (LONG32) (size = LogicalSize()) + signed_offset >= 0)
  325. m_Offset = size + signed_offset;
  326.     else
  327. return HXR_FAIL;
  328.     return HXR_OK;
  329. }
  330. /////////////////////////////////////////////////////////////////////////
  331. //
  332. // Method:
  333. //     HXBufferedDataFile::Tell()
  334. // Purpose:
  335. //      Tell returns the current (logical) file position in the file
  336. //
  337. STDMETHODIMP_(ULONG32)
  338. HXBufferedDataFile::Tell()
  339. {
  340.     return m_Offset;
  341. }
  342. /////////////////////////////////////////////////////////////////////////
  343. //
  344. // Method:
  345. //     HXBufferedDataFile::Read:
  346. // Purpose
  347. //     Read nbytes into the supplied buffer.  Values returned:
  348. //
  349. //        Actual bytes read.  The smaller of the number bytes requested
  350. //        and  the number of bytes between the current seek offset and the
  351. //        end of file is returned.
  352. //
  353. //        0, if the current seek pointer is at or beyond the end of file.
  354. //      
  355. //        -1, if errors occure.  The LastError() member function returns
  356. //        the errno of the last system request.
  357. //
  358. STDMETHODIMP_(ULONG32)
  359. HXBufferedDataFile::Read(REF(IHXBuffer *) pBuf, ULONG32 count)
  360. {
  361.     if (m_Fd >= 0)
  362.     {
  363. pBuf->AddRef();
  364. ULONG32 nleft = count;
  365. INT32 rval = 0;
  366. unsigned char* buf = pBuf->GetBuffer();
  367. while (nleft > 0)
  368. {
  369. // If we enter this block, m_Offset
  370. // lies within the mapped buffer.
  371.     if (m_Begin <= m_Offset && m_Offset < m_Begin + m_BufFill ||
  372. (m_Offset < FlushSize() && (rval = NewBuf()) > 0))
  373.     {
  374. UINT32 off = m_Offset - m_Begin;  // offset within buffer
  375.  // and how much to copy
  376. UINT32 ncopy = m_Begin + m_BufFill - m_Offset;
  377. if (nleft < ncopy)
  378.     ncopy = nleft;
  379. ::memcpy((void*) buf, (const void*) (m_pBuf+off), ncopy); /* Flawfinder: ignore */
  380. nleft -= ncopy;
  381. m_Offset += ncopy;
  382. buf += ncopy;
  383.     }
  384. // NewBuf() could not make the above
  385. // assertion, true.  m_Offset is either
  386. // at or beyond EOF, or an error occured.
  387.     else
  388. break;
  389. }
  390. pBuf->Release();
  391. return rval >= 0 ? count - nleft : HXR_FAIL;
  392.     }
  393.     return HXR_FAIL;
  394. }
  395. /////////////////////////////////////////////////////////////////////////
  396. //
  397. // Method:
  398. //     HXBufferedDataFile::Write:
  399. // Purpose:
  400. //      Write the requested number of bytes.  The number of bytes
  401. //      written are return.  If errors occur, -1 is returned.  The
  402. //      LastError() member function returns the value of errno from
  403. //      the last system request.
  404. //
  405. STDMETHODIMP_(ULONG32)
  406. HXBufferedDataFile::Write(REF(IHXBuffer *) pBuf)
  407. {
  408.     if (m_Fd >= 0)
  409.     {
  410. pBuf->AddRef();
  411. ULONG32 count = pBuf->GetSize();
  412. ULONG32 nleft = count;
  413. INT32 rval = 0;
  414. const unsigned char* buf = pBuf->GetBuffer();
  415. while (nleft > 0)
  416. {
  417. // If we enter this block, m_Offset
  418. // lies within the current buffer.
  419.     if (m_Begin <= m_Offset && m_Offset < m_Begin + m_BufSize ||
  420. (rval = NewBuf()) >= 0)
  421.     {
  422. UINT32 off = m_Offset - m_Begin;  // offset within buffer
  423.   // and how much to copy
  424. UINT32 ncopy = m_Begin + m_BufSize - m_Offset;
  425. if (nleft < ncopy)
  426.     ncopy = nleft;
  427. ::memcpy((void*) (m_pBuf+off), (const void*) buf, ncopy); /* Flawfinder: ignore */
  428. m_Dirty = 1;
  429. nleft -= ncopy;
  430. m_Offset += ncopy;
  431. buf += ncopy;
  432. // data extend beyond what was read in
  433. if (m_Offset-m_Begin > m_BufFill)
  434.     m_BufFill = m_Offset-m_Begin;
  435.     }
  436. // NewBuf() could not make the above
  437. // assertion, true because an error occured.
  438.     else
  439. break;
  440. }
  441. pBuf->Release();
  442. return rval >= 0 ? count - nleft : HXR_FAIL;
  443.     }
  444.     return HXR_FAIL;
  445. }
  446. /////////////////////////////////////////////////////////////////////////
  447. //
  448. // Method:
  449. //     HXBufferedDataFile::Flush()
  450. // Purpose:
  451. //     Flush out the data in case of buffered I/O
  452. //  
  453. STDMETHODIMP
  454. HXBufferedDataFile::Flush()
  455. {
  456.     if (m_Flags & HX_FILEFLAG_WRITE)
  457. return FlushBuf() > 0 ? HXR_OK : HXR_FAIL;
  458.     return HXR_OK;
  459. }
  460. /////////////////////////////////////////////////////////////////////////
  461. //
  462. // Method:
  463. //     HXBufferedDataFile::Stat
  464. // Purpose:
  465. //     Return info about the data file such as permissions, time of
  466. //     creation size in bytes, etc.  Note that if this method is
  467. //     called with unflushed extensions to the file, the st_size field
  468. //     will not be correct.  We could Flush before filling in the stat
  469. //     data, but this is a const function.  The other alternative is
  470. //     to set the st.st_size field to the value returned by
  471. //     LogicalSize() (which includes unflushed extensions to the
  472. //     file).
  473. //
  474. STDMETHODIMP
  475. HXBufferedDataFile::Stat(struct stat* buf)
  476. {
  477.     return GetFileStat(buf);
  478. }
  479. STDMETHODIMP_(INT16)
  480. HXBufferedDataFile::GetFd()
  481. {   
  482.     return m_Fd;
  483. }
  484. /////////////////////////////////////////////////////////////////////////
  485. //
  486. // Method:
  487. //     HXBufferedDataFile::GetLastError:
  488. // Purpose:
  489. //     Returns the value of errno from the last system request.
  490. //
  491. STDMETHODIMP
  492. HXBufferedDataFile::GetLastError()
  493. {
  494.     return m_LastError;
  495. }
  496. STDMETHODIMP_(void) 
  497. HXBufferedDataFile::GetLastError(REF(IHXBuffer*) err)
  498. {
  499.     char* str = ::strerror(m_LastError);
  500.     err = new CHXBuffer;
  501.     err->Set((BYTE*) str, ::strlen(str)+1);
  502.     err->AddRef();
  503. }
  504. /////////////////////////////////////////////////////////////////////////
  505. //
  506. //  Method:
  507. //      HXBufferedDataFile::FlushSize():
  508. //  Purpose:
  509. //       Return flushed file size.  We assume that only this object
  510. //       has changed the size of the file.  The size returned does NOT
  511. //       include bytes in the buffer not yet flushed to the file.
  512. //
  513. ULONG32
  514. HXBufferedDataFile::FlushSize()
  515. {
  516.     if (m_FlushSize == 0)
  517.     {
  518. struct stat st;
  519. if (GetFileStat(&st) == HXR_OK)
  520.     m_FlushSize = st.st_size;
  521.     }
  522.     return m_FlushSize;
  523. }
  524. /////////////////////////////////////////////////////////////////////////
  525. //
  526. //  Method:
  527. //      HXBufferedDataFile::LogicalSize():
  528. //  Purpose:
  529. //       Return logical file size.  We assume that only this object
  530. //       has changed the size of the file.  The size returned includes
  531. //       bytes in the buffer not yet flushed to the file.
  532. //
  533. ULONG32
  534. HXBufferedDataFile::LogicalSize()
  535. {
  536. // If the flushed size is <= the
  537. // beginning of the current buffer,
  538. // we have extended the file, but
  539. // have not flushed it.
  540.     ULONG32 size = FlushSize();
  541.     if (size <= m_Begin)
  542.     {
  543. size = m_Begin + m_BufFill;
  544.     }
  545.     return size;
  546. }
  547. /////////////////////////////////////////////////////////////////////////
  548. //
  549. // Method:
  550. //     HXBufferedDataFile::NewBuf:
  551. //  Purpose:
  552. //      Utility method.
  553. //      Request an new i/o buffer.  If the file is open for writing,
  554. //      the buffer is flushed if marked dirty.  If the file is open
  555. //      for reading a new buffer containing the current seek offset is
  556. //      read in from the file.  Note for files open for writing, the
  557. //      current buffer is flushed, before the new buffer is read in.
  558. //      Returns vales:
  559. //
  560. //         1       Buffer was successfully refreshed.
  561. //         0       If file is open for reading, cureent seek offset
  562. //                 is at or beyond EOF.
  563. //        -1       Error occured during flushing or filling.
  564. //
  565. INT32 HXBufferedDataFile::NewBuf()
  566. {
  567.     int status = 1;
  568. // if writing flush the current buffer 
  569.     if (m_Flags & HX_FILEFLAG_WRITE)
  570.     {
  571. status = FlushBuf();
  572.     }
  573. // fill buffer from file
  574.     if (status > 0)
  575.     {
  576. status = FillBuf();
  577.     }
  578.     return status;
  579. }
  580. /////////////////////////////////////////////////////////////////////////
  581. //
  582. // Method:
  583. //     HXBufferedDataFile::FillBuf:
  584. //
  585. // Purpose   
  586. //      Utility method:
  587. //      Fill buffer with file contents at current offset.
  588. //      Returns:
  589. //         1   Buffer filled.  If End of Buffer is beyond EOF,
  590. //             buffer is partially filled.  m_BufFill is set
  591. //             to how much of buffer is filled.
  592. //         0   End of File
  593. //        -1   Read or seek error, or file not open
  594. //
  595. INT32
  596. HXBufferedDataFile::FillBuf()
  597. {
  598.     int status = -1;
  599.     m_LastError = 0;
  600.     if (m_Fd >= 0)
  601.     {
  602. // Get beginning of buffer on a
  603. // m_BufSize boundry.  If the beginning
  604. // of the buffer is less then the current
  605. // flushed file size, seek and read it in.
  606. m_Begin = (m_Offset/m_BufSize)*m_BufSize;
  607. m_BufFill = 0;
  608. if (m_Begin < FlushSize())
  609. {
  610.     INT32 rval = -1;
  611.     m_BufFill = 0;
  612.     if ((rval = Pread((void*) m_pBuf, m_BufSize, m_Begin)) > 0)
  613.     {
  614. m_BufFill = rval;
  615. status = 1;
  616.     }
  617.     else if (rval < 0) // lseek or read error
  618.     {
  619. m_LastError = errno;
  620. status = -1;
  621.     }
  622.     else // EOF: zero buffer
  623.     {
  624. ::memset((void*) m_pBuf, 0, m_BufSize);
  625. status = 0;
  626.     }
  627. }
  628. else // m_Begin is beyond EOF: zero buffer
  629. {
  630.     ::memset((void*) m_pBuf, 0, m_BufSize);
  631.     status = 0;
  632. }
  633.     }
  634.     return status;
  635. }
  636. /////////////////////////////////////////////////////////////////////////
  637. //
  638. // Method:
  639. //     HXBufferedDataFile::FlushBuf:
  640. // Purpose:
  641. //    Utility method:
  642. //    If file is open for writing and the current i/o buffer is dirty,
  643. //    write the contents to the file.
  644. //    Returns:
  645. //         1   Buffer Flushed.
  646. //        -1   Read or seek error, or file not open or read only.
  647. //
  648. INT32
  649. HXBufferedDataFile::FlushBuf()
  650. {
  651.     int status = -1;
  652.     m_LastError = 0;
  653.     if (m_Fd >= 0 && (m_Flags & HX_FILEFLAG_WRITE))
  654.     {
  655. // buffer has been scribbled on.
  656. if (m_Dirty && m_BufFill > 0)
  657. {
  658.     int rval = -1;
  659.     if ((rval = Pwrite((const void*) m_pBuf, m_BufFill, m_Begin)) > 0)
  660.     {
  661. status = 1;
  662. m_Dirty = 0;
  663.     }
  664.     else
  665.     {
  666. status = -1;
  667. m_LastError = errno;
  668.     }
  669. }
  670. else // already flushed.
  671.     status = 1;
  672.     }
  673.     return status;
  674. }
  675. /////////////////////////////////////////////////////////////////////////
  676. //
  677. // Method:
  678. //     HXBufferedDataFile::AllocBuf:
  679. // Purpose:
  680. //     Allocate  the i/o buffer off of heap.
  681. //
  682. void
  683. HXBufferedDataFile::AllocBuf()
  684. {
  685.     if (m_pBuf == 0)
  686.     {
  687. m_pBuf = new char[m_BufSize];
  688.     }
  689. }
  690. /////////////////////////////////////////////////////////////////////////
  691. //
  692. // Method:
  693. //     HXBufferedDataFile::FreeBuf:
  694. //  Purpose:
  695. //     Free the i/o buffer.
  696. //
  697. void
  698. HXBufferedDataFile::FreeBuf()
  699. {
  700.     delete [] m_pBuf;
  701.     m_pBuf = 0;
  702.     m_BufFill = 0;
  703.     m_Begin = 0;
  704. }
  705. /////////////////////////////////////////////////////////////////////////
  706. //
  707. // Method:
  708. //     HXBufferedDataFile::Pread:
  709. // Purpose:
  710. //     Read data at requrested position.
  711. //     Number of bytes read is returned 0 if at EOF, or -1 on error
  712. //
  713. INT32
  714. HXBufferedDataFile::Pread(void* buf, INT32 nbytes, ULONG32 offset)
  715. {
  716.     INT32 nread = -1;
  717.     m_LastError = 0;
  718.     if (m_Fd >= 0)
  719.     {
  720. if (m_FileOffset == offset ||
  721.     ::lseek(m_Fd, offset, SEEK_SET) != -1)
  722. {
  723.     m_FileOffset = offset;
  724.     if ((nread = ::read(m_Fd, buf, nbytes)) > 0)
  725. m_FileOffset += nread;
  726.     else if (nread < 0)
  727. m_LastError = errno;
  728. }
  729.     }
  730.     return nread;
  731. }
  732. /////////////////////////////////////////////////////////////////////////
  733. //
  734. // Method:
  735. //     HXBufferedDataFile::Pwrite:
  736. // Purpose:
  737. //     Write data at requrested position.
  738. //     Number of bytes read is returned, or -1 on error
  739. //
  740. INT32
  741. HXBufferedDataFile::Pwrite(const void* buf, INT32 nbytes, ULONG32 offset)
  742. {
  743.     INT32 nwrite = -1;
  744.     m_LastError = 0;
  745.     if (m_Fd >= 0)
  746.     {
  747. if (m_FileOffset == offset ||
  748.     ::lseek(m_Fd, offset, SEEK_SET) != -1)
  749. {
  750.     m_FileOffset = offset;
  751.     if ((nwrite = ::write(m_Fd, buf, nbytes)) > 0)
  752.     {
  753. m_FileOffset += nwrite;
  754. if (m_FileOffset > m_FlushSize)
  755.     m_FlushSize = m_FileOffset;
  756.     }
  757.     else
  758. m_LastError = errno;
  759. }
  760.     }
  761.     return nwrite;
  762. }
  763. /////////////////////////////////////////////////////////////////////////
  764. //
  765. // Method:
  766. //     HXBufferedDataFile::GetFileStat
  767. //  Purpose
  768. //   Get file stat. If all is of HXR_OK is returned otherwise HXR_FAIL
  769. //
  770. INT32
  771. HXBufferedDataFile::GetFileStat(struct stat* st) const
  772. {
  773.     INT32 status = HXR_FAIL;
  774.     if ((m_Fd >= 0 && ::fstat(m_Fd, st) == 0) ||
  775. (m_pFileName->GetSize() &&
  776.  ::stat((const char*) m_pFileName->GetBuffer(), st) == 0))
  777.     {
  778. status = HXR_OK;
  779.     }
  780. // cast to get around const
  781.     ((HXBufferedDataFile*) this)->m_LastError = status == HXR_OK ? 0 : errno;
  782.     return status;
  783. }
  784. /////////////////////////////////////////////////////////////////////////
  785. //
  786. // Method:
  787. //     HXBufferedDataFile::GetPageSize:
  788. // Purpose:
  789. //    Get the system page size.
  790. INT32
  791. HXBufferedDataFile::GetPageSize() const
  792. {
  793. #if defined(_FREEBSD) || defined(_OPENBSD) || defined(_NETBSD) || defined(_MAC_UNIX)
  794.     return getpagesize();
  795. #else
  796. #if defined(_SC_PAGE_SIZE)
  797.     return ::sysconf(_SC_PAGE_SIZE);
  798. #else
  799.     return ::sysconf(_SC_PAGESIZE);
  800. #endif
  801. #endif
  802. }