2 * Copyright(c) 2000-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * June 1, 2001 Allan Nathanson <ajn@apple.com>
28 * - public API conversion
30 * November 9, 2000 Allan Nathanson <ajn@apple.com>
34 #include <SystemConfiguration/SystemConfiguration.h>
35 #include <SystemConfiguration/SCPrivate.h>
36 #include "SCPreferencesInternal.h"
40 #include <sys/errno.h>
43 SCPreferencesLock(SCPreferencesRef session
, Boolean wait
)
45 CFAllocatorRef allocator
= CFGetAllocator(session
);
47 CFDataRef currentSignature
= NULL
;
48 Boolean haveLock
= FALSE
;
49 SCPreferencesPrivateRef sessionPrivate
= (SCPreferencesPrivateRef
)session
;
51 CFDateRef value
= NULL
;
53 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("SCPreferencesLock:"));
55 if (sessionPrivate
->locked
) {
56 /* sorry, you already have the lock */
57 _SCErrorSet(kSCStatusLocked
);
61 if (!sessionPrivate
->isRoot
) {
62 if (!sessionPrivate
->perUser
) {
63 _SCErrorSet(kSCStatusAccessError
);
66 /* CONFIGD REALLY NEEDS NON-ROOT WRITE ACCESS */
71 if (sessionPrivate
->session
== NULL
) {
73 sessionPrivate
->session
= SCDynamicStoreCreate(allocator
,
74 CFSTR("SCPreferencesLock"),
77 if (!sessionPrivate
->session
) {
78 SCLog(_sc_verbose
, LOG_INFO
, CFSTR("SCDynamicStoreCreate() failed"));
83 if (sessionPrivate
->sessionKeyLock
== NULL
) {
84 /* create the session "lock" key */
85 sessionPrivate
->sessionKeyLock
= _SCPNotificationKey(allocator
,
86 sessionPrivate
->prefsID
,
87 sessionPrivate
->perUser
,
89 kSCPreferencesKeyLock
);
92 if (!SCDynamicStoreAddWatchedKey(sessionPrivate
->session
,
93 sessionPrivate
->sessionKeyLock
,
95 SCLog(_sc_verbose
, LOG_INFO
, CFSTR("SCDynamicStoreAddWatchedKey() failed"));
99 value
= CFDateCreate(allocator
, CFAbsoluteTimeGetCurrent());
102 CFArrayRef changedKeys
;
105 * Attempt to acquire the lock
107 if (SCDynamicStoreAddTemporaryValue(sessionPrivate
->session
,
108 sessionPrivate
->sessionKeyLock
,
114 _SCErrorSet(kSCStatusPrefsBusy
);
120 * Wait for the lock to be released
122 if (!SCDynamicStoreNotifyWait(sessionPrivate
->session
)) {
123 SCLog(_sc_verbose
, LOG_INFO
, CFSTR("SCDynamicStoreNotifyWait() failed"));
126 changedKeys
= SCDynamicStoreCopyNotifiedKeys(sessionPrivate
->session
);
128 SCLog(_sc_verbose
, LOG_INFO
, CFSTR("SCDynamicStoreCopyNotifiedKeys() failed"));
131 CFRelease(changedKeys
);
139 if (!SCDynamicStoreRemoveWatchedKey(sessionPrivate
->session
,
140 sessionPrivate
->sessionKeyLock
,
142 SCLog(_sc_verbose
, LOG_INFO
, CFSTR("SCDynamicStoreRemoveWatchedKey() failed"));
146 changes
= SCDynamicStoreCopyNotifiedKeys(sessionPrivate
->session
);
148 SCLog(_sc_verbose
, LOG_INFO
, CFSTR("SCDynamicStoreCopyNotifiedKeys() failed"));
156 * Check the signature
158 if (stat(sessionPrivate
->path
, &statBuf
) == -1) {
159 if (errno
== ENOENT
) {
160 bzero(&statBuf
, sizeof(statBuf
));
162 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("stat() failed: %s"), strerror(errno
));
163 _SCErrorSet(kSCStatusStale
);
168 currentSignature
= __SCPSignatureFromStatbuf(&statBuf
);
169 if (!CFEqual(sessionPrivate
->signature
, currentSignature
)) {
170 if (sessionPrivate
->accessed
) {
172 * the preferences have been accessed since the
173 * session was created so we've got no choice
174 * but to deny the lock request.
176 _SCErrorSet(kSCStatusStale
);
180 * the file contents have changed but since we
181 * haven't accessed any of the preferences we
182 * don't need to return an error. Simply reload
183 * the stored data and proceed.
185 SCPreferencesRef newPrefs
;
186 SCPreferencesPrivateRef newPrivate
;
188 newPrefs
= __SCPreferencesCreate(allocator
,
189 sessionPrivate
->name
,
190 sessionPrivate
->prefsID
,
191 sessionPrivate
->perUser
,
192 sessionPrivate
->user
);
194 /* if updated preferences could not be loaded */
195 _SCErrorSet(kSCStatusStale
);
199 /* synchronize this sessions prefs/signature */
200 newPrivate
= (SCPreferencesPrivateRef
)newPrefs
;
201 CFRelease(sessionPrivate
->prefs
);
202 sessionPrivate
->prefs
= newPrivate
->prefs
;
203 CFRetain(sessionPrivate
->prefs
);
204 CFRelease(sessionPrivate
->signature
);
205 sessionPrivate
->signature
= CFRetain(newPrivate
->signature
);
209 CFRelease(currentSignature
);
211 sessionPrivate
->locked
= TRUE
;
217 SCDynamicStoreRemoveValue(sessionPrivate
->session
,
218 sessionPrivate
->sessionKeyLock
);
220 if (currentSignature
) CFRelease(currentSignature
);
221 if (value
) CFRelease(value
);