static OSErr FSSetFInfo(const FSRef* ref, FInfo *fInfo) { FSCatalogInfo cinfo; *(FInfo*)cinfo.finderInfo = *fInfo; OSErr err = FSSetCatalogInfo(ref, kFSCatInfoFinderInfo, &cinfo); return err; }
int dir_SetMacFileTypeAndCreator(char *filename, sqInt filenameSize, char *fType, char *fCreator) { /* Set the Macintosh type and creator of the given file. */ /* Note: On other platforms, this is just a noop. */ FSCatalogInfo catInfo; FInfo finderInfo; OSErr err; FSRef theFSRef; char fileNameBuffer[DOCUMENT_NAME_SIZE+1]; int bytes; bytes = ioFilenamefromStringofLengthresolveAliasesRetry(fileNameBuffer,filename, filenameSize, true, true); if (bytes == 0) return false; if (getFInfo(fileNameBuffer,&catInfo,kCFStringEncodingUTF8) != noErr) return false; memcpy(&finderInfo,&catInfo.finderInfo,16); finderInfo.fdType = CFSwapInt32HostToBig(*((int *) fType)); finderInfo.fdCreator = CFSwapInt32HostToBig(*((int *) fCreator)); memcpy(&catInfo.finderInfo,&finderInfo,16); err = getFSRef(fileNameBuffer,&theFSRef,kCFStringEncodingUTF8); if (err != 0) return err; err = FSSetCatalogInfo (&theFSRef,kFSCatInfoFinderInfo,&catInfo); return true; }
int main(int argc, char **argv) { if (argc < 2) { printf("Usage: %s <save file>\n", argv[0]); printf("Applies the creator and type codes so the save can be used\n"); printf("by the original interpreter.\n"); return 0; } uint32 creator, type; // First, let's open our file to make sure it's a pegasus save // Also, we're going to extract what type we need to set (for the correct disc) try { Common::File file(argv[1], "rb"); // Let's make sure the user already gunzip'd the file uint16 gzipTest = file.readUint16BE(); if (gzipTest == 0x1F8B) { printf("Please gunzip the save file first\n"); return 1; } creator = (gzipTest << 16) | file.readUint16BE(); // Too lazy to seek back :P type = file.readUint32BE(); if (creator != kPegasusCreator) { printf("Failed to find pegasus creator in save file\n"); return 1; } if (type != kPegasusDisc1 && type != kPegasusDisc2 && type != kPegasusDisc3 && type != kPegasusDisc4) { printf("Invalid pegasus save type in save file\n"); return 1; } } catch (Common::FileException e) { printf("File error: '%s'\n", e.what()); return 1; } FSCatalogInfo catInfo; FSRef ref; if (!FSPathMakeRef((const UInt8 *)argv[1], &ref, false)) { FSGetCatalogInfo(&ref, kFSCatInfoFinderInfo, &catInfo, 0, 0, 0); FileInfo *info = (FileInfo *)catInfo.finderInfo; info->fileCreator = creator; info->fileType = type; FSSetCatalogInfo(&ref, kFSCatInfoFinderInfo, &catInfo); } else { printf("Failed to use File Manager to open the file\n"); return 1; } printf("Success!\n"); return 0; }
void HLFileSystemObject::SetCreator(UInt32 inCreator) { // get the current Finder info from the catalog FSCatalogInfo theInfo; OSStatus theError = FSGetCatalogInfo(&mFSRef, kFSCatInfoFinderInfo, &theInfo, NULL, NULL, NULL); ThrowIfError(theError, CAException(theError), "HLFileSystemObject::SetType: couldn't get the catalog information"); // update just the creator FInfo* theFinderInfo = reinterpret_cast<FInfo*>(&theInfo.finderInfo); theFinderInfo->fdCreator = inCreator; // write it back out theError = FSSetCatalogInfo(&mFSRef, kFSCatInfoFinderInfo, &theInfo); ThrowIfError(theError, CAException(theError), "HLFileSystemObject::SetType: couldn't set the catalog information"); }
void ChangeTypeAndCreator (const char *path, OSType type, OSType creator) { OSStatus err; FSRef ref; err = FSPathMakeRef((unsigned char *) path, &ref, NULL); if (err == noErr) { FSCatalogInfo catinfo; err = FSGetCatalogInfo(&ref, kFSCatInfoFinderInfo, &catinfo, NULL, NULL, NULL); if (err == noErr) { ((FileInfo *) &catinfo.finderInfo)->fileCreator = creator; ((FileInfo *) &catinfo.finderInfo)->fileType = type; err = FSSetCatalogInfo(&ref, kFSCatInfoFinderInfo, &catinfo); } } }
/** * Sets the @c OSType of a given file to @c 'Midi', but only if it's not * already set. * * @param *ref A @c FSSpec structure referencing a file. */ static void SetMIDITypeIfNeeded(const FSRef *ref) { FSCatalogInfo catalogInfo; assert(ref); if (noErr != FSGetCatalogInfo(ref, kFSCatInfoNodeFlags | kFSCatInfoFinderInfo, &catalogInfo, NULL, NULL, NULL)) return; if (!(catalogInfo.nodeFlags & kFSNodeIsDirectoryMask)) { FileInfo * const info = (FileInfo *) catalogInfo.finderInfo; if (info->fileType != MIDI_TYPE && !(info->finderFlags & kIsAlias)) { OSErr e; info->fileType = MIDI_TYPE; e = FSSetCatalogInfo(ref, kFSCatInfoFinderInfo, &catalogInfo); if (e == noErr) { DEBUG(driver, 3, "qtmidi: changed filetype to 'Midi'"); } else { DEBUG(driver, 0, "qtmidi: changing filetype to 'Midi' failed - error %d", e); } } } }
void filecontainer_doopen(t_filecontainer *x, t_symbol *arg) { t_atom a[4]; int err = 0; char filename[256]; short path; t_fourcc outtype = 0; t_fourcc type = 'cO0p'; #ifdef MAC_VERSION char *temppath; FSRef ref; Boolean isDir; FSCatalogInfo catalogInfo; #else // WIN_VERSION char temppath[512]; #endif char fullpath[512]; t_object *result = NULL; t_object *result2 = NULL; char **record = NULL; // sqlite records char **record2 = NULL; // sqlite records t_filehandle file_handle; t_ptr_size len = 0; char *blob; char sql[512]; if(!arg || !arg->s_name[0]) { if(open_dialog(filename, &path, &outtype, NULL, -1)) // Returns 0 if successful return; } else { t_fourcc typelist[1]; typelist[0] = 'cO0p'; strcpy(filename, arg->s_name); path = 0; locatefile_extended(filename, &path, &type, typelist, 0); } path_topotentialname(path, filename, fullpath, 0); #ifdef MAC_VERSION temppath = strchr(fullpath, ':'); temppath += 1; #else // WIN_VERSION path_nameconform(fullpath, temppath, PATH_STYLE_NATIVE_WIN, PATH_TYPE_ABSOLUTE); #endif x->name = gensym(temppath); // Create our temp folder for extracted files filecontainer_gettemppath(x); // Create the SQLite instance atom_setsym(&a[0], gensym("@rambased")); atom_setlong(&a[1], 0); atom_setsym(&a[2], gensym("@db")); atom_setsym(&a[3], x->name); x->sqlite = object_new_typed(CLASS_NOBOX, _sym_sqlite, 4, a); // Operate on the open DB if(x->sqlite) { object_method(x->sqlite, ps_starttransaction); object_method(x->sqlite, _sym_execstring, TABLEDEF_FILES, NULL); object_method(x->sqlite, _sym_execstring, TABLEDEF_ATTRS, NULL); object_method(x->sqlite, _sym_execstring, "UPDATE files SET valid = 1", NULL); object_method(x->sqlite, _sym_execstring, "SELECT file_id, filename, moddate FROM files", &result); while(record = (char **)object_method(result, _sym_nextrecord)) { // Here we check for the optional 'platform' attr for this file. // If a flag exists for the other platform, but not for the current platform, then we ignore this file. #ifdef MAC_VERSION sprintf(sql, "SELECT file_id_ext FROM attrs \ WHERE attr_name = 'platform' AND attr_value = 'windows' AND file_id_ext = %s ", record[0]); object_method(x->sqlite, _sym_execstring, sql, &result2); record2 = (char **)object_method(result2, _sym_nextrecord); if(record2) { sprintf(sql, "SELECT file_id_ext FROM attrs \ WHERE attr_name = 'platform' AND attr_value = 'mac' AND file_id_ext = %s ", record[0]); object_method(x->sqlite, _sym_execstring, sql, &result2); record2 = (char **)object_method(result2, _sym_nextrecord); if(!record2) { sprintf(sql, "UPDATE files SET valid = 0 WHERE file_id = %s ", record[0]); object_method(x->sqlite, _sym_execstring, sql, NULL); continue; } } #else // WIN_VERSION snprintf(sql, 512, "SELECT file_id_ext FROM attrs \ WHERE attr_name = 'platform' AND attr_value = 'mac' AND file_id_ext = %s ", record[0]); object_method(x->sqlite, _sym_execstring, sql, &result2); record2 = (char **)object_method(result2, _sym_nextrecord); if(record2) { snprintf(sql, 512, "SELECT file_id_ext FROM attrs \ WHERE attr_name = 'platform' AND attr_value = 'windows' AND file_id_ext = %s ", record[0]); object_method(x->sqlite, _sym_execstring, sql, &result2); record2 = (char **)object_method(result2, _sym_nextrecord); if(!record2) { snprintf(sql, 512, "UPDATE files SET valid = 0 WHERE file_id = %s ", record[0]); object_method(x->sqlite, _sym_execstring, sql, NULL); continue; } } #endif // At this point we have a file (record[0]), and we have determined that it is indeed a file we want to cache // So cache it to a new file in our temp path err = path_createsysfile(record[1], x->temp_path, type, &file_handle); if(err) { // Handle any errors that occur object_error((t_object *)x, "%s - error %d creating file", filename, err); } else { snprintf(sql, 512, "SELECT content FROM files WHERE file_id = %s", record[0]); object_method(x->sqlite, ps_getblob, sql, &blob, &len); err = sysfile_write(file_handle, &len, blob); if(err) { object_error((t_object *)x, "sysfile_write error (%d)", err); } } err = sysfile_seteof(file_handle, len); if(err) { object_error((t_object *)x, "%s - error %d setting EOF", filename, err); } sysfile_close(file_handle); // close file reference sysmem_freeptr(blob); blob = NULL; // Set the moddate #ifdef MAC_VERSION // FSCatalogInfo catalogInfo; // Boolean status; CFGregorianDate gdate; CFAbsoluteTime abstime; CFTimeZoneRef tz; UTCDateTime utc; sscanf(record[2], "%4ld-%02hd-%02hd %02hd:%02hd:%02lf", &gdate.year, (signed short*)&gdate.month, (signed short*)&gdate.day, (signed short*)&gdate.hour, (signed short*)&gdate.minute, &gdate.second); tz = CFTimeZoneCopySystem(); abstime = CFGregorianDateGetAbsoluteTime(gdate, tz); UCConvertCFAbsoluteTimeToUTCDateTime(abstime, &utc); catalogInfo.contentModDate = utc; strcpy(s_tempstr, x->temp_fullpath->s_name); temppath = strchr(s_tempstr, ':'); temppath++; strcat(temppath, "/"); strcat(temppath, record[1]); FSPathMakeRef((UInt8*)temppath, &ref, &isDir); err = FSSetCatalogInfo(&ref, kFSCatInfoContentMod, &catalogInfo); #else // WIN_VERSION char winpath[512]; HANDLE hFile; FILETIME fileTime; SYSTEMTIME systemTime; sscanf(record[2], "%4lu-%02lu-%02lu %02lu:%02lu:%02lu", &systemTime.wYear, &systemTime.wMonth, &systemTime.wDay, &systemTime.wHour, &systemTime.wMinute, &systemTime.wSecond); err = SystemTimeToFileTime(&systemTime, &fileTime); strcpy(s_tempstr, x->temp_fullpath->s_name); path_nameconform(s_tempstr, winpath, PATH_STYLE_NATIVE_WIN, PATH_TYPE_ABSOLUTE); strcat(winpath, "\\"); strcat(winpath, record[1]); hFile = CreateFile((LPCSTR)winpath , GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if(hFile == INVALID_HANDLE_VALUE) { object_error((t_object *)x, "invalid handle value"); goto out; } err = SetFileTime(hFile, &fileTime, &fileTime, &fileTime); if(err == 0) { err = GetLastError(); object_error((t_object *)x, "Error setting date: %i", err); } CloseHandle(hFile); out: ; #endif } object_method(x->sqlite, ps_endtransaction); }
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 void AddFolderIcon (FSRef *fref, const char *folderName) { OSStatus err; FSCatalogInfo fcat, icat; FSRef bref, iref; CFStringRef str; CFURLRef url; IconFamilyHandle family; IconRef icon; HFSUniStr255 fork; Boolean r; SInt16 resf; char name[64]; UniChar iconName[5] = { 'I', 'c', 'o', 'n', '\r' }; strcpy(name, "folder_"); strcat(name, folderName); str = CFStringCreateWithCString(kCFAllocatorDefault, name, CFStringGetSystemEncoding()); if (str) { url = CFBundleCopyResourceURL(CFBundleGetMainBundle(), str, CFSTR("icns"), NULL); if (url) { r = CFURLGetFSRef(url, &bref); if (r) { err = RegisterIconRefFromFSRef('~9X~', 'TEMP', &bref, &icon); if (err == noErr) { err = FSGetResourceForkName(&fork); if (err == noErr) { err = FSCreateResourceFile(fref, 5, iconName, kFSCatInfoNone, NULL, fork.length, fork.unicode, &iref, NULL); if (err == noErr) { err = FSOpenResourceFile(&iref, fork.length, fork.unicode, fsWrPerm, &resf); if (err == noErr) { err = IconRefToIconFamily(icon, kSelectorAllAvailableData, &family); if (err == noErr) { AddResource((Handle) family, 'icns', -16455, "\p"); WriteResource((Handle) family); ReleaseResource((Handle) family); err = FSGetCatalogInfo(&iref, kFSCatInfoFinderInfo, &icat, NULL, NULL, NULL); ((FileInfo *) &icat.finderInfo)->finderFlags |= kIsInvisible; ((FileInfo *) &icat.finderInfo)->fileCreator = 'MACS'; ((FileInfo *) &icat.finderInfo)->fileType = 'icon'; err = FSSetCatalogInfo(&iref, kFSCatInfoFinderInfo, &icat); err = FSGetCatalogInfo(fref, kFSCatInfoFinderInfo, &fcat, NULL, NULL, NULL); ((FolderInfo *) &fcat.finderInfo)->finderFlags |= kHasCustomIcon; ((FolderInfo *) &fcat.finderInfo)->finderFlags &= ~kHasBeenInited; err = FSSetCatalogInfo(fref, kFSCatInfoFinderInfo, &fcat); } CloseResFile(resf); } } }
static PyObject * MacOS_SetCreatorAndType(PyObject *self, PyObject *args) { ResType creator, type; FSRef ref; FileInfo* finfo; OSErr err; FSCatalogInfo cataloginfo; if (!PyArg_ParseTuple(args, "O&O&O&", PyMac_GetFSRef, &ref, PyMac_GetOSType, &creator, PyMac_GetOSType, &type)) { #ifndef __LP64__ /* Try to handle FSSpec arguments, for backward compatibility */ FSSpec fss; FInfo info; if (!PyArg_ParseTuple(args, "O&O&O&", PyMac_GetFSSpec, &fss, PyMac_GetOSType, &creator, PyMac_GetOSType, &type)) return NULL; if ((err = FSpGetFInfo(&fss, &info)) != noErr) return PyErr_Mac(MacOS_Error, err); info.fdCreator = creator; info.fdType = type; if ((err = FSpSetFInfo(&fss, &info)) != noErr) return PyErr_Mac(MacOS_Error, err); Py_INCREF(Py_None); return Py_None; #else /* __LP64__ */ return NULL; #endif /* __LP64__ */ } err = FSGetCatalogInfo(&ref, kFSCatInfoFinderInfo|kFSCatInfoNodeFlags, &cataloginfo, NULL, NULL, NULL); if (err != noErr) { PyErr_Mac(MacOS_Error, err); return NULL; } if ((cataloginfo.nodeFlags & kFSNodeIsDirectoryMask) != 0) { /* Directory: doesn't have type/creator info. * * The specific error code is for backward compatibility with * earlier versions. */ PyErr_Mac(MacOS_Error, fnfErr); return NULL; } finfo = (FileInfo*)&(cataloginfo.finderInfo); finfo->fileCreator = creator; finfo->fileType = type; err = FSSetCatalogInfo(&ref, kFSCatInfoFinderInfo, &cataloginfo); if (err != noErr) { PyErr_Mac(MacOS_Error, fnfErr); return NULL; } Py_INCREF(Py_None); return Py_None; }
OSErr FSExchangeObjectsEmulate(const FSRef *sourceRef, const FSRef *destRef, FSRef *newSourceRef, FSRef *newDestRef) { enum { /* get all settable info except for mod dates, plus the volume refNum and parent directory ID */ kGetCatInformationMask = (kFSCatInfoSettableInfo | kFSCatInfoVolume | kFSCatInfoParentDirID) & ~(kFSCatInfoContentMod | kFSCatInfoAttrMod), /* set everything possible except for mod dates */ kSetCatinformationMask = kFSCatInfoSettableInfo & ~(kFSCatInfoContentMod | kFSCatInfoAttrMod) }; OSErr result; FSCatalogInfo sourceCatalogInfo; /* source file's catalog information */ FSCatalogInfo destCatalogInfo; /* destination file's catalog information */ HFSUniStr255 sourceName; /* source file's Unicode name */ HFSUniStr255 destName; /* destination file's Unicode name */ FSRef sourceCurrentRef; /* FSRef to current location of source file throughout this function */ FSRef destCurrentRef; /* FSRef to current location of destination file throughout this function */ FSRef sourceParentRef; /* FSRef to parent directory of source file */ FSRef destParentRef; /* FSRef to parent directory of destination file */ HFSUniStr255 sourceUniqueName; /* unique name given to source file while exchanging it with destination */ HFSUniStr255 destUniqueName; /* unique name given to destination file while exchanging it with source */ long theSeed; /* the seed for generating unique names */ Boolean sameParentDirs; /* true if source and destinatin parent directory is the same */ /* check parameters */ require_action((NULL != newSourceRef) && (NULL != newDestRef), BadParameter, result = paramErr); /* output refs and current refs = input refs to start with */ memcpy(newSourceRef, sourceRef, sizeof(FSRef)); memcpy(&sourceCurrentRef, sourceRef, sizeof(FSRef)); memcpy(newDestRef, destRef, sizeof(FSRef)); memcpy(&destCurrentRef, destRef, sizeof(FSRef)); /* Note: The compatibility case won't work for files with *Btree control blocks. */ /* Right now the only *Btree files are created by the system. */ /* get all catalog information and Unicode names for each file */ result = FSGetCatalogInfo(&sourceCurrentRef, kGetCatInformationMask, &sourceCatalogInfo, &sourceName, NULL, &sourceParentRef); require_noerr(result, SourceFSGetCatalogInfoFailed); result = FSGetCatalogInfo(&destCurrentRef, kGetCatInformationMask, &destCatalogInfo, &destName, NULL, &destParentRef); require_noerr(result, DestFSGetCatalogInfoFailed); /* make sure source and destination are on same volume */ require_action(sourceCatalogInfo.volume == destCatalogInfo.volume, NotSameVolume, result = diffVolErr); /* make sure both files are *really* files */ require_action((0 == (sourceCatalogInfo.nodeFlags & kFSNodeIsDirectoryMask)) && (0 == (destCatalogInfo.nodeFlags & kFSNodeIsDirectoryMask)), NotAFile, result = notAFileErr); /* generate 2 names that are unique in both directories */ theSeed = 0x4a696d4c; /* a fine unlikely filename */ result = GenerateUniqueHFSUniStr(&theSeed, &sourceParentRef, &destParentRef, &sourceUniqueName); require_noerr(result, GenerateUniqueHFSUniStr1Failed); result = GenerateUniqueHFSUniStr(&theSeed, &sourceParentRef, &destParentRef, &destUniqueName); require_noerr(result, GenerateUniqueHFSUniStr2Failed); /* rename sourceCurrentRef to sourceUniqueName */ result = FSRenameUnicode(&sourceCurrentRef, sourceUniqueName.length, sourceUniqueName.unicode, kTextEncodingUnknown, newSourceRef); require_noerr(result, FSRenameUnicode1Failed); memcpy(&sourceCurrentRef, newSourceRef, sizeof(FSRef)); /* rename destCurrentRef to destUniqueName */ result = FSRenameUnicode(&destCurrentRef, destUniqueName.length, destUniqueName.unicode, kTextEncodingUnknown, newDestRef); require_noerr(result, FSRenameUnicode2Failed); memcpy(&destCurrentRef, newDestRef, sizeof(FSRef)); /* are the source and destination parent directories the same? */ sameParentDirs = ( sourceCatalogInfo.parentDirID == destCatalogInfo.parentDirID ); if ( !sameParentDirs ) { /* move source file to dest parent directory */ result = FSMoveObject(&sourceCurrentRef, &destParentRef, newSourceRef); require_noerr(result, FSMoveObject1Failed); memcpy(&sourceCurrentRef, newSourceRef, sizeof(FSRef)); /* move dest file to source parent directory */ result = FSMoveObject(&destCurrentRef, &sourceParentRef, newDestRef); require_noerr(result, FSMoveObject2Failed); memcpy(&destCurrentRef, newDestRef, sizeof(FSRef)); } /* At this point, the files are in their new locations (if they were moved). */ /* The source file is named sourceUniqueName and is in the directory referred to */ /* by destParentRef. The destination file is named destUniqueName and is in the */ /* directory referred to by sourceParentRef. */ /* give source file the dest file's catalog information except for mod dates */ result = FSSetCatalogInfo(&sourceCurrentRef, kSetCatinformationMask, &destCatalogInfo); require_noerr(result, FSSetCatalogInfo1Failed); /* give dest file the source file's catalog information except for mod dates */ result = FSSetCatalogInfo(&destCurrentRef, kSetCatinformationMask, &sourceCatalogInfo); require_noerr(result, FSSetCatalogInfo2Failed); /* rename source file with dest file's name */ result = FSRenameUnicode(&sourceCurrentRef, destName.length, destName.unicode, destCatalogInfo.textEncodingHint, newSourceRef); require_noerr(result, FSRenameUnicode3Failed); memcpy(&sourceCurrentRef, newSourceRef, sizeof(FSRef)); /* rename dest file with source file's name */ result = FSRenameUnicode(&destCurrentRef, sourceName.length, sourceName.unicode, sourceCatalogInfo.textEncodingHint, newDestRef); require_noerr(result, FSRenameUnicode4Failed); /* we're done with no errors, so swap newSourceRef and newDestRef */ memcpy(newSourceRef, newDestRef, sizeof(FSRef)); memcpy(newDestRef, &sourceCurrentRef, sizeof(FSRef)); return ( result ); /**********************/ /* If there are any failures while emulating FSExchangeObjects, attempt to reverse any steps */ /* already taken. In any case, newSourceRef and newDestRef will refer to the files in whatever */ /* state and location they ended up in so that both files can be found by the calling code. */ FSRenameUnicode4Failed: /* attempt to rename source file to sourceUniqueName */ if ( noErr == FSRenameUnicode(&sourceCurrentRef, sourceUniqueName.length, sourceUniqueName.unicode, kTextEncodingUnknown, newSourceRef) ) { memcpy(&sourceCurrentRef, newSourceRef, sizeof(FSRef)); } FSRenameUnicode3Failed: /* attempt to restore dest file's catalog information */ verify_noerr(FSSetCatalogInfo(&destCurrentRef, kFSCatInfoSettableInfo, &destCatalogInfo)); FSSetCatalogInfo2Failed: /* attempt to restore source file's catalog information */ verify_noerr(FSSetCatalogInfo(&sourceCurrentRef, kFSCatInfoSettableInfo, &sourceCatalogInfo)); FSSetCatalogInfo1Failed: if ( !sameParentDirs ) { /* attempt to move dest file back to dest directory */ if ( noErr == FSMoveObject(&destCurrentRef, &destParentRef, newDestRef) ) { memcpy(&destCurrentRef, newDestRef, sizeof(FSRef)); } } FSMoveObject2Failed: if ( !sameParentDirs ) { /* attempt to move source file back to source directory */ if ( noErr == FSMoveObject(&sourceCurrentRef, &sourceParentRef, newSourceRef) ) { memcpy(&sourceCurrentRef, newSourceRef, sizeof(FSRef)); } } FSMoveObject1Failed: /* attempt to rename dest file to original name */ verify_noerr(FSRenameUnicode(&destCurrentRef, destName.length, destName.unicode, destCatalogInfo.textEncodingHint, newDestRef)); FSRenameUnicode2Failed: /* attempt to rename source file to original name */ verify_noerr(FSRenameUnicode(&sourceCurrentRef, sourceName.length, sourceName.unicode, sourceCatalogInfo.textEncodingHint, newSourceRef)); FSRenameUnicode1Failed: GenerateUniqueHFSUniStr2Failed: GenerateUniqueHFSUniStr1Failed: NotAFile: NotSameVolume: DestFSGetCatalogInfoFailed: SourceFSGetCatalogInfoFailed: BadParameter: return ( result ); }