this repo has no description
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
67static const char * const prefixAll[] = {
68 Tilde,
69 "",
70 Network,
71 ""
72};
73static const char * const prefixAllSystem[] = {
74 Tilde,
75 "",
76 Network,
77 System
78};
79static const char * const prefixNoUserSystem[] = {
80 NULL,
81 "",
82 Network,
83 NULL
84};
85static const char * const prefixNoNetwork[] = {
86 Tilde,
87 "",
88 NULL,
89 System
90};
91static const char * const prefixSystemOnly[] = {
92 NULL,
93 NULL,
94 NULL,
95 System
96};
97static const char * const prefixUserOnly[] = {
98 Tilde,
99 NULL,
100 NULL,
101 NULL
102};
103
104static const char * const _prefixNetwork4[] = {
105 Network,
106 Network,
107 Network,
108 Network
109};
110static const char * const _prefixNone4[] = {
111 "",
112 "",
113 "",
114 ""
115};
116static const char * const _prefixTilde4[] = {
117 Tilde,
118 Tilde,
119 Tilde,
120 Tilde
121};
122static const char * const * const prefixAllApplicationsDirectory[] = {
123 _prefixTilde4,
124 _prefixNone4,
125 _prefixNetwork4,
126 _prefixNone4
127};
128static const char * const baseAllApplicationsDirectory[] = {
129 NSApplicationDirectoryBase,
130 NSAdminApplicationDirectoryBase,
131 NSDeveloperApplicationDirectoryBase,
132 NSDemoApplicationDirectoryBase
133};
134
135static const char * const _prefixNetwork2[] = {
136 Network,
137 Network
138};
139static const char * const _prefixNone2[] = {
140 "",
141 ""
142};
143static const char * const _prefixSystemNone2[] = {
144 System,
145 ""
146};
147static const char * const _prefixTilde2[] = {
148 Tilde,
149 Tilde
150};
151static const char * const * const prefixAllLibrariesDirectory[] = {
152 _prefixTilde2,
153 _prefixNone2,
154 _prefixNetwork2,
155 _prefixSystemNone2
156};
157static const char * const baseAllLibrariesDirectory[] = {
158 NSLibraryDirectoryBase,
159 NSDeveloperDirectoryBase
160};
161
162// The dirInfo table drives path creation
163static 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
297NSSearchPathEnumerationState 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
319static const char *nextRoot = NULL;
320static pthread_once_t nextRoot_init_once = PTHREAD_ONCE_INIT;
321
322static void
323nextRoot_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
333NSSearchPathEnumerationState 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}