]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCPOpen.c
b24a0066d61bbe7dff4a04aa490de7d3513124c5
[apple/configd.git] / SystemConfiguration.fproj / SCPOpen.c
1 /*
2 * Copyright(c) 2000-2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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.
11 *
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
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23 /*
24 * Modification History
25 *
26 * June 1, 2001 Allan Nathanson <ajn@apple.com>
27 * - public API conversion
28 *
29 * November 9, 2000 Allan Nathanson <ajn@apple.com>
30 * - initial revision
31 */
32
33 #include <SystemConfiguration/SystemConfiguration.h>
34 #include <SystemConfiguration/SCPrivate.h>
35 #include <SystemConfiguration/SCValidation.h>
36 #include "SCPreferencesInternal.h"
37
38 #include <fcntl.h>
39 #include <pthread.h>
40 #include <unistd.h>
41 #include <sys/errno.h>
42
43 static CFStringRef
44 __SCPreferencesCopyDescription(CFTypeRef cf) {
45 CFAllocatorRef allocator = CFGetAllocator(cf);
46 CFMutableStringRef result;
47
48 result = CFStringCreateMutable(allocator, 0);
49 CFStringAppendFormat(result, NULL, CFSTR("<SCPreferences %p [%p]> {\n"), cf, allocator);
50 CFStringAppendFormat(result, NULL, CFSTR("}"));
51
52 return result;
53 }
54
55
56 static void
57 __SCPreferencesDeallocate(CFTypeRef cf)
58 {
59 SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)cf;
60
61 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCPreferencesDeallocate:"));
62
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);
74
75 return;
76 }
77
78
79 static CFTypeID __kSCPreferencesTypeID = _kCFRuntimeNotATypeID;
80
81
82 static const CFRuntimeClass __SCPreferencesClass = {
83 0, // version
84 "SCPreferences", // className
85 NULL, // init
86 NULL, // copy
87 __SCPreferencesDeallocate, // dealloc
88 NULL, // equal
89 NULL, // hash
90 NULL, // copyFormattingDesc
91 __SCPreferencesCopyDescription // copyDebugDesc
92 };
93
94
95 static pthread_once_t initialized = PTHREAD_ONCE_INIT;
96
97
98 static void
99 __SCPreferencesInitialize(void) {
100 __kSCPreferencesTypeID = _CFRuntimeRegisterClass(&__SCPreferencesClass);
101 return;
102 }
103
104
105 SCPreferencesRef
106 __SCPreferencesCreatePrivate(CFAllocatorRef allocator)
107 {
108 SCPreferencesPrivateRef prefs;
109 UInt32 size;
110
111 /* initialize runtime */
112 pthread_once(&initialized, __SCPreferencesInitialize);
113
114 /* allocate session */
115 size = sizeof(SCPreferencesPrivate) - sizeof(CFRuntimeBase);
116 prefs = (SCPreferencesPrivateRef)_CFRuntimeCreateInstance(allocator,
117 __kSCPreferencesTypeID,
118 size,
119 NULL);
120 if (!prefs) {
121 return NULL;
122 }
123
124 prefs->name = NULL;
125 prefs->prefsID = NULL;
126 prefs->perUser = FALSE;
127 prefs->user = NULL;
128 prefs->path = NULL;
129 prefs->signature = NULL;
130 prefs->session = NULL;
131 prefs->sessionKeyLock = NULL;
132 prefs->sessionKeyCommit = NULL;
133 prefs->sessionKeyApply = NULL;
134 prefs->prefs = NULL;
135 prefs->accessed = FALSE;
136 prefs->changed = FALSE;
137 prefs->locked = FALSE;
138 prefs->isRoot = (geteuid() == 0);
139
140 return (SCPreferencesRef)prefs;
141 }
142
143
144 __private_extern__ SCPreferencesRef
145 __SCPreferencesCreate(CFAllocatorRef allocator,
146 CFStringRef name,
147 CFStringRef prefsID,
148 Boolean perUser,
149 CFStringRef user)
150 {
151 int fd = -1;
152 SCPreferencesRef prefs;
153 SCPreferencesPrivateRef prefsPrivate;
154 int sc_status = kSCStatusOK;
155 struct stat statBuf;
156 CFMutableDataRef xmlData;
157 CFStringRef xmlError;
158
159 /*
160 * allocate and initialize a new session
161 */
162 prefs = __SCPreferencesCreatePrivate(allocator);
163 if (!prefs) {
164 return NULL;
165 }
166 prefsPrivate = (SCPreferencesPrivateRef)prefs;
167
168 /*
169 * convert prefsID to path
170 */
171 prefsPrivate->path = __SCPreferencesPath(NULL, prefsID, perUser, user);
172 if (prefsPrivate->path == NULL) {
173 sc_status = kSCStatusFailed;
174 goto error;
175 }
176
177 /*
178 * open file
179 */
180 fd = open(prefsPrivate->path, O_RDONLY, 0644);
181 if (fd == -1) {
182 switch (errno) {
183 case ENOENT :
184 /* no prefs file, start fresh */
185 bzero(&statBuf, sizeof(statBuf));
186 goto create_1;
187 case EACCES :
188 sc_status = kSCStatusAccessError;
189 break;
190 default :
191 sc_status = kSCStatusFailed;
192 break;
193 }
194 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("open() failed: %s"), strerror(errno));
195 goto error;
196 }
197
198 /*
199 * check file, create signature
200 */
201 if (fstat(fd, &statBuf) == -1) {
202 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("fstat() failed: %s"), strerror(errno));
203 sc_status = kSCStatusFailed;
204 goto error;
205 }
206
207 create_1 :
208
209 prefsPrivate->signature = __SCPSignatureFromStatbuf(&statBuf);
210
211 if (statBuf.st_size > 0) {
212 CFDictionaryRef dict;
213
214 /*
215 * extract property list
216 */
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."));
222 CFRelease(xmlData);
223 xmlData = NULL;
224 goto create_2;
225 }
226
227 /*
228 * load preferences
229 */
230 dict = CFPropertyListCreateFromXMLData(NULL,
231 xmlData,
232 kCFPropertyListImmutable,
233 &xmlError);
234 CFRelease(xmlData);
235 if (!dict) {
236 /* corrupt prefs file, start fresh */
237 if (xmlError) {
238 SCLog(TRUE, LOG_ERR,
239 CFSTR("_SCPOpen CFPropertyListCreateFromXMLData(): %@"),
240 xmlError);
241 CFRelease(xmlError);
242 }
243 goto create_2;
244 }
245
246 /*
247 * make sure that we've got a dictionary
248 */
249 if (!isA_CFDictionary(dict)) {
250 /* corrupt prefs file, start fresh */
251 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("_SCPOpen CFGetTypeID(): not a dictionary."));
252 CFRelease(dict);
253 goto create_2;
254 }
255
256 prefsPrivate->prefs = CFDictionaryCreateMutableCopy(NULL, 0, dict);
257 CFRelease(dict);
258 }
259
260 create_2 :
261
262 if (fd != -1) {
263 (void) close(fd);
264 fd = -1;
265 }
266
267 if (prefsPrivate->prefs == NULL) {
268 /*
269 * new file, create empty preferences
270 */
271 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("_SCPOpen(): creating new dictionary."));
272 prefsPrivate->prefs = CFDictionaryCreateMutable(NULL,
273 0,
274 &kCFTypeDictionaryKeyCallBacks,
275 &kCFTypeDictionaryValueCallBacks);
276 prefsPrivate->changed = TRUE;
277 }
278
279 /*
280 * all OK
281 */
282 prefsPrivate->name = CFRetain(name);
283 if (prefsID) {
284 prefsPrivate->prefsID = CFRetain(prefsID);
285 }
286 prefsPrivate->perUser = perUser;
287 if (user) {
288 prefsPrivate->user = CFRetain(user);
289 }
290 return prefs;
291
292 error :
293
294 if (fd != -1) {
295 (void) close(fd);
296 }
297 CFRelease(prefs);
298 _SCErrorSet(sc_status);
299 return NULL;
300 }
301
302
303 SCPreferencesRef
304 SCPreferencesCreate(CFAllocatorRef allocator,
305 CFStringRef name,
306 CFStringRef prefsID)
307 {
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);
311
312 return __SCPreferencesCreate(allocator, name, prefsID, FALSE, NULL);
313 }
314
315
316 SCPreferencesRef
317 SCUserPreferencesCreate(CFAllocatorRef allocator,
318 CFStringRef name,
319 CFStringRef prefsID,
320 CFStringRef user)
321 {
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);
326
327 return __SCPreferencesCreate(allocator, name, prefsID, TRUE, user);
328 }
329
330
331 CFTypeID
332 SCPreferencesGetTypeID(void) {
333 return __kSCPreferencesTypeID;
334 }