2 * Copyright(c) 2000-2003 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@
25 * Modification History
27 * June 1, 2001 Allan Nathanson <ajn@apple.com>
28 * - public API conversion
30 * November 9, 2000 Allan Nathanson <ajn@apple.com>
34 #include <SystemConfiguration/SystemConfiguration.h>
35 #include <SystemConfiguration/SCValidation.h>
36 #include <SystemConfiguration/SCPrivate.h>
37 #include "SCPreferencesInternal.h"
42 #include <sys/errno.h>
45 __SCPreferencesCopyDescription(CFTypeRef cf
) {
46 CFAllocatorRef allocator
= CFGetAllocator(cf
);
47 CFMutableStringRef result
;
49 result
= CFStringCreateMutable(allocator
, 0);
50 CFStringAppendFormat(result
, NULL
, CFSTR("<SCPreferences %p [%p]> {\n"), cf
, allocator
);
51 CFStringAppendFormat(result
, NULL
, CFSTR("}"));
58 __SCPreferencesDeallocate(CFTypeRef cf
)
60 SCPreferencesPrivateRef sessionPrivate
= (SCPreferencesPrivateRef
)cf
;
62 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("__SCPreferencesDeallocate:"));
64 /* release resources */
65 if (sessionPrivate
->name
) CFRelease(sessionPrivate
->name
);
66 if (sessionPrivate
->prefsID
) CFRelease(sessionPrivate
->prefsID
);
67 if (sessionPrivate
->user
) CFRelease(sessionPrivate
->user
);
68 if (sessionPrivate
->path
) CFAllocatorDeallocate(NULL
, sessionPrivate
->path
);
69 if (sessionPrivate
->newPath
) CFAllocatorDeallocate(NULL
, sessionPrivate
->newPath
);
70 if (sessionPrivate
->signature
) CFRelease(sessionPrivate
->signature
);
71 if (sessionPrivate
->session
) CFRelease(sessionPrivate
->session
);
72 if (sessionPrivate
->sessionKeyLock
) CFRelease(sessionPrivate
->sessionKeyLock
);
73 if (sessionPrivate
->sessionKeyCommit
) CFRelease(sessionPrivate
->sessionKeyCommit
);
74 if (sessionPrivate
->sessionKeyApply
) CFRelease(sessionPrivate
->sessionKeyApply
);
75 if (sessionPrivate
->prefs
) CFRelease(sessionPrivate
->prefs
);
81 static CFTypeID __kSCPreferencesTypeID
= _kCFRuntimeNotATypeID
;
84 static const CFRuntimeClass __SCPreferencesClass
= {
86 "SCPreferences", // className
89 __SCPreferencesDeallocate
, // dealloc
92 NULL
, // copyFormattingDesc
93 __SCPreferencesCopyDescription
// copyDebugDesc
97 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
100 __SCPreferencesInitialize(void) {
101 __kSCPreferencesTypeID
= _CFRuntimeRegisterClass(&__SCPreferencesClass
);
106 static SCPreferencesPrivateRef
107 __SCPreferencesCreatePrivate(CFAllocatorRef allocator
)
109 SCPreferencesPrivateRef prefsPrivate
;
112 /* initialize runtime */
113 pthread_once(&initialized
, __SCPreferencesInitialize
);
115 /* allocate session */
116 size
= sizeof(SCPreferencesPrivate
) - sizeof(CFRuntimeBase
);
117 prefsPrivate
= (SCPreferencesPrivateRef
)_CFRuntimeCreateInstance(allocator
,
118 __kSCPreferencesTypeID
,
125 prefsPrivate
->name
= NULL
;
126 prefsPrivate
->prefsID
= NULL
;
127 prefsPrivate
->perUser
= FALSE
;
128 prefsPrivate
->user
= NULL
;
129 prefsPrivate
->path
= NULL
;
130 prefsPrivate
->newPath
= NULL
; // new prefs path
131 prefsPrivate
->signature
= NULL
;
132 prefsPrivate
->session
= NULL
;
133 prefsPrivate
->sessionKeyLock
= NULL
;
134 prefsPrivate
->sessionKeyCommit
= NULL
;
135 prefsPrivate
->sessionKeyApply
= NULL
;
136 prefsPrivate
->prefs
= NULL
;
137 prefsPrivate
->accessed
= FALSE
;
138 prefsPrivate
->changed
= FALSE
;
139 prefsPrivate
->locked
= FALSE
;
140 prefsPrivate
->isRoot
= (geteuid() == 0);
146 __private_extern__ SCPreferencesRef
147 __SCPreferencesCreate(CFAllocatorRef allocator
,
154 SCPreferencesPrivateRef prefsPrivate
;
155 int sc_status
= kSCStatusOK
;
157 CFMutableDataRef xmlData
;
158 CFStringRef xmlError
;
161 * allocate and initialize a new session
163 prefsPrivate
= __SCPreferencesCreatePrivate(allocator
);
171 * convert prefsID to path
173 prefsPrivate
->path
= __SCPreferencesPath(allocator
,
177 (prefsPrivate
->newPath
== NULL
));
178 if (prefsPrivate
->path
== NULL
) {
179 sc_status
= kSCStatusFailed
;
186 fd
= open(prefsPrivate
->path
, O_RDONLY
, 0644);
192 ((prefsID
== NULL
) || !CFStringHasPrefix(prefsID
, CFSTR("/")))) {
193 /* if default preference ID or relative path */
194 if (prefsPrivate
->newPath
== NULL
) {
196 * we've looked in the "new" prefs directory
197 * without success. Save the "new" path and
198 * look in the "old" prefs directory.
200 prefsPrivate
->newPath
= prefsPrivate
->path
;
204 * we've looked in both the "new" and "old"
205 * prefs directories without success. USe
208 CFAllocatorDeallocate(NULL
, prefsPrivate
->path
);
209 prefsPrivate
->path
= prefsPrivate
->newPath
;
210 prefsPrivate
->newPath
= NULL
;
215 bzero(&statBuf
, sizeof(statBuf
));
218 sc_status
= kSCStatusAccessError
;
221 sc_status
= kSCStatusFailed
;
224 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("open() failed: %s"), strerror(errno
));
229 * check file, create signature
231 if (fstat(fd
, &statBuf
) == -1) {
232 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("fstat() failed: %s"), strerror(errno
));
233 sc_status
= kSCStatusFailed
;
239 prefsPrivate
->signature
= __SCPSignatureFromStatbuf(&statBuf
);
241 if (statBuf
.st_size
> 0) {
242 CFDictionaryRef dict
;
245 * extract property list
247 xmlData
= CFDataCreateMutable(allocator
, statBuf
.st_size
);
248 CFDataSetLength(xmlData
, statBuf
.st_size
);
249 if (read(fd
, (void *)CFDataGetBytePtr(xmlData
), statBuf
.st_size
) != statBuf
.st_size
) {
250 /* corrupt prefs file, start fresh */
251 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("_SCPOpen read(): could not load preference data."));
260 dict
= CFPropertyListCreateFromXMLData(allocator
,
262 kCFPropertyListImmutable
,
266 /* corrupt prefs file, start fresh */
269 CFSTR("_SCPOpen CFPropertyListCreateFromXMLData(): %@"),
277 * make sure that we've got a dictionary
279 if (!isA_CFDictionary(dict
)) {
280 /* corrupt prefs file, start fresh */
281 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("_SCPOpen CFGetTypeID(): not a dictionary."));
286 prefsPrivate
->prefs
= CFDictionaryCreateMutableCopy(allocator
, 0, dict
);
297 if (prefsPrivate
->prefs
== NULL
) {
299 * new file, create empty preferences
301 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("_SCPOpen(): creating new dictionary."));
302 prefsPrivate
->prefs
= CFDictionaryCreateMutable(allocator
,
304 &kCFTypeDictionaryKeyCallBacks
,
305 &kCFTypeDictionaryValueCallBacks
);
306 prefsPrivate
->changed
= TRUE
;
312 prefsPrivate
->name
= CFStringCreateCopy(allocator
, name
);
313 if (prefsID
) prefsPrivate
->prefsID
= CFStringCreateCopy(allocator
, prefsID
);
314 prefsPrivate
->perUser
= perUser
;
315 if (user
) prefsPrivate
->user
= CFStringCreateCopy(allocator
, user
);
316 return (SCPreferencesRef
)prefsPrivate
;
320 if (fd
!= -1) (void) close(fd
);
321 CFRelease(prefsPrivate
);
322 _SCErrorSet(sc_status
);
328 SCPreferencesCreate(CFAllocatorRef allocator
,
333 SCLog(TRUE
, LOG_DEBUG
, CFSTR("SCPreferencesCreate:"));
334 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" name = %@"), name
);
335 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" prefsID = %@"), prefsID
);
338 return __SCPreferencesCreate(allocator
, name
, prefsID
, FALSE
, NULL
);
343 SCUserPreferencesCreate(CFAllocatorRef allocator
,
349 SCLog(TRUE
, LOG_DEBUG
, CFSTR("SCUserPreferencesCreate:"));
350 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" name = %@"), name
);
351 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" prefsID = %@"), prefsID
);
352 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" user = %@"), user
);
355 return __SCPreferencesCreate(allocator
, name
, prefsID
, TRUE
, user
);
360 SCPreferencesGetTypeID(void) {
361 pthread_once(&initialized
, __SCPreferencesInitialize
); /* initialize runtime */
362 return __kSCPreferencesTypeID
;