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