Subject: | Mac::Path::Util assumes mounts at /Volume |
I ran into a problem with the module where it doesn't properly determine
the volume name from a Unix style path because it makes a hard-coded
assumption that all mount points are under /Volumes, which isn't the case
if you use File Vault, then your home directory becomes a mount point:
$ mount |grep $USER
/dev/disk2s2 on /Users/blair (local, nodev, nosuid, journaled)
Here is some code that I'm using that handles this.
The only issue with this code is that it doesn't properly handle paths
that have .. 's in them. It does handle paths where the path given is
the mount point itself, such as /Users/blair returns blair:
Regards,
Blair
# Convert Unix style paths with / as directory separators to old
# Macintosh style paths with : as directory separators.
sub unix_to_mac_path {
my $u_path = shift;
# The first time that this function is called, create a set of
# mappings from Unix mount points to Macintosh volume names that
# will be used later on to find the volume that a given path refers
# to. For each Unix mount, create a regular expression that will
# remove the mount point when the path refers to a path on that
# volume. Care must be taken to not match paths that have a common
# leading path, for example if /Users/blair is a mount point, then
# /Users/blairzajac should not match. Create an array holding pairs
# of (Unix mount point regex, Macintosh volume name) sorted in
# descending string length order.
unless (@unix_volumes_to_mac_volumes) {
my %u_to_m;
foreach my $fsspec (MacPerl::Volumes()) {
my $unix_volume = MacPerl::MakePath($fsspec);
my $re;
if ($unix_volume eq '/') {
$re = qr#^/#;
} else {
$re = qr#^\Q$unix_volume\E(/|$)#;
}
# Trim the leading portion of the FSSPEC to get the Macintosh
# volume name.
$fsspec =~ s/^[^:]+://;
$u_to_m{$re} = $fsspec;
}
foreach my $unix_volume (reverse sort keys %u_to_m) {
push(@unix_volumes_to_mac_volumes, $unix_volume, $u_to_m{$unix_volume});
}
}
my $u_abs_path = File::Spec->rel2abs($u_path);
for (my $i=0; $i<@unix_volumes_to_mac_volumes; $i+=2) {
my $re = $unix_volumes_to_mac_volumes[$i];
if ($u_abs_path =~ s/$re//) {
$u_abs_path =~ y#/#:#;
return $unix_volumes_to_mac_volumes[$i+1] . ":$u_abs_path";
}
}
confess "$0: internal error: no match on filename '$u_path'.\n";
}