2 * Copyright(c) 2000 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 "SCPreferencesInternal.h"
40 #include <sys/errno.h>
43 __SCPreferencesCopyDescription(CFTypeRef cf
) {
44 CFAllocatorRef allocator
= CFGetAllocator(cf
);
45 CFMutableStringRef result
;
47 result
= CFStringCreateMutable(allocator
, 0);
48 CFStringAppendFormat(result
, NULL
, CFSTR("<SCPreferences %p [%p]> {\n"), cf
, allocator
);
49 CFStringAppendFormat(result
, NULL
, CFSTR("}"));
56 __SCPreferencesDeallocate(CFTypeRef cf
)
58 SCPreferencesPrivateRef sessionPrivate
= (SCPreferencesPrivateRef
)cf
;
60 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("__SCPreferencesDeallocate:"));
62 /* release resources */
63 if (sessionPrivate
->name
) CFRelease(sessionPrivate
->name
);
64 if (sessionPrivate
->prefsID
) CFRelease(sessionPrivate
->prefsID
);
65 if (sessionPrivate
->user
) CFRelease(sessionPrivate
->user
);
66 if (sessionPrivate
->path
) CFAllocatorDeallocate(NULL
, sessionPrivate
->path
);
67 if (sessionPrivate
->signature
) CFRelease(sessionPrivate
->signature
);
68 if (sessionPrivate
->session
) CFRelease(sessionPrivate
->session
);
69 if (sessionPrivate
->sessionKeyLock
) CFRelease(sessionPrivate
->sessionKeyLock
);
70 if (sessionPrivate
->sessionKeyCommit
) CFRelease(sessionPrivate
->sessionKeyCommit
);
71 if (sessionPrivate
->sessionKeyApply
) CFRelease(sessionPrivate
->sessionKeyApply
);
72 if (sessionPrivate
->prefs
) CFRelease(sessionPrivate
->prefs
);
78 static CFTypeID __kSCPreferencesTypeID
= _kCFRuntimeNotATypeID
;
81 static const CFRuntimeClass __SCPreferencesClass
= {
83 "SCPreferences", // className
86 __SCPreferencesDeallocate
, // dealloc
89 NULL
, // copyFormattingDesc
90 __SCPreferencesCopyDescription
// copyDebugDesc
94 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
98 __SCPreferencesInitialize(void) {
99 __kSCPreferencesTypeID
= _CFRuntimeRegisterClass(&__SCPreferencesClass
);
105 __SCPreferencesCreatePrivate(CFAllocatorRef allocator
)
107 SCPreferencesPrivateRef prefs
;
110 /* initialize runtime */
111 pthread_once(&initialized
, __SCPreferencesInitialize
);
113 /* allocate session */
114 size
= sizeof(SCPreferencesPrivate
) - sizeof(CFRuntimeBase
);
115 prefs
= (SCPreferencesPrivateRef
)_CFRuntimeCreateInstance(allocator
,
116 __kSCPreferencesTypeID
,
124 prefs
->prefsID
= NULL
;
125 prefs
->perUser
= FALSE
;
128 prefs
->signature
= NULL
;
129 prefs
->session
= NULL
;
130 prefs
->sessionKeyLock
= NULL
;
131 prefs
->sessionKeyCommit
= NULL
;
132 prefs
->sessionKeyApply
= NULL
;
134 prefs
->accessed
= FALSE
;
135 prefs
->changed
= FALSE
;
136 prefs
->locked
= FALSE
;
137 prefs
->isRoot
= (geteuid() == 0);
139 return (SCPreferencesRef
)prefs
;
143 __private_extern__ SCPreferencesRef
144 __SCPreferencesCreate(CFAllocatorRef allocator
,
151 SCPreferencesRef prefs
;
152 SCPreferencesPrivateRef prefsPrivate
;
153 int sc_status
= kSCStatusOK
;
155 CFMutableDataRef xmlData
;
156 CFStringRef xmlError
;
159 * allocate and initialize a new session
161 prefs
= __SCPreferencesCreatePrivate(allocator
);
165 prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
168 * convert prefsID to path
170 prefsPrivate
->path
= __SCPreferencesPath(NULL
, prefsID
, perUser
, user
);
171 if (prefsPrivate
->path
== NULL
) {
172 sc_status
= kSCStatusFailed
;
179 fd
= open(prefsPrivate
->path
, O_RDONLY
, 0644);
183 /* no prefs file, start fresh */
184 bzero(&statBuf
, sizeof(statBuf
));
187 sc_status
= kSCStatusAccessError
;
190 sc_status
= kSCStatusFailed
;
193 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("open() failed: %s"), strerror(errno
));
198 * check file, create signature
200 if (fstat(fd
, &statBuf
) == -1) {
201 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("fstat() failed: %s"), strerror(errno
));
202 sc_status
= kSCStatusFailed
;
208 prefsPrivate
->signature
= __SCPSignatureFromStatbuf(&statBuf
);
210 if (statBuf
.st_size
> 0) {
212 * extract property list
214 xmlData
= CFDataCreateMutable(NULL
, statBuf
.st_size
);
215 CFDataSetLength(xmlData
, statBuf
.st_size
);
216 if (read(fd
, (void *)CFDataGetBytePtr(xmlData
), statBuf
.st_size
) != statBuf
.st_size
) {
217 /* corrupt prefs file, start fresh */
218 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("_SCPOpen read(): could not load preference data."));
227 prefsPrivate
->prefs
= (CFMutableDictionaryRef
)
228 CFPropertyListCreateFromXMLData(NULL
,
230 kCFPropertyListMutableContainers
,
233 if (!prefsPrivate
->prefs
) {
234 /* corrupt prefs file, start fresh */
236 SCLog(_sc_verbose
, LOG_DEBUG
,
237 CFSTR("_SCPOpen CFPropertyListCreateFromXMLData(): %@"),
245 * make sure that we've got a dictionary
247 if (CFGetTypeID(prefsPrivate
->prefs
) != CFDictionaryGetTypeID()) {
248 /* corrupt prefs file, start fresh */
249 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("_SCPOpen CFGetTypeID(): not a dictionary."));
250 CFRelease(prefsPrivate
->prefs
);
251 prefsPrivate
->prefs
= NULL
;
263 if (prefsPrivate
->prefs
== NULL
) {
265 * new file, create empty preferences
267 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("_SCPOpen(): creating new dictionary."));
268 prefsPrivate
->prefs
= CFDictionaryCreateMutable(NULL
,
270 &kCFTypeDictionaryKeyCallBacks
,
271 &kCFTypeDictionaryValueCallBacks
);
272 prefsPrivate
->changed
= TRUE
;
278 prefsPrivate
->name
= CFRetain(name
);
280 prefsPrivate
->prefsID
= CFRetain(prefsID
);
282 prefsPrivate
->perUser
= perUser
;
284 prefsPrivate
->user
= CFRetain(user
);
294 _SCErrorSet(sc_status
);
300 SCPreferencesCreate(CFAllocatorRef allocator
,
304 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("SCPreferencesCreate:"));
305 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" name = %@"), name
);
306 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" prefsID = %@"), prefsID
);
308 return __SCPreferencesCreate(allocator
, name
, prefsID
, FALSE
, NULL
);
313 SCUserPreferencesCreate(CFAllocatorRef allocator
,
318 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("SCUserPreferencesCreate:"));
319 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" name = %@"), name
);
320 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" prefsID = %@"), prefsID
);
321 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" user = %@"), user
);
323 return __SCPreferencesCreate(allocator
, name
, prefsID
, TRUE
, user
);
328 SCPreferencesGetTypeID(void) {
329 return __kSCPreferencesTypeID
;