2 * Copyright(c) 2000-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1(the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
24 * Modification History
26 * June 1, 2001 Allan Nathanson <ajn@apple.com>
27 * - public API conversion
29 * November 9, 2000 Allan Nathanson <ajn@apple.com>
33 #include <SystemConfiguration/SystemConfiguration.h>
34 #include <SystemConfiguration/SCPrivate.h>
35 #include <SystemConfiguration/SCValidation.h>
36 #include "SCPreferencesInternal.h"
41 #include <sys/errno.h>
44 __SCPreferencesCopyDescription(CFTypeRef cf
) {
45 CFAllocatorRef allocator
= CFGetAllocator(cf
);
46 CFMutableStringRef result
;
48 result
= CFStringCreateMutable(allocator
, 0);
49 CFStringAppendFormat(result
, NULL
, CFSTR("<SCPreferences %p [%p]> {\n"), cf
, allocator
);
50 CFStringAppendFormat(result
, NULL
, CFSTR("}"));
57 __SCPreferencesDeallocate(CFTypeRef cf
)
59 SCPreferencesPrivateRef sessionPrivate
= (SCPreferencesPrivateRef
)cf
;
61 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("__SCPreferencesDeallocate:"));
63 /* release resources */
64 if (sessionPrivate
->name
) CFRelease(sessionPrivate
->name
);
65 if (sessionPrivate
->prefsID
) CFRelease(sessionPrivate
->prefsID
);
66 if (sessionPrivate
->user
) CFRelease(sessionPrivate
->user
);
67 if (sessionPrivate
->path
) CFAllocatorDeallocate(NULL
, sessionPrivate
->path
);
68 if (sessionPrivate
->signature
) CFRelease(sessionPrivate
->signature
);
69 if (sessionPrivate
->session
) CFRelease(sessionPrivate
->session
);
70 if (sessionPrivate
->sessionKeyLock
) CFRelease(sessionPrivate
->sessionKeyLock
);
71 if (sessionPrivate
->sessionKeyCommit
) CFRelease(sessionPrivate
->sessionKeyCommit
);
72 if (sessionPrivate
->sessionKeyApply
) CFRelease(sessionPrivate
->sessionKeyApply
);
73 if (sessionPrivate
->prefs
) CFRelease(sessionPrivate
->prefs
);
79 static CFTypeID __kSCPreferencesTypeID
= _kCFRuntimeNotATypeID
;
82 static const CFRuntimeClass __SCPreferencesClass
= {
84 "SCPreferences", // className
87 __SCPreferencesDeallocate
, // dealloc
90 NULL
, // copyFormattingDesc
91 __SCPreferencesCopyDescription
// copyDebugDesc
95 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
99 __SCPreferencesInitialize(void) {
100 __kSCPreferencesTypeID
= _CFRuntimeRegisterClass(&__SCPreferencesClass
);
106 __SCPreferencesCreatePrivate(CFAllocatorRef allocator
)
108 SCPreferencesPrivateRef prefs
;
111 /* initialize runtime */
112 pthread_once(&initialized
, __SCPreferencesInitialize
);
114 /* allocate session */
115 size
= sizeof(SCPreferencesPrivate
) - sizeof(CFRuntimeBase
);
116 prefs
= (SCPreferencesPrivateRef
)_CFRuntimeCreateInstance(allocator
,
117 __kSCPreferencesTypeID
,
125 prefs
->prefsID
= NULL
;
126 prefs
->perUser
= FALSE
;
129 prefs
->signature
= NULL
;
130 prefs
->session
= NULL
;
131 prefs
->sessionKeyLock
= NULL
;
132 prefs
->sessionKeyCommit
= NULL
;
133 prefs
->sessionKeyApply
= NULL
;
135 prefs
->accessed
= FALSE
;
136 prefs
->changed
= FALSE
;
137 prefs
->locked
= FALSE
;
138 prefs
->isRoot
= (geteuid() == 0);
140 return (SCPreferencesRef
)prefs
;
144 __private_extern__ SCPreferencesRef
145 __SCPreferencesCreate(CFAllocatorRef allocator
,
152 SCPreferencesRef prefs
;
153 SCPreferencesPrivateRef prefsPrivate
;
154 int sc_status
= kSCStatusOK
;
156 CFMutableDataRef xmlData
;
157 CFStringRef xmlError
;
160 * allocate and initialize a new session
162 prefs
= __SCPreferencesCreatePrivate(allocator
);
166 prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
169 * convert prefsID to path
171 prefsPrivate
->path
= __SCPreferencesPath(NULL
, prefsID
, perUser
, user
);
172 if (prefsPrivate
->path
== NULL
) {
173 sc_status
= kSCStatusFailed
;
180 fd
= open(prefsPrivate
->path
, O_RDONLY
, 0644);
184 /* no prefs file, start fresh */
185 bzero(&statBuf
, sizeof(statBuf
));
188 sc_status
= kSCStatusAccessError
;
191 sc_status
= kSCStatusFailed
;
194 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("open() failed: %s"), strerror(errno
));
199 * check file, create signature
201 if (fstat(fd
, &statBuf
) == -1) {
202 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("fstat() failed: %s"), strerror(errno
));
203 sc_status
= kSCStatusFailed
;
209 prefsPrivate
->signature
= __SCPSignatureFromStatbuf(&statBuf
);
211 if (statBuf
.st_size
> 0) {
212 CFDictionaryRef dict
;
215 * extract property list
217 xmlData
= CFDataCreateMutable(NULL
, statBuf
.st_size
);
218 CFDataSetLength(xmlData
, statBuf
.st_size
);
219 if (read(fd
, (void *)CFDataGetBytePtr(xmlData
), statBuf
.st_size
) != statBuf
.st_size
) {
220 /* corrupt prefs file, start fresh */
221 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("_SCPOpen read(): could not load preference data."));
230 dict
= CFPropertyListCreateFromXMLData(NULL
,
232 kCFPropertyListImmutable
,
236 /* corrupt prefs file, start fresh */
239 CFSTR("_SCPOpen CFPropertyListCreateFromXMLData(): %@"),
247 * make sure that we've got a dictionary
249 if (!isA_CFDictionary(dict
)) {
250 /* corrupt prefs file, start fresh */
251 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("_SCPOpen CFGetTypeID(): not a dictionary."));
256 prefsPrivate
->prefs
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
267 if (prefsPrivate
->prefs
== NULL
) {
269 * new file, create empty preferences
271 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("_SCPOpen(): creating new dictionary."));
272 prefsPrivate
->prefs
= CFDictionaryCreateMutable(NULL
,
274 &kCFTypeDictionaryKeyCallBacks
,
275 &kCFTypeDictionaryValueCallBacks
);
276 prefsPrivate
->changed
= TRUE
;
282 prefsPrivate
->name
= CFRetain(name
);
284 prefsPrivate
->prefsID
= CFRetain(prefsID
);
286 prefsPrivate
->perUser
= perUser
;
288 prefsPrivate
->user
= CFRetain(user
);
298 _SCErrorSet(sc_status
);
304 SCPreferencesCreate(CFAllocatorRef allocator
,
308 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("SCPreferencesCreate:"));
309 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" name = %@"), name
);
310 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" prefsID = %@"), prefsID
);
312 return __SCPreferencesCreate(allocator
, name
, prefsID
, FALSE
, NULL
);
317 SCUserPreferencesCreate(CFAllocatorRef allocator
,
322 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("SCUserPreferencesCreate:"));
323 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" name = %@"), name
);
324 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" prefsID = %@"), prefsID
);
325 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" user = %@"), user
);
327 return __SCPreferencesCreate(allocator
, name
, prefsID
, TRUE
, user
);
332 SCPreferencesGetTypeID(void) {
333 return __kSCPreferencesTypeID
;