static OSStatus CFCreateDirectory(FSRef *parentRef, CFStringRef name, FSRef *newRef) { OSStatus result = noErr; HFSUniStr255 uniStr; uniStr.length = CFStringGetLength(name); CFStringGetCharacters(name, CFRangeMake(0, uniStr.length), uniStr.unicode); result = FSMakeFSRefUnicode(parentRef, uniStr.length, uniStr.unicode, kTextEncodingMacRoman, newRef); if (result != noErr) { result = FSCreateDirectoryUnicode(parentRef, uniStr.length, uniStr.unicode, 0, NULL, newRef, NULL, NULL); } return result; }
void myCreateFolder(t_mkdir, t_symbol *newfoldername) // short CreateFolder(const FSRef parentFolder, const CFStringRef folderName) { OSErr myerr; long len; short path; char name[256]; char inname[2048]; char name[2048]; char parentname[2048]; FSSpec fs; CFStringRef str; CFURLRef url; HFSUniStr255 folderNameU; path_nameconform(inname, newfoldername->s_name, PATH_STYLE_NATIVE, PATH_TYPE_ABSOLUTE); len = strlen(inname); strrchr(); filename = strrchr(name, '/') + 1; if (!path_topathname(path, "", inname)) { // check if path alreay exists path_nameconform(outname, natname, PATH_STYLE_NATIVE, PATH_TYPE_ABSOLUTE); path_tospec(0, natname, &fs); str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII); folderNameU.length = (UInt16) CFStringGetLength(str); CFStringGetCharacters(folderName, CFRangeMake(0, folderNameU.length), folderNameU.unicode); // see if it already exists? myerr = FSMakeFSRefUnicode(&parentname, folderNameU.length,folderNameU.unicode, kTextEncodingUnicodeDefault, NULL); // should now verify that is, in fact, a folder. if (myerr != noErr) { // no, so try to create it. myerr = FSCreateDirectoryUnicode(&parentFolder, folderNameU.length, folderNameU.unicode, kFSCatInfoNone, NULL, NULL, NULL, NULL); } return myerr; } }
static OSErr FindSNESFolder(FSRef *folderRef, char *folderPath, const char *folderName) { OSStatus err; CFURLRef burl, purl; CFStringRef fstr; FSRef pref; UniChar buffer[PATH_MAX + 1]; Boolean r; fstr = CFStringCreateWithCString(kCFAllocatorDefault, folderName, CFStringGetSystemEncoding()); CFStringGetCharacters(fstr, CFRangeMake(0, CFStringGetLength(fstr)), buffer); burl = CFBundleCopyBundleURL(CFBundleGetMainBundle()); purl = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, burl); r = CFURLGetFSRef(purl, &pref); err = FSMakeFSRefUnicode(&pref, CFStringGetLength(fstr), buffer, kTextEncodingUnicodeDefault, folderRef); if (err == dirNFErr || err == fnfErr) { err = FSCreateDirectoryUnicode(&pref, CFStringGetLength(fstr), buffer, kFSCatInfoNone, nil, folderRef, nil, nil); if (err == noErr) AddFolderIcon(folderRef, folderName); } if (err != noErr && !folderWarning) { AppearanceAlert(kAlertCautionAlert, kFolderFail, kFolderHint); folderWarning = true; } else err = FSRefMakePath(folderRef, (unsigned char *) folderPath, PATH_MAX); CFRelease(purl); CFRelease(burl); CFRelease(fstr); return err; }
static bool _q_isMacHidden(const QString &path) { OSErr err = noErr; FSRef fsRef; #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { err = FSPathMakeRefWithOptions(reinterpret_cast<const UInt8 *>(QFile::encodeName(QDir::cleanPath(path)).constData()), kFSPathMakeRefDoNotFollowLeafSymlink, &fsRef, 0); } else #endif { QFileInfo fi(path); FSRef parentRef; err = FSPathMakeRef(reinterpret_cast<const UInt8 *>(fi.absoluteDir().absolutePath().toUtf8().constData()), &parentRef, 0); if (err == noErr) { QString fileName = fi.fileName(); err = FSMakeFSRefUnicode(&parentRef, fileName.length(), reinterpret_cast<const UniChar *>(fileName.unicode()), kTextEncodingUnknown, &fsRef); } } if (err != noErr) return false; FSCatalogInfo catInfo; err = FSGetCatalogInfo(&fsRef, kFSCatInfoFinderInfo, &catInfo, NULL, NULL, NULL); if (err != noErr) return false; FileInfo * const fileInfo = reinterpret_cast<FileInfo*>(&catInfo.finderInfo); bool result = (fileInfo->finderFlags & kIsInvisible); return result; }
static OSStatus FindCustomFolder (FSRef *folderRef, char *folderPath, const char *folderName) { OSStatus err; CFStringRef fstr; FSRef pref; UniChar buffer[PATH_MAX + 1]; char s[PATH_MAX + 1]; if (saveFolderPath == NULL) return (-1); err = CFStringGetCString(saveFolderPath, s, PATH_MAX, kCFStringEncodingUTF8) ? noErr : -1; if (err == noErr) err = FSPathMakeRef((unsigned char *) s, &pref, NULL); if (err) return (err); fstr = CFStringCreateWithCString(kCFAllocatorDefault, folderName, CFStringGetSystemEncoding()); CFStringGetCharacters(fstr, CFRangeMake(0, CFStringGetLength(fstr)), buffer); err = FSMakeFSRefUnicode(&pref, CFStringGetLength(fstr), buffer, kTextEncodingUnicodeDefault, folderRef); if (err == dirNFErr || err == fnfErr) { err = FSCreateDirectoryUnicode(&pref, CFStringGetLength(fstr), buffer, kFSCatInfoNone, NULL, folderRef, NULL, NULL); if (err == noErr) AddFolderIcon(folderRef, folderName); } if (err == noErr) err = FSRefMakePath(folderRef, (unsigned char *) folderPath, PATH_MAX); CFRelease(fstr); return (err); }
int doItTheHardWay(unsigned char *pathString,FSSpec *spec,Boolean noDrillDown) { char *token; Str255 lookup; UniChar buffer[1024]; Boolean firstTime=true; OSErr err; long parentDirectory,tokenLength; FSRef parentFSRef,childFSRef; CFStringRef aLevel; FSSpec fix; token = strtok((char*) pathString,":"); if (token == 0) return -1; while (token) { tokenLength = strlen(token); if (firstTime) {// Mmm will crash if volume name is 255 characters, unlikely strncpy((char*) lookup+1,(char*) token,tokenLength); lookup[0] = tokenLength+1; lookup[lookup[0]] = ':'; firstTime = false; err = FSMakeFSSpecCompat(spec->vRefNum,spec->parID, lookup, spec); if (err != noErr) return err; err = FSpMakeFSRef(spec,&parentFSRef); if (err != noErr) return err; } else { fix = *spec; fix.name[0] = 0; err = FSpMakeFSRef(&fix,&parentFSRef); if (err != noErr) return err; aLevel = CFStringCreateWithCString(kCFAllocatorDefault,token,gCurrentVMEncoding); if (aLevel == nil) return -1000; tokenLength = CFStringGetLength(aLevel); CFStringGetCharacters(aLevel,CFRangeMake(0,tokenLength),buffer); err = FSMakeFSRefUnicode(&parentFSRef,tokenLength,buffer,gCurrentVMEncoding,&childFSRef); if (err != noErr) { CFStringGetPascalString(aLevel,spec->name,64,gCurrentVMEncoding); CFRelease(aLevel); token = strtok(nil,":"); if (token == nil) return err; else return -1001; } CFRelease(aLevel); parentFSRef = childFSRef; err = FSGetCatalogInfo (&parentFSRef,kFSCatInfoNone,nil,nil,spec,nil); if (err != noErr) return err; } fetchFileSpec(spec,spec->name,&parentDirectory); token = strtok(nil,":"); } if (noDrillDown) spec->parID = parentDirectory; return noErr; }
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; }
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; }
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); }
OSStatus BeginSave( NavDialogRef inDialog, NavReplyRecord* outReply, FSRef* outFileRef ) { OSStatus status = paramErr; AEDesc dirDesc; AEKeyword keyword; CFIndex len; require( outReply, Return ); require( outFileRef, Return ); status = NavDialogGetReply( inDialog, outReply ); nrequire( status, Return ); status = AEGetNthDesc( &outReply->selection, 1, typeWildCard, &keyword, &dirDesc ); nrequire( status, DisposeReply ); len = CFStringGetLength( outReply->saveFileName ); if ( dirDesc.descriptorType == typeFSRef ) { const UInt32 kMaxNameLen = 255; FSRef dirRef; UniChar name[ kMaxNameLen ]; if ( len > kMaxNameLen ) { len = kMaxNameLen; } status = AEGetDescData( &dirDesc, &dirRef, sizeof( dirRef )); nrequire( status, DisposeDesc ); CFStringGetCharacters( outReply->saveFileName, CFRangeMake( 0, len ), &name[0] ); status = FSMakeFSRefUnicode( &dirRef, len, &name[0], GetApplicationTextEncoding(), outFileRef ); if (status == fnfErr ) { // file is not there yet - create it and return FSRef status = FSCreateFileUnicode( &dirRef, len, &name[0], 0, NULL, outFileRef, NULL ); } else { // looks like file is there. Just make sure there is no error nrequire( status, DisposeDesc ); } } else if ( dirDesc.descriptorType == typeFSS ) { FSSpec theSpec; status = AEGetDescData( &dirDesc, &theSpec, sizeof( FSSpec )); nrequire( status, DisposeDesc ); if ( CFStringGetPascalString( outReply->saveFileName, &(theSpec.name[0]), sizeof( StrFileName ), GetApplicationTextEncoding())) { status = FSpMakeFSRef(&theSpec, outFileRef); nrequire( status, DisposeDesc ); status = FSpCreate( &theSpec, 0, 0, smSystemScript ); nrequire( status, DisposeDesc ); } else { status = bdNamErr; nrequire( status, DisposeDesc ); } } DisposeDesc: AEDisposeDesc( &dirDesc ); DisposeReply: if ( status != noErr ) { NavDisposeReply( outReply ); } Return: return status; }