2 * Copyright (c) 1999, 2008 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
23 #include <NSSystemDirectories.h>
26 #include <sys/param.h>
29 #define NSUserDomainIndex 0
30 #define NSLocalDomainIndex 1
31 #define NSNetworkDomainIndex 2
32 #define NSSystemDomainIndex 3
34 #define numDomains (NSSystemDomainIndex + 1)
35 #define DomainMask ((1 << numDomains) - 1)
37 #define addNextRoot(x) (*(x) == '/' || *(x) == 0)
39 #define Network "/Network"
40 #define System "/System"
43 #define NSApplicationDirectoryBase "/Applications"
44 #define NSDemoApplicationDirectoryBase "/Applications/Demos"
45 #define NSDeveloperApplicationDirectoryBase "/Developer/Applications"
46 #define NSAdminApplicationDirectoryBase "/Applications/Utilities"
47 #define NSLibraryDirectoryBase "/Library"
48 #define NSDeveloperDirectoryBase "/Developer"
49 #define NSUserDirectoryBase "/Users"
50 #define NSDocumentationDirectoryBase "/Library/Documentation"
51 #define NSDocumentDirectoryBase "/Documents"
52 #define NSCoreServiceDirectoryBase "/Library/CoreServices"
53 #define NSAutosavedDocumentsDirectoryBase "/Library/Autosave Information"
54 #define NSDesktopDirectoryBase "/Desktop"
55 #define NSCachesDirectoryBase "/Library/Caches"
56 #define NSInputMethodsDirectoryBase "/Library/Input Methods"
57 #define NSMoviesDirectoryBase "/Movies"
58 #define NSMusicDirectoryBase "/Music"
59 #define NSPicturesDirectoryBase "/Pictures"
60 #define NSPrinterDescriptionDirectoryBase "/Library/Printers/PPDs"
61 #define NSSharedPublicDirectoryBase "/Public"
62 #define NSPreferencePanesDirectoryBase "/Library/PreferencePanes"
63 #define NSApplicationSupportDirectoryBase "/Library/Application Support"
64 #define NSDownloadsDirectoryBase "/Downloads"
66 static const char * const prefixAll
[] = {
72 static const char * const prefixAllSystem
[] = {
78 static const char * const prefixNoUserSystem
[] = {
84 static const char * const prefixNoNetwork
[] = {
90 static const char * const prefixSystemOnly
[] = {
96 static const char * const prefixUserOnly
[] = {
103 static const char * const _prefixNetwork4
[] = {
109 static const char * const _prefixNone4
[] = {
115 static const char * const _prefixTilde4
[] = {
121 static const char * const * const prefixAllApplicationsDirectory
[] = {
127 static const char * const baseAllApplicationsDirectory
[] = {
128 NSApplicationDirectoryBase
,
129 NSAdminApplicationDirectoryBase
,
130 NSDeveloperApplicationDirectoryBase
,
131 NSDemoApplicationDirectoryBase
134 static const char * const _prefixNetwork2
[] = {
138 static const char * const _prefixNone2
[] = {
142 static const char * const _prefixSystemNone2
[] = {
146 static const char * const _prefixTilde2
[] = {
150 static const char * const * const prefixAllLibrariesDirectory
[] = {
156 static const char * const baseAllLibrariesDirectory
[] = {
157 NSLibraryDirectoryBase
,
158 NSDeveloperDirectoryBase
161 // The dirInfo table drives path creation
164 const void * const * const prefix
;
165 const void * const base
;
167 { // NSApplicationDirectory
169 (const void * const * const)prefixAll
,
170 (const void * const)NSApplicationDirectoryBase
172 { // NSDemoApplicationDirectory
174 (const void * const * const)prefixAll
,
175 (const void * const)NSDemoApplicationDirectoryBase
177 { // NSDeveloperApplicationDirectory
179 (const void * const * const)prefixAll
,
180 (const void * const)NSDeveloperApplicationDirectoryBase
182 { // NSAdminApplicationDirectory
184 (const void * const * const)prefixAll
,
185 (const void * const)NSAdminApplicationDirectoryBase
187 { // NSLibraryDirectory
189 (const void * const * const)prefixAllSystem
,
190 (const void * const)NSLibraryDirectoryBase
192 { // NSDeveloperDirectory
194 (const void * const * const)prefixAll
,
195 (const void * const)NSDeveloperDirectoryBase
199 (const void * const * const)prefixNoUserSystem
,
200 (const void * const)NSUserDirectoryBase
202 { // NSDocumentationDirectory
204 (const void * const * const)prefixAllSystem
,
205 (const void * const)NSDocumentationDirectoryBase
207 { // NSDocumentDirectory
209 (const void * const * const)prefixUserOnly
,
210 (const void * const)NSDocumentDirectoryBase
212 { // NSCoreServiceDirectory
214 (const void * const * const)prefixSystemOnly
,
215 (const void * const)NSCoreServiceDirectoryBase
217 { // NSAutosavedInformationDirectory
219 (const void * const * const)prefixUserOnly
,
220 (const void * const)NSAutosavedDocumentsDirectoryBase
222 { // NSDesktopDirectory
224 (const void * const * const)prefixUserOnly
,
225 (const void * const)NSDesktopDirectoryBase
227 { // NSCachesDirectory
229 (const void * const * const)prefixAll
,
230 (const void * const)NSCachesDirectoryBase
232 { // NSApplicationSupportDirectory
234 (const void * const * const)prefixAll
,
235 (const void * const)NSApplicationSupportDirectoryBase
237 { // NSDownloadsDirectory
239 (const void * const * const)prefixUserOnly
,
240 (const void * const)NSDownloadsDirectoryBase
242 { // NSInputMethodsDirectory
244 (const void * const * const)prefixAll
,
245 (const void * const)NSInputMethodsDirectoryBase
247 { // NSMoviesDirectory
249 (const void * const * const)prefixUserOnly
,
250 (const void * const)NSMoviesDirectoryBase
252 { // NSMusicDirectory
254 (const void * const * const)prefixUserOnly
,
255 (const void * const)NSMusicDirectoryBase
257 { // NSPicturesDirectory
259 (const void * const * const)prefixUserOnly
,
260 (const void * const)NSPicturesDirectoryBase
262 { // NSPrinterDescriptionDirectory
264 (const void * const * const)prefixSystemOnly
,
265 (const void * const)NSPrinterDescriptionDirectoryBase
267 { // NSSharedPublicDirectory
269 (const void * const * const)prefixUserOnly
,
270 (const void * const)NSSharedPublicDirectoryBase
272 { // NSPreferencePanesDirectory
274 (const void * const * const)prefixNoNetwork
,
275 (const void * const)NSPreferencePanesDirectoryBase
277 { // NSAllApplicationsDirectory
279 (const void * const * const)prefixAllApplicationsDirectory
,
280 (const void * const)baseAllApplicationsDirectory
282 { // NSAllLibrariesDirectory
284 (const void * const * const)prefixAllLibrariesDirectory
,
285 (const void * const)baseAllLibrariesDirectory
289 #define Index(dir) (((dir) >= NSApplicationDirectory && (dir) <= NSPreferencePanesDirectory) ? ((dir) - 1) : (((dir) >= NSAllApplicationsDirectory && (dir) <= NSAllLibrariesDirectory) ? ((dir) - NSAllApplicationsDirectory + NSPreferencePanesDirectory) : -1))
291 #define invalidDomains 0x00 // some domains may be invalid on non-Mach systems
292 #define ByteMask 0xff
294 #define IndexShift 16
296 NSSearchPathEnumerationState
NSStartSearchPathEnumeration(NSSearchPathDirectory dir
, NSSearchPathDomainMask domainMask
) {
297 // The state is AABBCCCC, where
298 // AA is the dir(s) requested
299 // BB is the current state of dirs (if AA < 100, then this is always 0; otherwise it goes up to number of dirs)
300 // CCCC is the domains requested
301 // the state always contains the next item; if CCCC is 0, then we're done
304 if((i
= Index(dir
)) < 0) {
307 domainMask
= domainMask
& DomainMask
& ~invalidDomains
; // Just leave useful bits in there
309 // Trim Duplicates - This assumes the compiler generates a single address
310 // for multiple occurrences of the same literal strings.
311 if ((domainMask
& (NSLocalDomainMask
| NSSystemDomainMask
)) == (NSLocalDomainMask
| NSSystemDomainMask
) && dirInfo
[i
].prefix
[NSLocalDomainIndex
] == dirInfo
[i
].prefix
[NSSystemDomainIndex
]) {
312 domainMask
&= ~NSSystemDomainMask
;
315 return (dir
<< DirShift
) + domainMask
;
318 NSSearchPathEnumerationState
NSGetNextSearchPathEnumeration(NSSearchPathEnumerationState state
, char *path
) {
319 static const char *nextRoot
= NULL
;
320 int dir
= (state
>> DirShift
) & ByteMask
;
321 int domainMask
= state
& DomainMask
;
323 const char *prefix
, *base
;
325 if ((i
= Index(dir
)) < 0 || (domain
= ffs(domainMask
)) == 0)
327 domain
--; // adjust to zero-based index
329 if ((n
= dirInfo
[i
].pathsPerDomain
) == 1) {
330 const char * const *p
= (const char * const *)dirInfo
[i
].prefix
;
331 for (;;) { // loop, skipping over invalid domains (prefix is NULL)
332 domainMask
&= ~(1 << domain
);
333 if ((prefix
= p
[domain
]) != NULL
) {
336 if ((domain
= ffs(domainMask
)) == 0) {
339 domain
--; // adjust to zero-based index
341 base
= (const char *)dirInfo
[i
].base
;
342 state
= (dir
<< DirShift
) + domainMask
;
343 } else { // multiple paths per domain
344 const char * const **p
= (const char * const **)dirInfo
[i
].prefix
;
345 const char * const *b
= (const char * const *)dirInfo
[i
].base
;
346 int dirIndex
= (state
>> IndexShift
) & ByteMask
;
348 if (dirIndex
>= n
) { // done with the current domain, go to the next
349 domainMask
&= ~(1 << domain
);
350 if ((domain
= ffs(domainMask
)) == 0) {
353 domain
--; // adjust to zero-based index
356 prefix
= p
[domain
][dirIndex
];
358 state
= (dir
<< DirShift
) + (++dirIndex
<< IndexShift
) + domainMask
;
361 if (addNextRoot(prefix
)) {
362 if (nextRoot
== NULL
) { // Get NEXT_ROOT
363 if (!issetugid() && (nextRoot
= getenv("NEXT_ROOT")) != NULL
) {
364 nextRoot
= strdup(nextRoot
);
366 if (nextRoot
== NULL
) {
370 strlcpy(path
, nextRoot
, PATH_MAX
);
374 strlcat(path
, prefix
, PATH_MAX
);
375 strlcat(path
, base
, PATH_MAX
);