-
-
Save WardsParadox/d6a8fbe0c0d1f100b5574188e4bd627d to your computer and use it in GitHub Desktop.
openwithrosetta - a tool to check the box "Open with Rosetta" on Apple Silicon Big Sur Macs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import subprocess | |
import sys | |
from Foundation import * # pylint: disable=E0611 # | |
import objc | |
from SystemConfiguration import SCDynamicStoreCopyConsoleUser | |
def is_arm64(): | |
""" | |
Determine if a Mac can run ARM64 code, whether or not the binary is running in Rosetta 2 via pyobjc | |
https://gist.github.com/pudquick/ca7fa134895f30b070212ea505cab5eb | |
Returns: | |
boolean: True = arm64 device (aka Apple Silicon), False = x86_64 (Intel Silicon) | |
""" | |
CF = NSBundle.bundleWithPath_("/System/Library/Frameworks/CoreFoundation.framework") | |
f = [("CFBundleIsArchitectureLoadable", b"BQ")] | |
objc.loadBundleFunctions(CF, globals(), f) | |
NSBundleExecutableArchitectureARM64 = 0x0100000C | |
return CFBundleIsArchitectureLoadable(NSBundleExecutableArchitectureARM64) | |
# Shamelessly Stolen from FoundationPlist (L26-106): https://github.com/munki/munki/blob/main/code/client/munkilib/FoundationPlist.py | |
class NSPropertyListSerializationException(BaseException): | |
"""Read/parse error for plists""" | |
pass | |
class NSPropertyListWriteException(BaseException): | |
"""Write error for plists""" | |
pass | |
def readPlist(filepath): | |
""" | |
Read a .plist file from filepath. Return the unpacked root object | |
(which is usually a dictionary). | |
""" | |
plistData = NSData.dataWithContentsOfFile_(filepath) | |
( | |
dataObject, | |
dummy_plistFormat, | |
error, | |
) = NSPropertyListSerialization.propertyListFromData_mutabilityOption_format_errorDescription_( | |
plistData, NSPropertyListMutableContainers, None, None | |
) | |
if dataObject is None: | |
if error: | |
error = error.encode("ascii", "ignore") | |
else: | |
error = "Unknown error" | |
errmsg = "%s in file %s" % (error, filepath) | |
raise NSPropertyListSerializationException(errmsg) | |
else: | |
return dataObject | |
def readPlistFromString(data): | |
"""Read a plist data from a (byte)string. Return the root object.""" | |
plistData = NSData.dataWithBytes_length_(data, len(data)) | |
if not plistData: | |
raise NSPropertyListSerializationException("Could not convert string to NSData") | |
( | |
dataObject, | |
dummy_plistFormat, | |
error, | |
) = NSPropertyListSerialization.propertyListFromData_mutabilityOption_format_errorDescription_( | |
plistData, NSPropertyListMutableContainers, None, None | |
) | |
if dataObject is None: | |
if error: | |
error = error.encode("ascii", "ignore") | |
else: | |
error = "Unknown error" | |
raise NSPropertyListSerializationException(error) | |
else: | |
return dataObject | |
def writePlist(dataObject, filepath): | |
""" | |
Write 'rootObject' as a plist to filepath. | |
""" | |
( | |
plistData, | |
error, | |
) = NSPropertyListSerialization.dataFromPropertyList_format_errorDescription_( | |
dataObject, NSPropertyListXMLFormat_v1_0, None | |
) | |
if plistData is None: | |
if error: | |
error = error.encode("ascii", "ignore") | |
else: | |
error = "Unknown error" | |
raise NSPropertyListSerializationException(error) | |
else: | |
if plistData.writeToFile_atomically_(filepath, True): | |
return | |
else: | |
raise NSPropertyListWriteException( | |
"Failed to write plist data to %s" % filepath | |
) | |
def main(): | |
"""Main, duh, whatelse but RUNNNN!""" | |
if not is_arm64(): | |
print("Intel device detected...no problemo!") | |
sys.exit(0) | |
# Dont' rely on python knowing which user is active as we run this run sudo via jamf | |
name, uid, gid = SCDynamicStoreCopyConsoleUser(None, None, None) | |
ls_path = f"/Users/{name}/Library/Preferences/com.apple.LaunchServices/com.apple.LaunchServices.plist" | |
ls_mode = "x86_64" | |
app_path = "/Applications/Cisco/Cisco AnyConnect Secure Mobility Client.app" | |
if not os.path.exists(app_path) | |
print(f"Bad App Path given!") | |
sys.exit(1) | |
bundle_identifier = NSBundle.bundleWithPath_(app_path).bundleIdentifier() | |
file_path = NSURL.fileURLWithPath_(app_path) | |
bookmark = file_path.bookmarkDataWithOptions_includingResourceValuesForKeys_relativeToURL_error_( | |
NSURLBookmarkCreationSuitableForBookmarkFile, None, None, None | |
) | |
data = NSData.alloc().initWithBytes_length_(bookmark[0], len(bookmark[0])) | |
if os.path.exists(ls_path): | |
ls_data = readPlist(ls_path) | |
else: | |
dummy = plistlib.dumps({"Architectures for arm64": {}}) | |
ls_data = readPlistFromString(dummy) | |
if bundle_identifier in ls_data["Architectures for arm64"]: | |
if ls_mode in ls_data["Architectures for arm64"][bundle_identifier]: | |
print(f"App bundle {bundle_identifier} already set to {ls_mode}") | |
sys.exit(0) | |
else: | |
print(f"Setting App bundle {bundle_identifier} to {ls_mode}") | |
else: | |
print( | |
f"App bundle {bundle_identifier} not found. Creating and Setting to {ls_mode}" | |
) | |
ls_data["Architectures for arm64"][bundle_identifier] = [data, ls_mode] | |
writePlist(ls_data, ls_path) | |
# Kill LaunchServices daemon to load saved data | |
subprocess.check_call(["/usr/bin/killall", "lsd"]) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This came in SUPER clutch. Many thanks.