bool8 SNES9X_FreezeTo(void) { OSStatus err; FSRef ref; char filename[PATH_MAX + 1]; if (cartOpen) { if (NavFreezeTo(filename)) { err = FSPathMakeRef((unsigned char *) filename, &ref, nil); if (!err) FSDeleteObject(&ref); S9xFreezeGame(filename); ChangeTypeAndCreator(filename, 'SAVE', '~9X~'); err = FSPathMakeRef((unsigned char *) filename, &ref, nil); WriteThumbnailToResourceFork(&ref, 128, 120); return true; } } return false; }
void CAAudioFileConverter::OpenOutputFile(const CAStreamBasicDescription &srcFormat, const CAStreamBasicDescription &destFormat, FSRef &destFSRef, CAAudioChannelLayout &destFileLayout) { const ConversionParameters ¶ms = mParams; // output file if (params.output.filePath == NULL) { GenerateOutputFileName(params.input.filePath, srcFormat, destFormat, params.output.fileType, mOutName); } else strcpy(mOutName, params.output.filePath); // deal with pre-existing output file if (FSPathMakeRef((UInt8 *)mOutName, &destFSRef, NULL) == noErr) { XThrowIf(!(params.flags & kOpt_OverwriteOutputFile), 1, "overwrite output file"); // not allowed to overwrite // output file exists - delete it XThrowIfError(FSDeleteObject(&destFSRef), "delete output file"); } // get FSRef/CFStringRef for output file FSRef outFolderFSRef; CFStringRef outFileName; XThrowIfError(PosixPathToParentFSRefAndName(mOutName, outFolderFSRef, outFileName), "locate output audio file"); // create the output file mDestFile.CreateNew(outFolderFSRef, outFileName, params.output.fileType, destFormat, &destFileLayout.Layout()); CFRelease(outFileName); }
bool8 SNES9X_RecordMovie(void) { OSStatus err; FSRef ref; char filename[PATH_MAX + 1]; if (cartOpen) { if (NavRecordMovieTo(filename)) { err = FSPathMakeRef((unsigned char *) filename, &ref, nil); if (!err) FSDeleteObject(&ref); int r; uint8 opt = 0, mask = 0; for (int i = 0; i <= 4; i++) if (macRecordFlag & (1 << i)) mask |= (1 << i); if (macRecordFlag & (1 << 5)) opt |= MOVIE_OPT_FROM_RESET; else opt |= MOVIE_OPT_FROM_SNAPSHOT; r = S9xMovieCreate(filename, mask, opt, macRecordWChar, wcslen(macRecordWChar)); if (r == SUCCESS) { ChangeTypeAndCreator(filename, 'SMOV', '~9X~'); if ((macRecordFlag & (1 << 5)) == 0) { err = FSPathMakeRef((unsigned char *) filename, &ref, nil); WriteThumbnailToResourceFork(&ref, 128, 120); } SNES9X_Go(); return true; } } } return false; }
SMACsdec::SMACsdec(ComponentInstance inSelf) : mSelf(inSelf), mSourceComponent(NULL), mDecoder(NULL), mSourceID(0), mSourceData(NULL), mPacketFrameSize(0), mFloatBuffer(NULL), mOutputBuffer(NULL) #if CaptureDataToFile ,mOutputFileRefNum(-1) #endif { memset(&mOutputData, 0, sizeof(SoundComponentData)); mOutputData.format = k16BitNativeEndianFormat; mOutputData.sampleSize = 16; #if TARGET_API_MAC_OSX && TARGET_CPU_PPC mHasAltiVec = SMACSCDUtility::HasAltiVec(); #else mHasAltiVec = false; #endif #if TARGET_API_MAC_OSX mThreadStateMutex = new CAMutex("SMACsdec::mThreadStateMutex"); #endif #if CaptureDataToFile FSRef theFSRef; FSRef theParentRef; UniChar theFileName[] = { 'o', 'u', 't', 'p', 'u', 't', '.', 's', 'd', '2' }; OSStatus theError = FSPathMakeRef((const UInt8*)"/Volumes/Annex/Users/moorf/output.sd2", &theFSRef, NULL); if(theError != fnfErr) { FSDeleteObject(&theFSRef); } theError = FSPathMakeRef((const UInt8*)"/Volumes/Annex/Users/moorf", &theParentRef, NULL); theError = FSCreateFileUnicode(&theParentRef, 10, theFileName, kFSCatInfoNone, NULL, &theFSRef, NULL); theError = FSOpenFork(&theFSRef, 0, NULL, fsRdWrPerm, &mOutputFileRefNum); if(theError != 0) { mOutputFileRefNum = -1; } #endif }
/******************************************************************** * DeleteFile * lpFileName: file path ********************************************************************/ BOOL DeleteFile(const char * lpFileName) { OSErr theErr; FSRef theFileRef; theErr = FSPathMakeRef((const UInt8 *)lpFileName, &theFileRef, NULL); if (theErr != noErr) { SetLastError(theErr); return FALSE; } theErr = FSDeleteObject(&theFileRef); SetLastError(theErr); return theErr == noErr; }
bool8 SNES9X_Freeze(void) { OSStatus err; FSRef ref; int which; const char *filename; if (cartOpen) { MacStopSound(); which = PromptFreezeDefrost(true); if (which >= 0) { filename = S9xGetFreezeFilename(which); err = FSPathMakeRef((unsigned char *) filename, &ref, nil); if (!err) FSDeleteObject(&ref); S9xFreezeGame(filename); ChangeTypeAndCreator(filename, 'SAVE', '~9X~'); err = FSPathMakeRef((unsigned char *) filename, &ref, nil); WriteThumbnailToResourceFork(&ref, 128, 120); SNES9X_Go(); MacStartSound(); return true; } else { MacStartSound(); return false; } } else return false; }
OSStatus CompleteSave( NavReplyRecord* inReply, FSRef* inFileRef, Boolean inDidWriteFile ) { OSStatus theErr; if ( inReply->validRecord ) { if ( inDidWriteFile ) { theErr = NavCompleteSave( inReply, kNavTranslateInPlace ); } else if ( !inReply->replacing ) { // Write failed, not replacing, so delete the file // that was created in BeginSave. FSDeleteObject( inFileRef ); } theErr = NavDisposeReply( inReply ); } return theErr; }
OSErr SplitFileIfNeeded(FSRef * inFileReference,FSRef * inParentReference,FSCatalogInfo * inFileCatalogInfo,HFSUniStr255 * inFileName) { OSErr tErr; Boolean splitNeeded=FALSE; SInt16 tForkRefNum; UInt32 tResourceForkSize=0; static HFSUniStr255 sResourceForkName={0,{}}; Boolean hasResourceFork=FALSE; static UInt8 tPOSIXPath[PATH_MAX*2+1]; static UInt32 tPOSIXPathMaxLength=PATH_MAX*2; struct stat tFileStat; SInt16 tNewFileRefNum; if (sResourceForkName.length==0) { tErr=FSGetResourceForkName(&sResourceForkName); if (tErr!=noErr) { logerror("An error occurred when obtaining the ResourceFork name\n"); return -1; } } // 1. Check for the presence of a resource fork tErr=FSOpenFork(inFileReference,sResourceForkName.length,sResourceForkName.unicode,fsRdPerm,&tForkRefNum); if (tErr==noErr) { SInt64 tForkSize; // Get the size of the resource fork tErr=FSGetForkSize(tForkRefNum,&tForkSize); if (tErr!=noErr) { logerror("An error occurred on getting the resource fork size of a file or director\n"); FSCloseFork(tForkRefNum); return -1; } if (tForkSize>0xFFFFFFFF) { FSCloseFork(tForkRefNum); // AppleDouble File format does not support forks bigger than 2GB logerror("AppleDouble file format does not support forks bigger than 2 GB\n"); return -1; } tResourceForkSize=tForkSize; if (tForkSize>0) { hasResourceFork=TRUE; splitNeeded=TRUE; } else { FSCloseFork(tForkRefNum); } } else { switch(tErr) { case errFSForkNotFound: case eofErr: // No resource Fork tErr=noErr; break; default: logerror("Unable to open fork\n"); return -1; break; } } // 2. Check for the presence of FinderInfo or ExtFinderInfo if (splitNeeded==FALSE) { UInt32 * tUnsignedInt32Ptr; int i; // 1. We need to save the Folder(Ext) Info in the ._ file if there are any folder/finder or extend folder/finder info tUnsignedInt32Ptr= (UInt32 *) inFileCatalogInfo->finderInfo; for(i=0;i<4;i++) { if (tUnsignedInt32Ptr[i]!=0) { // We need to create a ._file splitNeeded=TRUE; break; } } if (splitNeeded==TRUE) // 01/02/07: Symbolic link looks like this { UInt32 tSymbolicLink; tSymbolicLink='s'; tSymbolicLink='l'+(tSymbolicLink<<8); tSymbolicLink='n'+(tSymbolicLink<<8); tSymbolicLink='k'+(tSymbolicLink<<8); if (tUnsignedInt32Ptr[0]==tSymbolicLink) { splitNeeded=FALSE; } } else { tUnsignedInt32Ptr= (UInt32 *) inFileCatalogInfo->extFinderInfo; for(i=0;i<4;i++) { if (tUnsignedInt32Ptr[i]!=0) { // We need to create a ._file splitNeeded=TRUE; break; } } } } // 3. Split if needed if (splitNeeded==TRUE) { FSRef tNewFileReference; HFSUniStr255 tNewFileName; // Get the absolute Posix Path Name tErr=FSRefMakePath(inFileReference,tPOSIXPath,tPOSIXPathMaxLength); if (tErr==noErr) { if (lstat((char *) tPOSIXPath,&tFileStat)==-1) { switch(errno) { case ENOENT: // A COMPLETER break; default: // A COMPLETER break; } tErr=-1; goto byebye; } } else { logerror("An error occurred when trying to get the absolute path of a file or directory\n"); tErr=-1; goto byebye; } if (gVerboseMode==TRUE) { printf(" splitting %s...\n",tPOSIXPath); } // Check that we do not explode the current limit for file names if (inFileName->length>gMaxFileNameLength) { // We do not have enough space to add the ._ prefix // The file name is too long // Write the error logerror("File name is too long. The maximum length allowed is %ld characters\n",gMaxFileNameLength+2); return -1; } tNewFileName.length=inFileName->length+2; tNewFileName.unicode[0]='.'; tNewFileName.unicode[1]='_'; BlockMoveData(inFileName->unicode,tNewFileName.unicode+2,inFileName->length*sizeof(UniChar)); // We need to create a ._file tryagain: tErr=FSCreateFileUnicode(inParentReference,tNewFileName.length,tNewFileName.unicode,0,NULL,&tNewFileReference,NULL); if (tErr!=noErr) { switch(tErr) { case bdNamErr: case fsmBadFFSNameErr: case errFSNameTooLong: // The file name is too long // Write the error logerror("File name is too long. The maximum length allowed is %ld characters\n",gMaxFileNameLength+2); break; case dskFulErr: logerror("Disk is full\n"); break; case errFSQuotaExceeded: logerror("Your quota are exceeded\n"); break; case dupFNErr: // The file already exists, we need to try to delete it before recreating it tErr=FSMakeFSRefUnicode(inParentReference,tNewFileName.length,tNewFileName.unicode,kTextEncodingDefaultFormat,&tNewFileReference); if (tErr==noErr) { // Delete the current ._file tErr=FSDeleteObject(&tNewFileReference); if (tErr==noErr) { goto tryagain; } else { // A COMPLETER } } else { // A COMPLETER } break; case afpVolLocked: // A COMPLETER break; default: // A COMPLETER break; } return -1; } tErr=FSOpenFork(&tNewFileReference,0,NULL,fsWrPerm,&tNewFileRefNum); if (tErr==noErr) { unsigned char tAppleDoubleMagicNumber[4]= {0x00,0x05,0x16,0x07}; unsigned char tAppleDoubleVersionNumber[4]={0x00,0x02,0x00,0x00}; unsigned char tAppleDoubleFiller[16]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; ByteCount tRequestCount; UInt16 tNumberOfEntries; UInt16 tSwappedNumberOfEntries; UInt32 tEntryID; UInt32 tEntryOffset; UInt32 tEntryLength; // Write the Magic Number tRequestCount=4; tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,tAppleDoubleMagicNumber,NULL); if (tErr!=noErr) { goto writebail; } // Write the Version Number tRequestCount=4; tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,tAppleDoubleVersionNumber,NULL); if (tErr!=noErr) { goto writebail; } // Write the Filler tRequestCount=16; tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,tAppleDoubleFiller,NULL); if (tErr!=noErr) { goto writebail; } // Compute the Number of Entries tNumberOfEntries=0x0002; tSwappedNumberOfEntries=tNumberOfEntries; #ifdef __LITTLE_ENDIAN__ // Swap for Intel processor tSwappedNumberOfEntries=CFSwapInt16(tSwappedNumberOfEntries); #endif tRequestCount=2; tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,&tSwappedNumberOfEntries,NULL); if (tErr!=noErr) { goto writebail; } // Write the Entries Descriptor // **** Finder Info tEntryID=0x00000009; // Finder Info ID tEntryOffset=0x0000001A+tNumberOfEntries*12; tEntryLength=0x00000020; // 32 bytes #ifdef __LITTLE_ENDIAN__ // Swap for Intel processor tEntryID=CFSwapInt32(tEntryID); tEntryOffset=CFSwapInt32(tEntryOffset); tEntryLength=CFSwapInt32(tEntryLength); #endif tRequestCount=4; tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,&tEntryID,NULL); if (tErr!=noErr) { goto writebail; } tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,&tEntryOffset,NULL); if (tErr!=noErr) { goto writebail; } tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,&tEntryLength,NULL); if (tErr!=noErr) { goto writebail; } tEntryID=0x00000002; // Resource Fork ID tEntryOffset=0x00000052; if (hasResourceFork==TRUE) { // **** Finder Info tEntryLength=tResourceForkSize; // As you can see the AppleDouble format file is not ready for forks bigger than 2 GB } else { tEntryLength=0; } #ifdef __LITTLE_ENDIAN__ // Swap for Intel processor tEntryID=CFSwapInt32(tEntryID); tEntryOffset=CFSwapInt32(tEntryOffset); tEntryLength=CFSwapInt32(tEntryLength); #endif tRequestCount=4; tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,&tEntryID,NULL); if (tErr!=noErr) { goto writebail; } tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,&tEntryOffset,NULL); if (tErr!=noErr) { goto writebail; } tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,&tEntryLength,NULL); if (tErr!=noErr) { goto writebail; } // Write the Entries // **** Write Finder Info #ifdef __LITTLE_ENDIAN__ // Intel Processors // Even though it's referenced as a bytes field in the File API, this is actually a structure we need to swap... if (inFileCatalogInfo->nodeFlags & kFSNodeIsDirectoryMask) { // It's a fragging folder FolderInfo * tFolderInfoStruct; ExtendedFolderInfo * tExtendedFolderInfoStruct; // Swap FolderInfo Structure tFolderInfoStruct=(FolderInfo *) inFileCatalogInfo->finderInfo; SWAP_RECT(tFolderInfoStruct->windowBounds); tFolderInfoStruct->finderFlags=CFSwapInt16(tFolderInfoStruct->finderFlags); SWAP_POINT(tFolderInfoStruct->location); tFolderInfoStruct->reservedField=CFSwapInt16(tFolderInfoStruct->reservedField); // Swap ExtendedFolderInfo Info Structure tExtendedFolderInfoStruct=(ExtendedFolderInfo *) inFileCatalogInfo->extFinderInfo; SWAP_POINT(tExtendedFolderInfoStruct->scrollPosition); tExtendedFolderInfoStruct->reserved1=CFSwapInt32(tExtendedFolderInfoStruct->reserved1); tExtendedFolderInfoStruct->extendedFinderFlags=CFSwapInt16(tExtendedFolderInfoStruct->extendedFinderFlags); tExtendedFolderInfoStruct->reserved2=CFSwapInt16(tExtendedFolderInfoStruct->reserved2); tExtendedFolderInfoStruct->putAwayFolderID=CFSwapInt32(tExtendedFolderInfoStruct->putAwayFolderID); } else { // I'm just a file, you know FileInfo * tFileInfoStruct; ExtendedFileInfo * tExtendedFileInfoStruct; // Swap FileInfo Structure tFileInfoStruct=(FileInfo *) inFileCatalogInfo->finderInfo; tFileInfoStruct->fileType=CFSwapInt32(tFileInfoStruct->fileType); tFileInfoStruct->fileCreator=CFSwapInt32(tFileInfoStruct->fileCreator); tFileInfoStruct->finderFlags=CFSwapInt16(tFileInfoStruct->finderFlags); SWAP_POINT(tFileInfoStruct->location); tFileInfoStruct->reservedField=CFSwapInt16(tFileInfoStruct->reservedField); // Swap ExtendedFileInfo Structure tExtendedFileInfoStruct=(ExtendedFileInfo *) inFileCatalogInfo->extFinderInfo; tExtendedFileInfoStruct->reserved1[0]=CFSwapInt16(tExtendedFileInfoStruct->reserved1[0]); tExtendedFileInfoStruct->reserved1[1]=CFSwapInt16(tExtendedFileInfoStruct->reserved1[1]); tExtendedFileInfoStruct->reserved1[2]=CFSwapInt16(tExtendedFileInfoStruct->reserved1[2]); tExtendedFileInfoStruct->reserved1[3]=CFSwapInt16(tExtendedFileInfoStruct->reserved1[3]); tExtendedFileInfoStruct->extendedFinderFlags=CFSwapInt16(tExtendedFileInfoStruct->extendedFinderFlags); tExtendedFileInfoStruct->reserved2=CFSwapInt16(tExtendedFileInfoStruct->reserved2); tExtendedFileInfoStruct->putAwayFolderID=CFSwapInt32(tExtendedFileInfoStruct->putAwayFolderID); } #endif tRequestCount=16; tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,inFileCatalogInfo->finderInfo,NULL); if (tErr!=noErr) { goto writebail; } tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,inFileCatalogInfo->extFinderInfo,NULL); if (tErr!=noErr) { goto writebail; } // **** Write Resource Fork? if (hasResourceFork==TRUE) { // We need to be clever and copy the Resource Fork by chunks to avoid using too much memory static UInt8 * tBuffer=NULL; static ByteCount tReadRequestCount=0; ByteCount tReadActualCount; OSErr tReadErr; #define GOLDIN_BUFFER_ONE_MEGABYTE_SIZE 1048576 if (tBuffer==NULL) { tReadRequestCount=GOLDIN_BUFFER_ONE_MEGABYTE_SIZE; do { tBuffer=(UInt8 *) malloc(tReadRequestCount*sizeof(UInt8)); tReadRequestCount/=2; } while (tBuffer==NULL && tReadRequestCount>1); if (tBuffer!=NULL && tReadRequestCount>1) { tReadRequestCount*=2; } else { // A COMPLETER } } do { tReadErr=FSReadFork(tForkRefNum, fsAtMark,0, tReadRequestCount, tBuffer, &tReadActualCount); if (tReadErr==noErr || tReadErr==eofErr) { tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tReadActualCount,tBuffer,NULL); if (tErr!=noErr) { break; } } else { break; } } while (tReadErr!=eofErr); if (tReadErr!=eofErr) { // A problem occurred while reading the Resource Fork goto writebail; } else if (tErr!=noErr) { // A problem occurred while writing the Resource Fork Data to the AppleDouble file goto writebail; } } tErr=FSCloseFork(tNewFileRefNum); tErr=noErr; // Set the owner tErr=FSSetCatalogInfo(&tNewFileReference,kFSCatInfoPermissions,inFileCatalogInfo); if (tErr!=noErr) { //logerror("Permissions, owner and group could not be set for the AppleDouble file of %s\n",tPOSIXPath); tErr=-1; goto byebye; } } else { // A COMPLETER } // Close the Resource Fork if needed if (hasResourceFork==TRUE) { tErr=FSCloseFork(tForkRefNum); if (gStripResourceForks==TRUE && tErr==noErr) { // Strip the resource fork tErr=FSDeleteFork(inFileReference,sResourceForkName.length,sResourceForkName.unicode); if (tErr!=noErr) { switch(tErr) { case errFSForkNotFound: // This is not important tErr=noErr; break; default: // A COMPLETER break; } } } else { if (gStripResourceForks==TRUE && tErr!=noErr) { logerror("Resource Fork could not be stripped from %s\n",tPOSIXPath); // A COMPLETER } } } } return tErr; writebail: switch(tErr) { case dskFulErr: logerror("Disk is full\n"); break; case errFSQuotaExceeded: logerror("Your quota are exceeded\n"); break; default: logerror("An unknown error occurred while writing the AppleDouble file of %s\n",tPOSIXPath); break; } FSCloseFork(tNewFileRefNum); byebye: if (hasResourceFork==TRUE) { FSCloseFork(tForkRefNum); } return tErr; }
static OSStatus DoFSRefSave(const OurSaveDialogData *dialogDataP, NavReplyRecord* reply, AEDesc *actualDescP) { OSStatus err = noErr; FSRef fileRefParent; if ((err = AEGetDescData( actualDescP, &fileRefParent, sizeof( FSRef ) )) == noErr ) { // get the name data and its length: HFSUniStr255 nameBuffer; UniCharCount sourceLength = 0; sourceLength = (UniCharCount)CFStringGetLength( reply->saveFileName ); CFStringGetCharacters( reply->saveFileName, CFRangeMake( 0, sourceLength ), (UniChar*)&nameBuffer.unicode ); if ( sourceLength > 0 ) { if ( reply->replacing ) { // delete the file we are replacing: FSRef fileToDelete; if ((err = FSMakeFSRefUnicode( &fileRefParent, sourceLength, nameBuffer.unicode, kTextEncodingUnicodeDefault, &fileToDelete )) == noErr ) { err = FSDeleteObject( &fileToDelete ); if ( err == fBsyErr ){ DoErrorAlert(fBsyErr, kMyDeleteErrorFormatStrKey); } } } if ( err == noErr ) { // create the file based on Unicode, but we can write the file's data with an FSSpec: FSSpec newFileSpec; // get the FSSpec back so we can write the file's data if ((err = FSCreateFileUnicode( &fileRefParent, sourceLength, nameBuffer.unicode, kFSCatInfoNone, NULL, NULL, &newFileSpec)) == noErr) { FInfo fileInfo; fileInfo.fdType = kFileTypePDF; fileInfo.fdCreator = kFileCreator; err = FSpSetFInfo( &newFileSpec, &fileInfo ); // now that we have the FSSpec, we can proceed with the save operation: if(!err){ FSRef fsRef; err = FSpMakeFSRef(&newFileSpec, &fsRef); // make an FSRef if(!err){ CFURLRef saveURL = CFURLCreateFromFSRef(NULL, &fsRef); if(saveURL){ // delete the file we just made for making the FSRef err = FSpDelete(&newFileSpec); if(!err) err = MakePDFDocument(dialogDataP->parentWindow, dialogDataP->documentDataP, saveURL); if(!err) err = NavCompleteSave( reply, kNavTranslateInPlace ); if(err){ // an error ocurred saving the file, so delete the copy // left over: (void)FSpDelete( &newFileSpec ); DoErrorAlert(err, kMyWriteErrorFormatStrKey); } CFRelease(saveURL); }else{ // delete the file we just made for making the FSRe (void)FSpDelete(&newFileSpec); err = kCantCreateSaveURL; DoErrorAlert(err, kMyCreateURLErrorFormatStrKey); } } } } } } } return err; }
//--------------------------------------------------------------------- // Gets a file to save from the user. Caller must release the CFURLRef. // CFURLRef GetSaveFileFromUser(WindowRef window) { CFURLRef previousFile; CFStringRef saveFileName; UniChar *chars = NULL; CFIndex length; NavDialogCreationOptions dialogOptions; NavDialogRef dialog; NavReplyRecord replyRecord; CFURLRef fileAsCFURLRef = NULL; FSRef fileAsFSRef; FSRef parentDirectory; OSStatus status; if ( window == NULL ) return NULL; // Get the standard set of defaults status = NavGetDefaultDialogCreationOptions(&dialogOptions); require_noerr( status, CantGetNavOptions ); // Change a few things (app-wide modal, show the extension) dialogOptions.modality = kWindowModalityAppModal; dialogOptions.parentWindow = window; dialogOptions.optionFlags = kNavDefaultNavDlogOptions | kNavPreserveSaveFileExtension; // Set up the default save name previousFile = GetWindowProxyFileCFURL(window); if (previousFile == NULL) dialogOptions.saveFileName = CFStringCreateWithCString(NULL, "Untitled.rtf", kCFStringEncodingASCII); else dialogOptions.saveFileName = CFURLCopyLastPathComponent(previousFile); // Create the dialog status = NavCreatePutFileDialog(&dialogOptions, kUnknownType, kUnknownType, NULL, NULL, &dialog); require_noerr( status, CantCreateDialog ); // Show it status = NavDialogRun(dialog); require_noerr( status, CantRunDialog ); // Get the reply status = NavDialogGetReply(dialog, &replyRecord); require( ((status == noErr) || (status == userCanceledErr)), CantGetReply ); // If the user clicked "Cancel", just bail if ( status == userCanceledErr ) goto UserCanceled; // Get the file's location and name status = AEGetNthPtr(&(replyRecord.selection), 1, typeFSRef, NULL, NULL, &parentDirectory, sizeof(FSRef), NULL); require_noerr( status, CantExtractFSRef ); saveFileName = replyRecord.saveFileName; length = CFStringGetLength(saveFileName); chars = malloc(length * sizeof(UniChar)); CFStringGetCharacters(saveFileName, CFRangeMake(0, length), chars); // If we are replacing a file, erase the previous one if ( replyRecord.replacing ) { status = FSMakeFSRefUnicode(&parentDirectory, length, chars, kTextEncodingUnknown, &fileAsFSRef); require_noerr( status, CantMakeFSRef ); status = FSDeleteObject(&fileAsFSRef); require_noerr( status, CantDeletePreviousFile ); } // Create the file status = FSCreateFileUnicode(&parentDirectory, length, chars, kFSCatInfoNone, NULL, &fileAsFSRef, NULL); require_noerr( status, CantCreateSaveFile ); // Convert the reference to the file to a CFURL fileAsCFURLRef = CFURLCreateFromFSRef(NULL, &fileAsFSRef); // Cleanup CantCreateSaveFile: CantDeletePreviousFile: CantMakeFSRef: if ( chars != NULL ) free(chars); CantExtractFSRef: UserCanceled: verify_noerr( NavDisposeReply(&replyRecord) ); CantGetReply: CantRunDialog: NavDialogDispose(dialog); CantCreateDialog: if (previousFile) CFRelease(previousFile); CFRelease(dialogOptions.saveFileName); CantGetNavOptions: return fileAsCFURLRef; }
UINT32 CHXDirectory::Rename(const char* szOldName, const char* szNewName) { UINT32 err; // Unfortunately, the semantics of the parameters for this call aren't clear // // presumably, szOldName is a full path, or a partial path in the current directory // presumably, szNewName is a full path, or just a name CHXString oldFileStr(szOldName); CHXString newFileStr(szNewName); CHXFileSpecifier oldFileSpec; CHXFileSpecifier newFileSpec; CHXDirSpecifier destDirSpec; if (oldFileStr.Find(':') >= 0) { // the old name has a colon; convert it to a file spec oldFileSpec = oldFileStr; } if (!oldFileSpec.IsSet()) { // we couldn't get a valid FSSpec for the old name, // so assume it's relative to the current directory, // and make a file spec for it CHXDirSpecifier currPathSpec(m_strPath); oldFileSpec = currPathSpec.SpecifyChildFile((const char *) oldFileStr); } require_action(oldFileSpec.IsSet(), CantGetSourceForRename, err = fnfErr); if (newFileStr.Find(':') >= 0) { // the new name has a colon; try to convert it to a file spec newFileSpec = newFileStr; } // make a filespec for the destination folder // // use the directory of the new file if it was specified, otherwise use // the directory of the old file FSRef destFSRef; if (newFileSpec.IsSet()) { CHXDirSpecifier newParentDir = newFileSpec.GetParentDirectory(); err = FSMakeFSRef(newFileSpec.GetVRefNum(), newParentDir.GetDirID(), NULL, &destFSRef); } else { CHXDirSpecifier oldParentDir = oldFileSpec.GetParentDirectory(); err = FSMakeFSRef(oldFileSpec.GetVRefNum(), oldParentDir.GetDirID(), NULL, &destFSRef); } check_noerr(err); destDirSpec = destFSRef; // make sure we're not trying to move to another volume require_action(destDirSpec.GetVRefNum() == oldFileSpec.GetVRefNum(), CantChangeVolumes, err = HXR_FAILED); // they're on the same drive; possibly in different folders // use the name from the new file spec, if we have one, or else from the parameter HFSUniStr255 uniName; if (newFileSpec.IsSet()) { uniName = newFileSpec.GetNameHFSUniStr255(); } else { newFileStr.MakeHFSUniStr255(uniName, CFStringGetSystemEncoding()); } FSRef newFSRef; err = FSMoveRenameObjectUnicode(oldFileSpec, destDirSpec, uniName.length, uniName.unicode, kTextEncodingUnknown, &newFSRef); if (err == dupFNErr) { err = FSDeleteObject(newFileSpec); if (err == noErr) { err = FSMoveRenameObjectUnicode(oldFileSpec, destDirSpec, uniName.length, uniName.unicode, kTextEncodingUnknown, &newFSRef); } } CantChangeVolumes: CantGetSourceForRename: if (err == noErr) err = HXR_OK; else err = HXR_FAILED; return err; }
Boolean GetFileFromObjectAndKey(const AEDescList* desc, AEKeyword keyword, FSRef* file, Boolean create) { DescType data_desc; MacSize data_size; OSErr err; err = AESizeOfKeyDesc(desc, keyword, &data_desc, &data_size); if (err == noErr) { if (data_desc == typeObjectSpecifier) { // file object... AEDesc fileObject; err = AEGetKeyDesc(desc, keyword, typeObjectSpecifier, &fileObject); if (err == noErr) { Boolean ok = GetFileFromObjectAndKey(&fileObject, keyAEKeyData, file, create); AEDisposeDesc(&fileObject); return ok; } } else if (data_desc == typeChar && data_size <= 255) { // file path... FSRef spec; Str255 path; err = AEGetKeyPtr(desc, keyword, typeChar, &data_desc, &path[1], 255, &data_size); path[0] = data_size; if (err == noErr) { FSRef folderRef; OpString unicode_path; unicode_path.SetL((const char*)path); err = FSFindFolder(kLocalDomain, kVolumeRootFolderType, kDontCreateFolder, &folderRef); // FIXME: ismailp - test rhoroughly err = FSMakeFSRefUnicode(&folderRef, unicode_path.Length(), (const UniChar*)unicode_path.CStr(), kTextEncodingUnknown, &spec); //FSMakeFSSpec(0, 0, path, &spec); if (create && (err == noErr || err == fnfErr)) { if (noErr == err) { FSDeleteObject(&spec); } err = FSCreateFileUnicode(&spec, 0, NULL, kFSCatInfoNone, NULL, file, NULL); } } } else if (data_desc == typeAlias) { // file alias... Handle alias = NewHandle(data_size); FSRef spec; HLock(alias); err = AEGetKeyPtr(desc, keyword, typeAlias, &data_desc, *alias, data_size, &data_size); if (err == noErr) { Boolean changed; err = FSResolveAlias(NULL, (AliasHandle)alias, &spec, &changed); if (create && (err == noErr || err == fnfErr)) { if (noErr == err) { FSDeleteObject(&spec); } err = FSCreateFileUnicode(&spec, 0, NULL, kFSCatInfoNone, NULL, file, NULL); //FSpCreate(&spec, '\?\?\?\?', '\?\?\?\?', NULL); } } DisposeHandle(alias); } else { err = paramErr; } } return (err == noErr); }
void XMLMacCarbonFile::create(const XMLCh* const filePath) { OSErr err = noErr; // Split path into directory and filename components int posSlash = XMLString::lastIndexOf(filePath, '/', XMLString::stringLen(filePath) - 1); int posName = (posSlash == -1) ? 0 : posSlash+1; const XMLCh* namePtr = filePath + posName; int nameLen = XMLString::stringLen(namePtr); // Make a temporary string of the directory ArrayJanitor<XMLCh> dirPath(new XMLCh[namePtr - filePath + 1]); XMLString::subString(dirPath.get(), filePath, 0, posName); // Create the file as appropriate for API set if (gHasHFSPlusAPIs) { // HFS+ FSRef ref; // If we find an existing file, delete it if (XMLParsePathToFSRef(filePath, ref)) FSDeleteObject(&ref); // Get a ref to the parent directory if (!XMLParsePathToFSRef(dirPath.get(), ref)) err = fnfErr; // Create a new file using the unicode name if (err == noErr) { UniChar uniName[256]; err = FSCreateFileUnicode( &ref, nameLen, CopyXMLChsToUniChars(namePtr, uniName, nameLen, sizeof(uniName)), 0, NULL, NULL, NULL); } } else { // HFS FSSpec spec; // If we find an existing file, delete it if (XMLParsePathToFSSpec(filePath, spec)) FSpDelete(&spec); // Get a spec to the parent directory if (!XMLParsePathToFSSpec(dirPath.get(), spec)) err = fnfErr; // Check that the new name is not too long for HFS if (err == noErr && nameLen > 31) err = errFSNameTooLong; if (err == noErr) { // Transcode the unicode name to native encoding ArrayJanitor<const char> nativeName(XMLString::transcode(namePtr)); // Make a partial pathname from our current spec (parent directory) to the new file unsigned char name[31 * 2 + 1 * 2 + 1]; unsigned char* partial = &name[1]; *partial++ = ':'; // Partial leads with : const unsigned char* specName = spec.name; // Copy in spec name for (int specCnt = *specName++; specCnt > 0; --specCnt) *partial++ = *specName++; *partial++ = ':'; // Path component separator char c; for (const char* p = nativeName.get(); (c = *p++) != 0; ) // Copy in new element *partial++ = (c == ':') ? '/' : c; // Convert : to / name[0] = partial - &name[1]; // Set the pascal string name length // Update the spec: this will probably return fnfErr // (since we just deleted any existing file) err = FSMakeFSSpec(spec.vRefNum, spec.parID, name, &spec); // Create the file from the spec err = FSpCreate(&spec, '??\??', 'TEXT', smSystemScript); } } // Fail if we didn't create the file if (err != noErr) { ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotReadFromFile); //ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotWriteToFile); } }
int main(int argc, const char * argv[]) { setbuf (stdout, NULL); #if TARGET_OS_MAC { thread_extended_policy_data_t theFixedPolicy; theFixedPolicy.timeshare = false; // set to true for a non-fixed thread thread_policy_set(pthread_mach_thread_np(pthread_self()), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT); // We keep a reference to the spawning thread's priority around (initialized in the constructor), // and set the importance of the child thread relative to the spawning thread's priority. thread_precedence_policy_data_t thePrecedencePolicy; thePrecedencePolicy.importance = 63 - 36; thread_policy_set(pthread_mach_thread_np(pthread_self()), THREAD_PRECEDENCE_POLICY, (thread_policy_t)&thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT); } #endif // These are the variables that are set up from the input parsing char* srcFilePath = NULL; char* destFilePath = NULL; char* auPresetFile = NULL; bool shortMemoryProfile = false; OSType manu, subType, type = 0; int userSetFrames = -1; for (int i = 1; i < argc; ++i) { if (strcmp (argv[i], "-au") == 0) { if ( (i + 3) < argc ) { StrToOSType (argv[i + 1], type); StrToOSType (argv[i + 2], subType); StrToOSType (argv[i + 3], manu); i += 3; } else { printf ("Which Audio Unit:\n%s", usageStr); exit(1); } } else if (strcmp (argv[i], "-i") == 0) { srcFilePath = const_cast<char*>(argv[++i]); } else if (strcmp (argv[i], "-o") == 0) { destFilePath = const_cast<char*>(argv[++i]); } else if (strcmp (argv[i], "-p") == 0) { auPresetFile = const_cast<char*>(argv[++i]); } else if (strcmp (argv[i], "-m") == 0) { shortMemoryProfile = true; } else if (strcmp (argv[i], "-f") == 0) { sscanf(argv[++i], "%d", &userSetFrames); } else { printf ("%s\n", usageStr); exit(1); } } if (!type || !srcFilePath) { printf ("%s\n", usageStr); exit(1); } if (!destFilePath) { if (!shortMemoryProfile) { printf ("%s\n", usageStr); exit(1); } } // delete pre-existing output file if (!shortMemoryProfile) { FSRef destFSRef; if (FSPathMakeRef((UInt8 *)destFilePath, &destFSRef, NULL) == noErr) { // output file exists - delete it if (FSDeleteObject(&destFSRef)) { printf ("Cannot Delete Output File\n"); exit(1); } } } CAComponentDescription desc(type, subType, manu); CFPropertyListRef presetDict = ReadPresetFromPresetFile(auPresetFile); // the num of frames to use when processing the file with the Render call UInt32 maxFramesToUse = shortMemoryProfile ? 512 : 32768; // not set from command line if (userSetFrames > 0) { maxFramesToUse = userSetFrames; } // in some settings (for instance a delay with 100% feedback) tail time is essentially infinite // so you should safeguard the final OL render stage (post process) which is aimed at pulling the tail through // if you want to bypass this completely, just set this to zero. Float64 maxTailTimeSecs = 10.; #pragma mark - #pragma mark __ The driving code #pragma mark - try { CAComponent comp(desc); // CAAUProcessor's constructor throws... so make sure the component is valid if (comp.IsValid() == false) { printf ("Can't Find Component\n"); desc.Print(); exit(1); } CAAUProcessor processor(comp); processor.AU().Print(); CAAudioFile srcFile; CAAudioFile destFile; srcFile.Open(srcFilePath); CAStreamBasicDescription procFormat (srcFile.GetFileDataFormat()); procFormat.SetCanonical (srcFile.GetFileDataFormat().NumberChannels(), false); printf ("Processing Format:\n\t"); procFormat.Print(); if (!shortMemoryProfile) { FSRef parentDir; CFStringRef filename; PosixPathToParentFSRefAndName(destFilePath, parentDir, filename); destFile.CreateNew (parentDir, filename, 'AIFF', srcFile.GetFileDataFormat()); destFile.SetClientFormat (procFormat); } srcFile.SetClientFormat (procFormat); AUOutputBL outputList(procFormat); ReadBuffer* readBuf = NULL; #if !CAAF_USE_EXTAUDIOFILE UInt64 numInputSamples = srcFile.GetNumberPackets(); #else UInt64 numInputSamples = srcFile.GetNumberFrames(); #endif if (shortMemoryProfile) { readBuf = new ReadBuffer; readBuf->readData = new AUOutputBL(procFormat); readBuf->readFrames = 0; UInt32 numFrames = UInt32(procFormat.mSampleRate / 2); readBuf->readData->Allocate (numFrames); // half a second of audio data readBuf->readData->Prepare(); // half a second of audio data // read 1/2 second of audio into this read buffer srcFile.Read (numFrames, readBuf->readData->ABL()); sInputCallback.inputProc = MemoryInputCallback; sInputCallback.inputProcRefCon = readBuf; numInputSamples = numFrames; } else { if (desc.IsFConv()) { maxFramesToUse = userSetFrames == -1 ? 512 : maxFramesToUse; // some format converter's can call you several times in small granularities // so you can't use a large buffer to render or you won't return all of the input data // this also lessens the final difference between what you should get and what you do // converter units *really* should have a version that are offline AU's to // handle this for you. sInputCallback.inputProc = FConvInputCallback; } else sInputCallback.inputProc = InputCallback; sInputCallback.inputProcRefCon = &srcFile; } OSStatus result; require_noerr (result = processor.EstablishInputCallback (sInputCallback), home); require_noerr (result = processor.SetMaxFramesPerRender (maxFramesToUse), home); processor.SetMaxTailTime (maxTailTimeSecs); require_noerr (result = processor.Initialize (procFormat, numInputSamples), home); if (presetDict) { require_noerr (result = processor.SetAUPreset (presetDict), home); CFRelease (presetDict); } // this does ALL of the preflighting.. could be specialise for an OfflineAU type // to do this piecemeal and do a progress bar by using the OfflineAUPreflight method require_noerr (result = processor.Preflight (), home); bool isDone; isDone = false; bool needsPostProcessing; bool isSilence; UInt32 numFrames; numFrames = processor.MaxFramesPerRender(); #if CA_AU_PROFILE_TIME sReadTime = 0; sRenderTime = 0; #endif PRINT_MARKS(); // this is the render loop while (!isDone) { #if CA_AU_PROFILE_TIME UInt64 now = CAHostTimeBase::GetTheCurrentTime(); #endif outputList.Prepare(); // have to do this every time... require_noerr (result = processor.Render (outputList.ABL(), numFrames, isSilence, &isDone, &needsPostProcessing), home); #if CA_AU_PROFILE_TIME sRenderTime += (CAHostTimeBase::GetTheCurrentTime() - now); #endif if (!shortMemoryProfile) PRINT_PROGRESS(processor.GetOLPercentComplete()); else PRINT_PROGRESS(((processor.SampleTime() / numInputSamples) * 100.)); if (numFrames && !shortMemoryProfile) destFile.Write (numFrames, outputList.ABL()); } // this is the postprocessing if needed if (!shortMemoryProfile && needsPostProcessing) { isDone = false; numFrames = processor.MaxFramesPerRender(); while (!isDone) { outputList.Prepare(); // have to do this every time... #if CA_AU_PROFILE_TIME UInt64 now = CAHostTimeBase::GetTheCurrentTime(); #endif require_noerr (result = processor.PostProcess (outputList.ABL(), numFrames, isSilence, isDone), home); #if CA_AU_PROFILE_TIME sRenderTime += (CAHostTimeBase::GetTheCurrentTime() - now); #endif PRINT_PROGRESS(processor.GetOLPercentComplete()); if (numFrames && !shortMemoryProfile) destFile.Write (numFrames, outputList.ABL()); } } printf ("\n"); home: if (result) { printf ("Exit with bad result:%ld\n", result); exit(result); } if (readBuf) { delete readBuf->readData; delete readBuf; } #if CA_AU_PROFILE_TIME if (!shortMemoryProfile) { // this flushes any remaing data to be written to the disk. // the source file is closed in its destructor of course destFile.Close(); // open the file again, to get stats about it for profiling destFile.Open(destFilePath); } SInt64 numWritten; if (shortMemoryProfile) numWritten = 0; else { #if !CAAF_USE_EXTAUDIOFILE numWritten = destFile.GetNumberPackets(); #else numWritten = destFile.GetNumberFrames(); #endif } printf ("Read File Time:%.2f secs for %lld packets (%.1f secs), wrote %lld packets\n", (CAHostTimeBase::ConvertToNanos (sReadTime) / 1.0e9), numInputSamples, (numInputSamples / procFormat.mSampleRate), numWritten); if (!shortMemoryProfile) { #if !CAAF_USE_EXTAUDIOFILE UInt64 numOutputSamples = destFile.GetNumberPackets(); #else UInt64 numOutputSamples = destFile.GetNumberFrames(); #endif if (numOutputSamples == numInputSamples) { printf ("\tWrote the same number of packets as read\n"); } else { bool expectationMet = !desc.IsOffline(); // we don't have any expectations for offline AU's if (processor.LatencySampleCount() || processor.TailSampleCount()) { if (numOutputSamples - numInputSamples == processor.TailSampleCount()) expectationMet = true; if (expectationMet) printf ("Correctly wrote \'Read Size + Tail\'. "); printf ("AU reports (samples): %ld latency, %ld tail\n", processor.LatencySampleCount(), processor.TailSampleCount()); } if (expectationMet == false) { if (numOutputSamples > numInputSamples) { printf ("\tWrote %lld packets (%.2f secs) more than read\n", (numOutputSamples - numInputSamples), ((numOutputSamples - numInputSamples) / procFormat.mSampleRate)); } else { printf ("\tRead %lld packets (%.2f secs) more than wrote\n", (numInputSamples - numOutputSamples), ((numInputSamples - numOutputSamples) / procFormat.mSampleRate)); } } } } Float64 renderTimeSecs = CAHostTimeBase::ConvertToNanos (sRenderTime - sReadTime) / 1.0e9; printf ("Total Render Time:%.2f secs, using render slice size of %ld frames\n", renderTimeSecs, maxFramesToUse); Float64 cpuUsage; if (shortMemoryProfile) cpuUsage = (renderTimeSecs / 0.5) * 100.; else cpuUsage = (renderTimeSecs / (numInputSamples / procFormat.mSampleRate)) * 100.; printf ("CPU Usage for Render Time:%.2f%%\n", cpuUsage); CFStringRef str = comp.GetCompName(); UInt32 compNameLen = CFStringGetLength (str); CFStringRef presetName = NULL; if (auPresetFile) { CFPropertyListRef dict; if (processor.AU().GetAUPreset (dict) == noErr) { presetName = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)dict, CFSTR("name")); CFRelease (dict); } } UInt32 presetLen = presetName ? CFStringGetLength(presetName) : 0; char* cstr = (char*)malloc (compNameLen + presetLen + 2 + 1); CFStringGetCString (str, cstr, (CFStringGetLength (str) + 1), kCFStringEncodingASCII); if (presetName) { cstr[compNameLen] = ':'; cstr[compNameLen+1] = ':'; CFStringGetCString (presetName, cstr + compNameLen + 2, (CFStringGetLength (presetName) + 1), kCFStringEncodingASCII); } PerfResult("AudioUnitProcess", EndianU32_NtoB(comp.Desc().componentSubType), cstr, cpuUsage, "%realtime"); free (cstr); #endif } catch (CAXException &e) { char buf[256]; printf("Error: %s (%s)\n", e.mOperation, e.FormatError(buf)); exit(1); } catch (...) { printf("An unknown error occurred\n"); exit(1); } return 0; }
void *updatethreadproc(void*) { char tempDir[PATH_MAX] = ""; /* Flawfinder: ignore */ FSRef tempDirRef; char temp[PATH_MAX] = ""; /* Flawfinder: ignore */ // *NOTE: This buffer length is used in a scanf() below. char deviceNode[1024] = ""; /* Flawfinder: ignore */ LLFILE *downloadFile = NULL; OSStatus err; ProcessSerialNumber psn; char target[PATH_MAX] = ""; /* Flawfinder: ignore */ FSRef targetRef; FSRef targetParentRef; FSVolumeRefNum targetVol; FSRef trashFolderRef; Boolean replacingTarget = false; memset(&tempDirRef, 0, sizeof(tempDirRef)); memset(&targetRef, 0, sizeof(targetRef)); memset(&targetParentRef, 0, sizeof(targetParentRef)); try { // Attempt to get a reference to the Second Life application bundle containing this updater. // Any failures during this process will cause us to default to updating /Applications/Second Life.app { FSRef myBundle; err = GetCurrentProcess(&psn); if(err == noErr) { err = GetProcessBundleLocation(&psn, &myBundle); } if(err == noErr) { // Sanity check: Make sure the name of the item referenced by targetRef is "Second Life.app". FSRefMakePath(&myBundle, (UInt8*)target, sizeof(target)); llinfos << "Updater bundle location: " << target << llendl; } // Our bundle should be in Second Life.app/Contents/Resources/AutoUpdater.app // so we need to go up 3 levels to get the path to the main application bundle. if(err == noErr) { err = FSGetCatalogInfo(&myBundle, kFSCatInfoNone, NULL, NULL, NULL, &targetRef); } if(err == noErr) { err = FSGetCatalogInfo(&targetRef, kFSCatInfoNone, NULL, NULL, NULL, &targetRef); } if(err == noErr) { err = FSGetCatalogInfo(&targetRef, kFSCatInfoNone, NULL, NULL, NULL, &targetRef); } // And once more to get the parent of the target if(err == noErr) { err = FSGetCatalogInfo(&targetRef, kFSCatInfoNone, NULL, NULL, NULL, &targetParentRef); } if(err == noErr) { FSRefMakePath(&targetRef, (UInt8*)target, sizeof(target)); llinfos << "Path to target: " << target << llendl; } // Sanity check: make sure the target is a bundle with the right identifier if(err == noErr) { // Assume the worst... err = -1; if(isFSRefViewerBundle(&targetRef)) { // This is the bundle we're looking for. err = noErr; replacingTarget = true; } } // Make sure the target's parent directory is writable. if(err == noErr) { if(!isDirWritable(targetParentRef)) { // Parent directory isn't writable. llinfos << "Target parent directory not writable." << llendl; err = -1; replacingTarget = false; } } if(err != noErr) { Boolean isDirectory; llinfos << "Target search failed, defaulting to /Applications/" << gProductName << ".app." << llendl; // Set up the parent directory err = FSPathMakeRef((UInt8*)"/Applications", &targetParentRef, &isDirectory); if((err != noErr) || (!isDirectory)) { // We're so hosed. llinfos << "Applications directory not found, giving up." << llendl; throw 0; } snprintf(target, sizeof(target), "/Applications/%s.app", gProductName); memset(&targetRef, 0, sizeof(targetRef)); err = FSPathMakeRef((UInt8*)target, &targetRef, NULL); if(err == fnfErr) { // This is fine, just means we're not replacing anything. err = noErr; replacingTarget = false; } else { replacingTarget = true; } // Make sure the target's parent directory is writable. if(err == noErr) { if(!isDirWritable(targetParentRef)) { // Parent directory isn't writable. llinfos << "Target parent directory not writable." << llendl; err = -1; replacingTarget = false; } } } // If we haven't fixed all problems by this point, just bail. if(err != noErr) { llinfos << "Unable to pick a target, giving up." << llendl; throw 0; } } // Find the volID of the volume the target resides on { FSCatalogInfo info; err = FSGetCatalogInfo( &targetParentRef, kFSCatInfoVolume, &info, NULL, NULL, NULL); if(err != noErr) throw 0; targetVol = info.volume; } // Find the temporary items and trash folders on that volume. err = FSFindFolder( targetVol, kTrashFolderType, true, &trashFolderRef); if(err != noErr) throw 0; #if 0 // *HACK for DEV-11935 see below for details. FSRef tempFolderRef; err = FSFindFolder( targetVol, kTemporaryFolderType, true, &tempFolderRef); if(err != noErr) throw 0; err = FSRefMakePath(&tempFolderRef, (UInt8*)temp, sizeof(temp)); if(err != noErr) throw 0; #else // *HACK for DEV-11935 the above kTemporaryFolderType query was giving // back results with path names that seem to be too long to be used as // mount points. I suspect this incompatibility was introduced in the // Leopard 10.5.2 update, but I have not verified this. char const HARDCODED_TMP[] = "/tmp"; strncpy(temp, HARDCODED_TMP, sizeof(HARDCODED_TMP)); #endif // 0 *HACK for DEV-11935 // Skip downloading the file if the dmg was passed on the command line. std::string dmgName; if(gDmgFile != NULL) { dmgName = basename((char *)gDmgFile); char * dmgDir = dirname((char *)gDmgFile); strncpy(tempDir, dmgDir, sizeof(tempDir)); err = FSPathMakeRef((UInt8*)tempDir, &tempDirRef, NULL); if(err != noErr) throw 0; chdir(tempDir); goto begin_install; } else { // Continue on to download file. dmgName = "SecondLife.dmg"; } strncat(temp, "/SecondLifeUpdate_XXXXXX", (sizeof(temp) - strlen(temp)) - 1); if(mkdtemp(temp) == NULL) { throw 0; } strncpy(tempDir, temp, sizeof(tempDir)); temp[sizeof(tempDir) - 1] = '\0'; llinfos << "tempDir is " << tempDir << llendl; err = FSPathMakeRef((UInt8*)tempDir, &tempDirRef, NULL); if(err != noErr) throw 0; chdir(tempDir); snprintf(temp, sizeof(temp), "SecondLife.dmg"); downloadFile = LLFile::fopen(temp, "wb"); /* Flawfinder: ignore */ if(downloadFile == NULL) { throw 0; } { CURL *curl = curl_easy_init(); curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); // curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &curl_download_callback); curl_easy_setopt(curl, CURLOPT_FILE, downloadFile); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, &curl_progress_callback_func); curl_easy_setopt(curl, CURLOPT_URL, gUpdateURL); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); sendProgress(0, 1, CFSTR("Downloading...")); CURLcode result = curl_easy_perform(curl); curl_easy_cleanup(curl); if(gCancelled) { llinfos << "User cancel, bailing out."<< llendl; throw 0; } if(result != CURLE_OK) { llinfos << "Error " << result << " while downloading disk image."<< llendl; throw 0; } fclose(downloadFile); downloadFile = NULL; } begin_install: sendProgress(0, 0, CFSTR("Mounting image...")); LLFile::mkdir("mnt", 0700); // NOTE: we could add -private at the end of this command line to keep the image from showing up in the Finder, // but if our cleanup fails, this makes it much harder for the user to unmount the image. std::string mountOutput; boost::format cmdFormat("hdiutil attach %s -mountpoint mnt"); cmdFormat % dmgName; FILE* mounter = popen(cmdFormat.str().c_str(), "r"); /* Flawfinder: ignore */ if(mounter == NULL) { llinfos << "Failed to mount disk image, exiting."<< llendl; throw 0; } // We need to scan the output from hdiutil to find the device node it uses to attach the disk image. // If we don't have this information, we can't detach it later. while(mounter != NULL) { size_t len = fread(temp, 1, sizeof(temp)-1, mounter); temp[len] = 0; mountOutput.append(temp); if(len < sizeof(temp)-1) { // End of file or error. int result = pclose(mounter); if(result != 0) { // NOTE: We used to abort here, but pclose() started returning // -1, possibly when the size of the DMG passed a certain point llinfos << "Unexpected result closing pipe: " << result << llendl; } mounter = NULL; } } if(!mountOutput.empty()) { const char *s = mountOutput.c_str(); const char *prefix = "/dev/"; char *sub = strstr(s, prefix); if(sub != NULL) { sub += strlen(prefix); /* Flawfinder: ignore */ sscanf(sub, "%1023s", deviceNode); /* Flawfinder: ignore */ } } if(deviceNode[0] != 0) { llinfos << "Disk image attached on /dev/" << deviceNode << llendl; } else { llinfos << "Disk image device node not found!" << llendl; throw 0; } // Get an FSRef to the new application on the disk image FSRef sourceRef; FSRef mountRef; snprintf(temp, sizeof(temp), "%s/mnt", tempDir); llinfos << "Disk image mount point is: " << temp << llendl; err = FSPathMakeRef((UInt8 *)temp, &mountRef, NULL); if(err != noErr) { llinfos << "Couldn't make FSRef to disk image mount point." << llendl; throw 0; } sendProgress(0, 0, CFSTR("Searching for the app bundle...")); err = findAppBundleOnDiskImage(&mountRef, &sourceRef); if(err != noErr) { llinfos << "Couldn't find application bundle on mounted disk image." << llendl; throw 0; } else { llinfos << "found the bundle." << llendl; } sendProgress(0, 0, CFSTR("Preparing to copy files...")); FSRef asideRef; char aside[MAX_PATH]; /* Flawfinder: ignore */ // this will hold the name of the destination target CFStringRef appNameRef; if(replacingTarget) { // Get the name of the target we're replacing HFSUniStr255 appNameUniStr; err = FSGetCatalogInfo(&targetRef, 0, NULL, &appNameUniStr, NULL, NULL); if(err != noErr) throw 0; appNameRef = FSCreateStringFromHFSUniStr(NULL, &appNameUniStr); // Move aside old version (into work directory) err = FSMoveObject(&targetRef, &tempDirRef, &asideRef); if(err != noErr) { llwarns << "failed to move aside old version (error code " << err << ")" << llendl; throw 0; } // Grab the path for later use. err = FSRefMakePath(&asideRef, (UInt8*)aside, sizeof(aside)); } else { // Construct the name of the target based on the product name char appName[MAX_PATH]; /* Flawfinder: ignore */ snprintf(appName, sizeof(appName), "%s.app", gProductName); appNameRef = CFStringCreateWithCString(NULL, appName, kCFStringEncodingUTF8); } sendProgress(0, 0, CFSTR("Copying files...")); llinfos << "Starting copy..." << llendl; // Copy the new version from the disk image to the target location. err = FSCopyObjectSync( &sourceRef, &targetParentRef, appNameRef, &targetRef, kFSFileOperationDefaultOptions); // Grab the path for later use. err = FSRefMakePath(&targetRef, (UInt8*)target, sizeof(target)); if(err != noErr) throw 0; llinfos << "Copy complete. Target = " << target << llendl; if(err != noErr) { // Something went wrong during the copy. Attempt to put the old version back and bail. (void)FSDeleteObject(&targetRef); if(replacingTarget) { (void)FSMoveObject(&asideRef, &targetParentRef, NULL); } throw 0; } else { // The update has succeeded. Clear the cache directory. sendProgress(0, 0, CFSTR("Clearing cache...")); llinfos << "Clearing cache..." << llendl; char mask[LL_MAX_PATH]; /* Flawfinder: ignore */ snprintf(mask, LL_MAX_PATH, "%s*.*", gDirUtilp->getDirDelimiter().c_str()); gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),mask); llinfos << "Clear complete." << llendl; } } catch(...) { if(!gCancelled) if(gFailure == noErr) gFailure = -1; } // Failures from here on out are all non-fatal and not reported. sendProgress(0, 3, CFSTR("Cleaning up...")); // Close disk image file if necessary if(downloadFile != NULL) { llinfos << "Closing download file." << llendl; fclose(downloadFile); downloadFile = NULL; } sendProgress(1, 3); // Unmount image if(deviceNode[0] != 0) { llinfos << "Detaching disk image." << llendl; snprintf(temp, sizeof(temp), "hdiutil detach '%s'", deviceNode); system(temp); /* Flawfinder: ignore */ } sendProgress(2, 3); // Move work directory to the trash if(tempDir[0] != 0) { // chdir("/"); // FSDeleteObjects(tempDirRef); llinfos << "Moving work directory to the trash." << llendl; err = FSMoveObject(&tempDirRef, &trashFolderRef, NULL); if(err != noErr) { llwarns << "failed to move files to trash, (error code " << err << ")" << llendl; } // snprintf(temp, sizeof(temp), "rm -rf '%s'", tempDir); // printf("%s\n", temp); // system(temp); } if(!gCancelled && !gFailure && (target[0] != 0)) { llinfos << "Touching application bundle." << llendl; snprintf(temp, sizeof(temp), "touch '%s'", target); system(temp); /* Flawfinder: ignore */ llinfos << "Launching updated application." << llendl; snprintf(temp, sizeof(temp), "open '%s'", target); system(temp); /* Flawfinder: ignore */ } sendDone(); return(NULL); }
CFURLRef GetSaveDialogForUser(char* title, char* message) { NavDialogCreationOptions dialogOptions; FSRef output_file; CFURLRef fileAsCFURLRef = NULL; OSStatus status; CFAllocatorRef alloc_default = kCFAllocatorDefault; AEKeyword keyword; DescType actual_type; Size actual_size; FSRef output_dir; NavReplyRecord reply; CFIndex len; // Get the standard set of defaults status = NavGetDefaultDialogCreationOptions( &dialogOptions ); require_noerr( status, CantGetNavOptions ); dialogOptions.optionFlags = kNavNoTypePopup + kNavSupportPackages + kNavAllowOpenPackages; // = NULL; if (title != NULL) { CFStringRef cftitle = CFStringCreateWithCString(alloc_default,title,kCFStringEncodingMacRoman); dialogOptions.windowTitle = cftitle; } if (message != NULL) { CFStringRef cfmessage = CFStringCreateWithCString(alloc_default,message,kCFStringEncodingMacRoman); dialogOptions.message = cfmessage; } // Make the window app-wide modal dialogOptions.modality = kWindowModalityAppModal; NavDialogRef dialog; status = NavCreatePutFileDialog ( &dialogOptions, NULL, NULL, NULL, NULL, &dialog); require_noerr( status, CantCreateDialog ); status = NavDialogRun(dialog); require_noerr( status, CantRunDialog ); // get dialog reply status = NavDialogGetReply(dialog, &reply); require( ((status == noErr) || (status == userCanceledErr)), CantGetReply ); //get file directory status = AEGetNthPtr(&(reply.selection), 1, typeFSRef, &keyword, &actual_type, &output_dir, sizeof(output_file), &actual_size); require_noerr( status, CantExtractFSRef ); UInt8 output_dir_name[1024]; FSRefMakePath(&output_dir, output_dir_name, 1024 ); // now get filename len = CFStringGetLength(reply.saveFileName); if (len > 255) len = 255; UniChar output_filename[255]; CFStringGetCharacters(reply.saveFileName, CFRangeMake(0, len), output_filename); // need to unlink the old file if ( reply.replacing ) { FSRef oldfile; status = FSMakeFSRefUnicode(&output_dir, len, output_filename, kTextEncodingUnicodeDefault, &oldfile); if (status == noErr) status = FSDeleteObject(&oldfile); //overwrite failed! require_noerr( status, UserCanceled ); } //create fsref again to new file (NOTE: this actually makes a file...) status = FSCreateFileUnicode( &output_dir, len, output_filename, kFSCatInfoNone, NULL, &output_file, NULL ); require_noerr( status, CantExtractFSRef ); // Convert it to a CFURL fileAsCFURLRef = CFURLCreateFromFSRef(NULL, &output_file); CantExtractFSRef: UserCanceled: verify_noerr( NavDisposeReply(&reply) ); CantGetReply: CantRunDialog: // cleanup dialog NavDialogDispose(dialog); CantCreateDialog: CantGetNavOptions: return fileAsCFURLRef; }
/******************************************************************** * CreateFile * ulMode: GENERIC_READ | GENERIC_WRITE * ulSharing: FILE_SHARE_READ * pSecAttrib: NULL * ulCreation: MPQ_CREATE_NEW, MPQ_CREATE_ALWAYS, MPQ_OPEN_EXISTING, MPQ_OPEN_ALWAYS * ulFlags: 0 * hFile: NULL ********************************************************************/ HANDLE CreateFile( const char *sFileName, /* file name */ DWORD ulMode, /* access mode */ DWORD ulSharing, /* share mode */ void *pSecAttrib, /* SD */ DWORD ulCreation, /* how to create */ DWORD ulFlags, /* file attributes */ HANDLE hFile ) /* handle to template file */ { #pragma unused (ulSharing, pSecAttrib, ulFlags, hFile) OSErr theErr; FSRef theFileRef; FSRef theParentRef; short fileRef; char permission; theErr = FSPathMakeRef((const UInt8 *)sFileName, &theFileRef, NULL); if (ulCreation == MPQ_CREATE_NEW && theErr != fnfErr) { return INVALID_HANDLE_VALUE; } if (ulCreation == MPQ_CREATE_ALWAYS && theErr == noErr) { FSDeleteObject(&theFileRef); } if (theErr == fnfErr || ulCreation == MPQ_CREATE_ALWAYS) { // Create the FSRef for the parent directory. memset(&theFileRef, 0, sizeof(FSRef)); UInt8 folderName[MAX_PATH]; CFStringRef folderPathCFString = CFStringCreateWithCString(NULL, sFileName, kCFStringEncodingUTF8); CFURLRef fileURL = CFURLCreateWithFileSystemPath(NULL, folderPathCFString, kCFURLPOSIXPathStyle, FALSE); CFURLRef folderURL = CFURLCreateCopyDeletingLastPathComponent(NULL, fileURL); CFURLGetFileSystemRepresentation(folderURL, TRUE, folderName, MAX_PATH); theErr = FSPathMakeRef(folderName, &theParentRef, NULL); CFRelease(fileURL); CFRelease(folderURL); CFRelease(folderPathCFString); } if (theErr != noErr) { SetLastError(theErr); if (ulCreation == MPQ_OPEN_EXISTING || theErr != fnfErr) return INVALID_HANDLE_VALUE; } if (ulCreation != MPQ_OPEN_EXISTING && FSGetCatalogInfo(&theFileRef, kFSCatInfoNone, NULL, NULL, NULL, NULL)) { /* We create the file */ UniChar unicodeFileName[256]; CFStringRef filePathCFString = CFStringCreateWithCString(NULL, sFileName, kCFStringEncodingUTF8); CFURLRef fileURL = CFURLCreateWithFileSystemPath(NULL, filePathCFString, kCFURLPOSIXPathStyle, FALSE); CFStringRef fileNameCFString = CFURLCopyLastPathComponent(fileURL); CFStringGetCharacters(fileNameCFString, CFRangeMake(0, CFStringGetLength(fileNameCFString)), unicodeFileName); theErr = FSCreateFileUnicode(&theParentRef, CFStringGetLength(fileNameCFString), unicodeFileName, kFSCatInfoNone, NULL, &theFileRef, NULL); CFRelease(fileNameCFString); CFRelease(filePathCFString); CFRelease(fileURL); if (theErr != noErr) { SetLastError(theErr); return INVALID_HANDLE_VALUE; } } if (ulMode == GENERIC_READ) { permission = fsRdPerm; } else { if (ulMode == GENERIC_WRITE) { permission = fsWrPerm; } else { permission = fsRdWrPerm; } } theErr = FSOpenDFCompat(&theFileRef, permission, &fileRef); SetLastError(theErr); if (theErr == noErr) { return (HANDLE)(int)fileRef; } else { return INVALID_HANDLE_VALUE; } }