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