LCOV - code coverage report
Current view: top level - sal/osl/unx - file.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 420 574 73.2 %
Date: 2012-08-25 Functions: 44 48 91.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 254 505 50.3 %

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

Generated by: LCOV version 1.10