The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Mac::Alias - Read or create macOS alias files

VERSION

version 1.01

SYNOPSIS

 # Import functions as needed
 use Mac::Alias qw( :all );
 
 # Check files and follow aliases
 $bool = is_alias('/path/to/file');
 $path = read_alias('/path/to/alias');
 
 # Create new aliases
 make_alias('/path/to/original', '/path/to/alias');  # Mac only
 
 # Parse details from an alias file
 %info = parse_alias('/path/to/alias')->%*;
 
 # More fine-grained control over reading aliases
 $path = read_alias_perl($file);
 $path = read_alias_mac($file);  # Mac only

DESCRIPTION

This Perl module offers functions to read and write macOS Finder alias files. It reads alias data directly from alias files using pure Perl. As such, reading aliases works on any OS and file system. Creating new aliases is only possible on a Mac though.

Aliases are similar to POSIX symlinks in that they contain the target path and are marked by a file system flag. Unlike symlinks however, aliases contain a bunch of additional metadata, including the target file's inode number. This allows the macOS Finder to update aliases after their target was moved.

This module is effectively a replacement for MacOSX::Alias.

FUNCTIONS

is_alias

 $bool = is_alias $file;

Checks whether the given file looks like a macOS Finder alias. It does so not by looking at the kIsAlias Finder flag, but rather inspects the file for its contents, so it works on any operating system.

make_alias

 $success = make_alias $target, $alias_file;

Creates a new alias file. Returns a truthy value on success. Mac-only.

Note that this function will happily create aliases of a target that itself is an alias. The macOS Finder can't handle such alias chains and is smart enough to avoid creating them, but this function will do exactly what you ask of it, even if the result is useless.

parse_alias

 $data = parse_alias $file;

Parses the given data fork alias file and returns a reference to a hash that attempts to describe the alias's contents in human-readable format.

If you're familiar with Apple's Cocoa framework: The result is similar to what calling [NSURL resourceValuesForKeys] with NSURLBookmarkDetailedDescription would get you, except that it skips most of the low-level technical output and it works on any operating system. For example:

 $data = {
   pathComponents => [ 'Users', ... ],  # alias target path
   fileIDs        => [  21338 , ... ],  # inode path
   creationDate   => 1627592891.72982514,  # POSIX epoch
   volName        => 'Macintosh HD',
   volPath        => '/',      # volume mount point
   volUUID        => '...',    # unique volume ID
   ...
 }

Older aliases may contain an alis record, accessible via a $data->{aliasData} entry. This record can be further decoded with "unpack_alias" in Mac::Alias::Parse.

read_alias

 $path = read_alias $file;

Returns the target file system path. If no target path can be determined, an undefined value is returned instead.

This function will first try to parse the alias file by reading it directly within Perl, and return the result if the target path exists in the file system. This gives a very fast result and works on any operating system. However, the result doesn't account for the possibility of the target having been moved or deleted.

If direct parsing didn't yield a path that exists, this function will therefore try to pass on the alias to the macOS Finder for resolving its new location. The Finder is contacted through the osascript utility, which is rather slow. If the Finder fails to resolve the alias target, too (for example, because the target was deleted), the non-existing path parsed directly from the alias file earlier is returned, because this is still the best information available at that point. The same is true on non-Mac systems.

read_alias_mac

 $path = read_alias_mac $file;

Like "read_alias", but will always use the Finder alias resolution through the osascript utility. Slow and Mac-only.

read_alias_perl

 $path = read_alias_perl $file;

Like "read_alias", but will only use direct parsing of the alias file and never go through the Finder. Very fast, but might be inaccurate.

SECURITY CONSIDERATIONS

Some uses of aliases have a risk of exposing protected parts of the file system. This is the same risk as is known from symlinks. For example, consider a Perl web server that resolves aliases, with one of these aliases pointing to a target located outside of the web server's root directory, or to a hidden file. Always make sure to sanitise the target's path as appropriate before using it.

Resolving aliases on macOS can have side-effects, such as updating the alias file itself or the mounting of network volumes. Such side-effects could unintentionally expose information as well. To avoid side-effects with read_alias(), you can use the read_alias_perl() variant instead, which will never use the Finder API to resolve aliases.

BUGS AND LIMITATIONS

The parse_alias() function currently does not decode structured properties (resourceProps, volProps) or alias file headers into a hash. This will hopefully change in a future version.

For unmounted network volumes, read_alias_perl() will currently return the file system path read from the alias. It should probably yield the URI instead. The same is true for the Perl-only part of read_alias(), if the network volume can't be mounted.

This module currently doesn't handle resource fork aliases at all. Because the last macOS Finder version that created resource fork aliases was released a long time ago (back in 2007 or so), this may not be a big deal.

SEE ALSO

Mac::Alias::Format

Dist::Zilla::Plugin::PruneAliases

AUTHOR

Arne Johannessen <ajnn@cpan.org>

If you contact me by email, please make sure you include the word "Perl" in your subject header to help beat the spam filters.

COPYRIGHT AND LICENSE

This software is Copyright (c) 2022 by Arne Johannessen.

This is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0 or (at your option) the same terms as the Perl 5 programming language system itself.