jueves, 25 de octubre de 2012

MacOSX, FUSE, SSH, Finder and other goodies...

Ok, another post and another subject...

I have been a Mac devote since more than 10 years already... Though I am too a Linux fan since my early years, and keep using the Linux power for all my servers and services, since the first PowerBook came to me I haven't used other kind of desktop computers.

Since most of my work is done across Linux and Unix servers, I am very used to Terminal. I feel already good working with vi editors and all the related unix stuff. It's good to making a small script, or doing some slight changes to a text file, but when it comes to long scripts, multiple file editing, I think nothing better than an editor (choose yours, TextMate, TextEdit, Xcode editor, Taco Editor, BBEdit,...) to do the work...

When the files are stored in a Unix server, you have some possibilities to accomplish this. One of them that I feel comfortable with is sshfs. SSH is a communication protocol to access remote machines. Most unix servers, and definitly 99% of Linux servers, run ssh servers. sshfs is a filesystem that can mount in your computer a remote server's filesystem locally (as long as the server is running a ssh server). Same as accesing a apf or samba share across the network.

So to make this magic work, you have to install OSXFUSE and the SSHFS filesystem (http://osxfuse.github.com). You can find all the information and help needed in the project page.

As soon as you have done this, you will be able to mount ssh filesystems as network shares. To do this, you will have to use the Terminal application, make a mount point directory and issue the sshfs command to do the mount. You can see an example right below.



Though this works really fine, to some not used to terminals, or simple as lazy as I am, it is a bit overwork ;-) to do all this to mount the filesystem, more if you take into consideration that finder has a nice option "Connect to server" to manage this stuff.

So you can try just goto "Connect to server" and in the address input box type: sshfs://root@otrs.imcs.es:/ to accomplish the same task. And, of course, you will receive a message saying something like 'URL addresses of type "sshfs" are not compatible'. And no mounting at all. Annoying.

As I have allways wanted to start contributing to Apple software scene, I decided to make this work my first project in this scene. Downloaded Xcode, subscribed an Apple Developer suscription just to have access to official developer forums and documentation and started digging about how to accomplish this.

It hasn't been an easy start. Not much documentation, only an official post I could find talking directly about this in the developer forums, with an answer like this "It is currently not possible for third party network file systems to fully integrate with the Connect to Server dialog. " and not much more. In that post it talked about a private Apple api, URLMount and that was my starting point.

Soon I found that this Connect to server dialog actually uses some "bundles" (let's say 'plugins') in the /System/Library/Filesystems/NetFSPlugins. There are plugins in this folder for AFP, FTP, HTTP (WebDav), NFS and SMB sharing protocols. Of course no plugin for our SSHFS filesystem. So I decided to build my own.

Digging this plugins plist files, learning about Apple 'bundles', was the first step. I learned that NetFSPlugin was the one to implement. Sadly I couldn't find official nor unofficial documentation about this API. Then I found that some of this Plugins (smb, afp, http) have been opensourced by apple (opensource.apple.com) and I studied the smb_netfs.c source code. This was such a good source of information, and then I found the "Mac9P" that is an OpenSource implementation of the 9P filesystem and that includes a 9P NetFSPlugin to use the "Connect to server" dialog to mount this kind of filesystems.

That was all I needed, I just got my old C knowledge out of the dark back junk rooms of my memory and taking this 9P plugin as a starting point, built my own SSHFS NetFSPlugin. Basically all you have to do is implement an entry function NetFSInterfaceFactory that returns a structure NetFSMountInterface_V1 with pointers to some other functions you have to implement too.

Basically this is the entry point:

/*
 *  NetFS Type implementation:
 */
static NetFSMountInterface_V1 gSSHFSNetFSMountInterfaceFTbl = {
    NULL,    /* IUNKNOWN_C_GUTS: _reserved */
    NetFSQueryInterface,  /* IUNKNOWN_C_GUTS: QueryInterface */
    NetFSInterface_AddRef,  /* IUNKNOWN_C_GUTS: AddRef */
    NetFSInterface_Release,  /* IUNKNOWN_C_GUTS: Release */
    SSHFS_CreateSessionRef,  /* CreateSessionRef */
    SSHFS_GetServerInfo,  /* GetServerInfo */
    SSHFS_ParseURL,             /* ParseURL */
    SSHFS_CreateURL,   /* CreateURL */
    SSHFS_OpenSession,   /* OpenSession */
    SSHFS_EnumerateShares,  /* EnumerateShares */
    SSHFS_Mount,    /* Mount */
    SSHFS_Cancel,    /* Cancel */
    SSHFS_CloseSession,   /* CloseSession */
    SSHFS_GetMountInfo,   /* GetMountInfo */
};

void *SSHFSNetFSInterfaceFactory(CFAllocatorRef allocator, CFUUIDRef typeID);

void *SSHFSNetFSInterfaceFactory(CFAllocatorRef allocator, CFUUIDRef typeID)
{
#pragma unused(allocator)
 if (CFEqual(typeID, kNetFSTypeID)) {
  return NetFS_CreateInterface(kSSHFSNetFSInterfaceFactoryID, &gSSHFSNetFSMountInterfaceFTbl);
    } else {
  return NULL;
 }
}

Now all you have to do is implement the SSHFS_* functions pointed in that structure, and that's it. You can better see it yourself in the mac9p plugin source or in any of the open sourced plugins by apple or you can download my code from here or just send me an email and I will gladly send it to you.

Just copy the sshfs.bundle into /System/Library/Filesystems/NetFSPlugins and try it...


you will get your filesystem mounted...


Of course it's only a proof of concept, not even a beta version, will have surely lots of bugs and you can imagine a million improvements that can be done.

I have no plans to make a project out of this, don't even know if it deserves. If you think it can be interesting, and want to try, send me an email and let's see what we can do... ;-)