1/* 2 * Copyright 2005-2014 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stefano Ceccherini, burton666@libero.it 7 */ 8 9 10#include <DataIO.h> 11 12#include <stdio.h> 13#include <string.h> 14#include <stdlib.h> 15 16#include <Errors.h> 17 18#if defined(_KERNEL_MODE) && !defined(_BOOT_MODE) 19// for user_memcpy() and IS_USER_ADDRESS() 20#include <KernelExport.h> 21 22#include <kernel.h> 23#endif 24 25 26BDataIO::BDataIO() 27{ 28} 29 30 31BDataIO::~BDataIO() 32{ 33} 34 35 36ssize_t 37BDataIO::Read(void* buffer, size_t size) 38{ 39 return B_NOT_SUPPORTED; 40} 41 42 43ssize_t 44BDataIO::Write(const void* buffer, size_t size) 45{ 46 return B_NOT_SUPPORTED; 47} 48 49 50status_t 51BDataIO::Flush() 52{ 53 return B_OK; 54} 55 56 57status_t 58BDataIO::ReadExactly(void* buffer, size_t size, size_t* _bytesRead) 59{ 60 uint8* out = (uint8*)buffer; 61 size_t bytesRemaining = size; 62 status_t error = B_OK; 63 64 while (bytesRemaining > 0) { 65 ssize_t bytesRead = Read(out, bytesRemaining); 66 if (bytesRead < 0) { 67 error = bytesRead; 68 break; 69 } 70 71 if (bytesRead == 0) { 72 error = B_PARTIAL_READ; 73 break; 74 } 75 76 out += bytesRead; 77 bytesRemaining -= bytesRead; 78 } 79 80 if (_bytesRead != NULL) 81 *_bytesRead = size - bytesRemaining; 82 83 return error; 84} 85 86 87status_t 88BDataIO::WriteExactly(const void* buffer, size_t size, size_t* _bytesWritten) 89{ 90 const uint8* in = (const uint8*)buffer; 91 size_t bytesRemaining = size; 92 status_t error = B_OK; 93 94 while (bytesRemaining > 0) { 95 ssize_t bytesWritten = Write(in, bytesRemaining); 96 if (bytesWritten < 0) { 97 error = bytesWritten; 98 break; 99 } 100 101 if (bytesWritten == 0) { 102 error = B_PARTIAL_WRITE; 103 break; 104 } 105 106 in += bytesWritten; 107 bytesRemaining -= bytesWritten; 108 } 109 110 if (_bytesWritten != NULL) 111 *_bytesWritten = size - bytesRemaining; 112 113 return error; 114} 115 116 117// Private or Reserved 118 119BDataIO::BDataIO(const BDataIO &) 120{ 121 // Copying not allowed 122} 123 124 125BDataIO & 126BDataIO::operator=(const BDataIO &) 127{ 128 // Copying not allowed 129 return *this; 130} 131 132 133#if __GNUC__ == 2 134 135 136extern "C" status_t 137_ReservedDataIO1__7BDataIO(BDataIO* self) 138{ 139 return self->BDataIO::Flush(); 140} 141 142 143#else 144 145 146// TODO: RELEASE: Remove! 147 148extern "C" status_t 149_ZN7BDataIO16_ReservedDataIO1Ev(BDataIO* self) 150{ 151 return self->BDataIO::Flush(); 152} 153 154 155#endif 156 157 158// FBC 159void BDataIO::_ReservedDataIO2(){} 160void BDataIO::_ReservedDataIO3(){} 161void BDataIO::_ReservedDataIO4(){} 162void BDataIO::_ReservedDataIO5(){} 163void BDataIO::_ReservedDataIO6(){} 164void BDataIO::_ReservedDataIO7(){} 165void BDataIO::_ReservedDataIO8(){} 166void BDataIO::_ReservedDataIO9(){} 167void BDataIO::_ReservedDataIO10(){} 168void BDataIO::_ReservedDataIO11(){} 169void BDataIO::_ReservedDataIO12(){} 170 171 172// #pragma mark - 173 174 175BPositionIO::BPositionIO() 176{ 177} 178 179 180BPositionIO::~BPositionIO() 181{ 182} 183 184 185ssize_t 186BPositionIO::Read(void* buffer, size_t size) 187{ 188 off_t curPos = Position(); 189 ssize_t result = ReadAt(curPos, buffer, size); 190 if (result > 0) 191 Seek(result, SEEK_CUR); 192 193 return result; 194} 195 196 197ssize_t 198BPositionIO::Write(const void* buffer, size_t size) 199{ 200 off_t curPos = Position(); 201 ssize_t result = WriteAt(curPos, buffer, size); 202 if (result > 0) 203 Seek(result, SEEK_CUR); 204 205 return result; 206} 207 208 209status_t 210BPositionIO::ReadAtExactly(off_t position, void* buffer, size_t size, 211 size_t* _bytesRead) 212{ 213 uint8* out = (uint8*)buffer; 214 size_t bytesRemaining = size; 215 status_t error = B_OK; 216 217 while (bytesRemaining > 0) { 218 ssize_t bytesRead = ReadAt(position, out, bytesRemaining); 219 if (bytesRead < 0) { 220 error = bytesRead; 221 break; 222 } 223 224 if (bytesRead == 0) { 225 error = B_PARTIAL_READ; 226 break; 227 } 228 229 out += bytesRead; 230 bytesRemaining -= bytesRead; 231 position += bytesRead; 232 } 233 234 if (_bytesRead != NULL) 235 *_bytesRead = size - bytesRemaining; 236 237 return error; 238} 239 240 241status_t 242BPositionIO::WriteAtExactly(off_t position, const void* buffer, size_t size, 243 size_t* _bytesWritten) 244{ 245 const uint8* in = (const uint8*)buffer; 246 size_t bytesRemaining = size; 247 status_t error = B_OK; 248 249 while (bytesRemaining > 0) { 250 ssize_t bytesWritten = WriteAt(position, in, bytesRemaining); 251 if (bytesWritten < 0) { 252 error = bytesWritten; 253 break; 254 } 255 256 if (bytesWritten == 0) { 257 error = B_PARTIAL_WRITE; 258 break; 259 } 260 261 in += bytesWritten; 262 bytesRemaining -= bytesWritten; 263 position += bytesWritten; 264 } 265 266 if (_bytesWritten != NULL) 267 *_bytesWritten = size - bytesRemaining; 268 269 return error; 270} 271 272 273status_t 274BPositionIO::SetSize(off_t size) 275{ 276 return B_ERROR; 277} 278 279 280status_t 281BPositionIO::GetSize(off_t* size) const 282{ 283 if (!size) 284 return B_BAD_VALUE; 285 286 off_t currentPos = Position(); 287 if (currentPos < 0) 288 return (status_t)currentPos; 289 290 *size = const_cast<BPositionIO*>(this)->Seek(0, SEEK_END); 291 if (*size < 0) 292 return (status_t)*size; 293 294 off_t pos = const_cast<BPositionIO*>(this)->Seek(currentPos, SEEK_SET); 295 296 if (pos != currentPos) 297 return pos < 0 ? (status_t)pos : B_ERROR; 298 299 return B_OK; 300} 301 302 303// FBC 304extern "C" void _ReservedPositionIO1__11BPositionIO() {} 305void BPositionIO::_ReservedPositionIO2(){} 306void BPositionIO::_ReservedPositionIO3(){} 307void BPositionIO::_ReservedPositionIO4(){} 308void BPositionIO::_ReservedPositionIO5(){} 309void BPositionIO::_ReservedPositionIO6(){} 310void BPositionIO::_ReservedPositionIO7(){} 311void BPositionIO::_ReservedPositionIO8(){} 312void BPositionIO::_ReservedPositionIO9(){} 313void BPositionIO::_ReservedPositionIO10(){} 314void BPositionIO::_ReservedPositionIO11(){} 315void BPositionIO::_ReservedPositionIO12(){} 316 317 318// #pragma mark - 319 320 321BMemoryIO::BMemoryIO(void* buffer, size_t length) 322 : 323 fReadOnly(false), 324 fBuffer(static_cast<char*>(buffer)), 325 fLength(length), 326 fBufferSize(length), 327 fPosition(0) 328{ 329} 330 331 332BMemoryIO::BMemoryIO(const void* buffer, size_t length) 333 : 334 fReadOnly(true), 335 fBuffer(const_cast<char*>(static_cast<const char*>(buffer))), 336 fLength(length), 337 fBufferSize(length), 338 fPosition(0) 339{ 340} 341 342 343BMemoryIO::~BMemoryIO() 344{ 345} 346 347 348ssize_t 349BMemoryIO::ReadAt(off_t pos, void* buffer, size_t size) 350{ 351 if (buffer == NULL || pos < 0) 352 return B_BAD_VALUE; 353 354 ssize_t sizeRead = 0; 355 if (pos < (off_t)fLength) { 356 sizeRead = min_c((off_t)size, (off_t)fLength - pos); 357 memcpy(buffer, fBuffer + pos, sizeRead); 358 } 359 360 return sizeRead; 361} 362 363 364ssize_t 365BMemoryIO::WriteAt(off_t pos, const void* buffer, size_t size) 366{ 367 if (fReadOnly) 368 return B_NOT_ALLOWED; 369 370 if (buffer == NULL || pos < 0) 371 return B_BAD_VALUE; 372 373 ssize_t sizeWritten = 0; 374 if (pos < (off_t)fBufferSize) { 375 sizeWritten = min_c((off_t)size, (off_t)fBufferSize - pos); 376#if defined(_KERNEL_MODE) && !defined(_BOOT_MODE) 377 if (IS_USER_ADDRESS(fBuffer)) { 378 if (user_memcpy(fBuffer + pos, buffer, sizeWritten) != B_OK) 379 return B_BAD_ADDRESS; 380 } else 381#endif 382 memcpy(fBuffer + pos, buffer, sizeWritten); 383 } 384 385 if (pos + sizeWritten > (off_t)fLength) 386 fLength = pos + sizeWritten; 387 388 return sizeWritten; 389} 390 391 392off_t 393BMemoryIO::Seek(off_t position, uint32 seek_mode) 394{ 395 switch (seek_mode) { 396 case SEEK_SET: 397 fPosition = position; 398 break; 399 case SEEK_CUR: 400 fPosition += position; 401 break; 402 case SEEK_END: 403 fPosition = fLength + position; 404 break; 405 default: 406 break; 407 } 408 409 return fPosition; 410} 411 412 413off_t 414BMemoryIO::Position() const 415{ 416 return fPosition; 417} 418 419 420status_t 421BMemoryIO::SetSize(off_t size) 422{ 423 if (fReadOnly) 424 return B_NOT_ALLOWED; 425 426 if (size > (off_t)fBufferSize) 427 return B_ERROR; 428 429 fLength = size; 430 431 return B_OK; 432} 433 434 435// Private or Reserved 436 437BMemoryIO::BMemoryIO(const BMemoryIO &) 438{ 439 //Copying not allowed 440} 441 442 443BMemoryIO & 444BMemoryIO::operator=(const BMemoryIO &) 445{ 446 //Copying not allowed 447 return *this; 448} 449 450 451// FBC 452void BMemoryIO::_ReservedMemoryIO1(){} 453void BMemoryIO::_ReservedMemoryIO2(){} 454 455 456// #pragma mark - 457 458 459BMallocIO::BMallocIO() 460 : 461 fBlockSize(256), 462 fMallocSize(0), 463 fLength(0), 464 fData(NULL), 465 fPosition(0) 466{ 467} 468 469 470BMallocIO::~BMallocIO() 471{ 472 free(fData); 473} 474 475 476ssize_t 477BMallocIO::ReadAt(off_t pos, void* buffer, size_t size) 478{ 479 if (buffer == NULL) 480 return B_BAD_VALUE; 481 482 ssize_t sizeRead = 0; 483 if (pos < (off_t)fLength) { 484 sizeRead = min_c((off_t)size, (off_t)fLength - pos); 485 memcpy(buffer, fData + pos, sizeRead); 486 } 487 488 return sizeRead; 489} 490 491 492ssize_t 493BMallocIO::WriteAt(off_t pos, const void* buffer, size_t size) 494{ 495 if (buffer == NULL) 496 return B_BAD_VALUE; 497 498 size_t newSize = max_c(pos + (off_t)size, (off_t)fLength); 499 status_t error = B_OK; 500 501 if (newSize > fMallocSize) 502 error = SetSize(newSize); 503 504 if (error == B_OK) { 505 memcpy(fData + pos, buffer, size); 506 if (pos + size > fLength) 507 fLength = pos + size; 508 } 509 510 return error != B_OK ? error : size; 511} 512 513 514off_t 515BMallocIO::Seek(off_t position, uint32 seekMode) 516{ 517 switch (seekMode) { 518 case SEEK_SET: 519 fPosition = position; 520 break; 521 case SEEK_END: 522 fPosition = fLength + position; 523 break; 524 case SEEK_CUR: 525 fPosition += position; 526 break; 527 default: 528 break; 529 } 530 return fPosition; 531} 532 533 534off_t 535BMallocIO::Position() const 536{ 537 return fPosition; 538} 539 540 541status_t 542BMallocIO::SetSize(off_t size) 543{ 544 status_t error = B_OK; 545 if (size == 0) { 546 // size == 0, free the memory 547 free(fData); 548 fData = NULL; 549 fMallocSize = 0; 550 } else { 551 // size != 0, see, if necessary to resize 552 size_t newSize = (size + fBlockSize - 1) / fBlockSize * fBlockSize; 553 if (size != (off_t)fMallocSize) { 554 // we need to resize 555 if (char* newData = static_cast<char*>(realloc(fData, newSize))) { 556 // set the new area to 0 557 if (newSize > fMallocSize) 558 memset(newData + fMallocSize, 0, newSize - fMallocSize); 559 fData = newData; 560 fMallocSize = newSize; 561 } else // couldn't alloc the memory 562 error = B_NO_MEMORY; 563 } 564 } 565 566 if (error == B_OK) 567 fLength = size; 568 569 return error; 570} 571 572 573void 574BMallocIO::SetBlockSize(size_t blockSize) 575{ 576 if (blockSize == 0) 577 blockSize = 1; 578 579 if (blockSize != fBlockSize) 580 fBlockSize = blockSize; 581} 582 583 584const void* 585BMallocIO::Buffer() const 586{ 587 return fData; 588} 589 590 591size_t 592BMallocIO::BufferLength() const 593{ 594 return fLength; 595} 596 597 598// Private or Reserved 599 600BMallocIO::BMallocIO(const BMallocIO &) 601{ 602 // copying not allowed... 603} 604 605 606BMallocIO & 607BMallocIO::operator=(const BMallocIO &) 608{ 609 // copying not allowed... 610 return *this; 611} 612 613 614// FBC 615void BMallocIO::_ReservedMallocIO1() {} 616void BMallocIO::_ReservedMallocIO2() {} 617