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