xref: /xnu-8020.140.41/libkern/c++/OSData.cpp (revision 27b03b360a988dfd3dfdf34262bb0042026747cc)
1*27b03b36SApple OSS Distributions /*
2*27b03b36SApple OSS Distributions  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3*27b03b36SApple OSS Distributions  *
4*27b03b36SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*27b03b36SApple OSS Distributions  *
6*27b03b36SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*27b03b36SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*27b03b36SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*27b03b36SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*27b03b36SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*27b03b36SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*27b03b36SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*27b03b36SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*27b03b36SApple OSS Distributions  *
15*27b03b36SApple OSS Distributions  * Please obtain a copy of the License at
16*27b03b36SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*27b03b36SApple OSS Distributions  *
18*27b03b36SApple OSS Distributions  * The Original Code and all software distributed under the License are
19*27b03b36SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*27b03b36SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*27b03b36SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*27b03b36SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*27b03b36SApple OSS Distributions  * Please see the License for the specific language governing rights and
24*27b03b36SApple OSS Distributions  * limitations under the License.
25*27b03b36SApple OSS Distributions  *
26*27b03b36SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*27b03b36SApple OSS Distributions  */
28*27b03b36SApple OSS Distributions /* IOData.m created by rsulack on Thu 25-Sep-1997 */
29*27b03b36SApple OSS Distributions 
30*27b03b36SApple OSS Distributions #include <string.h>
31*27b03b36SApple OSS Distributions 
32*27b03b36SApple OSS Distributions #include <vm/vm_kern.h>
33*27b03b36SApple OSS Distributions 
34*27b03b36SApple OSS Distributions #define IOKIT_ENABLE_SHARED_PTR
35*27b03b36SApple OSS Distributions 
36*27b03b36SApple OSS Distributions #include <libkern/c++/OSData.h>
37*27b03b36SApple OSS Distributions #include <libkern/c++/OSSerialize.h>
38*27b03b36SApple OSS Distributions #include <libkern/c++/OSLib.h>
39*27b03b36SApple OSS Distributions #include <libkern/c++/OSString.h>
40*27b03b36SApple OSS Distributions #include <IOKit/IOLib.h>
41*27b03b36SApple OSS Distributions 
42*27b03b36SApple OSS Distributions #define super OSObject
43*27b03b36SApple OSS Distributions 
44*27b03b36SApple OSS Distributions OSDefineMetaClassAndStructorsWithZone(OSData, OSObject, ZC_ZFREE_CLEARMEM)
45*27b03b36SApple OSS Distributions OSMetaClassDefineReservedUsedX86(OSData, 0);    // setDeallocFunction
46*27b03b36SApple OSS Distributions OSMetaClassDefineReservedUnused(OSData, 1);
47*27b03b36SApple OSS Distributions OSMetaClassDefineReservedUnused(OSData, 2);
48*27b03b36SApple OSS Distributions OSMetaClassDefineReservedUnused(OSData, 3);
49*27b03b36SApple OSS Distributions OSMetaClassDefineReservedUnused(OSData, 4);
50*27b03b36SApple OSS Distributions OSMetaClassDefineReservedUnused(OSData, 5);
51*27b03b36SApple OSS Distributions OSMetaClassDefineReservedUnused(OSData, 6);
52*27b03b36SApple OSS Distributions OSMetaClassDefineReservedUnused(OSData, 7);
53*27b03b36SApple OSS Distributions 
54*27b03b36SApple OSS Distributions #define EXTERNAL ((unsigned int) -1)
55*27b03b36SApple OSS Distributions 
56*27b03b36SApple OSS Distributions bool
initWithCapacity(unsigned int inCapacity)57*27b03b36SApple OSS Distributions OSData::initWithCapacity(unsigned int inCapacity)
58*27b03b36SApple OSS Distributions {
59*27b03b36SApple OSS Distributions 	struct kalloc_result kr;
60*27b03b36SApple OSS Distributions 	bool success = true;
61*27b03b36SApple OSS Distributions 
62*27b03b36SApple OSS Distributions 	if (!super::init()) {
63*27b03b36SApple OSS Distributions 		return false;
64*27b03b36SApple OSS Distributions 	}
65*27b03b36SApple OSS Distributions 
66*27b03b36SApple OSS Distributions 	/*
67*27b03b36SApple OSS Distributions 	 * OSData use of Z_MAY_COPYINMAP serves 2 purpposes:
68*27b03b36SApple OSS Distributions 	 *
69*27b03b36SApple OSS Distributions 	 * - It makes sure than when it goes to the VM, it uses its own object
70*27b03b36SApple OSS Distributions 	 *   rather than the kernel object so that vm_map_copyin() can be used.
71*27b03b36SApple OSS Distributions 	 *
72*27b03b36SApple OSS Distributions 	 * - On Intel, it goes to the VM for any size >= PAGE_SIZE to maintain
73*27b03b36SApple OSS Distributions 	 *   old (inefficient) ABI. On arm64 it will use kalloc_data() instead
74*27b03b36SApple OSS Distributions 	 *   until the vm_map_copy_t msg_ool_size_small threshold for copies.
75*27b03b36SApple OSS Distributions 	 */
76*27b03b36SApple OSS Distributions 
77*27b03b36SApple OSS Distributions 	if (inCapacity == 0) {
78*27b03b36SApple OSS Distributions 		if (capacity) {
79*27b03b36SApple OSS Distributions 			OSCONTAINER_ACCUMSIZE(-(size_t)capacity);
80*27b03b36SApple OSS Distributions 			/* can't use kfree() as we need to pass Z_MAY_COPYINMAP */
81*27b03b36SApple OSS Distributions 			__kheap_realloc(KHEAP_DATA_BUFFERS, data, capacity, 0,
82*27b03b36SApple OSS Distributions 			    Z_VM_TAG_BT(Z_WAITOK_ZERO | Z_MAY_COPYINMAP,
83*27b03b36SApple OSS Distributions 			    VM_KERN_MEMORY_LIBKERN), (void *)&this->data);
84*27b03b36SApple OSS Distributions 			data     = nullptr;
85*27b03b36SApple OSS Distributions 			capacity = 0;
86*27b03b36SApple OSS Distributions 		}
87*27b03b36SApple OSS Distributions 	} else if (inCapacity <= capacity) {
88*27b03b36SApple OSS Distributions 		/*
89*27b03b36SApple OSS Distributions 		 * Nothing to change
90*27b03b36SApple OSS Distributions 		 */
91*27b03b36SApple OSS Distributions 	} else {
92*27b03b36SApple OSS Distributions 		if (inCapacity >= PAGE_SIZE) {
93*27b03b36SApple OSS Distributions 			inCapacity = (uint32_t)round_page(inCapacity);
94*27b03b36SApple OSS Distributions 		}
95*27b03b36SApple OSS Distributions 		kr = kalloc_ext(KHEAP_DATA_BUFFERS, inCapacity,
96*27b03b36SApple OSS Distributions 		    Z_VM_TAG_BT(Z_WAITOK_ZERO | Z_MAY_COPYINMAP,
97*27b03b36SApple OSS Distributions 		    VM_KERN_MEMORY_LIBKERN), (void *)&this->data);
98*27b03b36SApple OSS Distributions 
99*27b03b36SApple OSS Distributions 		if (kr.addr) {
100*27b03b36SApple OSS Distributions 			size_t delta = 0;
101*27b03b36SApple OSS Distributions 
102*27b03b36SApple OSS Distributions 			data     = kr.addr;
103*27b03b36SApple OSS Distributions 			delta   -= capacity;
104*27b03b36SApple OSS Distributions 			capacity = (uint32_t)MIN(kr.size, UINT32_MAX);
105*27b03b36SApple OSS Distributions 			delta   += capacity;
106*27b03b36SApple OSS Distributions 			OSCONTAINER_ACCUMSIZE(delta);
107*27b03b36SApple OSS Distributions 		} else {
108*27b03b36SApple OSS Distributions 			success = false;
109*27b03b36SApple OSS Distributions 		}
110*27b03b36SApple OSS Distributions 	}
111*27b03b36SApple OSS Distributions 
112*27b03b36SApple OSS Distributions 	length = 0;
113*27b03b36SApple OSS Distributions 	capacityIncrement = MAX(16, inCapacity);
114*27b03b36SApple OSS Distributions 
115*27b03b36SApple OSS Distributions 	return success;
116*27b03b36SApple OSS Distributions }
117*27b03b36SApple OSS Distributions 
118*27b03b36SApple OSS Distributions bool
initWithBytes(const void * bytes,unsigned int inLength)119*27b03b36SApple OSS Distributions OSData::initWithBytes(const void *bytes, unsigned int inLength)
120*27b03b36SApple OSS Distributions {
121*27b03b36SApple OSS Distributions 	if ((inLength && !bytes) || !initWithCapacity(inLength)) {
122*27b03b36SApple OSS Distributions 		return false;
123*27b03b36SApple OSS Distributions 	}
124*27b03b36SApple OSS Distributions 
125*27b03b36SApple OSS Distributions 	if (bytes != data) {
126*27b03b36SApple OSS Distributions 		bcopy(bytes, data, inLength);
127*27b03b36SApple OSS Distributions 	}
128*27b03b36SApple OSS Distributions 	length = inLength;
129*27b03b36SApple OSS Distributions 
130*27b03b36SApple OSS Distributions 	return true;
131*27b03b36SApple OSS Distributions }
132*27b03b36SApple OSS Distributions 
133*27b03b36SApple OSS Distributions bool
initWithBytesNoCopy(void * bytes,unsigned int inLength)134*27b03b36SApple OSS Distributions OSData::initWithBytesNoCopy(void *bytes, unsigned int inLength)
135*27b03b36SApple OSS Distributions {
136*27b03b36SApple OSS Distributions 	if (!super::init()) {
137*27b03b36SApple OSS Distributions 		return false;
138*27b03b36SApple OSS Distributions 	}
139*27b03b36SApple OSS Distributions 
140*27b03b36SApple OSS Distributions 	length = inLength;
141*27b03b36SApple OSS Distributions 	capacity = EXTERNAL;
142*27b03b36SApple OSS Distributions 	data = bytes;
143*27b03b36SApple OSS Distributions 
144*27b03b36SApple OSS Distributions 	return true;
145*27b03b36SApple OSS Distributions }
146*27b03b36SApple OSS Distributions 
147*27b03b36SApple OSS Distributions bool
initWithData(const OSData * inData)148*27b03b36SApple OSS Distributions OSData::initWithData(const OSData *inData)
149*27b03b36SApple OSS Distributions {
150*27b03b36SApple OSS Distributions 	return initWithBytes(inData->data, inData->length);
151*27b03b36SApple OSS Distributions }
152*27b03b36SApple OSS Distributions 
153*27b03b36SApple OSS Distributions bool
initWithData(const OSData * inData,unsigned int start,unsigned int inLength)154*27b03b36SApple OSS Distributions OSData::initWithData(const OSData *inData,
155*27b03b36SApple OSS Distributions     unsigned int start, unsigned int inLength)
156*27b03b36SApple OSS Distributions {
157*27b03b36SApple OSS Distributions 	const void *localData = inData->getBytesNoCopy(start, inLength);
158*27b03b36SApple OSS Distributions 
159*27b03b36SApple OSS Distributions 	if (localData) {
160*27b03b36SApple OSS Distributions 		return initWithBytes(localData, inLength);
161*27b03b36SApple OSS Distributions 	} else {
162*27b03b36SApple OSS Distributions 		return false;
163*27b03b36SApple OSS Distributions 	}
164*27b03b36SApple OSS Distributions }
165*27b03b36SApple OSS Distributions 
166*27b03b36SApple OSS Distributions OSSharedPtr<OSData>
withCapacity(unsigned int inCapacity)167*27b03b36SApple OSS Distributions OSData::withCapacity(unsigned int inCapacity)
168*27b03b36SApple OSS Distributions {
169*27b03b36SApple OSS Distributions 	OSSharedPtr<OSData> me = OSMakeShared<OSData>();
170*27b03b36SApple OSS Distributions 
171*27b03b36SApple OSS Distributions 	if (me && !me->initWithCapacity(inCapacity)) {
172*27b03b36SApple OSS Distributions 		return nullptr;
173*27b03b36SApple OSS Distributions 	}
174*27b03b36SApple OSS Distributions 
175*27b03b36SApple OSS Distributions 	return me;
176*27b03b36SApple OSS Distributions }
177*27b03b36SApple OSS Distributions 
178*27b03b36SApple OSS Distributions OSSharedPtr<OSData>
withBytes(const void * bytes,unsigned int inLength)179*27b03b36SApple OSS Distributions OSData::withBytes(const void *bytes, unsigned int inLength)
180*27b03b36SApple OSS Distributions {
181*27b03b36SApple OSS Distributions 	OSSharedPtr<OSData> me = OSMakeShared<OSData>();
182*27b03b36SApple OSS Distributions 
183*27b03b36SApple OSS Distributions 	if (me && !me->initWithBytes(bytes, inLength)) {
184*27b03b36SApple OSS Distributions 		return nullptr;
185*27b03b36SApple OSS Distributions 	}
186*27b03b36SApple OSS Distributions 	return me;
187*27b03b36SApple OSS Distributions }
188*27b03b36SApple OSS Distributions 
189*27b03b36SApple OSS Distributions OSSharedPtr<OSData>
withBytesNoCopy(void * bytes,unsigned int inLength)190*27b03b36SApple OSS Distributions OSData::withBytesNoCopy(void *bytes, unsigned int inLength)
191*27b03b36SApple OSS Distributions {
192*27b03b36SApple OSS Distributions 	OSSharedPtr<OSData> me = OSMakeShared<OSData>();
193*27b03b36SApple OSS Distributions 
194*27b03b36SApple OSS Distributions 	if (me && !me->initWithBytesNoCopy(bytes, inLength)) {
195*27b03b36SApple OSS Distributions 		return nullptr;
196*27b03b36SApple OSS Distributions 	}
197*27b03b36SApple OSS Distributions 
198*27b03b36SApple OSS Distributions 	return me;
199*27b03b36SApple OSS Distributions }
200*27b03b36SApple OSS Distributions 
201*27b03b36SApple OSS Distributions OSSharedPtr<OSData>
withData(const OSData * inData)202*27b03b36SApple OSS Distributions OSData::withData(const OSData *inData)
203*27b03b36SApple OSS Distributions {
204*27b03b36SApple OSS Distributions 	OSSharedPtr<OSData> me = OSMakeShared<OSData>();
205*27b03b36SApple OSS Distributions 
206*27b03b36SApple OSS Distributions 	if (me && !me->initWithData(inData)) {
207*27b03b36SApple OSS Distributions 		return nullptr;
208*27b03b36SApple OSS Distributions 	}
209*27b03b36SApple OSS Distributions 
210*27b03b36SApple OSS Distributions 	return me;
211*27b03b36SApple OSS Distributions }
212*27b03b36SApple OSS Distributions 
213*27b03b36SApple OSS Distributions OSSharedPtr<OSData>
withData(const OSData * inData,unsigned int start,unsigned int inLength)214*27b03b36SApple OSS Distributions OSData::withData(const OSData *inData,
215*27b03b36SApple OSS Distributions     unsigned int start, unsigned int inLength)
216*27b03b36SApple OSS Distributions {
217*27b03b36SApple OSS Distributions 	OSSharedPtr<OSData> me = OSMakeShared<OSData>();
218*27b03b36SApple OSS Distributions 
219*27b03b36SApple OSS Distributions 	if (me && !me->initWithData(inData, start, inLength)) {
220*27b03b36SApple OSS Distributions 		return nullptr;
221*27b03b36SApple OSS Distributions 	}
222*27b03b36SApple OSS Distributions 
223*27b03b36SApple OSS Distributions 	return me;
224*27b03b36SApple OSS Distributions }
225*27b03b36SApple OSS Distributions 
226*27b03b36SApple OSS Distributions void
free()227*27b03b36SApple OSS Distributions OSData::free()
228*27b03b36SApple OSS Distributions {
229*27b03b36SApple OSS Distributions 	if ((capacity != EXTERNAL) && data && capacity) {
230*27b03b36SApple OSS Distributions 		/* can't use kfree() as we need to pass Z_MAY_COPYINMAP */
231*27b03b36SApple OSS Distributions 		__kheap_realloc(KHEAP_DATA_BUFFERS, data, capacity, 0,
232*27b03b36SApple OSS Distributions 		    Z_VM_TAG_BT(Z_WAITOK_ZERO | Z_FULLSIZE | Z_MAY_COPYINMAP,
233*27b03b36SApple OSS Distributions 		    VM_KERN_MEMORY_LIBKERN), (void *)&this->data);
234*27b03b36SApple OSS Distributions 		OSCONTAINER_ACCUMSIZE( -((size_t)capacity));
235*27b03b36SApple OSS Distributions 	} else if (capacity == EXTERNAL) {
236*27b03b36SApple OSS Distributions 		DeallocFunction freemem = reserved ? reserved->deallocFunction : NULL;
237*27b03b36SApple OSS Distributions 		if (freemem && data && length) {
238*27b03b36SApple OSS Distributions 			freemem(data, length);
239*27b03b36SApple OSS Distributions 		}
240*27b03b36SApple OSS Distributions 	}
241*27b03b36SApple OSS Distributions 	if (reserved) {
242*27b03b36SApple OSS Distributions 		kfree_type(ExpansionData, reserved);
243*27b03b36SApple OSS Distributions 	}
244*27b03b36SApple OSS Distributions 	super::free();
245*27b03b36SApple OSS Distributions }
246*27b03b36SApple OSS Distributions 
247*27b03b36SApple OSS Distributions unsigned int
getLength() const248*27b03b36SApple OSS Distributions OSData::getLength() const
249*27b03b36SApple OSS Distributions {
250*27b03b36SApple OSS Distributions 	return length;
251*27b03b36SApple OSS Distributions }
252*27b03b36SApple OSS Distributions unsigned int
getCapacity() const253*27b03b36SApple OSS Distributions OSData::getCapacity() const
254*27b03b36SApple OSS Distributions {
255*27b03b36SApple OSS Distributions 	return capacity;
256*27b03b36SApple OSS Distributions }
257*27b03b36SApple OSS Distributions 
258*27b03b36SApple OSS Distributions unsigned int
getCapacityIncrement() const259*27b03b36SApple OSS Distributions OSData::getCapacityIncrement() const
260*27b03b36SApple OSS Distributions {
261*27b03b36SApple OSS Distributions 	return capacityIncrement;
262*27b03b36SApple OSS Distributions }
263*27b03b36SApple OSS Distributions 
264*27b03b36SApple OSS Distributions unsigned int
setCapacityIncrement(unsigned increment)265*27b03b36SApple OSS Distributions OSData::setCapacityIncrement(unsigned increment)
266*27b03b36SApple OSS Distributions {
267*27b03b36SApple OSS Distributions 	return capacityIncrement = increment;
268*27b03b36SApple OSS Distributions }
269*27b03b36SApple OSS Distributions 
270*27b03b36SApple OSS Distributions // xx-review: does not check for capacity == EXTERNAL
271*27b03b36SApple OSS Distributions 
272*27b03b36SApple OSS Distributions unsigned int
ensureCapacity(unsigned int newCapacity)273*27b03b36SApple OSS Distributions OSData::ensureCapacity(unsigned int newCapacity)
274*27b03b36SApple OSS Distributions {
275*27b03b36SApple OSS Distributions 	struct kalloc_result kr;
276*27b03b36SApple OSS Distributions 	unsigned int finalCapacity;
277*27b03b36SApple OSS Distributions 
278*27b03b36SApple OSS Distributions 	if (newCapacity <= capacity) {
279*27b03b36SApple OSS Distributions 		return capacity;
280*27b03b36SApple OSS Distributions 	}
281*27b03b36SApple OSS Distributions 
282*27b03b36SApple OSS Distributions 	finalCapacity = (((newCapacity - 1) / capacityIncrement) + 1)
283*27b03b36SApple OSS Distributions 	    * capacityIncrement;
284*27b03b36SApple OSS Distributions 
285*27b03b36SApple OSS Distributions 	// integer overflow check
286*27b03b36SApple OSS Distributions 	if (finalCapacity < newCapacity) {
287*27b03b36SApple OSS Distributions 		return capacity;
288*27b03b36SApple OSS Distributions 	}
289*27b03b36SApple OSS Distributions 
290*27b03b36SApple OSS Distributions 	if (finalCapacity >= PAGE_SIZE) {
291*27b03b36SApple OSS Distributions 		finalCapacity = (uint32_t)round_page(finalCapacity);
292*27b03b36SApple OSS Distributions 	}
293*27b03b36SApple OSS Distributions 	kr = krealloc_ext((void *)KHEAP_DATA_BUFFERS, data, capacity, finalCapacity,
294*27b03b36SApple OSS Distributions 	    Z_VM_TAG_BT(Z_WAITOK_ZERO | Z_MAY_COPYINMAP,
295*27b03b36SApple OSS Distributions 	    VM_KERN_MEMORY_LIBKERN), (void *)&this->data);
296*27b03b36SApple OSS Distributions 
297*27b03b36SApple OSS Distributions 	if (kr.addr) {
298*27b03b36SApple OSS Distributions 		size_t delta = 0;
299*27b03b36SApple OSS Distributions 
300*27b03b36SApple OSS Distributions 		data     = kr.addr;
301*27b03b36SApple OSS Distributions 		delta   -= capacity;
302*27b03b36SApple OSS Distributions 		capacity = (uint32_t)MIN(kr.size, UINT32_MAX);
303*27b03b36SApple OSS Distributions 		delta   += capacity;
304*27b03b36SApple OSS Distributions 		OSCONTAINER_ACCUMSIZE(delta);
305*27b03b36SApple OSS Distributions 	}
306*27b03b36SApple OSS Distributions 
307*27b03b36SApple OSS Distributions 	return capacity;
308*27b03b36SApple OSS Distributions }
309*27b03b36SApple OSS Distributions 
310*27b03b36SApple OSS Distributions bool
clipForCopyout()311*27b03b36SApple OSS Distributions OSData::clipForCopyout()
312*27b03b36SApple OSS Distributions {
313*27b03b36SApple OSS Distributions 	unsigned int newCapacity = (uint32_t)round_page(length);
314*27b03b36SApple OSS Distributions 	__assert_only struct kalloc_result kr;
315*27b03b36SApple OSS Distributions 
316*27b03b36SApple OSS Distributions 	/*
317*27b03b36SApple OSS Distributions 	 * OSData allocations are atomic, which means that if copyoutkdata()
318*27b03b36SApple OSS Distributions 	 * is used on them, and that there are fully unused pages at the end
319*27b03b36SApple OSS Distributions 	 * of the OSData buffer, then vm_map_copyin() will try to clip the VM
320*27b03b36SApple OSS Distributions 	 * entry which will panic.
321*27b03b36SApple OSS Distributions 	 *
322*27b03b36SApple OSS Distributions 	 * In order to avoid this, trim down the unused pages.
323*27b03b36SApple OSS Distributions 	 *
324*27b03b36SApple OSS Distributions 	 * We know this operation never fails and keeps the allocation
325*27b03b36SApple OSS Distributions 	 * address stable.
326*27b03b36SApple OSS Distributions 	 */
327*27b03b36SApple OSS Distributions 	if (length >= msg_ool_size_small && newCapacity < capacity) {
328*27b03b36SApple OSS Distributions 		kr = krealloc_ext((void *)KHEAP_DATA_BUFFERS,
329*27b03b36SApple OSS Distributions 		    data, capacity, newCapacity,
330*27b03b36SApple OSS Distributions 		    Z_VM_TAG_BT(Z_WAITOK_ZERO | Z_FULLSIZE | Z_MAY_COPYINMAP,
331*27b03b36SApple OSS Distributions 		    VM_KERN_MEMORY_LIBKERN), (void *)&this->data);
332*27b03b36SApple OSS Distributions 		assert(kr.addr == data);
333*27b03b36SApple OSS Distributions 		OSCONTAINER_ACCUMSIZE(((size_t)newCapacity) - ((size_t)capacity));
334*27b03b36SApple OSS Distributions 		capacity = newCapacity;
335*27b03b36SApple OSS Distributions 	}
336*27b03b36SApple OSS Distributions 	return true;
337*27b03b36SApple OSS Distributions }
338*27b03b36SApple OSS Distributions 
339*27b03b36SApple OSS Distributions bool
appendBytes(const void * bytes,unsigned int inLength)340*27b03b36SApple OSS Distributions OSData::appendBytes(const void *bytes, unsigned int inLength)
341*27b03b36SApple OSS Distributions {
342*27b03b36SApple OSS Distributions 	unsigned int newSize;
343*27b03b36SApple OSS Distributions 
344*27b03b36SApple OSS Distributions 	if (!inLength) {
345*27b03b36SApple OSS Distributions 		return true;
346*27b03b36SApple OSS Distributions 	}
347*27b03b36SApple OSS Distributions 
348*27b03b36SApple OSS Distributions 	if (capacity == EXTERNAL) {
349*27b03b36SApple OSS Distributions 		return false;
350*27b03b36SApple OSS Distributions 	}
351*27b03b36SApple OSS Distributions 
352*27b03b36SApple OSS Distributions 	if (os_add_overflow(length, inLength, &newSize)) {
353*27b03b36SApple OSS Distributions 		return false;
354*27b03b36SApple OSS Distributions 	}
355*27b03b36SApple OSS Distributions 
356*27b03b36SApple OSS Distributions 	if ((newSize > capacity) && newSize > ensureCapacity(newSize)) {
357*27b03b36SApple OSS Distributions 		return false;
358*27b03b36SApple OSS Distributions 	}
359*27b03b36SApple OSS Distributions 
360*27b03b36SApple OSS Distributions 	if (bytes) {
361*27b03b36SApple OSS Distributions 		bcopy(bytes, &((unsigned char *)data)[length], inLength);
362*27b03b36SApple OSS Distributions 	} else {
363*27b03b36SApple OSS Distributions 		bzero(&((unsigned char *)data)[length], inLength);
364*27b03b36SApple OSS Distributions 	}
365*27b03b36SApple OSS Distributions 
366*27b03b36SApple OSS Distributions 	length = newSize;
367*27b03b36SApple OSS Distributions 
368*27b03b36SApple OSS Distributions 	return true;
369*27b03b36SApple OSS Distributions }
370*27b03b36SApple OSS Distributions 
371*27b03b36SApple OSS Distributions bool
appendByte(unsigned char byte,unsigned int inLength)372*27b03b36SApple OSS Distributions OSData::appendByte(unsigned char byte, unsigned int inLength)
373*27b03b36SApple OSS Distributions {
374*27b03b36SApple OSS Distributions 	unsigned int newSize;
375*27b03b36SApple OSS Distributions 
376*27b03b36SApple OSS Distributions 	if (!inLength) {
377*27b03b36SApple OSS Distributions 		return true;
378*27b03b36SApple OSS Distributions 	}
379*27b03b36SApple OSS Distributions 
380*27b03b36SApple OSS Distributions 	if (capacity == EXTERNAL) {
381*27b03b36SApple OSS Distributions 		return false;
382*27b03b36SApple OSS Distributions 	}
383*27b03b36SApple OSS Distributions 
384*27b03b36SApple OSS Distributions 	if (os_add_overflow(length, inLength, &newSize)) {
385*27b03b36SApple OSS Distributions 		return false;
386*27b03b36SApple OSS Distributions 	}
387*27b03b36SApple OSS Distributions 
388*27b03b36SApple OSS Distributions 	if ((newSize > capacity) && newSize > ensureCapacity(newSize)) {
389*27b03b36SApple OSS Distributions 		return false;
390*27b03b36SApple OSS Distributions 	}
391*27b03b36SApple OSS Distributions 
392*27b03b36SApple OSS Distributions 	memset(&((unsigned char *)data)[length], byte, inLength);
393*27b03b36SApple OSS Distributions 	length = newSize;
394*27b03b36SApple OSS Distributions 
395*27b03b36SApple OSS Distributions 	return true;
396*27b03b36SApple OSS Distributions }
397*27b03b36SApple OSS Distributions 
398*27b03b36SApple OSS Distributions bool
appendBytes(const OSData * other)399*27b03b36SApple OSS Distributions OSData::appendBytes(const OSData *other)
400*27b03b36SApple OSS Distributions {
401*27b03b36SApple OSS Distributions 	return appendBytes(other->data, other->length);
402*27b03b36SApple OSS Distributions }
403*27b03b36SApple OSS Distributions 
404*27b03b36SApple OSS Distributions const void *
getBytesNoCopy() const405*27b03b36SApple OSS Distributions OSData::getBytesNoCopy() const
406*27b03b36SApple OSS Distributions {
407*27b03b36SApple OSS Distributions 	if (!length) {
408*27b03b36SApple OSS Distributions 		return NULL;
409*27b03b36SApple OSS Distributions 	} else {
410*27b03b36SApple OSS Distributions 		return data;
411*27b03b36SApple OSS Distributions 	}
412*27b03b36SApple OSS Distributions }
413*27b03b36SApple OSS Distributions 
414*27b03b36SApple OSS Distributions const void *
getBytesNoCopy(unsigned int start,unsigned int inLength) const415*27b03b36SApple OSS Distributions OSData::getBytesNoCopy(unsigned int start,
416*27b03b36SApple OSS Distributions     unsigned int inLength) const
417*27b03b36SApple OSS Distributions {
418*27b03b36SApple OSS Distributions 	const void *outData = NULL;
419*27b03b36SApple OSS Distributions 
420*27b03b36SApple OSS Distributions 	if (length
421*27b03b36SApple OSS Distributions 	    && start < length
422*27b03b36SApple OSS Distributions 	    && (start + inLength) >= inLength // overflow check
423*27b03b36SApple OSS Distributions 	    && (start + inLength) <= length) {
424*27b03b36SApple OSS Distributions 		outData = (const void *) ((char *) data + start);
425*27b03b36SApple OSS Distributions 	}
426*27b03b36SApple OSS Distributions 
427*27b03b36SApple OSS Distributions 	return outData;
428*27b03b36SApple OSS Distributions }
429*27b03b36SApple OSS Distributions 
430*27b03b36SApple OSS Distributions bool
isEqualTo(const OSData * aData) const431*27b03b36SApple OSS Distributions OSData::isEqualTo(const OSData *aData) const
432*27b03b36SApple OSS Distributions {
433*27b03b36SApple OSS Distributions 	unsigned int len;
434*27b03b36SApple OSS Distributions 
435*27b03b36SApple OSS Distributions 	len = aData->length;
436*27b03b36SApple OSS Distributions 	if (length != len) {
437*27b03b36SApple OSS Distributions 		return false;
438*27b03b36SApple OSS Distributions 	}
439*27b03b36SApple OSS Distributions 
440*27b03b36SApple OSS Distributions 	return isEqualTo(aData->data, len);
441*27b03b36SApple OSS Distributions }
442*27b03b36SApple OSS Distributions 
443*27b03b36SApple OSS Distributions bool
isEqualTo(const void * someData,unsigned int inLength) const444*27b03b36SApple OSS Distributions OSData::isEqualTo(const void *someData, unsigned int inLength) const
445*27b03b36SApple OSS Distributions {
446*27b03b36SApple OSS Distributions 	return (length >= inLength) && (bcmp(data, someData, inLength) == 0);
447*27b03b36SApple OSS Distributions }
448*27b03b36SApple OSS Distributions 
449*27b03b36SApple OSS Distributions bool
isEqualTo(const OSMetaClassBase * obj) const450*27b03b36SApple OSS Distributions OSData::isEqualTo(const OSMetaClassBase *obj) const
451*27b03b36SApple OSS Distributions {
452*27b03b36SApple OSS Distributions 	OSData *    otherData;
453*27b03b36SApple OSS Distributions 	OSString *  str;
454*27b03b36SApple OSS Distributions 
455*27b03b36SApple OSS Distributions 	if ((otherData = OSDynamicCast(OSData, obj))) {
456*27b03b36SApple OSS Distributions 		return isEqualTo(otherData);
457*27b03b36SApple OSS Distributions 	} else if ((str = OSDynamicCast(OSString, obj))) {
458*27b03b36SApple OSS Distributions 		return isEqualTo(str);
459*27b03b36SApple OSS Distributions 	} else {
460*27b03b36SApple OSS Distributions 		return false;
461*27b03b36SApple OSS Distributions 	}
462*27b03b36SApple OSS Distributions }
463*27b03b36SApple OSS Distributions 
464*27b03b36SApple OSS Distributions bool
isEqualTo(const OSString * obj) const465*27b03b36SApple OSS Distributions OSData::isEqualTo(const OSString *obj) const
466*27b03b36SApple OSS Distributions {
467*27b03b36SApple OSS Distributions 	const char * aCString;
468*27b03b36SApple OSS Distributions 	char * dataPtr;
469*27b03b36SApple OSS Distributions 	unsigned int checkLen = length;
470*27b03b36SApple OSS Distributions 	unsigned int stringLen;
471*27b03b36SApple OSS Distributions 
472*27b03b36SApple OSS Distributions 	if (!obj) {
473*27b03b36SApple OSS Distributions 		return false;
474*27b03b36SApple OSS Distributions 	}
475*27b03b36SApple OSS Distributions 
476*27b03b36SApple OSS Distributions 	stringLen = obj->getLength();
477*27b03b36SApple OSS Distributions 
478*27b03b36SApple OSS Distributions 	dataPtr = (char *)data;
479*27b03b36SApple OSS Distributions 
480*27b03b36SApple OSS Distributions 	if (stringLen != checkLen) {
481*27b03b36SApple OSS Distributions 		// check for the fact that OSData may be a buffer that
482*27b03b36SApple OSS Distributions 		// that includes a termination byte and will thus have
483*27b03b36SApple OSS Distributions 		// a length of the actual string length PLUS 1. In this
484*27b03b36SApple OSS Distributions 		// case we verify that the additional byte is a terminator
485*27b03b36SApple OSS Distributions 		// and if so count the two lengths as being the same.
486*27b03b36SApple OSS Distributions 
487*27b03b36SApple OSS Distributions 		if ((checkLen - stringLen) == 1) {
488*27b03b36SApple OSS Distributions 			if (dataPtr[checkLen - 1] != 0) { // non-zero means not a terminator and thus not likely the same
489*27b03b36SApple OSS Distributions 				return false;
490*27b03b36SApple OSS Distributions 			}
491*27b03b36SApple OSS Distributions 			checkLen--;
492*27b03b36SApple OSS Distributions 		} else {
493*27b03b36SApple OSS Distributions 			return false;
494*27b03b36SApple OSS Distributions 		}
495*27b03b36SApple OSS Distributions 	}
496*27b03b36SApple OSS Distributions 
497*27b03b36SApple OSS Distributions 	aCString = obj->getCStringNoCopy();
498*27b03b36SApple OSS Distributions 
499*27b03b36SApple OSS Distributions 	for (unsigned int i = 0; i < checkLen; i++) {
500*27b03b36SApple OSS Distributions 		if (*dataPtr++ != aCString[i]) {
501*27b03b36SApple OSS Distributions 			return false;
502*27b03b36SApple OSS Distributions 		}
503*27b03b36SApple OSS Distributions 	}
504*27b03b36SApple OSS Distributions 
505*27b03b36SApple OSS Distributions 	return true;
506*27b03b36SApple OSS Distributions }
507*27b03b36SApple OSS Distributions 
508*27b03b36SApple OSS Distributions //this was taken from CFPropertyList.c
509*27b03b36SApple OSS Distributions static const char __CFPLDataEncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
510*27b03b36SApple OSS Distributions 
511*27b03b36SApple OSS Distributions bool
serialize(OSSerialize * s) const512*27b03b36SApple OSS Distributions OSData::serialize(OSSerialize *s) const
513*27b03b36SApple OSS Distributions {
514*27b03b36SApple OSS Distributions 	unsigned int i;
515*27b03b36SApple OSS Distributions 	const unsigned char *p;
516*27b03b36SApple OSS Distributions 	unsigned char c;
517*27b03b36SApple OSS Distributions 	unsigned int serializeLength;
518*27b03b36SApple OSS Distributions 
519*27b03b36SApple OSS Distributions 	if (s->previouslySerialized(this)) {
520*27b03b36SApple OSS Distributions 		return true;
521*27b03b36SApple OSS Distributions 	}
522*27b03b36SApple OSS Distributions 
523*27b03b36SApple OSS Distributions 	if (!s->addXMLStartTag(this, "data")) {
524*27b03b36SApple OSS Distributions 		return false;
525*27b03b36SApple OSS Distributions 	}
526*27b03b36SApple OSS Distributions 
527*27b03b36SApple OSS Distributions 	serializeLength = length;
528*27b03b36SApple OSS Distributions 	if (reserved && reserved->disableSerialization) {
529*27b03b36SApple OSS Distributions 		serializeLength = 0;
530*27b03b36SApple OSS Distributions 	}
531*27b03b36SApple OSS Distributions 
532*27b03b36SApple OSS Distributions 	for (i = 0, p = (unsigned char *)data; i < serializeLength; i++, p++) {
533*27b03b36SApple OSS Distributions 		/* 3 bytes are encoded as 4 */
534*27b03b36SApple OSS Distributions 		switch (i % 3) {
535*27b03b36SApple OSS Distributions 		case 0:
536*27b03b36SApple OSS Distributions 			c = __CFPLDataEncodeTable[((p[0] >> 2) & 0x3f)];
537*27b03b36SApple OSS Distributions 			if (!s->addChar(c)) {
538*27b03b36SApple OSS Distributions 				return false;
539*27b03b36SApple OSS Distributions 			}
540*27b03b36SApple OSS Distributions 			break;
541*27b03b36SApple OSS Distributions 		case 1:
542*27b03b36SApple OSS Distributions 			c = __CFPLDataEncodeTable[((((p[-1] << 8) | p[0]) >> 4) & 0x3f)];
543*27b03b36SApple OSS Distributions 			if (!s->addChar(c)) {
544*27b03b36SApple OSS Distributions 				return false;
545*27b03b36SApple OSS Distributions 			}
546*27b03b36SApple OSS Distributions 			break;
547*27b03b36SApple OSS Distributions 		case 2:
548*27b03b36SApple OSS Distributions 			c = __CFPLDataEncodeTable[((((p[-1] << 8) | p[0]) >> 6) & 0x3f)];
549*27b03b36SApple OSS Distributions 			if (!s->addChar(c)) {
550*27b03b36SApple OSS Distributions 				return false;
551*27b03b36SApple OSS Distributions 			}
552*27b03b36SApple OSS Distributions 			c = __CFPLDataEncodeTable[(p[0] & 0x3f)];
553*27b03b36SApple OSS Distributions 			if (!s->addChar(c)) {
554*27b03b36SApple OSS Distributions 				return false;
555*27b03b36SApple OSS Distributions 			}
556*27b03b36SApple OSS Distributions 			break;
557*27b03b36SApple OSS Distributions 		}
558*27b03b36SApple OSS Distributions 	}
559*27b03b36SApple OSS Distributions 	switch (i % 3) {
560*27b03b36SApple OSS Distributions 	case 0:
561*27b03b36SApple OSS Distributions 		break;
562*27b03b36SApple OSS Distributions 	case 1:
563*27b03b36SApple OSS Distributions 		c = __CFPLDataEncodeTable[((p[-1] << 4) & 0x30)];
564*27b03b36SApple OSS Distributions 		if (!s->addChar(c)) {
565*27b03b36SApple OSS Distributions 			return false;
566*27b03b36SApple OSS Distributions 		}
567*27b03b36SApple OSS Distributions 		if (!s->addChar('=')) {
568*27b03b36SApple OSS Distributions 			return false;
569*27b03b36SApple OSS Distributions 		}
570*27b03b36SApple OSS Distributions 		if (!s->addChar('=')) {
571*27b03b36SApple OSS Distributions 			return false;
572*27b03b36SApple OSS Distributions 		}
573*27b03b36SApple OSS Distributions 		break;
574*27b03b36SApple OSS Distributions 	case 2:
575*27b03b36SApple OSS Distributions 		c = __CFPLDataEncodeTable[((p[-1] << 2) & 0x3c)];
576*27b03b36SApple OSS Distributions 		if (!s->addChar(c)) {
577*27b03b36SApple OSS Distributions 			return false;
578*27b03b36SApple OSS Distributions 		}
579*27b03b36SApple OSS Distributions 		if (!s->addChar('=')) {
580*27b03b36SApple OSS Distributions 			return false;
581*27b03b36SApple OSS Distributions 		}
582*27b03b36SApple OSS Distributions 		break;
583*27b03b36SApple OSS Distributions 	}
584*27b03b36SApple OSS Distributions 
585*27b03b36SApple OSS Distributions 	return s->addXMLEndTag("data");
586*27b03b36SApple OSS Distributions }
587*27b03b36SApple OSS Distributions 
588*27b03b36SApple OSS Distributions void
setDeallocFunction(DeallocFunction func)589*27b03b36SApple OSS Distributions OSData::setDeallocFunction(DeallocFunction func)
590*27b03b36SApple OSS Distributions {
591*27b03b36SApple OSS Distributions 	if (!reserved) {
592*27b03b36SApple OSS Distributions 		reserved = (typeof(reserved))kalloc_type(ExpansionData, (zalloc_flags_t)(Z_WAITOK | Z_ZERO));
593*27b03b36SApple OSS Distributions 		if (!reserved) {
594*27b03b36SApple OSS Distributions 			return;
595*27b03b36SApple OSS Distributions 		}
596*27b03b36SApple OSS Distributions 	}
597*27b03b36SApple OSS Distributions 	reserved->deallocFunction = func;
598*27b03b36SApple OSS Distributions }
599*27b03b36SApple OSS Distributions 
600*27b03b36SApple OSS Distributions void
setSerializable(bool serializable)601*27b03b36SApple OSS Distributions OSData::setSerializable(bool serializable)
602*27b03b36SApple OSS Distributions {
603*27b03b36SApple OSS Distributions 	if (!reserved) {
604*27b03b36SApple OSS Distributions 		reserved = (typeof(reserved))kalloc_type(ExpansionData, (zalloc_flags_t)(Z_WAITOK | Z_ZERO));
605*27b03b36SApple OSS Distributions 		if (!reserved) {
606*27b03b36SApple OSS Distributions 			return;
607*27b03b36SApple OSS Distributions 		}
608*27b03b36SApple OSS Distributions 	}
609*27b03b36SApple OSS Distributions 	reserved->disableSerialization = (!serializable);
610*27b03b36SApple OSS Distributions }
611*27b03b36SApple OSS Distributions 
612*27b03b36SApple OSS Distributions bool
isSerializable(void)613*27b03b36SApple OSS Distributions OSData::isSerializable(void)
614*27b03b36SApple OSS Distributions {
615*27b03b36SApple OSS Distributions 	return !reserved || !reserved->disableSerialization;
616*27b03b36SApple OSS Distributions }
617