Skip to content

Commit 63c1baf

Browse files
committed
Change paths to be FHS/XDG-friendly in CFPreferences.
1 parent a4ca69e commit 63c1baf

File tree

6 files changed

+210
-37
lines changed

6 files changed

+210
-37
lines changed

CoreFoundation/Base.subproj/CFFileUtilities.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,7 +1179,7 @@ CF_PRIVATE void _CFIterateDirectory(CFStringRef directoryPath, Boolean appendSla
11791179
}
11801180

11811181

1182-
#if DEPLOYMENT_RUNTIME_SWIFT
1182+
#if !DEPLOYMENT_RUNTIME_OBJC
11831183

11841184
// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
11851185
// Version 0.8
@@ -1356,5 +1356,5 @@ CF_PRIVATE CFArrayRef _CFCreateCFArrayByTokenizingString(const char *values, cha
13561356
return CFArrayCreate(kCFAllocatorSystemDefault, NULL, 0, &kCFTypeArrayCallBacks);
13571357
}
13581358

1359-
#endif
1359+
#endif // !DEPLOYMENT_RUNTIME_OBJC
13601360

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/* CFKnownLocations.c
2+
Copyright (c) 1999-2017, Apple Inc. and the Swift project authors
3+
4+
Portions Copyright (c) 2014-2017, Apple Inc. and the Swift project authors
5+
Licensed under Apache License v2.0 with Runtime Library Exception
6+
See http://swift.org/LICENSE.txt for license information
7+
See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
8+
*/
9+
10+
#include "CFKnownLocations.h"
11+
12+
#include <CoreFoundation/CFString.h>
13+
#include "CFPriv.h"
14+
#include "CFInternal.h"
15+
16+
CONST_STRING_DECL(_kCFKnownLocationUserAny, " == _kCFKnownLocationUserAny");
17+
CONST_STRING_DECL(_kCFKnownLocationUserCurrent, " == _kCFKnownLocationUserCurrent");
18+
19+
CFURLRef _Nullable _CFKnownLocationCreatePreferencesURLForUser(CFKnownLocationUser user) {
20+
CFURLRef location = NULL;
21+
22+
#if (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
23+
24+
/*
25+
Building for a Darwin OS. (We use these paths on Swift builds as well, so that we can interoperate a little with Darwin's defaults(1) command and the other system facilities; but you want to use the system version of CF if possible on those platforms, which will talk to cfprefsd(8) and has stronger interprocess consistency guarantees.)
26+
27+
User:
28+
- Any: /Library/Preferences
29+
- Current: $HOME/Library/Preferences
30+
*/
31+
32+
if (user == _kCFKnownLocationUserAny) {
33+
location = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, CFSTR("/Library/Preferences"), kCFURLPOSIXPathStyle, true);
34+
} else {
35+
if (user == _kCFKnownLocationUserCurrent) {
36+
user = NULL;
37+
}
38+
39+
CFURLRef home = CFCopyHomeDirectoryURLForUser(user);
40+
location = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, CFSTR("/Library/Preferences"), kCFURLPOSIXPathStyle, true, home);
41+
CFRelease(home);
42+
}
43+
44+
#elif !DEPLOYMENT_RUNTIME_OBJC && !DEPLOYMENT_TARGET_WINDOWS
45+
46+
/*
47+
Building for an OS that uses the FHS, BSD's hier(7), and/or the XDG specification for paths:
48+
49+
User:
50+
- Any: /usr/local/etc/
51+
- Current: $XDG_CONFIG_PATH (usually: $HOME/.config/).
52+
*/
53+
54+
if (user == _kCFKnownLocationUserAny) {
55+
location = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, CFSTR("/usr/local/etc"), kCFURLPOSIXPathStyle, true);
56+
} else {
57+
assert(user == _kCFKnownLocationUserCurrent);
58+
59+
if (user == _kCFKnownLocationUserCurrent) {
60+
location = _CFXDGCreateConfigHomePath();
61+
}
62+
}
63+
64+
#else
65+
66+
#error For this platform, you need to define a preferences path for both 'any user' (i.e. installation-wide preferences) or the current user.
67+
68+
#endif
69+
70+
return location;
71+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/* CFKnownLocations.h
2+
Copyright (c) 1999-2017, Apple Inc. and the Swift project authors
3+
4+
Portions Copyright (c) 2014-2017, Apple Inc. and the Swift project authors
5+
Licensed under Apache License v2.0 with Runtime Library Exception
6+
See http://swift.org/LICENSE.txt for license information
7+
See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
8+
*/
9+
10+
#if !defined(__COREFOUNDATION_CFKNOWNLOCATIONS__)
11+
#define __COREFOUNDATION_CFKNOWNLOCATIONS__ 1
12+
13+
#include <CoreFoundation/CFBase.h>
14+
#include <CoreFoundation/CFURL.h>
15+
16+
CF_ASSUME_NONNULL_BEGIN
17+
CF_EXTERN_C_BEGIN
18+
19+
typedef CFStringRef CFKnownLocationUser CF_TYPED_EXTENSIBLE_ENUM;
20+
21+
CF_EXPORT
22+
const CFKnownLocationUser _kCFKnownLocationUserAny;
23+
24+
CF_EXPORT
25+
const CFKnownLocationUser _kCFKnownLocationUserCurrent;
26+
27+
/* A note on support:
28+
29+
- We document that CFPreferences… can only take AnyUser or CurrentUser as users.
30+
- The code we shipped so far accepted the name of any one user on the current system as an alternative, but:
31+
- For platforms that use the XDG spec to identify a configuration path in a user's home, we cannot determine that path for any user other than the one we're currently running as.
32+
33+
So:
34+
- We're keeping that behavior when building Core Foundation for Darwin/ObjC for compatibility, hence the _EXTENSIBLE above; but
35+
- For Swift and any new platform, we are enforcing the documented constraint. Using a user value other than …Any or …Current above will assert (or return NULL if asserts are off).
36+
37+
See CFKnownLocations.c for a summary of what paths are returned.
38+
*/
39+
40+
CF_EXPORT
41+
CFURLRef _Nullable _CFKnownLocationCreatePreferencesURLForUser(CFKnownLocationUser user);
42+
43+
CF_EXTERN_C_END
44+
CF_ASSUME_NONNULL_END
45+
46+
#endif /* __COREFOUNDATION_CFKNOWNLOCATIONS__ */

