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