Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine if a network share exists before mounting

I'm working on a tool to automatically mount network volumes based on what wireless network the user is connected to. Mounting the volume is easy:

NSURL *volumeURL = /* The URL to the network volume */

// Attempt to mount the volume
FSVolumeRefNum volumeRefNum;
OSStatus error = FSMountServerVolumeSync((CFURLRef)volumeURL, NULL, NULL, NULL, &volumeRefNum, 0L);

However, if there is no network share at volumeURL (if someone turned off or removed a network hard drive, for example), Finder pops up an error message explaining this fact. My goal is for this not to happen — I'd like to attempt to mount the volume, but fail silently if mounting fails.

Does anyone have any tips on how to do this? Ideally, I'd like to find a way to check if the share exists before attempting to mount it (so as to avoid unnecessary work). If that's not possible, some way to tell the Finder not to display its error message would work as well.

like image 372
Matt Ball Avatar asked Oct 01 '09 23:10

Matt Ball


People also ask

How do I know if my network share is available?

Use the MS-DOS "net share" command Click Start, Run, type cmd, and press Enter . At the MS-DOS prompt, type net share and press Enter . Each of the shares, the location of the resource, and any remarks for that share are displayed.


1 Answers

This answer uses Private Frameworks. As naixn points out in the comments, this means it could break even on a dot release.

There is no way to do this using only public API (that I can find after a couple of hours of searching/disassembling).

This code will access the URL and not display any UI elements pass or fail. This includes not only errors, but authentication dialogs, selection dialogs, etc.

Also, it's not Finder displaying those messages, but NetAuthApp from CoreServices. The function being called here (netfs_MountURLWithAuthenticationSync) is called directly from the function in the question (FSMountServerVolumeSync). Calling it at this level lets us pass the kSuppressAllUI flag.

On success, rc is 0 and mountpoints contains a list of NSStrings of the mounted directories.

//
// compile with:
//
//  gcc -o test test.m -framework NetFS -framework Foundation
include <inttypes.h>
#include <Foundation/Foundation.h>

// Calls to FSMountServerVolumeSync result in kSoftMount being set
// kSuppressAllUI was found to exist here:
// http://www.opensource.apple.com/source/autofs/autofs-109.8/mount_url/mount_url.c
// its value was found by trial and error
const uint32_t kSoftMount     = 0x10000;
const uint32_t kSuppressAllUI = 0x00100;

int main(int argc, char** argv)
{
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

    NSURL *volumeURL = [NSURL URLWithString:@"afp://server/path"];
    NSArray* mountpoints = nil;

    const uint32_t flags = kSuppressAllUI | kSoftMount;

    const int rc = netfs_MountURLWithAuthenticationSync((CFURLRef)volumeURL, NULL, NULL,
            NULL, flags, (CFArrayRef)&mountpoints);

    NSLog(@"mountpoints: %@; status = 0x%x", mountpoints, rc);

    [pool release];
}
like image 61
nall Avatar answered Sep 30 '22 16:09

nall