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 SCPLock(SCPSessionRef session
, boolean_t wait
)
38 SCPSessionPrivateRef sessionPrivate
;
39 SCDHandleRef handle
= NULL
;
43 CFDataRef currentSignature
;
45 if (session
== NULL
) {
46 return SCP_FAILED
; /* you can't do anything with a closed session */
48 sessionPrivate
= (SCPSessionPrivateRef
)session
;
50 if (!sessionPrivate
->isRoot
) {
51 /* CONFIGD REALLY NEEDS NON-ROOT WRITE ACCESS */
55 if (sessionPrivate
->session
== NULL
) {
57 scd_status
= SCDOpen(&sessionPrivate
->session
, sessionPrivate
->name
);
58 if (scd_status
!= SCD_OK
) {
59 SCDLog(LOG_INFO
, CFSTR("SCDOpen() failed: %s"), SCDError(scd_status
));
64 if (sessionPrivate
->sessionKeyLock
== NULL
) {
65 /* create the session "lock" key */
66 sessionPrivate
->sessionKeyLock
= _SCPNotificationKey(sessionPrivate
->prefsID
,
67 sessionPrivate
->perUser
,
72 scd_status
= SCDNotifierAdd(sessionPrivate
->session
,
73 sessionPrivate
->sessionKeyLock
,
75 if (scd_status
!= SCD_OK
) {
76 SCDLog(LOG_INFO
, CFSTR("SCDNotifierAdd() failed: %s"), SCDError(scd_status
));
77 scp_status
= SCP_FAILED
;
81 handle
= SCDHandleInit();
82 value
= CFDateCreate(NULL
, CFAbsoluteTimeGetCurrent());
83 SCDHandleSetData(handle
, value
);
88 * Attempt to acquire the lock
90 scd_status
= SCDAddSession(sessionPrivate
->session
,
91 sessionPrivate
->sessionKeyLock
,
99 scp_status
= SCP_BUSY
;
104 SCDLog(LOG_INFO
, CFSTR("SCDAddSession() failed: %s"), SCDError(scd_status
));
105 scp_status
= SCP_FAILED
;
110 * Wait for the lock to be released
112 scd_status
= SCDNotifierWait(sessionPrivate
->session
);
113 if (scd_status
!= SCD_OK
) {
114 SCDLog(LOG_INFO
, CFSTR("SCDAddSession() failed: %s"), SCDError(scd_status
));
115 scp_status
= SCP_FAILED
;
122 SCDHandleRelease(handle
);
125 scd_status
= SCDNotifierRemove(sessionPrivate
->session
,
126 sessionPrivate
->sessionKeyLock
,
128 if (scd_status
!= SCD_OK
) {
129 SCDLog(LOG_INFO
, CFSTR("SCDNotifierRemove() failed: %s"), SCDError(scd_status
));
130 scp_status
= SCP_FAILED
;
134 scd_status
= SCDNotifierGetChanges(sessionPrivate
->session
, &changes
);
135 if (scd_status
!= SCD_OK
) {
136 SCDLog(LOG_INFO
, CFSTR("SCDNotifierGetChanges() failed: %s"), SCDError(scd_status
));
137 scp_status
= SCP_FAILED
;
145 * Check the signature
147 if (stat(sessionPrivate
->path
, &statBuf
) == -1) {
148 if (errno
== ENOENT
) {
149 bzero(&statBuf
, sizeof(statBuf
));
151 SCDLog(LOG_DEBUG
, CFSTR("stat() failed: %s"), strerror(errno
));
152 scp_status
= SCP_STALE
;
157 currentSignature
= _SCPSignatureFromStatbuf(&statBuf
);
158 if (!CFEqual(sessionPrivate
->signature
, currentSignature
)) {
159 CFRelease(currentSignature
);
160 scp_status
= SCP_STALE
;
163 CFRelease(currentSignature
);
165 sessionPrivate
->locked
= TRUE
;
170 if (handle
) SCDHandleRelease(handle
);