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