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