pchannel.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:19k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. /*
  2.  * pchannel.cxx
  3.  *
  4.  * Operating System utilities.
  5.  *
  6.  * Portable Windows Library
  7.  *
  8.  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
  9.  *
  10.  * The contents of this file are subject to the Mozilla Public License
  11.  * Version 1.0 (the "License"); you may not use this file except in
  12.  * compliance with the License. You may obtain a copy of the License at
  13.  * http://www.mozilla.org/MPL/
  14.  *
  15.  * Software distributed under the License is distributed on an "AS IS"
  16.  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  17.  * the License for the specific language governing rights and limitations
  18.  * under the License.
  19.  *
  20.  * The Original Code is Portable Windows Library.
  21.  *
  22.  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
  23.  *
  24.  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
  25.  * All Rights Reserved.
  26.  *
  27.  * Contributor(s): ______________________________________.
  28.  *
  29.  * $Log: pchannel.cxx,v $
  30.  * Revision 1.7  2000/06/26 11:17:20  robertj
  31.  * Nucleus++ port (incomplete).
  32.  *
  33.  * Revision 1.6  1999/07/06 08:55:05  robertj
  34.  * Fixed bug in PFile::Copy, does not write last chunk of data to new file.
  35.  *
  36.  * Revision 1.5  1999/06/17 14:44:42  robertj
  37.  * Fixed incorrect comparison of open write channel
  38.  *
  39.  * Revision 1.4  1999/06/17 13:38:11  robertj
  40.  * Fixed race condition on indirect channel close, mutex needed in PIndirectChannel.
  41.  *
  42.  * Revision 1.3  1999/02/22 10:10:12  robertj
  43.  * Changed channel output flush to remove double Write() call.
  44.  *
  45.  * Revision 1.2  1999/01/31 00:57:18  robertj
  46.  * Fixed bug when opening an already open file, should close it!
  47.  *
  48.  * Revision 1.1  1998/11/30 12:46:19  robertj
  49.  * Initial revision
  50.  *
  51.  */
  52. #include <ptlib.h>
  53. #include <ctype.h>
  54. ///////////////////////////////////////////////////////////////////////////////
  55. // PChannel
  56. PChannelStreamBuffer::PChannelStreamBuffer(PChannel * chan)
  57.   : channel(PAssertNULL(chan))
  58. {
  59. }
  60. int PChannelStreamBuffer::overflow(int c)
  61. {
  62.   if (pbase() == NULL) {
  63.     if (eback() == 0)
  64.       setp(buffer, &buffer[sizeof(buffer)]);
  65.     else {
  66.       char * halfway = &buffer[sizeof(buffer)/2];
  67.       setp(buffer, halfway);
  68.       setg(halfway, &buffer[sizeof(buffer)], &buffer[sizeof(buffer)]);
  69.     }
  70.   }
  71.   int bufSize = pptr() - pbase();
  72.   if (bufSize > 0) {
  73.     setp(pbase(), epptr());
  74.     if (!channel->Write(pbase(), bufSize))
  75.       return EOF;
  76.   }
  77.   if (c != EOF) {
  78.     *pptr() = (char)c;
  79.     pbump(1);
  80.   }
  81.   return 0;
  82. }
  83. int PChannelStreamBuffer::underflow()
  84. {
  85.   if (eback() == NULL) {
  86.     if (pbase() == 0)
  87.       setg(buffer, &buffer[sizeof(buffer)], &buffer[sizeof(buffer)]);
  88.     else {
  89.       char * halfway = &buffer[sizeof(buffer)/2];
  90.       setp(buffer, halfway);
  91.       setg(halfway, &buffer[sizeof(buffer)], &buffer[sizeof(buffer)]);
  92.     }
  93.   }
  94.   if (gptr() != egptr())
  95.     return (BYTE)*gptr();
  96.   if (!channel->Read(eback(), egptr() - eback()) ||
  97.                                   channel->GetErrorCode() != PChannel::NoError)
  98.     return EOF;
  99.   PINDEX count = channel->GetLastReadCount();
  100.   char * p = egptr() - count;
  101.   memmove(p, eback(), count);
  102.   setg(eback(), p, egptr());
  103.   return (BYTE)*p;
  104. }
  105. int PChannelStreamBuffer::sync()
  106. {
  107.   int inAvail = egptr() - gptr();
  108.   if (inAvail > 0) {
  109.     setg(eback(), egptr(), egptr());
  110.     if (channel->IsDescendant(PFile::Class()))
  111.       ((PFile *)channel)->SetPosition(-inAvail, PFile::Current);
  112.   }
  113.   if (pptr() > pbase())
  114.     return overflow();
  115.   return 0;
  116. }
  117. streampos PChannelStreamBuffer::seekoff(streamoff off,
  118. #ifdef __MWERKS__
  119.                                         ios::seekdir dir, ios::openmode)
  120. #else
  121.                                         ios::seek_dir dir, int)
  122. #endif
  123. {
  124.   sync();
  125.   if (!channel->IsDescendant(PFile::Class()))
  126.     return -1;
  127.   ((PFile *)channel)->SetPosition(off, (PFile::FilePositionOrigin)dir);
  128.   return ((PFile *)channel)->GetPosition();
  129. }
  130. PChannel::PChannel()
  131.   : readTimeout(PMaxTimeInterval), writeTimeout(PMaxTimeInterval)
  132. {
  133.   os_handle = -1;
  134.   osError = 0;
  135.   lastError = NoError;
  136.   lastReadCount = lastWriteCount = 0;
  137.   init(new PChannelStreamBuffer(this));
  138.   Construct();
  139. }
  140. PChannel::~PChannel()
  141. {
  142.   flush();
  143.   Close();
  144.   delete (PChannelStreamBuffer *)rdbuf();
  145.   init(NULL);
  146. }
  147. BOOL PChannel::IsOpen() const
  148. {
  149.   return os_handle >= 0;
  150. }
  151. int PChannel::ReadChar()
  152. {
  153.   BYTE c;
  154.   BOOL retVal = Read(&c, 1);
  155.   return (retVal && lastReadCount == 1) ? c : -1;
  156. }
  157. int PChannel::ReadCharWithTimeout(PTimeInterval & timeout)
  158. {
  159.   SetReadTimeout(timeout);
  160.   PTimeInterval startTick = PTimer::Tick();
  161.   int c;
  162.   if ((c = ReadChar()) < 0) // Timeout or aborted
  163.     return -1;
  164.   timeout -= PTimer::Tick() - startTick;
  165.   return c;
  166. }
  167. BOOL PChannel::ReadBlock(void * buf, PINDEX len)
  168. {
  169.   char * ptr = (char *)buf;
  170.   PINDEX numRead = 0;
  171.   while (numRead < len && Read(ptr+numRead, len - numRead))
  172.     numRead += lastReadCount;
  173.   lastReadCount = numRead;
  174.   return lastReadCount == len;
  175. }
  176. PString PChannel::ReadString(PINDEX len)
  177. {
  178.   PString str;
  179.   ReadBlock(str.GetPointer(len+1), len);
  180.   str.SetSize(lastReadCount+1);
  181.   return str;
  182. }
  183. BOOL PChannel::WriteString(const PString & str)
  184. {
  185.   const char * ptr = str;
  186.   PINDEX len = 0, slen = str.GetLength();
  187.   while (len < slen && Write(ptr+len, slen - len))
  188.     len += lastWriteCount;
  189.   return len == slen;
  190. }
  191. BOOL PChannel::ReadAsync(void * buf, PINDEX len)
  192. {
  193.   BOOL retVal = Read(buf, len);
  194.   OnReadComplete(buf, lastReadCount);
  195.   return retVal;
  196. }
  197. void PChannel::OnReadComplete(void *, PINDEX)
  198. {
  199. }
  200. BOOL PChannel::WriteChar(int c)
  201. {
  202.   PAssert(c >= 0 && c < 256, PInvalidParameter);
  203.   char buf = (char)c;
  204.   return Write(&buf, 1);
  205. }
  206. BOOL PChannel::WriteAsync(const void * buf, PINDEX len)
  207. {
  208.   BOOL retVal = Write(buf, len);
  209.   OnWriteComplete(buf, lastWriteCount);
  210.   return retVal;
  211. }
  212. void PChannel::OnWriteComplete(const void *, PINDEX)
  213. {
  214. }
  215. enum {
  216.   NextCharEndOfString = -1,
  217.   NextCharDelay = -2,
  218.   NextCharSend = -3,
  219.   NextCharWait = -4
  220. };
  221. static int HexDigit(char c)
  222. {
  223.   if (!isxdigit(c))
  224.     return 0;
  225.   int hex = c - '0';
  226.   if (hex < 10)
  227.     return hex;
  228.   hex -= 'A' - '9' - 1;
  229.   if (hex < 16)
  230.     return hex;
  231.   return hex - ('a' - 'A');
  232. }
  233. static int GetNextChar(const PString & command,
  234.                                     PINDEX & pos, PTimeInterval * time = NULL)
  235. {
  236.   int temp;
  237.   if (command[pos] == '')
  238.     return NextCharEndOfString;
  239.   if (command[pos] != '\')
  240.     return command[pos++];
  241.   switch (command[++pos]) {
  242.     case '' :
  243.       return NextCharEndOfString;
  244.     case 'a' : // alert (ascii value 7)
  245.       pos++;
  246.       return 7;
  247.     case 'b' : // backspace (ascii value 8)
  248.       pos++;
  249.       return 8;
  250.     case 'f' : // formfeed (ascii value 12)
  251.       pos++;
  252.       return 12;
  253.     case 'n' : // newline (ascii value 10)
  254.       pos++;
  255.       return 10;
  256.     case 'r' : // return (ascii value 13)
  257.       pos++;
  258.       return 13;
  259.     case 't' : // horizontal tab (ascii value 9)
  260.       pos++;
  261.       return 9;
  262.     case 'v' : // vertical tab (ascii value 11)
  263.       pos++;
  264.       return 11;
  265.     case 'x' : // followed by hh  where nn is hex number (ascii value 0xhh)
  266.       if (isxdigit(command[++pos])) {
  267.         temp = HexDigit(command[pos++]);
  268.         if (isxdigit(command[pos]))
  269.           temp += HexDigit(command[pos++]);
  270.         return temp;
  271.       }
  272.       return command[pos];
  273.     case 's' :
  274.       pos++;
  275.       return NextCharSend;
  276.     case 'd' : // ns  delay for n seconds/milliseconds
  277.     case 'w' :
  278.       temp = command[pos] == 'd' ? NextCharDelay : NextCharWait;
  279.       long milliseconds = 0;
  280.       while (isdigit(command[++pos]))
  281.         milliseconds = milliseconds*10 + command[pos] - '0';
  282.       if (milliseconds <= 0)
  283.         milliseconds = 1;
  284.       if (command[pos] == 'm')
  285.         pos++;
  286.       else {
  287.         milliseconds *= 1000;
  288.         if (command[pos] == 's')
  289.           pos++;
  290.       }
  291.       if (time != NULL)
  292.         *time = milliseconds;
  293.       return temp;
  294.   }
  295.   if (command[pos] < '0' || command[pos] > '7')
  296.     return command[pos++];
  297.   // octal number
  298.   temp = command[pos++] - '0';
  299.   if (command[pos] < '0' || command[pos] > '7')
  300.     return temp;
  301.   temp += command[pos++] - '0';
  302.   if (command[pos] < '0' || command[pos] > '7')
  303.     return temp;
  304.   temp += command[pos++] - '0';
  305.   return temp;
  306. }
  307. BOOL PChannel::ReceiveCommandString(int nextChar,
  308.                             const PString & reply, PINDEX & pos, PINDEX start)
  309. {
  310.   if (nextChar != GetNextChar(reply, pos)) {
  311.     pos = start;
  312.     return FALSE;
  313.   }
  314.   PINDEX dummyPos = pos;
  315.   return GetNextChar(reply, dummyPos) < 0;
  316. }
  317. BOOL PChannel::SendCommandString(const PString & command)
  318. {
  319.   abortCommandString = FALSE;
  320.   int nextChar;
  321.   PINDEX sendPosition = 0;
  322.   PTimeInterval timeout;
  323.   SetWriteTimeout(10000);
  324.   while (!abortCommandString) { // not aborted
  325.     nextChar = GetNextChar(command, sendPosition, &timeout);
  326.     switch (nextChar) {
  327.       default :
  328.         if (!WriteChar(nextChar))
  329.           return FALSE;
  330.         break;
  331.       case NextCharEndOfString :
  332.         return TRUE;  // Success!!
  333.       case NextCharSend :
  334.         break;
  335.       case NextCharDelay : // Delay in send
  336.         PThread::Current()->Sleep(timeout);
  337.         break;
  338.       case NextCharWait : // Wait for reply
  339.         PINDEX receivePosition = sendPosition;
  340.         if (GetNextChar(command, receivePosition) < 0) {
  341.           SetReadTimeout(timeout);
  342.           while (ReadChar() >= 0)
  343.             if (abortCommandString) // aborted
  344.               return FALSE;
  345.         }
  346.         else {
  347.           receivePosition = sendPosition;
  348.           do {
  349.             if (abortCommandString) // aborted
  350.               return FALSE;
  351.             if ((nextChar = ReadCharWithTimeout(timeout)) < 0)
  352.               return FALSE;
  353.           } while (!ReceiveCommandString(nextChar,
  354.                                      command, receivePosition, sendPosition));
  355. //          nextChar = GetNextChar(command, receivePosition);
  356.           sendPosition = receivePosition;
  357.         }
  358.     }
  359.   }
  360.   return FALSE;
  361. }
  362. BOOL PChannel::Shutdown(ShutdownValue)
  363. {
  364.   return FALSE;
  365. }
  366. PChannel * PChannel::GetBaseReadChannel() const
  367. {
  368.   return (PChannel *)this;
  369. }
  370. PChannel * PChannel::GetBaseWriteChannel() const
  371. {
  372.   return (PChannel *)this;
  373. }
  374. ///////////////////////////////////////////////////////////////////////////////
  375. // PIndirectChannel
  376. PIndirectChannel::PIndirectChannel()
  377. {
  378.   readChannel = writeChannel = NULL;
  379.   writeAutoDelete = readAutoDelete = FALSE;
  380. }
  381. PObject::Comparison PIndirectChannel::Compare(const PObject & obj) const
  382. {
  383.   PAssert(obj.IsDescendant(PIndirectChannel::Class()), PInvalidCast);
  384.   const PIndirectChannel & other = (const PIndirectChannel &)obj;
  385.   return readChannel == other.readChannel &&
  386.          writeChannel == other.writeChannel ? EqualTo : GreaterThan;
  387. }
  388. PString PIndirectChannel::GetName() const
  389. {
  390.   ((PIndirectChannel*)this)->channelPointerMutex.StartRead();
  391.   PString name;
  392.   if (readChannel != NULL && readChannel == writeChannel)
  393.     name = readChannel->GetName();
  394.   else {
  395.     name = "R<";
  396.     if (readChannel != NULL)
  397.       name += readChannel->GetName();
  398.     name += "> T<";
  399.     if (writeChannel != NULL)
  400.       name += writeChannel->GetName();
  401.     name += ">";
  402.   }
  403.   ((PIndirectChannel*)this)->channelPointerMutex.EndRead();
  404.   return name;
  405. }
  406. BOOL PIndirectChannel::Close()
  407. {
  408.   BOOL retval = TRUE;
  409.   flush();
  410.   channelPointerMutex.StartRead();
  411.   if (readChannel != NULL)
  412.     retval = readChannel->Close();
  413.   if (readChannel != writeChannel && writeChannel != NULL)
  414.     retval = writeChannel->Close() && retval;
  415.   channelPointerMutex.EndRead();
  416.   channelPointerMutex.StartWrite();
  417.   PChannel * r = readChannel;
  418.   PChannel * w = writeChannel;
  419.   readChannel = NULL;
  420.   writeChannel = NULL;
  421.   if (readAutoDelete)
  422.     delete r;
  423.   if (r != w && writeAutoDelete)
  424.     delete w;
  425.   channelPointerMutex.EndWrite();
  426.   return retval;
  427. }
  428. BOOL PIndirectChannel::IsOpen() const
  429. {
  430.   ((PIndirectChannel*)this)->channelPointerMutex.StartRead();
  431.   BOOL returnValue;
  432.   if (readChannel != NULL && readChannel == writeChannel)
  433.     returnValue = readChannel->IsOpen();
  434.   else {
  435.     returnValue = readChannel != NULL ? readChannel->IsOpen() : FALSE;
  436.     if (writeChannel != NULL)
  437.       returnValue = writeChannel->IsOpen() || returnValue;
  438.   }
  439.   ((PIndirectChannel*)this)->channelPointerMutex.EndRead();
  440.   return returnValue;
  441. }
  442. BOOL PIndirectChannel::Read(void * buf, PINDEX len)
  443. {
  444.   flush();
  445.   channelPointerMutex.StartRead();
  446.   PAssert(readChannel != NULL, "Indirect read though NULL channel");
  447.   BOOL returnValue;
  448.   if (readChannel == NULL)
  449.     returnValue = FALSE;
  450.   else {
  451.     readChannel->SetReadTimeout(readTimeout);
  452.     returnValue = readChannel->Read(buf, len);
  453.     lastError = readChannel->GetErrorCode();
  454.     osError = readChannel->GetErrorNumber();
  455.     lastReadCount = readChannel->GetLastReadCount();
  456.   }
  457.   channelPointerMutex.EndRead();
  458.   return returnValue;
  459. }
  460. BOOL PIndirectChannel::Write(const void * buf, PINDEX len)
  461. {
  462.   flush();
  463.   channelPointerMutex.StartRead();
  464.   PAssert(writeChannel != NULL, "Indirect write though NULL channel");
  465.   BOOL returnValue;
  466.   if (writeChannel == NULL)
  467.     returnValue = FALSE;
  468.   else {
  469.     writeChannel->SetWriteTimeout(writeTimeout);
  470.     returnValue = writeChannel->Write(buf, len);
  471.     lastError = writeChannel->GetErrorCode();
  472.     osError = writeChannel->GetErrorNumber();
  473.     lastWriteCount = writeChannel->GetLastWriteCount();
  474.   }
  475.   channelPointerMutex.EndRead();
  476.   return returnValue;
  477. }
  478. BOOL PIndirectChannel::Shutdown(ShutdownValue value)
  479. {
  480.   channelPointerMutex.StartRead();
  481.   BOOL returnValue;
  482.   if (readChannel != NULL && readChannel == writeChannel)
  483.     returnValue = readChannel->Shutdown(value);
  484.   else {
  485.     returnValue = readChannel != NULL ? readChannel->Shutdown(value) : FALSE;
  486.     if (writeChannel != NULL)
  487.       returnValue = writeChannel->Shutdown(value) || returnValue;
  488.   }
  489.   channelPointerMutex.EndRead();
  490.   return returnValue;
  491. }
  492. BOOL PIndirectChannel::Open(PChannel & channel)
  493. {
  494.   return Open(&channel, FALSE);
  495. }
  496. BOOL PIndirectChannel::Open(PChannel * channel, BOOL autoDelete)
  497. {
  498.   return Open(channel, channel, autoDelete, autoDelete);
  499. }
  500. BOOL PIndirectChannel::Open(PChannel * readChan,
  501.                             PChannel * writeChan,
  502.                             BOOL autoDeleteRead,
  503.                             BOOL autoDeleteWrite)
  504. {
  505.   Close();
  506.   channelPointerMutex.StartWrite();
  507.   readChannel = readChan;
  508.   readAutoDelete = autoDeleteRead;
  509.   writeChannel = writeChan;
  510.   writeAutoDelete = autoDeleteWrite;
  511.   channelPointerMutex.EndWrite();
  512.   return IsOpen() && OnOpen();
  513. }
  514. BOOL PIndirectChannel::OnOpen()
  515. {
  516.   return TRUE;
  517. }
  518. BOOL PIndirectChannel::SetReadChannel(PChannel * channel, BOOL autoDelete)
  519. {
  520.   if (readChannel != NULL) {
  521.     lastError = Miscellaneous;
  522.     osError = EBADF;
  523.     return FALSE;
  524.   }
  525.   channelPointerMutex.StartWrite();
  526.   readChannel = channel;
  527.   readAutoDelete = autoDelete;
  528.   channelPointerMutex.EndWrite();
  529.   return IsOpen();
  530. }
  531. BOOL PIndirectChannel::SetWriteChannel(PChannel * channel, BOOL autoDelete)
  532. {
  533.   if (writeChannel != NULL) {
  534.     lastError = Miscellaneous;
  535.     osError = EBADF;
  536.     return FALSE;
  537.   }
  538.   channelPointerMutex.StartWrite();
  539.   writeChannel = channel;
  540.   writeAutoDelete = autoDelete;
  541.   channelPointerMutex.EndWrite();
  542.   return IsOpen();
  543. }
  544. PChannel * PIndirectChannel::GetBaseReadChannel() const
  545. {
  546.   ((PIndirectChannel*)this)->channelPointerMutex.StartRead();
  547.   PChannel * returnValue = readChannel != NULL ? readChannel->GetBaseReadChannel() : 0;
  548.   ((PIndirectChannel*)this)->channelPointerMutex.EndRead();
  549.   return returnValue;
  550. }
  551. PChannel * PIndirectChannel::GetBaseWriteChannel() const
  552. {
  553.   ((PIndirectChannel*)this)->channelPointerMutex.StartRead();
  554.   PChannel * returnValue = writeChannel != NULL ? writeChannel->GetBaseWriteChannel() : 0;
  555.   ((PIndirectChannel*)this)->channelPointerMutex.EndRead();
  556.   return returnValue;
  557. }
  558. ///////////////////////////////////////////////////////////////////////////////
  559. // PFile
  560. PFile::~PFile()
  561. {
  562.   Close();
  563. }
  564. PObject::Comparison PFile::Compare(const PObject & obj) const
  565. {
  566.   PAssert(obj.IsDescendant(PFile::Class()), PInvalidCast);
  567.   return path.Compare(((const PFile &)obj).path);
  568. }
  569. BOOL PFile::Rename(const PString & newname, BOOL force)
  570. {
  571.   Close();
  572.   if (!ConvertOSError(Rename(path, newname, force) ? 0 : -1))
  573.     return FALSE;
  574.   path = path.GetDirectory() + newname;
  575.   return TRUE;
  576. }
  577. BOOL PFile::Close()
  578. {
  579.   if (os_handle < 0) {
  580.     osError = EBADF;
  581.     lastError = NotOpen;
  582.     return FALSE;
  583.   }
  584.   flush();
  585. #ifdef WOT_NO_FILESYSTEM
  586.   BOOL ok = TRUE;
  587. #else
  588.   BOOL ok = ConvertOSError(_close(os_handle));
  589. #endif
  590.   os_handle = -1;
  591.   if (removeOnClose)
  592.     Remove();
  593.   return ok;
  594. }
  595. BOOL PFile::Read(void * buffer, PINDEX amount)
  596. {
  597.   flush();
  598. #ifdef WOT_NO_FILESYSTEM
  599.   lastReadCount = 0;
  600. #else
  601.   lastReadCount = _read(GetHandle(), buffer, amount);
  602. #endif
  603.   return ConvertOSError(lastReadCount) && lastReadCount > 0;
  604. }
  605. BOOL PFile::Write(const void * buffer, PINDEX amount)
  606. {
  607.   flush();
  608. #ifdef WOT_NO_FILESYSTEM
  609.   lastWriteCount = amount;
  610. #else
  611.   lastWriteCount = _write(GetHandle(), buffer, amount);
  612. #endif
  613.   return ConvertOSError(lastWriteCount) && lastWriteCount >= amount;
  614. }
  615. BOOL PFile::Open(const PFilePath & name, OpenMode  mode, int opts)
  616. {
  617.   Close();
  618.   SetFilePath(name);
  619.   return Open(mode, opts);
  620. }
  621. off_t PFile::GetLength() const
  622. {
  623. #ifdef WOT_NO_FILESYSTEM
  624.   return 0;
  625. #else
  626.   off_t pos = _lseek(GetHandle(), 0, SEEK_CUR);
  627.   off_t len = _lseek(GetHandle(), 0, SEEK_END);
  628.   PAssertOS(_lseek(GetHandle(), pos, SEEK_SET) == pos);
  629.   return len;
  630. #endif
  631. }
  632. BOOL PFile::IsEndOfFile() const
  633. {
  634.   ((PFile *)this)->flush();
  635.   return GetPosition() >= GetLength();
  636. }
  637. BOOL PFile::SetPosition(off_t pos, FilePositionOrigin origin)
  638. {
  639. #ifdef WOT_NO_FILESYSTEM
  640.   return TRUE;
  641. #else
  642.   return _lseek(GetHandle(), pos, origin) == pos;
  643. #endif
  644. }
  645. BOOL PFile::Copy(const PFilePath & oldname, const PFilePath & newname, BOOL force)
  646. {
  647.   PFile oldfile(oldname, ReadOnly);
  648.   if (!oldfile.IsOpen())
  649.     return FALSE;
  650.   PFile newfile(newname,
  651.                    WriteOnly, Create|Truncate|(force ? MustExist : Exclusive));
  652.   if (!newfile.IsOpen())
  653.     return FALSE;
  654.   PCharArray buffer(10000);
  655.   off_t amount = oldfile.GetLength();
  656.   while (amount > 10000) {
  657.     if (!oldfile.Read(buffer.GetPointer(), 10000))
  658.       return FALSE;
  659.     if (!newfile.Write((const char *)buffer, 10000))
  660.       return FALSE;
  661.     amount -= 10000;
  662.   }
  663.   if (!oldfile.Read(buffer.GetPointer(), (int)amount))
  664.     return FALSE;
  665.   if (!newfile.Write((const char *)buffer, (int)amount))
  666.     return FALSE;
  667.   return newfile.Close();
  668. }
  669. // End Of File ///////////////////////////////////////////////////////////////