Because my application deals with a small number of documents -- most users will have only one, and because these documents have "agents" associated with them and are often not edited, I want my app to warn the user immediately upon opening a document that is in the Trash, instead of the default Cocoa behavior which is to open it and complain later only if the user attempts to save changes.

Unfortunately, the correct way to determine if a file is in a special directory, using Folder Manager function FSDetermineIfRefIsEnclosedByFolder(), does not seem able to determine whether or not a path that I get from the url passed to -[NSDocument readFromURL:ofType:error:] is temporary. The first problem is that Cocoa apparently copies the file to a temporary directory, something like
     /private/var/folders/PR/PRtZlutkFa82jPnfdYcUUk+++TI/-Tmp-/
before opening it, so this path is indeed "not in the trash".

OK, so then I try FSDetermineIfRefIsEnclosedByFolder() again, and again, passing kTemporaryFolderType, kChewableItemsFolderType, kTemporaryItemsInCacheDataFolderType, and kWhereToEmptyTrashFolderType in succession. But it in each case, it returns 'false' -- meaning that the file is not in the specified special directory.

So, finally I resorted to the obviously wrong kludge of getting the "Cocoa" temporary directory from NSTemporaryDirectory() and testing whether or not this is a prefix of the given path. Of course, this works.

What's the correct way to do this?

Sincerely,

Jerry Krinock


@interface NSFileManager (SomeMore)

/*!
 @brief    Returns YES if a file or directory exists at a given
 path and is not in a temporary or Trash folder.   Otherwise,
 returns NO.
 */
- (BOOL)fileIsPermanentAtPath:(NSString*)path ;

// ...Other methods

@end


@implementation NSFileManager (SomeMore)

- (BOOL)fileIsPermanentAtPath:(NSString*)path {
// The ^correct^ way to find if a path is in a temporary folder should
    // be to pass its FSRef along with kTemporaryFolderType to
// FSDetermineIfRefIsEnclosedByFolder(). I have done this farther down,
    // but it "just doesn't work" to find paths which are in the
    // temporary directory that Cocoa uses, something like:
    //    /private/var/folders/PR/PRtZlutkFa82jPnfdYcUUk+++TI/-Tmp-/
// So, to work around that I first get the current ^Cocoa^ temporary // directory and see if the given path is in there, with or without the
    // "/private" symbolic link
    NSString* cocoaTempDir = NSTemporaryDirectory() ;
    if ([path hasPrefix:cocoaTempDir]) {
        return NO ;
    }
cocoaTempDir = [@"/private" stringByAppendingPathComponent:cocoaTempDir] ;
    if ([path hasPrefix:cocoaTempDir]) {
        return NO ;
    }

    FSRef fsRef;
    OSStatus err = paramErr ;
    if (path) {
        err = FSPathMakeRef(
                            (UInt8*)[path UTF8String],
                            &fsRef,
                            NULL) ;
        // If file does not exist, the above will return -43 fnfErr
        // So we will skip to the end with ok = NO.
    }

    if (err == noErr) {
        Boolean result ;

        FSDetermineIfRefIsEnclosedByFolder (
                                            0,
                                            kTrashFolderType,
                                            &fsRef,
                                            &result
                                            ) ;
// Note: FSDetermineIfRefIsEnclosedByFolder will return a -35 nsvErr // (no such volume) if the fsRef given in the third argument is not // in the specified folder. Probably that is because it is iterating // through all possible volumes that match the specification given in the // first parameter, 0, which means "all volumes", and the last one it tried // was something that didn't exist, maybe an OS9/Classic volume.
        // Seems like a bug to me.  But anyhow, we ignore it.
        if (result == true) {
            return NO ;
        }

        FSDetermineIfRefIsEnclosedByFolder (
                                            0,
                                            kTemporaryFolderType,
                                            &fsRef,
                                            &result
                                            ) ;
        if (result == true) {
            return NO ;
        }

        err = FSDetermineIfRefIsEnclosedByFolder (
                                                  0,
kWhereToEmptyTrashFolderType,
                                                  &fsRef,
                                                  &result
                                                  ) ;
        if (result == true) {
            return NO ;
        }

        FSDetermineIfRefIsEnclosedByFolder (
                                            0,
kTemporaryItemsInCacheDataFolderType,
                                            &fsRef,
                                            &result
                                            ) ;
        if (result == true) {
            return NO ;
        }

        FSDetermineIfRefIsEnclosedByFolder (
                                            0,
                                            kChewableItemsFolderType,
                                            &fsRef,
                                            &result
                                            ) ;
        if (result == true) {
            return NO ;
        }
    }

    return YES ;
}

// ...Other methdods

@end
_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to