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