📄 cmacfile_carbon.cpp
字号:
/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: cmacfile_carbon.cpp,v 1.5.32.3 2004/07/09 01:44:13 hubbe Exp $ * * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved. * * The contents of this file, and the files included with this file, * are subject to the current version of the RealNetworks Public * Source License (the "RPSL") available at * http://www.helixcommunity.org/content/rpsl unless you have licensed * the file under the current version of the RealNetworks Community * Source License (the "RCSL") available at * http://www.helixcommunity.org/content/rcsl, in which case the RCSL * will apply. You may also obtain the license terms directly from * RealNetworks. You may not use this file except in compliance with * the RPSL or, if you have a valid RCSL with RealNetworks applicable * to this file, the RCSL. Please see the applicable RPSL or RCSL for * the rights, obligations and limitations governing use of the * contents of the file. * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL") in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your version of * this file only under the terms of the GPL, and not to allow others * to use your version of this file under the terms of either the RPSL * or RCSL, indicate your decision by deleting the provisions above * and replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient may * use your version of this file under the terms of any one of the * RPSL, the RCSL or the GPL. * * This file is part of the Helix DNA Technology. RealNetworks is the * developer of the Original Code and owns the copyrights in the * portions it created. * * This file, and the files included with this file, is distributed * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET * ENJOYMENT OR NON-INFRINGEMENT. * * Technology Compatibility Kit Test Suite(s) Location: * http://www.helixcommunity.org/content/tck * * Contributor(s): * * ***** END LICENSE BLOCK ***** */#include <fcntl.h>#include "CMacFile.h"#include "MoreFilesX.h"#include "filespecutils.h"#include "hx_moreprocesses.h"#include "hxstrutl.h"OSType CMacFile::sCreator = 'PNst';OSType CMacFile::sFileType = 'PNRA';BOOL gReadDone = FALSE;ULONG32 gReadCount = 0;// async callback procpascal void ReadCallback(ParamBlockRec* pb);// async callback UPPstatic IOCompletionUPP gReadCallbackUPP=NewIOCompletionUPP(ReadCallback);CHXDataFile*CHXDataFile::Construct(UINT32 ulFlags, IUnknown** ppCommonObj){ return (CHXDataFile *) new CMacFile;}// CHXFile should set the file reference to a value indicating the file is not openCMacFile::CMacFile (void){ mRefNum = 0; mLastError = noErr; mAppendMode = FALSE; mBufferFile = NULL; mBufferedRead = FALSE; mWriteFile = NULL; mBufferedWrite = FALSE; m_pseudoFileHandle = NULL; // if non-null, a memory manager handle containing the "file data" m_pseudoFileOffset = 0; // current "read" position in the pseudo file m_pseudoFileSize = 0; // total pseudo file size}// ~CHXFile should close the file if it is openCMacFile::~CMacFile(void){ Close(); // close file if necessary}// Create a file with the specified mode// Close the previous file if it was openHX_RESULT CMacFile::Create(const char *filename, UINT16 mode,BOOL textflag){ Close(); // close previous file if necessary CHXFileSpecifier fileSpec(filename); require_return(fileSpec.IsSet(), HXR_INVALID_PATH); BOOL bExistsAlready; OSErr err = noErr; // if the file already exists, it might be an alias file to somewhere else // (well, the pre-Carbon code checked for this; I'm not sure why we're resolving // an alias file if this path already exists) bExistsAlready = CHXFileSpecUtils::FileExists(fileSpec); if (bExistsAlready) { CHXFileSpecUtils::ResolveFileSpecifierAlias(fileSpec); bExistsAlready = CHXFileSpecUtils::FileExists(fileSpec); } // create the file if it doesn't already exist FSRef parentRef; HFSUniStr255 hfsName; FSRef openFileRef; parentRef = (FSRef) fileSpec.GetParentDirectory(); hfsName = fileSpec.GetNameHFSUniStr255(); if (!bExistsAlready) { FSCatalogInfo catInfo; FileInfo fInfo; FSSpec *kDontWantSpec = NULL; ZeroInit(&fInfo); fInfo.fileCreator = textflag ? 'ttxt' : sCreator; fInfo.fileType = textflag ? 'TEXT' : sFileType; (* (FileInfo *) &catInfo.finderInfo) = fInfo; err = FSCreateFileUnicode(&parentRef, hfsName.length, hfsName.unicode, kFSCatInfoFinderInfo, &catInfo, &openFileRef, kDontWantSpec); } else // already existed... { openFileRef = (FSRef) fileSpec; } // open the file (to mimic Windows' create semantics) if (err == noErr) { HFSUniStr255 dataForkName; dataForkName.length = 0; err = FSGetDataForkName(&dataForkName); check_noerr(err); err = FSOpenFork(&openFileRef, dataForkName.length, dataForkName.unicode, fsRdWrPerm, &mRefNum); } if (err == noErr) { mFile = openFileRef; err = FSSetForkSize(mRefNum, fsFromStart, 0); } mLastError = err; return (err != noErr ? -1 : 0);}// Open a file with the specified permissions// Close the previous file if it was open//// If the file isn't found, look for a 'RLFL' resource *in the current// resource chain* with the same name as the file.HX_RESULT CMacFile::Open(const char *filename, UINT16 mode,BOOL textflag){ Close(); // close previous file if necessary CHXFileSpecifier fileSpec(filename); if (!fileSpec.IsSet()) return HXR_INVALID_PATH; // fails if we're trying to open a file inside a non-existing directory short perm; // figure out mac file permission perm = fsRdPerm; if (mode & O_WRONLY) { perm = fsWrPerm; } else if (mode & O_RDONLY) { perm = fsRdPerm; } else if (mode & O_RDWR) { perm = fsRdWrPerm; } // Store the permissions for this file for later. m_mode = mode; BOOL bExistsAlready; OSErr err = fnfErr; bExistsAlready = CHXFileSpecUtils::FileExists(fileSpec); if (bExistsAlready) { CHXFileSpecUtils::ResolveFileSpecifierAlias(fileSpec); bExistsAlready = CHXFileSpecUtils::FileExists(fileSpec); } if (!bExistsAlready && ((mode & O_CREAT) || (mode & O_WRONLY))) { return Create(filename, mode, textflag); } if (bExistsAlready) { HFSUniStr255 dataForkName; FSRef openFileRef; dataForkName.length = 0; err = FSGetDataForkName(&dataForkName); check_noerr(err); openFileRef = (FSRef) fileSpec; err = FSOpenFork(&openFileRef, dataForkName.length, dataForkName.unicode, perm, &mRefNum); if (err == noErr) { mFile = openFileRef; } } if ((err != noErr) && (mode & O_RDONLY)) { Handle resHandle; SInt32 resSize; Str255 pascFileName; // We couldn't open the file, and the request was read-only // // See if there's a pseudo-file resource we can use // // We need a handle to the resource so we can read from it, but // we don't want the whole resource loaded into memory, so we // set ResLoad to false. SetResLoad(false); fileSpec.GetName().MakeStr255(pascFileName); resHandle = GetNamedResource(kRealFileResource, pascFileName); // 'RLFL' SetResLoad(true); if (resHandle) { // we have a handle to the resource; determine // its size and reset our "file pointer" resSize = GetResourceSizeOnDisk(resHandle); if (resSize > 0) { m_pseudoFileHandle = resHandle; m_pseudoFileSize = resSize; m_pseudoFileOffset = 0; err = noErr; mRefNum = -1; // signals that we're using a pseudo-file and no actual file is open } } } if (!m_pseudoFileHandle) { if((err == noErr) && (mode & O_CREAT)) { err = ::SetEOF(mRefNum, 0L); } if(err == noErr) { mAppendMode = (mode & O_APPEND); if (mode & O_TRUNC) { err = ::SetEOF(mRefNum, 0L); } } if (err != noErr && mRefNum != 0) { Close(); } } mLastError = err; return(err != noErr ? HXR_DOC_MISSING : 0); }// Close the previous file if it was openHX_RESULT CMacFile::Close(void){ OSErr err = noErr; if (m_pseudoFileHandle) { // "close" our pseudo file // // We don't need or want to dispose or release our pseudo- // file handle since it's not using up memory anyway, and // releasing it would hurt anyone else who happens to be // reading from it. The handle will be released // automatically when its owning resource file closes. m_pseudoFileHandle = 0; m_pseudoFileOffset = 0; m_pseudoFileSize = 0; err = noErr; mRefNum = 0; } else if (mRefNum) { if (mBufferFile) { delete mBufferFile; mBufferFile = NULL; } if (mWriteFile) { delete mWriteFile; mWriteFile = NULL; } OSErr tempErr; FSVolumeRefNum vRefNum; tempErr = FSGetVRefNum(&mFile, &vRefNum); // close a real file err = ::FSCloseFork(mRefNum); mRefNum = 0; if (err == noErr && tempErr == noErr) { tempErr = ::FlushVol(nil, vRefNum); } } mLastError = err; return(err != noErr ? -1 : 0); }HX_RESULT CMacFile::Delete (const char *filename){ HX_RESULT res; require_return(!m_pseudoFileHandle, HXR_INVALID_OPERATION); CHXFileSpecifier fileSpec(filename); res = CHXFileSpecUtils::RemoveFile(fileSpec); return SUCCEEDED(res) ? 0 : -1; }/* Returns the size of the file in bytes. */ULONG32 CMacFile::GetSize(void){ ULONG32 fileSize = 0; if (m_pseudoFileHandle) { fileSize = m_pseudoFileSize; } else if (mRefNum) { OSErr err; SInt64 forkSize; err = FSGetForkSize(mRefNum, &forkSize); if (err == noErr) { fileSize = (ULONG32) forkSize; } } else { check(!"Cannot get file size because no file is open"); } return fileSize; }// Rewinds the file position to the start of the fileHX_RESULT CMacFile::Rewind(void){ OSErr err; if (m_pseudoFileHandle) { m_pseudoFileOffset = 0; err = noErr; } else { err = ::FSSetForkPosition(mRefNum, fsFromStart, 0); } mLastError = err; return(err != noErr ? HXR_INVALID_FILE : HXR_OK);} // Seek moves the current file position to the offset from the fromWhere specifierHX_RESULT CMacFile::Seek(ULONG32 offset, UINT16 fromWhere){ OSErr err = noErr; if (m_pseudoFileHandle) { switch(fromWhere) { case SEEK_SET: m_pseudoFileOffset = offset; break; case SEEK_CUR: m_pseudoFileOffset += offset; break; case SEEK_END: m_pseudoFileOffset = (m_pseudoFileSize - 1) - offset; break; } // don't go beyond the end (we won't return eofErr either to match // the real seek below) if (m_pseudoFileOffset >= m_pseudoFileSize) { m_pseudoFileOffset = m_pseudoFileSize - 1; } err = HXR_OK; } else if (mBufferedWrite) { long pos = 0; switch(fromWhere) { case SEEK_SET: pos = offset;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -