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