12

我想以编程方式更改使用OSXFUSE(以前称为 MacFUSE)实现的堆叠文件系统的音量图标。图标需要反映已挂载文件系统的状态。

我一直在尝试的方法是将 /.VolumeIcon.icns 的请求映射到应用程序包中的适当图标。然后向文件系统发送实际路径(path)和挂载路径(mountPath)的更改通知。

    [[NSWorkspace sharedWorkspace] noteFileSystemChanged: @"/Volumes"]; 
    [[NSWorkspace sharedWorkspace] noteFileSystemChanged: [mountPath stringByDeletingLastPathComponent]];
    [[NSWorkspace sharedWorkspace] noteFileSystemChanged: mountPath];
    [[NSWorkspace sharedWorkspace] noteFileSystemChanged: [path stringByDeletingLastPathComponent]];
    [[NSWorkspace sharedWorkspace] noteFileSystemChanged: path];

    FNNotifyByPath([[[mountPath stringByDeletingLastPathComponent] dataUsingEncoding:NSUTF8StringEncoding] bytes], kFNDirectoryModifiedMessage, kNilOptions);
    FNNotifyByPath([[[path stringByDeletingLastPathComponent] dataUsingEncoding:NSUTF8StringEncoding] bytes], kFNDirectoryModifiedMessage, kNilOptions);
    FNNotifyByPath([[@"/Volumes" dataUsingEncoding:NSUTF8StringEncoding] bytes], kFNDirectoryModifiedMessage, kNilOptions);

单步调试调试器,我可以看到此代码被命中,但映射 /.VolumeIcon.icns 的代码很少被调用,并且从不响应这些通知。

4

2 回答 2

3

我认为简短的回答是,你不走运。长答案是,虽然 OSXFUSE 项目与 Fuse4X 项目不同,但它们都来自同一个源,Fuse4X 在其常见问题解答中对音量图标有这样的说法:

问 4.1。为什么 Fuse4X 卷显示有“服务器”(或“网络卷”)图标?

答:准确地说,默认情况下,Fuse4X 卷显示为非本地卷,不幸的是,Finder 将其视为“服务器”。关于为什么 Fuse4X 通常将其卷标记为非本地,这是一个很好的问题。有些人认为在基于磁盘的文件系统的情况下,Fuse4X 必须将卷标记为本地。好吧,让我们看看。

要使 vfs 在 Mac OS X 上是本地的,您需要一个“真正的”磁盘设备 - /dev/disk* 样式的节点。在 Fuse4X 的情况下,这样一个真实的磁盘设备节点是有问题的:在挂载时,对于本地卷,内核会自己打开设备节点并将其传递给 Fuse4X。这样做时,内核将确保该设备当前未在使用中(例如,禁止同一设备的多次挂载)。这发生在控制传递给 Fuse4X 并且可以继续安装之前。如果整个文件系统都存在于内核中,这会很好,但在 Fuse4X 的情况下,用户空间文件系统程序也希望(专门)打开磁盘设备。

于 2012-02-14T16:24:41.650 回答
2

看看路径查找器源代码

- (BOOL)setAsCustomIconForVolume:(NString *)path;
{
    FSref FSRefpath = convertoFsref(path);
    // filename for custom icon is ".VolumeIcon.icns"
    NSString *iconPath = [path stringByAppendingPathComponent:@".VolumeIcon.icns"];

    // remove any existing file first.

    [self writeToFile:iconPath];
    FSSetHasCustomIcon(FSRefpath);

    // rebuild volumeList


    return YES;
}
OSErr FSSetHasCustomIcon(
                   const FSRef *ref)
{
    return ( FSChangeFinderFlags(ref, true, kHasCustomIcon) );
}
OSErr FSChangeFinderFlags(
                    const FSRef *ref,
                    Boolean setBits,
                    UInt16 flagBits)
{
    OSErr           result;
    FSCatalogInfo   catalogInfo;
    FSRef           parentRef;

    /* get the current finderInfo */
    result = FSGetCatalogInfo(ref, kFSCatInfoFinderInfo, &catalogInfo, NULL, NULL, &parentRef);
    require_noerr(result, FSGetCatalogInfo);

    /* set or clear the appropriate bits in the finderInfo.finderFlags */
    if ( setBits )
    {
        /* OR in the bits */
        ((FileInfo *)&catalogInfo.finderInfo)->finderFlags |= flagBits;
    }
    else
    {
        /* AND out the bits */
        ((FileInfo *)&catalogInfo.finderInfo)->finderFlags &= ~flagBits;
    }

    /* save the modified finderInfo */
    result = FSSetCatalogInfo(ref, kFSCatInfoFinderInfo, &catalogInfo);
    require_noerr(result, FSSetCatalogInfo);

FSSetCatalogInfo:
FSGetCatalogInfo:

        return ( result );
}  

NTVolumeNotificationMgr
NTIconFamily

于 2012-02-16T10:31:44.650 回答