/*
- * Copyright (c) 2003, 2004, 2006-2008, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2003, 2004, 2006-2008, 2011, 2012, 2015 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
- *
+ *
* 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,
* 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@
*/
typedef struct {
CFMutableArrayRef pInfo;
- regex_t *preg;
+ CFDataRef pRegex;
} addContext, *addContextRef;
}
-static void
-identifyKeyForPattern(const void *key, void *val, void *context)
+static Boolean
+keyMatchesPattern(CFStringRef key, CFDataRef pRegex)
{
- CFStringRef storeKey = (CFStringRef)key;
- CFDictionaryRef storeValue = (CFDictionaryRef)val;
- CFMutableArrayRef pInfo = ((addContextRef)context)->pInfo;
- regex_t * preg = ((addContextRef)context)->preg;
-
CFIndex len;
+ Boolean match = FALSE;
+ regex_t *preg;
int reError;
char str_q[256];
char * str = str_q;
- if (!CFDictionaryContainsKey(storeValue, kSCDData)) {
- /* if no data (yet) */
- return;
- }
-
/* convert store key to C string */
- len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(storeKey), kCFStringEncodingASCII) + 1;
+ len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(key), kCFStringEncodingASCII) + 1;
if (len > (CFIndex)sizeof(str_q))
str = CFAllocatorAllocate(NULL, len, 0);
- if (_SC_cfstring_to_cstring(storeKey, str, len, kCFStringEncodingASCII) == NULL) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("identifyKeyForPattern(): could not convert store key to C string"));
+ if (_SC_cfstring_to_cstring(key, str, len, kCFStringEncodingASCII) == NULL) {
+ SC_log(LOG_INFO, "could not convert store key to C string");
goto done;
}
- /* compare store key to new notification keys regular expression pattern */
+ /* ALIGN: CF aligns to >8 byte boundries */
+ preg = (regex_t *)(void *)CFDataGetBytePtr(pRegex);
+
+ /* compare key to regular expression pattern */
reError = regexec(preg, str, 0, NULL, 0);
switch (reError) {
case 0 :
- /* we've got a match */
- CFArrayAppendValue(pInfo, storeKey);
+ match = TRUE;
break;
case REG_NOMATCH :
/* no match */
char reErrBuf[256];
(void)regerror(reError, preg, reErrBuf, sizeof(reErrBuf));
- SCLog(TRUE, LOG_DEBUG, CFSTR("identifyKeyForPattern regexec(): %s"), reErrBuf);
+ SC_log(LOG_INFO, "regexec() failed: %s", reErrBuf);
break;
}
}
done :
if (str != str_q) CFAllocatorDeallocate(NULL, str);
+ return match;
+}
+
+
+static void
+identifyKeyForPattern(const void *key, void *val, void *context)
+{
+ CFStringRef storeKey = (CFStringRef)key;
+ CFDictionaryRef storeValue = (CFDictionaryRef)val;
+ CFMutableArrayRef pInfo = ((addContextRef)context)->pInfo;
+ CFDataRef pRegex = ((addContextRef)context)->pRegex;
+
+ if (!CFDictionaryContainsKey(storeValue, kSCDData)) {
+ /* if no data (yet) */
+ return;
+ }
+
+ if (keyMatchesPattern(storeKey, pRegex)) {
+ /* if we've got a match */
+ CFArrayAppendValue(pInfo, storeKey);
+ }
+
return;
}
static Boolean
-patternCompile(CFStringRef pattern, regex_t *preg, CFStringRef *error)
+patternCompile(CFStringRef pattern, CFDataRef pRegex, CFStringRef *error)
{
Boolean append = FALSE;
Boolean insert = FALSE;
char * str = str_q;
if (CFStringGetLength(pattern) == 0) {
- SCLog(TRUE, LOG_ERR, CFSTR("patternCompile(): empty string"));
+ SC_log(LOG_NOTICE, "empty regex pattern");
}
if (!CFStringHasPrefix(pattern, CFSTR("^"))) {
0,
&len);
if (len_c <= 0) {
- SCLog(TRUE, LOG_ERR, CFSTR("patternCompile(): could not get buffer length for \"%@\""), pattern);
+ SC_log(LOG_NOTICE, "could not get buffer length for \"%@\"", pattern);
len = sizeof(str_q) - 1;
}
if (++len > (CFIndex)sizeof(str_q)) {
CFRelease(pattern);
}
if (ok) {
+ regex_t *preg;
int reError;
+ /* ALIGN: CF aligns to >8 byte boundries */
+ preg = (regex_t *)(void *)CFDataGetBytePtr(pRegex);
+
reError = regcomp(preg, str, REG_EXTENDED);
if (reError != 0) {
char reErrBuf[256];
(void)regerror(reError, preg, reErrBuf, sizeof(reErrBuf));
*error = CFStringCreateWithCString(NULL, reErrBuf, kCFStringEncodingASCII);
#ifdef DEBUG
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("patternCompile regcomp(%s) failed: %s"), str, reErrBuf);
+ SC_log(LOG_DEBUG, "regcomp(%s) failed: %s", str, reErrBuf);
#endif /* DEBUG */
ok = FALSE;
}
} else {
*error = CFRetain(CFSTR("could not convert pattern to regex string"));
#ifdef DEBUG
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("%@"), *error);
+ SC_log(LOG_DEBUG, "%@", *error);
#endif /* DEBUG */
}
}
+static void
+patternRelease(CFDataRef pRegex)
+{
+ regex_t *preg;
+
+ /* ALIGN: CF aligns to >8 byte boundries */
+ preg = (regex_t *)(void *)CFDataGetBytePtr(pRegex);
+ regfree(preg);
+
+ return;
+}
+
+
static CF_RETURNS_RETAINED CFMutableArrayRef
patternCopy(CFStringRef pattern)
{
CFArrayRef pInfo;
pInfo = CFDictionaryGetValue(patternData, pattern);
- return pInfo ? CFArrayCreateMutableCopy(NULL, 0, pInfo) : NULL;
+ return (pInfo != NULL) ? CFArrayCreateMutableCopy(NULL, 0, pInfo) : NULL;
}
/* compile the regular expression from the pattern string. */
pRegex = CFDataCreateMutable(NULL, sizeof(regex_t));
CFDataSetLength(pRegex, sizeof(regex_t));
- /* ALIGN: CF aligns to >8 byte boundries */
- if (!patternCompile(pattern, (regex_t *)(void *)CFDataGetBytePtr(pRegex), &err)) {
+ if (!patternCompile(pattern, pRegex, &err)) {
CFRelease(err);
CFRelease(pRegex);
CFRelease(pInfo);
CFRelease(pSessions);
/* identify/add all existing keys that match the specified pattern */
- context.pInfo = pInfo;
- /* ALIGN: CF aligns to >8 byte boundries */
- context.preg = (regex_t *)(void *)CFDataGetBytePtr(pRegex);
+ context.pInfo = pInfo;
+ context.pRegex = pRegex;
my_CFDictionaryApplyFunction(storeData,
(CFDictionaryApplierFunction)identifyKeyForPattern,
&context);
CFDataRef pRegex;
pRegex = CFArrayGetValueAtIndex(pInfo, 0);
- /* ALIGN: CF aligns to >8 byte boundries */
- regfree((regex_t *)(void *)CFDataGetBytePtr(pRegex));
+ patternRelease(pRegex);
}
CFArrayReplaceValues(pInfo, CFRangeMake(0, 2), NULL, 0);
}
+__private_extern__
+Boolean
+patternKeyMatches(CFStringRef pattern, CFStringRef key)
+{
+ Boolean isNew = FALSE;
+ Boolean match = FALSE;
+ CFMutableArrayRef pInfo;
+ CFDataRef pRegex;
+
+ /* find (or create new instance of) this pattern */
+ pInfo = patternCopy(pattern);
+ if (pInfo != NULL) {
+ CFIndex n;
+
+ /* if existing pattern, check if known key */
+ n = CFArrayGetCount(pInfo);
+ match = (n > 2) &&
+ CFArrayContainsValue(pInfo, CFRangeMake(2, n - 2), key);
+ if (match) {
+ goto done;
+ }
+ } else {
+ /* if new pattern */
+ pInfo = patternNew(pattern);
+ if (pInfo == NULL) {
+ return FALSE;
+ }
+
+ isNew = TRUE;
+ }
+
+ pRegex = CFArrayGetValueAtIndex(pInfo, 0);
+ match = keyMatchesPattern(key, pRegex);
+
+ if (isNew) {
+ patternRelease(pRegex);
+ }
+
+ done :
+
+ CFRelease(pInfo);
+
+ return match;
+}
+
+
__private_extern__
Boolean
patternAddSession(CFStringRef pattern, CFNumberRef sessionNum)
/* find instance of this pattern */
pInfo = patternCopy(pattern);
+ assert(pInfo != NULL);
/* remove this session as a watcher from all matching keys */
n = CFArrayGetCount(pInfo);
/* if no other sessions are watching this pattern */
pRegex = CFArrayGetValueAtIndex(pInfo, 0);
- /* ALIGN: CF aligns to >8 byte boundries */
- regfree((regex_t *)(void *)CFDataGetBytePtr(pRegex));
+ patternRelease(pRegex);
CFDictionaryRemoveValue(patternData, pattern);
}
if (len > (CFIndex)sizeof(str_q))
str = CFAllocatorAllocate(NULL, len, 0);
if (_SC_cfstring_to_cstring(storeKey, str, len, kCFStringEncodingASCII) == NULL) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("addKeyForPattern(): could not convert store key to C string"));
+ SC_log(LOG_INFO, "could not convert store key to C string");
goto done;
}
char reErrBuf[256];
(void)regerror(reError, preg, reErrBuf, sizeof(reErrBuf));
- SCLog(TRUE, LOG_DEBUG, CFSTR("addKeyForPattern regexec(): %s"), reErrBuf);
+ SC_log(LOG_INFO, "%s", reErrBuf);
break;
}
}