]> git.saurik.com Git - apple/libc.git/blob - gen/NSSystemDirectories.c
Libc-763.12.tar.gz
[apple/libc.git] / gen / NSSystemDirectories.c
1 /*
2 * Copyright (c) 1999, 2008 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 #include <NSSystemDirectories.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/param.h>
27 #include <unistd.h>
28 #include <pthread.h>
29
30 #define NSUserDomainIndex 0
31 #define NSLocalDomainIndex 1
32 #define NSNetworkDomainIndex 2
33 #define NSSystemDomainIndex 3
34
35 #define numDomains (NSSystemDomainIndex + 1)
36 #define DomainMask ((1 << numDomains) - 1)
37
38 #define addNextRoot(x) (*(x) == '/' || *(x) == 0)
39
40 #define Network "/Network"
41 #define System "/System"
42 #define Tilde "~"
43
44 #define NSApplicationDirectoryBase "/Applications"
45 #define NSDemoApplicationDirectoryBase "/Applications/Demos"
46 #define NSDeveloperApplicationDirectoryBase "/Developer/Applications"
47 #define NSAdminApplicationDirectoryBase "/Applications/Utilities"
48 #define NSLibraryDirectoryBase "/Library"
49 #define NSDeveloperDirectoryBase "/Developer"
50 #define NSUserDirectoryBase "/Users"
51 #define NSDocumentationDirectoryBase "/Library/Documentation"
52 #define NSDocumentDirectoryBase "/Documents"
53 #define NSCoreServiceDirectoryBase "/Library/CoreServices"
54 #define NSAutosavedDocumentsDirectoryBase "/Library/Autosave Information"
55 #define NSDesktopDirectoryBase "/Desktop"
56 #define NSCachesDirectoryBase "/Library/Caches"
57 #define NSInputMethodsDirectoryBase "/Library/Input Methods"
58 #define NSMoviesDirectoryBase "/Movies"
59 #define NSMusicDirectoryBase "/Music"
60 #define NSPicturesDirectoryBase "/Pictures"
61 #define NSPrinterDescriptionDirectoryBase "/Library/Printers/PPDs"
62 #define NSSharedPublicDirectoryBase "/Public"
63 #define NSPreferencePanesDirectoryBase "/Library/PreferencePanes"
64 #define NSApplicationSupportDirectoryBase "/Library/Application Support"
65 #define NSDownloadsDirectoryBase "/Downloads"
66
67 static const char * const prefixAll[] = {
68 Tilde,
69 "",
70 Network,
71 ""
72 };
73 static const char * const prefixAllSystem[] = {
74 Tilde,
75 "",
76 Network,
77 System
78 };
79 static const char * const prefixNoUserSystem[] = {
80 NULL,
81 "",
82 Network,
83 NULL
84 };
85 static const char * const prefixNoNetwork[] = {
86 Tilde,
87 "",
88 NULL,
89 System
90 };
91 static const char * const prefixSystemOnly[] = {
92 NULL,
93 NULL,
94 NULL,
95 System
96 };
97 static const char * const prefixUserOnly[] = {
98 Tilde,
99 NULL,
100 NULL,
101 NULL
102 };
103
104 static const char * const _prefixNetwork4[] = {
105 Network,
106 Network,
107 Network,
108 Network
109 };
110 static const char * const _prefixNone4[] = {
111 "",
112 "",
113 "",
114 ""
115 };
116 static const char * const _prefixTilde4[] = {
117 Tilde,
118 Tilde,
119 Tilde,
120 Tilde
121 };
122 static const char * const * const prefixAllApplicationsDirectory[] = {
123 _prefixTilde4,
124 _prefixNone4,
125 _prefixNetwork4,
126 _prefixNone4
127 };
128 static const char * const baseAllApplicationsDirectory[] = {
129 NSApplicationDirectoryBase,
130 NSAdminApplicationDirectoryBase,
131 NSDeveloperApplicationDirectoryBase,
132 NSDemoApplicationDirectoryBase
133 };
134
135 static const char * const _prefixNetwork2[] = {
136 Network,
137 Network
138 };
139 static const char * const _prefixNone2[] = {
140 "",
141 ""
142 };
143 static const char * const _prefixSystemNone2[] = {
144 System,
145 ""
146 };
147 static const char * const _prefixTilde2[] = {
148 Tilde,
149 Tilde
150 };
151 static const char * const * const prefixAllLibrariesDirectory[] = {
152 _prefixTilde2,
153 _prefixNone2,
154 _prefixNetwork2,
155 _prefixSystemNone2
156 };
157 static const char * const baseAllLibrariesDirectory[] = {
158 NSLibraryDirectoryBase,
159 NSDeveloperDirectoryBase
160 };
161
162 // The dirInfo table drives path creation
163 static struct {
164 int pathsPerDomain;
165 const void * const * const prefix;
166 const void * const base;
167 } dirInfo[] = {
168 { // NSApplicationDirectory
169 1,
170 (const void * const * const)prefixAll,
171 (const void * const)NSApplicationDirectoryBase
172 },
173 { // NSDemoApplicationDirectory
174 1,
175 (const void * const * const)prefixAll,
176 (const void * const)NSDemoApplicationDirectoryBase
177 },
178 { // NSDeveloperApplicationDirectory
179 1,
180 (const void * const * const)prefixAll,
181 (const void * const)NSDeveloperApplicationDirectoryBase
182 },
183 { // NSAdminApplicationDirectory
184 1,
185 (const void * const * const)prefixAll,
186 (const void * const)NSAdminApplicationDirectoryBase
187 },
188 { // NSLibraryDirectory
189 1,
190 (const void * const * const)prefixAllSystem,
191 (const void * const)NSLibraryDirectoryBase
192 },
193 { // NSDeveloperDirectory
194 1,
195 (const void * const * const)prefixAll,
196 (const void * const)NSDeveloperDirectoryBase
197 },
198 { // NSUserDirectory
199 1,
200 (const void * const * const)prefixNoUserSystem,
201 (const void * const)NSUserDirectoryBase
202 },
203 { // NSDocumentationDirectory
204 1,
205 (const void * const * const)prefixAllSystem,
206 (const void * const)NSDocumentationDirectoryBase
207 },
208 { // NSDocumentDirectory
209 1,
210 (const void * const * const)prefixUserOnly,
211 (const void * const)NSDocumentDirectoryBase
212 },
213 { // NSCoreServiceDirectory
214 1,
215 (const void * const * const)prefixSystemOnly,
216 (const void * const)NSCoreServiceDirectoryBase
217 },
218 { // NSAutosavedInformationDirectory
219 1,
220 (const void * const * const)prefixUserOnly,
221 (const void * const)NSAutosavedDocumentsDirectoryBase
222 },
223 { // NSDesktopDirectory
224 1,
225 (const void * const * const)prefixUserOnly,
226 (const void * const)NSDesktopDirectoryBase
227 },
228 { // NSCachesDirectory
229 1,
230 (const void * const * const)prefixNoNetwork,
231 (const void * const)NSCachesDirectoryBase
232 },
233 { // NSApplicationSupportDirectory
234 1,
235 (const void * const * const)prefixAll,
236 (const void * const)NSApplicationSupportDirectoryBase
237 },
238 { // NSDownloadsDirectory
239 1,
240 (const void * const * const)prefixUserOnly,
241 (const void * const)NSDownloadsDirectoryBase
242 },
243 { // NSInputMethodsDirectory
244 1,
245 (const void * const * const)prefixAllSystem,
246 (const void * const)NSInputMethodsDirectoryBase
247 },
248 { // NSMoviesDirectory
249 1,
250 (const void * const * const)prefixUserOnly,
251 (const void * const)NSMoviesDirectoryBase
252 },
253 { // NSMusicDirectory
254 1,
255 (const void * const * const)prefixUserOnly,
256 (const void * const)NSMusicDirectoryBase
257 },
258 { // NSPicturesDirectory
259 1,
260 (const void * const * const)prefixUserOnly,
261 (const void * const)NSPicturesDirectoryBase
262 },
263 { // NSPrinterDescriptionDirectory
264 1,
265 (const void * const * const)prefixSystemOnly,
266 (const void * const)NSPrinterDescriptionDirectoryBase
267 },
268 { // NSSharedPublicDirectory
269 1,
270 (const void * const * const)prefixUserOnly,
271 (const void * const)NSSharedPublicDirectoryBase
272 },
273 { // NSPreferencePanesDirectory
274 1,
275 (const void * const * const)prefixNoNetwork,
276 (const void * const)NSPreferencePanesDirectoryBase
277 },
278 { // NSAllApplicationsDirectory
279 4,
280 (const void * const * const)prefixAllApplicationsDirectory,
281 (const void * const)baseAllApplicationsDirectory
282 },
283 { // NSAllLibrariesDirectory
284 2,
285 (const void * const * const)prefixAllLibrariesDirectory,
286 (const void * const)baseAllLibrariesDirectory
287 }
288 };
289
290 #define Index(dir) (((dir) >= NSApplicationDirectory && (dir) <= NSPreferencePanesDirectory) ? ((dir) - 1) : (((dir) >= NSAllApplicationsDirectory && (dir) <= NSAllLibrariesDirectory) ? ((dir) - NSAllApplicationsDirectory + NSPreferencePanesDirectory) : -1))
291
292 #define invalidDomains 0x00 // some domains may be invalid on non-Mach systems
293 #define ByteMask 0xff
294 #define DirShift 24
295 #define IndexShift 16
296
297 NSSearchPathEnumerationState NSStartSearchPathEnumeration(NSSearchPathDirectory dir, NSSearchPathDomainMask domainMask) {
298 // The state is AABBCCCC, where
299 // AA is the dir(s) requested
300 // BB is the current state of dirs (if AA < 100, then this is always 0; otherwise it goes up to number of dirs)
301 // CCCC is the domains requested
302 // the state always contains the next item; if CCCC is 0, then we're done
303 int i;
304
305 if((i = Index(dir)) < 0) {
306 return 0;
307 }
308 domainMask = domainMask & DomainMask & ~invalidDomains; // Just leave useful bits in there
309
310 // Trim Duplicates - This assumes the compiler generates a single address
311 // for multiple occurrences of the same literal strings.
312 if ((domainMask & (NSLocalDomainMask | NSSystemDomainMask)) == (NSLocalDomainMask | NSSystemDomainMask) && dirInfo[i].prefix[NSLocalDomainIndex] == dirInfo[i].prefix[NSSystemDomainIndex]) {
313 domainMask &= ~NSSystemDomainMask;
314 }
315
316 return (dir << DirShift) + domainMask;
317 }
318
319 static const char *nextRoot = NULL;
320 static pthread_once_t nextRoot_init_once = PTHREAD_ONCE_INIT;
321
322 static void
323 nextRoot_init(void)
324 {
325 if (!issetugid() && (nextRoot = getenv("NEXT_ROOT")) != NULL) {
326 nextRoot = strdup(nextRoot);
327 }
328 if (nextRoot == NULL) {
329 nextRoot = "";
330 }
331 }
332
333 NSSearchPathEnumerationState NSGetNextSearchPathEnumeration(NSSearchPathEnumerationState state, char *path) {
334 int dir = (state >> DirShift) & ByteMask;
335 int domainMask = state & DomainMask;
336 int domain, i, n;
337 const char *prefix, *base;
338
339 if ((i = Index(dir)) < 0 || (domain = ffs(domainMask)) == 0)
340 return 0;
341 domain--; // adjust to zero-based index
342
343 if ((n = dirInfo[i].pathsPerDomain) == 1) {
344 const char * const *p = (const char * const *)dirInfo[i].prefix;
345 for (;;) { // loop, skipping over invalid domains (prefix is NULL)
346 domainMask &= ~(1 << domain);
347 if ((prefix = p[domain]) != NULL) {
348 break;
349 }
350 if ((domain = ffs(domainMask)) == 0) {
351 return 0;
352 }
353 domain--; // adjust to zero-based index
354 }
355 base = (const char *)dirInfo[i].base;
356 state = (dir << DirShift) + domainMask;
357 } else { // multiple paths per domain
358 const char * const **p = (const char * const **)dirInfo[i].prefix;
359 const char * const *b = (const char * const *)dirInfo[i].base;
360 int dirIndex = (state >> IndexShift) & ByteMask;
361
362 if (dirIndex >= n) { // done with the current domain, go to the next
363 domainMask &= ~(1 << domain);
364 if ((domain = ffs(domainMask)) == 0) {
365 return 0;
366 }
367 domain--; // adjust to zero-based index
368 dirIndex = 0;
369 }
370 prefix = p[domain][dirIndex];
371 base = b[dirIndex];
372 state = (dir << DirShift) + (++dirIndex << IndexShift) + domainMask;
373 }
374
375 if (addNextRoot(prefix)) {
376 if (pthread_once(&nextRoot_init_once, nextRoot_init) != 0 || nextRoot == NULL)// Error
377 return 0;
378 strlcpy(path, nextRoot, PATH_MAX);
379 } else {
380 *path = 0;
381 }
382 strlcat(path, prefix, PATH_MAX);
383 strlcat(path, base, PATH_MAX);
384
385 return state;
386 }