1// FileStreams.cpp 2 3#include "StdAfx.h" 4 5// #include <stdio.h> 6 7#ifndef _WIN32 8#include <fcntl.h> 9#include <unistd.h> 10#include <errno.h> 11#include <grp.h> 12#include <pwd.h> 13 14// for major()/minor(): 15#include <sys/types.h> 16#if defined(__FreeBSD__) || defined(BSD) || defined(__APPLE__) 17#else 18#ifndef major 19#include <sys/sysmacros.h> 20#endif 21#endif 22 23#endif // _WIN32 24 25#include "../../Windows/FileFind.h" 26 27#ifdef Z7_DEVICE_FILE 28#include "../../../C/Alloc.h" 29#include "../../Common/Defs.h" 30#endif 31 32#include "../PropID.h" 33 34#include "FileStreams.h" 35 36static inline HRESULT GetLastError_HRESULT() 37{ 38 DWORD lastError = ::GetLastError(); 39 if (lastError == 0) 40 return E_FAIL; 41 return HRESULT_FROM_WIN32(lastError); 42} 43 44static inline HRESULT ConvertBoolToHRESULT(bool result) 45{ 46 if (result) 47 return S_OK; 48 return GetLastError_HRESULT(); 49} 50 51 52#ifdef Z7_DEVICE_FILE 53static const UInt32 kClusterSize = 1 << 18; 54#endif 55 56CInFileStream::CInFileStream(): 57 #ifdef Z7_DEVICE_FILE 58 VirtPos(0), 59 PhyPos(0), 60 Buf(NULL), 61 BufSize(0), 62 #endif 63 #ifndef _WIN32 64 _uid(0), 65 _gid(0), 66 StoreOwnerId(false), 67 StoreOwnerName(false), 68 #endif 69 _info_WasLoaded(false), 70 SupportHardLinks(false), 71 Callback(NULL), 72 CallbackRef(0) 73{ 74} 75 76CInFileStream::~CInFileStream() 77{ 78 #ifdef Z7_DEVICE_FILE 79 MidFree(Buf); 80 #endif 81 82 if (Callback) 83 Callback->InFileStream_On_Destroy(this, CallbackRef); 84} 85 86Z7_COM7F_IMF(CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)) 87{ 88 #ifdef Z7_FILE_STREAMS_USE_WIN_FILE 89 90 #ifdef Z7_DEVICE_FILE 91 if (processedSize) 92 *processedSize = 0; 93 if (size == 0) 94 return S_OK; 95 if (File.IsDeviceFile) 96 { 97 if (File.SizeDefined) 98 { 99 if (VirtPos >= File.Size) 100 return VirtPos == File.Size ? S_OK : E_FAIL; 101 const UInt64 rem = File.Size - VirtPos; 102 if (size > rem) 103 size = (UInt32)rem; 104 } 105 for (;;) 106 { 107 const UInt32 mask = kClusterSize - 1; 108 const UInt64 mask2 = ~(UInt64)mask; 109 const UInt64 alignedPos = VirtPos & mask2; 110 if (BufSize > 0 && BufStartPos == alignedPos) 111 { 112 const UInt32 pos = (UInt32)VirtPos & mask; 113 if (pos >= BufSize) 114 return S_OK; 115 const UInt32 rem = MyMin(BufSize - pos, size); 116 memcpy(data, Buf + pos, rem); 117 VirtPos += rem; 118 if (processedSize) 119 *processedSize += rem; 120 return S_OK; 121 } 122 123 bool useBuf = false; 124 if ((VirtPos & mask) != 0 || ((size_t)(ptrdiff_t)data & mask) != 0 ) 125 useBuf = true; 126 else 127 { 128 UInt64 end = VirtPos + size; 129 if ((end & mask) != 0) 130 { 131 end &= mask2; 132 if (end <= VirtPos) 133 useBuf = true; 134 else 135 size = (UInt32)(end - VirtPos); 136 } 137 } 138 if (!useBuf) 139 break; 140 if (alignedPos != PhyPos) 141 { 142 UInt64 realNewPosition; 143 const bool result = File.Seek((Int64)alignedPos, FILE_BEGIN, realNewPosition); 144 if (!result) 145 return ConvertBoolToHRESULT(result); 146 PhyPos = realNewPosition; 147 } 148 149 BufStartPos = alignedPos; 150 UInt32 readSize = kClusterSize; 151 if (File.SizeDefined) 152 readSize = (UInt32)MyMin(File.Size - PhyPos, (UInt64)kClusterSize); 153 154 if (!Buf) 155 { 156 Buf = (Byte *)MidAlloc(kClusterSize); 157 if (!Buf) 158 return E_OUTOFMEMORY; 159 } 160 const bool result = File.Read1(Buf, readSize, BufSize); 161 if (!result) 162 return ConvertBoolToHRESULT(result); 163 164 if (BufSize == 0) 165 return S_OK; 166 PhyPos += BufSize; 167 } 168 169 if (VirtPos != PhyPos) 170 { 171 UInt64 realNewPosition; 172 bool result = File.Seek((Int64)VirtPos, FILE_BEGIN, realNewPosition); 173 if (!result) 174 return ConvertBoolToHRESULT(result); 175 PhyPos = VirtPos = realNewPosition; 176 } 177 } 178 #endif 179 180 UInt32 realProcessedSize; 181 const bool result = File.ReadPart(data, size, realProcessedSize); 182 if (processedSize) 183 *processedSize = realProcessedSize; 184 185 #ifdef Z7_DEVICE_FILE 186 VirtPos += realProcessedSize; 187 PhyPos += realProcessedSize; 188 #endif 189 190 if (result) 191 return S_OK; 192 193 #else // Z7_FILE_STREAMS_USE_WIN_FILE 194 195 if (processedSize) 196 *processedSize = 0; 197 const ssize_t res = File.read_part(data, (size_t)size); 198 if (res != -1) 199 { 200 if (processedSize) 201 *processedSize = (UInt32)res; 202 return S_OK; 203 } 204 #endif // Z7_FILE_STREAMS_USE_WIN_FILE 205 206 { 207 const DWORD error = ::GetLastError(); 208 if (Callback) 209 return Callback->InFileStream_On_Error(CallbackRef, error); 210 if (error == 0) 211 return E_FAIL; 212 return HRESULT_FROM_WIN32(error); 213 } 214} 215 216#ifdef UNDER_CE 217Z7_COM7F_IMF(CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)) 218{ 219 size_t s2 = fread(data, 1, size, stdin); 220 int error = ferror(stdin); 221 if (processedSize) 222 *processedSize = s2; 223 if (s2 <= size && error == 0) 224 return S_OK; 225 return E_FAIL; 226} 227#else 228Z7_COM7F_IMF(CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)) 229{ 230 #ifdef _WIN32 231 232 DWORD realProcessedSize; 233 UInt32 sizeTemp = (1 << 20); 234 if (sizeTemp > size) 235 sizeTemp = size; 236 BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, sizeTemp, &realProcessedSize, NULL); 237 if (processedSize) 238 *processedSize = realProcessedSize; 239 if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE) 240 return S_OK; 241 return ConvertBoolToHRESULT(res != FALSE); 242 243 #else 244 245 if (processedSize) 246 *processedSize = 0; 247 ssize_t res; 248 do 249 { 250 res = read(0, data, (size_t)size); 251 } 252 while (res < 0 && (errno == EINTR)); 253 if (res == -1) 254 return GetLastError_HRESULT(); 255 if (processedSize) 256 *processedSize = (UInt32)res; 257 return S_OK; 258 259 #endif 260} 261 262#endif 263 264Z7_COM7F_IMF(CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) 265{ 266 if (seekOrigin >= 3) 267 return STG_E_INVALIDFUNCTION; 268 269 #ifdef Z7_FILE_STREAMS_USE_WIN_FILE 270 271 #ifdef Z7_DEVICE_FILE 272 if (File.IsDeviceFile && (File.SizeDefined || seekOrigin != STREAM_SEEK_END)) 273 { 274 switch (seekOrigin) 275 { 276 case STREAM_SEEK_SET: break; 277 case STREAM_SEEK_CUR: offset += VirtPos; break; 278 case STREAM_SEEK_END: offset += File.Size; break; 279 default: return STG_E_INVALIDFUNCTION; 280 } 281 if (offset < 0) 282 return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; 283 VirtPos = (UInt64)offset; 284 if (newPosition) 285 *newPosition = (UInt64)offset; 286 return S_OK; 287 } 288 #endif 289 290 UInt64 realNewPosition = 0; 291 const bool result = File.Seek(offset, seekOrigin, realNewPosition); 292 const HRESULT hres = ConvertBoolToHRESULT(result); 293 294 /* 21.07: new File.Seek() in 21.07 already returns correct (realNewPosition) 295 in case of error. So we don't need additional code below */ 296 // if (!result) { realNewPosition = 0; File.GetPosition(realNewPosition); } 297 298 #ifdef Z7_DEVICE_FILE 299 PhyPos = VirtPos = realNewPosition; 300 #endif 301 302 if (newPosition) 303 *newPosition = realNewPosition; 304 305 return hres; 306 307 #else 308 309 const off_t res = File.seek((off_t)offset, (int)seekOrigin); 310 if (res == -1) 311 { 312 const HRESULT hres = GetLastError_HRESULT(); 313 if (newPosition) 314 *newPosition = (UInt64)File.seekToCur(); 315 return hres; 316 } 317 if (newPosition) 318 *newPosition = (UInt64)res; 319 return S_OK; 320 321 #endif 322} 323 324Z7_COM7F_IMF(CInFileStream::GetSize(UInt64 *size)) 325{ 326 return ConvertBoolToHRESULT(File.GetLength(*size)); 327} 328 329#ifdef Z7_FILE_STREAMS_USE_WIN_FILE 330 331Z7_COM7F_IMF(CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib)) 332{ 333 if (!_info_WasLoaded) 334 { 335 RINOK(ReloadProps()) 336 } 337 const BY_HANDLE_FILE_INFORMATION &info = _info; 338 /* 339 BY_HANDLE_FILE_INFORMATION info; 340 if (!File.GetFileInformation(&info)) 341 return GetLastError_HRESULT(); 342 */ 343 { 344 if (size) *size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; 345 if (cTime) *cTime = info.ftCreationTime; 346 if (aTime) *aTime = info.ftLastAccessTime; 347 if (mTime) *mTime = info.ftLastWriteTime; 348 if (attrib) *attrib = info.dwFileAttributes; 349 return S_OK; 350 } 351} 352 353Z7_COM7F_IMF(CInFileStream::GetProps2(CStreamFileProps *props)) 354{ 355 if (!_info_WasLoaded) 356 { 357 RINOK(ReloadProps()) 358 } 359 const BY_HANDLE_FILE_INFORMATION &info = _info; 360 /* 361 BY_HANDLE_FILE_INFORMATION info; 362 if (!File.GetFileInformation(&info)) 363 return GetLastError_HRESULT(); 364 */ 365 { 366 props->Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; 367 props->VolID = info.dwVolumeSerialNumber; 368 props->FileID_Low = (((UInt64)info.nFileIndexHigh) << 32) + info.nFileIndexLow; 369 props->FileID_High = 0; 370 props->NumLinks = SupportHardLinks ? info.nNumberOfLinks : 1; 371 props->Attrib = info.dwFileAttributes; 372 props->CTime = info.ftCreationTime; 373 props->ATime = info.ftLastAccessTime; 374 props->MTime = info.ftLastWriteTime; 375 return S_OK; 376 } 377} 378 379Z7_COM7F_IMF(CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value)) 380{ 381 if (!_info_WasLoaded) 382 { 383 RINOK(ReloadProps()) 384 } 385 386 if (!_info_WasLoaded) 387 return S_OK; 388 389 NWindows::NCOM::CPropVariant prop; 390 391 #ifdef Z7_DEVICE_FILE 392 if (File.IsDeviceFile) 393 { 394 switch (propID) 395 { 396 case kpidSize: 397 if (File.SizeDefined) 398 prop = File.Size; 399 break; 400 // case kpidAttrib: prop = (UInt32)0; break; 401 case kpidPosixAttrib: 402 { 403 prop = (UInt32)NWindows::NFile::NFind::NAttributes:: 404 Get_PosixMode_From_WinAttrib(0); 405 /* GNU TAR by default can't extract file with MY_LIN_S_IFBLK attribute 406 so we don't use MY_LIN_S_IFBLK here */ 407 // prop = (UInt32)(MY_LIN_S_IFBLK | 0600); // for debug 408 break; 409 } 410 /* 411 case kpidDeviceMajor: 412 prop = (UInt32)8; // id for SCSI type device (sda) 413 break; 414 case kpidDeviceMinor: 415 prop = (UInt32)0; 416 break; 417 */ 418 } 419 } 420 else 421 #endif 422 { 423 switch (propID) 424 { 425 case kpidSize: 426 { 427 const UInt64 size = (((UInt64)_info.nFileSizeHigh) << 32) + _info.nFileSizeLow; 428 prop = size; 429 break; 430 } 431 case kpidAttrib: prop = (UInt32)_info.dwFileAttributes; break; 432 case kpidCTime: PropVariant_SetFrom_FiTime(prop, _info.ftCreationTime); break; 433 case kpidATime: PropVariant_SetFrom_FiTime(prop, _info.ftLastAccessTime); break; 434 case kpidMTime: PropVariant_SetFrom_FiTime(prop, _info.ftLastWriteTime); break; 435 case kpidPosixAttrib: 436 prop = (UInt32)NWindows::NFile::NFind::NAttributes:: 437 Get_PosixMode_From_WinAttrib(_info.dwFileAttributes); 438 // | (UInt32)(1 << 21); // for debug 439 break; 440 } 441 } 442 prop.Detach(value); 443 return S_OK; 444} 445 446 447Z7_COM7F_IMF(CInFileStream::ReloadProps()) 448{ 449 #ifdef Z7_DEVICE_FILE 450 if (File.IsDeviceFile) 451 { 452 memset(&_info, 0, sizeof(_info)); 453 if (File.SizeDefined) 454 { 455 _info.nFileSizeHigh = (DWORD)(File.Size >> 32); 456 _info.nFileSizeLow = (DWORD)(File.Size); 457 } 458 _info.nNumberOfLinks = 1; 459 _info_WasLoaded = true; 460 return S_OK; 461 } 462 #endif 463 _info_WasLoaded = File.GetFileInformation(&_info); 464 if (!_info_WasLoaded) 465 return GetLastError_HRESULT(); 466 return S_OK; 467} 468 469 470#elif !defined(_WIN32) 471 472Z7_COM7F_IMF(CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib)) 473{ 474 if (!_info_WasLoaded) 475 { 476 RINOK(ReloadProps()) 477 } 478 const struct stat &st = _info; 479 /* 480 struct stat st; 481 if (File.my_fstat(&st) != 0) 482 return GetLastError_HRESULT(); 483 */ 484 485 if (size) *size = (UInt64)st.st_size; 486 if (cTime) FiTime_To_FILETIME (ST_CTIME(st), *cTime); 487 if (aTime) FiTime_To_FILETIME (ST_ATIME(st), *aTime); 488 if (mTime) FiTime_To_FILETIME (ST_MTIME(st), *mTime); 489 if (attrib) *attrib = NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode); 490 491 return S_OK; 492} 493 494// #include <stdio.h> 495 496Z7_COM7F_IMF(CInFileStream::GetProps2(CStreamFileProps *props)) 497{ 498 if (!_info_WasLoaded) 499 { 500 RINOK(ReloadProps()) 501 } 502 const struct stat &st = _info; 503 /* 504 struct stat st; 505 if (File.my_fstat(&st) != 0) 506 return GetLastError_HRESULT(); 507 */ 508 509 props->Size = (UInt64)st.st_size; 510 /* 511 dev_t stat::st_dev: 512 GCC:Linux long unsigned int : __dev_t 513 Mac: int 514 */ 515 props->VolID = (UInt64)(Int64)st.st_dev; 516 props->FileID_Low = st.st_ino; 517 props->FileID_High = 0; 518 props->NumLinks = (UInt32)st.st_nlink; // we reduce to UInt32 from (nlink_t) that is (unsigned long) 519 props->Attrib = NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode); 520 521 FiTime_To_FILETIME (ST_CTIME(st), props->CTime); 522 FiTime_To_FILETIME (ST_ATIME(st), props->ATime); 523 FiTime_To_FILETIME (ST_MTIME(st), props->MTime); 524 525 /* 526 printf("\nGetProps2() NumLinks=%d = st_dev=%d st_ino = %d\n" 527 , (unsigned)(props->NumLinks) 528 , (unsigned)(st.st_dev) 529 , (unsigned)(st.st_ino) 530 ); 531 */ 532 533 return S_OK; 534} 535 536Z7_COM7F_IMF(CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value)) 537{ 538 if (!_info_WasLoaded) 539 { 540 RINOK(ReloadProps()) 541 } 542 543 if (!_info_WasLoaded) 544 return S_OK; 545 546 const struct stat &st = _info; 547 548 NWindows::NCOM::CPropVariant prop; 549 { 550 switch (propID) 551 { 552 case kpidSize: prop = (UInt64)st.st_size; break; 553 case kpidAttrib: 554 prop = (UInt32)NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode); 555 break; 556 case kpidCTime: PropVariant_SetFrom_FiTime(prop, ST_CTIME(st)); break; 557 case kpidATime: PropVariant_SetFrom_FiTime(prop, ST_ATIME(st)); break; 558 case kpidMTime: PropVariant_SetFrom_FiTime(prop, ST_MTIME(st)); break; 559 case kpidPosixAttrib: prop = (UInt32)st.st_mode; break; 560 561 #if defined(__APPLE__) 562 #pragma GCC diagnostic push 563 #pragma GCC diagnostic ignored "-Wsign-conversion" 564 #endif 565 566 case kpidDeviceMajor: 567 { 568 // printf("\nst.st_rdev = %d\n", st.st_rdev); 569 if (S_ISCHR(st.st_mode) || 570 S_ISBLK(st.st_mode)) 571 prop = (UInt32)(major(st.st_rdev)); // + 1000); 572 // prop = (UInt32)12345678; // for debug 573 break; 574 } 575 576 case kpidDeviceMinor: 577 if (S_ISCHR(st.st_mode) || 578 S_ISBLK(st.st_mode)) 579 prop = (UInt32)(minor(st.st_rdev)); // + 100); 580 // prop = (UInt32)(st.st_rdev); // for debug 581 // printf("\nst.st_rdev = %d\n", st.st_rdev); 582 // prop = (UInt32)123456789; // for debug 583 break; 584 585 #if defined(__APPLE__) 586 #pragma GCC diagnostic pop 587 #endif 588 589 /* 590 case kpidDevice: 591 if (S_ISCHR(st.st_mode) || 592 S_ISBLK(st.st_mode)) 593 prop = (UInt64)(st.st_rdev); 594 break; 595 */ 596 597 case kpidUserId: 598 { 599 if (StoreOwnerId) 600 prop = (UInt32)st.st_uid; 601 break; 602 } 603 case kpidGroupId: 604 { 605 if (StoreOwnerId) 606 prop = (UInt32)st.st_gid; 607 break; 608 } 609 case kpidUser: 610 { 611 if (StoreOwnerName) 612 { 613 const uid_t uid = st.st_uid; 614 { 615 if (!OwnerName.IsEmpty() && _uid == uid) 616 prop = OwnerName; 617 else 618 { 619 const passwd *pw = getpwuid(uid); 620 if (pw) 621 { 622 // we can use utf-8 here. 623 // prop = pw->pw_name; 624 } 625 } 626 } 627 } 628 break; 629 } 630 case kpidGroup: 631 { 632 if (StoreOwnerName) 633 { 634 const uid_t gid = st.st_gid; 635 { 636 if (!OwnerGroup.IsEmpty() && _gid == gid) 637 prop = OwnerGroup; 638 else 639 { 640 const group *gr = getgrgid(gid); 641 if (gr) 642 { 643 // we can use utf-8 here. 644 // prop = gr->gr_name; 645 } 646 } 647 } 648 } 649 break; 650 } 651 } 652 } 653 prop.Detach(value); 654 return S_OK; 655} 656 657 658Z7_COM7F_IMF(CInFileStream::ReloadProps()) 659{ 660 _info_WasLoaded = (File.my_fstat(&_info) == 0); 661 if (!_info_WasLoaded) 662 return GetLastError_HRESULT(); 663 return S_OK; 664} 665 666#endif 667 668 669 670 671////////////////////////// 672// COutFileStream 673 674HRESULT COutFileStream::Close() 675{ 676 return ConvertBoolToHRESULT(File.Close()); 677} 678 679Z7_COM7F_IMF(COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)) 680{ 681 #ifdef Z7_FILE_STREAMS_USE_WIN_FILE 682 683 UInt32 realProcessedSize; 684 const bool result = File.Write(data, size, realProcessedSize); 685 ProcessedSize += realProcessedSize; 686 if (processedSize) 687 *processedSize = realProcessedSize; 688 return ConvertBoolToHRESULT(result); 689 690 #else 691 692 if (processedSize) 693 *processedSize = 0; 694 size_t realProcessedSize; 695 const ssize_t res = File.write_full(data, (size_t)size, realProcessedSize); 696 ProcessedSize += realProcessedSize; 697 if (processedSize) 698 *processedSize = (UInt32)realProcessedSize; 699 if (res == -1) 700 return GetLastError_HRESULT(); 701 return S_OK; 702 703 #endif 704} 705 706Z7_COM7F_IMF(COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) 707{ 708 if (seekOrigin >= 3) 709 return STG_E_INVALIDFUNCTION; 710 711 #ifdef Z7_FILE_STREAMS_USE_WIN_FILE 712 713 UInt64 realNewPosition = 0; 714 const bool result = File.Seek(offset, seekOrigin, realNewPosition); 715 if (newPosition) 716 *newPosition = realNewPosition; 717 return ConvertBoolToHRESULT(result); 718 719 #else 720 721 const off_t res = File.seek((off_t)offset, (int)seekOrigin); 722 if (res == -1) 723 return GetLastError_HRESULT(); 724 if (newPosition) 725 *newPosition = (UInt64)res; 726 return S_OK; 727 728 #endif 729} 730 731Z7_COM7F_IMF(COutFileStream::SetSize(UInt64 newSize)) 732{ 733 return ConvertBoolToHRESULT(File.SetLength_KeepPosition(newSize)); 734} 735 736HRESULT COutFileStream::GetSize(UInt64 *size) 737{ 738 return ConvertBoolToHRESULT(File.GetLength(*size)); 739} 740 741#ifdef UNDER_CE 742 743Z7_COM7F_IMF(CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)) 744{ 745 size_t s2 = fwrite(data, 1, size, stdout); 746 if (processedSize) 747 *processedSize = s2; 748 return (s2 == size) ? S_OK : E_FAIL; 749} 750 751#else 752 753Z7_COM7F_IMF(CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)) 754{ 755 if (processedSize) 756 *processedSize = 0; 757 758 #ifdef _WIN32 759 760 UInt32 realProcessedSize; 761 BOOL res = TRUE; 762 if (size > 0) 763 { 764 // Seems that Windows doesn't like big amounts writing to stdout. 765 // So we limit portions by 32KB. 766 UInt32 sizeTemp = (1 << 15); 767 if (sizeTemp > size) 768 sizeTemp = size; 769 res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), 770 data, sizeTemp, (DWORD *)&realProcessedSize, NULL); 771 _size += realProcessedSize; 772 size -= realProcessedSize; 773 data = (const void *)((const Byte *)data + realProcessedSize); 774 if (processedSize) 775 *processedSize += realProcessedSize; 776 } 777 return ConvertBoolToHRESULT(res != FALSE); 778 779 #else 780 781 ssize_t res; 782 783 do 784 { 785 res = write(1, data, (size_t)size); 786 } 787 while (res < 0 && (errno == EINTR)); 788 789 if (res == -1) 790 return GetLastError_HRESULT(); 791 792 _size += (size_t)res; 793 if (processedSize) 794 *processedSize = (UInt32)res; 795 return S_OK; 796 797 #endif 798} 799 800#endif 801