LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sal/osl/unx - file.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 417 572 72.9 %
Date: 2013-07-09 Functions: 43 47 91.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10