2 * Copyright(c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
27 * Modification History
29 * June 1, 2001 Allan Nathanson <ajn@apple.com>
30 * - public API conversion
32 * November 9, 2000 Allan Nathanson <ajn@apple.com>
36 #include <SystemConfiguration/SystemConfiguration.h>
37 #include <SystemConfiguration/SCPrivate.h>
38 #include "SCPreferencesInternal.h"
42 #include <sys/errno.h>
45 writen(int d
, const void *buf
, size_t nbytes
)
53 n
= write(d
, p
, left
);
68 SCPreferencesCommitChanges(SCPreferencesRef session
)
70 SCPreferencesPrivateRef sessionPrivate
= (SCPreferencesPrivateRef
)session
;
73 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("SCPreferencesCommitChanges:"));
76 * Determine if the we have exclusive access to the preferences
77 * and acquire the lock if necessary.
79 wasLocked
= sessionPrivate
->locked
;
81 if (!SCPreferencesLock(session
, TRUE
)) {
82 SCLog(_sc_verbose
, LOG_ERR
, CFSTR(" SCPreferencesLock() failed"));
88 * if necessary, apply changes
90 if (sessionPrivate
->changed
) {
98 if (stat(sessionPrivate
->path
, &statBuf
) == -1) {
99 if (errno
== ENOENT
) {
100 bzero(&statBuf
, sizeof(statBuf
));
101 statBuf
.st_mode
= 0644;
102 statBuf
.st_uid
= geteuid();
103 statBuf
.st_gid
= getegid();
105 SCLog(_sc_verbose
, LOG_ERR
, CFSTR("stat() failed: %s"), strerror(errno
));
110 /* create the (new) preferences file */
111 path
= sessionPrivate
->newPath
? sessionPrivate
->newPath
: sessionPrivate
->path
;
112 pathLen
= strlen(path
) + sizeof("-new");
113 thePath
= CFAllocatorAllocate(NULL
, pathLen
, 0);
114 snprintf(thePath
, pathLen
, "%s-new", path
);
116 /* open the (new) preferences file */
118 fd
= open(thePath
, O_WRONLY
|O_CREAT
, statBuf
.st_mode
);
120 if ((errno
== ENOENT
) &&
121 ((sessionPrivate
->prefsID
== NULL
) || !CFStringHasPrefix(sessionPrivate
->prefsID
, CFSTR("/")))) {
124 ch
= strrchr(thePath
, '/');
129 status
= mkdir(thePath
, 0755);
136 SCLog(_sc_verbose
, LOG_ERR
, CFSTR("SCPCommit open() failed: %s"), strerror(errno
));
137 CFAllocatorDeallocate(NULL
, thePath
);
141 /* preserve permissions */
142 (void) fchown(fd
, statBuf
.st_uid
, statBuf
.st_gid
);
143 (void) fchmod(fd
, statBuf
.st_mode
);
145 /* write the new preferences */
146 newPrefs
= CFPropertyListCreateXMLData(NULL
, sessionPrivate
->prefs
);
148 _SCErrorSet(kSCStatusFailed
);
149 SCLog(_sc_verbose
, LOG_ERR
, CFSTR(" CFPropertyListCreateXMLData() failed"));
150 CFAllocatorDeallocate(NULL
, thePath
);
154 if (writen(fd
, (void *)CFDataGetBytePtr(newPrefs
), CFDataGetLength(newPrefs
)) == -1) {
156 SCLog(_sc_verbose
, LOG_ERR
, CFSTR("write() failed: %s"), strerror(errno
));
157 (void) unlink(thePath
);
158 CFAllocatorDeallocate(NULL
, thePath
);
166 /* rename new->old */
167 if (rename(thePath
, path
) == -1) {
169 SCLog(_sc_verbose
, LOG_ERR
, CFSTR("rename() failed: %s"), strerror(errno
));
170 CFAllocatorDeallocate(NULL
, thePath
);
173 CFAllocatorDeallocate(NULL
, thePath
);
175 if (sessionPrivate
->newPath
) {
176 /* prefs file saved in "new" directory */
177 (void) unlink(sessionPrivate
->path
);
178 (void) symlink(sessionPrivate
->newPath
, sessionPrivate
->path
);
179 CFAllocatorDeallocate(NULL
, sessionPrivate
->path
);
180 sessionPrivate
->path
= path
;
181 sessionPrivate
->newPath
= NULL
;
184 /* update signature */
185 if (stat(path
, &statBuf
) == -1) {
187 SCLog(_sc_verbose
, LOG_ERR
, CFSTR("stat() failed: %s"), strerror(errno
));
190 CFRelease(sessionPrivate
->signature
);
191 sessionPrivate
->signature
= __SCPSignatureFromStatbuf(&statBuf
);
194 if (!sessionPrivate
->isRoot
) {
195 /* CONFIGD REALLY NEEDS NON-ROOT WRITE ACCESS */
199 /* if necessary, create the session "commit" key */
200 if (sessionPrivate
->sessionKeyCommit
== NULL
) {
201 sessionPrivate
->sessionKeyCommit
= _SCPNotificationKey(NULL
,
202 sessionPrivate
->prefsID
,
203 sessionPrivate
->perUser
,
204 sessionPrivate
->user
,
205 kSCPreferencesKeyCommit
);
208 /* post notification */
209 if (!SCDynamicStoreNotifyValue(sessionPrivate
->session
,
210 sessionPrivate
->sessionKeyCommit
)) {
211 SCLog(_sc_verbose
, LOG_ERR
, CFSTR(" SCDynamicStoreNotifyValue() failed"));
212 _SCErrorSet(kSCStatusFailed
);
218 if (!wasLocked
) (void) SCPreferencesUnlock(session
);
219 sessionPrivate
->changed
= FALSE
;
224 if (!wasLocked
) (void) SCPreferencesUnlock(session
);