Skip to content

Instantly share code, notes, and snippets.

@pudquick
Last active January 19, 2023 22:07
Show Gist options
  • Save pudquick/1362a8908be01e23041d to your computer and use it in GitHub Desktop.
Save pudquick/1362a8908be01e23041d to your computer and use it in GitHub Desktop.
Mounting shares in OS X using python and pyobjc - works with OS X 10.8+
import objc, CoreFoundation, Foundation
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^@')])
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_at_path(share_path, mount_path):
# Mounts a share at the specified path, returns the mount point or raises an error
sh_url = CoreFoundation.CFURLCreateWithString(None, share_path, None)
mo_url = CoreFoundation.CFURLCreateWithString(None, mount_path, None)
# Set UI to reduced interaction
open_options = {NetFS.kNAUIOptionKey: NetFS.kNAUIOptionNoUI}
# Allow mounting sub-directories of root shares
# Also specify the share should be mounted directly at (not under) mount_path
mount_options = {
NetFS.kNetFSAllowSubMountsKey: True,
NetFS.kNetFSMountAtMountDirKey: True,
}
# Mount!
result, output = NetFS.NetFSMountURLSync(sh_url, mo_url, None, None, open_options, mount_options, None)
# Check if it worked
if result != 0:
raise Exception('Error mounting url "%s" at path "%s": %s' % (share_path, mount_path, output))
# Return the mountpath
return str(output[0])
def mount_share_with_credentials(share_path, username, password):
# Mounts a share at /Volumes, returns the mount point or raises an error
# Include username and password as parameters, not in the share_path URL
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, username, password, 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_at_path_with_credentials(share_path, mount_path, username, password):
# Mounts a share at the specified path, returns the mount point or raises an error
# Include username and password as parameters, not in the share_path URL
sh_url = CoreFoundation.CFURLCreateWithString(None, share_path, None)
mo_url = CoreFoundation.CFURLCreateWithString(None, mount_path, None)
# Set UI to reduced interaction
open_options = {NetFS.kNAUIOptionKey: NetFS.kNAUIOptionNoUI}
# Allow mounting sub-directories of root shares
# Also specify the share should be mounted directly at (not under) mount_path
mount_options = {
NetFS.kNetFSAllowSubMountsKey: True,
NetFS.kNetFSMountAtMountDirKey: True,
}
# Mount!
result, output = NetFS.NetFSMountURLSync(sh_url, mo_url, username, password, open_options, mount_options, None)
# Check if it worked
if result != 0:
raise Exception('Error mounting url "%s" at path "%s": %s' % (share_path, mount_path, output))
# Return the mountpath
return str(output[0])
@carlashley
Copy link

carlashley commented Feb 8, 2022

@pudquick just wondering if you've revisited this given some deprecations that are going to happen in PyObjC 9:

/usr/local/bin/redlands/mount_shares.py:24: DeprecationWarning: This function will be removed in PyObjC 9, switch to the modern metadata system
  NetFS_bundle = objc.initFrameworkWrapper('NetFS',  frameworkIdentifier=None, frameworkPath=objc.pathForFramework('NetFS.framework'), 1globals=NetFS, scan_classes=False)

@carlashley
Copy link

carlashley commented Feb 10, 2022

Thanks @pudquick for the chat over Slack about the changes that will be upcoming to PyObjC 9.

For anyone else using this, you should be able to comment out these lines and simply replace it all with import NetFS and have it work...
(tested against PyObjC v7.3).

# 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)
# # NetFS_bundle = objc.ObjCLazyModule('NetFS', None, objc.pathForFramework('NetFS.framework'))
# 
# # 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', b'i@@@@@@o^@')])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment