#include <unistd.h>
#include <mntopts.h>
#include <syslog.h>
#include <sys/mount.h>
#include <CoreFoundation/CoreFoundation.h>
#include <NetFS/NetFS.h>
#include <NetFS/NetFSPrivate.h>
#include <NetAuth/NetAuth.h>
#define ALT_SOFT 0x00000001
static const struct mntopt mopts_std[] = {
MOPT_STDOPTS,
MOPT_UPDATE,
MOPT_RELOAD,
{ "soft", 0, ALT_SOFT, 1 },
{ NULL, 0, 0, 0 }
};
static void usage(void);
static int do_mount_direct(CFURLRef server_URL, CFStringRef mountdir,
CFDictionaryRef open_options, CFDictionaryRef mount_options,
CFDictionaryRef *mount_infop);
int
main(int argc, char **argv)
{
int c;
int usenetauth = 0;
mntoptparse_t mp;
int flags, altflags;
CFURLRef URL;
CFStringRef mountdir_CFString;
CFMutableDictionaryRef open_options, mount_options;
CFDictionaryRef mount_info;
int res;
flags = altflags = 0;
getmnt_silent = 1;
while ((c = getopt(argc, argv, "no:rw")) != -1) {
switch (c) {
case 'n':
usenetauth = 1;
break;
case 'o':
mp = getmntopts(optarg, mopts_std, &flags, &altflags);
freemntopts(mp);
break;
case 'r':
flags |= MNT_RDONLY;
break;
case 'w':
flags &= ~MNT_RDONLY;
break;
case '?':
default:
usage();
break;
}
}
argc -= optind;
argv += optind;
if (argc != 2)
usage();
URL = CFURLCreateWithBytes(kCFAllocatorDefault, (const UInt8 *)argv[0],
strlen(argv[0]), kCFStringEncodingUTF8, NULL);
if (URL == NULL)
exit(ENOMEM);
mountdir_CFString = CFStringCreateWithCString(kCFAllocatorDefault,
argv[1], kCFStringEncodingUTF8);
if (mountdir_CFString == NULL)
exit(ENOMEM);
open_options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
if (open_options == NULL)
exit(ENOMEM);
CFDictionaryAddValue(open_options, kNetFSForceNewSessionKey,
kCFBooleanFalse);
CFDictionaryAddValue(open_options, kNetFSAllowLoopbackKey,
kCFBooleanTrue);
CFDictionaryAddValue(open_options, kNetFSNoUserPreferencesKey,
kCFBooleanTrue);
CFDictionaryAddValue(open_options, kUIOptionKey, kUIOptionNoUI);
mount_options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
if (mount_options == NULL)
exit(ENOMEM);
CFDictionaryAddValue(mount_options, kNetFSForceNewSessionKey,
kCFBooleanFalse);
CFDictionaryAddValue(mount_options, kNetFSMountAtMountDirKey,
kCFBooleanTrue);
CFDictionaryAddValue(mount_options, kNetFSNoUserPreferencesKey,
kCFBooleanTrue);
CFDictionaryAddValue(mount_options, kNetFSAllowSubMountsKey,
kCFBooleanTrue);
CFDictionaryAddValue(mount_options, kNetFSMountFlagsKey,
CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type,
&flags));
CFDictionaryAddValue(mount_options, kNetFSSoftMountKey,
(altflags & ALT_SOFT) ? kCFBooleanTrue : kCFBooleanFalse);
CFDictionaryAddValue(mount_options, kUIOptionKey, kUIOptionNoUI);
if (usenetauth)
res = NAConnectToServerSync(URL, mountdir_CFString,
open_options, mount_options, &mount_info);
else
res = do_mount_direct(URL, mountdir_CFString, open_options,
mount_options, &mount_info);
if (res == 0 || res == EEXIST)
CFRelease(mount_info);
CFRelease(mount_options);
CFRelease(open_options);
CFRelease(mountdir_CFString);
CFRelease(URL);
if (res != 0) {
if ((res & 0xFFFFFF00) != 0) {
syslog(LOG_ERR,
"mount_url: Mount of %s on %s gives status %d",
argv[0], argv[1], res);
switch (res) {
case ENETFSACCOUNTRESTRICTED:
case ENETFSPWDNEEDSCHANGE:
case ENETFSPWDPOLICY:
res = EAUTH;
break;
default:
res = EIO;
break;
}
}
}
return res;
}
static void
usage(void)
{
fprintf(stderr, "Usage: mount_url [-n] [-rw] [-o options] url node\n");
exit(1);
}
static int
do_mount_direct(CFURLRef server_URL, CFStringRef mountdir,
CFDictionaryRef open_options, CFDictionaryRef mount_options,
CFDictionaryRef *mount_infop)
{
int ret;
void *session_ref;
*mount_infop = NULL;
ret = netfs_CreateSessionRef(server_URL, &session_ref);
if (ret != 0)
return ret;
ret = netfs_OpenSession(server_URL, session_ref, open_options, NULL);
if (ret != 0) {
netfs_CloseSession(session_ref);
return ret;
}
ret = netfs_Mount(session_ref, server_URL, mountdir, mount_options,
mount_infop);
netfs_CloseSession(session_ref);
return ret;
}