📄 filespecutils_carbon.cpp
字号:
HX_RESULT CHXFileSpecUtils::RemoveDir(const CHXDirSpecifier& dirSpec){ FSRef dirRef; OSErr err; require_return(dirSpec.IsSet(), HXR_INVALID_PARAMETER); dirRef = (FSRef) dirSpec; err = FSDeleteObject(&dirRef); return err;}// ------------------------------------------------------------------------------------//// RemoveFile//// ------------------------------------------------------------------------------------HX_RESULT CHXFileSpecUtils::RemoveFile(const CHXFileSpecifier& fileSpec){ FSRef fileRef; OSErr err; require_return(fileSpec.IsSet(), HXR_INVALID_PARAMETER); fileRef = (FSRef) fileSpec; err = FSDeleteObject(&fileRef); return err;}// ------------------------------------------------------------------------------------//// MakeFileReadOnly/MakeFileNotReadOnly//// ------------------------------------------------------------------------------------HX_RESULT CHXFileSpecUtils::MakeFileReadOnly(const CHXFileSpecifier& fileSpec){ FSSpec fileFSSpec; OSErr err; require_return(fileSpec.IsSet(), HXR_INVALID_PARAMETER); fileFSSpec = (FSSpec) fileSpec; err = FSpSetFLock(&fileFSSpec); // is there an FSRef variant for this? if (err) { err = HXR_FAIL; // poor-man's OSErr-to-HX_RESULT conversion } return err;}HX_RESULT CHXFileSpecUtils::MakeFileNotReadOnly(const CHXFileSpecifier& fileSpec){ FSSpec fileFSSpec; OSErr err; require_return(fileSpec.IsSet(), HXR_INVALID_PARAMETER); fileFSSpec = (FSSpec) fileSpec; err = FSpRstFLock(&fileFSSpec); // is there an FSRef variant for this? if (err) { err = HXR_FAIL; // poor-man's OSErr-to-HX_RESULT conversion } return err;}// ------------------------------------------------------------------------------------//// RenameMoveFile//// ------------------------------------------------------------------------------------HX_RESULT CHXFileSpecUtils::RenameMoveFile(CHXFileSpecifier& fileSpec, const char* pNewNameIfAny, const CHXDirSpecifier* pNewDirectoryIfAny){ HX_RESULT res; CHXDirSpecifier fileDir, destDir; CHXFileSpecifier interimFileSpec; CHXString strNewName; FSRef fileRef, interimRef, targetRef; HFSUniStr255 newUniName; BOOL bRenaming, bMoving, bRenamed, bMoved; res = HXR_FAIL; bRenamed = bMoved = FALSE; require_return(fileSpec.IsSet(), HXR_INVALID_PARAMETER); fileDir = fileSpec.GetParentDirectory(); if (pNewDirectoryIfAny) { destDir = *pNewDirectoryIfAny; bMoving = (destDir != fileDir) ? TRUE : FALSE; } else { destDir = fileDir; bMoving = FALSE; } if (pNewNameIfAny) { strNewName = pNewNameIfAny; bRenaming = (strNewName != fileSpec.GetName()) ? TRUE : FALSE; } else { strNewName = fileSpec.GetName(); bRenaming = FALSE; } // ensure there's not already something there with this name CHXFileSpecifier specTestDest = destDir.SpecifyChildFile(strNewName); require( (!CHXFileSpecUtils::FileExists(specTestDest)), Bail); // try renaming, then move, then rename if we couldn't originally fileRef = (FSRef) fileSpec; // rename interimFileSpec = fileDir.SpecifyChildFile(strNewName); // new name in old directory if (bRenaming && interimFileSpec.IsSet() && !CHXFileSpecUtils::FileExists(interimFileSpec)) { newUniName = interimFileSpec.GetNameHFSUniStr255(); res = FSRenameUnicode(&fileRef, newUniName.length, newUniName.unicode, kTextEncodingUnknown, &interimRef); if (res == noErr) { bRenamed = TRUE; fileRef = interimRef; } } // move if (bMoving) { targetRef = (FSRef) destDir; res = FSMoveObject(&fileRef, &targetRef, &interimRef); if (res == noErr) { bMoved = TRUE; fileRef = interimRef; } } // rename -- don't try to rename if we were supposed to move & didn't if (bRenaming && !bRenamed && (bMoved || !bMoving)) { interimFileSpec = destDir.SpecifyChildFile(strNewName); // new name in new directory newUniName = interimFileSpec.GetNameHFSUniStr255(); res = FSRenameUnicode(&fileRef, newUniName.length, newUniName.unicode, kTextEncodingUnknown, &interimRef); if (res == noErr) { bRenamed = TRUE; fileRef = interimRef; } } if ((bRenamed || !bRenaming) && (bMoved || !bMoving)) { fileSpec = fileRef; res = HXR_OK; } else { res = HXR_FAIL; }Bail: return res;}// ------------------------------------------------------------------------------------//// read/write files//// ------------------------------------------------------------------------------------static HX_RESULT WriteFileInternal(CHXFileSpecifier& fileSpec, const void *pBuff, UInt32 length, BOOL bReplaceExistingFile);static HX_RESULT ReadFileInternal(const CHXFileSpecifier& fileSpec, IHXBuffer*& pOutBuffer);HX_RESULT CHXFileSpecUtils::WriteBinaryFile(CHXFileSpecifier& fileSpec, IHXBuffer* inBuffer, BOOL bReplaceExistingFile){ return WriteFileInternal(fileSpec, (void *) inBuffer->GetBuffer(), inBuffer->GetSize(), bReplaceExistingFile);}HX_RESULT CHXFileSpecUtils::WriteTextFile(CHXFileSpecifier& fileSpec, const CHXString& inStr, BOOL bReplaceExistingFile){ return WriteFileInternal(fileSpec, (const char *) inStr, inStr.GetLength(), bReplaceExistingFile);}HX_RESULT WriteFileInternal(CHXFileSpecifier& fileSpec, const void *pBuff, UInt32 length, BOOL bReplaceExistingFile){ check_nonnull(pBuff); require_return(fileSpec.IsSet(), HXR_INVALID_PARAMETER); long * kDontWantNodeID = NULL; FSCatalogInfo * kDontSetCatInfo = NULL; FSSpec * kDontWantFileFSSpec = NULL; CHXDirSpecifier parentDirSpec; Boolean targetIsDir; Boolean targetAlreadyExists; HFSUniStr255 uniName, dataForkName; FSRef fileFSRef; SInt16 forkRefNum; OSErr err; // if an item is there already, bail if we're in dont replace mode // or if the item is a directory fileFSRef = (FSRef) fileSpec; targetAlreadyExists = (FSGetNodeID(&fileFSRef, kDontWantNodeID, &targetIsDir) == noErr); // before we delete an old file, save the parent and filename info so we can create the new one // (since the FSRef for the file in the old file spec becomes invalid once we delete the file) parentDirSpec = fileSpec.GetParentDirectory(); uniName = fileSpec.GetNameHFSUniStr255(); if (targetAlreadyExists) { if (targetIsDir) return HXR_INVALID_PATH; if (!bReplaceExistingFile) return HXR_FILE_EXISTS; if (bReplaceExistingFile) { err = FSDeleteObject(&fileFSRef); } } // create, open, write into the file, and close it err = FSCreateFileUnicode((FSRef *) parentDirSpec, uniName.length, uniName.unicode, kFSCatInfoNone, kDontSetCatInfo, &fileFSRef, kDontWantFileFSSpec); if (err == noErr) { dataForkName.length = 0; err = FSGetDataForkName(&dataForkName); check_noerr(err); err = FSOpenFork(&fileFSRef, dataForkName.length, dataForkName.unicode, fsWrPerm, &forkRefNum); if (err == noErr) { long ioBytes = length; err = FSWrite(forkRefNum, &ioBytes, pBuff); check_noerr(err); FSCloseFork(forkRefNum); } if (err == noErr) { // update the file spec to point to the new file fileSpec = fileFSRef; } else { // we failed to write it; delete it (void) FSDeleteObject(&fileFSRef); } } return (err == noErr ? HXR_OK : HXR_FAIL);}HX_RESULT CHXFileSpecUtils::ReadBinaryFile(const CHXFileSpecifier& fileSpec, IHXBuffer*& pOutBuffer){ return ReadFileInternal(fileSpec, pOutBuffer);}HX_RESULT CHXFileSpecUtils::ReadTextFile(const CHXFileSpecifier& fileSpec, CHXString& outStr){ HX_RESULT res; IHXBuffer *pBuff = NULL; res = ReadFileInternal(fileSpec, pBuff); if (SUCCEEDED(res)) { outStr = CHXString((const char *) pBuff->GetBuffer(), (int) pBuff->GetSize()); HX_RELEASE(pBuff); } return res;}HX_RESULT ReadFileInternal(const CHXFileSpecifier& fileSpec, IHXBuffer*& pOutBuffer){ require_return(fileSpec.IsSet(), HXR_INVALID_PARAMETER); HFSUniStr255 dataForkName; FSRef fileFSRef; SInt16 forkRefNum = -1; SInt64 forkSize; OSStatus err; pOutBuffer = new CHXBuffer(); require_nonnull_action(pOutBuffer, Bail, err = HXR_OUTOFMEMORY); pOutBuffer->AddRef(); dataForkName.length = 0; err = FSGetDataForkName(&dataForkName); require_noerr(err, Bail); fileFSRef = (FSRef) fileSpec; err = FSOpenFork(&fileFSRef, dataForkName.length, dataForkName.unicode, fsRdPerm, &forkRefNum); require_noerr_quiet(err, Bail); err = FSGetForkSize(forkRefNum, &forkSize); require_noerr(err, Bail); require_action(forkSize <= 0x07FFFFFFF, Bail, err = HXR_INVALID_PATH); // file is too big for a 32-bit signed length err = pOutBuffer->SetSize((UInt32) forkSize); require_noerr(err, Bail); { long ioBytes = forkSize; err = FSRead(forkRefNum, &ioBytes, pOutBuffer->GetBuffer()); require_noerr(err, Bail); (void) FSCloseFork(forkRefNum); return HXR_OK; } Bail: HX_RELEASE(pOutBuffer); if (forkRefNum != -1) (void) FSCloseFork(forkRefNum); return HXR_FAIL;}// ------------------------------------------------------------------------------------//// GetFileType//// ------------------------------------------------------------------------------------FOURCC CHXFileSpecUtils::GetFileType(const CHXFileSpecifier& fileSpec){ FOURCC fileType; OSErr err; require_return(fileSpec.IsSet(), 0); fileType = 0; FSRef fileRef; FinderInfo fndrInfo; Boolean isDir; ExtendedFinderInfo * kDontWantExtendedInfo = NULL; fileRef = (FSRef) fileSpec; err = FSGetFinderInfo(&fileRef, &fndrInfo, kDontWantExtendedInfo, &isDir); if ((err == noErr) && !isDir) { fileType = fndrInfo.file.fileType; } return fileType;}// ------------------------------------------------------------------------------------//// MakeNameLegal//// returns TRUE if the name was changed//// ------------------------------------------------------------------------------------BOOL CHXFileSpecUtils::MakeNameLegal(char *pszName){ const char *badChars = ":"; const char replacementChar = '-'; const long maxNameLength = 255; long len, idx; BOOL bChanged; require_nonnull_return(pszName, FALSE); bChanged = FALSE; len = strlen(pszName); // replace any illegal characters for (idx = 0; idx < len; idx++) { if (strchr(badChars, pszName[idx])) { pszName[idx] = replacementChar; bChanged = TRUE; } } // be sure the name isn't too long if (len > maxNameLength) { pszName[maxNameLength] = 0; bChanged = TRUE; } return bChanged;}// ------------------------------------------------------------------------------------//// FindFolder//// ------------------------------------------------------------------------------------CHXDirSpecifier CHXFileSpecUtils::MacFindFolder(short vRefNum, FolderType foldType){ CHXDirSpecifier foundDirSpec; OSErr err; FSRef folderRef; err = ::FSFindFolder(vRefNum, foldType, kCreateFolder, &folderRef); if (err == noErr) { foundDirSpec = folderRef; } return foundDirSpec;}CHXFileSpecifier CHXFileSpecUtils::SpecifyFileWithMacFindFolder(short vRefNum, FolderType foldType, const char *pszChildFile){ CHXDirSpecifier parentDir; CHXFileSpecifier targetFile; parentDir = CHXFileSpecUtils::MacFindFolder(vRefNum, foldType); check(parentDir.IsSet()); if (CHXFileSpecUtils::DirectoryExists(parentDir)) { targetFile = parentDir.SpecifyChildFile(pszChildFile); } return targetFile;}CHXDirSpecifier CHXFileSpecUtils::SpecifyFolderWithMacFindFolder(short vRefNum, FolderType foldType, const char *pszChildFolder){ CHXDirSpecifier parentDir; CHXDirSpecifier targetDir; parentDir = CHXFileSpecUtils::MacFindFolder(vRefNum, foldType); check(parentDir.IsSet()); if (CHXFileSpecUtils::DirectoryExists(parentDir)) { targetDir = parentDir.SpecifyChildDirectory(pszChildFolder); } return targetDir;}// ------------------------------------------------------------------------------------//// ResolveFileSpecifierAlias// ResolveDirSpecifierAlias//// These resolve a file spec to an alias file in place//// ------------------------------------------------------------------------------------HX_RESULT CHXFileSpecUtils::ResolveFileSpecifierAlias(CHXFileSpecifier& fileSpec){ HX_RESULT res; res = HXR_FAIL; // GR 7/8/02 // check that the file exists before resolving it in hopes of avoiding // a mysterious crash on 10.1.5 if (CHXFileSpecUtils::FileExists(fileSpec)) { FSRef fileRef; OSErr err; Boolean bIsFolder; Boolean bWasAliased; const Boolean kShouldResolveChains = true; fileRef = (FSRef) fileSpec; err = FSResolveAliasFileWithMountFlags(&fileRef, kShouldResolveChains, &bIsFolder, &bWasAliased, kResolveAliasFileNoUI); if ((err == noErr) && !bIsFolder) { res = HXR_OK; if (bWasAliased) { fileSpec = fileRef; } } else { // error occurred } } return res;}HX_RESULT CHXFileSpecUtils::ResolveDirSpecifierAlias(CHXDirSpecifier& dirSpec)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -