QList<VolumeInfo> RunInfo::mountedVolumes() { QList<VolumeInfo> result; FSVolumeRefNum volume; FSVolumeInfo info; HFSUniStr255 volName; FSRef ref; int i = 0; while (FSGetVolumeInfo(kFSInvalidVolumeRefNum, ++i, &volume, kFSVolInfoFSInfo, &info, &volName, &ref) == 0) { UInt8 path[PATH_MAX + 1]; if (FSRefMakePath(&ref, path, PATH_MAX) == 0) { FSGetVolumeInfo(volume, 0, 0, kFSVolInfoSizes, &info, 0, 0); VolumeInfo v; v.setSize(quint64(info.totalBytes)); v.setAvailableSize(quint64(info.freeBytes)); v.setMountPath(QString::fromLocal8Bit(reinterpret_cast< char* >(path))); struct statfs data; if (statfs(qPrintable(v.mountPath() + QLatin1String("/.")), &data) == 0) { v.setFileSystemType(QLatin1String(data.f_fstypename)); v.setVolumeDescriptor(QLatin1String(data.f_mntfromname)); } result.append(v); } } return result; }
void QStorageInfoPrivate::retrieveLabel() { #if !defined(Q_OS_IOS) // deprecated since 10.8 FSRef ref; FSPathMakeRef(reinterpret_cast<const UInt8*>(QFile::encodeName(rootPath).constData()), &ref, Q_NULLPTR); // deprecated since 10.8 FSCatalogInfo catalogInfo; OSErr error; error = FSGetCatalogInfo(&ref, kFSCatInfoVolume, &catalogInfo, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR); if (error != noErr) { return; } // deprecated (use CFURLCopyResourcePropertiesForKeys for 10.7 and higher) HFSUniStr255 volumeName; error = FSGetVolumeInfo(catalogInfo.volume, 0, Q_NULLPTR, kFSVolInfoFSInfo, Q_NULLPTR, &volumeName, Q_NULLPTR); if (error == noErr) { name = QCFString(FSCreateStringFromHFSUniStr(Q_NULLPTR, &volumeName)); } #endif }
static void nglSetPathVolumeFromRefNum(int32 volnum, nglPathVolume& rPath) { // Get the volume Name: FSVolumeInfo info; HFSUniStr255 volumeName; FSRef root; FSGetVolumeInfo(volnum, 0, NULL, kFSVolInfoNone, &info, &volumeName, &root); // Fetch the name: rPath.mComment.Import((char*)volumeName.unicode, volumeName.length*2, eUCS2); // Then the root path: char path[1024]; FSRefMakePath(&root, (UInt8*)path, 1024); rPath.mPath = path; // Get other infos: GetVolParmsInfoBuffer buf; UInt32 s = sizeof(buf); nglFSGetVolParms(volnum, s, &buf, &s); rPath.mType = nglPathVolume::eTypeHD; if (VolIsNetworkVolume(&buf)) rPath.mType = nglPathVolume::eTypeNetwork; rPath.mFlags = 0; if (VolIsEjectable(&buf)) rPath.mFlags |= nglPathVolume::Removable; }
uint gp_file_name_root(const char *fname, uint len) { OSErr err = noErr; HFSUniStr255 volumeName; FSRef rootDirectory; int index, match; if (len > 0 && fname[0] == ':') return 0; /* A relative path, no root. */ /* iterate over mounted volumes and compare our path */ index = 1; while (err == noErr) { err = FSGetVolumeInfo (kFSInvalidVolumeRefNum, index, NULL, kFSVolInfoNone, NULL, /* not interested in these fields */ &volumeName, &rootDirectory); if (err == nsvErr) return 0; /* no more volumes */ if (err == noErr) { match = compare_UniStr(volumeName, fname, len); if (match > 0) { /* include the separator if it's present */ if (fname[match] == ':') return match + 1; return match; } } index++; } /* nothing matched */ return 0; }
OSErr MyGetVInfo(short drvNum, StringPtr volNamePtr, short *vRefNumPtr, double *freeBytesPtr) { OSErr err = 0; if(volNamePtr) volNamePtr[0] = 0; if(vRefNumPtr) *vRefNumPtr = 0; if(freeBytesPtr) *freeBytesPtr = 0; #if TARGET_API_MAC_CARBON { FSVolumeRefNum volume = kFSInvalidVolumeRefNum; // to index through the volumes ItemCount volumeIndex = drvNum; // // hmmm... maybe the drvNum is the index into the drives FSVolumeRefNum actualVolume; FSVolumeInfoBitmap whichInfo; FSVolumeInfo info; HFSUniStr255 * volumeName = 0; // we don't ask for this info FSRef rootDirectoryFSRef; // only ask for the sizes if we need to if(freeBytesPtr) whichInfo = kFSVolInfoSizes; else whichInfo = kFSVolInfoNone; memset(&info,0,sizeof(info)); err = FSGetVolumeInfo (volume,volumeIndex,&actualVolume,whichInfo,&info,volumeName,&rootDirectoryFSRef); if(!err) { if(vRefNumPtr) *vRefNumPtr = actualVolume; if(freeBytesPtr) *freeBytesPtr = info.freeBytes; if(volNamePtr){ FSSpec fsSpec; err = FSGetCatalogInfo(&rootDirectoryFSRef, 0,0,0,&fsSpec,0) ; if(!err) { mypstrcpyJM(volNamePtr,(char*)fsSpec.name); } } } } #else // MACB4CARBON { char pStr[256]; short vNum; long fBytes; err = GetVInfo(drvNum,(StringPtr)pStr,&vNum,&fBytes); if(!err) { if(volNamePtr) mypstrcpyJM(volNamePtr,pStr); if(vRefNumPtr) *vRefNumPtr = vNum; if(freeBytesPtr) *freeBytesPtr = fBytes; } } #endif return err; }
QString Utils::filesystemName(QString path) { QString name; #if defined(Q_OS_WIN32) wchar_t volname[MAX_PATH+1]; bool res = GetVolumeInformationW((LPTSTR)path.utf16(), volname, MAX_PATH+1, NULL, NULL, NULL, NULL, 0); if(res) { name = QString::fromWCharArray(volname); } #endif #if defined(Q_OS_MACX) // BSD label does not include folder. QString bsd = Utils::resolveDevicename(path).remove("/dev/"); if(bsd.isEmpty()) { return name; } OSStatus result; ItemCount index = 1; do { FSVolumeRefNum volrefnum; HFSUniStr255 volname; result = FSGetVolumeInfo(kFSInvalidVolumeRefNum, index, &volrefnum, kFSVolInfoFSInfo, NULL, &volname, NULL); if(result == noErr) { GetVolParmsInfoBuffer volparms; HParamBlockRec hpb; hpb.ioParam.ioNamePtr = NULL; hpb.ioParam.ioVRefNum = volrefnum; hpb.ioParam.ioBuffer = (Ptr)&volparms; hpb.ioParam.ioReqCount = sizeof(volparms); if(PBHGetVolParmsSync(&hpb) == noErr) { if(volparms.vMServerAdr == 0) { if(bsd == (char*)volparms.vMDeviceID) { name = QString::fromUtf16((const ushort*)volname.unicode, (int)volname.length); break; } } } } index++; } while(result == noErr); #endif qDebug() << "[Utils] Volume name of" << path << "is" << name; return name; }
void nglPathVolume::UpdateVolumes(std::list<nglPathVolume>& rVolumes) { OSErr result; uint volumeIndex = 1; /* Call FSGetVolumeInfo in loop to get all volumes starting with the first */ do { FSVolumeRefNum refnum = 0; result = FSGetVolumeInfo(kFSInvalidVolumeRefNum, volumeIndex, &refnum, kFSVolInfoNone, NULL, NULL, NULL); if ( noErr == result ) { // Found a new volume. AddVolume(rVolumes, refnum); ++volumeIndex; } } while ( noErr == result ); }
int DetectAudioCDVolumes(FSVolumeRefNum *volumes, int numVolumes) { int volumeIndex; int cdVolumeCount = 0; OSStatus result = noErr; for (volumeIndex = 1; result == noErr || result != nsvErr; volumeIndex++) { FSVolumeRefNum actualVolume; FSVolumeInfo volumeInfo; memset (&volumeInfo, 0, sizeof(volumeInfo)); result = FSGetVolumeInfo (kFSInvalidVolumeRefNum, volumeIndex, &actualVolume, kFSVolInfoFSInfo, &volumeInfo, NULL, NULL); if (result == noErr) { if (volumeInfo.filesystemID == kAudioCDFilesystemID) { if (volumes != NULL && cdVolumeCount < numVolumes) volumes[cdVolumeCount] = actualVolume; cdVolumeCount++; } } else { } } return cdVolumeCount; }
/** Eject device from PC. * Request the OS to eject the player. * @param device mountpoint of the device * @return true on success, fals otherwise. */ bool Utils::ejectDevice(QString device) { #if defined(Q_OS_WIN32) /* See http://support.microsoft.com/kb/165721 on the procedure to eject a * device. */ bool success = false; int i; HANDLE hdl; DWORD bytesReturned; TCHAR volume[8]; /* CreateFile */ _stprintf(volume, _TEXT("\\\\.\\%c:"), device.toLatin1().at(0)); hdl = CreateFile(volume, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if(hdl == INVALID_HANDLE_VALUE) return false; /* lock volume to make sure no other application is accessing the volume. * Try up to 10 times. */ for(i = 0; i < 10; i++) { if(DeviceIoControl(hdl, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &bytesReturned, NULL)) break; /* short break before retry */ Sleep(100); } if(i < 10) { /* successfully locked, now dismount */ if(DeviceIoControl(hdl, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &bytesReturned, NULL)) { /* make sure media can be removed. */ PREVENT_MEDIA_REMOVAL pmr; pmr.PreventMediaRemoval = false; if(DeviceIoControl(hdl, IOCTL_STORAGE_MEDIA_REMOVAL, &pmr, sizeof(PREVENT_MEDIA_REMOVAL), NULL, 0, &bytesReturned, NULL)) { /* eject the media */ if(DeviceIoControl(hdl, IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, NULL, 0, &bytesReturned, NULL)) success = true; } } } /* close handle */ CloseHandle(hdl); return success; #endif #if defined(Q_OS_MACX) // FIXME: FSUnmountVolumeSync is deprecated starting with 10.8. // Use DADiskUnmount / DiskArbitration framework eventually. // BSD label does not include folder. QString bsd = Utils::resolveDevicename(device).remove("/dev/"); OSStatus result; ItemCount index = 1; bool found = false; do { FSVolumeRefNum volrefnum; result = FSGetVolumeInfo(kFSInvalidVolumeRefNum, index, &volrefnum, kFSVolInfoFSInfo, NULL, NULL, NULL); if(result == noErr) { GetVolParmsInfoBuffer volparms; /* See above -- PBHGetVolParmsSync() is not available for 64bit, * and FSGetVolumeParms() on 10.5+ only. */ #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050 if(FSGetVolumeParms(volrefnum, &volparms, sizeof(volparms)) == noErr) #else HParamBlockRec hpb; hpb.ioParam.ioNamePtr = NULL; hpb.ioParam.ioVRefNum = volrefnum; hpb.ioParam.ioBuffer = (Ptr)&volparms; hpb.ioParam.ioReqCount = sizeof(volparms); if(PBHGetVolParmsSync(&hpb) == noErr) #endif { if(volparms.vMServerAdr == 0) { if(bsd == (char*)volparms.vMDeviceID) { pid_t dissenter; result = FSUnmountVolumeSync(volrefnum, 0, &dissenter); found = true; break; } } } } index++; } while(result == noErr); if(result == noErr && found) return true; #endif #if defined(Q_OS_LINUX) (void)device; #endif return false; }
QString Utils::filesystemName(QString path) { QString name; #if defined(Q_OS_WIN32) wchar_t volname[MAX_PATH+1]; bool res = GetVolumeInformationW((LPTSTR)path.utf16(), volname, MAX_PATH+1, NULL, NULL, NULL, NULL, 0); if(res) { name = QString::fromWCharArray(volname); } #endif #if defined(Q_OS_MACX) // BSD label does not include folder. QString bsd = Utils::resolveDevicename(path).remove("/dev/"); if(bsd.isEmpty()) { return name; } OSStatus result; ItemCount index = 1; do { FSVolumeRefNum volrefnum; HFSUniStr255 volname; result = FSGetVolumeInfo(kFSInvalidVolumeRefNum, index, &volrefnum, kFSVolInfoFSInfo, NULL, &volname, NULL); if(result == noErr) { GetVolParmsInfoBuffer volparms; /* PBHGetVolParmsSync() is not available for 64bit while FSGetVolumeParms() is available in 10.5+. Thus we need to use PBHGetVolParmsSync() for 10.4, and that also requires 10.4 to always use 32bit. Qt 4 supports 32bit on 10.6 Cocoa only. */ #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050 if(FSGetVolumeParms(volrefnum, &volparms, sizeof(volparms)) == noErr) #else HParamBlockRec hpb; hpb.ioParam.ioNamePtr = NULL; hpb.ioParam.ioVRefNum = volrefnum; hpb.ioParam.ioBuffer = (Ptr)&volparms; hpb.ioParam.ioReqCount = sizeof(volparms); if(PBHGetVolParmsSync(&hpb) == noErr) #endif { if(volparms.vMServerAdr == 0) { if(bsd == (char*)volparms.vMDeviceID) { name = QString::fromUtf16((const ushort*)volname.unicode, (int)volname.length); break; } } } } index++; } while(result == noErr); #endif LOG_INFO() << "Volume name of" << path << "is" << name; return name; }
int main(int argc, const char* argv[]) { kern_return_t kernResult; OSErr result = noErr; ItemCount volumeIndex; kernResult = IOMasterPort(MACH_PORT_NULL, &gMasterPort); if (KERN_SUCCESS != kernResult) printf("IOMasterPort returned %d\n", kernResult); // Iterate across all mounted volumes using FSGetVolumeInfo. This will return nsvErr // (no such volume) when volumeIndex becomes greater than the number of mounted volumes. for (volumeIndex = 1; result == noErr || result != nsvErr; volumeIndex++) { FSVolumeRefNum actualVolume; HFSUniStr255 volumeName; FSVolumeInfo volumeInfo; bzero((void*)&volumeInfo, sizeof(volumeInfo)); // We're mostly interested in the volume reference number (actualVolume) result = FSGetVolumeInfo(kFSInvalidVolumeRefNum, volumeIndex, &actualVolume, kFSVolInfoFSInfo, &volumeInfo, &volumeName, NULL); if (result == noErr) { GetVolParmsInfoBuffer volumeParms; HParamBlockRec pb; // Use the volume reference number to retrieve the volume parameters. See the documentation // on PBHGetVolParmsSync for other possible ways to specify a volume. pb.ioParam.ioNamePtr = NULL; pb.ioParam.ioVRefNum = actualVolume; pb.ioParam.ioBuffer = (Ptr) & volumeParms; pb.ioParam.ioReqCount = sizeof(volumeParms); // A version 4 GetVolParmsInfoBuffer contains the BSD node name in the vMDeviceID field. // It is actually a char * value. This is mentioned in the header CoreServices/CarbonCore/Files.h. result = PBHGetVolParmsSync(&pb); if (result != noErr) { printf("PBHGetVolParmsSync returned %d\n", result); } else { // This code is just to convert the volume name from a HFSUniCharStr to // a plain C string so we can print it with printf. It'd be preferable to // use CoreFoundation to work with the volume name in its Unicode form. CFStringRef volNameAsCFString; char volNameAsCString[256]; volNameAsCFString = CFStringCreateWithCharacters(kCFAllocatorDefault, volumeName.unicode, volumeName.length); // If the conversion to a C string fails, just treat it as a null string. if (!CFStringGetCString(volNameAsCFString, volNameAsCString, sizeof(volNameAsCString), kCFStringEncodingUTF8)) { volNameAsCString[0] = 0; } // The last parameter of this printf call is the BSD node name from the // GetVolParmsInfoBuffer struct. printf("Volume \"%s\" (vRefNum %d), BSD node /dev/%s, ", volNameAsCString, actualVolume, (char*)volumeParms.vMDeviceID); // Use the BSD node name to call I/O Kit and get additional information about the volume GetAdditionalVolumeInfo((char*)volumeParms.vMDeviceID); } } } return 0; }
size_t wxGetAvailableDrives(wxArrayString &paths, wxArrayString &names, wxArrayInt &icon_ids) { #ifdef wxHAS_FILESYSTEM_VOLUMES #ifdef __WXWINCE__ // No logical drives; return "\" paths.Add(wxT("\\")); names.Add(wxT("\\")); icon_ids.Add(wxFileIconsTable::computer); #elif defined(__WIN32__) && wxUSE_FSVOLUME // TODO: this code (using wxFSVolumeBase) should be used for all platforms // but unfortunately wxFSVolumeBase is not implemented everywhere const wxArrayString as = wxFSVolumeBase::GetVolumes(); for (size_t i = 0; i < as.GetCount(); i++) { wxString path = as[i]; wxFSVolume vol(path); int imageId; switch (vol.GetKind()) { case wxFS_VOL_FLOPPY: if ( (path == wxT("a:\\")) || (path == wxT("b:\\")) ) imageId = wxFileIconsTable::floppy; else imageId = wxFileIconsTable::removeable; break; case wxFS_VOL_DVDROM: case wxFS_VOL_CDROM: imageId = wxFileIconsTable::cdrom; break; case wxFS_VOL_NETWORK: if (path[0] == wxT('\\')) continue; // skip "\\computer\folder" imageId = wxFileIconsTable::drive; break; case wxFS_VOL_DISK: case wxFS_VOL_OTHER: default: imageId = wxFileIconsTable::drive; break; } paths.Add(path); names.Add(vol.GetDisplayName()); icon_ids.Add(imageId); } #elif defined(__OS2__) APIRET rc; ULONG ulDriveNum = 0; ULONG ulDriveMap = 0; rc = ::DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap); if ( rc == 0) { size_t i = 0; while (i < 26) { if (ulDriveMap & ( 1 << i )) { const wxString path = wxFileName::GetVolumeString( 'A' + i, wxPATH_GET_SEPARATOR); const wxString name = wxFileName::GetVolumeString( 'A' + i, wxPATH_NO_SEPARATOR); // Note: If _filesys is unsupported by some compilers, // we can always replace it by DosQueryFSAttach char filesysname[20]; #ifdef __WATCOMC__ ULONG cbBuffer = sizeof(filesysname); PFSQBUFFER2 pfsqBuffer = (PFSQBUFFER2)filesysname; APIRET rc = ::DosQueryFSAttach(name.fn_str(),0,FSAIL_QUERYNAME,pfsqBuffer,&cbBuffer); if (rc != NO_ERROR) { filesysname[0] = '\0'; } #else _filesys(name.fn_str(), filesysname, sizeof(filesysname)); #endif /* FAT, LAN, HPFS, CDFS, NFS */ int imageId; if (path == wxT("A:\\") || path == wxT("B:\\")) imageId = wxFileIconsTable::floppy; else if (!strcmp(filesysname, "CDFS")) imageId = wxFileIconsTable::cdrom; else if (!strcmp(filesysname, "LAN") || !strcmp(filesysname, "NFS")) imageId = wxFileIconsTable::drive; else imageId = wxFileIconsTable::drive; paths.Add(path); names.Add(name); icon_ids.Add(imageId); } i ++; } } #else // !__WIN32__, !__OS2__ /* If we can switch to the drive, it exists. */ for ( char drive = 'A'; drive <= 'Z'; drive++ ) { const wxString path = wxFileName::GetVolumeString(drive, wxPATH_GET_SEPARATOR); if (wxIsDriveAvailable(path)) { paths.Add(path); names.Add(wxFileName::GetVolumeString(drive, wxPATH_NO_SEPARATOR)); icon_ids.Add(drive <= 2 ? wxFileIconsTable::floppy : wxFileIconsTable::drive); } } #endif // __WIN32__/!__WIN32__ #elif defined(__WXMAC__) && wxOSX_USE_COCOA_OR_CARBON ItemCount volumeIndex = 1; OSErr err = noErr ; while( noErr == err ) { HFSUniStr255 volumeName ; FSRef fsRef ; FSVolumeInfo volumeInfo ; err = FSGetVolumeInfo(0, volumeIndex, NULL, kFSVolInfoFlags , &volumeInfo , &volumeName, &fsRef); if( noErr == err ) { wxString path = wxMacFSRefToPath( &fsRef ) ; wxString name = wxMacHFSUniStrToString( &volumeName ) ; if ( (volumeInfo.flags & kFSVolFlagSoftwareLockedMask) || (volumeInfo.flags & kFSVolFlagHardwareLockedMask) ) { icon_ids.Add(wxFileIconsTable::cdrom); } else { icon_ids.Add(wxFileIconsTable::drive); } // todo other removable paths.Add(path); names.Add(name); volumeIndex++ ; } } #elif defined(__UNIX__) || defined(__WXPALMOS__) paths.Add(wxT("/")); names.Add(wxT("/")); icon_ids.Add(wxFileIconsTable::computer); #else #error "Unsupported platform in wxGenericDirCtrl!" #endif wxASSERT_MSG( (paths.GetCount() == names.GetCount()), wxT("The number of paths and their human readable names should be equal in number.")); wxASSERT_MSG( (paths.GetCount() == icon_ids.GetCount()), wxT("Wrong number of icons for available drives.")); return paths.GetCount(); }
void CheckSaveFolder (FSRef *cartRef) { OSStatus err; Boolean r; FSCatalogInfo finfo; FSVolumeInfo vinfo; FSRef ref; CFURLRef burl, purl; char s[PATH_MAX + 1]; switch (saveInROMFolder) { case 0: // Snes9x folder burl = CFBundleCopyBundleURL(CFBundleGetMainBundle()); purl = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, burl); r = CFURLGetFSRef(purl, &ref); CFRelease(purl); CFRelease(burl); break; case 1: // ROM folder err = FSGetCatalogInfo(cartRef, kFSCatInfoNone, NULL, NULL, NULL, &ref); break; case 2: // Application Support folder return; case 4: // Custom folder if (saveFolderPath == NULL) { saveInROMFolder = 2; return; } r = CFStringGetCString(saveFolderPath, s, PATH_MAX, kCFStringEncodingUTF8); err = FSPathMakeRef((unsigned char *) s, &ref, NULL); if (err) { AppearanceAlert(kAlertCautionAlert, kS9xMacAlertFolderNotFound, kS9xMacAlertFolderNotFoundHint); saveInROMFolder = 2; return; } break; } err = FSGetCatalogInfo(&ref, kFSCatInfoUserPrivs | kFSCatInfoVolume, &finfo, NULL, NULL, NULL); if (err == noErr) { if (finfo.userPrivileges & kioACUserNoMakeChangesMask) { AppearanceAlert(kAlertCautionAlert, kS9xMacAlertFolderFailToCreate, kS9xMacAlertFolderFailToCreateHint); saveInROMFolder = 2; return; } err = FSGetVolumeInfo(finfo.volume, 0, NULL, kFSVolInfoFlags, &vinfo, NULL, NULL); if (err == noErr) { if ((vinfo.flags & kFSVolFlagHardwareLockedMask) || (vinfo.flags & kFSVolFlagSoftwareLockedMask)) { AppearanceAlert(kAlertCautionAlert, kS9xMacAlertFolderFailToCreate, kS9xMacAlertFolderFailToCreateHint); saveInROMFolder = 2; return; } } } if (err) saveInROMFolder = 2; }
int ListTrackFiles (FSVolumeRefNum theVolume, FSRef *trackFiles, int numTracks) { OSStatus result = -1; FSIterator iterator; ItemCount actualObjects; FSRef rootDirectory; FSRef ref; HFSUniStr255 nameStr; result = FSGetVolumeInfo (theVolume, 0, NULL, kFSVolInfoFSInfo, NULL, NULL, &rootDirectory); if (result != noErr) { SDL_SetError ("ListTrackFiles: FSGetVolumeInfo returned %d", result); return result; } result = FSOpenIterator (&rootDirectory, kFSIterateFlat, &iterator); if (result == noErr) { do { result = FSGetCatalogInfoBulk (iterator, 1, &actualObjects, NULL, kFSCatInfoNone, NULL, &ref, NULL, &nameStr); if (result == noErr) { CFStringRef name; name = CFStringCreateWithCharacters (NULL, nameStr.unicode, nameStr.length); if (CFStringHasSuffix (name, CFSTR(".aiff")) || CFStringHasSuffix (name, CFSTR(".cdda"))) { int trackID = 0, i = 0; while (i < nameStr.length && !isdigit(nameStr.unicode[i])) { ++i; } while (i < nameStr.length && isdigit(nameStr.unicode[i])) { trackID = 10 * trackID +(nameStr.unicode[i] - '0'); ++i; } #if DEBUG_CDROM printf("Found AIFF for track %d: '%s'\n", trackID, CFStringGetCStringPtr (name, CFStringGetSystemEncoding())); #endif trackID--; assert(0 <= trackID && trackID <= SDL_MAX_TRACKS); if (trackID < numTracks) memcpy (&trackFiles[trackID], &ref, sizeof(FSRef)); } CFRelease (name); } } while(noErr == result); FSCloseIterator (iterator); } return 0; }
int ReadTOCData (FSVolumeRefNum theVolume, SDL_CD *theCD) { HFSUniStr255 dataForkName; OSStatus theErr; FSIORefNum forkRefNum; SInt64 forkSize; Ptr forkData = 0; ByteCount actualRead; CFDataRef dataRef = 0; CFPropertyListRef propertyListRef = 0; FSRefParam fsRefPB; FSRef tocPlistFSRef; FSRef rootRef; const char* error = "Unspecified Error"; const UniChar uniName[] = { '.','T','O','C','.','p','l','i','s','t' }; theErr = FSGetVolumeInfo(theVolume, 0, 0, kFSVolInfoNone, 0, 0, &rootRef); if(theErr != noErr) { error = "FSGetVolumeInfo"; goto bail; } SDL_memset(&fsRefPB, '\0', sizeof (fsRefPB)); fsRefPB.ref = &rootRef; fsRefPB.newRef = &tocPlistFSRef; fsRefPB.nameLength = sizeof (uniName) / sizeof (uniName[0]); fsRefPB.name = uniName; fsRefPB.textEncodingHint = kTextEncodingUnknown; theErr = PBMakeFSRefUnicodeSync (&fsRefPB); if(theErr != noErr) { error = "PBMakeFSRefUnicodeSync"; goto bail; } theErr = FSGetDataForkName (&dataForkName); if (theErr != noErr) { error = "FSGetDataForkName"; goto bail; } theErr = FSOpenFork (&tocPlistFSRef, dataForkName.length, dataForkName.unicode, fsRdPerm, &forkRefNum); if (theErr != noErr) { error = "FSOpenFork"; goto bail; } theErr = FSGetForkSize (forkRefNum, &forkSize); if (theErr != noErr) { error = "FSGetForkSize"; goto bail; } forkData = NewPtr (forkSize); if(forkData == NULL) { error = "NewPtr"; goto bail; } theErr = FSReadFork (forkRefNum, fsFromStart, 0 , forkSize, forkData, &actualRead); if(theErr != noErr) { error = "FSReadFork"; goto bail; } dataRef = CFDataCreate (kCFAllocatorDefault, (UInt8 *)forkData, forkSize); if(dataRef == 0) { error = "CFDataCreate"; goto bail; } propertyListRef = CFPropertyListCreateFromXMLData (kCFAllocatorDefault, dataRef, kCFPropertyListImmutable, NULL); if (propertyListRef == NULL) { error = "CFPropertyListCreateFromXMLData"; goto bail; } if(CFGetTypeID(propertyListRef)== CFDictionaryGetTypeID()) { CFDictionaryRef dictRef = (CFDictionaryRef)propertyListRef; CFDataRef theRawTOCDataRef; CFArrayRef theSessionArrayRef; CFIndex numSessions; CFIndex index; theRawTOCDataRef = (CFDataRef)CFDictionaryGetValue (dictRef, CFSTR(kRawTOCDataString)); theSessionArrayRef = (CFArrayRef)CFDictionaryGetValue (dictRef, CFSTR(kSessionsString)); numSessions = CFArrayGetCount (theSessionArrayRef); theCD->numtracks = 0; for(index = 0; index < numSessions; index++) { CFDictionaryRef theSessionDict; CFNumberRef leadoutBlock; CFArrayRef trackArray; CFIndex numTracks; CFIndex trackIndex; UInt32 value = 0; theSessionDict = (CFDictionaryRef) CFArrayGetValueAtIndex (theSessionArrayRef, index); leadoutBlock = (CFNumberRef) CFDictionaryGetValue (theSessionDict, CFSTR(kLeadoutBlockString)); trackArray = (CFArrayRef)CFDictionaryGetValue (theSessionDict, CFSTR(kTrackArrayString)); numTracks = CFArrayGetCount (trackArray); for(trackIndex = 0; trackIndex < numTracks; trackIndex++) { CFDictionaryRef theTrackDict; CFNumberRef trackNumber; CFNumberRef sessionNumber; CFNumberRef startBlock; CFBooleanRef isDataTrack; UInt32 value; theTrackDict = (CFDictionaryRef) CFArrayGetValueAtIndex (trackArray, trackIndex); trackNumber = (CFNumberRef) CFDictionaryGetValue (theTrackDict, CFSTR(kPointKeyString)); sessionNumber = (CFNumberRef) CFDictionaryGetValue (theTrackDict, CFSTR(kSessionNumberKeyString)); startBlock = (CFNumberRef) CFDictionaryGetValue (theTrackDict, CFSTR(kStartBlockKeyString)); isDataTrack = (CFBooleanRef) CFDictionaryGetValue (theTrackDict, CFSTR(kDataKeyString)); int idx = theCD->numtracks++; CFNumberGetValue (trackNumber, kCFNumberSInt32Type, &value); theCD->track[idx].id = value; CFNumberGetValue (startBlock, kCFNumberSInt32Type, &value); theCD->track[idx].offset = value; theCD->track[idx].type = (isDataTrack == kCFBooleanTrue) ? SDL_DATA_TRACK : SDL_AUDIO_TRACK; if (trackIndex > 0) { theCD->track[idx-1].length = theCD->track[idx].offset - theCD->track[idx-1].offset; } } CFNumberGetValue (leadoutBlock, kCFNumberSInt32Type, &value); theCD->track[theCD->numtracks-1].length = value - theCD->track[theCD->numtracks-1].offset; theCD->track[theCD->numtracks].offset = value; } } theErr = 0; goto cleanup; bail: SDL_SetError ("ReadTOCData: %s returned %d", error, theErr); theErr = -1; cleanup: if (propertyListRef != NULL) CFRelease(propertyListRef); if (dataRef != NULL) CFRelease(dataRef); if (forkData != NULL) DisposePtr(forkData); FSCloseFork (forkRefNum); return theErr; }