X-Git-Url: https://git.saurik.com/apple/configd.git/blobdiff_plain/009ee3c6fe2929a4c90ae5c9eb1925573e17956b..bda8ce6bde503c8aa95a6f09eaff112229c3686a:/scutil.tproj/cache.c diff --git a/scutil.tproj/cache.c b/scutil.tproj/cache.c index 15d1d67..b8016e7 100644 --- a/scutil.tproj/cache.c +++ b/scutil.tproj/cache.c @@ -1,10 +1,8 @@ /* - * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2005, 2011 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * - * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. - * * 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 @@ -39,6 +37,226 @@ #include "cache.h" +#pragma mark - +#pragma mark SCDynamicStore "cache" + + +static Boolean use_cache = FALSE; + +static CFMutableDictionaryRef cached_keys = NULL; +static CFMutableDictionaryRef cached_set = NULL; +static CFMutableArrayRef cached_removals = NULL; +static CFMutableArrayRef cached_notifys = NULL; + + +static void +cache_open(void) +{ + if (use_cache) { + // if we are already using the cache + cache_close(); + } + + cached_keys = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + cached_set = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + cached_removals = CFArrayCreateMutable(NULL, + 0, + &kCFTypeArrayCallBacks); + cached_notifys = CFArrayCreateMutable(NULL, + 0, + &kCFTypeArrayCallBacks); + + use_cache = TRUE; + return; +} + + +static CFPropertyListRef +cache_SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key) +{ + CFPropertyListRef value; + + value = CFDictionaryGetValue(cached_set, key); + if (value) { + // if we have "set" a new value + return (CFRetain(value)); + } + + if (CFArrayContainsValue(cached_removals, + CFRangeMake(0, CFArrayGetCount(cached_removals)), + key)) { + // if we have "removed" the key + _SCErrorSet(kSCStatusNoKey); + return NULL; + } + + value = CFDictionaryGetValue(cached_keys, key); + if (value) { + // if we have a cached value + return (CFRetain(value)); + } + + value = SCDynamicStoreCopyValue(store, key); + if (value) { + CFDictionarySetValue(cached_keys, key, value); + } + + return value; +} + + +static void +cache_SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value) +{ + CFIndex i; + + i = CFArrayGetFirstIndexOfValue(cached_removals, + CFRangeMake(0, CFArrayGetCount(cached_removals)), + key); + if (i != kCFNotFound) { + // if previously "removed" + CFArrayRemoveValueAtIndex(cached_removals, i); + } + + CFDictionarySetValue(cached_set, key, value); + + return; +} + +static void +cache_SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key) +{ + CFDictionaryRemoveValue(cached_set, key); + + if (!CFArrayContainsValue(cached_removals, + CFRangeMake(0, CFArrayGetCount(cached_removals)), + key)) { + CFArrayAppendValue(cached_removals, key); + } + + return; +} + + +static void +cache_SCDynamicStoreNotifyValue(SCDynamicStoreRef store, CFStringRef key) +{ + if (!CFArrayContainsValue(cached_notifys, + CFRangeMake(0, CFArrayGetCount(cached_notifys)), + key)) { + CFArrayAppendValue(cached_notifys, key); + } + + return; +} + + +static void +cache_write(SCDynamicStoreRef store) +{ + if ((CFDictionaryGetCount(cached_set) > 0) || + (CFArrayGetCount(cached_removals) > 0) || + (CFArrayGetCount(cached_notifys) > 0)) { + if (!SCDynamicStoreSetMultiple(store, + cached_set, + cached_removals, + cached_notifys)) { + SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); + } + } + + return; +} + + +__private_extern__ +void +cache_close(void) +{ + if (!use_cache) { + return; + } + + CFRelease(cached_keys); + CFRelease(cached_set); + CFRelease(cached_removals); + CFRelease(cached_notifys); + + use_cache = FALSE; + return; +} + + +#pragma mark - +#pragma mark SCDynamicStore operations + + +__private_extern__ +void +do_block(int argc, char **argv) +{ + Boolean enable = FALSE; + + if (argc >= 1) { + if ((strcasecmp(argv[0], "begin") == 0) || + (strcasecmp(argv[0], "start") == 0) || + (strcasecmp(argv[0], "on" ) == 0) || + (strcasecmp(argv[0], "1" ) == 0)) { + enable = TRUE; + } else if ((strcasecmp(argv[0], "end" ) == 0) || + (strcasecmp(argv[0], "stop" ) == 0) || + (strcasecmp(argv[0], "off" ) == 0) || + (strcasecmp(argv[0], "0" ) == 0)) { + enable = FALSE; + } else { + SCPrint(TRUE, stdout, CFSTR("invalid value\n")); + return; + } + } else { + enable = !use_cache; // toggle + } + + if (enable) { + // begin block of SCDynamicStore operations + if (use_cache) { + SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(kSCStatusLocked)); + return; + } + + SCPrint(TRUE, stdout, CFSTR("Begin block of SCDynamicStore operations\n")); + + cache_open(); + } else { + CFIndex n; + + // end block of SCDynamicStore operations + if (!use_cache) { + SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(kSCStatusNeedLock)); + return; + } + + n = CFDictionaryGetCount(cached_keys) + + CFArrayGetCount(cached_removals) + + CFArrayGetCount(cached_notifys); + SCPrint(TRUE, stdout, + CFSTR("End block of SCDynamicStore operations%s\n"), + (n > 0) ? ", posting changes" : ""); + if (n > 0) { + cache_write(store); + } + cache_close(); + } + + return; +} + + static CFComparisonResult sort_keys(const void *p1, const void *p2, void *context) { CFStringRef key1 = (CFStringRef)p1; @@ -47,6 +265,10 @@ sort_keys(const void *p1, const void *p2, void *context) { } +#define N_QUICK 64 + + +__private_extern__ void do_list(int argc, char **argv) { @@ -58,17 +280,44 @@ do_list(int argc, char **argv) pattern = CFStringCreateWithCString(NULL, (argc >= 1) ? argv[0] : ".*", - kCFStringEncodingMacRoman); + kCFStringEncodingUTF8); list = SCDynamicStoreCopyKeyList(store, pattern); CFRelease(pattern); - if (!list) { + if (list == NULL) { if (SCError() != kSCStatusOK) { SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); + return; } else { + if (!use_cache) { SCPrint(TRUE, stdout, CFSTR(" no keys.\n")); + return; + } else { + CFIndex n; + + n = CFDictionaryGetCount(cached_set); + if (n > 0) { + const void * cachedKeys_q[N_QUICK]; + const void ** cachedKeys = cachedKeys_q; + + if (n > (CFIndex)(sizeof(cachedKeys_q) / sizeof(CFStringRef))) { + cachedKeys = CFAllocatorAllocate(NULL, n * sizeof(CFStringRef), 0); + } + CFDictionaryGetKeysAndValues(cached_set, cachedKeys, NULL); + list = CFArrayCreate(NULL, cachedKeys, n, &kCFTypeArrayCallBacks); + if (cachedKeys != cachedKeys_q) { + CFAllocatorDeallocate(NULL, cachedKeys); + } + } else { + SCPrint(TRUE, stdout, CFSTR(" no keys.\n")); + return; + } + } } - return; + } else if (use_cache && + ((CFDictionaryGetCount(cached_set) > 0) || (CFArrayGetCount(cached_removals) > 0))) { + SCPrint(TRUE, stdout, + CFSTR(" Note: SCDynamicStore transactions in progress, key list (below) may be out of date.\n\n")); } listCnt = CFArrayGetCount(list); @@ -96,20 +345,50 @@ do_list(int argc, char **argv) } +__private_extern__ void do_add(int argc, char **argv) { CFStringRef key; - key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman); + key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); if (argc < 2) { - if (!SCDynamicStoreAddValue(store, key, value)) { - SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); + if (!use_cache) { + if (!SCDynamicStoreAddValue(store, key, value)) { + SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); + } + } else { + CFTypeRef val; + + val = cache_SCDynamicStoreCopyValue(store, key); + if (val != NULL) { + CFRelease(val); + SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(kSCStatusKeyExists)); + } else { + cache_SCDynamicStoreSetValue(store, key, value); + } } } else { - if (!SCDynamicStoreAddTemporaryValue(store, key, value)) { - SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); + if (!use_cache) { + if (!SCDynamicStoreAddTemporaryValue(store, key, value)) { + SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); + } + } else { + CFTypeRef val; + + val = cache_SCDynamicStoreCopyValue(store, key); + if (val != NULL) { + CFRelease(val); + SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(kSCStatusKeyExists)); + } else { + if (!SCDynamicStoreAddTemporaryValue(store, key, value)) { + SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); + } else { + // and save the temp value in the cache too! + cache_SCDynamicStoreSetValue(store, key, value); + } + } } } @@ -118,16 +397,21 @@ do_add(int argc, char **argv) } +__private_extern__ void do_get(int argc, char **argv) { CFStringRef key; CFPropertyListRef newValue; - key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman); - newValue = SCDynamicStoreCopyValue(store, key); + key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); + if (!use_cache) { + newValue = SCDynamicStoreCopyValue(store, key); + } else { + newValue = cache_SCDynamicStoreCopyValue(store, key); + } CFRelease(key); - if (!newValue) { + if (newValue == NULL) { SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); return; } @@ -141,40 +425,85 @@ do_get(int argc, char **argv) } +__private_extern__ void do_set(int argc, char **argv) { CFStringRef key; - key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman); - if (!SCDynamicStoreSetValue(store, key, value)) { - SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); + key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); + if (!use_cache) { + if (!SCDynamicStoreSetValue(store, key, value)) { + SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); + } + } else { + cache_SCDynamicStoreSetValue(store, key, value); } CFRelease(key); return; } +__private_extern__ void do_show(int argc, char **argv) { CFStringRef key; CFPropertyListRef newValue; - key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman); + key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); if (argc == 1) { - newValue = SCDynamicStoreCopyValue(store, key); + if (!use_cache) { + newValue = SCDynamicStoreCopyValue(store, key); + } else { + newValue = cache_SCDynamicStoreCopyValue(store, key); + } } else { CFArrayRef patterns; patterns = CFArrayCreate(NULL, (const void **)&key, 1, &kCFTypeArrayCallBacks); - newValue = SCDynamicStoreCopyMultiple(store, NULL, patterns); + if (!use_cache) { + newValue = SCDynamicStoreCopyMultiple(store, NULL, patterns); + } else { + CFArrayRef keys; + CFMutableDictionaryRef newDict; + + newDict = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + keys = SCDynamicStoreCopyKeyList(store, key); + if (keys != NULL) { + CFIndex i; + CFIndex n; + + n = CFArrayGetCount(keys); + for (i = 0; i < n; i++) { + CFStringRef storeKey; + CFTypeRef storeVal; + + storeKey = CFArrayGetValueAtIndex(keys, i); + storeVal = cache_SCDynamicStoreCopyValue(store, storeKey); + if (storeVal != NULL) { + CFDictionarySetValue(newDict, storeKey, storeVal); + CFRelease(storeVal); + } + } + CFRelease(keys); + } + + if ((CFDictionaryGetCount(cached_set) > 0) || (CFArrayGetCount(cached_removals) > 0)) { + SCPrint(TRUE, stdout, CFSTR(" Note: SCDynamicStore locked, keys included (below) may be out of date.\n\n")); + } + + newValue = newDict; + } CFRelease(patterns); } CFRelease(key); - if (!newValue) { + if (newValue == NULL) { SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); return; } @@ -185,42 +514,38 @@ do_show(int argc, char **argv) } +__private_extern__ void do_remove(int argc, char **argv) { CFStringRef key; - key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman); - if (!SCDynamicStoreRemoveValue(store, key)) { - SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); + key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); + if (!use_cache) { + if (!SCDynamicStoreRemoveValue(store, key)) { + SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); + } + } else { + cache_SCDynamicStoreRemoveValue(store, key); } CFRelease(key); return; } +__private_extern__ void do_notify(int argc, char **argv) { CFStringRef key; - key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman); - if (!SCDynamicStoreNotifyValue(store, key)) { - SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); - } - CFRelease(key); - return; -} - - -void -do_touch(int argc, char **argv) -{ - CFStringRef key; - - key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman); - if (!SCDynamicStoreTouchValue(store, key)) { - SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); + key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); + if (!use_cache) { + if (!SCDynamicStoreNotifyValue(store, key)) { + SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); + } + } else { + cache_SCDynamicStoreNotifyValue(store, key); } CFRelease(key); return;