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