X-Git-Url: https://git.saurik.com/apple/configd.git/blobdiff_plain/a40a14f8bcc57d8bed0203ddee43e8d64db39796..refs/heads/master:/configd.tproj/pattern.c diff --git a/configd.tproj/pattern.c b/configd.tproj/pattern.c index 207491b..9090757 100644 --- a/configd.tproj/pattern.c +++ b/configd.tproj/pattern.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2003, 2004, 2006-2008 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, @@ -17,7 +17,7 @@ * 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@ */ @@ -47,7 +47,7 @@ typedef struct { CFMutableArrayRef pInfo; - regex_t *preg; + CFDataRef pRegex; } addContext, *addContextRef; @@ -67,39 +67,33 @@ my_CFDictionaryApplyFunction(CFDictionaryRef theDict, } -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 */ @@ -108,7 +102,7 @@ identifyKeyForPattern(const void *key, void *val, void *context) 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; } } @@ -116,20 +110,47 @@ identifyKeyForPattern(const void *key, void *val, void *context) 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; CFIndex len = 0; + CFIndex len_c; Boolean ok; char str_q[256]; char * str = str_q; + if (CFStringGetLength(pattern) == 0) { + SC_log(LOG_NOTICE, "empty regex pattern"); + } + if (!CFStringHasPrefix(pattern, CFSTR("^"))) { insert = TRUE; } @@ -149,14 +170,18 @@ patternCompile(CFStringRef pattern, regex_t *preg, CFStringRef *error) append ? "$" : ""); } - (void)CFStringGetBytes(pattern, - CFRangeMake(0, CFStringGetLength(pattern)), - kCFStringEncodingASCII, - 0, - FALSE, - NULL, - 0, - &len); + len_c = CFStringGetBytes(pattern, + CFRangeMake(0, CFStringGetLength(pattern)), + kCFStringEncodingASCII, + 0, + FALSE, + NULL, + 0, + &len); + if (len_c <= 0) { + SC_log(LOG_NOTICE, "could not get buffer length for \"%@\"", pattern); + len = sizeof(str_q) - 1; + } if (++len > (CFIndex)sizeof(str_q)) { str = CFAllocatorAllocate(NULL, len, 0); } @@ -165,8 +190,12 @@ patternCompile(CFStringRef pattern, regex_t *preg, CFStringRef *error) 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]; @@ -174,14 +203,14 @@ patternCompile(CFStringRef pattern, regex_t *preg, CFStringRef *error) (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 */ } @@ -190,17 +219,30 @@ patternCompile(CFStringRef pattern, regex_t *preg, CFStringRef *error) } -static CFMutableArrayRef +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; } -static CFMutableArrayRef +static CF_RETURNS_RETAINED CFMutableArrayRef patternNew(CFStringRef pattern) { addContext context; @@ -215,7 +257,7 @@ patternNew(CFStringRef pattern) /* compile the regular expression from the pattern string. */ pRegex = CFDataCreateMutable(NULL, sizeof(regex_t)); CFDataSetLength(pRegex, sizeof(regex_t)); - if (!patternCompile(pattern, (regex_t *)CFDataGetBytePtr(pRegex), &err)) { + if (!patternCompile(pattern, pRegex, &err)) { CFRelease(err); CFRelease(pRegex); CFRelease(pInfo); @@ -231,8 +273,8 @@ patternNew(CFStringRef pattern) CFRelease(pSessions); /* identify/add all existing keys that match the specified pattern */ - context.pInfo = pInfo; - context.preg = (regex_t *)CFDataGetBytePtr(pRegex); + context.pInfo = pInfo; + context.pRegex = pRegex; my_CFDictionaryApplyFunction(storeData, (CFDictionaryApplierFunction)identifyKeyForPattern, &context); @@ -266,7 +308,7 @@ patternCopyMatches(CFStringRef pattern) CFDataRef pRegex; pRegex = CFArrayGetValueAtIndex(pInfo, 0); - regfree((regex_t *)CFDataGetBytePtr(pRegex)); + patternRelease(pRegex); } CFArrayReplaceValues(pInfo, CFRangeMake(0, 2), NULL, 0); @@ -277,6 +319,52 @@ patternCopyMatches(CFStringRef pattern) } +__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) @@ -332,6 +420,7 @@ patternRemoveSession(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); @@ -359,7 +448,7 @@ patternRemoveSession(CFStringRef pattern, CFNumberRef sessionNum) /* if no other sessions are watching this pattern */ pRegex = CFArrayGetValueAtIndex(pInfo, 0); - regfree((regex_t *)CFDataGetBytePtr(pRegex)); + patternRelease(pRegex); CFDictionaryRemoveValue(patternData, pattern); } @@ -386,12 +475,13 @@ addKeyForPattern(const void *key, void *val, void *context) 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; } /* compare new store key to regular expression pattern */ - preg = (regex_t *)CFDataGetBytePtr(CFArrayGetValueAtIndex(pInfo, 0)); + /* ALIGN: CF aligns to >8 byte boundries */ + preg = (regex_t *)(void *)CFDataGetBytePtr(CFArrayGetValueAtIndex(pInfo, 0)); reError = regexec(preg, str, 0, NULL, 0); switch (reError) { case 0 : { @@ -426,7 +516,7 @@ addKeyForPattern(const void *key, void *val, void *context) 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; } }