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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: cmacfile_carbon.cpp,v 1.5.32.3 2004/07/09 01:44:13 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 <fcntl.h>
  50. #include "CMacFile.h"
  51. #include "MoreFilesX.h"
  52. #include "filespecutils.h"
  53. #include "hx_moreprocesses.h"
  54. #include "hxstrutl.h"
  55. OSType CMacFile::sCreator = 'PNst';
  56. OSType CMacFile::sFileType  = 'PNRA';
  57. BOOL gReadDone = FALSE;
  58. ULONG32 gReadCount = 0;
  59. // async callback proc
  60. pascal void ReadCallback(ParamBlockRec* pb);
  61. // async callback UPP
  62. static IOCompletionUPP gReadCallbackUPP=NewIOCompletionUPP(ReadCallback);
  63. CHXDataFile*
  64. CHXDataFile::Construct(UINT32 ulFlags, IUnknown** ppCommonObj)
  65. {
  66.     return (CHXDataFile *) new CMacFile;
  67. }
  68. // CHXFile should set the file reference to a value indicating the file is not open
  69. CMacFile::CMacFile (void)
  70. {
  71. mRefNum = 0;
  72. mLastError = noErr;
  73. mAppendMode = FALSE;
  74. mBufferFile = NULL;
  75. mBufferedRead = FALSE;
  76. mWriteFile = NULL;
  77. mBufferedWrite = FALSE;
  78. m_pseudoFileHandle = NULL; // if non-null, a memory manager handle containing the "file data"
  79. m_pseudoFileOffset = 0; // current "read" position in the pseudo file
  80. m_pseudoFileSize = 0; // total pseudo file size
  81. }
  82. // ~CHXFile should close the file if it is open
  83. CMacFile::~CMacFile(void)
  84. {
  85. Close(); // close file if necessary
  86. }
  87. // Create a file with the specified mode
  88. // Close the previous file if it was open
  89. HX_RESULT CMacFile::Create(const char *filename, UINT16 mode,BOOL textflag)
  90. {
  91. Close(); // close previous file if necessary
  92. CHXFileSpecifier fileSpec(filename);
  93. require_return(fileSpec.IsSet(), HXR_INVALID_PATH);
  94. BOOL bExistsAlready;
  95. OSErr err = noErr;
  96. // if the file already exists, it might be an alias file to somewhere else
  97. // (well, the pre-Carbon code checked for this; I'm not sure why we're resolving
  98. // an alias file if this path already exists)
  99. bExistsAlready = CHXFileSpecUtils::FileExists(fileSpec);
  100. if (bExistsAlready)
  101. {
  102. CHXFileSpecUtils::ResolveFileSpecifierAlias(fileSpec);
  103. bExistsAlready = CHXFileSpecUtils::FileExists(fileSpec);
  104. }
  105. // create the file if it doesn't already exist
  106. FSRef parentRef;
  107. HFSUniStr255 hfsName;
  108. FSRef openFileRef;
  109. parentRef = (FSRef) fileSpec.GetParentDirectory();
  110. hfsName = fileSpec.GetNameHFSUniStr255();
  111. if (!bExistsAlready)
  112. {
  113. FSCatalogInfo catInfo;
  114. FileInfo fInfo;
  115. FSSpec *kDontWantSpec = NULL;
  116. ZeroInit(&fInfo);
  117. fInfo.fileCreator = textflag ? 'ttxt' : sCreator;
  118. fInfo.fileType = textflag ? 'TEXT' : sFileType;
  119. (* (FileInfo *) &catInfo.finderInfo) = fInfo;
  120. err = FSCreateFileUnicode(&parentRef, hfsName.length,
  121. hfsName.unicode, kFSCatInfoFinderInfo, &catInfo,
  122. &openFileRef, kDontWantSpec);
  123. }
  124. else // already existed...
  125. {
  126. openFileRef = (FSRef) fileSpec;
  127. }
  128. // open the file (to mimic Windows' create semantics)
  129. if (err == noErr)
  130. {
  131. HFSUniStr255 dataForkName;
  132. dataForkName.length = 0;
  133. err = FSGetDataForkName(&dataForkName);
  134. check_noerr(err);
  135. err = FSOpenFork(&openFileRef, dataForkName.length, dataForkName.unicode,
  136. fsRdWrPerm, &mRefNum);
  137. }
  138. if (err == noErr)
  139. {
  140. mFile = openFileRef;
  141. err = FSSetForkSize(mRefNum, fsFromStart, 0);
  142. }
  143. mLastError = err;
  144. return (err != noErr ? -1 : 0);
  145. }
  146. // Open a file with the specified permissions
  147. // Close the previous file if it was open
  148. //
  149. // If the file isn't found, look for a 'RLFL' resource *in the current
  150. // resource chain* with the same name as the file.
  151. HX_RESULT CMacFile::Open(const char *filename, UINT16 mode,BOOL textflag)
  152. {
  153. Close(); // close previous file if necessary
  154. CHXFileSpecifier fileSpec(filename);
  155. if (!fileSpec.IsSet()) return HXR_INVALID_PATH; // fails if we're trying to open a file inside a non-existing directory
  156. short perm;
  157. // figure out mac file permission
  158. perm = fsRdPerm;
  159. if (mode & O_WRONLY)
  160. {
  161. perm = fsWrPerm;
  162. }
  163. else if (mode & O_RDONLY)
  164. {
  165. perm = fsRdPerm;
  166. }
  167.         else if (mode & O_RDWR)
  168.         {
  169.                 perm = fsRdWrPerm;
  170.         }
  171. // Store the permissions for this file for later.
  172. m_mode = mode;
  173. BOOL bExistsAlready;
  174. OSErr err = fnfErr;
  175. bExistsAlready = CHXFileSpecUtils::FileExists(fileSpec);
  176. if (bExistsAlready)
  177. {
  178. CHXFileSpecUtils::ResolveFileSpecifierAlias(fileSpec);
  179. bExistsAlready = CHXFileSpecUtils::FileExists(fileSpec);
  180. }
  181. if (!bExistsAlready && ((mode & O_CREAT) || (mode & O_WRONLY)))
  182. {
  183. return Create(filename, mode, textflag);
  184. }
  185. if (bExistsAlready)
  186. {
  187. HFSUniStr255 dataForkName;
  188. FSRef openFileRef;
  189. dataForkName.length = 0;
  190. err = FSGetDataForkName(&dataForkName);
  191. check_noerr(err);
  192. openFileRef = (FSRef) fileSpec;
  193. err = FSOpenFork(&openFileRef, dataForkName.length, dataForkName.unicode,
  194. perm, &mRefNum);
  195. if (err == noErr)
  196. {
  197. mFile = openFileRef;
  198. }
  199. }
  200. if ((err != noErr) && (mode & O_RDONLY))
  201. {
  202. Handle resHandle;
  203. SInt32 resSize;
  204. Str255 pascFileName;
  205. // We couldn't open the file, and the request was read-only
  206. //
  207. // See if there's a pseudo-file resource we can use
  208. //
  209. // We need a handle to the resource so we can read from it, but
  210. // we don't want the whole resource loaded into memory, so we
  211. // set ResLoad to false.
  212. SetResLoad(false);
  213. fileSpec.GetName().MakeStr255(pascFileName);
  214. resHandle = GetNamedResource(kRealFileResource, pascFileName); // 'RLFL'
  215. SetResLoad(true);
  216. if (resHandle)
  217. {
  218. // we have a handle to the resource; determine
  219. // its size and reset our "file pointer"
  220. resSize = GetResourceSizeOnDisk(resHandle);
  221. if (resSize > 0)
  222. {
  223. m_pseudoFileHandle = resHandle;
  224. m_pseudoFileSize = resSize;
  225. m_pseudoFileOffset = 0;
  226. err = noErr;
  227. mRefNum = -1; // signals that we're using a pseudo-file and no actual file is open
  228. }
  229. }
  230. }
  231. if (!m_pseudoFileHandle)
  232. {
  233. if((err == noErr) && (mode & O_CREAT))
  234. {
  235. err = ::SetEOF(mRefNum, 0L);
  236. }
  237. if(err == noErr)
  238. {
  239. mAppendMode = (mode & O_APPEND);
  240. if (mode & O_TRUNC) 
  241. {
  242. err = ::SetEOF(mRefNum, 0L);
  243. }
  244. }
  245. if (err != noErr && mRefNum != 0) 
  246. {
  247. Close();
  248. }
  249. }
  250. mLastError = err;
  251. return(err != noErr ? HXR_DOC_MISSING : 0);
  252. }
  253. // Close the previous file if it was open
  254. HX_RESULT CMacFile::Close(void)
  255. {
  256. OSErr err = noErr;
  257. if (m_pseudoFileHandle)
  258. {
  259. // "close" our pseudo file
  260. //
  261. // We don't need or want to dispose or release our pseudo-
  262. // file handle since it's not using up memory anyway, and
  263. // releasing it would hurt anyone else who happens to be
  264. // reading from it.  The handle will be released 
  265. // automatically when its owning resource file closes.
  266. m_pseudoFileHandle = 0;
  267. m_pseudoFileOffset = 0;
  268. m_pseudoFileSize = 0;
  269. err = noErr;
  270. mRefNum = 0;
  271. }
  272. else if (mRefNum) 
  273. {
  274. if (mBufferFile)
  275. delete mBufferFile;
  276. mBufferFile = NULL;
  277. }
  278. if (mWriteFile) 
  279. {
  280. delete mWriteFile;
  281. mWriteFile = NULL;
  282. }
  283. OSErr tempErr;
  284. FSVolumeRefNum vRefNum;
  285. tempErr = FSGetVRefNum(&mFile, &vRefNum);
  286. // close a real file
  287. err = ::FSCloseFork(mRefNum);
  288. mRefNum = 0;
  289. if (err == noErr && tempErr == noErr) 
  290. {
  291. tempErr = ::FlushVol(nil, vRefNum);
  292. }
  293. }
  294. mLastError = err;
  295. return(err != noErr ? -1 : 0);
  296. }
  297. HX_RESULT CMacFile::Delete (const char *filename)
  298. {
  299. HX_RESULT res;
  300. require_return(!m_pseudoFileHandle, HXR_INVALID_OPERATION);
  301. CHXFileSpecifier fileSpec(filename);
  302. res = CHXFileSpecUtils::RemoveFile(fileSpec);
  303. return SUCCEEDED(res) ? 0 : -1;
  304. }
  305. /* Returns the size of the file in bytes. */
  306. ULONG32 CMacFile::GetSize(void)
  307. {
  308. ULONG32 fileSize = 0;
  309. if (m_pseudoFileHandle)
  310. {
  311. fileSize = m_pseudoFileSize;
  312. }
  313. else if (mRefNum) 
  314. {
  315. OSErr err;
  316. SInt64 forkSize;
  317. err = FSGetForkSize(mRefNum, &forkSize);
  318. if (err == noErr)
  319. {
  320. fileSize = (ULONG32) forkSize;
  321. }
  322. }
  323. else
  324. {
  325. check(!"Cannot get file size because no file is open");
  326. }
  327. return fileSize;
  328.  }
  329. // Rewinds the file position to the start of the file
  330. HX_RESULT CMacFile::Rewind(void)
  331. {
  332. OSErr err;
  333. if (m_pseudoFileHandle)
  334. {
  335. m_pseudoFileOffset = 0;
  336. err = noErr;
  337. }
  338. else
  339. {
  340. err = ::FSSetForkPosition(mRefNum, fsFromStart, 0);
  341. }
  342. mLastError = err;
  343. return(err != noErr ? HXR_INVALID_FILE : HXR_OK);
  344. }
  345. // Seek moves the current file position to the offset from the fromWhere specifier
  346. HX_RESULT CMacFile::Seek(ULONG32 offset, UINT16 fromWhere)
  347. {
  348. OSErr err = noErr;
  349. if (m_pseudoFileHandle)
  350. {
  351. switch(fromWhere)
  352. {
  353. case SEEK_SET:
  354. m_pseudoFileOffset = offset;
  355. break;
  356. case SEEK_CUR:
  357. m_pseudoFileOffset += offset;
  358. break;
  359. case SEEK_END:
  360. m_pseudoFileOffset = (m_pseudoFileSize - 1) - offset;
  361. break;
  362. }
  363. // don't go beyond the end (we won't return eofErr either to match
  364. // the real seek below)
  365. if (m_pseudoFileOffset >= m_pseudoFileSize)
  366. {
  367. m_pseudoFileOffset = m_pseudoFileSize - 1;
  368. }
  369. err = HXR_OK;
  370. }
  371. else if (mBufferedWrite)
  372. {
  373. long pos = 0;
  374. switch(fromWhere)
  375. {
  376. case SEEK_SET:
  377. pos = offset;
  378. break;
  379. case SEEK_CUR:
  380. pos = mWriteFile->GetCurPos() + offset;
  381. break;
  382. case SEEK_END:
  383. pos = (mWriteFile->GetBufSize() - 1) - offset;
  384. break;
  385. }
  386. mWriteFile->Seek(pos);
  387. }
  388. else
  389. {
  390. switch(fromWhere)
  391. {
  392. case SEEK_SET:
  393. fromWhere = fsFromStart;
  394. break;
  395. case SEEK_CUR:
  396. fromWhere = fsFromMark;
  397. break;
  398. case SEEK_END:
  399. fromWhere = fsFromLEOF;
  400. break;
  401. }
  402. err =  ::SetFPos(mRefNum, fromWhere, offset);
  403. // returning eofErr was causing problems for ChunkyRes during http play
  404. if (err == eofErr)
  405. {
  406. err = ::SetEOF(mRefNum, offset);
  407. err = ::SetFPos(mRefNum, fromWhere, offset);
  408. err = HXR_OK;
  409. }
  410. long pos;
  411. ::GetFPos(mRefNum,(long *)&pos);
  412. if(!err && mBufferedRead)
  413. {
  414. long count; 
  415. ::GetEOF(mRefNum, &count);
  416. mBufferFile->PreLoad(pos,count - offset);
  417. }
  418. /* if(!theErr && mBufferedWrite)
  419. {
  420. mWriteFile->Seek(pos);
  421. } */
  422. }
  423. mLastError = err;
  424. return(err != noErr ? HXR_INVALID_FILE : 0);
  425. }
  426. // Tell 
  427. ULONG32 CMacFile::Tell(void)
  428. {
  429. ULONG32 pos;
  430. if (m_pseudoFileHandle)
  431. {
  432. pos = m_pseudoFileOffset;
  433. mLastError = noErr;
  434. }
  435. else
  436. {
  437. mLastError = ::GetFPos(mRefNum,(long *)&pos);
  438. }
  439. return(pos);
  440. }
  441. // callback could be at interrupt time
  442. pascal void ReadCallback(ParamBlockRec* pb)
  443. {
  444.     OSErr theErr = (*pb).ioParam.ioResult;      
  445.     gReadCount = pb->ioParam.ioActCount;
  446.     gReadDone = TRUE;
  447. }
  448. /*  Read reads up to count bytes of data into buf.
  449. returns the number of bytes read, EOF, or -1 if the read failed */
  450. ULONG32 CMacFile::Read (char *buf, ULONG32 count)
  451. {
  452. OSErr theErr = noErr;
  453. if (m_pseudoFileHandle)
  454. {
  455. INT32 actualCount;
  456. theErr = Read(buf, count, &actualCount);
  457. count = actualCount;
  458. }
  459. else
  460. {
  461. if(mBufferedRead)
  462. {
  463. count = Copy(buf,count);
  464. if(count == 0)
  465. theErr = eofErr;
  466. }
  467. else
  468. {
  469.         // can't do synchronous read at interrupt time
  470.         if (IsRunningNativeOnMacOSX() || IsMacInCooperativeThread())
  471.         {
  472. theErr = ::FSRead(mRefNum, (long *)&count, buf);
  473.     }
  474.     else
  475.     { // async i/o - callback could be at interrupt time
  476. #if 1
  477.      ParamBlockRec pb;
  478.      gReadCount = 0;
  479.      gReadDone = FALSE;
  480. pb.ioParam.ioRefNum = mRefNum;
  481. pb.ioParam.ioBuffer = buf;
  482. pb.ioParam.ioReqCount = count;
  483. pb.ioParam.ioPosMode=fsAtMark;
  484. pb.ioParam.ioCompletion = gReadCallbackUPP;
  485. theErr = PBReadAsync(&pb);
  486. UINT32 timeout = TickCount() + 60L;
  487. while (!gReadDone && timeout-TickCount() > 0)
  488. {
  489. }
  490. count = gReadCount;
  491. #endif
  492.     }
  493. }
  494. if (theErr == eofErr && count > 0)
  495. {
  496. theErr = noErr;
  497. }
  498. }
  499. mLastError = theErr;
  500. return(mLastError ? 0 : count); //smplfsys::read assumes we return 0 for eof
  501. }
  502. /*  Read reads up to count bytes of data into buf.
  503. returns the number of bytes read, EOF, or -1 if the read failed */
  504. INT16 CMacFile::Read (char *buf, INT32 count, INT32 *actualCount)
  505. {
  506. OSErr theErr = noErr;
  507. long readCount = (long) count;
  508. if (m_pseudoFileHandle)
  509. {
  510. // read from our pseudo-file
  511. SInt32 remainingBytes;
  512. remainingBytes = m_pseudoFileSize - m_pseudoFileOffset;
  513. if (remainingBytes <= 0)
  514. {
  515. // we've already exhausted the buffer
  516. theErr = eofErr;
  517. }
  518. else
  519. {
  520. // some bytes remain to be "read" so read them directly
  521. // from the resource into the caller's buffer
  522. if (remainingBytes < count)
  523. {
  524. count = remainingBytes;
  525. }
  526. ReadPartialResource(m_pseudoFileHandle, m_pseudoFileOffset, buf, count);
  527. theErr = ResError();
  528. HX_ASSERT(theErr == noErr);
  529. // while we don't expect any errors, -188 (resourceInMemory) isn't fatal
  530. if (theErr == noErr || theErr == resourceInMemory)
  531. {
  532. // update our pseudo-file pointer
  533. readCount = count;
  534. m_pseudoFileOffset += count;
  535. theErr = noErr;
  536. }
  537. }
  538. }
  539. else
  540. {
  541. if(mBufferedRead)
  542. {
  543. readCount = Copy(buf,readCount);
  544. if(readCount == 0)
  545. theErr = eofErr;
  546. }
  547. else
  548. {
  549.         if (IsRunningNativeOnMacOSX() || IsMacInCooperativeThread())
  550. theErr = ::FSRead(mRefNum, &readCount, buf);
  551.     else
  552.     { // async i/o - callback could be at interrupt time
  553. #if 0
  554.      ParamBlockRec pb;
  555. // IOCompletionUPP proc = NewIOCompletionProc(ReadCallback);
  556.      gReadCount = 0;
  557.      gReadDone = FALSE;
  558. pb.ioParam.ioRefNum = mRefNum;
  559. pb.ioParam.ioBuffer = buf;
  560. pb.ioParam.ioReqCount = count;
  561. pb.ioParam.ioPosMode=fsAtMark;
  562. pb.ioParam.ioCompletion = m_CompletionProc;
  563. theErr = PBReadAsync(&pb);
  564. EventRecord   theEvent;
  565. long sleepTime=10;
  566. long timeout = 0;
  567. // timeout, in case file read can't complete
  568. while (!gReadDone && timeout < 100)
  569. {
  570. ::WaitNextEvent(everyEvent, &theEvent, sleepTime, nil);
  571. timeout++;
  572. }
  573. count = gReadCount;
  574. #endif
  575.     }
  576. }
  577. }
  578. if(theErr == eofErr && readCount > 0)
  579. theErr = noErr;
  580. if (actualCount)
  581. {
  582. *actualCount = (INT32) readCount;
  583. }
  584. return(theErr);
  585. }
  586. /*  Write writes up to count bytes of data from buf.
  587. returns the number of bytes written, or -1 if the write failed */
  588. ULONG32 CMacFile::Write(const char *buf, ULONG32 count)
  589. {
  590. HX_ASSERT(!m_pseudoFileHandle);
  591.     OSErr theErr = noErr;
  592.     if (IsRunningNativeOnMacOSX() || IsMacInCooperativeThread())
  593.     {
  594. if(mAppendMode) 
  595. {
  596. theErr = ::SetFPos(mRefNum,fsFromLEOF,0L);
  597. }
  598. if(!theErr)
  599. {
  600. if(mBufferedWrite)
  601. {
  602. mWriteFile->write_data((Ptr)buf,(long)count);
  603. }
  604. else
  605. {
  606.   theErr = ::FSWrite(mRefNum, (long *)&count, buf);
  607. //check_noerr(theErr);  a disk full error may occur
  608. }
  609. }
  610. mLastError = theErr;
  611. // return(theErr ? -1 : count);
  612.     }
  613.     else
  614.     {
  615. if(mBufferedWrite)
  616. {
  617. mWriteFile->write_data((Ptr)buf,(long)count);
  618. }
  619. mLastError = theErr;
  620.     }
  621. return ((theErr == noErr) ? count : -1);
  622. }
  623. /*  Write writes up to count bytes of data from buf.
  624. returns the number of bytes written, or -1 if the write failed */
  625. INT16 CMacFile::Write(const char *buf, INT32 count, INT32 *actualCount)
  626. {
  627. HX_ASSERT(!m_pseudoFileHandle);
  628.     OSErr theErr = noErr;
  629.     *actualCount = 0;
  630.     if (IsRunningNativeOnMacOSX() || IsMacInCooperativeThread())
  631.     {
  632. long writeCount = 0;
  633. if(mAppendMode) 
  634. theErr = ::SetFPos(mRefNum, fsFromLEOF, 0L);
  635. if(!theErr) 
  636. {
  637. writeCount = count;
  638. theErr = ::FSWrite(mRefNum, &writeCount, buf);
  639. }
  640. *actualCount = (INT32) writeCount;
  641.     }
  642.     
  643. //check_noerr(theErr); a disk full error may occur
  644. // elsewhere the file code expects a negative actualCount when
  645. // the write failed
  646.     if (theErr != noErr) *actualCount = -1;
  647.     
  648.     return(theErr);
  649. }
  650. void CMacFile::SetFileType(OSType creator, OSType type)
  651. {
  652. sFileType = type;
  653. sCreator = creator;
  654. }
  655. long CMacFile::Copy(Ptr destBuf, long numBytes)
  656. {
  657. long count;
  658. // check for buffered i/o
  659. if(mBufferedRead)
  660. count = mBufferFile->Copy(destBuf,numBytes);
  661. else
  662. count = 0;
  663. return(count);
  664. }
  665. HX_RESULT CMacFile::set_buffered_read (char buffered)
  666. {
  667. Boolean OK = TRUE;
  668. HX_ASSERT(!m_pseudoFileHandle);
  669. // If this file is setup for writing then we don't want to do any buffered reading.
  670. if (m_mode & O_WRONLY) return HXR_OK;
  671. if (m_mode & O_RDWR) return HXR_OK;
  672. mBufferedRead = 0;
  673. return HXR_OK; //HACK! - this needs to be redone!
  674. // set up buffered read object if necessary
  675. if(buffered && !mBufferedRead)
  676. {
  677. if(mBufferFile == NULL) 
  678. {
  679. mBufferFile = new CBufferFile;
  680. OK = mBufferFile != NULL;
  681. }
  682. if(OK) 
  683. OK = mBufferFile->Specify(mRefNum);
  684. }
  685. else if(!buffered && mBufferedRead)
  686. {
  687. if(mBufferFile != NULL) 
  688. {
  689. delete mBufferFile;
  690. mBufferFile = NULL;
  691. }
  692. }
  693. mBufferedRead = buffered != 0;
  694. if(OK)
  695. Seek(0,SEEK_SET);
  696. return(OK ? HXR_OK : HXR_OUTOFMEMORY);
  697. }
  698. HX_RESULT CMacFile::set_buffered_write (char buffered)
  699. {
  700. Boolean OK = TRUE;
  701. HX_ASSERT(!m_pseudoFileHandle);
  702. // set up buffered read object if necessary
  703. if(buffered && !mBufferedWrite)
  704. {
  705. if(mWriteFile == NULL) 
  706. {
  707. mWriteFile = new CWriteFile;
  708. OK = mWriteFile != NULL;
  709. }
  710. if(OK) 
  711. {
  712. OK = mWriteFile->Specify(mRefNum,Tell());
  713. }
  714. }
  715. else if(!buffered && mBufferedWrite)
  716. {
  717. if(mWriteFile != NULL) 
  718. {
  719. delete mWriteFile;
  720. mWriteFile = NULL;
  721. }
  722. }
  723. mBufferedWrite = buffered != 0;
  724. return(OK ? HXR_OK : HXR_OUTOFMEMORY);
  725. }
  726. // This seems to exist solely so FileIO::status can get the size and an error value;
  727. // Otherwise, it's redundant with GetSize
  728. INT16 CMacFile::FileSize(long *size)
  729. {
  730. if (m_pseudoFileSize)
  731. {
  732. *size = m_pseudoFileSize;
  733. return 0;
  734. }
  735. return ::GetEOF(mRefNum, size);
  736. }
  737. BOOL CMacFile::GetTemporaryFileName(const char *tag, char* name, UINT32 ulBufLen)
  738. {
  739. // we'll make a temp name like tag_2345
  740. CHXString tempNameTemplate(tag);
  741. tempNameTemplate += "_%SUB%";
  742. CHXDirSpecifier tempDirSpec = CHXFileSpecUtils::GetSystemTempDirectory();
  743. CHXFileSpecifier tempFileSpec = CHXFileSpecUtils::GetUniqueTempFileSpec(
  744. tempDirSpec, (const char *) tempNameTemplate, "%SUB%");
  745. // copy the temp path to the supplied buffer, name
  746. name[0] = '';
  747. if (tempFileSpec.IsSet())
  748. {
  749. CHXString strPath = tempFileSpec.GetPathName();
  750. SafeStrCpy(name, (const char *) strPath, ulBufLen);
  751. return TRUE;
  752. }
  753. return FALSE;
  754. }