]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCPOpen.c
configd-24.1.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 #include <SystemConfiguration/SCP.h>
24 #include <SystemConfiguration/SCPPath.h>
25 #include "SCPPrivate.h"
26
27 #include <SystemConfiguration/SCD.h>
28
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <sys/errno.h>
32
33
34 static SCPStatus
35 _SCPOpen(SCPSessionRef *session,
36 CFStringRef name,
37 CFStringRef prefsID,
38 boolean_t perUser,
39 CFStringRef user,
40 int options)
41 {
42 SCPStatus scp_status;
43 SCPSessionPrivateRef newSession;
44 int fd = -1;
45 struct stat statBuf;
46 CFMutableDataRef xmlData;
47 CFStringRef xmlError;
48
49 newSession = (SCPSessionPrivateRef)CFAllocatorAllocate(NULL, sizeof(SCPSessionPrivate), 0);
50 newSession->name = NULL;
51 newSession->prefsID = NULL;
52 newSession->perUser = perUser;
53 newSession->user = NULL;
54 newSession->path = NULL;
55 newSession->signature = NULL;
56 newSession->session = NULL;
57 newSession->sessionKeyLock = NULL;
58 newSession->sessionKeyCommit = NULL;
59 newSession->sessionKeyApply = NULL;
60 newSession->prefs = NULL;
61 newSession->changed = FALSE;
62 newSession->locked = FALSE;
63 newSession->isRoot = (geteuid() == 0);
64
65 /*
66 * convert prefsID to path
67 */
68 newSession->path = _SCPPrefsPath(prefsID, perUser, user);
69 if (newSession->path == NULL) {
70 scp_status = SCP_FAILED;
71 goto error;
72 }
73
74 /*
75 * open file
76 */
77 fd = open(newSession->path, O_RDONLY, 0644);
78 if (fd == -1) {
79 char *errmsg = strerror(errno);
80
81 switch (errno) {
82 case ENOENT :
83 if (options & kSCPOpenCreatePrefs) {
84 bzero(&statBuf, sizeof(statBuf));
85 goto create_1;
86 }
87 scp_status = SCP_ENOENT;
88 break;
89 case EACCES :
90 scp_status = SCP_EACCESS;
91 break;
92 default :
93 scp_status = SCP_FAILED;
94 }
95 SCDLog(LOG_DEBUG, CFSTR("open() failed: %s"), errmsg);
96 goto error;
97 }
98
99 /*
100 * check file, create signature
101 */
102 if (fstat(fd, &statBuf) == -1) {
103 SCDLog(LOG_DEBUG, CFSTR("fstat() failed: %s"), strerror(errno));
104 scp_status = SCP_FAILED;
105 goto error;
106 }
107
108 create_1 :
109
110 newSession->signature = _SCPSignatureFromStatbuf(&statBuf);
111
112 if (statBuf.st_size > 0) {
113 /*
114 * extract property list
115 */
116 xmlData = CFDataCreateMutable(NULL, statBuf.st_size);
117 CFDataSetLength(xmlData, statBuf.st_size);
118 if (read(fd, (void *)CFDataGetBytePtr(xmlData), statBuf.st_size) != statBuf.st_size) {
119 SCDLog(LOG_DEBUG, CFSTR("_SCPOpen read(): could not load preference data."));
120 CFRelease(xmlData);
121 xmlData = NULL;
122 if (options & kSCPOpenCreatePrefs) {
123 goto create_2;
124 }
125 scp_status = SCP_BADCF;
126 goto error;
127 }
128
129 /*
130 * load preferences
131 */
132 newSession->prefs = (CFMutableDictionaryRef)
133 CFPropertyListCreateFromXMLData(NULL,
134 xmlData,
135 kCFPropertyListMutableContainers,
136 &xmlError);
137 CFRelease(xmlData);
138 if (xmlError) {
139 SCDLog(LOG_DEBUG, CFSTR("_SCPOpen CFPropertyListCreateFromXMLData(): %s"), xmlError);
140 if (options & kSCPOpenCreatePrefs) {
141 goto create_2;
142 }
143 scp_status = SCP_BADCF;
144 goto error;
145 }
146
147 /*
148 * make sure that we've got a dictionary
149 */
150 if (CFGetTypeID(newSession->prefs) != CFDictionaryGetTypeID()) {
151 SCDLog(LOG_DEBUG, CFSTR("_SCPOpen CFGetTypeID(): not a dictionary."));
152 CFRelease(newSession->prefs);
153 newSession->prefs = NULL;
154 if (options & kSCPOpenCreatePrefs) {
155 goto create_2;
156 }
157 scp_status = SCP_BADCF;
158 goto error;
159 }
160 }
161
162 create_2 :
163
164 if (fd != -1) {
165 (void) close(fd);
166 fd = -1;
167 }
168
169 if (newSession->prefs == NULL) {
170 /*
171 * new file, create empty preferences
172 */
173 SCDLog(LOG_DEBUG, CFSTR("_SCPOpen(): creating new dictionary."));
174 newSession->prefs = CFDictionaryCreateMutable(NULL,
175 0,
176 &kCFTypeDictionaryKeyCallBacks,
177 &kCFTypeDictionaryValueCallBacks);
178 newSession->changed = TRUE;
179 }
180
181 /*
182 * all OK
183 */
184 newSession->name = CFRetain(name);
185 if (prefsID) {
186 newSession->prefsID = CFRetain(prefsID);
187 }
188 newSession->perUser = perUser;
189 if (user) {
190 newSession->user = CFRetain(user);
191 }
192 *session = (SCPSessionRef)newSession;
193 return SCP_OK;
194
195 error :
196
197 if (fd != -1) {
198 (void)close(fd);
199 }
200 (void) SCPClose((SCPSessionRef *)&newSession);
201 return scp_status;
202 }
203
204
205 SCPStatus
206 SCPOpen(SCPSessionRef *session,
207 CFStringRef name,
208 CFStringRef prefsID,
209 int options)
210 {
211 return _SCPOpen(session, name, prefsID, FALSE, NULL, options);
212 }
213
214
215 SCPStatus
216 SCPUserOpen(SCPSessionRef *session,
217 CFStringRef name,
218 CFStringRef prefsID,
219 CFStringRef user,
220 int options)
221 {
222 return _SCPOpen(session, name, prefsID, TRUE, user, options);
223 }