CoreFoundation/Base.subproj/CFPriv.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include <CoreFoundation/CFRunLoop.h>
4343
#include <CoreFoundation/CFSocket.h>
4444
#include <CoreFoundation/CFBundlePriv.h>
45+
#include <CoreFoundation/CFKnownLocations.h>
4546

4647
CF_EXTERN_C_BEGIN
4748

@@ -655,6 +656,34 @@ CF_EXPORT void _CFGetPathExtensionRangesFromPathComponent(CFStringRef inName, CF
655656
CF_EXPORT Boolean _CFExtensionUniCharsIsValidToAppend(const UniChar *uchars, CFIndex ucharsLength) API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
656657
CF_EXPORT Boolean _CFExtensionIsValidToAppend(CFStringRef extension) API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
657658

659+
660+
#if !DEPLOYMENT_RUNTIME_OBJC
661+
662+
// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
663+
// Version 0.8
664+
665+
// note: All paths set in these environment variables must be absolute.
666+
667+
/// a single base directory relative to which user-specific data files should be written. This directory is defined by the environment variable $XDG_DATA_HOME.
668+
CF_EXPORT CFStringRef _CFXDGCreateDataHomePath(void) CF_RETURNS_RETAINED;
669+
670+
/// a single base directory relative to which user-specific configuration files should be written. This directory is defined by the environment variable $XDG_CONFIG_HOME.
671+
CF_EXPORT CFStringRef _CFXDGCreateConfigHomePath(void) CF_RETURNS_RETAINED;
672+
673+
/// a set of preference ordered base directories relative to which data files should be searched. This set of directories is defined by the environment variable $XDG_DATA_DIRS.
674+
CF_EXPORT CFArrayRef _CFXDGCreateDataDirectoriesPaths(void) CF_RETURNS_RETAINED;
675+
676+
/// a set of preference ordered base directories relative to which configuration files should be searched. This set of directories is defined by the environment variable $XDG_CONFIG_DIRS.
677+
CF_EXPORT CFArrayRef _CFXDGCreateConfigDirectoriesPaths(void) CF_RETURNS_RETAINED;
678+
679+
/// a single base directory relative to which user-specific non-essential (cached) data should be written. This directory is defined by the environment variable $XDG_CACHE_HOME.
680+
CF_EXPORT CFStringRef _CFXDGCreateCacheDirectoryPath(void) CF_RETURNS_RETAINED;
681+
682+
/// a single base directory relative to which user-specific runtime files and other file objects should be placed. This directory is defined by the environment variable $XDG_RUNTIME_DIR.
683+
CF_EXPORT CFStringRef _CFXDGCreateRuntimeDirectoryPath(void) CF_RETURNS_RETAINED;
684+
685+
#endif // !DEPLOYMENT_RUNTIME_OBJC
686+
658687
CF_EXTERN_C_END
659688

660689
#endif /* ! __COREFOUNDATION_CFPRIV__ */

CoreFoundation/Preferences.subproj/CFPreferences.c

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
#include <CoreFoundation/CFUUID.h>
2727
#endif
2828

29+
#include <assert.h>
30+
2931
#if DEBUG_PREFERENCES_MEMORY
3032
#include "../Tests/CFCountingAllocator.c"
3133
#endif
@@ -182,37 +184,29 @@ static CFURLRef _preferencesDirectoryForUserHostSafetyLevel(CFStringRef userName
182184
return url;
183185

184186
#else
185-
CFURLRef home = NULL;
186-
CFURLRef url;
187-
int levels = 0;
188-
// if (hostName != kCFPreferencesCurrentHost && hostName != kCFPreferencesAnyHost) return NULL; // Arbitrary host access not permitted
187+
CFURLRef location = NULL;
188+
189+
CFKnownLocationUser user;
190+
189191
if (userName == kCFPreferencesAnyUser) {
190-
if (!home) home = CFURLCreateWithFileSystemPath(alloc, CFSTR("/Library/Preferences/"), kCFURLPOSIXPathStyle, true);
191-
levels = 1;
192-
if (hostName == kCFPreferencesCurrentHost) url = home;
193-
else {
194-
url = CFURLCreateWithFileSystemPathRelativeToBase(alloc, CFSTR("Network/"), kCFURLPOSIXPathStyle, true, home);
195-
levels ++;
196-
CFRelease(home);
197-
}
192+
user = _kCFKnownLocationUserAny;
193+
} else if (userName == kCFPreferencesCurrentUser) {
194+
user = _kCFKnownLocationUserCurrent;
198195
} else {
199-
home = CFCopyHomeDirectoryURLForUser((userName == kCFPreferencesCurrentUser) ? NULL : userName);
200-
if (home) {
201-
url = (safeLevel > 0) ? CFURLCreateWithFileSystemPathRelativeToBase(alloc, CFSTR("Library/Safe Preferences/"), kCFURLPOSIXPathStyle, true, home) :
202-
CFURLCreateWithFileSystemPathRelativeToBase(alloc, CFSTR("Library/Preferences/"), kCFURLPOSIXPathStyle, true, home);
203-
levels = 2;
204-
CFRelease(home);
205-
if (hostName != kCFPreferencesAnyHost) {
206-
home = url;
207-
url = CFURLCreateWithFileSystemPathRelativeToBase(alloc, CFSTR("ByHost/"), kCFURLPOSIXPathStyle, true, home);
208-
levels ++;
209-
CFRelease(home);
210-
}
211-
} else {
212-
url = NULL;
213-
}
196+
user = userName;
214197
}
215-
return url;
198+
199+
CFURLRef base = _CFKnownLocationCreatePreferencesURLForUser(user);
200+
201+
if (hostName == kCFPreferencesCurrentHost) {
202+
location = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, CFSTR("ByHost"), kCFURLPOSIXPathStyle, true, base);
203+
} else {
204+
assert(hostName == kCFPreferencesAnyHost);
205+
location = CFRetain(base);
206+
}
207+
208+
CFRelease(base);
209+
return location;
216210
#endif
217211
}
218212

