/*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2005, 2009-2011, 2013, 2016, 2017, 2019 Apple 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 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.
*
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * 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@
*/
-#include <sys/types.h>
-#include <regex.h>
-
-#include <mach/mach.h>
-#include <mach/mach_error.h>
+/*
+ * Modification History
+ *
+ * June 1, 2001 Allan Nathanson <ajn@apple.com>
+ * - public API conversion
+ *
+ * March 24, 2000 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
-#include <SystemConfiguration/SCD.h>
+#include "SCDynamicStoreInternal.h"
#include "config.h" /* MiG generated file */
-#include "SCDPrivate.h"
-SCDStatus
-SCDNotifierAdd(SCDSessionRef session, CFStringRef key, int regexOptions)
+static void
+addKey(CFMutableArrayRef *keysP, CFStringRef key)
{
- SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session;
- kern_return_t status;
- CFDataRef xmlKey; /* serialized key */
- xmlData_t myKeyRef;
- CFIndex myKeyLen;
- SCDStatus scd_status;
-
- SCDLog(LOG_DEBUG, CFSTR("SCDNotifierAdd:"));
- SCDLog(LOG_DEBUG, CFSTR(" key = %@"), key);
- SCDLog(LOG_DEBUG, CFSTR(" regexOptions = %0o"), regexOptions);
-
- if (key == NULL) {
- return SCD_INVALIDARGUMENT; /* no key specified */
+ if (*keysP == NULL) {
+ *keysP = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
}
- if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) {
- return SCD_NOSESSION; /* you can't do anything with a closed session */
+ CFArrayAppendValue(*keysP, key);
+ return;
+}
+
+
+Boolean
+SCDynamicStoreAddWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean isRegex)
+{
+ SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
+ kern_return_t status;
+ CFDataRef utfKey; /* serialized key */
+ xmlData_t myKeyRef;
+ CFIndex myKeyLen;
+ int sc_status;
+
+ if (store == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoStoreSession);
+ return FALSE;
}
- /*
- * add new key after checking if key has already been defined
- */
- if (regexOptions & kSCDRegexKey) {
- if (CFSetContainsValue(sessionPrivate->reKeys, key))
- return SCD_EXISTS; /* sorry, key already exists in notifier list */
- CFSetAddValue(sessionPrivate->reKeys, key); /* add key to this sessions notifier list */
- } else {
- if (CFSetContainsValue(sessionPrivate->keys, key))
- return SCD_EXISTS; /* sorry, key already exists in notifier list */
- CFSetAddValue(sessionPrivate->keys, key); /* add key to this sessions notifier list */
+ if (storePrivate->server == MACH_PORT_NULL) {
+ /* sorry, you must have an open session to play */
+ _SCErrorSet(kSCStatusNoStoreServer);
+ return FALSE;
}
/* serialize the key */
- xmlKey = CFPropertyListCreateXMLData(NULL, key);
- myKeyRef = (xmlData_t)CFDataGetBytePtr(xmlKey);
- myKeyLen = CFDataGetLength(xmlKey);
+ if (!_SCSerializeString(key, &utfKey, (void **)&myKeyRef, &myKeyLen)) {
+ _SCErrorSet(kSCStatusFailed);
+ return FALSE;
+ }
- /* send the key & data to the server */
- status = notifyadd(sessionPrivate->server,
+ retry :
+
+ /* send the key to the server */
+ status = notifyadd(storePrivate->server,
myKeyRef,
- myKeyLen,
- regexOptions,
- (int *)&scd_status);
+ (mach_msg_type_number_t)myKeyLen,
+ isRegex,
+ (int *)&sc_status);
+
+ if (__SCDynamicStoreCheckRetryAndHandleError(store,
+ status,
+ &sc_status,
+ "SCDynamicStoreAddWatchedKey notifyadd()")) {
+ goto retry;
+ }
/* clean up */
- CFRelease(xmlKey);
-
- if (status != KERN_SUCCESS) {
- if (status != MACH_SEND_INVALID_DEST)
- SCDLog(LOG_DEBUG, CFSTR("notifyadd(): %s"), mach_error_string(status));
- (void) mach_port_destroy(mach_task_self(), sessionPrivate->server);
- sessionPrivate->server = MACH_PORT_NULL;
- return SCD_NOSERVER;
+ CFRelease(utfKey);
+
+ if (sc_status != kSCStatusOK) {
+ _SCErrorSet(sc_status);
+ return FALSE;
}
- return scd_status;
+ if (isRegex) {
+ addKey(&storePrivate->patterns, key);
+ } else {
+ addKey(&storePrivate->keys, key);
+ }
+ return TRUE;
}