📄 filespecutils_carbon.cpp
字号:
{ HX_RESULT res; res = HXR_FAIL; if (dirSpec.IsSet()) { FSRef dirRef; OSErr err; Boolean bIsFolder; Boolean bWasAliased; const Boolean kShouldResolveChains = true; dirRef = dirSpec; err = FSResolveAliasFileWithMountFlags(&dirRef, kShouldResolveChains, &bIsFolder, &bWasAliased, kResolveAliasFileNoUI); if ((err == noErr) && bIsFolder) { res = HXR_OK; if (bWasAliased) { dirSpec = dirRef; } } else { // error occurred } } return res;}// ------------------------------------------------------------------------------------//// MoveFileToTrash// MoveFolderToTrash// MoveFileToFolderWithRenaming// MoveFolderToFolderWithRenaming//// ------------------------------------------------------------------------------------static HX_RESULT MoveToFolderWithRenamingInternal(const FSRef* itemRef, const CHXDirSpecifier& targetSpec, BOOL bDeleteIfCantMove, FSRef& outNewItemRef);HX_RESULT CHXFileSpecUtils::MoveFileToTrash(const CHXFileSpecifier& fileSpec) { if (!CHXFileSpecUtils::FileExists(fileSpec)) return HXR_INVALID_PARAMETER; CHXDirSpecifier trashSpec; FSRef itemRef, newItemRef; const BOOL bDeleteIfCantMove = TRUE; itemRef = (FSRef) fileSpec; trashSpec = CHXFileSpecUtils::MacFindFolder(fileSpec.GetVRefNum(), kTrashFolderType); return MoveToFolderWithRenamingInternal(&itemRef, trashSpec, bDeleteIfCantMove, newItemRef);}HX_RESULT CHXFileSpecUtils::MoveFolderToTrash(const CHXDirSpecifier& dirSpec) { if (!CHXFileSpecUtils::DirectoryExists(dirSpec)) return HXR_INVALID_PARAMETER; CHXDirSpecifier trashSpec; FSRef itemRef, newItemRef; const BOOL bDeleteIfCantMove = TRUE; itemRef = (FSRef) dirSpec; trashSpec = CHXFileSpecUtils::MacFindFolder(dirSpec.GetVRefNum(), kTrashFolderType); return MoveToFolderWithRenamingInternal(&itemRef, trashSpec, bDeleteIfCantMove, newItemRef);}HX_RESULT CHXFileSpecUtils::MoveFileToCleanupAtStartup(const CHXFileSpecifier& fileSpec, BOOL bDeleteIfCantMove) { CHXFileSpecifier nonConstFileSpec(fileSpec); return MoveFileToCleanupAtStartup(nonConstFileSpec, bDeleteIfCantMove);}HX_RESULT CHXFileSpecUtils::MoveFileToCleanupAtStartup(CHXFileSpecifier& fileSpec, BOOL bDeleteIfCantMove) { if (!CHXFileSpecUtils::FileExists(fileSpec)) return HXR_INVALID_PARAMETER; CHXDirSpecifier cleanupSpec; FSRef itemRef, newItemRef; HX_RESULT res; itemRef = (FSRef) fileSpec; cleanupSpec = CHXFileSpecUtils::MacFindFolder(fileSpec.GetVRefNum(), kChewableItemsFolderType); res = MoveToFolderWithRenamingInternal(&itemRef, cleanupSpec, bDeleteIfCantMove, newItemRef); if (SUCCEEDED(res)) { fileSpec = newItemRef; } return res;}HX_RESULT CHXFileSpecUtils::MoveFolderToCleanupAtStartup(const CHXDirSpecifier& dirSpec, BOOL bDeleteIfCantMove) { CHXDirSpecifier nonConstDirSpec(dirSpec); return MoveFolderToCleanupAtStartup(nonConstDirSpec, bDeleteIfCantMove);}HX_RESULT CHXFileSpecUtils::MoveFolderToCleanupAtStartup(CHXDirSpecifier& dirSpec, BOOL bDeleteIfCantMove) { if (!CHXFileSpecUtils::DirectoryExists(dirSpec)) return HXR_INVALID_PARAMETER; CHXDirSpecifier cleanupSpec; FSRef itemRef, newItemRef; HX_RESULT res; itemRef = (FSRef) dirSpec; cleanupSpec = CHXFileSpecUtils::MacFindFolder(dirSpec.GetVRefNum(), kChewableItemsFolderType); res = MoveToFolderWithRenamingInternal(&itemRef, cleanupSpec, bDeleteIfCantMove, newItemRef); if (SUCCEEDED(res)) { dirSpec = newItemRef; } return res;}HX_RESULT CHXFileSpecUtils::MoveFileToFolderWithRenaming(CHXFileSpecifier& fileSpec, const CHXDirSpecifier& targetSpec, BOOL bDeleteIfCantMove) { if (!CHXFileSpecUtils::FileExists(fileSpec)) return HXR_INVALID_PARAMETER; if (!CHXFileSpecUtils::DirectoryExists(targetSpec)) return HXR_INVALID_PARAMETER; FSRef itemRef, newItemRef; HX_RESULT res; itemRef = (FSRef) fileSpec; res = MoveToFolderWithRenamingInternal(&itemRef, targetSpec, bDeleteIfCantMove, newItemRef); if (SUCCEEDED(res)) { fileSpec = newItemRef; } return res;}HX_RESULT CHXFileSpecUtils::MoveFolderToFolderWithRenaming(CHXDirSpecifier& dirSpec, const CHXDirSpecifier& targetSpec, BOOL bDeleteIfCantMove) { if (!CHXFileSpecUtils::DirectoryExists(dirSpec)) return HXR_INVALID_PARAMETER; if (!CHXFileSpecUtils::DirectoryExists(targetSpec)) return HXR_INVALID_PARAMETER; FSRef itemRef, newItemRef; HX_RESULT res; itemRef = (FSRef) dirSpec; res = MoveToFolderWithRenamingInternal(&itemRef, targetSpec, bDeleteIfCantMove, newItemRef); if (SUCCEEDED(res)) { dirSpec = newItemRef; } return res;}static HX_RESULT MoveToFolderWithRenamingInternal(const FSRef* itemRef, const CHXDirSpecifier& targetSpec, BOOL bDeleteIfCantMove, FSRef& outNewItemRef) { check_nonnull(itemRef); HX_RESULT pnres; OSErr err; pnres = HXR_FAILED; ZeroInit(&outNewItemRef); if (!targetSpec.IsSet()) { // targetSpec wasn't set, nowhere to move to if (bDeleteIfCantMove) { err = FSDeleteObject(itemRef); if (err == noErr) { pnres = HXR_OK; } } } else { // targetSpec is set // // try to move the file to the target FSRef newItemRef, targetRef, newNameRef; targetRef = (FSRef) targetSpec; err = FSMoveObject(itemRef, &targetRef, &newItemRef); if (err == noErr) { outNewItemRef = newItemRef; pnres = HXR_OK; } else if (err != dupFNErr) { // catmove failed for some unknown reason, not a name conflict if (bDeleteIfCantMove) { err = FSDeleteObject(itemRef); if (err == noErr) { pnres = HXR_OK; } } } else { // there's a name conflict; find a unique name for the file we're moving in the // target folder, rename it, and then move it again CHXString strName, strTemplate; CHXFileSpecifier specNewNamedFile; HFSUniStr255 uniName, newUniName; INT32 periodOffset; const char* const kWildcard = "%-%-%"; err = FSGetFileDirName(itemRef, &uniName); strName.SetFromHFSUniStr255(uniName, CFStringGetSystemEncoding()); // make a template like "filename_%-%-%" periodOffset = strName.ReverseFind('.'); if (periodOffset != -1) { // put the _2 or whatever just before the extension strTemplate = strName.Left(periodOffset); strTemplate += "_"; strTemplate += kWildcard; strTemplate += strName.Mid(periodOffset); } else { // put the _2 or whatever after the filename strTemplate = strName + "_"; strTemplate += kWildcard; } specNewNamedFile = CHXFileSpecUtils::GetUniqueFileSpec(targetSpec, strName, strTemplate, kWildcard); newUniName = specNewNamedFile.GetNameHFSUniStr255(); err = FSRenameUnicode(itemRef, newUniName.length, newUniName.unicode, kTextEncodingUnknown, &newNameRef); if (err == noErr) { err = FSMoveObject(&newNameRef, &targetRef, &newItemRef); if (err == noErr) { outNewItemRef = newItemRef; pnres = HXR_OK; } else if (err != noErr && bDeleteIfCantMove) { // couldn't move it; delete the renamed file err = FSDeleteObject(&newNameRef); if (err == noErr) { pnres = HXR_OK; } } else { // couldn't move it; change the name back err = FSRenameUnicode(&newNameRef, uniName.length, uniName.unicode, kTextEncodingUnknown, &newNameRef); } } else { // rename failed for some reason if (bDeleteIfCantMove) { // couldn't move it; delete the renamed file err = FSDeleteObject(itemRef); if (err == noErr) { pnres = HXR_OK; } } } } } return pnres;}// ------------------------------------------------------------------------------------//// GetSystemTempDirectory//// ------------------------------------------------------------------------------------CHXDirSpecifier CHXFileSpecUtils::GetSystemTempDirectory(){ return CHXFileSpecUtils::MacFindFolder(kOnAppropriateDisk, kChewableItemsFolderType);}// ------------------------------------------------------------------------------------//// GetUniqueFileSpec// GetUniqueTempFileSpec//// ------------------------------------------------------------------------------------static CHXFileSpecifier GetUniqueFileSpecInternal(const CHXDirSpecifier& locationSpec, const char *pszNameFirst, const char *pszTemplate, const char *pszWildcard, UINT32 nStartNum); const UINT32 kNumWrapValue = 9999+1; // limit insertions to 4-digit numbers CHXFileSpecifier CHXFileSpecUtils::GetUniqueFileSpec(const CHXDirSpecifier& locationSpec, const char *pszNameFirst, const char *pszTemplate, const char *pszWildcard){ return GetUniqueFileSpecInternal(locationSpec, pszNameFirst, pszTemplate, pszWildcard, 0);}CHXFileSpecifier CHXFileSpecUtils::GetUniqueTempFileSpec(const CHXDirSpecifier& locationSpec, const char *pszTemplate, const char *pszWildcard){ CMultiplePrimeRandom rand(HX_GET_TICKCOUNT()); UINT32 num; num = rand.GetRandomNumber(); num %= kNumWrapValue; // skip 0, which means "don't substitute for the wildcard", and 1 if (num == 0 || num == 1) num = 2; return GetUniqueFileSpecInternal(locationSpec, NULL, pszTemplate, pszWildcard, num);}static CHXFileSpecifier GetUniqueFileSpecInternal(const CHXDirSpecifier& locationSpec, const char *pszNameFirst, const char *pszTemplate, const char *pszWildcard, UINT32 nStartNum){ CHXFileSpecifier resultFileSpec; require_return(locationSpec.IsSet(), resultFileSpec); require_return(pszTemplate != NULL && pszWildcard != NULL, resultFileSpec); require_return(pszNameFirst != NULL || nStartNum != 0, resultFileSpec); CHXFileSpecifier testFileSpec; CHXDirSpecifier testDirSpec; CHXString strNumber; CHXString strName; UINT32 nCurrentNum; nCurrentNum = nStartNum; while (1) { // if the number is non-zero, make a string from the template; // if the number is zero, user the initial name string if (nCurrentNum == 0) { // replace the wildcard in the template with the number string strName = pszNameFirst; } else { // replace the wildcard in the template with the number string strNumber.Empty(); strNumber.AppendULONG(nCurrentNum); strName = pszTemplate; strName.FindAndReplace(pszWildcard, strNumber); // replace first wildcard with number string } // test if a file or directory exists with that name testFileSpec = locationSpec.SpecifyChildFile(strName); testDirSpec = locationSpec.SpecifyChildDirectory(strName); if (CHXFileSpecUtils::FileExists(testFileSpec) || CHXFileSpecUtils::DirectoryExists(testDirSpec)) { // an item already has that name, so increment & wrap the number nCurrentNum++; nCurrentNum %= kNumWrapValue; // don't use 0 again, and skip 1 since "MyFile2.txt" logically follows "MyFile.txt" if (nCurrentNum == 0 || nCurrentNum == 1) { nCurrentNum = 2; } // a quick sanity check if (nCurrentNum == nStartNum) { check(!"GetUniqueFileSpecInternal number wrapped"); break; } } else { // the name is unique resultFileSpec = testFileSpec; break; } } // while return resultFileSpec;}CHXDirSpecifier CHXFileSpecUtils::GetAppDataDir(const char* szAppName){ // we'll use a com.RealNetworks.data folder in user's prefs CHXDirSpecifier targetDir; CHXDirSpecifier prefsDir = CHXFileSpecUtils::MacFindFolder(kUserDomain, kPreferencesFolderType); CHXDirSpecifier dataDir = prefsDir.SpecifyChildDirectory( "com.RealNetworks.data" ); if (!CHXFileSpecUtils::DirectoryExists(dataDir)) { CHXFileSpecUtils::CreateDir(dataDir); } if (szAppName == NULL || *szAppName == 0) { targetDir = dataDir; } else { targetDir = dataDir.SpecifyChildDirectory(szAppName); if (!CHXFileSpecUtils::DirectoryExists(targetDir)) { CHXFileSpecUtils::CreateDir(targetDir); } } HX_ASSERT(CHXFileSpecUtils::DirectoryExists(targetDir)); return targetDir;}#ifdef _DEBUGvoid CHXFileSpecUtils::TestMacFileSpecUtils(){ CHXString drive1Name = "Tenspot:"; CHXString drive2Name = "Sandy:"; CHXString driveEjectableLockedName = "Dev.CD Feb 01 TC Disk 1:"; CHXString driveServerName = "grobbins:"; CHXDirSpecifier dirServerSpec = drive2Name; dirServerSpec = "Dev.CD Feb 01 TC Disk 1:Tool Chest:fake"; dirServerSpec = "Sandy:fake:"; //dirServerSpec = "grobbins:Sites:"; //dirServerSpec = "grobbins:Sites:fake"; CHXDirSpecifier dirServer2Spec = driveServerName; CHXFileSpecifier file1Spec = "Tenspot:123456789a123456789b123456789c123456789d.png"; CHXFileSpecifier file2Spec = "Tenspot:123456789a123456789b123456789c123456789d:LVd"; CHXFileSpecifier fileFake1Spec = "Tenspot:123456789a123456789b123456789c123456789d:BOO"; CHXDirSpecifier dirFake1Spec = "Tenspot:123456789a123456789b123456789c123456789d:BOO Folder"; CHXFileSpecifier fromNameSpec = "RealPlayer.xSYM"; CHXFileSpecifier fromPartialPath = ":RealPlayer.xSYM"; CHXFileSpecifier fromBadName = "BOO"; HX_RESULT res; INT64 spaceFree, spaceTotal, fileSize; BOOL bFlag; res = CHXFileSpecUtils::GetFreeSpaceOnDisk(drive1Name, spaceFree); res = CHXFileSpecUtils::GetTotalSpaceOnDisk(drive1Name, spaceTotal); check(spaceTotal > spaceFree); bFlag = CHXFileSpecUtils::IsDiskEjectable(drive1Name); check(!bFlag); bFlag = CHXFileSpecUtils::IsDiskEjectable(driveEjectableLockedName); check(bFlag); bFlag = CHXFileSpecUtils::IsDiskWritable(drive1Name); check(bFlag); bFlag = CHXFileSpecUtils::IsDiskWritable(driveEjectableLockedName); check(!bFlag); bFlag = CHXFileSpecUtils::IsDiskLocal(drive1Name); check(bFlag); //bFlag = CHXFileSpecUtils::IsDiskLocal(driveServerName); this fails because HFS<-->FSRef fails on mounted vols //check(!bFlag); res = CHXFileSpecUtils::GetFileSize(file1Spec, fileSize); res = CHXFileSpecUtils::GetFileSize(file2Spec, fileSize); res = CHXFileSpecUtils::GetFileSize(fileFake1Spec, fileSize); res = CHXFileSpecUtils::FileExists(file1Spec); res = CHXFileSpecUtils::FileExists(file2Spec); res = CHXFileSpecUtils::FileExists(fileFake1Spec); bFlag = CHXFileSpecUtils::DirectoryExists(dirFake1Spec); check(!bFlag); res = CHXFileSpecUtils::CreateDir(dirFake1Spec); bFlag = CHXFileSpecUtils::DirectoryExists(dirFake1Spec); check(bFlag); res = CHXFileSpecUtils::RemoveDir(dirFake1Spec); bFlag = CHXFileSpecUtils::DirectoryExists(dirFake1Spec); check(!bFlag); CHXDirSpecifier ffDir = CHXFileSpecUtils::SpecifyFolderWithMacFindFolder(file1Spec.GetVRefNum(), kPreferencesFolderType, "Real Folder"); res = CHXFileSpecUtils::CreateDir(ffDir); bFlag = CHXFileSpecUtils::DirectoryExists(ffDir); check(bFlag); res = CHXFileSpecUtils::MoveFolderToCleanupAtStartup(ffDir); bFlag = CHXFileSpecUtils::DirectoryExists(ffDir); check(!bFlag); }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -