/*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004, 2006 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
- *
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
* @APPLE_LICENSE_HEADER_END@
*/
+/*
+ * Modification History
+ *
+ * June 1, 2001 Allan Nathanson <ajn@apple.com>
+ * - public API conversion
+ *
+ * March 24, 2000 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+
#include "configd.h"
#include "session.h"
+#include "pattern.h"
-SCDStatus
-_SCDNotifierRemove(SCDSessionRef session, CFStringRef key, int regexOptions)
+
+__private_extern__
+int
+__SCDynamicStoreRemoveWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean isRegex, Boolean internal)
{
- SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session;
+ CFNumberRef sessionNum;
+ SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
- SCDLog(LOG_DEBUG, CFSTR("_SCDNotifierRemove:"));
- SCDLog(LOG_DEBUG, CFSTR(" key = %@"), key);
- SCDLog(LOG_DEBUG, CFSTR(" regexOptions = %0o"), regexOptions);
+ if ((store == NULL) || (storePrivate->server == MACH_PORT_NULL)) {
+ return kSCStatusNoStoreSession; /* you must have an open session to play */
+ }
- if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) {
- return SCD_NOSESSION; /* you can't do anything with a closed session */
+ if (_configd_trace) {
+ SCTrace(TRUE, _configd_trace,
+ CFSTR("%s : %5d : %s : %@\n"),
+ internal ? "*watch-" : "watch- ",
+ storePrivate->server,
+ isRegex ? "pattern" : "key",
+ key);
}
/*
* remove key from this sessions notifier list after checking that
* it was previously defined.
*/
- if (regexOptions & kSCDRegexKey) {
- if (!CFSetContainsValue(sessionPrivate->reKeys, key))
- return SCD_NOKEY; /* sorry, key does not exist in notifier list */
- CFSetRemoveValue(sessionPrivate->reKeys, key); /* remove key from this sessions notifier list */
- } else {
- if (!CFSetContainsValue(sessionPrivate->keys, key))
- return SCD_NOKEY; /* sorry, key does not exist in notifier list */
- CFSetRemoveValue(sessionPrivate->keys, key); /* remove key from this sessions notifier list */
- }
+ if (isRegex) {
+ if (!CFSetContainsValue(storePrivate->patterns, key))
+ return kSCStatusNoKey; /* sorry, key does not exist in notifier list */
+
+ /* remove key from this sessions notifier list */
+ CFSetRemoveValue(storePrivate->patterns, key);
- if (regexOptions & kSCDRegexKey) {
- CFStringRef sessionKey;
- CFDictionaryRef info;
- CFMutableDictionaryRef newInfo;
- CFArrayRef rKeys;
- CFMutableArrayRef newRKeys;
- CFArrayRef rData;
- CFMutableArrayRef newRData;
- CFIndex i;
- CFDataRef regexData;
- removeContext context;
-
- sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), sessionPrivate->server);
-
- info = CFDictionaryGetValue(sessionData, sessionKey);
- newInfo = CFDictionaryCreateMutableCopy(NULL, 0, info);
-
- rKeys = CFDictionaryGetValue(newInfo, kSCDRegexKeys);
- newRKeys = CFArrayCreateMutableCopy(NULL, 0, rKeys);
-
- rData = CFDictionaryGetValue(newInfo, kSCDRegexData);
- newRData = CFArrayCreateMutableCopy(NULL, 0, rData);
-
- i = CFArrayGetFirstIndexOfValue(newRKeys,
- CFRangeMake(0, CFArrayGetCount(newRData)),
- key);
- regexData = CFArrayGetValueAtIndex(newRData, i);
-
- context.session = sessionPrivate;
- context.preg = (regex_t *)CFDataGetBytePtr(regexData);
- CFDictionaryApplyFunction(cacheData,
- (CFDictionaryApplierFunction)_removeRegexWatcherByKey,
- &context);
-
- /* remove the regex key */
- CFArrayRemoveValueAtIndex(newRKeys, i);
- if (CFArrayGetCount(newRKeys) > 0) {
- CFDictionarySetValue(newInfo, kSCDRegexKeys, newRKeys);
- } else {
- CFDictionaryRemoveValue(newInfo, kSCDRegexKeys);
- }
- CFRelease(newRKeys);
-
- /* ...and the compiled expression */
- regfree((regex_t *)CFDataGetBytePtr(regexData));
- CFArrayRemoveValueAtIndex(newRData, i);
- if (CFArrayGetCount(newRData) > 0) {
- CFDictionarySetValue(newInfo, kSCDRegexData, newRData);
- } else {
- CFDictionaryRemoveValue(newInfo, kSCDRegexData);
- }
- CFRelease(newRData);
-
- /* save the updated session data */
- CFDictionarySetValue(sessionData, sessionKey, newInfo);
- CFRelease(newInfo);
-
- CFRelease(sessionKey);
+ /* remove this session as a pattern watcher */
+ sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &storePrivate->server);
+ patternRemoveSession(key, sessionNum);
+ CFRelease(sessionNum);
} else {
- CFNumberRef sessionNum;
+ if (!CFSetContainsValue(storePrivate->keys, key))
+ return kSCStatusNoKey; /* sorry, key does not exist in notifier list */
+
+ /* remove key from this sessions notifier list */
+ CFSetRemoveValue(storePrivate->keys, key);
/*
* We are watching a specific key. As such, update the
- * cache to mark our interest in any changes.
+ * store to mark our interest in any changes.
*/
-
- sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &sessionPrivate->server);
+ sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &storePrivate->server);
_removeWatcher(sessionNum, key);
CFRelease(sessionNum);
}
- return SCD_OK;
+ return kSCStatusOK;
}
+__private_extern__
kern_return_t
_notifyremove(mach_port_t server,
xmlData_t keyRef, /* raw XML bytes */
mach_msg_type_number_t keyLen,
- int regexOptions,
- int *scd_status
+ int isRegex,
+ int *sc_status
)
{
- kern_return_t status;
- serverSessionRef mySession = getSession(server);
- CFDataRef xmlKey; /* key (XML serialized) */
- CFStringRef key; /* key (un-serialized) */
- CFStringRef xmlError;
-
- SCDLog(LOG_DEBUG, CFSTR("Remove notification key for this session."));
- SCDLog(LOG_DEBUG, CFSTR(" server = %d"), server);
+ CFStringRef key = NULL; /* key (un-serialized) */
+ serverSessionRef mySession = getSession(server);
/* un-serialize the key */
- xmlKey = CFDataCreate(NULL, keyRef, keyLen);
- status = vm_deallocate(mach_task_self(), (vm_address_t)keyRef, keyLen);
- if (status != KERN_SUCCESS) {
- SCDLog(LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status));
- /* non-fatal???, proceed */
+ if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
+ *sc_status = kSCStatusFailed;
+ goto done;
}
- key = CFPropertyListCreateFromXMLData(NULL,
- xmlKey,
- kCFPropertyListImmutable,
- &xmlError);
- CFRelease(xmlKey);
- if (xmlError) {
- SCDLog(LOG_DEBUG, CFSTR("CFPropertyListCreateFromXMLData() key: %s"), xmlError);
- *scd_status = SCD_FAILED;
- return KERN_SUCCESS;
+
+ if (!isA_CFString(key)) {
+ *sc_status = kSCStatusInvalidArgument;
+ goto done;
}
- *scd_status = _SCDNotifierRemove(mySession->session, key, regexOptions);
- CFRelease(key);
+ if (mySession == NULL) {
+ *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
+ goto done;
+ }
+
+ *sc_status = __SCDynamicStoreRemoveWatchedKey(mySession->store,
+ key,
+ isRegex != 0,
+ FALSE);
+
+ done :
+ if (key) CFRelease(key);
return KERN_SUCCESS;
}