#include "configd.h"
#include "session.h"
#include "pattern.h"
__private_extern__
int
__SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef value, Boolean internal)
{
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
int sc_status = kSCStatusOK;
CFDictionaryRef dict;
CFMutableDictionaryRef newDict;
Boolean newEntry = FALSE;
CFStringRef sessionKey;
CFStringRef storeSessionKey;
if (_configd_verbose) {
CFPropertyListRef val;
(void) _SCUnserialize(&val, value, NULL, NULL);
SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreSetValue:"));
SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
SCLog(TRUE, LOG_DEBUG, CFSTR(" value = %@"), val);
CFRelease(val);
}
if (!store || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession;
}
if (_configd_trace) {
SCTrace(TRUE, _configd_trace,
CFSTR("%s : %5d : %@\n"),
internal ? "*set " : "set ",
storePrivate->server,
key);
}
sc_status = __SCDynamicStoreLock(store, TRUE);
if (sc_status != kSCStatusOK) {
return sc_status;
}
dict = CFDictionaryGetValue(storeData, key);
if (dict) {
newDict = CFDictionaryCreateMutableCopy(NULL,
0,
dict);
} else {
newDict = CFDictionaryCreateMutable(NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
newEntry = !CFDictionaryContainsKey(newDict, kSCDData);
CFDictionarySetValue(newDict, kSCDData, value);
sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server);
if (CFDictionaryGetValueIfPresent(newDict, kSCDSession, (void *)&storeSessionKey) &&
!CFEqual(sessionKey, storeSessionKey)) {
CFStringRef removedKey;
CFDictionaryRemoveValue(newDict, kSCDSession);
removedKey = CFStringCreateWithFormat(NULL, 0, CFSTR("%@:%@"), storeSessionKey, key);
CFSetAddValue(removedSessionKeys, removedKey);
CFRelease(removedKey);
}
CFRelease(sessionKey);
CFDictionarySetValue(storeData, key, newDict);
CFRelease(newDict);
if (newEntry) {
if (CFSetContainsValue(deferredRemovals, key)) {
CFSetRemoveValue(deferredRemovals, key);
} else {
patternAddKey(key);
}
}
CFSetAddValue(changedKeys, key);
__SCDynamicStoreUnlock(store, TRUE);
return sc_status;
}
__private_extern__
kern_return_t
_configset(mach_port_t server,
xmlData_t keyRef,
mach_msg_type_number_t keyLen,
xmlData_t dataRef,
mach_msg_type_number_t dataLen,
int oldInstance,
int *newInstance,
int *sc_status
)
{
serverSessionRef mySession = getSession(server);
CFStringRef key;
CFDataRef data;
if (_configd_verbose) {
SCLog(TRUE, LOG_DEBUG, CFSTR("Set key to configuration database."));
SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
}
*sc_status = kSCStatusOK;
if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
*sc_status = kSCStatusFailed;
} else if (!isA_CFString(key)) {
*sc_status = kSCStatusInvalidArgument;
}
if (!_SCUnserializeData(&data, (void *)dataRef, dataLen)) {
*sc_status = kSCStatusFailed;
}
if (!mySession) {
*sc_status = kSCStatusNoStoreSession;
}
if (*sc_status != kSCStatusOK) {
if (key) CFRelease(key);
if (data) CFRelease(data);
return KERN_SUCCESS;
}
*sc_status = __SCDynamicStoreSetValue(mySession->store, key, data, FALSE);
*newInstance = 0;
CFRelease(key);
CFRelease(data);
return KERN_SUCCESS;
}
static void
setSpecificKey(const void *key, const void *value, void *context)
{
CFStringRef k = (CFStringRef)key;
CFDataRef v = (CFDataRef)value;
SCDynamicStoreRef store = (SCDynamicStoreRef)context;
if (!isA_CFString(k)) {
return;
}
if (!isA_CFData(v)) {
return;
}
(void) __SCDynamicStoreSetValue(store, k, v, TRUE);
return;
}
static void
removeSpecificKey(const void *value, void *context)
{
CFStringRef k = (CFStringRef)value;
SCDynamicStoreRef store = (SCDynamicStoreRef)context;
if (!isA_CFString(k)) {
return;
}
(void) __SCDynamicStoreRemoveValue(store, k, TRUE);
return;
}
static void
notifySpecificKey(const void *value, void *context)
{
CFStringRef k = (CFStringRef)value;
SCDynamicStoreRef store = (SCDynamicStoreRef)context;
if (!isA_CFString(k)) {
return;
}
(void) __SCDynamicStoreNotifyValue(store, k, TRUE);
return;
}
__private_extern__
int
__SCDynamicStoreSetMultiple(SCDynamicStoreRef store, CFDictionaryRef keysToSet, CFArrayRef keysToRemove, CFArrayRef keysToNotify)
{
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
int sc_status = kSCStatusOK;
if (_configd_verbose) {
CFDictionaryRef expDict;
expDict = keysToSet ? _SCUnserializeMultiple(keysToSet) : NULL;
SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreSetMultiple:"));
SCLog(TRUE, LOG_DEBUG, CFSTR(" keysToSet = %@"), expDict);
SCLog(TRUE, LOG_DEBUG, CFSTR(" keysToRemove = %@"), keysToRemove);
SCLog(TRUE, LOG_DEBUG, CFSTR(" keysToNotify = %@"), keysToNotify);
if (expDict) CFRelease(expDict);
}
if (!store || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession;
}
if (_configd_trace) {
SCTrace(TRUE, _configd_trace,
CFSTR("set m : %5d : %d set, %d remove, %d notify\n"),
storePrivate->server,
keysToSet ? CFDictionaryGetCount(keysToSet) : 0,
keysToRemove ? CFArrayGetCount (keysToRemove) : 0,
keysToNotify ? CFArrayGetCount (keysToNotify) : 0);
}
sc_status = __SCDynamicStoreLock(store, TRUE);
if (sc_status != kSCStatusOK) {
return sc_status;
}
if (keysToSet) {
CFDictionaryApplyFunction(keysToSet,
setSpecificKey,
(void *)store);
}
if (keysToRemove) {
CFArrayApplyFunction(keysToRemove,
CFRangeMake(0, CFArrayGetCount(keysToRemove)),
removeSpecificKey,
(void *)store);
}
if (keysToNotify) {
CFArrayApplyFunction(keysToNotify,
CFRangeMake(0, CFArrayGetCount(keysToNotify)),
notifySpecificKey,
(void *)store);
}
__SCDynamicStoreUnlock(store, TRUE);
return sc_status;
}
__private_extern__
kern_return_t
_configset_m(mach_port_t server,
xmlData_t dictRef,
mach_msg_type_number_t dictLen,
xmlData_t removeRef,
mach_msg_type_number_t removeLen,
xmlData_t notifyRef,
mach_msg_type_number_t notifyLen,
int *sc_status)
{
serverSessionRef mySession = getSession(server);
CFDictionaryRef dict = NULL;
CFArrayRef remove = NULL;
CFArrayRef notify = NULL;
if (_configd_verbose) {
SCLog(TRUE, LOG_DEBUG, CFSTR("Set/remove/notify keys to configuration database."));
SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
}
*sc_status = kSCStatusOK;
if (dictRef && (dictLen > 0)) {
if (!_SCUnserialize((CFPropertyListRef *)&dict, NULL, (void *)dictRef, dictLen)) {
*sc_status = kSCStatusFailed;
} else if (!isA_CFDictionary(dict)) {
*sc_status = kSCStatusInvalidArgument;
}
}
if (removeRef && (removeLen > 0)) {
if (!_SCUnserialize((CFPropertyListRef *)&remove, NULL, (void *)removeRef, removeLen)) {
*sc_status = kSCStatusFailed;
} else if (!isA_CFArray(remove)) {
*sc_status = kSCStatusInvalidArgument;
}
}
if (notifyRef && (notifyLen > 0)) {
if (!_SCUnserialize((CFPropertyListRef *)¬ify, NULL, (void *)notifyRef, notifyLen)) {
*sc_status = kSCStatusFailed;
} else if (!isA_CFArray(notify)) {
*sc_status = kSCStatusInvalidArgument;
}
}
if (!mySession) {
*sc_status = kSCStatusNoStoreSession;
}
if (*sc_status != kSCStatusOK) {
goto done;
}
*sc_status = __SCDynamicStoreSetMultiple(mySession->store, dict, remove, notify);
done :
if (dict) CFRelease(dict);
if (remove) CFRelease(remove);
if (notify) CFRelease(notify);
return KERN_SUCCESS;
}