LCOV - code coverage report
Current view: top level - libreoffice/sal/osl/unx - file.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 399 570 70.0 %
Date: 2012-12-27 Functions: 43 47 91.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10