#include "configd.h"
#include "session.h"
#include "pattern.h"
#define N_QUICK 64
__private_extern__
int
__SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef key, Boolean isRegex, CFArrayRef *subKeys)
{
CFMutableArrayRef keyArray;
CFIndex storeCnt;
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
CFStringRef storeStr;
CFDictionaryRef storeValue;
SC_trace(_configd_trace, "%s : %5d : %s : %@\n",
"list ",
storePrivate->server,
isRegex ? "pattern" : "key",
key);
if (isRegex) {
*subKeys = patternCopyMatches(key);
return (*subKeys != NULL) ? kSCStatusOK : kSCStatusFailed;
}
storeCnt = CFDictionaryGetCount(storeData);
keyArray = CFArrayCreateMutable(NULL, storeCnt, &kCFTypeArrayCallBacks);
if (storeCnt > 0) {
int i;
const void * storeKeys_q[N_QUICK];
const void ** storeKeys = storeKeys_q;
const void * storeValues_q[N_QUICK];
const void ** storeValues = storeValues_q;
if (storeCnt > (CFIndex)(sizeof(storeKeys_q) / sizeof(CFStringRef))) {
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 (((CFStringGetLength(key) == 0) || CFStringHasPrefix(storeStr, key)) &&
CFDictionaryContainsKey(storeValue, kSCDData)) {
CFArrayAppendValue(keyArray, storeStr);
}
}
if (storeKeys != storeKeys_q) {
CFAllocatorDeallocate(NULL, storeKeys);
CFAllocatorDeallocate(NULL, storeValues);
}
}
*subKeys = CFArrayCreateCopy(NULL, keyArray);
CFRelease(keyArray);
return kSCStatusOK;
}
__private_extern__
kern_return_t
_configlist(mach_port_t server,
xmlData_t keyRef,
mach_msg_type_number_t keyLen,
int isRegex,
xmlDataOut_t *listRef,
mach_msg_type_number_t *listLen,
int *sc_status,
audit_token_t audit_token)
{
CFStringRef key = NULL;
CFIndex len;
serverSessionRef mySession;
Boolean ok;
CFArrayRef subKeys;
*listRef = NULL;
*listLen = 0;
if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
*sc_status = kSCStatusFailed;
goto done;
}
if (!isA_CFString(key)) {
*sc_status = kSCStatusInvalidArgument;
goto done;
}
mySession = getSession(server);
if (mySession == NULL) {
mySession = tempSession(server, CFSTR("SCDynamicStoreCopyKeyList"), audit_token);
if (mySession == NULL) {
*sc_status = kSCStatusNoStoreSession;
goto done;
}
}
*sc_status = __SCDynamicStoreCopyKeyList(mySession->store, key, isRegex != 0, &subKeys);
if (*sc_status != kSCStatusOK) {
goto done;
}
ok = _SCSerialize(subKeys, NULL, (void **)listRef, &len);
*listLen = (mach_msg_type_number_t)len;
CFRelease(subKeys);
if (!ok) {
*sc_status = kSCStatusFailed;
goto done;
}
done :
if (key) CFRelease(key);
return KERN_SUCCESS;
}