2 * Copyright (c) 1999 Apple Computer, 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@
26 #import <NSSystemDirectories.h>
28 // Names of directories; index into this with NSSearchPathDirectory - 1
31 unsigned char invalidDomainMask
; // Domains in which this dir does not appear
32 unsigned char alternateDomainMask
; // Domains in which this dir uses the alternate domain path
34 } dirInfo
[numDirs
] = {
35 {0, 0, "Applications"},
36 {0, 0, "Applications/Demos"},
37 {0, 0, "Developer/Applications"},
38 {0, 0, "Applications/Utilities"},
39 {0, 0x8, "Library"}, // Uses alternate form in System domain
41 {0x9, 0, "Users"}, // Not valid in the System and User domains
42 {0, 0x8, "Library/Documentation"}, // Uses alternate form in System domain
43 {0xe, 0, "Documents"}, // Only valid in user domain
44 {0x7, 0, "Library/CoreServices"}, // Only valid in System domain
45 {0xe, 0, "Documents/Autosaved"}, // Only valid in user domain; not public API yet
46 {0xe, 0, "Desktop"}, // Only valid in user domain
47 {0, 0, "Library/Caches"},
48 {0, 0, "Library/Application Support"},
49 {0xe, 0, "Downloads"}, // Only valid in user domain
52 // Unpublicized values for NSSearchPathDirectory
54 NSAutosavedDocumentsDirectory
= 11
57 // Ordered list of where to find applications in each domain (the numbers are NSSearchPathDirectory)
58 #define numApplicationDirs 4
59 static const char applicationDirs
[numApplicationDirs
] = {1, 4, 3, 2};
61 // Ordered list of where to find resources in each domain (the numbers are NSSearchPathDirectory)
62 #define numLibraryDirs 2
63 static const char libraryDirs
[numLibraryDirs
] = {5, 6};
65 // Names of domains; index into this log2(domainMask). If the search path ordering is ever changed, then we need an indirection (as the domainMask values cannot be changed).
68 char needsRootPrepended
;
69 const char *domainPath
;
70 const char *alternateDomainPath
;
71 } domainInfo
[numDomains
] = {
74 {1, "/Network", "/Network"},
78 #define invalidDomains 0x00 // some domains may be invalid on non-Mach systems
80 NSSearchPathEnumerationState
NSStartSearchPathEnumeration(NSSearchPathDirectory dir
, NSSearchPathDomainMask domainMask
) {
81 // The state is AABBCCCC, where
82 // AA is the dir(s) requested
83 // BB is the current state of dirs (if AA < 100, then this is always 0; otherwise it goes up to number of dirs)
84 // CCCC is the domains requested
85 // the state always contains the next item; if CCCC is 0, then we're done
86 domainMask
= domainMask
& ((1 << numDomains
) - 1) & ~invalidDomains
; // Just leave useful bits in there
87 if (dir
!= NSAllLibrariesDirectory
&& dir
!= NSLibraryDirectory
&& dir
!= NSUserDirectory
&& dir
!= NSDocumentationDirectory
&& (domainMask
& NSLocalDomainMask
) && (domainMask
& NSSystemDomainMask
)) domainMask
= domainMask
& ~NSSystemDomainMask
; // Hack to avoid duplication
88 return (((unsigned int)dir
) << 24) + ((unsigned int)domainMask
);
91 NSSearchPathEnumerationState
NSGetNextSearchPathEnumeration(NSSearchPathEnumerationState state
, char *path
) {
92 static const char *nextRoot
= NULL
;
93 unsigned dir
= (state
>> 24) & 0xff;
94 unsigned dirState
= (state
>> 16) & 0xff;
95 unsigned domainMask
= state
& 0xffff;
96 unsigned int curDomain
; // The current domain we're at...
97 unsigned int curDir
= 0; // The current dir...
100 if (domainMask
== 0) return 0; // Looks like we're done
101 for (curDomain
= 0; curDomain
< numDomains
; curDomain
++) if ((domainMask
& (1 << curDomain
))) break;
103 // Determine directory
104 if (dir
< NSAllApplicationsDirectory
) { // One directory per domain, simple...
106 } else { // Can return multiple directories for each domain
107 if (dir
== NSAllApplicationsDirectory
) {
108 curDir
= applicationDirs
[dirState
];
109 if (++dirState
== numApplicationDirs
) dirState
= 0;
110 } else if (dir
== NSAllLibrariesDirectory
) {
111 curDir
= libraryDirs
[dirState
];
112 if (++dirState
== numLibraryDirs
) dirState
= 0;
115 if (dirState
== 0) domainMask
&= ~(1 << curDomain
); // If necessary, jump to next domain
116 } while ((dirInfo
[curDir
- 1].invalidDomainMask
& (1 << curDomain
))); // If invalid, try again...
118 // Get NEXT_ROOT, if necessary.
119 if (domainInfo
[curDomain
].needsRootPrepended
&& nextRoot
== 0) {
120 if (!issetugid() && (nextRoot
= getenv("NEXT_ROOT")) != NULL
) {
121 nextRoot
= strdup(nextRoot
);
123 if (nextRoot
== NULL
) {
128 snprintf(path
, PATH_MAX
, "%s%s/%s", domainInfo
[curDomain
].needsRootPrepended
? nextRoot
: "", (dirInfo
[curDir
- 1].alternateDomainMask
& (1 << curDomain
)) ? domainInfo
[curDomain
].alternateDomainPath
: domainInfo
[curDomain
].domainPath
, dirInfo
[curDir
- 1].dirPath
);
130 return (dir
<< 24) + (dirState
<< 16) + domainMask
;