2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * June 1, 2001 Allan Nathanson <ajn@apple.com>
28 * - public API conversion
30 * November 9, 2000 Allan Nathanson <ajn@apple.com>
34 #include <SystemConfiguration/SystemConfiguration.h>
35 #include <SystemConfiguration/SCValidation.h>
36 #include <SystemConfiguration/SCPrivate.h>
38 #include <mach/mach.h>
39 #include <mach/notify.h>
40 #include <mach/mach_error.h>
47 _SC_cfstring_to_cstring(CFStringRef cfstr
, char *buf
, int bufLen
, CFStringEncoding encoding
)
50 CFIndex len
= CFStringGetLength(cfstr
);
52 /* how much buffer space will we really need? */
53 (void)CFStringGetBytes(cfstr
,
64 buf
= CFAllocatorAllocate(NULL
, bufLen
, 0);
74 (void)CFStringGetBytes(cfstr
,
89 _SCSerialize(CFPropertyListRef obj
, CFDataRef
*xml
, void **dataRef
, CFIndex
*dataLen
)
93 if (!xml
&& !(dataRef
&& dataLen
)) {
94 /* if not keeping track of allocated space */
98 myXml
= CFPropertyListCreateXMLData(NULL
, obj
);
100 SCLog(TRUE
, LOG_ERR
, CFSTR("CFPropertyListCreateXMLData() failed"));
101 if (xml
) *xml
= NULL
;
102 if (dataRef
) *dataRef
= NULL
;
103 if (dataLen
) *dataLen
= 0;
110 *dataRef
= (void *)CFDataGetBytePtr(myXml
);
113 *dataLen
= CFDataGetLength(myXml
);
116 kern_return_t status
;
118 *dataLen
= CFDataGetLength(myXml
);
119 status
= vm_allocate(mach_task_self(), (void *)dataRef
, *dataLen
, TRUE
);
120 if (status
!= KERN_SUCCESS
) {
123 CFSTR("vm_allocate(): %s"),
124 mach_error_string(status
));
131 bcopy((char *)CFDataGetBytePtr(myXml
), *dataRef
, *dataLen
);
140 _SCUnserialize(CFPropertyListRef
*obj
, CFDataRef xml
, void *dataRef
, CFIndex dataLen
)
142 CFStringRef xmlError
;
145 kern_return_t status
;
147 xml
= CFDataCreateWithBytesNoCopy(NULL
, (void *)dataRef
, dataLen
, kCFAllocatorNull
);
148 *obj
= CFPropertyListCreateFromXMLData(NULL
,
150 kCFPropertyListImmutable
,
154 status
= vm_deallocate(mach_task_self(), (vm_address_t
)dataRef
, dataLen
);
155 if (status
!= KERN_SUCCESS
) {
156 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("vm_deallocate(): %s"), mach_error_string(status
));
157 /* non-fatal???, proceed */
160 *obj
= CFPropertyListCreateFromXMLData(NULL
,
162 kCFPropertyListImmutable
,
170 CFSTR("CFPropertyListCreateFromXMLData() failed: %@"),
174 _SCErrorSet(kSCStatusFailed
);
183 _SCSerializeString(CFStringRef str
, CFDataRef
*data
, void **dataRef
, CFIndex
*dataLen
)
187 if (!isA_CFString(str
)) {
188 /* if not a CFString */
192 if (!data
&& !(dataRef
&& dataLen
)) {
193 /* if not keeping track of allocated space */
197 myData
= CFStringCreateExternalRepresentation(NULL
, str
, kCFStringEncodingUTF8
, 0);
199 SCLog(TRUE
, LOG_ERR
, CFSTR("CFStringCreateExternalRepresentation() failed"));
200 if (data
) *data
= NULL
;
201 if (dataRef
) *dataRef
= NULL
;
202 if (dataLen
) *dataLen
= 0;
209 *dataRef
= (void *)CFDataGetBytePtr(myData
);
212 *dataLen
= CFDataGetLength(myData
);
215 kern_return_t status
;
217 *dataLen
= CFDataGetLength(myData
);
218 status
= vm_allocate(mach_task_self(), (void *)dataRef
, *dataLen
, TRUE
);
219 if (status
!= KERN_SUCCESS
) {
222 CFSTR("vm_allocate(): %s"),
223 mach_error_string(status
));
230 bcopy((char *)CFDataGetBytePtr(myData
), *dataRef
, *dataLen
);
239 _SCUnserializeString(CFStringRef
*str
, CFDataRef utf8
, void *dataRef
, CFIndex dataLen
)
242 kern_return_t status
;
244 utf8
= CFDataCreateWithBytesNoCopy(NULL
, dataRef
, dataLen
, kCFAllocatorNull
);
245 *str
= CFStringCreateFromExternalRepresentation(NULL
, utf8
, kCFStringEncodingUTF8
);
248 status
= vm_deallocate(mach_task_self(), (vm_address_t
)dataRef
, dataLen
);
249 if (status
!= KERN_SUCCESS
) {
250 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("vm_deallocate(): %s"), mach_error_string(status
));
251 /* non-fatal???, proceed */
254 *str
= CFStringCreateFromExternalRepresentation(NULL
, utf8
, kCFStringEncodingUTF8
);
258 SCLog(TRUE
, LOG_ERR
, CFSTR("CFStringCreateFromExternalRepresentation() failed"));
267 _SCSerializeData(CFDataRef data
, void **dataRef
, CFIndex
*dataLen
)
269 kern_return_t status
;
271 if (!isA_CFData(data
)) {
272 /* if not a CFData */
276 *dataLen
= CFDataGetLength(data
);
277 status
= vm_allocate(mach_task_self(), (void *)dataRef
, *dataLen
, TRUE
);
278 if (status
!= KERN_SUCCESS
) {
281 CFSTR("vm_allocate(): %s"),
282 mach_error_string(status
));
288 bcopy((char *)CFDataGetBytePtr(data
), *dataRef
, *dataLen
);
295 _SCUnserializeData(CFDataRef
*data
, void *dataRef
, CFIndex dataLen
)
297 kern_return_t status
;
299 *data
= CFDataCreate(NULL
, dataRef
, dataLen
);
300 status
= vm_deallocate(mach_task_self(), (vm_address_t
)dataRef
, dataLen
);
301 if (status
!= KERN_SUCCESS
) {
302 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("vm_deallocate(): %s"), mach_error_string(status
));
303 _SCErrorSet(kSCStatusFailed
);
312 _SCSerializeMultiple(CFDictionaryRef dict
)
314 const void * keys_q
[N_QUICK
];
315 const void ** keys
= keys_q
;
317 CFDictionaryRef newDict
= NULL
;
318 const void * pLists_q
[N_QUICK
];
319 const void ** pLists
= pLists_q
;
320 const void * values_q
[N_QUICK
];
321 const void ** values
= values_q
;
323 nElements
= CFDictionaryGetCount(dict
);
327 if (nElements
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
328 keys
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
329 values
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
330 pLists
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
332 bzero(pLists
, nElements
* sizeof(CFTypeRef
));
334 CFDictionaryGetKeysAndValues(dict
, keys
, values
);
335 for (i
= 0; i
< nElements
; i
++) {
336 if (!_SCSerialize((CFPropertyListRef
)values
[i
], (CFDataRef
*)&pLists
[i
], NULL
, NULL
)) {
342 newDict
= CFDictionaryCreate(NULL
,
346 &kCFTypeDictionaryKeyCallBacks
,
347 &kCFTypeDictionaryValueCallBacks
);
354 for (i
= 0; i
< nElements
; i
++) {
355 if (pLists
[i
]) CFRelease(pLists
[i
]);
358 if (keys
!= keys_q
) {
359 CFAllocatorDeallocate(NULL
, keys
);
360 CFAllocatorDeallocate(NULL
, values
);
361 CFAllocatorDeallocate(NULL
, pLists
);
370 _SCUnserializeMultiple(CFDictionaryRef dict
)
372 const void * keys_q
[N_QUICK
];
373 const void ** keys
= keys_q
;
375 CFDictionaryRef newDict
= NULL
;
376 const void * pLists_q
[N_QUICK
];
377 const void ** pLists
= pLists_q
;
378 const void * values_q
[N_QUICK
];
379 const void ** values
= values_q
;
381 nElements
= CFDictionaryGetCount(dict
);
385 if (nElements
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
386 keys
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
387 values
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
388 pLists
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
390 bzero(pLists
, nElements
* sizeof(CFTypeRef
));
392 CFDictionaryGetKeysAndValues(dict
, keys
, values
);
393 for (i
= 0; i
< nElements
; i
++) {
394 if (!_SCUnserialize((CFPropertyListRef
*)&pLists
[i
], values
[i
], NULL
, NULL
)) {
400 newDict
= CFDictionaryCreate(NULL
,
404 &kCFTypeDictionaryKeyCallBacks
,
405 &kCFTypeDictionaryValueCallBacks
);
412 for (i
= 0; i
< nElements
; i
++) {
413 if (pLists
[i
]) CFRelease(pLists
[i
]);
416 if (keys
!= keys_q
) {
417 CFAllocatorDeallocate(NULL
, keys
);
418 CFAllocatorDeallocate(NULL
, values
);
419 CFAllocatorDeallocate(NULL
, pLists
);
428 __showMachPortStatus()
431 /* print status of in-use mach ports */
433 kern_return_t status
;
434 mach_port_name_array_t ports
;
435 mach_port_type_array_t types
;
437 CFMutableStringRef str
;
439 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("----------"));
441 /* report on ALL mach ports associated with this task */
442 status
= mach_port_names(mach_task_self(), &ports
, &pn
, &types
, &tn
);
443 if (status
== MACH_MSG_SUCCESS
) {
444 str
= CFStringCreateMutable(NULL
, 0);
445 for (pi
= 0; pi
< pn
; pi
++) {
446 char rights
[16], *rp
= &rights
[0];
448 if (types
[pi
] != MACH_PORT_TYPE_NONE
) {
451 if (types
[pi
] & MACH_PORT_TYPE_SEND
)
453 if (types
[pi
] & MACH_PORT_TYPE_RECEIVE
)
455 if (types
[pi
] & MACH_PORT_TYPE_SEND_ONCE
)
457 if (types
[pi
] & MACH_PORT_TYPE_PORT_SET
)
459 if (types
[pi
] & MACH_PORT_TYPE_DEAD_NAME
)
464 CFStringAppendFormat(str
, NULL
, CFSTR(" %d%s"), ports
[pi
], rights
);
466 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("Task ports (n=%d):%@"), pn
, str
);
469 /* log (but ignore) errors */
470 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("mach_port_names(): %s"), mach_error_string(status
));
479 __showMachPortReferences(mach_port_t port
)
482 kern_return_t status
;
483 mach_port_urefs_t refs_send
= 0;
484 mach_port_urefs_t refs_recv
= 0;
485 mach_port_urefs_t refs_once
= 0;
486 mach_port_urefs_t refs_pset
= 0;
487 mach_port_urefs_t refs_dead
= 0;
489 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("user references for mach port %d"), port
);
491 status
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_SEND
, &refs_send
);
492 if (status
!= KERN_SUCCESS
) {
493 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" mach_port_get_refs(MACH_PORT_RIGHT_SEND): %s"), mach_error_string(status
));
497 status
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_RECEIVE
, &refs_recv
);
498 if (status
!= KERN_SUCCESS
) {
499 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" mach_port_get_refs(MACH_PORT_RIGHT_RECEIVE): %s"), mach_error_string(status
));
503 status
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_SEND_ONCE
, &refs_once
);
504 if (status
!= KERN_SUCCESS
) {
505 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" mach_port_get_refs(MACH_PORT_RIGHT_SEND_ONCE): %s"), mach_error_string(status
));
509 status
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_PORT_SET
, &refs_pset
);
510 if (status
!= KERN_SUCCESS
) {
511 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" mach_port_get_refs(MACH_PORT_RIGHT_PORT_SET): %s"), mach_error_string(status
));
515 status
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_DEAD_NAME
, &refs_dead
);
516 if (status
!= KERN_SUCCESS
) {
517 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" mach_port_get_refs(MACH_PORT_RIGHT_DEAD_NAME): %s"), mach_error_string(status
));
521 SCLog(_sc_verbose
, LOG_DEBUG
,
522 CFSTR(" send = %d, receive = %d, send once = %d, port set = %d, dead name = %d"),