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 #include "osl/file.hxx" 32 33 #include "osl/diagnose.h" 34 #include "rtl/alloc.h" 35 36 #include "system.h" 37 #include "file_error_transl.h" 38 #include "file_url.h" 39 40 #include <algorithm> 41 #include <limits> 42 43 #include <string.h> 44 #include <pthread.h> 45 #include <sys/mman.h> 46 47 #if defined(MACOSX) 48 49 #include <sys/param.h> 50 #include <sys/mount.h> 51 #define HAVE_O_EXLOCK 52 53 // add MACOSX Time Value 54 #define TimeValue CFTimeValue 55 #include <CoreFoundation/CoreFoundation.h> 56 #undef TimeValue 57 58 #endif /* MACOSX */ 59 60 #ifdef DEBUG_OSL_FILE 61 # define OSL_FILE_TRACE 0 ? (void)(0) : osl_trace 62 # define PERROR( a, b ) perror( a ); fprintf( stderr, b ) 63 #else 64 # define OSL_FILE_TRACE 1 ? (void)(0) : osl_trace 65 # define PERROR( a, b ) 66 #endif 67 68 /******************************************************************* 69 * 70 * FileHandle_Impl interface 71 * 72 ******************************************************************/ 73 struct FileHandle_Impl 74 { 75 pthread_mutex_t m_mutex; 76 rtl_String * m_strFilePath; /* holds native file path */ 77 int m_fd; 78 79 /** State 80 */ 81 enum StateBits 82 { 83 STATE_SEEKABLE = 1, /* default */ 84 STATE_READABLE = 2, /* default */ 85 STATE_WRITEABLE = 4, /* open() sets, write() requires, else osl_File_E_BADF */ 86 STATE_MODIFIED = 8 /* write() sets, flush() resets */ 87 }; 88 int m_state; 89 90 sal_uInt64 m_size; /* file size */ 91 off_t m_offset; /* physical offset from begin of file */ 92 off_t m_fileptr; /* logical offset from begin of file */ 93 94 off_t m_bufptr; /* buffer offset from begin of file */ 95 size_t m_buflen; /* buffer filled [0, m_bufsiz - 1] */ 96 97 size_t m_bufsiz; 98 sal_uInt8 * m_buffer; 99 100 explicit FileHandle_Impl (int fd, char const * path = "<anon>"); 101 ~FileHandle_Impl(); 102 103 static void* operator new (size_t n); 104 static void operator delete (void * p, size_t); 105 106 static size_t getpagesize(); 107 108 sal_uInt64 getPos() const; 109 oslFileError setPos (sal_uInt64 uPos); 110 111 sal_uInt64 getSize() const; 112 oslFileError setSize (sal_uInt64 uSize); 113 114 oslFileError readAt ( 115 off_t nOffset, 116 void * pBuffer, 117 size_t nBytesRequested, 118 sal_uInt64 * pBytesRead); 119 120 oslFileError writeAt ( 121 off_t nOffset, 122 void const * pBuffer, 123 size_t nBytesToWrite, 124 sal_uInt64 * pBytesWritten); 125 126 oslFileError readFileAt ( 127 off_t nOffset, 128 void * pBuffer, 129 size_t nBytesRequested, 130 sal_uInt64 * pBytesRead); 131 132 oslFileError writeFileAt ( 133 off_t nOffset, 134 void const * pBuffer, 135 size_t nBytesToWrite, 136 sal_uInt64 * pBytesWritten); 137 138 oslFileError readLineAt ( 139 off_t nOffset, 140 sal_Sequence ** ppSequence, 141 sal_uInt64 * pBytesRead); 142 143 oslFileError writeSequence_Impl ( 144 sal_Sequence ** ppSequence, 145 size_t * pnOffset, 146 const void * pBuffer, 147 size_t nBytes); 148 149 oslFileError syncFile(); 150 151 /** Buffer cache / allocator. 152 */ 153 class Allocator 154 { 155 rtl_cache_type * m_cache; 156 size_t m_bufsiz; 157 158 Allocator (Allocator const &); 159 Allocator & operator= (Allocator const &); 160 161 public: 162 static Allocator & get(); 163 164 void allocate (sal_uInt8 ** ppBuffer, size_t * pnSize); 165 void deallocate (sal_uInt8 * pBuffer); 166 167 protected: 168 Allocator(); 169 ~Allocator(); 170 }; 171 172 /** Guard. 173 */ 174 class Guard 175 { 176 pthread_mutex_t * m_mutex; 177 178 public: 179 explicit Guard(pthread_mutex_t * pMutex); 180 ~Guard(); 181 }; 182 }; 183 184 /******************************************************************* 185 * 186 * FileHandle_Impl implementation 187 * 188 ******************************************************************/ 189 190 FileHandle_Impl::Allocator & 191 FileHandle_Impl::Allocator::get() 192 { 193 static Allocator g_aBufferAllocator; 194 return g_aBufferAllocator; 195 } 196 197 FileHandle_Impl::Allocator::Allocator() 198 : m_cache (0), 199 m_bufsiz (0) 200 { 201 size_t const pagesize = FileHandle_Impl::getpagesize(); 202 if (size_t(-1) != pagesize) 203 { 204 m_cache = rtl_cache_create ( 205 "osl_file_buffer_cache", pagesize, 0, 0, 0, 0, 0, 0, 0); 206 if (0 != m_cache) 207 m_bufsiz = pagesize; 208 } 209 } 210 FileHandle_Impl::Allocator::~Allocator() 211 { 212 rtl_cache_destroy (m_cache), m_cache = 0; 213 } 214 215 void FileHandle_Impl::Allocator::allocate (sal_uInt8 ** ppBuffer, size_t * pnSize) 216 { 217 OSL_PRECOND((0 != ppBuffer) && (0 != pnSize), "FileHandle_Impl::Allocator::allocate(): contract violation"); 218 if ((0 != ppBuffer) && (0 != pnSize)) 219 *ppBuffer = static_cast< sal_uInt8* >(rtl_cache_alloc(m_cache)), *pnSize = m_bufsiz; 220 } 221 void FileHandle_Impl::Allocator::deallocate (sal_uInt8 * pBuffer) 222 { 223 if (0 != pBuffer) 224 rtl_cache_free (m_cache, pBuffer); 225 } 226 227 FileHandle_Impl::Guard::Guard(pthread_mutex_t * pMutex) 228 : m_mutex (pMutex) 229 { 230 OSL_PRECOND (m_mutex != 0, "FileHandle_Impl::Guard::Guard(): null pointer."); 231 (void) pthread_mutex_lock (m_mutex); // ignoring EINVAL ... 232 } 233 FileHandle_Impl::Guard::~Guard() 234 { 235 OSL_PRECOND (m_mutex != 0, "FileHandle_Impl::Guard::~Guard(): null pointer."); 236 (void) pthread_mutex_unlock (m_mutex); 237 } 238 239 FileHandle_Impl::FileHandle_Impl (int fd, char const * path) 240 : m_strFilePath (0), 241 m_fd (fd), 242 m_state (STATE_SEEKABLE | STATE_READABLE), 243 m_size (0), 244 m_offset (0), 245 m_fileptr (0), 246 m_bufptr (-1), 247 m_buflen (0), 248 m_bufsiz (0), 249 m_buffer (0) 250 { 251 (void) pthread_mutex_init(&m_mutex, 0); 252 rtl_string_newFromStr (&m_strFilePath, path); 253 Allocator::get().allocate (&m_buffer, &m_bufsiz); 254 if (0 != m_buffer) 255 memset (m_buffer, 0, m_bufsiz); 256 } 257 FileHandle_Impl::~FileHandle_Impl() 258 { 259 Allocator::get().deallocate (m_buffer), m_buffer = 0; 260 rtl_string_release (m_strFilePath), m_strFilePath = 0; 261 (void) pthread_mutex_destroy(&m_mutex); // ignoring EBUSY ... 262 } 263 264 void* FileHandle_Impl::operator new (size_t n) 265 { 266 return rtl_allocateMemory(n); 267 } 268 void FileHandle_Impl::operator delete (void * p, size_t) 269 { 270 rtl_freeMemory(p); 271 } 272 273 size_t FileHandle_Impl::getpagesize() 274 { 275 #if defined(FREEBSD) || defined(NETBSD) || defined(MACOSX) 276 return sal::static_int_cast< size_t >(::getpagesize()); 277 #else /* POSIX */ 278 return sal::static_int_cast< size_t >(::sysconf(_SC_PAGESIZE)); 279 #endif /* xBSD || POSIX */ 280 } 281 282 sal_uInt64 FileHandle_Impl::getPos() const 283 { 284 return sal::static_int_cast< sal_uInt64 >(m_fileptr); 285 } 286 287 oslFileError FileHandle_Impl::setPos (sal_uInt64 uPos) 288 { 289 OSL_FILE_TRACE("FileHandle_Impl::setPos(%d, %lld) => %lld", m_fd, getPos(), uPos); 290 m_fileptr = sal::static_int_cast< off_t >(uPos); 291 return osl_File_E_None; 292 } 293 294 sal_uInt64 FileHandle_Impl::getSize() const 295 { 296 off_t const bufend = std::max((off_t)(0), m_bufptr) + m_buflen; 297 return std::max(m_size, sal::static_int_cast< sal_uInt64 >(bufend)); 298 } 299 300 oslFileError FileHandle_Impl::setSize (sal_uInt64 uSize) 301 { 302 off_t const nSize = sal::static_int_cast< off_t >(uSize); 303 if (-1 == ftruncate (m_fd, nSize)) 304 { 305 /* Failure. Save original result. Try fallback algorithm */ 306 oslFileError result = oslTranslateFileError (OSL_FET_ERROR, errno); 307 308 /* Check against current size. Fail upon 'shrink' */ 309 if (uSize <= getSize()) 310 { 311 /* Failure upon 'shrink'. Return original result */ 312 return (result); 313 } 314 315 /* Save current position */ 316 off_t const nCurPos = (off_t)lseek (m_fd, (off_t)0, SEEK_CUR); 317 if (nCurPos == (off_t)(-1)) 318 return (result); 319 320 /* Try 'expand' via 'lseek()' and 'write()' */ 321 if (-1 == lseek (m_fd, (off_t)(nSize - 1), SEEK_SET)) 322 return (result); 323 324 if (-1 == write (m_fd, (char*)"", (size_t)1)) 325 { 326 /* Failure. Restore saved position */ 327 (void) lseek (m_fd, (off_t)(nCurPos), SEEK_SET); 328 return (result); 329 } 330 331 /* Success. Restore saved position */ 332 if (-1 == lseek (m_fd, (off_t)nCurPos, SEEK_SET)) 333 return (result); 334 } 335 336 OSL_FILE_TRACE("osl_setFileSize(%d, %lld) => %ld", m_fd, getSize(), nSize); 337 m_size = sal::static_int_cast< sal_uInt64 >(nSize); 338 return osl_File_E_None; 339 } 340 341 oslFileError FileHandle_Impl::readAt ( 342 off_t nOffset, 343 void * pBuffer, 344 size_t nBytesRequested, 345 sal_uInt64 * pBytesRead) 346 { 347 OSL_PRECOND((m_state & STATE_SEEKABLE), "FileHandle_Impl::readAt(): not seekable"); 348 if (!(m_state & STATE_SEEKABLE)) 349 return osl_File_E_SPIPE; 350 351 OSL_PRECOND((m_state & STATE_READABLE), "FileHandle_Impl::readAt(): not readable"); 352 if (!(m_state & STATE_READABLE)) 353 return osl_File_E_BADF; 354 355 #if defined(LINUX) || defined(SOLARIS) 356 357 ssize_t nBytes = ::pread (m_fd, pBuffer, nBytesRequested, nOffset); 358 if ((-1 == nBytes) && (EOVERFLOW == errno)) 359 { 360 /* Some 'pread()'s fail with EOVERFLOW when reading at (or past) 361 * end-of-file, different from 'lseek() + read()' behaviour. 362 * Returning '0 bytes read' and 'osl_File_E_None' instead. 363 */ 364 nBytes = 0; 365 } 366 if (-1 == nBytes) 367 return oslTranslateFileError (OSL_FET_ERROR, errno); 368 369 #else /* !(LINUX || SOLARIS) */ 370 371 if (nOffset != m_offset) 372 { 373 if (-1 == ::lseek (m_fd, nOffset, SEEK_SET)) 374 return oslTranslateFileError (OSL_FET_ERROR, errno); 375 m_offset = nOffset; 376 } 377 378 ssize_t nBytes = ::read (m_fd, pBuffer, nBytesRequested); 379 if (-1 == nBytes) 380 return oslTranslateFileError (OSL_FET_ERROR, errno); 381 m_offset += nBytes; 382 383 #endif /* !(LINUX || SOLARIS) */ 384 385 OSL_FILE_TRACE("FileHandle_Impl::readAt(%d, %lld, %ld)", m_fd, nOffset, nBytes); 386 *pBytesRead = nBytes; 387 return osl_File_E_None; 388 } 389 390 oslFileError FileHandle_Impl::writeAt ( 391 off_t nOffset, 392 void const * pBuffer, 393 size_t nBytesToWrite, 394 sal_uInt64 * pBytesWritten) 395 { 396 OSL_PRECOND((m_state & STATE_SEEKABLE), "FileHandle_Impl::writeAt(): not seekable"); 397 if (!(m_state & STATE_SEEKABLE)) 398 return osl_File_E_SPIPE; 399 400 OSL_PRECOND((m_state & STATE_WRITEABLE), "FileHandle_Impl::writeAt(): not writeable"); 401 if (!(m_state & STATE_WRITEABLE)) 402 return osl_File_E_BADF; 403 404 #if defined(LINUX) || defined(SOLARIS) 405 406 ssize_t nBytes = ::pwrite (m_fd, pBuffer, nBytesToWrite, nOffset); 407 if (-1 == nBytes) 408 return oslTranslateFileError (OSL_FET_ERROR, errno); 409 410 #else /* !(LINUX || SOLARIS) */ 411 412 if (nOffset != m_offset) 413 { 414 if (-1 == ::lseek (m_fd, nOffset, SEEK_SET)) 415 return oslTranslateFileError (OSL_FET_ERROR, errno); 416 m_offset = nOffset; 417 } 418 419 ssize_t nBytes = ::write (m_fd, pBuffer, nBytesToWrite); 420 if (-1 == nBytes) 421 return oslTranslateFileError (OSL_FET_ERROR, errno); 422 m_offset += nBytes; 423 424 #endif /* !(LINUX || SOLARIS) */ 425 426 OSL_FILE_TRACE("FileHandle_Impl::writeAt(%d, %lld, %ld)", m_fd, nOffset, nBytes); 427 m_size = std::max (m_size, sal::static_int_cast< sal_uInt64 >(nOffset + nBytes)); 428 429 *pBytesWritten = nBytes; 430 return osl_File_E_None; 431 } 432 433 oslFileError FileHandle_Impl::readFileAt ( 434 off_t nOffset, 435 void * pBuffer, 436 size_t nBytesRequested, 437 sal_uInt64 * pBytesRead) 438 { 439 if (0 == (m_state & STATE_SEEKABLE)) 440 { 441 // not seekable (pipe) 442 ssize_t nBytes = ::read (m_fd, pBuffer, nBytesRequested); 443 if (-1 == nBytes) 444 return oslTranslateFileError (OSL_FET_ERROR, errno); 445 *pBytesRead = nBytes; 446 return osl_File_E_None; 447 } 448 else if (0 == m_buffer) 449 { 450 // not buffered 451 return readAt (nOffset, pBuffer, nBytesRequested, pBytesRead); 452 } 453 else 454 { 455 sal_uInt8 * buffer = static_cast<sal_uInt8*>(pBuffer); 456 for (*pBytesRead = 0; nBytesRequested > 0; ) 457 { 458 off_t const bufptr = (nOffset / m_bufsiz) * m_bufsiz; 459 size_t const bufpos = (nOffset % m_bufsiz); 460 461 if (bufptr != m_bufptr) 462 { 463 // flush current buffer 464 oslFileError result = syncFile(); 465 if (result != osl_File_E_None) 466 return (result); 467 m_bufptr = -1, m_buflen = 0; 468 469 if (nBytesRequested >= m_bufsiz) 470 { 471 // buffer too small, read through from file 472 sal_uInt64 uDone = 0; 473 result = readAt (nOffset, &(buffer[*pBytesRead]), nBytesRequested, &uDone); 474 if (result != osl_File_E_None) 475 return (result); 476 477 nBytesRequested -= uDone, *pBytesRead += uDone; 478 return osl_File_E_None; 479 } 480 481 // update buffer (pointer) 482 sal_uInt64 uDone = 0; 483 result = readAt (bufptr, m_buffer, m_bufsiz, &uDone); 484 if (result != osl_File_E_None) 485 return (result); 486 m_bufptr = bufptr, m_buflen = uDone; 487 } 488 if (bufpos >= m_buflen) 489 { 490 // end of file 491 return osl_File_E_None; 492 } 493 494 size_t const bytes = std::min (m_buflen - bufpos, nBytesRequested); 495 OSL_FILE_TRACE("FileHandle_Impl::readFileAt(%d, %lld, %ld)", m_fd, nOffset, bytes); 496 497 memcpy (&(buffer[*pBytesRead]), &(m_buffer[bufpos]), bytes); 498 nBytesRequested -= bytes, *pBytesRead += bytes, nOffset += bytes; 499 } 500 return osl_File_E_None; 501 } 502 } 503 504 oslFileError FileHandle_Impl::writeFileAt ( 505 off_t nOffset, 506 void const * pBuffer, 507 size_t nBytesToWrite, 508 sal_uInt64 * pBytesWritten) 509 { 510 if (0 == (m_state & STATE_SEEKABLE)) 511 { 512 // not seekable (pipe) 513 ssize_t nBytes = ::write (m_fd, pBuffer, nBytesToWrite); 514 if (-1 == nBytes) 515 return oslTranslateFileError (OSL_FET_ERROR, errno); 516 *pBytesWritten = nBytes; 517 return osl_File_E_None; 518 } 519 else if (0 == m_buffer) 520 { 521 // not buffered 522 return writeAt (nOffset, pBuffer, nBytesToWrite, pBytesWritten); 523 } 524 else 525 { 526 sal_uInt8 const * buffer = static_cast<sal_uInt8 const *>(pBuffer); 527 for (*pBytesWritten = 0; nBytesToWrite > 0; ) 528 { 529 off_t const bufptr = (nOffset / m_bufsiz) * m_bufsiz; 530 size_t const bufpos = (nOffset % m_bufsiz); 531 if (bufptr != m_bufptr) 532 { 533 // flush current buffer 534 oslFileError result = syncFile(); 535 if (result != osl_File_E_None) 536 return (result); 537 m_bufptr = -1, m_buflen = 0; 538 539 if (nBytesToWrite >= m_bufsiz) 540 { 541 // buffer to small, write through to file 542 sal_uInt64 uDone = 0; 543 result = writeAt (nOffset, &(buffer[*pBytesWritten]), nBytesToWrite, &uDone); 544 if (result != osl_File_E_None) 545 return (result); 546 if (uDone != nBytesToWrite) 547 return osl_File_E_IO; 548 549 nBytesToWrite -= uDone, *pBytesWritten += uDone; 550 return osl_File_E_None; 551 } 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 = uDone; 559 } 560 561 size_t const bytes = std::min (m_bufsiz - bufpos, nBytesToWrite); 562 OSL_FILE_TRACE("FileHandle_Impl::writeFileAt(%d, %lld, %ld)", m_fd, nOffset, bytes); 563 564 memcpy (&(m_buffer[bufpos]), &(buffer[*pBytesWritten]), bytes); 565 nBytesToWrite -= bytes, *pBytesWritten += bytes, nOffset += bytes; 566 567 m_buflen = std::max(m_buflen, bufpos + bytes); 568 m_state |= STATE_MODIFIED; 569 } 570 return osl_File_E_None; 571 } 572 } 573 574 oslFileError FileHandle_Impl::readLineAt ( 575 off_t nOffset, 576 sal_Sequence ** ppSequence, 577 sal_uInt64 * pBytesRead) 578 { 579 oslFileError result = osl_File_E_None; 580 581 off_t bufptr = nOffset / m_bufsiz * m_bufsiz; 582 if (bufptr != m_bufptr) 583 { 584 /* flush current buffer */ 585 result = syncFile(); 586 if (result != osl_File_E_None) 587 return (result); 588 589 /* update buffer (pointer) */ 590 sal_uInt64 uDone = 0; 591 result = readAt (bufptr, m_buffer, m_bufsiz, &uDone); 592 if (result != osl_File_E_None) 593 return (result); 594 595 m_bufptr = bufptr, m_buflen = uDone; 596 } 597 598 static int const LINE_STATE_BEGIN = 0; 599 static int const LINE_STATE_CR = 1; 600 static int const LINE_STATE_LF = 2; 601 602 size_t bufpos = nOffset - m_bufptr, curpos = bufpos, dstpos = 0; 603 int state = (bufpos >= m_buflen) ? LINE_STATE_LF : LINE_STATE_BEGIN; 604 605 for ( ; state != LINE_STATE_LF; ) 606 { 607 if (curpos >= m_buflen) 608 { 609 /* buffer examined */ 610 if (0 < (curpos - bufpos)) 611 { 612 /* flush buffer to sequence */ 613 result = writeSequence_Impl ( 614 ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos); 615 if (result != osl_File_E_None) 616 return (result); 617 *pBytesRead += curpos - bufpos, nOffset += curpos - bufpos; 618 } 619 620 bufptr = nOffset / m_bufsiz * m_bufsiz; 621 if (bufptr != m_bufptr) 622 { 623 /* update buffer (pointer) */ 624 sal_uInt64 uDone = 0; 625 result = readAt (bufptr, m_buffer, m_bufsiz, &uDone); 626 if (result != osl_File_E_None) 627 return (result); 628 m_bufptr = bufptr, m_buflen = uDone; 629 } 630 631 bufpos = nOffset - m_bufptr, curpos = bufpos; 632 if (bufpos >= m_buflen) 633 break; 634 } 635 switch (state) 636 { 637 case LINE_STATE_CR: 638 state = LINE_STATE_LF; 639 switch (m_buffer[curpos]) 640 { 641 case 0x0A: /* CRLF */ 642 /* eat current char */ 643 curpos++; 644 break; 645 default: /* single CR */ 646 /* keep current char */ 647 break; 648 } 649 break; 650 default: 651 /* determine next state */ 652 switch (m_buffer[curpos]) 653 { 654 case 0x0A: /* single LF */ 655 state = LINE_STATE_LF; 656 break; 657 case 0x0D: /* CR */ 658 state = LINE_STATE_CR; 659 break; 660 default: /* advance to next char */ 661 curpos++; 662 break; 663 } 664 if (state != LINE_STATE_BEGIN) 665 { 666 /* store (and eat) the newline char */ 667 m_buffer[curpos] = 0x0A, curpos++; 668 669 /* flush buffer to sequence */ 670 result = writeSequence_Impl ( 671 ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos - 1); 672 if (result != osl_File_E_None) 673 return (result); 674 *pBytesRead += curpos - bufpos, nOffset += curpos - bufpos; 675 } 676 break; 677 } 678 } 679 680 result = writeSequence_Impl (ppSequence, &dstpos, 0, 0); 681 if (result != osl_File_E_None) 682 return (result); 683 if (0 < dstpos) 684 return osl_File_E_None; 685 if (bufpos >= m_buflen) 686 return osl_File_E_AGAIN; 687 return osl_File_E_None; 688 } 689 690 oslFileError FileHandle_Impl::writeSequence_Impl ( 691 sal_Sequence ** ppSequence, 692 size_t * pnOffset, 693 const void * pBuffer, 694 size_t nBytes) 695 { 696 sal_Int32 nElements = *pnOffset + nBytes; 697 if (!*ppSequence) 698 { 699 /* construct sequence */ 700 rtl_byte_sequence_constructNoDefault(ppSequence, nElements); 701 } 702 else if (nElements != (*ppSequence)->nElements) 703 { 704 /* resize sequence */ 705 rtl_byte_sequence_realloc(ppSequence, nElements); 706 } 707 if (*ppSequence != 0) 708 { 709 /* fill sequence */ 710 memcpy(&((*ppSequence)->elements[*pnOffset]), pBuffer, nBytes), *pnOffset += nBytes; 711 } 712 return (*ppSequence != 0) ? osl_File_E_None : osl_File_E_NOMEM; 713 } 714 715 oslFileError FileHandle_Impl::syncFile() 716 { 717 oslFileError result = osl_File_E_None; 718 if (m_state & STATE_MODIFIED) 719 { 720 sal_uInt64 uDone = 0; 721 result = writeAt (m_bufptr, m_buffer, m_buflen, &uDone); 722 if (result != osl_File_E_None) 723 return (result); 724 if (uDone != m_buflen) 725 return osl_File_E_IO; 726 m_state &= ~STATE_MODIFIED; 727 } 728 return (result); 729 } 730 731 /**************************************************************************** 732 * osl_createFileHandleFromFD 733 ***************************************************************************/ 734 extern "C" oslFileHandle osl_createFileHandleFromFD( int fd ) 735 { 736 if (-1 == fd) 737 return 0; // EINVAL 738 739 struct stat aFileStat; 740 if (-1 == fstat (fd, &aFileStat)) 741 return 0; // EBADF 742 743 FileHandle_Impl * pImpl = new FileHandle_Impl (fd); 744 if (0 == pImpl) 745 return 0; // ENOMEM 746 747 // assume writeable 748 pImpl->m_state |= FileHandle_Impl::STATE_WRITEABLE; 749 if (!S_ISREG(aFileStat.st_mode)) 750 { 751 /* not a regular file, mark not seekable */ 752 pImpl->m_state &= ~FileHandle_Impl::STATE_SEEKABLE; 753 } 754 else 755 { 756 /* regular file, init current size */ 757 pImpl->m_size = sal::static_int_cast< sal_uInt64 >(aFileStat.st_size); 758 } 759 760 OSL_FILE_TRACE("osl_createFileHandleFromFD(%d, writeable) => %s", 761 pImpl->m_fd, rtl_string_getStr(pImpl->m_strFilePath)); 762 return (oslFileHandle)(pImpl); 763 } 764 765 /******************************************************************* 766 * osl_file_adjustLockFlags 767 ******************************************************************/ 768 static int osl_file_adjustLockFlags (const char * path, int flags) 769 { 770 #ifdef MACOSX 771 /* 772 * The AFP implementation of MacOS X 10.4 treats O_EXLOCK in a way 773 * that makes it impossible for OOo to create a backup copy of the 774 * file it keeps opened. OTOH O_SHLOCK for AFP behaves as desired by 775 * the OOo file handling, so we need to check the path of the file 776 * for the filesystem name. 777 */ 778 struct statfs s; 779 if( 0 <= statfs( path, &s ) ) 780 { 781 if( 0 == strncmp("afpfs", s.f_fstypename, 5) ) 782 { 783 flags &= ~O_EXLOCK; 784 flags |= O_SHLOCK; 785 } 786 else 787 { 788 /* Needed flags to allow opening a webdav file */ 789 flags &= ~(O_EXLOCK | O_SHLOCK | O_NONBLOCK); 790 } 791 } 792 #endif /* MACOSX */ 793 794 (void) path; 795 return flags; 796 } 797 798 /**************************************************************************** 799 * osl_file_queryLocking 800 ***************************************************************************/ 801 struct Locking_Impl 802 { 803 int m_enabled; 804 Locking_Impl() : m_enabled(0) 805 { 806 #ifndef HAVE_O_EXLOCK 807 m_enabled = ((getenv("SAL_ENABLE_FILE_LOCKING") != 0) || (getenv("STAR_ENABLE_FILE_LOCKING") != 0)); 808 #endif /* HAVE_O_EXLOCK */ 809 } 810 }; 811 static int osl_file_queryLocking (sal_uInt32 uFlags) 812 { 813 if (!(uFlags & osl_File_OpenFlag_NoLock)) 814 { 815 if ((uFlags & osl_File_OpenFlag_Write) || (uFlags & osl_File_OpenFlag_Create)) 816 { 817 static Locking_Impl g_locking; 818 return (g_locking.m_enabled != 0); 819 } 820 } 821 return 0; 822 } 823 824 /**************************************************************************** 825 * osl_openFile 826 ***************************************************************************/ 827 #ifdef HAVE_O_EXLOCK 828 #define OPEN_WRITE_FLAGS ( O_RDWR | O_EXLOCK | O_NONBLOCK ) 829 #define OPEN_CREATE_FLAGS ( O_CREAT | O_EXCL | O_RDWR | O_EXLOCK | O_NONBLOCK ) 830 #else 831 #define OPEN_WRITE_FLAGS ( O_RDWR ) 832 #define OPEN_CREATE_FLAGS ( O_CREAT | O_EXCL | O_RDWR ) 833 #endif 834 835 oslFileError 836 SAL_CALL osl_openFile( rtl_uString* ustrFileURL, oslFileHandle* pHandle, sal_uInt32 uFlags ) 837 { 838 oslFileError eRet; 839 840 if ((ustrFileURL == 0) || (ustrFileURL->length == 0) || (pHandle == 0)) 841 return osl_File_E_INVAL; 842 843 /* convert file URL to system path */ 844 char buffer[PATH_MAX]; 845 eRet = FileURLToPath (buffer, sizeof(buffer), ustrFileURL); 846 if (eRet != osl_File_E_None) 847 return eRet; 848 #ifdef MACOSX 849 if (macxp_resolveAlias (buffer, sizeof(buffer)) != 0) 850 return oslTranslateFileError (OSL_FET_ERROR, errno); 851 #endif /* MACOSX */ 852 853 /* set mode and flags */ 854 int mode = S_IRUSR | S_IRGRP | S_IROTH; 855 int flags = O_RDONLY; 856 if (uFlags & osl_File_OpenFlag_Write) 857 { 858 mode |= S_IWUSR | S_IWGRP | S_IWOTH; 859 flags = OPEN_WRITE_FLAGS; 860 } 861 if (uFlags & osl_File_OpenFlag_Create) 862 { 863 mode |= S_IWUSR | S_IWGRP | S_IWOTH; 864 flags = OPEN_CREATE_FLAGS; 865 } 866 if (uFlags & osl_File_OpenFlag_NoLock) 867 { 868 #ifdef HAVE_O_EXLOCK 869 flags &= ~(O_EXLOCK | O_SHLOCK | O_NONBLOCK); 870 #endif /* HAVE_O_EXLOCK */ 871 } 872 else 873 { 874 flags = osl_file_adjustLockFlags (buffer, flags); 875 } 876 877 /* open the file */ 878 int fd = open( buffer, flags, mode ); 879 if (-1 == fd) 880 return oslTranslateFileError (OSL_FET_ERROR, errno); 881 882 /* reset O_NONBLOCK flag */ 883 if (flags & O_NONBLOCK) 884 { 885 int f = fcntl (fd, F_GETFL, 0); 886 if (-1 == f) 887 { 888 eRet = oslTranslateFileError (OSL_FET_ERROR, errno); 889 (void) close(fd); 890 return eRet; 891 } 892 if (-1 == fcntl (fd, F_SETFL, (f & ~O_NONBLOCK))) 893 { 894 eRet = oslTranslateFileError (OSL_FET_ERROR, errno); 895 (void) close(fd); 896 return eRet; 897 } 898 } 899 900 /* get file status (mode, size) */ 901 struct stat aFileStat; 902 if (-1 == fstat (fd, &aFileStat)) 903 { 904 eRet = oslTranslateFileError (OSL_FET_ERROR, errno); 905 (void) close(fd); 906 return eRet; 907 } 908 if (!S_ISREG(aFileStat.st_mode)) 909 { 910 /* we only open regular files here */ 911 (void) close(fd); 912 return osl_File_E_INVAL; 913 } 914 915 if (osl_file_queryLocking (uFlags)) 916 { 917 #ifdef MACOSX 918 if (-1 == flock (fd, LOCK_EX | LOCK_NB)) 919 { 920 /* Mac OSX returns ENOTSUP for webdav drives. We should try read lock */ 921 if ((errno != ENOTSUP) || ((-1 == flock (fd, LOCK_SH | LOCK_NB)) && (errno != ENOTSUP))) 922 { 923 eRet = oslTranslateFileError (OSL_FET_ERROR, errno); 924 (void) close(fd); 925 return eRet; 926 } 927 } 928 #else /* F_SETLK */ 929 { 930 struct flock aflock; 931 932 aflock.l_type = F_WRLCK; 933 aflock.l_whence = SEEK_SET; 934 aflock.l_start = 0; 935 aflock.l_len = 0; 936 937 if (-1 == fcntl (fd, F_SETLK, &aflock)) 938 { 939 eRet = oslTranslateFileError (OSL_FET_ERROR, errno); 940 (void) close(fd); 941 return eRet; 942 } 943 } 944 #endif /* F_SETLK */ 945 } 946 947 /* allocate memory for impl structure */ 948 FileHandle_Impl * pImpl = new FileHandle_Impl (fd, buffer); 949 if (!pImpl) 950 { 951 eRet = oslTranslateFileError (OSL_FET_ERROR, ENOMEM); 952 (void) close(fd); 953 return eRet; 954 } 955 if (flags & O_RDWR) 956 pImpl->m_state |= FileHandle_Impl::STATE_WRITEABLE; 957 pImpl->m_size = sal::static_int_cast< sal_uInt64 >(aFileStat.st_size); 958 959 OSL_TRACE("osl_openFile(%d, %s) => %s", pImpl->m_fd, 960 flags & O_RDWR ? "writeable":"readonly", 961 rtl_string_getStr(pImpl->m_strFilePath)); 962 963 *pHandle = (oslFileHandle)(pImpl); 964 return osl_File_E_None; 965 } 966 967 /****************************************************************************/ 968 /* osl_closeFile */ 969 /****************************************************************************/ 970 oslFileError 971 SAL_CALL osl_closeFile( oslFileHandle Handle ) 972 { 973 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 974 975 if ((pImpl == 0) || (pImpl->m_fd < 0)) 976 return osl_File_E_INVAL; 977 978 (void) pthread_mutex_lock (&(pImpl->m_mutex)); 979 980 /* close(2) implicitly (and unconditionally) unlocks */ 981 OSL_TRACE("osl_closeFile(%d) => %s", pImpl->m_fd, rtl_string_getStr(pImpl->m_strFilePath)); 982 oslFileError result = pImpl->syncFile(); 983 if (result != osl_File_E_None) 984 { 985 /* close, ignoring double failure */ 986 (void) close (pImpl->m_fd); 987 } 988 else if (-1 == close (pImpl->m_fd)) 989 { 990 /* translate error code */ 991 result = oslTranslateFileError (OSL_FET_ERROR, errno); 992 } 993 994 (void) pthread_mutex_unlock (&(pImpl->m_mutex)); 995 delete pImpl; 996 return (result); 997 } 998 999 /************************************************ 1000 * osl_syncFile 1001 ***********************************************/ 1002 oslFileError 1003 SAL_CALL osl_syncFile(oslFileHandle Handle) 1004 { 1005 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 1006 1007 if ((0 == pImpl) || (-1 == pImpl->m_fd)) 1008 return osl_File_E_INVAL; 1009 1010 FileHandle_Impl::Guard lock (&(pImpl->m_mutex)); 1011 1012 OSL_TRACE("osl_syncFile(%d)", pImpl->m_fd); 1013 oslFileError result = pImpl->syncFile(); 1014 if (result != osl_File_E_None) 1015 return (result); 1016 if (-1 == fsync (pImpl->m_fd)) 1017 return oslTranslateFileError (OSL_FET_ERROR, errno); 1018 1019 return osl_File_E_None; 1020 } 1021 1022 /******************************************* 1023 osl_mapFile 1024 ********************************************/ 1025 oslFileError 1026 SAL_CALL osl_mapFile ( 1027 oslFileHandle Handle, 1028 void** ppAddr, 1029 sal_uInt64 uLength, 1030 sal_uInt64 uOffset, 1031 sal_uInt32 uFlags 1032 ) 1033 { 1034 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 1035 1036 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == ppAddr)) 1037 return osl_File_E_INVAL; 1038 *ppAddr = 0; 1039 1040 static sal_uInt64 const g_limit_size_t = std::numeric_limits< size_t >::max(); 1041 if (g_limit_size_t < uLength) 1042 return osl_File_E_OVERFLOW; 1043 size_t const nLength = sal::static_int_cast< size_t >(uLength); 1044 1045 static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max(); 1046 if (g_limit_off_t < uOffset) 1047 return osl_File_E_OVERFLOW; 1048 off_t const nOffset = sal::static_int_cast< off_t >(uOffset); 1049 1050 void* p = mmap(NULL, nLength, PROT_READ, MAP_SHARED, pImpl->m_fd, nOffset); 1051 if (MAP_FAILED == p) 1052 return oslTranslateFileError(OSL_FET_ERROR, errno); 1053 *ppAddr = p; 1054 1055 if (uFlags & osl_File_MapFlag_RandomAccess) 1056 { 1057 // Determine memory pagesize. 1058 size_t const nPageSize = FileHandle_Impl::getpagesize(); 1059 if (size_t(-1) != nPageSize) 1060 { 1061 /* 1062 * Pagein, touching first byte of every memory page. 1063 * Note: volatile disables optimizing the loop away. 1064 */ 1065 sal_uInt8 * pData (reinterpret_cast<sal_uInt8*>(*ppAddr)); 1066 size_t nSize (nLength); 1067 1068 volatile sal_uInt8 c = 0; 1069 while (nSize > nPageSize) 1070 { 1071 c ^= pData[0]; 1072 pData += nPageSize; 1073 nSize -= nPageSize; 1074 } 1075 if (nSize > 0) 1076 { 1077 c^= pData[0]; 1078 pData += nSize; 1079 nSize -= nSize; 1080 } 1081 } 1082 } 1083 if (uFlags & osl_File_MapFlag_WillNeed) 1084 { 1085 // On Linux, madvise(..., MADV_WILLNEED) appears to have the undesirable 1086 // effect of not returning until the data has actually been paged in, so 1087 // that its net effect would typically be to slow down the process 1088 // (which could start processing at the beginning of the data while the 1089 // OS simultaneously pages in the rest); on other platforms, it remains 1090 // to be evaluated whether madvise or equivalent is available and 1091 // actually useful: 1092 #if defined MACOSX 1093 int e = posix_madvise(p, nLength, POSIX_MADV_WILLNEED); 1094 if (e != 0) 1095 { 1096 OSL_TRACE( 1097 "posix_madvise(..., POSIX_MADV_WILLNEED) failed with %d", e); 1098 } 1099 #elif defined SOLARIS 1100 if (madvise(static_cast< caddr_t >(p), nLength, MADV_WILLNEED) != 0) 1101 { 1102 OSL_TRACE("madvise(..., MADV_WILLNEED) failed with %d", errno); 1103 } 1104 #endif 1105 } 1106 return osl_File_E_None; 1107 } 1108 1109 /******************************************* 1110 osl_unmapFile 1111 ********************************************/ 1112 oslFileError 1113 SAL_CALL osl_unmapFile (void* pAddr, sal_uInt64 uLength) 1114 { 1115 if (0 == pAddr) 1116 return osl_File_E_INVAL; 1117 1118 static sal_uInt64 const g_limit_size_t = std::numeric_limits< size_t >::max(); 1119 if (g_limit_size_t < uLength) 1120 return osl_File_E_OVERFLOW; 1121 size_t const nLength = sal::static_int_cast< size_t >(uLength); 1122 1123 if (-1 == munmap(static_cast<char*>(pAddr), nLength)) 1124 return oslTranslateFileError(OSL_FET_ERROR, errno); 1125 1126 return osl_File_E_None; 1127 } 1128 1129 /******************************************* 1130 osl_readLine 1131 ********************************************/ 1132 oslFileError 1133 SAL_CALL osl_readLine ( 1134 oslFileHandle Handle, 1135 sal_Sequence ** ppSequence) 1136 { 1137 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle); 1138 1139 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == ppSequence)) 1140 return osl_File_E_INVAL; 1141 sal_uInt64 uBytesRead = 0; 1142 1143 // read at current fileptr; fileptr += uBytesRead; 1144 FileHandle_Impl::Guard lock (&(pImpl->m_mutex)); 1145 oslFileError result = pImpl->readLineAt ( 1146 pImpl->m_fileptr, ppSequence, &uBytesRead); 1147 if (result == osl_File_E_None) 1148 pImpl->m_fileptr += uBytesRead; 1149 return (result); 1150 } 1151 1152 /******************************************* 1153 osl_readFile 1154 ********************************************/ 1155 oslFileError 1156 SAL_CALL osl_readFile ( 1157 oslFileHandle Handle, 1158 void * pBuffer, 1159 sal_uInt64 uBytesRequested, 1160 sal_uInt64 * pBytesRead) 1161 { 1162 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 1163 1164 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesRead)) 1165 return osl_File_E_INVAL; 1166 1167 static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max(); 1168 if (g_limit_ssize_t < uBytesRequested) 1169 return osl_File_E_OVERFLOW; 1170 size_t const nBytesRequested = sal::static_int_cast< size_t >(uBytesRequested); 1171 1172 // read at current fileptr; fileptr += *pBytesRead; 1173 FileHandle_Impl::Guard lock (&(pImpl->m_mutex)); 1174 oslFileError result = pImpl->readFileAt ( 1175 pImpl->m_fileptr, pBuffer, nBytesRequested, pBytesRead); 1176 if (result == osl_File_E_None) 1177 pImpl->m_fileptr += *pBytesRead; 1178 return (result); 1179 } 1180 1181 /******************************************* 1182 osl_writeFile 1183 ********************************************/ 1184 oslFileError 1185 SAL_CALL osl_writeFile ( 1186 oslFileHandle Handle, 1187 const void * pBuffer, 1188 sal_uInt64 uBytesToWrite, 1189 sal_uInt64 * pBytesWritten) 1190 { 1191 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 1192 1193 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesWritten)) 1194 return osl_File_E_INVAL; 1195 if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE)) 1196 return osl_File_E_BADF; 1197 1198 static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max(); 1199 if (g_limit_ssize_t < uBytesToWrite) 1200 return osl_File_E_OVERFLOW; 1201 size_t const nBytesToWrite = sal::static_int_cast< size_t >(uBytesToWrite); 1202 1203 // write at current fileptr; fileptr += *pBytesWritten; 1204 FileHandle_Impl::Guard lock (&(pImpl->m_mutex)); 1205 oslFileError result = pImpl->writeFileAt ( 1206 pImpl->m_fileptr, pBuffer, nBytesToWrite, pBytesWritten); 1207 if (result == osl_File_E_None) 1208 pImpl->m_fileptr += *pBytesWritten; 1209 return (result); 1210 } 1211 1212 /******************************************* 1213 osl_readFileAt 1214 ********************************************/ 1215 oslFileError 1216 SAL_CALL osl_readFileAt ( 1217 oslFileHandle Handle, 1218 sal_uInt64 uOffset, 1219 void* pBuffer, 1220 sal_uInt64 uBytesRequested, 1221 sal_uInt64* pBytesRead) 1222 { 1223 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 1224 1225 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesRead)) 1226 return osl_File_E_INVAL; 1227 if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE)) 1228 return osl_File_E_SPIPE; 1229 1230 static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max(); 1231 if (g_limit_off_t < uOffset) 1232 return osl_File_E_OVERFLOW; 1233 off_t const nOffset = sal::static_int_cast< off_t >(uOffset); 1234 1235 static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max(); 1236 if (g_limit_ssize_t < uBytesRequested) 1237 return osl_File_E_OVERFLOW; 1238 size_t const nBytesRequested = sal::static_int_cast< size_t >(uBytesRequested); 1239 1240 // read at specified fileptr 1241 FileHandle_Impl::Guard lock (&(pImpl->m_mutex)); 1242 return pImpl->readFileAt (nOffset, pBuffer, nBytesRequested, pBytesRead); 1243 } 1244 1245 /******************************************* 1246 osl_writeFileAt 1247 ********************************************/ 1248 oslFileError 1249 SAL_CALL osl_writeFileAt ( 1250 oslFileHandle Handle, 1251 sal_uInt64 uOffset, 1252 const void* pBuffer, 1253 sal_uInt64 uBytesToWrite, 1254 sal_uInt64* pBytesWritten) 1255 { 1256 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 1257 1258 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesWritten)) 1259 return osl_File_E_INVAL; 1260 if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE)) 1261 return osl_File_E_SPIPE; 1262 if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE)) 1263 return osl_File_E_BADF; 1264 1265 static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max(); 1266 if (g_limit_off_t < uOffset) 1267 return osl_File_E_OVERFLOW; 1268 off_t const nOffset = sal::static_int_cast< off_t >(uOffset); 1269 1270 static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max(); 1271 if (g_limit_ssize_t < uBytesToWrite) 1272 return osl_File_E_OVERFLOW; 1273 size_t const nBytesToWrite = sal::static_int_cast< size_t >(uBytesToWrite); 1274 1275 // write at specified fileptr 1276 FileHandle_Impl::Guard lock (&(pImpl->m_mutex)); 1277 return pImpl->writeFileAt (nOffset, pBuffer, nBytesToWrite, pBytesWritten); 1278 } 1279 1280 /****************************************************************************/ 1281 /* osl_isEndOfFile */ 1282 /****************************************************************************/ 1283 oslFileError 1284 SAL_CALL osl_isEndOfFile( oslFileHandle Handle, sal_Bool *pIsEOF ) 1285 { 1286 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 1287 1288 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pIsEOF)) 1289 return osl_File_E_INVAL; 1290 1291 FileHandle_Impl::Guard lock (&(pImpl->m_mutex)); 1292 *pIsEOF = (pImpl->getPos() == pImpl->getSize()); 1293 return osl_File_E_None; 1294 } 1295 1296 /************************************************ 1297 * osl_getFilePos 1298 ***********************************************/ 1299 oslFileError 1300 SAL_CALL osl_getFilePos( oslFileHandle Handle, sal_uInt64* pPos ) 1301 { 1302 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 1303 1304 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pPos)) 1305 return osl_File_E_INVAL; 1306 1307 FileHandle_Impl::Guard lock (&(pImpl->m_mutex)); 1308 *pPos = pImpl->getPos(); 1309 return osl_File_E_None; 1310 } 1311 1312 /******************************************* 1313 osl_setFilePos 1314 ********************************************/ 1315 oslFileError 1316 SAL_CALL osl_setFilePos (oslFileHandle Handle, sal_uInt32 uHow, sal_Int64 uOffset) 1317 { 1318 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 1319 1320 if ((0 == pImpl) || (-1 == pImpl->m_fd)) 1321 return osl_File_E_INVAL; 1322 1323 static sal_Int64 const g_limit_off_t = std::numeric_limits< off_t >::max(); 1324 if (g_limit_off_t < uOffset) 1325 return osl_File_E_OVERFLOW; 1326 off_t nPos = 0, nOffset = sal::static_int_cast< off_t >(uOffset); 1327 1328 FileHandle_Impl::Guard lock (&(pImpl->m_mutex)); 1329 switch(uHow) 1330 { 1331 case osl_Pos_Absolut: 1332 if (0 > nOffset) 1333 return osl_File_E_INVAL; 1334 break; 1335 1336 case osl_Pos_Current: 1337 nPos = sal::static_int_cast< off_t >(pImpl->getPos()); 1338 if ((0 > nOffset) && (-1*nOffset > nPos)) 1339 return osl_File_E_INVAL; 1340 if (g_limit_off_t < nPos + nOffset) 1341 return osl_File_E_OVERFLOW; 1342 break; 1343 1344 case osl_Pos_End: 1345 nPos = sal::static_int_cast< off_t >(pImpl->getSize()); 1346 if ((0 > nOffset) && (-1*nOffset > nPos)) 1347 return osl_File_E_INVAL; 1348 if (g_limit_off_t < nPos + nOffset) 1349 return osl_File_E_OVERFLOW; 1350 break; 1351 1352 default: 1353 return osl_File_E_INVAL; 1354 } 1355 1356 return pImpl->setPos (nPos + nOffset); 1357 } 1358 1359 /**************************************************************************** 1360 * osl_getFileSize 1361 ****************************************************************************/ 1362 oslFileError 1363 SAL_CALL osl_getFileSize( oslFileHandle Handle, sal_uInt64* pSize ) 1364 { 1365 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 1366 1367 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pSize)) 1368 return osl_File_E_INVAL; 1369 1370 FileHandle_Impl::Guard lock (&(pImpl->m_mutex)); 1371 *pSize = pImpl->getSize(); 1372 return osl_File_E_None; 1373 } 1374 1375 /************************************************ 1376 * osl_setFileSize 1377 ***********************************************/ 1378 oslFileError 1379 SAL_CALL osl_setFileSize( oslFileHandle Handle, sal_uInt64 uSize ) 1380 { 1381 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 1382 1383 if ((0 == pImpl) || (-1 == pImpl->m_fd)) 1384 return osl_File_E_INVAL; 1385 if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE)) 1386 return osl_File_E_BADF; 1387 1388 static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max(); 1389 if (g_limit_off_t < uSize) 1390 return osl_File_E_OVERFLOW; 1391 1392 oslFileError result = pImpl->syncFile(); 1393 if (result != osl_File_E_None) 1394 return (result); 1395 pImpl->m_bufptr = -1, pImpl->m_buflen = 0; 1396 1397 return pImpl->setSize (uSize); 1398 } 1399