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