Resolving OS-X aliases

My external drive recently started making clicking noises instead of spinning up some of the time so I thought it would be a good time to buy a new one. I keep my photos on the external disk and manipulate them with iPhoto and perl scripts. I dutifully copied the whole disk contents to the new disk and plugged it into the Airport Extreme to run some of my scripts. After a couple of minutes the disk dropped out (WD disks don’t work with Airport disk sharing due to spindown borking the airport, it turns out). No worries, I’ll just plug it in directly – it’ll mount at the same point /Volumes/mika-usb.

Now iPhoto likes to make aliases to files – the files that the library file points to are aliases. I use the MacOSX::Alias perl module to follow them. The problem is that the aliases point both to the afp share and the POSIX path and the API that MacOSX::Alias uses resolves into the afp share – which is not available.

Some searching on the intertubes provided me with enough code examples to write a small command line tool that resolves the path instead. Here it is, in case somebody else runs into the same problem:

#include <CoreServices/CoreServices.h>

int main (int argc, const char * argv[]) {
  OSErr err = noErr;
  FSRef input_file_ref;
  if (argc < 2) {
    fprintf(stderr, "Usage:\nalias path\n");
    return 2;
  }
  err = FSPathMakeRef(argv[1], &input_file_ref, false);
  if (noErr != err) {
    perror("cannot find file");
    return 1;
  }
  ResFileRefNum resource_ref = FSOpenResFile(&input_file_ref, fsRdPerm);
  AliasHandle alias_handle = (AliasHandle)GetIndResource('alis', 1);
  if (!alias_handle) {
    perror("no alis resource");
    return 1;
  }
  
  FSRef resolved_file_ref;
  Boolean was_changed;
  err = FSResolveAliasWithMountFlags(&input_file_ref, alias_handle,
                                     &resolved_file_ref,
                                     &was_changed, kResolveAliasFileNoUI); 
  CloseResFile(resource_ref);
  if (noErr != err) {
    perror("cannot resolve");
    return 1;
  }
  
  // Convert the file reference into a string
  UInt8 fileNameBuffer[1024];
  OSStatus status = FSRefMakePath(&resolved_file_ref,
                                  fileNameBuffer,
                                  1024);
  printf("resolved to %s\n", &fileNameBuffer);
  return 0;
}
This entry was posted in CS. Bookmark the permalink.

Comments are closed.