hxbufdataf.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:22k
源码类别:

Symbian

开发平台:

C/C++

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