BR: macOS - Aliases don't work with juce::File

As mentioned in this thread:

isSymbolicLink on macOS will use the NSFileManager destinationOfSymbolicLinkAtPath to determine whether a juce::File is a symbolic link. In the comment for the function it mentions “or alias” but this isn’t the case, as an alias will simply return nil

Since OSX 10.10 there is a better solution that correctly works with aliases and symbolic links:

static NSString* getFileLink (const String& path)
{
    NSURL* ns = [NSURL URLByResolvingAliasFileAtURL: createNSURLFromFile (path)
                                            options: NSURLBookmarkResolutionWithoutUI
                                              error: nil];

    if ([ns.path compare:juceStringToNS (path)] != NSOrderedSame)
        return ns.path;

    return nil;
}

The NSURL function will return a valid NSURL for a valid path, regardless of whether it is normal file, symbolic link or alias, hence the comparison with the original file path, with the conclusion being -if they are the same, then the file isn’t a link of any kind

This works well for this function, but it doesn’t help with any other juce::File function, as doing stat through the alias path won’t work. The juce::File functions could be retrofit to use the getLinkedTarget function throughout, which would work around that, but it will cause other issues. Such as:
juce::File (aliasPath).getChildFile ("childfile")

Does that return the resolved alias path?

I’m inclined to create a wrapper to avoid changing JUCE code too much, but I was wondering if there was a better solution

3 Likes

I ran into the same issue, thx for posting the code!

1 Like

any plan to fix that ?
if not (or meanwhile) could you please remove ‘alias’ from the doc:

 /** Returns true if this file is a link or alias that can be followed using getLinkedTarget(). */
    bool isSymbolicLink() const;

    /** If this file is a link or alias, this returns the file that it points to.
        If the file isn't actually a link, it'll just return itself.
    */
    File getLinkedTarget() const;
1 Like

I believe the MacOS alias is a Finder only feature. It’s not actually a symlink kind in the file system. That has some enjoying side affects in many different applications.

There is func to check this


FSRef ref;
  OSStatus status = FSPathMakeRef((const UInt8*)file.getFullPathName().toUTF8().getAddress(), &ref, NULL);
  if (status == noErr)
  {
    Boolean folderFlag;
    Boolean wasAliased;
    OSErr err = FSIsAliasFile(&ref, &wasAliased, &folderFlag);
    if ((err == noErr) && (wasAliased))
    {
      AliasHandle aliasHandle = AliasHandleFromAliasFile(&ref);
      FSAliasInfoBitmap bitmap = kFSAliasInfoIsDirectory;
      FSAliasInfo aliasInfo;
      err = FSCopyAliasInfo(aliasHandle, NULL, NULL, NULL, &bitmap, &aliasInfo);
      if (err == noErr)
      {
      }
      else
      {
      }
    }

and


FSRef ref;
  OSStatus status = FSPathMakeRef((const UInt8*)file.getFullPathName().toUTF8().getAddress(), &ref, NULL);
  if (status == noErr)
  {
    Boolean targetIsAFolder;
    Boolean wasAliased;

		OSErr err = ::FSResolveAliasFileWithMountFlags(&ref,  true, &targetIsAFolder, &wasAliased, 0);
    if ( (err == noErr) && (wasAliased) )
    {
      char buffer[1024];
      FSRefMakePath(&ref, (UInt8*)buffer, 1024);
      file = buffer;
    }
  }

Thanks. I just think that it would be useful to have some built-in support for that within juce (so that DirectoryContentsList etc. could work with aliases).
But really, my main point is : remove “alias” from the documentation so that it doesn’t mislead other developers. Improving the doc is a quick and non breaking change.

1 Like