Foundation.xcodeproj/project.pbxproj

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
0383A1751D2E558A0052E5D1 /* TestStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0383A1741D2E558A0052E5D1 /* TestStream.swift */; };
1111
03B6F5841F15F339004F25AF /* TestURLProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B6F5831F15F339004F25AF /* TestURLProtocol.swift */; };
1212
1520469B1D8AEABE00D02E36 /* HTTPServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1520469A1D8AEABE00D02E36 /* HTTPServer.swift */; };
13+
153E951120111DC500F250BE /* CFKnownLocations.h in Headers */ = {isa = PBXBuildFile; fileRef = 153E950F20111DC500F250BE /* CFKnownLocations.h */; settings = {ATTRIBUTES = (Private, ); }; };
14+
153E951220111DC500F250BE /* CFKnownLocations.c in Sources */ = {isa = PBXBuildFile; fileRef = 153E951020111DC500F250BE /* CFKnownLocations.c */; };
1315
159884921DCC877700E3314C /* TestHTTPCookieStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 159884911DCC877700E3314C /* TestHTTPCookieStorage.swift */; };
1416
231503DB1D8AEE5D0061694D /* TestDecimal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 231503DA1D8AEE5D0061694D /* TestDecimal.swift */; };
1517
294E3C1D1CC5E19300E4F44C /* TestNSAttributedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 294E3C1C1CC5E19300E4F44C /* TestNSAttributedString.swift */; };
@@ -498,6 +500,8 @@
498500
0383A1741D2E558A0052E5D1 /* TestStream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestStream.swift; sourceTree = "<group>"; };
499501
03B6F5831F15F339004F25AF /* TestURLProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestURLProtocol.swift; sourceTree = "<group>"; };
500502
1520469A1D8AEABE00D02E36 /* HTTPServer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTTPServer.swift; sourceTree = "<group>"; };
503+
153E950F20111DC500F250BE /* CFKnownLocations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CFKnownLocations.h; sourceTree = "<group>"; };
504+
153E951020111DC500F250BE /* CFKnownLocations.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = CFKnownLocations.c; sourceTree = "<group>"; };
501505
159884911DCC877700E3314C /* TestHTTPCookieStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestHTTPCookieStorage.swift; sourceTree = "<group>"; };
502506
22B9C1E01C165D7A00DECFF9 /* TestDate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestDate.swift; sourceTree = "<group>"; };
503507
231503DA1D8AEE5D0061694D /* TestDecimal.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestDecimal.swift; sourceTree = "<group>"; };
@@ -1091,6 +1095,8 @@
10911095
5B5D895F1BBDABF400234F36 /* CFUtilities.h */,
10921096
5B5D89541BBDAA0100234F36 /* CFUUID.c */,
10931097
5B5D89531BBDAA0100234F36 /* CFUUID.h */,
1098+
153E950F20111DC500F250BE /* CFKnownLocations.h */,
1099+
153E951020111DC500F250BE /* CFKnownLocations.c */,
10941100
5B5D88B51BBC978900234F36 /* CoreFoundation_Prefix.h */,
10951101
5B5D895B1BBDAB7E00234F36 /* CoreFoundation.h */,
10961102
5B5D88C61BBC983600234F36 /* ForFoundationOnly.h */,
@@ -1912,6 +1918,7 @@
19121918
5B7C8AD61BEA80FC00C5B690 /* CFPlugIn.h in Headers */,
19131919
5B7C8AD81BEA80FC00C5B690 /* CFPreferences.h in Headers */,
19141920
5B7C8AF11BEA81AC00C5B690 /* CFStreamAbstract.h in Headers */,
1921+
153E951120111DC500F250BE /* CFKnownLocations.h in Headers */,
19151922
5B7C8AFE1BEA81AC00C5B690 /* CFURLComponents.h in Headers */,
19161923
5B7C8ABC1BEA805C00C5B690 /* CFAvailability.h in Headers */,
19171924
5B6E11A91DA45EB5009B48A3 /* CFDateFormatter_Private.h in Headers */,
@@ -2363,6 +2370,7 @@
23632370
5B7C8A961BEA7FF900C5B690 /* CFBundle_Binary.c in Sources */,
23642371
5B7C8AAC1BEA800D00C5B690 /* CFString.c in Sources */,
23652372
5B7C8A821BEA7FCE00C5B690 /* CFStorage.c in Sources */,
2373+
153E951220111DC500F250BE /* CFKnownLocations.c in Sources */,
23662374
5B7C8AAF1BEA800D00C5B690 /* CFStringUtilities.c in Sources */,
23672375
5B7C8A891BEA7FDB00C5B690 /* CFNumberFormatter.c in Sources */,
23682376
5B7C8A8C1BEA7FE200C5B690 /* CFDate.c in Sources */,
@@ -2660,7 +2668,11 @@
26602668
INFOPLIST_FILE = Foundation/Info.plist;
26612669
INIT_ROUTINE = "___CFInitialize";
26622670
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
2663-
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
2671+
LD_RUNPATH_SEARCH_PATHS = (
2672+
"$(inherited)",
2673+
"@executable_path/../Frameworks",
2674+
"@loader_path/Frameworks",
2675+
);
26642676
OTHER_CFLAGS = (
26652677
"-DCF_BUILDING_CF",
26662678
"-DDEPLOYMENT_TARGET_MACOSX",
@@ -2732,7 +2744,11 @@
27322744
INFOPLIST_FILE = Foundation/Info.plist;
27332745
INIT_ROUTINE = "___CFInitialize";
27342746
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
2735-
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
2747+
LD_RUNPATH_SEARCH_PATHS = (
2748+
"$(inherited)",
2749+
"@executable_path/../Frameworks",
2750+
"@loader_path/Frameworks",
2751+
);
27362752
OTHER_CFLAGS = (
27372753
"-DCF_BUILDING_CF",
27382754
"-DDEPLOYMENT_TARGET_MACOSX",
@@ -2880,7 +2896,11 @@
28802896
/usr/include/libxml2,
28812897
);
28822898
INFOPLIST_FILE = TestFoundation/Resources/Info.plist;
2883-
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
2899+
LD_RUNPATH_SEARCH_PATHS = (
2900+
"$(inherited)",
2901+
"@executable_path/../Frameworks",
2902+
"@loader_path/../Frameworks",
2903+
);
28842904
LIBRARY_SEARCH_PATHS = "$(inherited)";
28852905
MACH_O_TYPE = mh_execute;
28862906
OTHER_SWIFT_FLAGS = "-DDEPLOYMENT_ENABLE_LIBDISPATCH -swift-version 4";
@@ -2906,7 +2926,11 @@
29062926
/usr/include/libxml2,
29072927
);
29082928
INFOPLIST_FILE = TestFoundation/Resources/Info.plist;
2909-
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
2929+
LD_RUNPATH_SEARCH_PATHS = (
2930+
"$(inherited)",
2931+
"@executable_path/../Frameworks",
2932+
"@loader_path/../Frameworks",
2933+
);
29102934
LIBRARY_SEARCH_PATHS = "$(inherited)";
29112935
MACH_O_TYPE = mh_execute;
29122936
OTHER_SWIFT_FLAGS = "-DDEPLOYMENT_ENABLE_LIBDISPATCH -swift-version 4";
@@ -2930,7 +2954,12 @@
29302954
CODE_SIGN_IDENTITY = "";
29312955
COMBINE_HIDPI_IMAGES = YES;
29322956
INFOPLIST_FILE = TestFoundation/xdgTestHelper/Info.plist;
2933-
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../../.. @loader_path/../../.. @executable_path/../Frameworks";
2957+
LD_RUNPATH_SEARCH_PATHS = (
2958+
"$(inherited)",
2959+
"@executable_path/../../..",
2960+
"@loader_path/../../..",
2961+
"@executable_path/../Frameworks",
2962+
);
29342963
MACOSX_DEPLOYMENT_TARGET = 10.12;
29352964
PRODUCT_BUNDLE_IDENTIFIER = org.swift.xdgTestHelper;
29362965
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -2952,7 +2981,12 @@
29522981
CODE_SIGN_IDENTITY = "";
29532982
COMBINE_HIDPI_IMAGES = YES;
29542983
INFOPLIST_FILE = TestFoundation/xdgTestHelper/Info.plist;
2955-
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../../.. @loader_path/../../.. @executable_path/../Frameworks";
2984+
LD_RUNPATH_SEARCH_PATHS = (
2985+
"$(inherited)",
2986+
"@executable_path/../../..",
2987+
"@loader_path/../../..",
2988+
"@executable_path/../Frameworks",
2989+
);
29562990
MACOSX_DEPLOYMENT_TARGET = 10.12;
29572991
PRODUCT_BUNDLE_IDENTIFIER = org.swift.xdgTestHelper;
29582992
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -3044,4 +3078,3 @@
30443078
};
30453079
rootObject = 5B5D88541BBC938800234F36 /* Project object */;
30463080
}
3047-

0 commit comments

Comments
 (0)