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