コード例 #1
0
ファイル: prefsmon.c プロジェクト: 010001111/darling
static void
updateSCDynamicStore(SCPreferencesRef prefs)
{
	CFStringRef		current		= NULL;
	CFDateRef		date		= NULL;
	CFMutableDictionaryRef	dict		= NULL;
	CFDictionaryRef		global		= NULL;
	CFIndex			i;
	CFArrayRef		keys;
	CFIndex			n;
	CFStringRef		pattern;
	CFMutableArrayRef	patterns;
	CFDictionaryRef		set		= NULL;

	/*
	 * initialize old preferences, new preferences, an array
	 * of keys which have not changed, and an array of keys
	 * to be removed (cleaned up).
	 */

	patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
	pattern  = CFStringCreateWithFormat(NULL,
					    NULL,
					    CFSTR("^%@.*"),
					    kSCDynamicStoreDomainSetup);
	CFArrayAppendValue(patterns, pattern);
	dict = (CFMutableDictionaryRef)SCDynamicStoreCopyMultiple(store, NULL, patterns);
	CFRelease(patterns);
	CFRelease(pattern);
	if (dict) {
		currentPrefs = CFDictionaryCreateMutableCopy(NULL, 0, dict);
		CFRelease(dict);
	} else {
		currentPrefs = CFDictionaryCreateMutable(NULL,
							 0,
							 &kCFTypeDictionaryKeyCallBacks,
							 &kCFTypeDictionaryValueCallBacks);
	}

	unchangedPrefsKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);

	i = CFDictionaryGetCount(currentPrefs);
	if (i > 0) {
		const void	**currentKeys;
		CFArrayRef	array;

		currentKeys = CFAllocatorAllocate(NULL, i * sizeof(CFStringRef), 0);
		CFDictionaryGetKeysAndValues(currentPrefs, currentKeys, NULL);
		array = CFArrayCreate(NULL, currentKeys, i, &kCFTypeArrayCallBacks);
		removedPrefsKeys = CFArrayCreateMutableCopy(NULL, 0, array);
		CFRelease(array);
		CFAllocatorDeallocate(NULL, currentKeys);
	} else {
		removedPrefsKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
	}

	/*
	 * The "newPrefs" dictionary will contain the new / updated
	 * configuration which will be written to the configuration cache.
	 */
	newPrefs = CFDictionaryCreateMutable(NULL,
						 0,
						 &kCFTypeDictionaryKeyCallBacks,
						 &kCFTypeDictionaryValueCallBacks);

	/*
	 * create status dictionary associated with current configuration
	 * information including:
	 *   - current set "name" to cache
	 *   - time stamp indicating when the cache preferences were
	 *     last updated.
	 */
	dict = CFDictionaryCreateMutable(NULL,
					 0,
					 &kCFTypeDictionaryKeyCallBacks,
					 &kCFTypeDictionaryValueCallBacks);
	date = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent());

	/*
	 * load preferences
	 */
	keys = SCPreferencesCopyKeyList(prefs);
	if ((keys == NULL) || (CFArrayGetCount(keys) == 0)) {
		SCLog(TRUE, LOG_NOTICE, CFSTR("updateConfiguration(): no preferences."));
		goto done;
	}

	/*
	 * get "global" system preferences
	 */
	global = SCPreferencesGetValue(prefs, kSCPrefSystem);
	if (!global) {
		/* if no global preferences are defined */
		goto getSet;
	}

	if (!isA_CFDictionary(global)) {
		SCLog(TRUE, LOG_ERR,
		      CFSTR("updateConfiguration(): %@ is not a dictionary."),
		      kSCPrefSystem);
		goto done;
	}

	/* flatten property list */
	flatten(prefs, CFSTR("/"), global);

    getSet :

	/*
	 * get current set name
	 */
	current = SCPreferencesGetValue(prefs, kSCPrefCurrentSet);
	if (!current) {
		/* if current set not defined */
		goto done;
	}

	if (!isA_CFString(current)) {
		SCLog(TRUE, LOG_ERR,
		      CFSTR("updateConfiguration(): %@ is not a string."),
		      kSCPrefCurrentSet);
		goto done;
	}

	/*
	 * get current set
	 */
	set = SCPreferencesPathGetValue(prefs, current);
	if (!set) {
		/* if error with path */
		SCLog(TRUE, LOG_ERR,
		      CFSTR("%@ value (%@) not valid"),
		      kSCPrefCurrentSet,
		      current);
		goto done;
	}

	if (!isA_CFDictionary(set)) {
		SCLog(TRUE, LOG_ERR,
		      CFSTR("updateConfiguration(): %@ is not a dictionary."),
		      current);
		goto done;
	}

	/* flatten property list */
	flatten(prefs, CFSTR("/"), set);

	CFDictionarySetValue(dict, kSCDynamicStorePropSetupCurrentSet, current);

    done :

	/* add last updated time stamp */
	CFDictionarySetValue(dict, kSCDynamicStorePropSetupLastUpdated, date);

	/* add Setup: key */
	CFDictionarySetValue(newPrefs, kSCDynamicStoreDomainSetup, dict);

	/* compare current and new preferences */
	CFDictionaryApplyFunction(newPrefs, updateCache, NULL);

	/* remove those keys which have not changed from the update */
	n = CFArrayGetCount(unchangedPrefsKeys);
	for (i = 0; i < n; i++) {
		CFStringRef	key;

		key = CFArrayGetValueAtIndex(unchangedPrefsKeys, i);
		CFDictionaryRemoveValue(newPrefs, key);
	}

	/* Update the dynamic store */
