How to mount a directory via afp using mount(2)?

368 Views Asked by At

I want to mount a directory that resides on another host on my network. So far I've been successfully doing this via afp, using mount(8) via a system call, like so:

std::string syscmd = "mount -v -t afp -r \"afp://user:password@host/dir\" \"/tmp/foo/bar\"";
FILE *fd;
if(!(fd = popen(syscmd.c_str(), "r"))) {
    std::cout << "oops. popen() failed." << std::endl;
    exit(1);
}    

But I'd like to mount directly with a function call, without the added overhead of invoking a shell with popen(). I can't figure out how to do this using mount(2), which has this signature:

 int mount(const char *type, const char *dir, int flags, void *data);

What should data be? The man page doesn't explain this in any detail. For example, it says:

Data is a pointer to a structure that contains the type specific arguments to mount. The format for these argument structures is described in the manual page for each filesystem.

Where is that manual page it refers to? Is there some other documentation that I'm missing? Can anyone point me to a simple working example to illustrate the use of mount(2) over afp? Is there a better way to do this?

1

There are 1 best solutions below

2
Ken Thomases On

Do you have a reason to require that it be done via mount(2)?

Apple provides the NetFSMountURLSync() function, from the NetFS framework, to mount network file systems. Sadly, the only documentation is the header file, so I can't link to it, but here's the relevant declaration:

/*
 * Given a URL that refers to a file server, connect to that server
 * and mount stuff.
 *
 * If the URL just specifies a server and you can't just mount the
 * "root directory" of the server, the user will be prompted with
 * a window to let them select one or more items to mount from that
 * server, otherwise whatever item the URL specifies to mount will
 * be mounted.
 *
 * If the mountpath is provided it will be used as the mount point.
 * If the mountpath is set to NULL, a default mount point will be used.
 *
 * If the user and passwd are set, they will override any user name
 * or password that may be set in the URL. These calls go through the NetAuth agent.
 * If the URL doesn't specify a password, and one is needed, the
 * user will be prompted with a window requesting password.
 *
 * Options can be provided for the session open and the mount itself.
 * If the mount is successful, the POSIX path to each mountpoint is
 * returned as a CFStringRef in mountpoints.
 *
 * If the return value is zero the mount has succeeded.
 *
 * A positive non-zero return value represents an errno value
 * (see /usr/include/sys/errno.h).  For instance, a missing mountpoint
 * error will be returned as ENOENT (2).
 *
 * A negative non-zero return value represents an OSStatus error.
 * For instance, error -128 is userCanceledErr, returned when a mount
 * operation is canceled by the user. These OSStatus errors are
 * extended to include:
 *
 *  from this header:
 *  ENETFSPWDNEEDSCHANGE        -5045
 *  ENETFSPWDPOLICY         -5046
 *  ENETFSACCOUNTRESTRICTED     -5999
 *  ENETFSNOSHARESAVAIL     -5998
 *  ENETFSNOAUTHMECHSUPP        -5997
 *  ENETFSNOPROTOVERSSUPP       -5996
 *
 *  from <NetAuth/NetAuthErrors.h>
 *  kNetAuthErrorInternal       -6600
 *  kNetAuthErrorMountFailed    -6602
 *  kNetAuthErrorNoSharesAvailable  -6003
 *  kNetAuthErrorGuestNotSupported  -6004
 *  kNetAuthErrorAlreadyClosed  -6005
 *
 */
int
NetFSMountURLSync(
    CFURLRef url,               // URL to mount, e.g. nfs://server/path
    CFURLRef mountpath,         // Path for the mountpoint
    CFStringRef user,           // Auth user name (overrides URL)
    CFStringRef passwd,             // Auth password (overrides URL)
    CFMutableDictionaryRef open_options,    // Options for session open (see below)
    CFMutableDictionaryRef mount_options,   // Options for mounting (see below)
    CFArrayRef *mountpoints)        // Array of mountpoints
    __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_NA);

There's also an async version if that's useful for your use case.

As shown in this answer, you will need to use the kNetFSMountAtMountDirKey option if you want to dictate the mount point.