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