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"
39 #include <sys/errno.h>
42 SCPreferencesCommitChanges(SCPreferencesRef session
)
44 SCPreferencesPrivateRef sessionPrivate
= (SCPreferencesPrivateRef
)session
;
47 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("SCPreferencesCommitChanges:"));
50 * Determine if the we have exclusive access to the preferences
51 * and acquire the lock if necessary.
53 wasLocked
= sessionPrivate
->locked
;
55 if (!SCPreferencesLock(session
, TRUE
)) {
56 SCLog(_sc_verbose
, LOG_ERR
, CFSTR(" SCPreferencesLock() failed"));
62 * if necessary, apply changes
64 if (sessionPrivate
->changed
) {
71 if (stat(sessionPrivate
->path
, &statBuf
) == -1) {
72 if (errno
== ENOENT
) {
73 bzero(&statBuf
, sizeof(statBuf
));
74 statBuf
.st_mode
= 0644;
75 statBuf
.st_uid
= geteuid();
76 statBuf
.st_gid
= getegid();
78 SCLog(_sc_verbose
, LOG_ERR
, CFSTR("stat() failed: %s"), strerror(errno
));
83 /* create the (new) preferences file */
84 pathLen
= strlen(sessionPrivate
->path
) + sizeof("-new");
85 newPath
= CFAllocatorAllocate(NULL
, pathLen
, 0);
86 snprintf(newPath
, pathLen
, "%s-new", sessionPrivate
->path
);
88 /* open the (new) preferences file */
90 fd
= open(newPath
, O_WRONLY
|O_CREAT
, statBuf
.st_mode
);
92 if ((errno
== ENOENT
) &&
93 ((sessionPrivate
->prefsID
== NULL
) || !CFStringHasPrefix(sessionPrivate
->prefsID
, CFSTR("/")))) {
96 ch
= strrchr(newPath
, '/');
101 status
= mkdir(newPath
, 0755);
108 SCLog(_sc_verbose
, LOG_ERR
, CFSTR("SCPCommit open() failed: %s"), strerror(errno
));
109 CFAllocatorDeallocate(NULL
, newPath
);
113 /* preserve permissions */
114 (void) fchown(fd
, statBuf
.st_uid
, statBuf
.st_gid
);
116 /* write the new preferences */
117 newPrefs
= CFPropertyListCreateXMLData(NULL
, sessionPrivate
->prefs
);
119 _SCErrorSet(kSCStatusFailed
);
120 SCLog(_sc_verbose
, LOG_ERR
, CFSTR(" CFPropertyListCreateXMLData() failed"));
121 CFAllocatorDeallocate(NULL
, newPath
);
125 (void) write(fd
, CFDataGetBytePtr(newPrefs
), CFDataGetLength(newPrefs
));
129 /* rename new->old */
130 if (rename(newPath
, sessionPrivate
->path
) == -1) {
132 SCLog(_sc_verbose
, LOG_ERR
, CFSTR("rename() failed: %s"), strerror(errno
));
133 CFAllocatorDeallocate(NULL
, newPath
);
136 CFAllocatorDeallocate(NULL
, newPath
);
138 /* update signature */
139 if (stat(sessionPrivate
->path
, &statBuf
) == -1) {
141 SCLog(_sc_verbose
, LOG_ERR
, CFSTR("stat() failed: %s"), strerror(errno
));
144 CFRelease(sessionPrivate
->signature
);
145 sessionPrivate
->signature
= __SCPSignatureFromStatbuf(&statBuf
);
148 if (!sessionPrivate
->isRoot
) {
149 /* CONFIGD REALLY NEEDS NON-ROOT WRITE ACCESS */
153 /* if necessary, create the session "commit" key */
154 if (sessionPrivate
->sessionKeyCommit
== NULL
) {
155 sessionPrivate
->sessionKeyCommit
= _SCPNotificationKey(NULL
,
156 sessionPrivate
->prefsID
,
157 sessionPrivate
->perUser
,
158 sessionPrivate
->user
,
159 kSCPreferencesKeyCommit
);
162 /* post notification */
163 if (!SCDynamicStoreNotifyValue(sessionPrivate
->session
,
164 sessionPrivate
->sessionKeyCommit
)) {
165 SCLog(_sc_verbose
, LOG_ERR
, CFSTR(" SCDynamicStoreNotifyValue() failed"));
166 _SCErrorSet(kSCStatusFailed
);
172 if (!wasLocked
) (void) SCPreferencesUnlock(session
);
173 sessionPrivate
->changed
= FALSE
;
178 if (!wasLocked
) (void) SCPreferencesUnlock(session
);