From ab5cb5a1b5a9aef6b22b5d40ee43eb6d37eb8515 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Rodr=C3=ADguez=20Troiti=C3=B1o?= Date: Mon, 1 Jul 2019 14:55:29 -0700 Subject: [PATCH] [android] Improve CFKnownLocations. The usage of CFKnownLocations from Swift Foundation seems to be reduced to both _kCFKnownLocationUserAny and _kCFKnownLocationUserCurrent. From the public API of Swift Foundation there's no way to get to _kCFKnownLocationUserByName. Supporting UserAny is, therefore, necessary. There are some ways of accessing _kCFKnownLocationUserByName from the CF API, but it seems that the API only allows Current or Any, even if they are not enforced. In any case, Android do not have Unix usernames, so ByName doesn't make sense. The change maps AnyUser into a directory inside the preferences of the HOME of the user, and other user names into another subdirectory. Each app will have their own set of Any and ByName, but at least they are not confussed with the CurrentUser preferences. Additionally, instead of picking up a CFFIXEDUSE_HOME, request the home directory from CFUtilities, since it deals with HOME, HOMEDIR and CFFIXED_HOME appropiedly, since HOME is necessary for many other things. The current code will have aborted the test suite, while the modified code, passes the test suite for UserDefaults. --- .../Base.subproj/CFKnownLocations.c | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/CoreFoundation/Base.subproj/CFKnownLocations.c b/CoreFoundation/Base.subproj/CFKnownLocations.c index d2c3507821..4ad3fbcd6e 100644 --- a/CoreFoundation/Base.subproj/CFKnownLocations.c +++ b/CoreFoundation/Base.subproj/CFKnownLocations.c @@ -12,6 +12,7 @@ #include #include "CFPriv.h" #include "CFInternal.h" +#include "CFUtilities.h" #include @@ -93,23 +94,26 @@ CFURLRef _Nullable _CFKnownLocationCreatePreferencesURLForUser(CFKnownLocationUs #elif TARGET_OS_ANDROID + // Android doesn't support users, and apps cannot write outside their + // sandbox. All the preferences will be local to the application, mapping + // "any user" and other users by name to different directories inside the + // sandbox. + CFURLRef userdir = CFCopyHomeDirectoryURL(); switch (user) { - case _kCFKnownLocationUserAny: - case _kCFKnownLocationUserByName: - abort(); - case _kCFKnownLocationUserCurrent: { - const char *buffer = getenv("CFFIXED_USER_HOME"); - if (buffer == NULL || *buffer == '\0') { - CFLog(__kCFLogAssertion, CFSTR("CFFIXED_USER_HOME is unset")); - HALT; - } - - CFURLRef userdir = CFURLCreateFromFileSystemRepresentation(kCFAllocatorSystemDefault, (const unsigned char *)buffer, strlen(buffer), true); - location = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, CFSTR("/Apple/Library/Preferences"), kCFURLPOSIXPathStyle, true, userdir); - CFRelease(userdir); - break; - } + case _kCFKnownLocationUserAny: + location = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, CFSTR("/Apple/Library/Preferences/AnyUser"), kCFURLPOSIXPathStyle, true, userdir); + break; + case _kCFKnownLocationUserByName: { + CFURLRef tmp = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, CFSTR("/Apple/Library/Preferences/ByUser"), kCFURLPOSIXPathStyle, true, userdir); + location = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, username, kCFURLPOSIXPathStyle, true, tmp); + CFRelease(tmp); + break; + } + case _kCFKnownLocationUserCurrent: + location = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, CFSTR("/Apple/Library/Preferences"), kCFURLPOSIXPathStyle, true, userdir); + break; } + CFRelease(userdir); #else