|
#!/usr/bin/python |
|
|
|
############################################################ |
|
# # |
|
# Author: Calum Hunter # |
|
# Date: 10-10-2016 # |
|
# Version: 2.30 # |
|
# Purpose: Mount shares using NetFS # |
|
# Credit: Big shout outs to Frogor and Mosen for this # |
|
# This is all pretty much their code # |
|
# # |
|
############################################################ |
|
|
|
import objc, CoreFoundation, Foundation, sys, os, time |
|
|
|
class attrdict(dict): |
|
__getattr__ = dict.__getitem__ |
|
__setattr__ = dict.__setitem__ |
|
|
|
NetFS = attrdict() |
|
# Can cheat and provide 'None' for the identifier, it'll just use frameworkPath instead |
|
# scan_classes=False means only add the contents of this Framework |
|
NetFS_bundle = objc.initFrameworkWrapper('NetFS', frameworkIdentifier=None, frameworkPath=objc.pathForFramework('NetFS.framework'), globals=NetFS, scan_classes=False) |
|
|
|
# https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html |
|
# Fix NetFSMountURLSync signature |
|
del NetFS['NetFSMountURLSync'] |
|
objc.loadBundleFunctions(NetFS_bundle, NetFS, [('NetFSMountURLSync', 'i@@@@@@o^@')]) |
|
|
|
# Get our passed arguments and assign them to nice variable names |
|
# share_name = $1, server_url = $2, mount option = $3 this might be the no browse option. |
|
# we must always pass atleast two arguments (sys.arg[0] is the name of the script) |
|
if len(sys.argv) < 3: |
|
print (time.strftime("%a %b %d %H:%M:%S")) + " [mount_shares.py] - [ERROR] You must provide atleast 2 arguments.)" |
|
quit() |
|
else: |
|
share_name = sys.argv[1] |
|
server_url = sys.argv[2] |
|
if len(sys.argv) > 3: |
|
mount_type = sys.argv[3] |
|
else: |
|
mount_type = "std" |
|
|
|
def timestamp(): |
|
return time.strftime("%a %b %d %H:%M:%S") |
|
|
|
def log(message): |
|
print '%s %s %s' % (timestamp(), "[" + sys.argv[0] + "]", message) |
|
|
|
def mount_share(share_path): |
|
# Mounts a share at /Volumes, returns the mount point or raises an error |
|
sh_url = CoreFoundation.CFURLCreateWithString(None, share_path, None) |
|
# Set UI to reduced interaction |
|
open_options = {NetFS.kNAUIOptionKey: NetFS.kNAUIOptionNoUI} |
|
# Allow mounting sub-directories of root shares |
|
mount_options = {NetFS.kNetFSAllowSubMountsKey: True} |
|
# Mount! |
|
result, output = NetFS.NetFSMountURLSync(sh_url, None, None, None, open_options, mount_options, None) |
|
# Check if it worked |
|
if result != 0: |
|
raise Exception('Error mounting url "%s": %s' % (share_path, output)) |
|
# Return the mountpath |
|
return str(output[0]) |
|
|
|
def mount_share_no_browse(share_path): |
|
# Mounts a share at /Volumes, returns the mount point or raises an error |
|
sh_url = CoreFoundation.CFURLCreateWithString(None, share_path, None) |
|
# Set UI to reduced interaction |
|
open_options = {NetFS.kNAUIOptionKey: NetFS.kNAUIOptionNoUI} |
|
# Allow mounting sub-directories of root shares, and don't show on the desktop! (DONT BROWSE) |
|
# MNT_DONTBROWSE = 0x00100000 |
|
mount_options = { |
|
NetFS.kNetFSAllowSubMountsKey: True, |
|
NetFS.kNetFSMountFlagsKey: 0x00100000, |
|
} |
|
# Mount! |
|
result, output = NetFS.NetFSMountURLSync(sh_url, None, None, None, open_options, mount_options, None) |
|
# Check if it worked |
|
if result != 0: |
|
raise Exception('Error mounting url "%s": %s' % (share_path, output)) |
|
# Return the mountpath |
|
return str(output[0]) |
|
|
|
# Lets check here first to see if any of the shares we are being asked to mount already exist in /Volumes |
|
if os.path.exists(os.path.join('/Volumes', share_name)): |
|
log(('[WARN] - The share: %s already exists in /Volumes! We are going to skip mounting this share') % share_name) |
|
pass |
|
else: |
|
log(('Attempting to mount: smb://%s') % server_url) |
|
if mount_type == "nobrowse": |
|
log('[INFO] Mounting with nobrowse mode') |
|
mount_share_no_browse('smb://%s' % (server_url)) |
|
else: |
|
mount_share('smb://%s' % (server_url)) |