1/*
2 * Copyright (c) 2000-2004, 2006, 2008, 2010-2012 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
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
34
35#include "configd.h"
36#include "session.h"
37#include "pattern.h"
38
39
40static int
41removeKey(CFMutableArrayRef keys, CFStringRef key)
42{
43	CFIndex	i;
44	CFIndex	n;
45
46	if (keys == NULL) {
47		/* sorry, empty notifier list */
48		return kSCStatusNoKey;
49	}
50
51	n = CFArrayGetCount(keys);
52	i = CFArrayGetFirstIndexOfValue(keys, CFRangeMake(0, n), key);
53	if (i == kCFNotFound) {
54		/* sorry, key does not exist in notifier list */
55		return kSCStatusNoKey;
56	}
57
58	/* remove key from this sessions notifier list */
59	CFArrayRemoveValueAtIndex(keys, i);
60	return kSCStatusOK;
61}
62
63
64__private_extern__
65int
66__SCDynamicStoreRemoveWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean isRegex, Boolean internal)
67{
68	int				sc_status	= kSCStatusOK;
69	CFNumberRef			sessionNum;
70	SCDynamicStorePrivateRef	storePrivate	= (SCDynamicStorePrivateRef)store;
71
72	if (_configd_trace) {
73		SCTrace(TRUE, _configd_trace,
74			CFSTR("%s : %5d : %s : %@\n"),
75			internal ? "*watch-" : "watch- ",
76			storePrivate->server,
77			isRegex  ? "pattern" : "key",
78			key);
79	}
80
81	/*
82	 * remove key from this sessions notifier list after checking that
83	 * it was previously defined.
84	 */
85	if (isRegex) {
86		sc_status = removeKey(storePrivate->patterns, key);
87		if (sc_status != kSCStatusOK) {
88			goto done;
89		}
90
91		/* remove this session as a pattern watcher */
92		sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &storePrivate->server);
93		patternRemoveSession(key, sessionNum);
94		CFRelease(sessionNum);
95	} else {
96		sc_status = removeKey(storePrivate->keys, key);
97		if (sc_status != kSCStatusOK) {
98			goto done;
99		}
100
101		/*
102		 * We are watching a specific key. As such, update the
103		 * store to remove our interest in any changes.
104		 */
105		sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &storePrivate->server);
106		_removeWatcher(sessionNum, key);
107		CFRelease(sessionNum);
108	}
109
110    done :
111
112	return sc_status;
113}
114
115
116__private_extern__
117kern_return_t
118_notifyremove(mach_port_t		server,
119	      xmlData_t			keyRef,		/* raw XML bytes */
120	      mach_msg_type_number_t	keyLen,
121	      int			isRegex,
122	      int			*sc_status
123)
124{
125	CFStringRef		key		= NULL;		/* key  (un-serialized) */
126	serverSessionRef	mySession;
127
128	/* un-serialize the key */
129	if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
130		*sc_status = kSCStatusFailed;
131		goto done;
132	}
133
134	if (!isA_CFString(key)) {
135		*sc_status = kSCStatusInvalidArgument;
136		goto done;
137	}
138
139	mySession = getSession(server);
140	if (mySession == NULL) {
141		*sc_status = kSCStatusNoStoreSession;	/* you must have an open session to play */
142		goto done;
143	}
144
145	*sc_status = __SCDynamicStoreRemoveWatchedKey(mySession->store,
146						      key,
147						      isRegex != 0,
148						      FALSE);
149
150    done :
151
152	if (key)	CFRelease(key);
153	return KERN_SUCCESS;
154}
155
156