-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
Copy pathCFKnownLocations.c
157 lines (123 loc) · 6.02 KB
/
CFKnownLocations.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/* CFKnownLocations.c
Copyright (c) 1999-2017, Apple Inc. and the Swift project authors
Portions Copyright (c) 2014-2017, Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception
See http://swift.org/LICENSE.txt for license information
See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
*/
#include "CFKnownLocations.h"
#include <CoreFoundation/CFString.h>
#include "CFPriv.h"
#include "CFInternal.h"
#include "CFUtilities.h"
#include <assert.h>
#if TARGET_OS_WIN32
#include <userenv.h>
#endif
CFURLRef _Nullable _CFKnownLocationCreatePreferencesURLForUser(CFKnownLocationUser user, CFStringRef _Nullable username) {
CFURLRef location = NULL;
#if TARGET_OS_MAC
/*
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.)
User:
- Any: /Library/Preferences
- Current: $HOME/Library/Preferences
*/
switch (user) {
case _kCFKnownLocationUserAny:
location = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, CFSTR("/Library/Preferences"), kCFURLPOSIXPathStyle, true);
break;
case _kCFKnownLocationUserCurrent:
username = NULL;
// passthrough to:
case _kCFKnownLocationUserByName: {
CFURLRef home = CFCopyHomeDirectoryURLForUser(username);
location = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, CFSTR("/Library/Preferences"), kCFURLPOSIXPathStyle, true, home);
CFRelease(home);
break;
}
}
#elif !DEPLOYMENT_RUNTIME_OBJC && !TARGET_OS_WIN32 && !TARGET_OS_ANDROID
/*
Building for an OS that uses the FHS, BSD's hier(7), and/or the XDG specification for paths:
User:
- Any: /usr/local/etc/
- Current: $XDG_CONFIG_PATH (usually: $HOME/.config/).
*/
switch (user) {
case _kCFKnownLocationUserAny:
location = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, CFSTR("/usr/local/etc"), kCFURLPOSIXPathStyle, true);
break;
case _kCFKnownLocationUserByName:
assert(username == NULL);
// passthrough to:
case _kCFKnownLocationUserCurrent: {
CFStringRef path = _CFXDGCreateConfigHomePath();
location = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, path, kCFURLPOSIXPathStyle, true);
CFRelease(path);
break;
}
}
#elif TARGET_OS_WIN32
switch (user) {
case _kCFKnownLocationUserAny: {
DWORD size = 0;
GetAllUsersProfileDirectoryW(NULL, &size);
wchar_t* path = (wchar_t*)malloc(size * sizeof(wchar_t));
GetAllUsersProfileDirectoryW(path, &size);
CFStringRef allUsersPath = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, path, size - 1);
free(path);
location = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, allUsersPath, kCFURLWindowsPathStyle, true);
CFRelease(allUsersPath);
break;
}
case _kCFKnownLocationUserCurrent:
username = CFGetUserName();
// fallthrough
case _kCFKnownLocationUserByName: {
DWORD size = 0;
GetProfilesDirectoryW(NULL, &size);
wchar_t* path = (wchar_t*)malloc(size * sizeof(wchar_t));
GetProfilesDirectoryW(path, &size);
CFStringRef pathRef = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, path, size - 1);
free(path);
CFURLRef profilesDir = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, pathRef, kCFURLWindowsPathStyle, true);
CFRelease(pathRef);
CFURLRef usernameDir = CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, profilesDir, username, true);
CFURLRef appdataDir = CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, usernameDir, CFSTR("AppData"), true);
location = CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, appdataDir, CFSTR("Local"), true);
CFRelease(usernameDir);
CFRelease(appdataDir);
CFRelease(profilesDir);
if (user == _kCFKnownLocationUserCurrent) {
CFRelease(username);
}
break;
}
}
#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:
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
#error For this platform, you need to define a preferences path for both 'any user' (i.e. installation-wide preferences) or the current user.
#endif
return location;
}