| 519 | } |
| 520 | |
| 521 | bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD, bool needTruncate) { |
| 522 | if (dstFD < 0) { |
| 523 | return false; |
| 524 | } |
| 525 | bool ret = false; |
| 526 | File srcFile(srcPath, OpenFlag::ReadOnly); |
| 527 | if (!srcFile.isFileValid()) { |
| 528 | return false; |
| 529 | } |
| 530 | auto bufferSize = getPageSize(); |
| 531 | auto buffer = (char *) malloc(bufferSize); |
| 532 | if (!buffer) { |
| 533 | MMKVError("fail to malloc size %zu, %d(%s)", bufferSize, errno, strerror(errno)); |
| 534 | goto errorOut; |
| 535 | } |
| 536 | lseek(dstFD, 0, SEEK_SET); |
| 537 | |
| 538 | // the POSIX standard don't have sendfile()/fcopyfile() equivalent, do it the hard way |
| 539 | while (true) { |
| 540 | auto sizeRead = read(srcFile.getFd(), buffer, bufferSize); |
| 541 | if (sizeRead < 0) { |
| 542 | MMKVError("fail to read file [%s], %d(%s)", srcPath.c_str(), errno, strerror(errno)); |
| 543 | goto errorOut; |
| 544 | } |
| 545 | |
| 546 | size_t totalWrite = 0; |
| 547 | do { |
| 548 | auto sizeWrite = write(dstFD, buffer + totalWrite, sizeRead - totalWrite); |
| 549 | if (sizeWrite < 0) { |
| 550 | MMKVError("fail to write fd [%d], %d(%s)", dstFD, errno, strerror(errno)); |
| 551 | goto errorOut; |
| 552 | } |
| 553 | totalWrite += sizeWrite; |
| 554 | } while (totalWrite < sizeRead); |
| 555 | |
| 556 | if (sizeRead < bufferSize) { |
| 557 | break; |
| 558 | } |
| 559 | } |
| 560 | if (needTruncate) { |
| 561 | size_t dstFileSize = 0; |
| 562 | getFileSize(dstFD, dstFileSize); |
| 563 | auto srcFileSize = srcFile.getActualFileSize(); |
| 564 | if ((dstFileSize != srcFileSize) && (::ftruncate(dstFD, static_cast<off_t>(srcFileSize)) != 0)) { |
| 565 | MMKVError("fail to truncate [%d] to size [%zu], %d(%s)", dstFD, srcFileSize, errno, strerror(errno)); |
| 566 | goto errorOut; |
| 567 | } |
| 568 | } |
| 569 | |
| 570 | ret = true; |
| 571 | MMKVInfo("copy content from %s to fd[%d] finish", srcPath.c_str(), dstFD); |
| 572 | |
| 573 | errorOut: |
| 574 | free(buffer); |
| 575 | return ret; |
| 576 | } |
| 577 | |
| 578 | #endif // !defined(MMKV_ANDROID) && !defined(MMKV_LINUX) |
no test coverage detected