Detecting when a folderitem is a symbolic link

Hello,

When dealing with folderitems, there’s one case where one can get “unexpected errors”; that’s with a symbolic link.

I’m experiencing this right now:
item as FolderItem is a symbolic link for which the original item is a folder.

item.Directory and item.IsFolder both return “false”, so my code naturally tries to read the file as a binary stream, thinking it’s a file. This raises an IOException with code 21 (found a folder instead of a file).

However, the relevant folderitem properties don’t help figuring out if “item” is a symbolic link. Here are the values for “item”:
Alias/IsAlias=true: with a true alias, one can still read its content, including the resource fork if the original item is stored there, so it doesn’t withdraw reading item as a file
Directory/IsDirectory=false: I’d be tempted to be allowed to read something that is “not a folder” if I can’t know it’s a symbolic link otherwise
IsReadable=True/IsWriteable=False: fine for reading, no problem.
Length=26: if the item has a length, it contains data (this is the actual path to the original item, but is still data)! Why on earth would a specific item with proper permissions and having content not be readable?
Name=Resources: no extension identifies a symbolic link; same principle for paths

Actually, the MacType could be used to identify a symbolic link (it’s “slnk”), but Xojo removed MacType and MacCreator; I knew those 2 properties were still useful (so, please, add them back)…
Other built-in properties are irrelevant here.

I’m sure there’s a terminal command to tell whether an item is a symbolic link; I’ve not searched, but it’s obvious. That’s not my point. When iterating thru several items, invoking a shell multiplies needed time.

This is a 2 parts problem:
1: we can’t easily know in Xojo if an item is a symbolic link, other than invoking a shell (it seems)
2: Xojo’s folderitem refers to the link (length=26, alias=true, etc.) while once you try to read with a binary stream, it tries to read the original item (which “becomes” a folder, invalid for reading).

Am I missing the obvious?

The length of a symbolic link file is the length of the path stored inside, so 26 bytes is just an example, but the maximum length is probably something like 1024 or 4096 (PATH_MAX constant), not sure exact value in current MacOS.

The NSFileManagerMBS class in MBS Xojo Plugins has a few methods for this:

method createSymbolicLink(file as folderitem, destFile as folderitem, byref error as NSErrorMBS) as boolean
method createSymbolicLink(path as string, destPath as string, byref error as NSErrorMBS) as boolean
method destinationOfSymbolicLinkAtPath(file as folderitem, byref error as NSErrorMBS) as string
method destinationOfSymbolicLinkAtPath(path as string, byref error as NSErrorMBS) as string

Yes, the properties written above are specific to the item I was observing (I’ve noted “this is the actual path to the original item, but is still data”, so there’s no confusion at this point).
The maximum length won’t help me identifying whether the item is a symbolic link either :wink:

[quote=488014:@Christian Schmitz]The NSFileManagerMBS class in MBS Xojo Plugins has a few methods for this:

method createSymbolicLink(file as folderitem, destFile as folderitem, byref error as NSErrorMBS) as boolean
method createSymbolicLink(path as string, destPath as string, byref error as NSErrorMBS) as boolean
method destinationOfSymbolicLinkAtPath(file as folderitem, byref error as NSErrorMBS) as string
method destinationOfSymbolicLinkAtPath(path as string, byref error as NSErrorMBS) as string[/quote]
Thank you. Are these methods, especially destinationOfSymbolicLinkAtPath, suitable for iteration, even for huge folders/disks?
I mean, if they call a shell or a time-consuming API under the hood, this is the same problem I’m explaining: iterating over [only] 1000 files will take an extra amount of seconds: imagine how much time for the whole volume!

I’m asking, because it looks to me like the destinationOfSymbolicLinkAtPath function tries to return an original item and, only if it fails, returns an error. So, if I just want to know whether each item is a symbolic link, this function would be a “trial then error” function for non-link items, taking more time than just fetching a boolean value, right?

this calls OS function, so it should be fastest way to do it on MacOS.

Thank you, I’ll give it a try.

Another advantage of using this function: since Xojo’s binary stream tries to read the original item and we can’t read the link itself, saving the destination would be impossible otherwise. Here, I can store the result of destinationOfSymbolicLinkAtPath in my archive and restore it later using the “create” function, being a workaround of the binary stream approach.

Wnat about using http://documentation.xojo.com/api/files/folderitem.html.ChildAt ?

Both bookmarks and Symbolic links will appear with .isAlias = true. In order to get the actual item (providing it exists), use folderitem.parent.child( folderitem.name ). If the resulting item still shows .isAlias = true, then the link is broken.

In most cases you don’t need to see if it’s a sym link or bookmark, just once you know it’s a reference to another file, let the OS do the rest for you.

Yes, resolving with ChildAt is a possibility when you deal with a specific file. In my case, I’m iterating through a folder (with its subfolders), so trying to resolve each item to figure out whether it’s an alias or not is too-much resources consuming; I better have an API to know that directly.

Also, as Sam said, regular aliases may still be resolved although I deal with regular aliases like regular files (i.e. read their data), where symbolic links are a different beast (that’s the root of my question, actually).
Thanks.

That’s the problem for me, actually: aliases are handled as I expect in Xojo, but symbolic links aren’t.

When not resolved (i.e. setting followAlias to false in ChildAt), symbolic links are as expected, pointing to the link itself, not the original; but once you try to read, using a binary stream, that link, Xojo tries to read the original item. If the original item happens to be a folder, one gets an exception.

Thank you.