]> git.saurik.com Git - apple/configd.git/blame - configd.tproj/_configunlock.c
configd-1109.101.1.tar.gz
[apple/configd.git] / configd.tproj / _configunlock.c
CommitLineData
5958d7c0 1/*
afb19109 2 * Copyright (c) 2000-2004, 2006, 2011, 2015, 2017, 2019 Apple Inc. All rights reserved.
5958d7c0
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
afb19109 5 *
009ee3c6
A
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
11 * file.
afb19109 12 *
009ee3c6
A
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
5958d7c0
A
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
009ee3c6
A
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.
afb19109 20 *
5958d7c0
A
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
0fae82ee
A
24/*
25 * Modification History
26 *
27 * June 1, 2001 Allan Nathanson <ajn@apple.com>
28 * - public API conversion
29 *
30 * March 24, 2000 Allan Nathanson <ajn@apple.com>
31 * - initial revision
32 */
33
5958d7c0
A
34
35#include "configd.h"
36#include "configd_server.h"
37#include "session.h"
009ee3c6
A
38#include "pattern.h"
39
40
41#define N_QUICK 32
5958d7c0
A
42
43
44static void
45_notifyWatchers()
46{
47 CFIndex keyCnt;
009ee3c6
A
48 const void * keys_q[N_QUICK];
49 const void ** keys = keys_q;
5958d7c0 50
a5f60add
A
51 keyCnt = CFSetGetCount(changedKeys);
52 if (keyCnt == 0)
5958d7c0
A
53 return; /* if nothing to do */
54
009ee3c6
A
55 if (keyCnt > (CFIndex)(sizeof(keys_q) / sizeof(CFStringRef)))
56 keys = CFAllocatorAllocate(NULL, keyCnt * sizeof(CFStringRef), 0);
57
5958d7c0 58 CFSetGetValues(changedKeys, keys);
009ee3c6 59
5958d7c0 60 while (--keyCnt >= 0) {
afb19109 61 CFStringRef changedKey = (CFStringRef)keys[keyCnt];
5958d7c0 62 CFDictionaryRef dict;
009ee3c6
A
63 CFArrayRef sessionsWatchingKey;
64 CFIndex watcherCnt;
65 const void * watchers_q[N_QUICK];
66 const void ** watchers = watchers_q;
5958d7c0 67
afb19109 68 dict = CFDictionaryGetValue(storeData, changedKey);
942cecd7 69 if ((dict == NULL) || !CFDictionaryContainsKey(dict, kSCDWatchers)) {
5958d7c0
A
70 /* key doesn't exist or nobody cares if it changed */
71 continue;
72 }
73
74 /*
75 * Add this key to the list of changes for each of the
76 * sessions which is "watching".
77 */
78 sessionsWatchingKey = CFDictionaryGetValue(dict, kSCDWatchers);
79 watcherCnt = CFArrayGetCount(sessionsWatchingKey);
009ee3c6
A
80 if (watcherCnt == 0) {
81 /* if no watchers */
82 continue;
83 }
84
85 if (watcherCnt > (CFIndex)(sizeof(watchers_q) / sizeof(CFNumberRef)))
86 watchers = CFAllocatorAllocate(NULL, watcherCnt * sizeof(CFNumberRef), 0);
87
88 CFArrayGetValues(sessionsWatchingKey, CFRangeMake(0, watcherCnt), watchers);
89
90 while (--watcherCnt >= 0) {
afb19109
A
91 serverSessionRef session;
92 CFNumberRef watchedSession = watchers[watcherCnt];
009ee3c6 93
afb19109
A
94 session = getSessionNum(watchedSession);
95 if (session->changedKeys == NULL) {
96 session->changedKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
009ee3c6 97 }
afb19109
A
98 if (!CFArrayContainsValue(session->changedKeys,
99 CFRangeMake(0, CFArrayGetCount(session->changedKeys)),
100 changedKey)) {
101 CFArrayAppendValue(session->changedKeys, changedKey);
009ee3c6 102 }
009ee3c6
A
103
104 /*
105 * flag this session as needing a kick
106 */
107 if (needsNotification == NULL)
108 needsNotification = CFSetCreateMutable(NULL,
109 0,
110 &kCFTypeSetCallBacks);
afb19109 111 CFSetAddValue(needsNotification, watchedSession);
5958d7c0 112 }
009ee3c6
A
113
114 if (watchers != watchers_q) CFAllocatorDeallocate(NULL, watchers);
5958d7c0 115 }
009ee3c6
A
116
117 if (keys != keys_q) CFAllocatorDeallocate(NULL, keys);
5958d7c0
A
118
119 /*
120 * The list of changed keys have been updated for any sessions
0fae82ee 121 * monitoring changes to the "store". The next step, handled by
5958d7c0
A
122 * the "configd" server, is to push out any needed notifications.
123 */
124 CFSetRemoveAllValues(changedKeys);
125
126}
127
128
129static void
130_processDeferredRemovals()
131{
132 CFIndex keyCnt;
009ee3c6
A
133 const void * keys_q[N_QUICK];
134 const void ** keys = keys_q;
5958d7c0 135
a5f60add
A
136 keyCnt = CFSetGetCount(deferredRemovals);
137 if (keyCnt == 0)
5958d7c0
A
138 return; /* if nothing to do */
139
009ee3c6
A
140 if (keyCnt > (CFIndex)(sizeof(keys_q) / sizeof(CFStringRef)))
141 keys = CFAllocatorAllocate(NULL, keyCnt * sizeof(CFStringRef), 0);
142
5958d7c0 143 CFSetGetValues(deferredRemovals, keys);
009ee3c6 144
5958d7c0 145 while (--keyCnt >= 0) {
009ee3c6 146 patternRemoveKey((CFStringRef)keys[keyCnt]);
5958d7c0 147 }
009ee3c6
A
148
149 if (keys != keys_q) CFAllocatorDeallocate(NULL, keys);
5958d7c0
A
150
151 /*
0fae82ee 152 * All regex keys associated with removed store dictionary keys have
5958d7c0
A
153 * been removed. Start the list fresh again.
154 */
155 CFSetRemoveAllValues(deferredRemovals);
156
157 return;
158}
159
160
161static void
162_cleanupRemovedSessionKeys(const void *value, void *context)
163{
1ef45fa4 164#pragma unused(context)
5958d7c0
A
165 CFStringRef removedKey = (CFStringRef)value;
166 CFRange dRange;
afb19109 167 serverSessionRef session;
5958d7c0
A
168 CFStringRef sessionKey;
169 CFStringRef key;
5958d7c0 170 CFIndex i;
5958d7c0
A
171
172 dRange = CFStringFind(removedKey, CFSTR(":"), 0);
173 sessionKey = CFStringCreateWithSubstring(NULL,
174 removedKey,
175 CFRangeMake(0, dRange.location));
176 key = CFStringCreateWithSubstring(NULL,
177 removedKey,
178 CFRangeMake(dRange.location+dRange.length,
179 CFStringGetLength(removedKey)-dRange.location-dRange.length));
180
afb19109
A
181 session = getSessionStr(sessionKey);
182 if (session == NULL) {
5958d7c0
A
183 /* if no session */
184 goto done;
185 }
186
afb19109
A
187 i = CFArrayGetFirstIndexOfValue(session->sessionKeys,
188 CFRangeMake(0, CFArrayGetCount(session->sessionKeys)),
5958d7c0 189 key);
dbf6a266 190 if (i == kCFNotFound) {
5958d7c0
A
191 /* if this session key has already been removed */
192 goto done;
193 }
afb19109
A
194 CFArrayRemoveValueAtIndex(session->sessionKeys, i);
195 if (CFArrayGetCount(session->sessionKeys) == 0) {
196 CFRelease(session->sessionKeys);
197 session->sessionKeys = NULL;
5958d7c0 198 }
5958d7c0
A
199
200 done:
201
202 CFRelease(sessionKey);
203 CFRelease(key);
204
205 return;
206}
207
208
009ee3c6 209__private_extern__
0fae82ee 210int
17d3ee29 211__SCDynamicStorePush(void)
5958d7c0 212{
5958d7c0
A
213 /*
214 * push notifications to any session watching those keys which
215 * were recently changed.
216 */
217 _notifyWatchers();
218
219 /*
220 * process any deferred key deletions.
221 */
222 _processDeferredRemovals();
223
224 /*
225 * clean up any removed session keys
226 */
227 CFSetApplyFunction(removedSessionKeys, _cleanupRemovedSessionKeys, NULL);
228 CFSetRemoveAllValues(removedSessionKeys);
229
0fae82ee 230 return kSCStatusOK;
5958d7c0 231}