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@
23 #include <SystemConfiguration/SCP.h>
24 #include "SCPPrivate.h"
26 #include <SystemConfiguration/SCD.h>
30 #include <sys/errno.h>
34 SCPCommit(SCPSessionRef session
)
36 SCPSessionPrivateRef sessionPrivate
;
37 SCPStatus scp_status
= SCP_OK
;
41 if (session
== NULL
) {
42 return SCP_FAILED
; /* you can't do anything with a closed session */
44 sessionPrivate
= (SCPSessionPrivateRef
)session
;
47 * Determine if the we have exclusive access to the preferences
48 * and acquire the lock if necessary.
50 wasLocked
= sessionPrivate
->locked
;
52 scp_status
= SCPLock(session
, TRUE
);
53 if (scp_status
!= SCD_OK
) {
54 SCDLog(LOG_DEBUG
, CFSTR(" SCPLock(): %s"), SCPError(scp_status
));
60 * if necessary, apply changes
62 if (sessionPrivate
->changed
) {
69 if (stat(sessionPrivate
->path
, &statBuf
) == -1) {
70 if (errno
== ENOENT
) {
71 bzero(&statBuf
, sizeof(statBuf
));
72 statBuf
.st_mode
= 0644;
73 statBuf
.st_uid
= geteuid();
74 statBuf
.st_gid
= getegid();
76 SCDLog(LOG_DEBUG
, CFSTR("stat() failed: %s"), strerror(errno
));
77 scp_status
= SCP_FAILED
;
82 /* create the (new) preferences file */
83 pathLen
= strlen(sessionPrivate
->path
) + sizeof("-new");
84 newPath
= CFAllocatorAllocate(NULL
, pathLen
, 0);
85 snprintf(newPath
, pathLen
, "%s-new", sessionPrivate
->path
);
87 /* open the (new) preferences file */
89 fd
= open(newPath
, O_WRONLY
|O_CREAT
, statBuf
.st_mode
);
91 if ((errno
== ENOENT
) &&
92 ((sessionPrivate
->prefsID
== NULL
) || !CFStringHasPrefix(sessionPrivate
->prefsID
, CFSTR("/")))) {
95 ch
= strrchr(newPath
, '/');
100 status
= mkdir(newPath
, 0755);
107 SCDLog(LOG_DEBUG
, CFSTR("SCPCommit open() failed: %s"), strerror(errno
));
108 CFAllocatorDeallocate(NULL
, newPath
);
109 scp_status
= SCP_FAILED
;
113 /* preserve permissions */
114 (void)fchown(fd
, statBuf
.st_uid
, statBuf
.st_gid
);
116 /* write the new preferences */
117 newPrefs
= CFPropertyListCreateXMLData(NULL
, sessionPrivate
->prefs
);
118 (void) write(fd
, CFDataGetBytePtr(newPrefs
), CFDataGetLength(newPrefs
));
122 /* rename new->old */
123 if (rename(newPath
, sessionPrivate
->path
) == -1) {
124 SCDLog(LOG_DEBUG
, CFSTR("rename() failed: %s"), strerror(errno
));
125 CFAllocatorDeallocate(NULL
, newPath
);
126 scp_status
= SCP_FAILED
;
129 CFAllocatorDeallocate(NULL
, newPath
);
131 /* update signature */
132 if (stat(sessionPrivate
->path
, &statBuf
) == -1) {
133 SCDLog(LOG_DEBUG
, CFSTR("stat() failed: %s"), strerror(errno
));
134 scp_status
= SCP_FAILED
;
137 CFRelease(sessionPrivate
->signature
);
138 sessionPrivate
->signature
= _SCPSignatureFromStatbuf(&statBuf
);
141 if (!sessionPrivate
->isRoot
) {
142 /* CONFIGD REALLY NEEDS NON-ROOT WRITE ACCESS */
146 /* if necessary, create the session "commit" key */
147 if (sessionPrivate
->sessionKeyCommit
== NULL
) {
148 sessionPrivate
->sessionKeyCommit
= _SCPNotificationKey(sessionPrivate
->prefsID
,
149 sessionPrivate
->perUser
,
150 sessionPrivate
->user
,
154 /* post notification */
155 scd_status
= SCDLock(sessionPrivate
->session
);
156 if (scd_status
== SCD_OK
) {
157 (void) SCDTouch (sessionPrivate
->session
, sessionPrivate
->sessionKeyCommit
);
158 (void) SCDRemove(sessionPrivate
->session
, sessionPrivate
->sessionKeyCommit
);
159 (void) SCDUnlock(sessionPrivate
->session
);
161 SCDLog(LOG_DEBUG
, CFSTR(" SCDLock(): %s"), SCDError(scd_status
));
162 scp_status
= SCP_FAILED
;
168 (void) SCPUnlock(session
);
170 sessionPrivate
->changed
= FALSE
;