Beispiel #1
0
SCPreferencesRef
SCPreferencesCreateWithOptions(CFAllocatorRef	allocator,
			       CFStringRef	name,
			       CFStringRef	prefsID,
			       AuthorizationRef	authorization,
			       CFDictionaryRef	options)
{
	CFDataRef			authorizationData	= NULL;
	SCPreferencesPrivateRef		prefsPrivate;

	if (options != NULL) {
		if (!isA_CFDictionary(options)) {
			_SCErrorSet(kSCStatusInvalidArgument);
			return NULL;
		}
	}

	if (authorization != NULL) {
		CFMutableDictionaryRef	authorizationDict;
		CFBundleRef		bundle;
		CFStringRef		bundleID	= NULL;

		authorizationDict =  CFDictionaryCreateMutable(NULL,
							       0,
							       &kCFTypeDictionaryKeyCallBacks,
							       &kCFTypeDictionaryValueCallBacks);
#if	!TARGET_OS_IPHONE
		if (authorization != kSCPreferencesUseEntitlementAuthorization) {
			CFDataRef			data;
			AuthorizationExternalForm	extForm;
			OSStatus			os_status;

			os_status = AuthorizationMakeExternalForm(authorization, &extForm);
			if (os_status != errAuthorizationSuccess) {
				SCLog(TRUE, LOG_INFO, CFSTR("_SCHelperOpen AuthorizationMakeExternalForm() failed"));
				_SCErrorSet(kSCStatusInvalidArgument);
				CFRelease(authorizationDict);
				return NULL;
			}

			data = CFDataCreate(NULL, (const UInt8 *)extForm.bytes, sizeof(extForm.bytes));
			CFDictionaryAddValue(authorizationDict,
					     kSCHelperAuthAuthorization,
					     data);
			CFRelease(data);
		}
#endif

		/* get the application/executable/bundle name */
		bundle = CFBundleGetMainBundle();
		if (bundle != NULL) {
			bundleID = CFBundleGetIdentifier(bundle);
			if (bundleID != NULL) {
				CFRetain(bundleID);
			} else {
				CFURLRef	url;

				url = CFBundleCopyExecutableURL(bundle);
				if (url != NULL) {
					bundleID = CFURLCopyPath(url);
					CFRelease(url);
				}
			}

			if (bundleID != NULL) {
				if (CFEqual(bundleID, CFSTR("/"))) {
					CFRelease(bundleID);
					bundleID = NULL;
				}
			}
		}
		if (bundleID == NULL) {
			bundleID = CFStringCreateWithFormat(NULL, NULL, CFSTR("Unknown(%d)"), getpid());
		}
		CFDictionaryAddValue(authorizationDict,
				     kSCHelperAuthCallerInfo,
				     bundleID);
		CFRelease(bundleID);

		if (authorizationDict != NULL) {
			_SCSerialize((CFPropertyListRef)authorizationDict,
				     &authorizationData,
				     NULL,
				     NULL);
			CFRelease(authorizationDict);
		}
	}

	prefsPrivate = __SCPreferencesCreate(allocator, name, prefsID, authorizationData, options);
	if (authorizationData != NULL) CFRelease(authorizationData);

	return (SCPreferencesRef)prefsPrivate;
}
Beispiel #2
0
__private_extern__ Boolean
__SCPreferencesCreate_helper(SCPreferencesRef prefs)
{
	CFDataRef		data		= NULL;
	CFMutableDictionaryRef	info;
	CFNumberRef		num;
	Boolean			ok;
	SCPreferencesPrivateRef	prefsPrivate	= (SCPreferencesPrivateRef)prefs;
	uint32_t		status		= kSCStatusOK;
	CFStringRef		str;
	uint32_t		pid		= getpid();

	// start helper
	ok = _SCHelperOpen(prefsPrivate->authorizationData,
			   &prefsPrivate->helper_port);
	if (!ok) {
		goto fail;
	}

	// create a dictionary of information to pass to the helper
	info = CFDictionaryCreateMutable(NULL,
					 0,
					 &kCFTypeDictionaryKeyCallBacks,
					 &kCFTypeDictionaryValueCallBacks);

	// save prefsID
	if (prefsPrivate->prefsID != NULL) {
		CFDictionarySetValue(info, CFSTR("prefsID"), prefsPrivate->prefsID);
	}

	// save options
	if (prefsPrivate->options != NULL) {
		CFDictionarySetValue(info, CFSTR("options"), prefsPrivate->options);
	}

	// save preferences session "name"
	CFDictionarySetValue(info, CFSTR("name"), prefsPrivate->name);

	// save PID
	num = CFNumberCreate(NULL, kCFNumberSInt32Type, &pid);
	CFDictionarySetValue(info, CFSTR("PID"), num);
	CFRelease(num);

	// save process name
	str = CFStringCreateWithCString(NULL, getprogname(), kCFStringEncodingUTF8);
	CFDictionarySetValue(info, CFSTR("PROC_NAME"), str);
	CFRelease(str);

	// serialize the info
	ok = _SCSerialize(info, &data, NULL, NULL);
	CFRelease(info);
	if (data == NULL || !ok) {
		goto fail;
	}

	// have the helper "open" the prefs
	ok = _SCHelperExec(prefsPrivate->helper_port,
			   SCHELPER_MSG_PREFS_OPEN,
			   data,
			   &status,
			   NULL);
	if (data != NULL) CFRelease(data);
	if (!ok) {
		goto fail;
	}

	if (status != kSCStatusOK) {
		goto error;
	}

	return TRUE;

    fail :

	// close helper
	if (prefsPrivate->helper_port != MACH_PORT_NULL) {
		_SCHelperClose(&prefsPrivate->helper_port);
	}

	status = kSCStatusAccessError;

    error :

	// return error
	_SCErrorSet(status);
	return FALSE;
}
Beispiel #3
0
static Boolean
__SCDynamicStoreAddSession(SCDynamicStorePrivateRef storePrivate)
{
	kern_return_t		kr		= KERN_SUCCESS;
	CFDataRef		myName;			/* serialized name */
	xmlData_t		myNameRef;
	CFIndex			myNameLen;
	CFDataRef		myOptions	= NULL;	/* serialized options */
	xmlData_t		myOptionsRef	= NULL;
	CFIndex			myOptionsLen	= 0;
	int			sc_status	= kSCStatusFailed;
	mach_port_t		server;

	if (!_SCSerializeString(storePrivate->name, &myName, (void **)&myNameRef, &myNameLen)) {
		goto done;
	}

	/* serialize the options */
	if (storePrivate->options != NULL) {
		if (!_SCSerialize(storePrivate->options, &myOptions, (void **)&myOptionsRef, &myOptionsLen)) {
			CFRelease(myName);
			goto done;
		}
	}

	/* open a new session with the server */
	server = MACH_PORT_NULL;


	updateServerPort(storePrivate, &server, &sc_status);


	while (server != MACH_PORT_NULL) {
		// if SCDynamicStore server available

		if (!storePrivate->serverNullSession) {
			// if SCDynamicStore session
			kr = configopen(server,
					myNameRef,
					(mach_msg_type_number_t)myNameLen,
					myOptionsRef,
					(mach_msg_type_number_t)myOptionsLen,
					&storePrivate->server,
					(int *)&sc_status);
		} else {
			// if NULL session
			if (storePrivate->server == MACH_PORT_NULL) {
				// use the [main] SCDynamicStore server port
				kr = mach_port_mod_refs(mach_task_self(), server, MACH_PORT_RIGHT_SEND, +1);
				if (kr == KERN_SUCCESS) {
					storePrivate->server = server;
					sc_status = kSCStatusOK;
				} else {
					storePrivate->server = MACH_PORT_NULL;
				}
			} else {
				// if the server port we used returned an error
				storePrivate->server = MACH_PORT_NULL;
				kr = MACH_SEND_INVALID_DEST;
			}
		}

		if (kr == KERN_SUCCESS) {
			break;
		}

		// our [cached] server port is not valid
		if ((kr != MACH_SEND_INVALID_DEST) && (kr != MIG_SERVER_DIED)) {
			// if we got an unexpected error, don't retry
			sc_status = kr;
			break;
		}


		updateServerPort(storePrivate, &server, &sc_status);
	}
	__MACH_PORT_DEBUG(TRUE, "*** SCDynamicStoreAddSession", storePrivate->server);

	// clean up
	CFRelease(myName);
	if (myOptions != NULL)	CFRelease(myOptions);

    done :

	switch (sc_status) {
		case kSCStatusOK :
			return TRUE;
		case BOOTSTRAP_UNKNOWN_SERVICE :
			SCLog(TRUE,
			      (kr == KERN_SUCCESS) ? LOG_DEBUG : LOG_ERR,
			      CFSTR("SCDynamicStore server not available"));
			sc_status = kSCStatusNoStoreServer;
			break;
		default :
			SCLog(TRUE,
			      (kr == KERN_SUCCESS) ? LOG_DEBUG : LOG_ERR,
			      CFSTR("SCDynamicStoreAddSession configopen(): %s"),
			      SCErrorString(sc_status));
			break;
	}

	_SCErrorSet(sc_status);
	return FALSE;
}
Boolean
SCDynamicStoreSetNotificationKeys(SCDynamicStoreRef	store,
				  CFArrayRef		keys,
				  CFArrayRef		patterns)
{
	SCDynamicStorePrivateRef	storePrivate = (SCDynamicStorePrivateRef)store;
	kern_return_t			status;
	CFDataRef			xmlKeys		= NULL;	/* keys (XML serialized) */
	xmlData_t			myKeysRef	= NULL;	/* keys (serialized) */
	CFIndex				myKeysLen	= 0;
	CFDataRef			xmlPatterns	= NULL;	/* patterns (XML serialized) */
	xmlData_t			myPatternsRef	= NULL;	/* patterns (serialized) */
	CFIndex				myPatternsLen	= 0;
	int				sc_status;
	CFMutableArrayRef		tmp;

	if (store == NULL) {
		/* sorry, you must provide a session */
		_SCErrorSet(kSCStatusNoStoreSession);
		return FALSE;
	}

	if (storePrivate->server == MACH_PORT_NULL) {
		_SCErrorSet(kSCStatusNoStoreServer);
		return FALSE;	/* you must have an open session to play */
	}

	/* serialize the keys */
	if (keys != NULL) {
		if (!_SCSerialize(keys, &xmlKeys, (void **)&myKeysRef, &myKeysLen)) {
			_SCErrorSet(kSCStatusFailed);
			return FALSE;
		}
	}

	/* serialize the patterns */
	if (patterns != NULL) {
		if (!_SCSerialize(patterns, &xmlPatterns, (void **)&myPatternsRef, &myPatternsLen)) {
			if (xmlKeys != NULL) CFRelease(xmlKeys);
			_SCErrorSet(kSCStatusFailed);
			return FALSE;
		}
	}

    retry :

	/* send the keys and patterns, fetch the associated result from the server */
	status = notifyset(storePrivate->server,
			   myKeysRef,
			   myKeysLen,
			   myPatternsRef,
			   myPatternsLen,
			   (int *)&sc_status);

	if (__SCDynamicStoreCheckRetryAndHandleError(store,
						     status,
						     &sc_status,
						     "SCDynamicStoreSetNotificationKeys notifyset()")) {
		goto retry;
	}

	/* clean up */
	if (xmlKeys != NULL)		CFRelease(xmlKeys);
	if (xmlPatterns != NULL)	CFRelease(xmlPatterns);

	if (sc_status != kSCStatusOK) {
		_SCErrorSet(sc_status);
		return FALSE;
	}

	/* in case we need to re-connect, save the keys/patterns */
	tmp = (keys != NULL) ? CFArrayCreateMutableCopy(NULL, 0, keys) : NULL;
	if (storePrivate->keys != NULL) CFRelease(storePrivate->keys);
	storePrivate->keys = tmp;

	tmp = (patterns != NULL) ? CFArrayCreateMutableCopy(NULL, 0, patterns) : NULL;
	if (storePrivate->patterns != NULL) CFRelease(storePrivate->patterns);
	storePrivate->patterns = tmp;

	return TRUE;
}
Boolean
SCDynamicStoreSetMultiple(SCDynamicStoreRef	store,
			  CFDictionaryRef	keysToSet,
			  CFArrayRef		keysToRemove,
			  CFArrayRef		keysToNotify)
{
	SCDynamicStorePrivateRef	storePrivate;
	kern_return_t			status;
	CFDataRef			xmlSet		= NULL;	/* key/value pairs to set (XML serialized) */
	xmlData_t			mySetRef	= NULL;	/* key/value pairs to set (serialized) */
	CFIndex				mySetLen	= 0;
	CFDataRef			xmlRemove	= NULL;	/* keys to remove (XML serialized) */
	xmlData_t			myRemoveRef	= NULL;	/* keys to remove (serialized) */
	CFIndex				myRemoveLen	= 0;
	CFDataRef			xmlNotify	= NULL;	/* keys to notify (XML serialized) */
	xmlData_t			myNotifyRef	= NULL;	/* keys to notify (serialized) */
	CFIndex				myNotifyLen	= 0;
	int				sc_status;

	if (store == NULL) {
		store = __SCDynamicStoreNullSession();
		if (store == NULL) {
			/* sorry, you must provide a session */
			_SCErrorSet(kSCStatusNoStoreSession);
			return FALSE;
		}
	}

	storePrivate = (SCDynamicStorePrivateRef)store;
	if (storePrivate->server == MACH_PORT_NULL) {
		_SCErrorSet(kSCStatusNoStoreServer);
		return FALSE;	/* you must have an open session to play */
	}

	/* serialize the key/value pairs to set*/
	if (keysToSet != NULL) {
		CFDictionaryRef	newInfo;
		Boolean		ok;

		newInfo = _SCSerializeMultiple(keysToSet);
		if (newInfo == NULL) {
			_SCErrorSet(kSCStatusInvalidArgument);
			return FALSE;
		}

		ok = _SCSerialize(newInfo, &xmlSet, (void **)&mySetRef, &mySetLen);
		CFRelease(newInfo);
		if (!ok) {
			_SCErrorSet(kSCStatusInvalidArgument);
			return FALSE;
		}
	}

	/* serialize the keys to remove */
	if (keysToRemove != NULL) {
		if (!_SCSerialize(keysToRemove, &xmlRemove, (void **)&myRemoveRef, &myRemoveLen)) {
			if (xmlSet != NULL)	CFRelease(xmlSet);
			_SCErrorSet(kSCStatusInvalidArgument);
			return FALSE;
		}
	}

	/* serialize the keys to notify */
	if (keysToNotify != NULL) {
		if (!_SCSerialize(keysToNotify, &xmlNotify, (void **)&myNotifyRef, &myNotifyLen)) {
			if (xmlSet != NULL)	CFRelease(xmlSet);
			if (xmlRemove != NULL)	CFRelease(xmlRemove);
			_SCErrorSet(kSCStatusInvalidArgument);
			return FALSE;
		}
	}

    retry :

	/* send the keys and patterns, fetch the associated result from the server */
	status = configset_m(storePrivate->server,
			     mySetRef,
			     mySetLen,
			     myRemoveRef,
			     myRemoveLen,
			     myNotifyRef,
			     myNotifyLen,
			     (int *)&sc_status);

	if (__SCDynamicStoreCheckRetryAndHandleError(store,
						     status,
						     &sc_status,
						     "SCDynamicStoreSetMultiple configset_m()")) {
		goto retry;
	}

	/* clean up */
	if (xmlSet != NULL)	CFRelease(xmlSet);
	if (xmlRemove != NULL)	CFRelease(xmlRemove);
	if (xmlNotify != NULL)	CFRelease(xmlNotify);

	if (sc_status != kSCStatusOK) {
		_SCErrorSet(sc_status);
		return FALSE;
	}

	return TRUE;
}
Boolean
SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value)
{
	SCDynamicStorePrivateRef	storePrivate;
	kern_return_t			status;
	CFDataRef			utfKey;		/* serialized key */
	xmlData_t			myKeyRef;
	CFIndex				myKeyLen;
	CFDataRef			xmlData;	/* serialized data */
	xmlData_t			myDataRef;
	CFIndex				myDataLen;
	int				sc_status;
	int				newInstance;

	if (store == NULL) {
		store = __SCDynamicStoreNullSession();
		if (store == NULL) {
			/* sorry, you must provide a session */
			_SCErrorSet(kSCStatusNoStoreSession);
			return FALSE;
		}
	}

	storePrivate = (SCDynamicStorePrivateRef)store;
	if (storePrivate->server == MACH_PORT_NULL) {
		/* sorry, you must have an open session to play */
		_SCErrorSet(kSCStatusNoStoreServer);
		return FALSE;
	}

	/* serialize the key */
	if (!_SCSerializeString(key, &utfKey, (void **)&myKeyRef, &myKeyLen)) {
		_SCErrorSet(kSCStatusInvalidArgument);
		return FALSE;
	}

	/* serialize the data */
	if (!_SCSerialize(value, &xmlData, (void **)&myDataRef, &myDataLen)) {
		CFRelease(utfKey);
		_SCErrorSet(kSCStatusInvalidArgument);
		return FALSE;
	}

    retry :

	/* send the key & data to the server, get new instance id */
	status = configset(storePrivate->server,
			   myKeyRef,
			   myKeyLen,
			   myDataRef,
			   myDataLen,
			   0,
			   &newInstance,
			   (int *)&sc_status);

	if (__SCDynamicStoreCheckRetryAndHandleError(store,
						     status,
						     &sc_status,
						     "SCDynamicStoreSetValue configset()")) {
		goto retry;
	}

	/* clean up */
	CFRelease(utfKey);
	CFRelease(xmlData);

	if (sc_status != kSCStatusOK) {
		_SCErrorSet(sc_status);
		return FALSE;
	}

	return TRUE;
}