X-Git-Url: https://git.saurik.com/apple/configd.git/blobdiff_plain/4c5e92e2493bdfbbce40e998f3b607c72c47af2c..edebe297f772e4cdd76278ebb777820466d2917b:/configd.tproj/_configset.c diff --git a/configd.tproj/_configset.c b/configd.tproj/_configset.c index 08747c3..3fda0fe 100644 --- a/configd.tproj/_configset.c +++ b/configd.tproj/_configset.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2004, 2006 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -49,24 +49,15 @@ __SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef val 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)) { + if ((store == NULL) || (storePrivate->server == MACH_PORT_NULL)) { return kSCStatusNoStoreSession; /* you must have an open session to play */ } if (_configd_trace) { SCTrace(TRUE, _configd_trace, - CFSTR("%s : %5d : %@\n"), - internal ? "*set " : "set ", + CFSTR("%s%s : %5d : %@\n"), + internal ? "*set " : "set ", + storePrivate->useSessionKeys ? "t " : " ", storePrivate->server, key); } @@ -101,24 +92,91 @@ __SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef val newEntry = !CFDictionaryContainsKey(newDict, kSCDData); CFDictionarySetValue(newDict, kSCDData, value); - /* - * 4. Since we are updating this key we need to check and, if - * necessary, remove the indication that this key is on - * another session's remove-on-close list. - */ sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server); - if (CFDictionaryGetValueIfPresent(newDict, kSCDSession, (void *)&storeSessionKey) && - !CFEqual(sessionKey, storeSessionKey)) { - CFStringRef removedKey; - - /* We are no longer a session key! */ - CFDictionaryRemoveValue(newDict, kSCDSession); - /* add this session key to the (session) removal list */ - removedKey = CFStringCreateWithFormat(NULL, 0, CFSTR("%@:%@"), storeSessionKey, key); - CFSetAddValue(removedSessionKeys, removedKey); - CFRelease(removedKey); + /* + * 4. Manage per-session keys. + */ + if (storePrivate->useSessionKeys) { + if (newEntry) { + CFArrayRef keys; + CFMutableDictionaryRef newSession; + CFMutableArrayRef newKeys; + CFDictionaryRef session; + + /* + * Add this key to my list of per-session keys + */ + session = CFDictionaryGetValue(sessionData, sessionKey); + keys = CFDictionaryGetValue(session, kSCDSessionKeys); + if ((keys == NULL) || + (CFArrayGetFirstIndexOfValue(keys, + CFRangeMake(0, CFArrayGetCount(keys)), + key) == kCFNotFound)) { + /* + * if no session keys defined "or" keys defined but not + * this one... + */ + if (keys != NULL) { + /* this is the first session key */ + newKeys = CFArrayCreateMutableCopy(NULL, 0, keys); + } else { + /* this is an additional session key */ + newKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + } + CFArrayAppendValue(newKeys, key); + + /* update session dictionary */ + newSession = CFDictionaryCreateMutableCopy(NULL, 0, session); + CFDictionarySetValue(newSession, kSCDSessionKeys, newKeys); + CFRelease(newKeys); + CFDictionarySetValue(sessionData, sessionKey, newSession); + CFRelease(newSession); + } + + /* + * Mark the key as a "session" key and track the creator. + */ + CFDictionarySetValue(newDict, kSCDSession, sessionKey); + } else { + /* + * Since we are using per-session keys and this key already + * exists, check if it was created by "our" session + */ + dict = CFDictionaryGetValue(storeData, key); + if (!CFDictionaryGetValueIfPresent(dict, kSCDSession, (void *)&storeSessionKey) || + !CFEqual(sessionKey, storeSessionKey)) { + /* + * if the key exists and is not a session key or + * if the key exists it's not "our" session. + */ + sc_status = kSCStatusKeyExists; + CFRelease(sessionKey); + CFRelease(newDict); + goto done; + } + } + } else { + /* + * Since we are updating this key we need to check and, if + * necessary, remove the indication that this key is on + * another session's remove-on-close list. + */ + if (!newEntry && + CFDictionaryGetValueIfPresent(newDict, kSCDSession, (void *)&storeSessionKey) && + !CFEqual(sessionKey, storeSessionKey)) { + CFStringRef removedKey; + + /* We are no longer a session key! */ + CFDictionaryRemoveValue(newDict, kSCDSession); + + /* add this session key to the (session) removal list */ + removedKey = CFStringCreateWithFormat(NULL, 0, CFSTR("%@:%@"), storeSessionKey, key); + CFSetAddValue(removedSessionKeys, removedKey); + CFRelease(removedKey); + } } + CFRelease(sessionKey); /* @@ -152,6 +210,8 @@ __SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef val */ CFSetAddValue(changedKeys, key); + done : + /* * 8. Release our lock. */ @@ -172,22 +232,15 @@ _configset(mach_port_t server, int *sc_status ) { - serverSessionRef mySession = getSession(server); - CFStringRef key; /* key (un-serialized) */ - CFDataRef data; /* data (un-serialized) */ - - if (_configd_verbose) { - SCLog(TRUE, LOG_DEBUG, CFSTR("Set key to configuration database.")); - SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server); - } + CFDataRef data = NULL; /* data (un-serialized) */ + CFStringRef key = NULL; /* key (un-serialized) */ + serverSessionRef mySession = getSession(server); *sc_status = kSCStatusOK; /* un-serialize the key */ if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) { *sc_status = kSCStatusFailed; - } else if (!isA_CFString(key)) { - *sc_status = kSCStatusInvalidArgument; } /* un-serialize the data */ @@ -195,22 +248,27 @@ _configset(mach_port_t server, *sc_status = kSCStatusFailed; } - if (!mySession) { - *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */ + if (*sc_status != kSCStatusOK) { + goto done; } - if (*sc_status != kSCStatusOK) { - if (key) CFRelease(key); - if (data) CFRelease(data); - return KERN_SUCCESS; + if (!isA_CFString(key)) { + *sc_status = kSCStatusInvalidArgument; + goto done; + } + + if (mySession == NULL) { + *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */ + goto done; } *sc_status = __SCDynamicStoreSetValue(mySession->store, key, data, FALSE); *newInstance = 0; - CFRelease(key); - CFRelease(data); + done : + if (key) CFRelease(key); + if (data) CFRelease(data); return KERN_SUCCESS; } @@ -271,18 +329,7 @@ __SCDynamicStoreSetMultiple(SCDynamicStoreRef store, CFDictionaryRef keysToSet, 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)) { + if ((store == NULL) || (storePrivate->server == MACH_PORT_NULL)) { return kSCStatusNoStoreSession; /* you must have an open session to play */ } @@ -349,51 +396,56 @@ _configset_m(mach_port_t server, mach_msg_type_number_t notifyLen, int *sc_status) { - serverSessionRef mySession = getSession(server); - CFDictionaryRef dict = NULL; /* key/value dictionary (un-serialized) */ - CFArrayRef remove = NULL; /* keys to remove (un-serialized) */ - CFArrayRef notify = NULL; /* keys to notify (un-serialized) */ - - if (_configd_verbose) { - SCLog(TRUE, LOG_DEBUG, CFSTR("Set/remove/notify keys to configuration database.")); - SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server); - } + CFDictionaryRef dict = NULL; /* key/value dictionary (un-serialized) */ + serverSessionRef mySession = getSession(server); + CFArrayRef notify = NULL; /* keys to notify (un-serialized) */ + CFArrayRef remove = NULL; /* keys to remove (un-serialized) */ *sc_status = kSCStatusOK; - if (dictRef && (dictLen > 0)) { + if ((dictRef != NULL) && (dictLen > 0)) { /* un-serialize the key/value pairs to set */ if (!_SCUnserialize((CFPropertyListRef *)&dict, NULL, (void *)dictRef, dictLen)) { *sc_status = kSCStatusFailed; - } else if (!isA_CFDictionary(dict)) { - *sc_status = kSCStatusInvalidArgument; } } - if (removeRef && (removeLen > 0)) { + if ((removeRef != NULL) && (removeLen > 0)) { /* un-serialize the keys to remove */ if (!_SCUnserialize((CFPropertyListRef *)&remove, NULL, (void *)removeRef, removeLen)) { *sc_status = kSCStatusFailed; - } else if (!isA_CFArray(remove)) { - *sc_status = kSCStatusInvalidArgument; } } - if (notifyRef && (notifyLen > 0)) { + if ((notifyRef != NULL) && (notifyLen > 0)) { /* un-serialize the keys to notify */ if (!_SCUnserialize((CFPropertyListRef *)¬ify, NULL, (void *)notifyRef, notifyLen)) { *sc_status = kSCStatusFailed; - } else if (!isA_CFArray(notify)) { - *sc_status = kSCStatusInvalidArgument; } } - if (!mySession) { - /* you must have an open session to play */ - *sc_status = kSCStatusNoStoreSession; + if (*sc_status != kSCStatusOK) { + goto done; } - if (*sc_status != kSCStatusOK) { + if ((dict != NULL) && !isA_CFDictionary(dict)) { + *sc_status = kSCStatusInvalidArgument; + goto done; + } + + if ((remove != NULL) && !isA_CFArray(remove)) { + *sc_status = kSCStatusInvalidArgument; + goto done; + } + + if ((notify != NULL) && !isA_CFArray(notify)) { + *sc_status = kSCStatusInvalidArgument; + goto done; + } + + if (mySession == NULL) { + /* you must have an open session to play */ + *sc_status = kSCStatusNoStoreSession; goto done; } @@ -401,9 +453,9 @@ _configset_m(mach_port_t server, done : - if (dict) CFRelease(dict); - if (remove) CFRelease(remove); - if (notify) CFRelease(notify); + if (dict != NULL) CFRelease(dict); + if (remove != NULL) CFRelease(remove); + if (notify != NULL) CFRelease(notify); return KERN_SUCCESS; }