#include "configd.h"
#include "session.h"
int
__SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value)
{
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
int sc_status = kSCStatusOK;
CFDictionaryRef dict;
CFMutableDictionaryRef newDict;
Boolean newEntry = FALSE;
CFStringRef sessionKey;
CFStringRef storeSessionKey;
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreSetValue:"));
SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" key = %@"), key);
SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" value = %@"), value);
if (!store || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession;
}
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 {
CFDictionaryApplyFunction(sessionData,
(CFDictionaryApplierFunction)_addRegexWatchersBySession,
(void *)key);
}
}
CFSetAddValue(changedKeys, key);
__SCDynamicStoreUnlock(store, TRUE);
return sc_status;
}
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;
CFPropertyListRef data;
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Set key to configuration database."));
SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server);
*sc_status = kSCStatusOK;
if (!_SCUnserialize((CFPropertyListRef *)&key, (void *)keyRef, keyLen)) {
*sc_status = kSCStatusFailed;
}
if (!isA_CFString(key)) {
*sc_status = kSCStatusInvalidArgument;
}
if (!_SCUnserialize((CFPropertyListRef *)&data, (void *)dataRef, dataLen)) {
*sc_status = kSCStatusFailed;
}
if (!isA_CFPropertyList(data)) {
*sc_status = kSCStatusInvalidArgument;
}
if (*sc_status != kSCStatusOK) {
if (key) CFRelease(key);
if (data) CFRelease(data);
return KERN_SUCCESS;
}
*sc_status = __SCDynamicStoreSetValue(mySession->store, key, data);
*newInstance = 0;
CFRelease(key);
CFRelease(data);
return KERN_SUCCESS;
}
static void
setSpecificKey(const void *key, const void *value, void *context)
{
CFStringRef k = (CFStringRef)key;
CFPropertyListRef v = (CFPropertyListRef)value;
SCDynamicStoreRef store = (SCDynamicStoreRef)context;
if (!isA_CFString(k)) {
return;
}
if (!isA_CFPropertyList(v)) {
return;
}
(void) __SCDynamicStoreSetValue(store, k, v);
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);
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);
return;
}
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;
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Set key to configuration database."));
SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server);
*sc_status = kSCStatusOK;
if (dictRef && (dictLen > 0)) {
if (!_SCUnserialize((CFPropertyListRef *)&dict, (void *)dictRef, dictLen)) {
*sc_status = kSCStatusFailed;
}
if (!isA_CFDictionary(dict)) {
*sc_status = kSCStatusInvalidArgument;
}
}
if (removeRef && (removeLen > 0)) {
if (!_SCUnserialize((CFPropertyListRef *)&remove, (void *)removeRef, removeLen)) {
*sc_status = kSCStatusFailed;
}
if (!isA_CFArray(remove)) {
*sc_status = kSCStatusInvalidArgument;
}
}
if (notifyRef && (notifyLen > 0)) {
if (!_SCUnserialize((CFPropertyListRef *)¬ify, (void *)notifyRef, notifyLen)) {
*sc_status = kSCStatusFailed;
}
if (!isA_CFArray(notify)) {
*sc_status = kSCStatusInvalidArgument;
}
}
if (*sc_status != kSCStatusOK) {
goto done;
}
*sc_status = __SCDynamicStoreLock(mySession->store, TRUE);
if (*sc_status != kSCStatusOK) {
goto done;
}
if (dict) {
CFDictionaryApplyFunction(dict,
setSpecificKey,
(void *)mySession->store);
}
if (remove) {
CFArrayApplyFunction(remove,
CFRangeMake(0, CFArrayGetCount(remove)),
removeSpecificKey,
(void *)mySession->store);
}
if (notify) {
CFArrayApplyFunction(notify,
CFRangeMake(0, CFArrayGetCount(notify)),
notifySpecificKey,
(void *)mySession->store);
}
__SCDynamicStoreUnlock(mySession->store, TRUE);
done :
if (dict) CFRelease(dict);
if (remove) CFRelease(remove);
if (notify) CFRelease(notify);
return KERN_SUCCESS;
}