1/* 2 * Copyright (c) 2000-2006, 2009-2011 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24/* 25 * Modification History 26 * 27 * June 1, 2001 Allan Nathanson <ajn@apple.com> 28 * - public API conversion 29 * 30 * April 14, 2000 Allan Nathanson <ajn@apple.com> 31 * - initial revision 32 */ 33 34#include <fcntl.h> 35#include <paths.h> 36#include <unistd.h> 37 38#include "configd.h" 39#include "configd_server.h" 40#include "session.h" 41#include "plugin_support.h" 42 43 44#define SNAPSHOT_PATH_STATE _PATH_VARTMP "configd-state" 45#define SNAPSHOT_PATH_STORE _PATH_VARTMP "configd-store.plist" 46#define SNAPSHOT_PATH_PATTERN _PATH_VARTMP "configd-pattern.plist" 47#define SNAPSHOT_PATH_SESSION _PATH_VARTMP "configd-session.plist" 48 49 50#define N_QUICK 100 51 52static CF_RETURNS_RETAINED CFDictionaryRef 53_expandStore(CFDictionaryRef storeData) 54{ 55 const void * keys_q[N_QUICK]; 56 const void ** keys = keys_q; 57 CFIndex nElements; 58 CFDictionaryRef newStoreData = NULL; 59 const void * nValues_q[N_QUICK]; 60 const void ** nValues = nValues_q; 61 const void * oValues_q[N_QUICK]; 62 const void ** oValues = oValues_q; 63 64 nElements = CFDictionaryGetCount(storeData); 65 if (nElements > 0) { 66 CFIndex i; 67 68 if (nElements > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { 69 keys = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); 70 oValues = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); 71 nValues = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); 72 } 73 bzero(nValues, nElements * sizeof(CFTypeRef)); 74 75 CFDictionaryGetKeysAndValues(storeData, keys, oValues); 76 for (i = 0; i < nElements; i++) { 77 CFDataRef data; 78 79 data = CFDictionaryGetValue(oValues[i], kSCDData); 80 if (data) { 81 CFPropertyListRef plist; 82 83 nValues[i] = CFDictionaryCreateMutableCopy(NULL, 0, oValues[i]); 84 85 _SCUnserialize(&plist, data, NULL, 0); 86 CFDictionarySetValue((CFMutableDictionaryRef)nValues[i], 87 kSCDData, 88 plist); 89 CFRelease(plist); 90 } else { 91 nValues[i] = CFRetain(oValues[i]); 92 } 93 } 94 } 95 96 newStoreData = CFDictionaryCreate(NULL, 97 keys, 98 nValues, 99 nElements, 100 &kCFTypeDictionaryKeyCallBacks, 101 &kCFTypeDictionaryValueCallBacks); 102 103 if (nElements > 0) { 104 CFIndex i; 105 106 for (i = 0; i < nElements; i++) { 107 CFRelease(nValues[i]); 108 } 109 110 if (keys != keys_q) { 111 CFAllocatorDeallocate(NULL, keys); 112 CFAllocatorDeallocate(NULL, oValues); 113 CFAllocatorDeallocate(NULL, nValues); 114 } 115 } 116 117 return newStoreData; 118} 119 120 121__private_extern__ 122int 123__SCDynamicStoreSnapshot(SCDynamicStoreRef store) 124{ 125 CFDictionaryRef expandedStoreData; 126 FILE *f; 127 int fd; 128 CFDataRef xmlData; 129 130 /* Save a snapshot of configd's "state" */ 131 132 (void) unlink(SNAPSHOT_PATH_STATE); 133 fd = open(SNAPSHOT_PATH_STATE, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644); 134 if (fd == -1) { 135 return kSCStatusFailed; 136 } 137 f = fdopen(fd, "w"); 138 if (f == NULL) { 139 return kSCStatusFailed; 140 } 141 SCPrint(TRUE, f, CFSTR("Main thread :\n\n")); 142 SCPrint(TRUE, f, CFSTR("%@\n"), CFRunLoopGetCurrent()); 143 if (plugin_runLoop != NULL) { 144 SCPrint(TRUE, f, CFSTR("Plug-in thread :\n\n")); 145 SCPrint(TRUE, f, CFSTR("%@\n"), plugin_runLoop); 146 } 147 listSessions(f); 148 (void) fclose(f); 149 150 /* Save a snapshot of the "store" data */ 151 152 (void) unlink(SNAPSHOT_PATH_STORE); 153 fd = open(SNAPSHOT_PATH_STORE, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644); 154 if (fd == -1) { 155 return kSCStatusFailed; 156 } 157 158 expandedStoreData = _expandStore(storeData); 159 xmlData = CFPropertyListCreateData(NULL, expandedStoreData, kCFPropertyListXMLFormat_v1_0, 0, NULL); 160 CFRelease(expandedStoreData); 161 if (xmlData == NULL) { 162 SCLog(TRUE, LOG_ERR, CFSTR("__SCDynamicStoreSnapshot CFPropertyListCreateData() failed")); 163 close(fd); 164 return kSCStatusFailed; 165 } 166 (void) write(fd, CFDataGetBytePtr(xmlData), CFDataGetLength(xmlData)); 167 (void) close(fd); 168 CFRelease(xmlData); 169 170 /* Save a snapshot of the "pattern" data */ 171 172 (void) unlink(SNAPSHOT_PATH_PATTERN); 173 fd = open(SNAPSHOT_PATH_PATTERN, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644); 174 if (fd == -1) { 175 return kSCStatusFailed; 176 } 177 178 xmlData = CFPropertyListCreateData(NULL, patternData, kCFPropertyListXMLFormat_v1_0, 0, NULL); 179 if (xmlData == NULL) { 180 SCLog(TRUE, LOG_ERR, CFSTR("__SCDynamicStoreSnapshot CFPropertyListCreateData() failed")); 181 close(fd); 182 return kSCStatusFailed; 183 } 184 (void) write(fd, CFDataGetBytePtr(xmlData), CFDataGetLength(xmlData)); 185 (void) close(fd); 186 CFRelease(xmlData); 187 188 /* Save a snapshot of the "session" data */ 189 190 (void) unlink(SNAPSHOT_PATH_SESSION); 191 fd = open(SNAPSHOT_PATH_SESSION, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644); 192 if (fd == -1) { 193 return kSCStatusFailed; 194 } 195 196 xmlData = CFPropertyListCreateData(NULL, sessionData, kCFPropertyListXMLFormat_v1_0, 0, NULL); 197 if (xmlData == NULL) { 198 SCLog(TRUE, LOG_ERR, CFSTR("__SCDynamicStoreSnapshot CFPropertyListCreateData() failed")); 199 close(fd); 200 return kSCStatusFailed; 201 } 202 (void) write(fd, CFDataGetBytePtr(xmlData), CFDataGetLength(xmlData)); 203 (void) close(fd); 204 CFRelease(xmlData); 205 206 return kSCStatusOK; 207} 208 209 210__private_extern__ 211kern_return_t 212_snapshot(mach_port_t server, int *sc_status, audit_token_t audit_token) 213{ 214 serverSessionRef mySession; 215 216 mySession = getSession(server); 217 if (mySession == NULL) { 218 mySession = tempSession(server, CFSTR("SCDynamicStoreSnapshot"), audit_token); 219 if (mySession == NULL) { 220 /* you must have an open session to play */ 221 return kSCStatusNoStoreSession; 222 } 223 } 224 225 if (!hasRootAccess(mySession)) { 226 return kSCStatusAccessError; 227 } 228 229 *sc_status = __SCDynamicStoreSnapshot(mySession->store); 230 return KERN_SUCCESS; 231} 232