2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
27 * Modification History
29 * June 1, 2001 Allan Nathanson <ajn@apple.com>
30 * - public API conversion
32 * November 9, 2000 Allan Nathanson <ajn@apple.com>
36 #include <SystemConfiguration/SystemConfiguration.h>
37 #include <SystemConfiguration/SCValidation.h>
38 #include <SystemConfiguration/SCPrivate.h>
40 #include <mach/mach.h>
41 #include <mach/notify.h>
42 #include <mach/mach_error.h>
49 _SC_cfstring_to_cstring(CFStringRef cfstr
, char *buf
, int bufLen
, CFStringEncoding encoding
)
52 CFIndex len
= CFStringGetLength(cfstr
);
54 /* how much buffer space will we really need? */
55 (void)CFStringGetBytes(cfstr
,
66 buf
= CFAllocatorAllocate(NULL
, bufLen
, 0);
76 (void)CFStringGetBytes(cfstr
,
91 _SCSerialize(CFPropertyListRef obj
, CFDataRef
*xml
, void **dataRef
, CFIndex
*dataLen
)
95 if (!xml
&& !(dataRef
&& dataLen
)) {
96 /* if not keeping track of allocated space */
100 myXml
= CFPropertyListCreateXMLData(NULL
, obj
);
102 SCLog(TRUE
, LOG_ERR
, CFSTR("CFPropertyListCreateXMLData() failed"));
103 if (xml
) *xml
= NULL
;
104 if (dataRef
) *dataRef
= NULL
;
105 if (dataLen
) *dataLen
= 0;
112 *dataRef
= (void *)CFDataGetBytePtr(myXml
);
115 *dataLen
= CFDataGetLength(myXml
);
118 kern_return_t status
;
120 *dataLen
= CFDataGetLength(myXml
);
121 status
= vm_allocate(mach_task_self(), (void *)dataRef
, *dataLen
, TRUE
);
122 if (status
!= KERN_SUCCESS
) {
125 CFSTR("vm_allocate(): %s"),
126 mach_error_string(status
));
133 bcopy((char *)CFDataGetBytePtr(myXml
), *dataRef
, *dataLen
);
142 _SCUnserialize(CFPropertyListRef
*obj
, CFDataRef xml
, void *dataRef
, CFIndex dataLen
)
144 CFStringRef xmlError
;
147 kern_return_t status
;
149 xml
= CFDataCreateWithBytesNoCopy(NULL
, (void *)dataRef
, dataLen
, kCFAllocatorNull
);
150 *obj
= CFPropertyListCreateFromXMLData(NULL
,
152 kCFPropertyListImmutable
,
156 status
= vm_deallocate(mach_task_self(), (vm_address_t
)dataRef
, dataLen
);
157 if (status
!= KERN_SUCCESS
) {
158 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("vm_deallocate(): %s"), mach_error_string(status
));
159 /* non-fatal???, proceed */
162 *obj
= CFPropertyListCreateFromXMLData(NULL
,
164 kCFPropertyListImmutable
,
172 CFSTR("CFPropertyListCreateFromXMLData() failed: %@"),
176 _SCErrorSet(kSCStatusFailed
);
185 _SCSerializeString(CFStringRef str
, CFDataRef
*data
, void **dataRef
, CFIndex
*dataLen
)
189 if (!isA_CFString(str
)) {
190 /* if not a CFString */
194 if (!data
&& !(dataRef
&& dataLen
)) {
195 /* if not keeping track of allocated space */
199 myData
= CFStringCreateExternalRepresentation(NULL
, str
, kCFStringEncodingUTF8
, 0);
201 SCLog(TRUE
, LOG_ERR
, CFSTR("CFStringCreateExternalRepresentation() failed"));
202 if (data
) *data
= NULL
;
203 if (dataRef
) *dataRef
= NULL
;
204 if (dataLen
) *dataLen
= 0;
211 *dataRef
= (void *)CFDataGetBytePtr(myData
);
214 *dataLen
= CFDataGetLength(myData
);
217 kern_return_t status
;
219 *dataLen
= CFDataGetLength(myData
);
220 status
= vm_allocate(mach_task_self(), (void *)dataRef
, *dataLen
, TRUE
);
221 if (status
!= KERN_SUCCESS
) {
224 CFSTR("vm_allocate(): %s"),
225 mach_error_string(status
));
232 bcopy((char *)CFDataGetBytePtr(myData
), *dataRef
, *dataLen
);
241 _SCUnserializeString(CFStringRef
*str
, CFDataRef utf8
, void *dataRef
, CFIndex dataLen
)
244 kern_return_t status
;
246 utf8
= CFDataCreateWithBytesNoCopy(NULL
, dataRef
, dataLen
, kCFAllocatorNull
);
247 *str
= CFStringCreateFromExternalRepresentation(NULL
, utf8
, kCFStringEncodingUTF8
);
250 status
= vm_deallocate(mach_task_self(), (vm_address_t
)dataRef
, dataLen
);
251 if (status
!= KERN_SUCCESS
) {
252 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("vm_deallocate(): %s"), mach_error_string(status
));
253 /* non-fatal???, proceed */
256 *str
= CFStringCreateFromExternalRepresentation(NULL
, utf8
, kCFStringEncodingUTF8
);
260 SCLog(TRUE
, LOG_ERR
, CFSTR("CFStringCreateFromExternalRepresentation() failed"));
269 _SCSerializeData(CFDataRef data
, void **dataRef
, CFIndex
*dataLen
)
271 kern_return_t status
;
273 if (!isA_CFData(data
)) {
274 /* if not a CFData */
278 *dataLen
= CFDataGetLength(data
);
279 status
= vm_allocate(mach_task_self(), (void *)dataRef
, *dataLen
, TRUE
);
280 if (status
!= KERN_SUCCESS
) {
283 CFSTR("vm_allocate(): %s"),
284 mach_error_string(status
));
290 bcopy((char *)CFDataGetBytePtr(data
), *dataRef
, *dataLen
);
297 _SCUnserializeData(CFDataRef
*data
, void *dataRef
, CFIndex dataLen
)
299 kern_return_t status
;
301 *data
= CFDataCreate(NULL
, dataRef
, dataLen
);
302 status
= vm_deallocate(mach_task_self(), (vm_address_t
)dataRef
, dataLen
);
303 if (status
!= KERN_SUCCESS
) {
304 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("vm_deallocate(): %s"), mach_error_string(status
));
305 _SCErrorSet(kSCStatusFailed
);
314 _SCSerializeMultiple(CFDictionaryRef dict
)
316 const void * keys_q
[N_QUICK
];
317 const void ** keys
= keys_q
;
319 CFDictionaryRef newDict
= NULL
;
320 const void * pLists_q
[N_QUICK
];
321 const void ** pLists
= pLists_q
;
322 const void * values_q
[N_QUICK
];
323 const void ** values
= values_q
;
325 nElements
= CFDictionaryGetCount(dict
);
329 if (nElements
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
330 keys
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
331 values
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
332 pLists
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
334 bzero(pLists
, nElements
* sizeof(CFTypeRef
));
336 CFDictionaryGetKeysAndValues(dict
, keys
, values
);
337 for (i
= 0; i
< nElements
; i
++) {
338 if (!_SCSerialize((CFPropertyListRef
)values
[i
], (CFDataRef
*)&pLists
[i
], NULL
, NULL
)) {
344 newDict
= CFDictionaryCreate(NULL
,
348 &kCFTypeDictionaryKeyCallBacks
,
349 &kCFTypeDictionaryValueCallBacks
);
356 for (i
= 0; i
< nElements
; i
++) {
357 if (pLists
[i
]) CFRelease(pLists
[i
]);
360 if (keys
!= keys_q
) {
361 CFAllocatorDeallocate(NULL
, keys
);
362 CFAllocatorDeallocate(NULL
, values
);
363 CFAllocatorDeallocate(NULL
, pLists
);
372 _SCUnserializeMultiple(CFDictionaryRef dict
)
374 const void * keys_q
[N_QUICK
];
375 const void ** keys
= keys_q
;
377 CFDictionaryRef newDict
= NULL
;
378 const void * pLists_q
[N_QUICK
];
379 const void ** pLists
= pLists_q
;
380 const void * values_q
[N_QUICK
];
381 const void ** values
= values_q
;
383 nElements
= CFDictionaryGetCount(dict
);
387 if (nElements
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
388 keys
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
389 values
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
390 pLists
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
392 bzero(pLists
, nElements
* sizeof(CFTypeRef
));
394 CFDictionaryGetKeysAndValues(dict
, keys
, values
);
395 for (i
= 0; i
< nElements
; i
++) {
396 if (!_SCUnserialize((CFPropertyListRef
*)&pLists
[i
], values
[i
], NULL
, NULL
)) {
402 newDict
= CFDictionaryCreate(NULL
,
406 &kCFTypeDictionaryKeyCallBacks
,
407 &kCFTypeDictionaryValueCallBacks
);
414 for (i
= 0; i
< nElements
; i
++) {
415 if (pLists
[i
]) CFRelease(pLists
[i
]);
418 if (keys
!= keys_q
) {
419 CFAllocatorDeallocate(NULL
, keys
);
420 CFAllocatorDeallocate(NULL
, values
);
421 CFAllocatorDeallocate(NULL
, pLists
);
430 __showMachPortStatus()
433 /* print status of in-use mach ports */
435 kern_return_t status
;
436 mach_port_name_array_t ports
;
437 mach_port_type_array_t types
;
439 CFMutableStringRef str
;
441 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("----------"));
443 /* report on ALL mach ports associated with this task */
444 status
= mach_port_names(mach_task_self(), &ports
, &pn
, &types
, &tn
);
445 if (status
== MACH_MSG_SUCCESS
) {
446 str
= CFStringCreateMutable(NULL
, 0);
447 for (pi
= 0; pi
< pn
; pi
++) {
448 char rights
[16], *rp
= &rights
[0];
450 if (types
[pi
] != MACH_PORT_TYPE_NONE
) {
453 if (types
[pi
] & MACH_PORT_TYPE_SEND
)
455 if (types
[pi
] & MACH_PORT_TYPE_RECEIVE
)
457 if (types
[pi
] & MACH_PORT_TYPE_SEND_ONCE
)
459 if (types
[pi
] & MACH_PORT_TYPE_PORT_SET
)
461 if (types
[pi
] & MACH_PORT_TYPE_DEAD_NAME
)
466 CFStringAppendFormat(str
, NULL
, CFSTR(" %d%s"), ports
[pi
], rights
);
468 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("Task ports (n=%d):%@"), pn
, str
);
471 /* log (but ignore) errors */
472 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("mach_port_names(): %s"), mach_error_string(status
));
481 __showMachPortReferences(mach_port_t port
)
484 kern_return_t status
;
485 mach_port_urefs_t refs_send
= 0;
486 mach_port_urefs_t refs_recv
= 0;
487 mach_port_urefs_t refs_once
= 0;
488 mach_port_urefs_t refs_pset
= 0;
489 mach_port_urefs_t refs_dead
= 0;
491 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("user references for mach port %d"), port
);
493 status
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_SEND
, &refs_send
);
494 if (status
!= KERN_SUCCESS
) {
495 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" mach_port_get_refs(MACH_PORT_RIGHT_SEND): %s"), mach_error_string(status
));
499 status
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_RECEIVE
, &refs_recv
);
500 if (status
!= KERN_SUCCESS
) {
501 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" mach_port_get_refs(MACH_PORT_RIGHT_RECEIVE): %s"), mach_error_string(status
));
505 status
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_SEND_ONCE
, &refs_once
);
506 if (status
!= KERN_SUCCESS
) {
507 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" mach_port_get_refs(MACH_PORT_RIGHT_SEND_ONCE): %s"), mach_error_string(status
));
511 status
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_PORT_SET
, &refs_pset
);
512 if (status
!= KERN_SUCCESS
) {
513 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" mach_port_get_refs(MACH_PORT_RIGHT_PORT_SET): %s"), mach_error_string(status
));
517 status
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_DEAD_NAME
, &refs_dead
);
518 if (status
!= KERN_SUCCESS
) {
519 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" mach_port_get_refs(MACH_PORT_RIGHT_DEAD_NAME): %s"), mach_error_string(status
));
523 SCLog(_sc_verbose
, LOG_DEBUG
,
524 CFSTR(" send = %d, receive = %d, send once = %d, port set = %d, dead name = %d"),