#ifndef MAIN
	if (!SCDynamicStoreSetMultiple(store, newPrefs, removedPrefsKeys, NULL)) {
		SCLog(TRUE, LOG_ERR,
		      CFSTR("SCDynamicStoreSetMultiple() failed: %s"),
		      SCErrorString(SCError()));
	}
#else	// !MAIN
	SCLog(TRUE, LOG_NOTICE,
	      CFSTR("SCDynamicStore\nset: %@\nremove: %@\n"),
	      newPrefs,
	      removedPrefsKeys);
#endif	// !MAIN

	CFRelease(currentPrefs);
	CFRelease(newPrefs);
	CFRelease(unchangedPrefsKeys);
	CFRelease(removedPrefsKeys);
	if (dict)	CFRelease(dict);
	if (date)	CFRelease(date);
	if (keys)	CFRelease(keys);
	return;
}
コード例 #2
0
ファイル: prefsmon.c プロジェクト: 010001111/darling
static Boolean
establishNewPreferences()
{
	CFBundleRef     bundle;
	SCNetworkSetRef	current		= NULL;
	CFStringRef	new_model;
	Boolean		ok		= FALSE;
	int		sc_status	= kSCStatusFailed;
	SCNetworkSetRef	set		= NULL;
	CFStringRef	setName		= NULL;
	Boolean		updated		= FALSE;

	while (TRUE) {
		ok = SCPreferencesLock(prefs, TRUE);
		if (ok) {
			break;
		}

		sc_status = SCError();
		if (sc_status == kSCStatusStale) {
			SCPreferencesSynchronize(prefs);
		} else {
			SCLog(TRUE, LOG_ERR,
			      CFSTR("Could not acquire network configuration lock: %s"),
			      SCErrorString(sc_status));
			return FALSE;
		}
	}

	/* Ensure that the preferences has the new model */
	new_model = _SC_hw_model(FALSE);

	/* Need to regenerate the new configuration for new model */
	if (new_model != NULL) {
		CFStringRef	old_model;

		old_model = SCPreferencesGetValue(prefs, MODEL);
		if ((old_model != NULL) && !_SC_CFEqual(old_model, new_model)) {
			CFIndex		count;
			CFIndex		index;
			CFArrayRef	keys;

			keys = SCPreferencesCopyKeyList(prefs);
			count = (keys != NULL) ? CFArrayGetCount(keys) : 0;
			// if new hardware
			for (index = 0; index < count; index++) {
				CFStringRef		existing_key;

				existing_key = CFArrayGetValueAtIndex(keys, index);
				if (isA_CFString(existing_key) != NULL) {
					CFStringRef		new_key;
					CFPropertyListRef	value;

					/* If it already contains a Model
					   or if it already contains a MODEL:KEY key skip it*/
					if (CFEqual(existing_key, MODEL)
					    || CFStringFind(existing_key, CFSTR(":"), 0).location
					    != kCFNotFound) {
						continue;
					}

					value = SCPreferencesGetValue(prefs, existing_key);

					/* Create a new key as OLD_MODEL:OLD_KEY */
					new_key = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@:%@"),
									   old_model, existing_key);
					SCPreferencesSetValue(prefs, new_key, value);
					if (!CFEqual(existing_key, kSCPrefSystem)) {
						/* preserve existing host names */
						SCPreferencesRemoveValue(prefs, existing_key);
					}
					CFRelease(new_key);
				}
			}

			if (keys != NULL) {
				CFRelease(keys);
			}
		}
		/* Set the new model */
		SCPreferencesSetValue(prefs, MODEL, new_model);
	}

	current = SCNetworkSetCopyCurrent(prefs);
	if (current != NULL) {
		set = current;
	}

	if (set == NULL) {
		set = SCNetworkSetCreate(prefs);
		if (set == NULL) {
			ok = FALSE;
			sc_status = SCError();
			goto done;
		}

		bundle = _SC_CFBundleGet();
		if (bundle != NULL) {
			setName = CFBundleCopyLocalizedString(bundle,
							      CFSTR("DEFAULT_SET_NAME"),
							      CFSTR("Automatic"),
							      NULL);
		}

		ok = SCNetworkSetSetName(set, (setName != NULL) ? setName : CFSTR("Automatic"));
		if (!ok) {
			sc_status = SCError();
			goto done;
		}

		ok = SCNetworkSetSetCurrent(set);
		if (!ok) {
			sc_status = SCError();
			goto done;
		}
	}

	ok = SCNetworkSetEstablishDefaultConfiguration(set);
	if (!ok) {
		sc_status = SCError();
		goto done;
	}

    done :

	if (ok) {
		ok = SCPreferencesCommitChanges(prefs);
		if (ok) {
			SCLog(TRUE, LOG_NOTICE, CFSTR("New network configuration saved"));
			updated = TRUE;
		} else {
			sc_status = SCError();
			if (sc_status == EROFS) {
				/* a read-only fileysstem is OK */
				ok = TRUE;

				/* ... but we don't want to synchronize */
				rofs = TRUE;
			}
		}

		/* apply (committed or temporary/read-only) changes */
		(void) SCPreferencesApplyChanges(prefs);
	} else if ((current == NULL) && (set != NULL)) {
		(void) SCNetworkSetRemove(set);
	}

	if (!ok) {
		SCLog(TRUE, LOG_ERR,
		      CFSTR("Could not establish network configuration: %s"),
		      SCErrorString(sc_status));
	}

	(void)SCPreferencesUnlock(prefs);
	if (setName != NULL) CFRelease(setName);
	if (set != NULL) CFRelease(set);
	return updated;
}
コード例 #3
0
static void LeakTest(TestFunc tester)
	// Given a test name and a pointer to a test function, 
	// this routine calls the test function repeatedly to check 
	// for SCF preferences reference count leaks.
{
	OSStatus 			err;
	SCPreferencesRef 	prefsRef;
	CFArrayRef 			allKeys;
	int					i;
	SInt32				startCount;
	SInt32				endCount;
	
	// This is kinda cheesy.  We need to use the same SCPreferencesRef 
	// that MoreSCF uses because otherwise we can't see the reference 
	// count changes done by MoreSCF.  Ideally, we wouldn't want to run 
	// within a MoreSCOpen/MoreSCClose pair because then our changes 
	// aren't necessarily being committed to the database.  However, 
	// given the current MoreSCF architecture, where the SCPreferenceRef 
	// is only valid inside the MoreSCOpen/MoreSCClose pair, that's 
	// exactly what we have to do.

	allKeys = NULL;
	
	err = MoreSCOpen(false, false);
	if (err == noErr) {
		prefsRef = MoreSCGetSCPreferencesRef();
	}

	// Now get a copy of the array of all keys in the database.  
	// We make this copy using CFPropertyListCreateDeepCopy so we 
	// know that it's completely independent of the SCF.
	
	if (err == noErr) {
		CFArrayRef allKeysOrig;
		
		allKeysOrig = NULL;

		allKeysOrig = SCPreferencesCopyKeyList(prefsRef);
		if (allKeysOrig == NULL) {
			err = SCError();
		}
		if (err == noErr) {
			allKeys = (CFArrayRef) CFPropertyListCreateDeepCopy(NULL, allKeysOrig, kCFPropertyListMutableContainersAndLeaves);	// C++ requires cast
			if (allKeys == NULL) {
				err = coreFoundationUnknownErr;
			}
		}
		
		CFQRelease(allKeysOrig);
	}

	// Now do the reference counting test.  Call the tester function
	// a few times to allow the refcounts to stabilise.  Then get 
	// a summ of all the nodes in all of the keys in SCF.  Then 
	// run the test a 10 more times and get another count.  If 
	// the counts are different, we're in trouble.
	
	if (err == noErr) {
		for (i = 0; i < 3; i++) {
			tester();
		}
		
		startCount = TotalAllRefCounts(prefsRef, allKeys);
		
		for (i = 0; i < 10; i++) {
			tester();
		}
		
		endCount = TotalAllRefCounts(prefsRef, allKeys);
		
		if (startCount != endCount) {
			CFIndex keyCount;
			CFIndex keyIndex;
			
			fprintf(stderr, "*** Leaked %ld reference counts.\n", endCount - startCount);

			keyCount = CFArrayGetCount(allKeys);
			for (keyIndex = 0; keyIndex < keyCount; keyIndex++) {
				CFPropertyListRef thisPref;

				// The commented out code is only needed when you're actively 
				// trying to track down a leak.  Given that leaks are rare 
				// I decided against making a proper architecture for this. 
				// Just uncomment the code and modify it appropriately.
				
				startCount = 0;
				thisPref = SCPreferencesGetValue(prefsRef, (CFStringRef) CFArrayGetValueAtIndex(allKeys, keyIndex));	// C++ requires cast
				CFQPropertyListDeepApplyFunction(thisPref, RefCounter, (void *) &startCount );
//				if (keyIndex == 0) {
//					fprintf(stderr, "*** BEFORE ***\n");
//					PrintPropertyList(thisPref);
//				}

				tester();

				endCount = 0;
				thisPref = SCPreferencesGetValue(prefsRef, (CFStringRef) CFArrayGetValueAtIndex(allKeys, keyIndex));	// C++ requires cast
				CFQPropertyListDeepApplyFunction(thisPref, RefCounter, (void *) &endCount );
//				if (keyIndex == 0) {
//					fprintf(stderr, "*** AFTER ***\n");
//					PrintPropertyList(thisPref);
//				}
				
				if (startCount != endCount) {
					fprintf(stderr, "*** Leaked %ld reference counts in set number %ld\n", endCount - startCount, keyIndex);
					CFShow(CFArrayGetValueAtIndex(allKeys, keyIndex));
				}
			}
		}
	}

	MoreSCClose(&err, false);

	CFQRelease(allKeys);

    if (err != noErr) {
        fprintf(stderr, "*** Failed with error %ld!\n", err);
    }
}