#include <SystemConfiguration/SystemConfiguration.h>
#include <SystemConfiguration/SCPrivate.h>
#include "SCPreferencesInternal.h"
#include "SCHelper_client.h"
#include <unistd.h>
#include <pthread.h>
static Boolean
__SCPreferencesUnlock_helper(SCPreferencesRef prefs)
{
Boolean ok;
SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
uint32_t status = kSCStatusOK;
if (prefsPrivate->helper_port == MACH_PORT_NULL) {
goto fail;
}
ok = _SCHelperExec(prefsPrivate->helper_port,
SCHELPER_MSG_PREFS_UNLOCK,
NULL,
&status,
NULL);
if (!ok) {
goto fail;
}
if (status != kSCStatusOK) {
goto error;
}
prefsPrivate->locked = FALSE;
return TRUE;
fail :
if (prefsPrivate->helper_port != MACH_PORT_NULL) {
_SCHelperClose(&prefsPrivate->helper_port);
}
status = kSCStatusAccessError;
error :
_SCErrorSet(status);
return FALSE;
}
static void
reportDelay(SCPreferencesRef prefs, struct timeval *delay)
{
asl_object_t m;
SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
char str[256];
m = asl_new(ASL_TYPE_MSG);
asl_set(m, "com.apple.message.domain", "com.apple.SystemConfiguration.SCPreferencesUnlock");
(void) _SC_cfstring_to_cstring(prefsPrivate->name, str, sizeof(str), kCFStringEncodingUTF8);
asl_set(m, "com.apple.message.signature", str);
(void) _SC_cfstring_to_cstring(prefsPrivate->prefsID, str, sizeof(str), kCFStringEncodingUTF8);
asl_set(m, "com.apple.message.signature2", str);
(void) snprintf(str, sizeof(str),
"%d.%3.3d",
(int)delay->tv_sec,
delay->tv_usec / 1000);
asl_set(m, "com.apple.message.value", str);
SCLOG(NULL, m, ASL_LEVEL_DEBUG,
CFSTR("SCPreferences(%@:%@) lock held for %d.%3.3d seconds"),
prefsPrivate->name,
prefsPrivate->prefsID,
(int)delay->tv_sec,
delay->tv_usec / 1000);
asl_release(m);
return;
}
Boolean
SCPreferencesUnlock(SCPreferencesRef prefs)
{
struct timeval lockElapsed;
struct timeval lockEnd;
SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
if (prefs == NULL) {
_SCErrorSet(kSCStatusNoPrefsSession);
return FALSE;
}
if (!prefsPrivate->locked) {
_SCErrorSet(kSCStatusNeedLock);
return FALSE;
}
if (prefsPrivate->authorizationData != NULL) {
return __SCPreferencesUnlock_helper(prefs);
}
pthread_mutex_lock(&prefsPrivate->lock);
if (prefsPrivate->sessionKeyLock != NULL) {
SCDynamicStoreRemoveValue(prefsPrivate->session,
prefsPrivate->sessionKeyLock);
}
if (prefsPrivate->lockFD != -1) {
if (prefsPrivate->lockPath != NULL) {
unlink(prefsPrivate->lockPath);
}
close(prefsPrivate->lockFD);
prefsPrivate->lockFD = -1;
}
(void)gettimeofday(&lockEnd, NULL);
timersub(&lockEnd, &prefsPrivate->lockTime, &lockElapsed);
if (lockElapsed.tv_sec > 0) {
reportDelay(prefs, &lockElapsed);
}
prefsPrivate->locked = FALSE;
pthread_mutex_unlock(&prefsPrivate->lock);
return TRUE;
}