1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sal.hxx" 26 27 #define UNICODE 28 #define _UNICODE 29 #define _WIN32_WINNT 0x0500 30 #include "systools/win32/uwinapi.h" 31 32 #include "osl/file.hxx" 33 34 #include "file_url.h" 35 #include "file_error.h" 36 37 #include "osl/diagnose.h" 38 #include "rtl/alloc.h" 39 #include "rtl/byteseq.h" 40 #include "rtl/ustring.hxx" 41 42 #include <stdio.h> 43 #include <tchar.h> 44 45 #ifdef __MINGW32__ 46 #include <wchar.h> 47 #include <ctype.h> 48 #endif 49 50 #include <algorithm> 51 #include <limits> 52 53 #ifdef max /* conflict w/ std::numeric_limits<T>::max() */ 54 #undef max 55 #endif 56 #ifdef min 57 #undef min 58 #endif 59 60 //################################################################## 61 // File handle implementation 62 //################################################################## 63 struct FileHandle_Impl 64 { 65 CRITICAL_SECTION m_mutex; 66 HANDLE m_hFile; 67 68 /** State 69 */ 70 enum StateBits 71 { 72 STATE_SEEKABLE = 1, /* open() sets, iff regular file */ 73 STATE_READABLE = 2, /* open() sets, read() requires */ 74 STATE_WRITEABLE = 4, /* open() sets, write() requires */ 75 STATE_MODIFIED = 8 /* write() sets, flush() resets */ 76 }; 77 int m_state; 78 79 sal_uInt64 m_size; /* file size */ 80 LONGLONG m_offset; /* physical offset from begin of file */ 81 LONGLONG m_filepos; /* logical offset from begin of file */ 82 83 LONGLONG m_bufptr; /* buffer offset from begin of file */ 84 SIZE_T m_buflen; /* buffer filled [0, m_bufsiz - 1] */ 85 86 SIZE_T m_bufsiz; 87 sal_uInt8 * m_buffer; 88 89 explicit FileHandle_Impl (HANDLE hFile); 90 ~FileHandle_Impl(); 91 92 static void* operator new(size_t n); 93 static void operator delete(void * p, size_t); 94 static SIZE_T getpagesize(); 95 96 sal_uInt64 getPos() const; 97 oslFileError setPos (sal_uInt64 uPos); 98 99 sal_uInt64 getSize() const; 100 oslFileError setSize (sal_uInt64 uPos); 101 102 oslFileError readAt ( 103 LONGLONG nOffset, 104 void * pBuffer, 105 DWORD nBytesRequested, 106 sal_uInt64 * pBytesRead); 107 108 oslFileError writeAt ( 109 LONGLONG nOffset, 110 void const * pBuffer, 111 DWORD nBytesToWrite, 112 sal_uInt64 * pBytesWritten); 113 114 oslFileError readFileAt ( 115 LONGLONG nOffset, 116 void * pBuffer, 117 sal_uInt64 uBytesRequested, 118 sal_uInt64 * pBytesRead); 119 120 oslFileError writeFileAt ( 121 LONGLONG nOffset, 122 void const * pBuffer, 123 sal_uInt64 uBytesToWrite, 124 sal_uInt64 * pBytesWritten); 125 126 oslFileError readLineAt ( 127 LONGLONG nOffset, 128 sal_Sequence ** ppSequence, 129 sal_uInt64 * pBytesRead); 130 131 oslFileError writeSequence_Impl ( 132 sal_Sequence ** ppSequence, 133 SIZE_T * pnOffset, 134 const void * pBuffer, 135 SIZE_T nBytes); 136 137 oslFileError syncFile(); 138 139 /** Buffer cache / allocator. 140 */ 141 class Allocator 142 { 143 rtl_cache_type * m_cache; 144 SIZE_T m_bufsiz; 145 146 Allocator (Allocator const &); 147 Allocator & operator= (Allocator const &); 148 149 public: 150 static Allocator & get(); 151 152 void allocate (sal_uInt8 ** ppBuffer, SIZE_T * pnSize); 153 void deallocate (sal_uInt8 * pBuffer); 154 155 protected: 156 Allocator(); 157 ~Allocator(); 158 }; 159 160 /** Guard. 161 */ 162 class Guard 163 { 164 LPCRITICAL_SECTION m_mutex; 165 166 public: 167 explicit Guard(LPCRITICAL_SECTION pMutex); 168 ~Guard(); 169 }; 170 }; 171 172 FileHandle_Impl::Allocator & 173 FileHandle_Impl::Allocator::get() 174 { 175 static Allocator g_aBufferAllocator; 176 return g_aBufferAllocator; 177 } 178 179 FileHandle_Impl::Allocator::Allocator() 180 : m_cache (0), 181 m_bufsiz (0) 182 { 183 SIZE_T const pagesize = FileHandle_Impl::getpagesize(); 184 m_cache = rtl_cache_create ( 185 "osl_file_buffer_cache", pagesize, 0, 0, 0, 0, 0, 0, 0); 186 if (0 != m_cache) 187 m_bufsiz = pagesize; 188 } 189 190 FileHandle_Impl::Allocator::~Allocator() 191 { 192 rtl_cache_destroy(m_cache), m_cache = 0; 193 } 194 195 void FileHandle_Impl::Allocator::allocate (sal_uInt8 ** ppBuffer, SIZE_T * pnSize) 196 { 197 OSL_PRECOND((0 != ppBuffer) && (0 != pnSize), "FileHandle_Impl::Allocator::allocate(): contract violation"); 198 *ppBuffer = static_cast< sal_uInt8* >(rtl_cache_alloc(m_cache)), *pnSize = m_bufsiz; 199 } 200 201 void FileHandle_Impl::Allocator::deallocate (sal_uInt8 * pBuffer) 202 { 203 if (0 != pBuffer) 204 rtl_cache_free (m_cache, pBuffer); 205 } 206 207 FileHandle_Impl::Guard::Guard(LPCRITICAL_SECTION pMutex) 208 : m_mutex (pMutex) 209 { 210 OSL_PRECOND (m_mutex != 0, "FileHandle_Impl::Guard::Guard(): null pointer."); 211 ::EnterCriticalSection (m_mutex); 212 } 213 FileHandle_Impl::Guard::~Guard() 214 { 215 OSL_PRECOND (m_mutex != 0, "FileHandle_Impl::Guard::~Guard(): null pointer."); 216 ::LeaveCriticalSection (m_mutex); 217 } 218 219 FileHandle_Impl::FileHandle_Impl(HANDLE hFile) 220 : m_hFile (hFile), 221 m_state (STATE_READABLE | STATE_WRITEABLE), 222 m_size (0), 223 m_offset (0), 224 m_filepos (0), 225 m_bufptr (-1), 226 m_buflen (0), 227 m_bufsiz (0), 228 m_buffer (0) 229 { 230 ::InitializeCriticalSection (&m_mutex); 231 Allocator::get().allocate (&m_buffer, &m_bufsiz); 232 if (m_buffer != 0) 233 memset (m_buffer, 0, m_bufsiz); 234 } 235 236 FileHandle_Impl::~FileHandle_Impl() 237 { 238 Allocator::get().deallocate (m_buffer), m_buffer = 0; 239 ::DeleteCriticalSection (&m_mutex); 240 } 241 242 void * FileHandle_Impl::operator new(size_t n) 243 { 244 return rtl_allocateMemory(n); 245 } 246 247 void FileHandle_Impl::operator delete(void * p, size_t) 248 { 249 rtl_freeMemory(p); 250 } 251 252 SIZE_T FileHandle_Impl::getpagesize() 253 { 254 SYSTEM_INFO info; 255 ::GetSystemInfo (&info); 256 return sal::static_int_cast< SIZE_T >(info.dwPageSize); 257 } 258 259 sal_uInt64 FileHandle_Impl::getPos() const 260 { 261 return sal::static_int_cast< sal_uInt64 >(m_filepos); 262 } 263 264 oslFileError FileHandle_Impl::setPos (sal_uInt64 uPos) 265 { 266 m_filepos = sal::static_int_cast< LONGLONG >(uPos); 267 return osl_File_E_None; 268 } 269 270 sal_uInt64 FileHandle_Impl::getSize() const 271 { 272 LONGLONG bufend = std::max((LONGLONG)(0), m_bufptr) + m_buflen; 273 return std::max(m_size, sal::static_int_cast< sal_uInt64 >(bufend)); 274 } 275 276 oslFileError FileHandle_Impl::setSize (sal_uInt64 uSize) 277 { 278 LARGE_INTEGER nDstPos; nDstPos.QuadPart = sal::static_int_cast< LONGLONG >(uSize); 279 if (!::SetFilePointerEx(m_hFile, nDstPos, 0, FILE_BEGIN)) 280 return oslTranslateFileError( GetLastError() ); 281 282 if (!::SetEndOfFile(m_hFile)) 283 return oslTranslateFileError( GetLastError() ); 284 m_size = uSize; 285 286 nDstPos.QuadPart = m_offset; 287 if (!::SetFilePointerEx(m_hFile, nDstPos, 0, FILE_BEGIN)) 288 return oslTranslateFileError( GetLastError() ); 289 290 return osl_File_E_None; 291 } 292 293 oslFileError FileHandle_Impl::readAt ( 294 LONGLONG nOffset, 295 void * pBuffer, 296 DWORD nBytesRequested, 297 sal_uInt64 * pBytesRead) 298 { 299 OSL_PRECOND(m_state & STATE_SEEKABLE, "FileHandle_Impl::readAt(): not seekable"); 300 if (!(m_state & STATE_SEEKABLE)) 301 return osl_File_E_SPIPE; 302 303 OSL_PRECOND(m_state & STATE_READABLE, "FileHandle_Impl::readAt(): not readable"); 304 if (!(m_state & STATE_READABLE)) 305 return osl_File_E_BADF; 306 307 if (nOffset != m_offset) 308 { 309 LARGE_INTEGER liOffset; liOffset.QuadPart = nOffset; 310 if (!::SetFilePointerEx(m_hFile, liOffset, 0, FILE_BEGIN)) 311 return oslTranslateFileError( GetLastError() ); 312 m_offset = nOffset; 313 } 314 315 DWORD dwDone = 0; 316 if (!::ReadFile(m_hFile, pBuffer, nBytesRequested, &dwDone, 0)) 317 return oslTranslateFileError( GetLastError() ); 318 m_offset += dwDone; 319 320 *pBytesRead = dwDone; 321 return osl_File_E_None; 322 } 323 324 oslFileError FileHandle_Impl::writeAt ( 325 LONGLONG nOffset, 326 void const * pBuffer, 327 DWORD nBytesToWrite, 328 sal_uInt64 * pBytesWritten) 329 { 330 OSL_PRECOND(m_state & STATE_SEEKABLE, "FileHandle_Impl::writeAt(): not seekable"); 331 if (!(m_state & STATE_SEEKABLE)) 332 return osl_File_E_SPIPE; 333 334 OSL_PRECOND(m_state & STATE_WRITEABLE, "FileHandle_Impl::writeAt(): not writeable"); 335 if (!(m_state & STATE_WRITEABLE)) 336 return osl_File_E_BADF; 337 338 if (nOffset != m_offset) 339 { 340 LARGE_INTEGER liOffset; liOffset.QuadPart = nOffset; 341 if (!::SetFilePointerEx (m_hFile, liOffset, 0, FILE_BEGIN)) 342 return oslTranslateFileError( GetLastError() ); 343 m_offset = nOffset; 344 } 345 346 DWORD dwDone = 0; 347 if (!::WriteFile(m_hFile, pBuffer, nBytesToWrite, &dwDone, 0)) 348 return oslTranslateFileError( GetLastError() ); 349 m_offset += dwDone; 350 351 m_size = std::max(m_size, sal::static_int_cast< sal_uInt64 >(m_offset)); 352 353 *pBytesWritten = dwDone; 354 return osl_File_E_None; 355 } 356 357 oslFileError FileHandle_Impl::readFileAt ( 358 LONGLONG nOffset, 359 void * pBuffer, 360 sal_uInt64 uBytesRequested, 361 sal_uInt64 * pBytesRead) 362 { 363 static sal_uInt64 const g_limit_dword = std::numeric_limits< DWORD >::max(); 364 if (g_limit_dword < uBytesRequested) 365 return osl_File_E_OVERFLOW; 366 DWORD nBytesRequested = sal::static_int_cast< DWORD >(uBytesRequested); 367 368 if (0 == (m_state & STATE_SEEKABLE)) 369 { 370 // not seekable (pipe) 371 DWORD dwDone = 0; 372 if (!::ReadFile(m_hFile, pBuffer, nBytesRequested, &dwDone, 0)) 373 return oslTranslateFileError( GetLastError() ); 374 *pBytesRead = dwDone; 375 return osl_File_E_None; 376 } 377 else if (0 == m_buffer) 378 { 379 // not buffered 380 return readAt (nOffset, pBuffer, nBytesRequested, pBytesRead); 381 } 382 else 383 { 384 sal_uInt8 * buffer = static_cast< sal_uInt8* >(pBuffer); 385 for (*pBytesRead = 0; nBytesRequested > 0; ) 386 { 387 LONGLONG const bufptr = (nOffset / m_bufsiz) * m_bufsiz; 388 SIZE_T const bufpos = (nOffset % m_bufsiz); 389 390 if (bufptr != m_bufptr) 391 { 392 // flush current buffer 393 oslFileError result = syncFile(); 394 if (result != osl_File_E_None) 395 return (result); 396 m_bufptr = -1, m_buflen = 0; 397 398 if (nBytesRequested >= m_bufsiz) 399 { 400 // buffer too small, read through from file 401 sal_uInt64 uDone = 0; 402 result = readAt (nOffset, &(buffer[*pBytesRead]), nBytesRequested, &uDone); 403 if (result != osl_File_E_None) 404 return (result); 405 406 nBytesRequested -= sal::static_int_cast< DWORD >(uDone), *pBytesRead += uDone; 407 return osl_File_E_None; 408 } 409 410 // update buffer (pointer) 411 sal_uInt64 uDone = 0; 412 result = readAt (bufptr, m_buffer, m_bufsiz, &uDone); 413 if (result != osl_File_E_None) 414 return (result); 415 m_bufptr = bufptr, m_buflen = sal::static_int_cast< SIZE_T >(uDone); 416 } 417 if (bufpos >= m_buflen) 418 { 419 // end of file 420 return osl_File_E_None; 421 } 422 423 SIZE_T const bytes = std::min(m_buflen - bufpos, nBytesRequested); 424 memcpy (&(buffer[*pBytesRead]), &(m_buffer[bufpos]), bytes); 425 nBytesRequested -= bytes, *pBytesRead += bytes, nOffset += bytes; 426 } 427 return osl_File_E_None; 428 } 429 } 430 431 oslFileError FileHandle_Impl::writeFileAt ( 432 LONGLONG nOffset, 433 void const * pBuffer, 434 sal_uInt64 uBytesToWrite, 435 sal_uInt64 * pBytesWritten) 436 { 437 static sal_uInt64 const g_limit_dword = std::numeric_limits< DWORD >::max(); 438 if (g_limit_dword < uBytesToWrite) 439 return osl_File_E_OVERFLOW; 440 DWORD nBytesToWrite = sal::static_int_cast< DWORD >(uBytesToWrite); 441 442 if (0 == (m_state & STATE_SEEKABLE)) 443 { 444 // not seekable (pipe) 445 DWORD dwDone = 0; 446 if (!::WriteFile(m_hFile, pBuffer, nBytesToWrite, &dwDone, 0)) 447 return oslTranslateFileError( GetLastError() ); 448 *pBytesWritten = dwDone; 449 return osl_File_E_None; 450 } 451 else if (0 == m_buffer) 452 { 453 // not buffered 454 return writeAt(nOffset, pBuffer, nBytesToWrite, pBytesWritten); 455 } 456 else 457 { 458 sal_uInt8 const * buffer = static_cast< sal_uInt8 const* >(pBuffer); 459 for (*pBytesWritten = 0; nBytesToWrite > 0; ) 460 { 461 LONGLONG const bufptr = (nOffset / m_bufsiz) * m_bufsiz; 462 SIZE_T const bufpos = (nOffset % m_bufsiz); 463 if (bufptr != m_bufptr) 464 { 465 // flush current buffer 466 oslFileError result = syncFile(); 467 if (result != osl_File_E_None) 468 return (result); 469 m_bufptr = -1, m_buflen = 0; 470 471 if (nBytesToWrite >= m_bufsiz) 472 { 473 // buffer too small, write through to file 474 sal_uInt64 uDone = 0; 475 result = writeAt (nOffset, &(buffer[*pBytesWritten]), nBytesToWrite, &uDone); 476 if (result != osl_File_E_None) 477 return (result); 478 if (uDone != nBytesToWrite) 479 return osl_File_E_IO; 480 481 nBytesToWrite -= sal::static_int_cast< DWORD >(uDone), *pBytesWritten += uDone; 482 return osl_File_E_None; 483 } 484 485 // update buffer (pointer) 486 sal_uInt64 uDone = 0; 487 result = readAt (bufptr, m_buffer, m_bufsiz, &uDone); 488 if (result != osl_File_E_None) 489 return (result); 490 m_bufptr = bufptr, m_buflen = sal::static_int_cast< SIZE_T >(uDone); 491 } 492 493 SIZE_T const bytes = std::min(m_bufsiz - bufpos, nBytesToWrite); 494 memcpy (&(m_buffer[bufpos]), &(buffer[*pBytesWritten]), bytes); 495 nBytesToWrite -= bytes, *pBytesWritten += bytes, nOffset += bytes; 496 497 m_buflen = std::max(m_buflen, bufpos + bytes); 498 m_state |= STATE_MODIFIED; 499 } 500 return osl_File_E_None; 501 } 502 } 503 504 oslFileError FileHandle_Impl::readLineAt ( 505 LONGLONG nOffset, 506 sal_Sequence ** ppSequence, 507 sal_uInt64 * pBytesRead) 508 { 509 oslFileError result = osl_File_E_None; 510 511 LONGLONG bufptr = (nOffset / m_bufsiz) * m_bufsiz; 512 if (bufptr != m_bufptr) 513 { 514 /* flush current buffer */ 515 result = syncFile(); 516 if (result != osl_File_E_None) 517 return (result); 518 519 /* update buffer (pointer) */ 520 sal_uInt64 uDone = 0; 521 result = readAt (bufptr, m_buffer, m_bufsiz, &uDone); 522 if (result != osl_File_E_None) 523 return (result); 524 525 m_bufptr = bufptr, m_buflen = sal::static_int_cast< SIZE_T >(uDone); 526 } 527 528 static int const LINE_STATE_BEGIN = 0; 529 static int const LINE_STATE_CR = 1; 530 static int const LINE_STATE_LF = 2; 531 532 SIZE_T bufpos = sal::static_int_cast< SIZE_T >(nOffset - m_bufptr), curpos = bufpos, dstpos = 0; 533 int state = (bufpos >= m_buflen) ? LINE_STATE_LF : LINE_STATE_BEGIN; 534 535 for ( ; state != LINE_STATE_LF; ) 536 { 537 if (curpos >= m_buflen) 538 { 539 /* buffer examined */ 540 if (0 < (curpos - bufpos)) 541 { 542 /* flush buffer to sequence */ 543 result = writeSequence_Impl ( 544 ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos); 545 if (result != osl_File_E_None) 546 return (result); 547 *pBytesRead += curpos - bufpos, nOffset += curpos - bufpos; 548 } 549 550 bufptr = nOffset / m_bufsiz * m_bufsiz; 551 if (bufptr != m_bufptr) 552 { 553 /* update buffer (pointer) */ 554 sal_uInt64 uDone = 0; 555 result = readAt (bufptr, m_buffer, m_bufsiz, &uDone); 556 if (result != osl_File_E_None) 557 return (result); 558 m_bufptr = bufptr, m_buflen = sal::static_int_cast< SIZE_T >(uDone); 559 } 560 561 bufpos = sal::static_int_cast< SIZE_T >(nOffset - m_bufptr), curpos = bufpos; 562 if (bufpos >= m_buflen) 563 break; 564 } 565 switch (state) 566 { 567 case LINE_STATE_CR: 568 state = LINE_STATE_LF; 569 switch (m_buffer[curpos]) 570 { 571 case 0x0A: /* CRLF */ 572 /* eat current char */ 573 curpos++; 574 break; 575 default: /* single CR */ 576 /* keep current char */ 577 break; 578 } 579 break; 580 default: 581 /* determine next state */ 582 switch (m_buffer[curpos]) 583 { 584 case 0x0A: /* single LF */ 585 state = LINE_STATE_LF; 586 break; 587 case 0x0D: /* CR */ 588 state = LINE_STATE_CR; 589 break; 590 default: /* advance to next char */ 591 curpos++; 592 break; 593 } 594 if (state != LINE_STATE_BEGIN) 595 { 596 /* store (and eat) the newline char */ 597 m_buffer[curpos] = 0x0A, curpos++; 598 599 /* flush buffer to sequence */ 600 result = writeSequence_Impl ( 601 ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos - 1); 602 if (result != osl_File_E_None) 603 return (result); 604 *pBytesRead += curpos - bufpos, nOffset += curpos - bufpos; 605 } 606 break; 607 } 608 } 609 610 result = writeSequence_Impl (ppSequence, &dstpos, 0, 0); 611 if (result != osl_File_E_None) 612 return (result); 613 if (0 < dstpos) 614 return osl_File_E_None; 615 if (bufpos >= m_buflen) 616 return osl_File_E_AGAIN; 617 return osl_File_E_None; 618 } 619 620 oslFileError FileHandle_Impl::writeSequence_Impl ( 621 sal_Sequence ** ppSequence, 622 SIZE_T * pnOffset, 623 const void * pBuffer, 624 SIZE_T nBytes) 625 { 626 sal_Int32 nElements = *pnOffset + nBytes; 627 if (!*ppSequence) 628 { 629 /* construct sequence */ 630 rtl_byte_sequence_constructNoDefault(ppSequence, nElements); 631 } 632 else if (nElements != (*ppSequence)->nElements) 633 { 634 /* resize sequence */ 635 rtl_byte_sequence_realloc(ppSequence, nElements); 636 } 637 if (*ppSequence != 0) 638 { 639 /* fill sequence */ 640 memcpy(&((*ppSequence)->elements[*pnOffset]), pBuffer, nBytes), *pnOffset += nBytes; 641 } 642 return (*ppSequence != 0) ? osl_File_E_None : osl_File_E_NOMEM; 643 } 644 645 oslFileError FileHandle_Impl::syncFile() 646 { 647 oslFileError result = osl_File_E_None; 648 if (m_state & STATE_MODIFIED) 649 { 650 sal_uInt64 uDone = 0; 651 result = writeAt (m_bufptr, m_buffer, m_buflen, &uDone); 652 if (result != osl_File_E_None) 653 return (result); 654 if (uDone != m_buflen) 655 return osl_File_E_IO; 656 m_state &= ~STATE_MODIFIED; 657 } 658 return (result); 659 } 660 661 //################################################################## 662 // File I/O functions 663 //################################################################## 664 665 extern "C" oslFileHandle 666 SAL_CALL osl_createFileHandleFromOSHandle ( 667 HANDLE hFile, 668 sal_uInt32 uFlags) 669 { 670 if ( !IsValidHandle(hFile) ) 671 return 0; // EINVAL 672 673 FileHandle_Impl * pImpl = new FileHandle_Impl(hFile); 674 if (pImpl == 0) 675 { 676 // cleanup and fail 677 (void) ::CloseHandle(hFile); 678 return 0; // ENOMEM 679 } 680 681 /* check for regular file */ 682 if (FILE_TYPE_DISK == GetFileType(hFile)) 683 { 684 /* mark seekable */ 685 pImpl->m_state |= FileHandle_Impl::STATE_SEEKABLE; 686 687 /* init current size */ 688 LARGE_INTEGER uSize = { 0, 0 }; 689 (void) ::GetFileSizeEx(hFile, &uSize); 690 pImpl->m_size = (sal::static_int_cast<sal_uInt64>(uSize.HighPart) << 32) + uSize.LowPart; 691 } 692 693 if (!(uFlags & osl_File_OpenFlag_Read)) 694 pImpl->m_state &= ~FileHandle_Impl::STATE_READABLE; 695 if (!(uFlags & osl_File_OpenFlag_Write)) 696 pImpl->m_state &= ~FileHandle_Impl::STATE_WRITEABLE; 697 698 OSL_POSTCOND( 699 (uFlags & osl_File_OpenFlag_Read) || (uFlags & osl_File_OpenFlag_Write), 700 "osl_createFileHandleFromOSHandle(): missing read/write access flags"); 701 return (oslFileHandle)(pImpl); 702 } 703 704 //############################################# 705 oslFileError 706 SAL_CALL osl_openFile( 707 rtl_uString * strPath, 708 oslFileHandle * pHandle, 709 sal_uInt32 uFlags ) 710 { 711 rtl_uString * strSysPath = 0; 712 oslFileError result = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False ); 713 if (result != osl_File_E_None) 714 return (result); 715 716 DWORD dwAccess = GENERIC_READ, dwShare = FILE_SHARE_READ, dwCreation = 0, dwAttributes = 0; 717 718 if ( uFlags & osl_File_OpenFlag_Write ) 719 dwAccess |= GENERIC_WRITE; 720 else 721 dwShare |= FILE_SHARE_WRITE; 722 723 if ( uFlags & osl_File_OpenFlag_NoLock ) 724 dwShare |= FILE_SHARE_WRITE; 725 726 if ( uFlags & osl_File_OpenFlag_Create ) 727 dwCreation |= CREATE_NEW; 728 else 729 dwCreation |= OPEN_EXISTING; 730 731 HANDLE hFile = CreateFileW( 732 reinterpret_cast<LPCWSTR>(rtl_uString_getStr( strSysPath )), 733 dwAccess, dwShare, NULL, dwCreation, dwAttributes, NULL ); 734 735 // @@@ ERROR HANDLING @@@ 736 if ( !IsValidHandle( hFile ) ) 737 result = oslTranslateFileError( GetLastError() ); 738 739 *pHandle = osl_createFileHandleFromOSHandle (hFile, uFlags | osl_File_OpenFlag_Read); 740 741 rtl_uString_release( strSysPath ); 742 return (result); 743 } 744 745 //############################################# 746 oslFileError 747 SAL_CALL osl_syncFile(oslFileHandle Handle) 748 { 749 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle); 750 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile)) 751 return osl_File_E_INVAL; 752 753 FileHandle_Impl::Guard lock (&(pImpl->m_mutex)); 754 755 oslFileError result = pImpl->syncFile(); 756 if (result != osl_File_E_None) 757 return result; 758 759 if (!FlushFileBuffers(pImpl->m_hFile)) 760 return oslTranslateFileError(GetLastError()); 761 762 return osl_File_E_None; 763 } 764 765 //############################################# 766 oslFileError 767 SAL_CALL osl_closeFile(oslFileHandle Handle) 768 { 769 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle); 770 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile)) 771 return osl_File_E_INVAL; 772 773 ::EnterCriticalSection (&(pImpl->m_mutex)); 774 775 oslFileError result = pImpl->syncFile(); 776 if (result != osl_File_E_None) 777 { 778 /* ignore double failure */ 779 (void)::CloseHandle(pImpl->m_hFile); 780 } 781 else if (!::CloseHandle(pImpl->m_hFile)) 782 { 783 /* translate error code */ 784 result = oslTranslateFileError( GetLastError() ); 785 } 786 787 ::LeaveCriticalSection (&(pImpl->m_mutex)); 788 delete pImpl; 789 return (result); 790 } 791 792 //############################################# 793 oslFileError 794 SAL_CALL osl_mapFile( 795 oslFileHandle Handle, 796 void** ppAddr, 797 sal_uInt64 uLength, 798 sal_uInt64 uOffset, 799 sal_uInt32 uFlags) 800 { 801 struct FileMapping 802 { 803 HANDLE m_handle; 804 805 explicit FileMapping (HANDLE hMap) 806 : m_handle (hMap) 807 {} 808 809 ~FileMapping() 810 { 811 (void)::CloseHandle(m_handle); 812 } 813 }; 814 815 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle); 816 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == ppAddr)) 817 return osl_File_E_INVAL; 818 *ppAddr = 0; 819 820 static SIZE_T const nLimit = std::numeric_limits< SIZE_T >::max(); 821 if (uLength > nLimit) 822 return osl_File_E_OVERFLOW; 823 SIZE_T const nLength = sal::static_int_cast< SIZE_T >(uLength); 824 825 OSVERSIONINFO osinfo; 826 osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 827 (void)::GetVersionEx(&osinfo); 828 829 if (VER_PLATFORM_WIN32_NT != osinfo.dwPlatformId) 830 return osl_File_E_NOSYS; // Unsupported 831 832 FileMapping aMap( ::CreateFileMapping (pImpl->m_hFile, NULL, SEC_COMMIT | PAGE_READONLY, 0, 0, NULL) ); 833 if (!IsValidHandle(aMap.m_handle)) 834 return oslTranslateFileError( GetLastError() ); 835 836 DWORD const dwOffsetHi = sal::static_int_cast<DWORD>(uOffset >> 32); 837 DWORD const dwOffsetLo = sal::static_int_cast<DWORD>(uOffset & 0xFFFFFFFF); 838 839 *ppAddr = ::MapViewOfFile( aMap.m_handle, FILE_MAP_READ, dwOffsetHi, dwOffsetLo, nLength ); 840 if (0 == *ppAddr) 841 return oslTranslateFileError( GetLastError() ); 842 843 if (uFlags & osl_File_MapFlag_RandomAccess) 844 { 845 // Determine memory pagesize. 846 SYSTEM_INFO info; 847 ::GetSystemInfo( &info ); 848 DWORD const dwPageSize = info.dwPageSize; 849 850 /* 851 * Pagein, touching first byte of each memory page. 852 * Note: volatile disables optimizing the loop away. 853 */ 854 BYTE * pData (reinterpret_cast<BYTE*>(*ppAddr)); 855 SIZE_T nSize (nLength); 856 857 volatile BYTE c = 0; 858 while (nSize > dwPageSize) 859 { 860 c ^= pData[0]; 861 pData += dwPageSize; 862 nSize -= dwPageSize; 863 } 864 if (nSize > 0) 865 { 866 c ^= pData[0]; 867 pData += nSize; 868 nSize -= nSize; 869 } 870 } 871 return osl_File_E_None; 872 } 873 874 //############################################# 875 oslFileError 876 SAL_CALL osl_unmapFile(void* pAddr, sal_uInt64 /* uLength */) 877 { 878 if (0 == pAddr) 879 return osl_File_E_INVAL; 880 881 if (!::UnmapViewOfFile (pAddr)) 882 return oslTranslateFileError( GetLastError() ); 883 884 return osl_File_E_None; 885 } 886 887 //############################################# 888 oslFileError 889 SAL_CALL osl_readLine( 890 oslFileHandle Handle, 891 sal_Sequence ** ppSequence) 892 { 893 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle); 894 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == ppSequence)) 895 return osl_File_E_INVAL; 896 sal_uInt64 uBytesRead = 0; 897 898 // read at current filepos; filepos += uBytesRead; 899 FileHandle_Impl::Guard lock (&(pImpl->m_mutex)); 900 oslFileError result = pImpl->readLineAt ( 901 pImpl->m_filepos, ppSequence, &uBytesRead); 902 if (result == osl_File_E_None) 903 pImpl->m_filepos += uBytesRead; 904 return (result); 905 } 906 907 //############################################# 908 oslFileError 909 SAL_CALL osl_readFile( 910 oslFileHandle Handle, 911 void * pBuffer, 912 sal_uInt64 uBytesRequested, 913 sal_uInt64 * pBytesRead) 914 { 915 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle); 916 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pBuffer) || (0 == pBytesRead)) 917 return osl_File_E_INVAL; 918 919 // read at current filepos; filepos += *pBytesRead; 920 FileHandle_Impl::Guard lock (&(pImpl->m_mutex)); 921 oslFileError result = pImpl->readFileAt ( 922 pImpl->m_filepos, pBuffer, uBytesRequested, pBytesRead); 923 if (result == osl_File_E_None) 924 pImpl->m_filepos += *pBytesRead; 925 return (result); 926 } 927 928 //############################################# 929 oslFileError 930 SAL_CALL osl_writeFile( 931 oslFileHandle Handle, 932 const void * pBuffer, 933 sal_uInt64 uBytesToWrite, 934 sal_uInt64 * pBytesWritten ) 935 { 936 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle); 937 938 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pBuffer) || (0 == pBytesWritten)) 939 return osl_File_E_INVAL; 940 941 // write at current filepos; filepos += *pBytesWritten; 942 FileHandle_Impl::Guard lock (&(pImpl->m_mutex)); 943 oslFileError result = pImpl->writeFileAt ( 944 pImpl->m_filepos, pBuffer, uBytesToWrite, pBytesWritten); 945 if (result == osl_File_E_None) 946 pImpl->m_filepos += *pBytesWritten; 947 return (result); 948 } 949 950 //############################################# 951 oslFileError 952 SAL_CALL osl_readFileAt( 953 oslFileHandle Handle, 954 sal_uInt64 uOffset, 955 void* pBuffer, 956 sal_uInt64 uBytesRequested, 957 sal_uInt64* pBytesRead) 958 { 959 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle); 960 961 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pBuffer) || (0 == pBytesRead)) 962 return osl_File_E_INVAL; 963 if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE)) 964 return osl_File_E_SPIPE; 965 966 static sal_uInt64 const g_limit_longlong = std::numeric_limits< LONGLONG >::max(); 967 if (g_limit_longlong < uOffset) 968 return osl_File_E_OVERFLOW; 969 LONGLONG const nOffset = sal::static_int_cast< LONGLONG >(uOffset); 970 971 // read at specified fileptr 972 FileHandle_Impl::Guard lock (&(pImpl->m_mutex)); 973 return pImpl->readFileAt (nOffset, pBuffer, uBytesRequested, pBytesRead); 974 } 975 976 //############################################# 977 oslFileError 978 SAL_CALL osl_writeFileAt( 979 oslFileHandle Handle, 980 sal_uInt64 uOffset, 981 const void* pBuffer, 982 sal_uInt64 uBytesToWrite, 983 sal_uInt64* pBytesWritten) 984 { 985 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle); 986 987 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pBuffer) || (0 == pBytesWritten)) 988 return osl_File_E_INVAL; 989 if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE)) 990 return osl_File_E_SPIPE; 991 992 static sal_uInt64 const g_limit_longlong = std::numeric_limits< LONGLONG >::max(); 993 if (g_limit_longlong < uOffset) 994 return osl_File_E_OVERFLOW; 995 LONGLONG const nOffset = sal::static_int_cast< LONGLONG >(uOffset); 996 997 // write at specified fileptr 998 FileHandle_Impl::Guard lock (&(pImpl->m_mutex)); 999 return pImpl->writeFileAt (nOffset, pBuffer, uBytesToWrite, pBytesWritten); 1000 } 1001 1002 //############################################# 1003 oslFileError 1004 SAL_CALL osl_isEndOfFile (oslFileHandle Handle, sal_Bool *pIsEOF) 1005 { 1006 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle); 1007 1008 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pIsEOF)) 1009 return osl_File_E_INVAL; 1010 1011 FileHandle_Impl::Guard lock (&(pImpl->m_mutex)); 1012 *pIsEOF = (pImpl->getPos() == pImpl->getSize()); 1013 return osl_File_E_None; 1014 } 1015 1016 //############################################# 1017 oslFileError 1018 SAL_CALL osl_getFilePos(oslFileHandle Handle, sal_uInt64 *pPos) 1019 { 1020 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle); 1021 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pPos)) 1022 return osl_File_E_INVAL; 1023 1024 FileHandle_Impl::Guard lock (&(pImpl->m_mutex)); 1025 *pPos = pImpl->getPos(); 1026 return osl_File_E_None; 1027 } 1028 1029 //############################################# 1030 oslFileError 1031 SAL_CALL osl_setFilePos(oslFileHandle Handle, sal_uInt32 uHow, sal_Int64 uOffset) 1032 { 1033 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle); 1034 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile)) 1035 return osl_File_E_INVAL; 1036 1037 static sal_Int64 const g_limit_longlong = std::numeric_limits< LONGLONG >::max(); 1038 if (g_limit_longlong < uOffset) 1039 return osl_File_E_OVERFLOW; 1040 LONGLONG nPos = 0, nOffset = sal::static_int_cast< LONGLONG >(uOffset); 1041 1042 FileHandle_Impl::Guard lock (&(pImpl->m_mutex)); 1043 switch (uHow) 1044 { 1045 case osl_Pos_Absolut: 1046 if (0 > nOffset) 1047 return osl_File_E_INVAL; 1048 break; 1049 1050 case osl_Pos_Current: 1051 nPos = sal::static_int_cast< LONGLONG >(pImpl->getPos()); 1052 if ((0 > nOffset) && (-1*nOffset > nPos)) 1053 return osl_File_E_INVAL; 1054 if (g_limit_longlong < nPos + nOffset) 1055 return osl_File_E_OVERFLOW; 1056 break; 1057 1058 case osl_Pos_End: 1059 nPos = sal::static_int_cast< LONGLONG >(pImpl->getSize()); 1060 if ((0 > nOffset) && (-1*nOffset > nPos)) 1061 return osl_File_E_INVAL; 1062 if (g_limit_longlong < nPos + nOffset) 1063 return osl_File_E_OVERFLOW; 1064 break; 1065 1066 default: 1067 return osl_File_E_INVAL; 1068 } 1069 1070 return pImpl->setPos (nPos + nOffset); 1071 } 1072 1073 //############################################# 1074 oslFileError 1075 SAL_CALL osl_getFileSize (oslFileHandle Handle, sal_uInt64 *pSize) 1076 { 1077 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle); 1078 1079 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pSize)) 1080 return osl_File_E_INVAL; 1081 1082 FileHandle_Impl::Guard lock (&(pImpl->m_mutex)); 1083 *pSize = pImpl->getSize(); 1084 return osl_File_E_None; 1085 } 1086 1087 //############################################# 1088 oslFileError 1089 SAL_CALL osl_setFileSize (oslFileHandle Handle, sal_uInt64 uSize) 1090 { 1091 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle); 1092 1093 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile)) 1094 return osl_File_E_INVAL; 1095 if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE)) 1096 return osl_File_E_BADF; 1097 1098 static sal_uInt64 const g_limit_longlong = std::numeric_limits< LONGLONG >::max(); 1099 if (g_limit_longlong < uSize) 1100 return osl_File_E_OVERFLOW; 1101 1102 FileHandle_Impl::Guard lock (&(pImpl->m_mutex)); 1103 oslFileError result = pImpl->syncFile(); 1104 if (result != osl_File_E_None) 1105 return (result); 1106 pImpl->m_bufptr = -1, pImpl->m_buflen = 0; 1107 1108 return pImpl->setSize (uSize); 1109 } 1110 1111 //################################################################## 1112 // File handling functions 1113 //################################################################## 1114 1115 //############################################# 1116 oslFileError SAL_CALL osl_removeFile( rtl_uString* strPath ) 1117 { 1118 rtl_uString *strSysPath = NULL; 1119 oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False ); 1120 1121 if ( osl_File_E_None == error ) 1122 { 1123 if ( DeleteFile( reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath )) ) ) 1124 error = osl_File_E_None; 1125 else 1126 error = oslTranslateFileError( GetLastError() ); 1127 1128 rtl_uString_release( strSysPath ); 1129 } 1130 return error; 1131 } 1132 1133 //############################################# 1134 #define osl_File_CopyRecursive 0x0001 1135 #define osl_File_CopyOverwrite 0x0002 1136 1137 oslFileError SAL_CALL osl_copyFile( rtl_uString* strPath, rtl_uString *strDestPath ) 1138 { 1139 rtl_uString *strSysPath = NULL, *strSysDestPath = NULL; 1140 oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False ); 1141 1142 if ( osl_File_E_None == error ) 1143 error = _osl_getSystemPathFromFileURL( strDestPath, &strSysDestPath, sal_False ); 1144 1145 if ( osl_File_E_None == error ) 1146 { 1147 LPCTSTR src = reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath )); 1148 LPCTSTR dst = reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysDestPath )); 1149 1150 if ( CopyFile( src, dst, FALSE ) ) 1151 error = osl_File_E_None; 1152 else 1153 error = oslTranslateFileError( GetLastError() ); 1154 } 1155 1156 if ( strSysPath ) 1157 rtl_uString_release( strSysPath ); 1158 if ( strSysDestPath ) 1159 rtl_uString_release( strSysDestPath ); 1160 1161 return error; 1162 } 1163 1164 //############################################# 1165 oslFileError SAL_CALL osl_moveFile( rtl_uString* strPath, rtl_uString *strDestPath ) 1166 { 1167 rtl_uString *strSysPath = NULL, *strSysDestPath = NULL; 1168 oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False ); 1169 1170 if ( osl_File_E_None == error ) 1171 error = _osl_getSystemPathFromFileURL( strDestPath, &strSysDestPath, sal_False ); 1172 1173 if ( osl_File_E_None == error ) 1174 { 1175 LPCTSTR src = reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath )); 1176 LPCTSTR dst = reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysDestPath )); 1177 1178 if ( MoveFileEx( src, dst, MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING ) ) 1179 error = osl_File_E_None; 1180 else 1181 error = oslTranslateFileError( GetLastError() ); 1182 } 1183 1184 if ( strSysPath ) 1185 rtl_uString_release( strSysPath ); 1186 if ( strSysDestPath ) 1187 rtl_uString_release( strSysDestPath ); 1188 1189 return error; 1190 } 1191