2 * Copyright(c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
27 * Modification History
29 * June 1, 2001 Allan Nathanson <ajn@apple.com>
30 * - public API conversion
32 * November 9, 2000 Allan Nathanson <ajn@apple.com>
36 #include <SystemConfiguration/SystemConfiguration.h>
37 #include <SystemConfiguration/SCValidation.h>
38 #include <SystemConfiguration/SCPrivate.h>
39 #include "SCPreferencesInternal.h"
44 #include <sys/errno.h>
47 __SCPreferencesCopyDescription(CFTypeRef cf
) {
48 CFAllocatorRef allocator
= CFGetAllocator(cf
);
49 CFMutableStringRef result
;
51 result
= CFStringCreateMutable(allocator
, 0);
52 CFStringAppendFormat(result
, NULL
, CFSTR("<SCPreferences %p [%p]> {\n"), cf
, allocator
);
53 CFStringAppendFormat(result
, NULL
, CFSTR("}"));
60 __SCPreferencesDeallocate(CFTypeRef cf
)
62 SCPreferencesPrivateRef sessionPrivate
= (SCPreferencesPrivateRef
)cf
;
64 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("__SCPreferencesDeallocate:"));
66 /* release resources */
67 if (sessionPrivate
->name
) CFRelease(sessionPrivate
->name
);
68 if (sessionPrivate
->prefsID
) CFRelease(sessionPrivate
->prefsID
);
69 if (sessionPrivate
->user
) CFRelease(sessionPrivate
->user
);
70 if (sessionPrivate
->path
) CFAllocatorDeallocate(NULL
, sessionPrivate
->path
);
71 if (sessionPrivate
->newPath
) CFAllocatorDeallocate(NULL
, sessionPrivate
->newPath
);
72 if (sessionPrivate
->signature
) CFRelease(sessionPrivate
->signature
);
73 if (sessionPrivate
->session
) CFRelease(sessionPrivate
->session
);
74 if (sessionPrivate
->sessionKeyLock
) CFRelease(sessionPrivate
->sessionKeyLock
);
75 if (sessionPrivate
->sessionKeyCommit
) CFRelease(sessionPrivate
->sessionKeyCommit
);
76 if (sessionPrivate
->sessionKeyApply
) CFRelease(sessionPrivate
->sessionKeyApply
);
77 if (sessionPrivate
->prefs
) CFRelease(sessionPrivate
->prefs
);
83 static CFTypeID __kSCPreferencesTypeID
= _kCFRuntimeNotATypeID
;
86 static const CFRuntimeClass __SCPreferencesClass
= {
88 "SCPreferences", // className
91 __SCPreferencesDeallocate
, // dealloc
94 NULL
, // copyFormattingDesc
95 __SCPreferencesCopyDescription
// copyDebugDesc
99 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
102 __SCPreferencesInitialize(void) {
103 __kSCPreferencesTypeID
= _CFRuntimeRegisterClass(&__SCPreferencesClass
);
108 static SCPreferencesPrivateRef
109 __SCPreferencesCreatePrivate(CFAllocatorRef allocator
)
111 SCPreferencesPrivateRef prefsPrivate
;
114 /* initialize runtime */
115 pthread_once(&initialized
, __SCPreferencesInitialize
);
117 /* allocate session */
118 size
= sizeof(SCPreferencesPrivate
) - sizeof(CFRuntimeBase
);
119 prefsPrivate
= (SCPreferencesPrivateRef
)_CFRuntimeCreateInstance(allocator
,
120 __kSCPreferencesTypeID
,
127 prefsPrivate
->name
= NULL
;
128 prefsPrivate
->prefsID
= NULL
;
129 prefsPrivate
->perUser
= FALSE
;
130 prefsPrivate
->user
= NULL
;
131 prefsPrivate
->path
= NULL
;
132 prefsPrivate
->newPath
= NULL
; // new prefs path
133 prefsPrivate
->signature
= NULL
;
134 prefsPrivate
->session
= NULL
;
135 prefsPrivate
->sessionKeyLock
= NULL
;
136 prefsPrivate
->sessionKeyCommit
= NULL
;
137 prefsPrivate
->sessionKeyApply
= NULL
;
138 prefsPrivate
->prefs
= NULL
;
139 prefsPrivate
->accessed
= FALSE
;
140 prefsPrivate
->changed
= FALSE
;
141 prefsPrivate
->locked
= FALSE
;
142 prefsPrivate
->isRoot
= (geteuid() == 0);
148 __private_extern__ SCPreferencesRef
149 __SCPreferencesCreate(CFAllocatorRef allocator
,
156 SCPreferencesPrivateRef prefsPrivate
;
157 int sc_status
= kSCStatusOK
;
159 CFMutableDataRef xmlData
;
160 CFStringRef xmlError
;
163 * allocate and initialize a new session
165 prefsPrivate
= __SCPreferencesCreatePrivate(allocator
);
173 * convert prefsID to path
175 prefsPrivate
->path
= __SCPreferencesPath(allocator
,
179 (prefsPrivate
->newPath
== NULL
));
180 if (prefsPrivate
->path
== NULL
) {
181 sc_status
= kSCStatusFailed
;
188 fd
= open(prefsPrivate
->path
, O_RDONLY
, 0644);
194 ((prefsID
== NULL
) || !CFStringHasPrefix(prefsID
, CFSTR("/")))) {
195 /* if default preference ID or relative path */
196 if (prefsPrivate
->newPath
== NULL
) {
198 * we've looked in the "new" prefs directory
199 * without success. Save the "new" path and
200 * look in the "old" prefs directory.
202 prefsPrivate
->newPath
= prefsPrivate
->path
;
206 * we've looked in both the "new" and "old"
207 * prefs directories without success. USe
210 CFAllocatorDeallocate(NULL
, prefsPrivate
->path
);
211 prefsPrivate
->path
= prefsPrivate
->newPath
;
212 prefsPrivate
->newPath
= NULL
;
217 bzero(&statBuf
, sizeof(statBuf
));
220 sc_status
= kSCStatusAccessError
;
223 sc_status
= kSCStatusFailed
;
226 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("open() failed: %s"), strerror(errno
));
231 * check file, create signature
233 if (fstat(fd
, &statBuf
) == -1) {
234 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("fstat() failed: %s"), strerror(errno
));
235 sc_status
= kSCStatusFailed
;
241 prefsPrivate
->signature
= __SCPSignatureFromStatbuf(&statBuf
);
243 if (statBuf
.st_size
> 0) {
244 CFDictionaryRef dict
;
247 * extract property list
249 xmlData
= CFDataCreateMutable(allocator
, statBuf
.st_size
);
250 CFDataSetLength(xmlData
, statBuf
.st_size
);
251 if (read(fd
, (void *)CFDataGetBytePtr(xmlData
), statBuf
.st_size
) != statBuf
.st_size
) {
252 /* corrupt prefs file, start fresh */
253 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("_SCPOpen read(): could not load preference data."));
262 dict
= CFPropertyListCreateFromXMLData(allocator
,
264 kCFPropertyListImmutable
,
268 /* corrupt prefs file, start fresh */
271 CFSTR("_SCPOpen CFPropertyListCreateFromXMLData(): %@"),
279 * make sure that we've got a dictionary
281 if (!isA_CFDictionary(dict
)) {
282 /* corrupt prefs file, start fresh */
283 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("_SCPOpen CFGetTypeID(): not a dictionary."));
288 prefsPrivate
->prefs
= CFDictionaryCreateMutableCopy(allocator
, 0, dict
);
299 if (prefsPrivate
->prefs
== NULL
) {
301 * new file, create empty preferences
303 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("_SCPOpen(): creating new dictionary."));
304 prefsPrivate
->prefs
= CFDictionaryCreateMutable(allocator
,
306 &kCFTypeDictionaryKeyCallBacks
,
307 &kCFTypeDictionaryValueCallBacks
);
308 prefsPrivate
->changed
= TRUE
;
314 prefsPrivate
->name
= CFStringCreateCopy(allocator
, name
);
315 if (prefsID
) prefsPrivate
->prefsID
= CFStringCreateCopy(allocator
, prefsID
);
316 prefsPrivate
->perUser
= perUser
;
317 if (user
) prefsPrivate
->user
= CFStringCreateCopy(allocator
, user
);
318 return (SCPreferencesRef
)prefsPrivate
;
322 if (fd
!= -1) (void) close(fd
);
323 CFRelease(prefsPrivate
);
324 _SCErrorSet(sc_status
);
330 SCPreferencesCreate(CFAllocatorRef allocator
,
335 SCLog(TRUE
, LOG_DEBUG
, CFSTR("SCPreferencesCreate:"));
336 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" name = %@"), name
);
337 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" prefsID = %@"), prefsID
);
340 return __SCPreferencesCreate(allocator
, name
, prefsID
, FALSE
, NULL
);
345 SCUserPreferencesCreate(CFAllocatorRef allocator
,
351 SCLog(TRUE
, LOG_DEBUG
, CFSTR("SCUserPreferencesCreate:"));
352 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" name = %@"), name
);
353 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" prefsID = %@"), prefsID
);
354 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" user = %@"), user
);
357 return __SCPreferencesCreate(allocator
, name
, prefsID
, TRUE
, user
);
362 SCPreferencesGetTypeID(void) {
363 pthread_once(&initialized
, __SCPreferencesInitialize
); /* initialize runtime */
364 return __kSCPreferencesTypeID
;