diff --git a/AKPlugin.swift b/AKPlugin.swift index f286006a..445c76c4 100644 --- a/AKPlugin.swift +++ b/AKPlugin.swift @@ -18,16 +18,34 @@ private struct AKAppSettingsData: Codable { var resizableAspectRatioHeight: Int? } -private func akCurrentUserHomeDirectoryPath() -> String { - let userName = NSUserName() - if let homeDirectory = NSHomeDirectoryForUser(userName) { - return homeDirectory +private func akCurrentAccountHomeDirectoryURL() -> URL { + let configuredBufferSize = sysconf(_SC_GETPW_R_SIZE_MAX) + var bufferSize = configuredBufferSize > 0 ? Int(configuredBufferSize) : 1_024 + + while true { + var password = passwd() + var result: UnsafeMutablePointer? + var buffer = [CChar](repeating: 0, count: bufferSize) + let lookup = buffer.withUnsafeMutableBufferPointer { bufferPointer -> (Int32, String?) in + let status = getpwuid_r(getuid(), &password, bufferPointer.baseAddress, bufferPointer.count, &result) + guard status == 0, result != nil, let path = password.pw_dir else { + return (status, nil) + } + return (status, String(cString: path)) + } + if lookup.0 == ERANGE { + bufferSize *= 2 + continue + } + guard let homeDirectoryPath = lookup.1 else { + fatalError("Unable to locate the current account home directory") + } + return URL(fileURLWithPath: homeDirectoryPath, isDirectory: true) } - return NSString(string: "~\(userName)").expandingTildeInPath } private func akSettingsURLForBundleIdentifier(_ bundleIdentifier: String) -> URL { - return URL(fileURLWithPath: akCurrentUserHomeDirectoryPath(), isDirectory: true) + return akCurrentAccountHomeDirectoryURL() .appendingPathComponent("Library", isDirectory: true) .appendingPathComponent("Containers", isDirectory: true) .appendingPathComponent("io.playcover.PlayCover", isDirectory: true) diff --git a/PlayTools/Keymap/Keymapping.swift b/PlayTools/Keymap/Keymapping.swift index 862a16a1..ac6bb7b7 100644 --- a/PlayTools/Keymap/Keymapping.swift +++ b/PlayTools/Keymap/Keymapping.swift @@ -60,7 +60,7 @@ class Keymapping { } init() { - baseKeymapURL = URL(fileURLWithPath: "/Users/\(NSUserName())/Library/Containers/io.playcover.PlayCover") + baseKeymapURL = playCoverContainerBaseURL() .appendingPathComponent("Keymapping") .appendingPathComponent(bundleIdentifier) diff --git a/PlayTools/PlayLoader.m b/PlayTools/PlayLoader.m index 85e45905..6be7f9d3 100644 --- a/PlayTools/PlayLoader.m +++ b/PlayTools/PlayLoader.m @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -219,48 +220,33 @@ static OSStatus pt_SecKeyGeneratePair(CFDictionaryRef parameters, SecKeyRef *pub static uint8_t ue_status = 0; static void pt_copyCurrentUserHomeDirectory(char *buffer, size_t bufferSize) { - if (bufferSize == 0) { + if (buffer == NULL || bufferSize == 0) { return; } - buffer[0] = '\0'; - char executablePath[PATH_MAX]; - uint32_t executablePathSize = sizeof(executablePath); - if (_NSGetExecutablePath(executablePath, &executablePathSize) == 0) { - static char const containerMarker[] = "/Library/Containers/io.playcover.PlayCover/"; - char *marker = strstr(executablePath, containerMarker); - if (marker != NULL) { - size_t homePathLength = (size_t)(marker - executablePath); - if (homePathLength > 0 && homePathLength < bufferSize) { - memcpy(buffer, executablePath, homePathLength); - buffer[homePathLength] = '\0'; - return; + long configuredBufferSize = sysconf(_SC_GETPW_R_SIZE_MAX); + size_t accountBufferSize = configuredBufferSize > 0 ? (size_t)configuredBufferSize : 1024; + char *accountBuffer = malloc(accountBufferSize); + while (accountBuffer != NULL) { + struct passwd password; + struct passwd *result = NULL; + int status = getpwuid_r(getuid(), &password, accountBuffer, accountBufferSize, &result); + if (status != ERANGE) { + if (status == 0 && result != NULL && password.pw_dir != NULL) { + snprintf(buffer, bufferSize, "%s", password.pw_dir); } + break; } - } - char const *homeDirectory = getenv("HOME"); - if (homeDirectory != NULL && homeDirectory[0] != '\0') { - static char const containerSuffix[] = "/Library/Containers/io.playcover.PlayCover"; - char const *suffix = strstr(homeDirectory, containerSuffix); - if (suffix != NULL) { - size_t homePathLength = (size_t)(suffix - homeDirectory); - if (homePathLength > 0 && homePathLength < bufferSize) { - memcpy(buffer, homeDirectory, homePathLength); - buffer[homePathLength] = '\0'; - return; - } + accountBufferSize *= 2; + char *resizedBuffer = realloc(accountBuffer, accountBufferSize); + if (resizedBuffer == NULL) { + break; } - - snprintf(buffer, bufferSize, "%s", homeDirectory); - return; - } - - char userName[256]; - if (getlogin_r(userName, sizeof(userName)) == 0) { - snprintf(buffer, bufferSize, "/Users/%s", userName); + accountBuffer = resizedBuffer; } + free(accountBuffer); } static char const* ue_fix_filename(char const* filename) { diff --git a/PlayTools/PlaySettings.swift b/PlayTools/PlaySettings.swift index cf14058d..d7b1ee12 100644 --- a/PlayTools/PlaySettings.swift +++ b/PlayTools/PlaySettings.swift @@ -3,16 +3,34 @@ import UIKit let settings = PlaySettings.shared -func playCoverUserHomeDirectoryPath() -> String { - let userName = NSUserName() - if let homeDirectory = NSHomeDirectoryForUser(userName) { - return homeDirectory +private func currentAccountHomeDirectoryURL() -> URL { + let configuredBufferSize = sysconf(_SC_GETPW_R_SIZE_MAX) + var bufferSize = configuredBufferSize > 0 ? Int(configuredBufferSize) : 1_024 + + while true { + var password = passwd() + var result: UnsafeMutablePointer? + var buffer = [CChar](repeating: 0, count: bufferSize) + let lookup = buffer.withUnsafeMutableBufferPointer { bufferPointer -> (Int32, String?) in + let status = getpwuid_r(getuid(), &password, bufferPointer.baseAddress, bufferPointer.count, &result) + guard status == 0, result != nil, let path = password.pw_dir else { + return (status, nil) + } + return (status, String(cString: path)) + } + if lookup.0 == ERANGE { + bufferSize *= 2 + continue + } + guard let homeDirectoryPath = lookup.1 else { + fatalError("Unable to locate the current account home directory") + } + return URL(fileURLWithPath: homeDirectoryPath, isDirectory: true) } - return NSString(string: "~\(userName)").expandingTildeInPath } func playCoverContainerBaseURL() -> URL { - URL(fileURLWithPath: playCoverUserHomeDirectoryPath(), isDirectory: true) + currentAccountHomeDirectoryURL() .appendingPathComponent("Library", isDirectory: true) .appendingPathComponent("Containers", isDirectory: true) .appendingPathComponent("io.playcover.PlayCover", isDirectory: true)