configd-53.1.tar.gz
[apple/configd.git] / configd.tproj / _configlist.c
index 85286c3add660950d12d31572aed9243a59625ba..da7a970ac6a9b82b00f373b0a3e89998ae8330e8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  *
  * @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"
 
-SCDStatus
-_SCDList(SCDSessionRef session, CFStringRef key, int regexOptions, CFArrayRef *subKeys)
+int
+__SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef key, Boolean isRegex, CFArrayRef *subKeys)
 {
-       SCDSessionPrivateRef    sessionPrivate = (SCDSessionPrivateRef)session;
-       CFIndex                 cacheCnt;
-       void                    **cacheKeys;
-       void                    **cacheValues;
-       CFMutableArrayRef       keyArray;
-       int                     i;
-       CFStringRef             cacheStr;
-       CFDictionaryRef         cacheValue;
-       int                     regexStrLen;
-       char                    *regexStr = NULL;
-       regex_t                 preg;
-       int                     reError;
-       char                    reErrBuf[256];
-       int                     reErrStrLen;
-
-       SCDLog(LOG_DEBUG, CFSTR("_SCDList:"));
-       SCDLog(LOG_DEBUG, CFSTR("  key          = %@"), key);
-       SCDLog(LOG_DEBUG, CFSTR("  regexOptions = %0o"), regexOptions);
-
-       if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) {
-               return SCD_NOSESSION;
+       SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
+       CFIndex                         storeCnt;
+       const void                      **storeKeys;
+       const void                      **storeValues;
+       CFMutableArrayRef               keyArray;
+       int                             i;
+       CFStringRef                     storeStr;
+       CFDictionaryRef                 storeValue;
+       int                             regexBufLen;
+       char                            *regexBuf = NULL;
+       regex_t                         preg;
+       int                             reError;
+       char                            reErrBuf[256];
+       int                             reErrStrLen;
+
+       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreCopyKeyList:"));
+       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  key     = %@"), key);
+       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  isRegex = %s"), isRegex ? "TRUE" : "FALSE");
+
+       if (!store || (storePrivate->server == MACH_PORT_NULL)) {
+               return kSCStatusNoStoreSession; /* you must have an open session to play */
        }
 
-       cacheCnt = CFDictionaryGetCount(cacheData);
-       keyArray = CFArrayCreateMutable(NULL, cacheCnt, &kCFTypeArrayCallBacks);
+       storeCnt = CFDictionaryGetCount(storeData);
+       keyArray = CFArrayCreateMutable(NULL, storeCnt, &kCFTypeArrayCallBacks);
+
+       if (isRegex) {
+               UniChar                 ch_s    = 0;
+               UniChar                 ch_e    = 0;
+               Boolean                 ok;
+               CFIndex                 regexLen;
+               CFMutableStringRef      regexStr;
+
+               regexStr = CFStringCreateMutableCopy(NULL, 0, key);
+               regexLen = CFStringGetLength(regexStr);
+               if (regexLen > 0) {
+                       ch_s = CFStringGetCharacterAtIndex(regexStr, 0);
+                       ch_e = CFStringGetCharacterAtIndex(regexStr, regexLen - 1);
+               }
+               if ((regexLen == 0) || ((ch_s != (UniChar)'^') && (ch_e != (UniChar)'$'))) {
+                       /* if regex pattern is not already bounded */
+                       CFStringInsert(regexStr, 0, CFSTR("^"));
+                       CFStringAppend(regexStr,    CFSTR("$"));
+               }
 
-       if (regexOptions & kSCDRegexKey) {
                /*
                 * compile the provided regular expression using the
-                * provided regexOptions (passing only those flags
-                * which would make sense).
+                * provided isRegex.
                 */
-               regexStrLen = CFStringGetLength(key) + 1;
-               regexStr    = CFAllocatorAllocate(NULL, regexStrLen, 0);
-               if (!CFStringGetCString(key,
-                                       regexStr,
-                                       regexStrLen,
-                                       kCFStringEncodingMacRoman)) {
-                       SCDLog(LOG_DEBUG, CFSTR("CFStringGetCString() key: could not convert to regex string"));
-                       CFAllocatorDeallocate(NULL, regexStr);
-                       return SCD_FAILED;
+               regexBufLen = CFStringGetLength(regexStr) + 1;
+               regexBuf    = CFAllocatorAllocate(NULL, regexBufLen, 0);
+               ok = CFStringGetCString(regexStr, regexBuf, regexBufLen, kCFStringEncodingMacRoman);
+               CFRelease(regexStr);
+               if (!ok) {
+                       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("CFStringGetCString() key: could not convert to regex string"));
+                       CFAllocatorDeallocate(NULL, regexBuf);
+                       return kSCStatusFailed;
                }
 
-               reError = regcomp(&preg, regexStr, REG_EXTENDED);
+               reError = regcomp(&preg, regexBuf, REG_EXTENDED);
                if (reError != 0) {
                        reErrStrLen = regerror(reError, &preg, reErrBuf, sizeof(reErrBuf));
-                       cacheStr = CFStringCreateWithCString(NULL, reErrBuf, kCFStringEncodingMacRoman);
-                       CFArrayAppendValue(keyArray, cacheStr);
-                       CFRelease(cacheStr);
+                       storeStr = CFStringCreateWithCString(NULL, reErrBuf, kCFStringEncodingMacRoman);
+                       CFArrayAppendValue(keyArray, storeStr);
+                       CFRelease(storeStr);
                        *subKeys = CFArrayCreateCopy(NULL, keyArray);
                        CFRelease(keyArray);
-                       CFAllocatorDeallocate(NULL, regexStr);
-                       return SCD_FAILED;
+                       CFAllocatorDeallocate(NULL, regexBuf);
+                       return kSCStatusFailed;
                }
        }
 
-       cacheKeys   = CFAllocatorAllocate(NULL, cacheCnt * sizeof(CFStringRef), 0);
-       cacheValues = CFAllocatorAllocate(NULL, cacheCnt * sizeof(CFStringRef), 0);
-       CFDictionaryGetKeysAndValues(cacheData, cacheKeys, cacheValues);
-       for (i=0; i<cacheCnt; i++) {
-               cacheStr   = (CFStringRef)cacheKeys[i];
-               cacheValue = (CFDictionaryRef)cacheValues[i];
-               if (regexOptions & kSCDRegexKey) {
-                       /*
-                        * only return those keys which match the regular
-                        * expression specified in the provided key.
-                        */
-
-                       int     cacheKeyLen = CFStringGetLength(cacheStr) + 1;
-                       char    *cacheKey   = CFAllocatorAllocate(NULL, cacheKeyLen, 0);
-
-                       if (!CFStringGetCString(cacheStr,
-                                               cacheKey,
-                                               cacheKeyLen,
-                                               kCFStringEncodingMacRoman)) {
-                               SCDLog(LOG_DEBUG, CFSTR("CFStringGetCString: could not convert cache key to C string"));
-                               CFAllocatorDeallocate(NULL, cacheKey);
-                               continue;
-                       }
-
-                       reError = regexec(&preg,
-                                         cacheKey,
-                                         0,
-                                         NULL,
-                                         0);
-                       switch (reError) {
-                               case 0 :
-                                       /* we've got a match */
-                                       if (CFDictionaryContainsKey(cacheValue, kSCDData))
-                                               CFArrayAppendValue(keyArray, cacheStr);
-                                       break;
-                               case REG_NOMATCH :
-                                       /* no match */
-                                       break;
-                               default :
-                                       reErrStrLen = regerror(reError,
-                                                              &preg,
-                                                              reErrBuf,
-                                                              sizeof(reErrBuf));
-                                       SCDLog(LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf);
-                                       break;
-                       }
-                       CFAllocatorDeallocate(NULL, cacheKey);
-               } else {
-                       /*
-                        * only return those keys which are prefixed by the
-                        * provided key string and have data.
-                        */
-                       if (((CFStringGetLength(key) == 0) || CFStringHasPrefix(cacheStr, key)) &&
-                           CFDictionaryContainsKey(cacheValue, kSCDData)) {
-                               CFArrayAppendValue(keyArray, cacheStr);
+       if (storeCnt > 0) {
+               storeKeys   = CFAllocatorAllocate(NULL, storeCnt * sizeof(CFStringRef), 0);
+               storeValues = CFAllocatorAllocate(NULL, storeCnt * sizeof(CFStringRef), 0);
+               CFDictionaryGetKeysAndValues(storeData, storeKeys, storeValues);
+               for (i=0; i<storeCnt; i++) {
+                       storeStr   = (CFStringRef)storeKeys[i];
+                       storeValue = (CFDictionaryRef)storeValues[i];
+                       if (isRegex) {
+                               /*
+                                * only return those keys which match the regular
+                                * expression specified in the provided key.
+                                */
+
+                               int     storeKeyLen = CFStringGetLength(storeStr) + 1;
+                               char    *storeKey   = CFAllocatorAllocate(NULL, storeKeyLen, 0);
+
+                               if (!CFStringGetCString(storeStr,
+                                                       storeKey,
+                                                       storeKeyLen,
+                                                       kCFStringEncodingMacRoman)) {
+                                       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("CFStringGetCString: could not convert store key to C string"));
+                                       CFAllocatorDeallocate(NULL, storeKey);
+                                       continue;
+                               }
+
+                               reError = regexec(&preg,
+                                                 storeKey,
+                                                 0,
+                                                 NULL,
+                                                 0);
+                               switch (reError) {
+                                       case 0 :
+                                               /* we've got a match */
+                                               if (CFDictionaryContainsKey(storeValue, kSCDData))
+                                                       CFArrayAppendValue(keyArray, storeStr);
+                                               break;
+                                       case REG_NOMATCH :
+                                               /* no match */
+                                               break;
+                                       default :
+                                               reErrStrLen = regerror(reError,
+                                                                      &preg,
+                                                                      reErrBuf,
+                                                                      sizeof(reErrBuf));
+                                               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf);
+                                               break;
+                               }
+                               CFAllocatorDeallocate(NULL, storeKey);
+                       } else {
+                               /*
+                                * only return those keys which are prefixed by the
+                                * provided key string and have data.
+                                */
+                               if (((CFStringGetLength(key) == 0) || CFStringHasPrefix(storeStr, key)) &&
+                                   CFDictionaryContainsKey(storeValue, kSCDData)) {
+                                       CFArrayAppendValue(keyArray, storeStr);
+                               }
                        }
                }
+               CFAllocatorDeallocate(NULL, storeKeys);
+               CFAllocatorDeallocate(NULL, storeValues);
        }
-       CFAllocatorDeallocate(NULL, cacheKeys);
-       CFAllocatorDeallocate(NULL, cacheValues);
 
-       if (regexOptions & kSCDRegexKey) {
+       if (isRegex) {
                regfree(&preg);
+               CFAllocatorDeallocate(NULL, regexBuf);
        }
 
        *subKeys = keyArray;
 
-       if (regexOptions & kSCDRegexKey) {
-               CFAllocatorDeallocate(NULL, regexStr);
-       }
-
-       return SCD_OK;
+       return kSCStatusOK;
 }
 
 
@@ -161,67 +186,48 @@ kern_return_t
 _configlist(mach_port_t                        server,
            xmlData_t                   keyRef,         /* raw XML bytes */
            mach_msg_type_number_t      keyLen,
-           int                         regexOptions,
+           int                         isRegex,
            xmlDataOut_t                *listRef,       /* raw XML bytes */
            mach_msg_type_number_t      *listLen,
-           int                         *scd_status
+           int                         *sc_status
 )
 {
-       kern_return_t           status;
-       serverSessionRef        mySession = getSession(server);
-       CFDataRef               xmlKey;         /* key  (XML serialized) */
        CFStringRef             key;            /* key  (un-serialized) */
+       serverSessionRef        mySession = getSession(server);
+       Boolean                 ok;
        CFArrayRef              subKeys;        /* array of CFStringRef's */
-       CFDataRef               xmlList;        /* list (XML serialized) */
-       CFStringRef             xmlError;
 
-       SCDLog(LOG_DEBUG, CFSTR("List keys in configuration database."));
-       SCDLog(LOG_DEBUG, CFSTR("  server = %d"), server);
+       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("List keys in configuration database."));
+       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  server = %d"), server);
+
+       *listRef = NULL;
+       *listLen = 0;
 
        /* 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 (!_SCUnserialize((CFPropertyListRef *)&key, (void *)keyRef, keyLen)) {
+               *sc_status = kSCStatusFailed;
+               return KERN_SUCCESS;
        }
-       key = CFPropertyListCreateFromXMLData(NULL,
-                                             xmlKey,
-                                             kCFPropertyListImmutable,
-                                             &xmlError);
-       CFRelease(xmlKey);
-       if (xmlError) {
-               SCDLog(LOG_DEBUG, CFSTR("CFPropertyListCreateFromXMLData() key: %s"), xmlError);
-               *scd_status = SCD_FAILED;
+
+       if (!isA_CFString(key)) {
+               CFRelease(key);
+               *sc_status = kSCStatusInvalidArgument;
                return KERN_SUCCESS;
        }
 
-       *scd_status = _SCDList(mySession->session, key, regexOptions, &subKeys);
+       *sc_status = __SCDynamicStoreCopyKeyList(mySession->store, key, isRegex, &subKeys);
        CFRelease(key);
-       if (*scd_status != SCD_OK) {
-               *listRef = NULL;
-               *listLen = 0;
+       if (*sc_status != kSCStatusOK) {
                return KERN_SUCCESS;
        }
 
-       /*
-        * serialize the array, copy it into an allocated buffer which will be
-        * released when it is returned as part of a Mach message.
-        */
-       xmlList = CFPropertyListCreateXMLData(NULL, subKeys);
+       /* serialize the list of keys */
+       ok = _SCSerialize(subKeys, NULL, (void **)listRef, (CFIndex *)listLen);
        CFRelease(subKeys);
-       *listLen = CFDataGetLength(xmlList);
-       status = vm_allocate(mach_task_self(), (void *)listRef, *listLen, TRUE);
-       if (status != KERN_SUCCESS) {
-               SCDLog(LOG_DEBUG, CFSTR("vm_allocate(): %s"), mach_error_string(status));
-               *scd_status = SCD_FAILED;
-               CFRelease(xmlList);
-               *listRef = NULL;
-               *listLen = 0;
+       if (!ok) {
+               *sc_status = kSCStatusFailed;
                return KERN_SUCCESS;
        }
-       bcopy((char *)CFDataGetBytePtr(xmlList), *listRef, *listLen);
-       CFRelease(xmlList);
 
        return KERN_SUCCESS;
 }