#include <fcntl.h>
#include <paths.h>
#include <unistd.h>
#include "configd.h"
#include "configd_server.h"
#include "session.h"
#include "plugin_support.h"
#define SNAPSHOT_PATH_STATE _PATH_VARTMP "configd-state"
#define SNAPSHOT_PATH_STORE _PATH_VARTMP "configd-store.plist"
#define SNAPSHOT_PATH_PATTERN _PATH_VARTMP "configd-pattern.plist"
#define SNAPSHOT_PATH_SESSION _PATH_VARTMP "configd-session.plist"
#define N_QUICK 100
static CF_RETURNS_RETAINED CFDictionaryRef
_expandStore(CFDictionaryRef storeData)
{
const void * keys_q[N_QUICK];
const void ** keys = keys_q;
CFIndex nElements;
CFDictionaryRef newStoreData = NULL;
const void * nValues_q[N_QUICK];
const void ** nValues = nValues_q;
const void * oValues_q[N_QUICK];
const void ** oValues = oValues_q;
nElements = CFDictionaryGetCount(storeData);
if (nElements > 0) {
CFIndex i;
if (nElements > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
keys = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0);
oValues = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0);
nValues = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0);
}
bzero(nValues, nElements * sizeof(CFTypeRef));
CFDictionaryGetKeysAndValues(storeData, keys, oValues);
for (i = 0; i < nElements; i++) {
CFDataRef data;
data = CFDictionaryGetValue(oValues[i], kSCDData);
if (data) {
CFPropertyListRef plist;
nValues[i] = CFDictionaryCreateMutableCopy(NULL, 0, oValues[i]);
_SCUnserialize(&plist, data, NULL, 0);
CFDictionarySetValue((CFMutableDictionaryRef)nValues[i],
kSCDData,
plist);
CFRelease(plist);
} else {
nValues[i] = CFRetain(oValues[i]);
}
}
}
newStoreData = CFDictionaryCreate(NULL,
keys,
nValues,
nElements,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (nElements > 0) {
CFIndex i;
for (i = 0; i < nElements; i++) {
CFRelease(nValues[i]);
}
if (keys != keys_q) {
CFAllocatorDeallocate(NULL, keys);
CFAllocatorDeallocate(NULL, oValues);
CFAllocatorDeallocate(NULL, nValues);
}
}
return newStoreData;
}
__private_extern__
int
__SCDynamicStoreSnapshot(SCDynamicStoreRef store)
{
CFDictionaryRef expandedStoreData;
FILE *f;
int fd;
CFDataRef xmlData;
(void) unlink(SNAPSHOT_PATH_STATE);
fd = open(SNAPSHOT_PATH_STATE, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644);
if (fd == -1) {
return kSCStatusFailed;
}
f = fdopen(fd, "w");
if (f == NULL) {
return kSCStatusFailed;
}
SCPrint(TRUE, f, CFSTR("Main thread :\n\n"));
SCPrint(TRUE, f, CFSTR("%@\n"), CFRunLoopGetCurrent());
if (plugin_runLoop != NULL) {
SCPrint(TRUE, f, CFSTR("Plug-in thread :\n\n"));
SCPrint(TRUE, f, CFSTR("%@\n"), plugin_runLoop);
}
listSessions(f);
(void) fclose(f);
(void) unlink(SNAPSHOT_PATH_STORE);
fd = open(SNAPSHOT_PATH_STORE, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644);
if (fd == -1) {
return kSCStatusFailed;
}
expandedStoreData = _expandStore(storeData);
xmlData = CFPropertyListCreateData(NULL, expandedStoreData, kCFPropertyListXMLFormat_v1_0, 0, NULL);
CFRelease(expandedStoreData);
if (xmlData == NULL) {
SC_log(LOG_NOTICE, "CFPropertyListCreateData() failed");
close(fd);
return kSCStatusFailed;
}
(void) write(fd, CFDataGetBytePtr(xmlData), CFDataGetLength(xmlData));
(void) close(fd);
CFRelease(xmlData);
(void) unlink(SNAPSHOT_PATH_PATTERN);
fd = open(SNAPSHOT_PATH_PATTERN, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644);
if (fd == -1) {
return kSCStatusFailed;
}
xmlData = CFPropertyListCreateData(NULL, patternData, kCFPropertyListXMLFormat_v1_0, 0, NULL);
if (xmlData == NULL) {
SC_log(LOG_NOTICE, "CFPropertyListCreateData() failed");
close(fd);
return kSCStatusFailed;
}
(void) write(fd, CFDataGetBytePtr(xmlData), CFDataGetLength(xmlData));
(void) close(fd);
CFRelease(xmlData);
(void) unlink(SNAPSHOT_PATH_SESSION);
fd = open(SNAPSHOT_PATH_SESSION, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644);
if (fd == -1) {
return kSCStatusFailed;
}
xmlData = CFPropertyListCreateData(NULL, sessionData, kCFPropertyListXMLFormat_v1_0, 0, NULL);
if (xmlData == NULL) {
SC_log(LOG_NOTICE, "CFPropertyListCreateData() failed");
close(fd);
return kSCStatusFailed;
}
(void) write(fd, CFDataGetBytePtr(xmlData), CFDataGetLength(xmlData));
(void) close(fd);
CFRelease(xmlData);
return kSCStatusOK;
}
__private_extern__
kern_return_t
_snapshot(mach_port_t server, int *sc_status, audit_token_t audit_token)
{
serverSessionRef mySession;
mySession = getSession(server);
if (mySession == NULL) {
mySession = tempSession(server, CFSTR("SCDynamicStoreSnapshot"), audit_token);
if (mySession == NULL) {
return kSCStatusNoStoreSession;
}
}
if (!hasRootAccess(mySession)) {
return kSCStatusAccessError;
}
*sc_status = __SCDynamicStoreSnapshot(mySession->store);
return KERN_SUCCESS;
}