merged tag ooo/DEV300_m102
[LibreOffice.git] / sal / osl / unx / file.cxx
blob67f1d05660a81251dc45d81dcf56e8995a75a978
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sal.hxx"
31 #include "osl/file.hxx"
33 #include "osl/diagnose.h"
34 #include "rtl/alloc.h"
36 #include "system.h"
37 #include "file_error_transl.h"
38 #include "file_url.h"
40 #include <algorithm>
41 #include <limits>
43 #include <string.h>
44 #include <pthread.h>
45 #include <sys/mman.h>
47 #if defined(MACOSX)
49 #include <sys/param.h>
50 #include <sys/mount.h>
51 #define HAVE_O_EXLOCK
53 // add MACOSX Time Value
54 #define TimeValue CFTimeValue
55 #include <CoreFoundation/CoreFoundation.h>
56 #undef TimeValue
58 #endif /* MACOSX */
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
68 /*******************************************************************
70 * FileHandle_Impl interface
72 ******************************************************************/
73 struct FileHandle_Impl
75 pthread_mutex_t m_mutex;
76 rtl_String * m_strFilePath; /* holds native file path */
77 int m_fd;
79 /** State
81 enum StateBits
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 */
88 int m_state;
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 */
94 off_t m_bufptr; /* buffer offset from begin of file */
95 size_t m_buflen; /* buffer filled [0, m_bufsiz - 1] */
97 size_t m_bufsiz;
98 sal_uInt8 * m_buffer;
100 explicit FileHandle_Impl (int fd, char const * path = "<anon>");
101 ~FileHandle_Impl();
103 static void* operator new (size_t n);
104 static void operator delete (void * p, size_t);
106 static size_t getpagesize();
108 sal_uInt64 getPos() const;
109 oslFileError setPos (sal_uInt64 uPos);
111 sal_uInt64 getSize() const;
112 oslFileError setSize (sal_uInt64 uSize);
114 oslFileError readAt (
115 off_t nOffset,
116 void * pBuffer,
117 size_t nBytesRequested,
118 sal_uInt64 * pBytesRead);
120 oslFileError writeAt (
121 off_t nOffset,
122 void const * pBuffer,
123 size_t nBytesToWrite,
124 sal_uInt64 * pBytesWritten);
126 oslFileError readFileAt (
127 off_t nOffset,
128 void * pBuffer,
129 size_t nBytesRequested,
130 sal_uInt64 * pBytesRead);
132 oslFileError writeFileAt (
133 off_t nOffset,
134 void const * pBuffer,
135 size_t nBytesToWrite,
136 sal_uInt64 * pBytesWritten);
138 oslFileError readLineAt (
139 off_t nOffset,
140 sal_Sequence ** ppSequence,
141 sal_uInt64 * pBytesRead);
143 oslFileError writeSequence_Impl (
144 sal_Sequence ** ppSequence,
145 size_t * pnOffset,
146 const void * pBuffer,
147 size_t nBytes);
149 oslFileError syncFile();
151 /** Buffer cache / allocator.
153 class Allocator
155 rtl_cache_type * m_cache;
156 size_t m_bufsiz;
158 Allocator (Allocator const &);
159 Allocator & operator= (Allocator const &);
161 public:
162 static Allocator & get();
164 void allocate (sal_uInt8 ** ppBuffer, size_t * pnSize);
165 void deallocate (sal_uInt8 * pBuffer);
167 protected:
168 Allocator();
169 ~Allocator();
172 /** Guard.
174 class Guard
176 pthread_mutex_t * m_mutex;
178 public:
179 explicit Guard(pthread_mutex_t * pMutex);
180 ~Guard();
184 /*******************************************************************
186 * FileHandle_Impl implementation
188 ******************************************************************/
190 FileHandle_Impl::Allocator &
191 FileHandle_Impl::Allocator::get()
193 static Allocator g_aBufferAllocator;
194 return g_aBufferAllocator;
197 FileHandle_Impl::Allocator::Allocator()
198 : m_cache (0),
199 m_bufsiz (0)
201 size_t const pagesize = FileHandle_Impl::getpagesize();
202 if (size_t(-1) != pagesize)
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;
210 FileHandle_Impl::Allocator::~Allocator()
212 rtl_cache_destroy (m_cache), m_cache = 0;
215 void FileHandle_Impl::Allocator::allocate (sal_uInt8 ** ppBuffer, size_t * pnSize)
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;
221 void FileHandle_Impl::Allocator::deallocate (sal_uInt8 * pBuffer)
223 if (0 != pBuffer)
224 rtl_cache_free (m_cache, pBuffer);
227 FileHandle_Impl::Guard::Guard(pthread_mutex_t * pMutex)
228 : m_mutex (pMutex)
230 OSL_PRECOND (m_mutex != 0, "FileHandle_Impl::Guard::Guard(): null pointer.");
231 (void) pthread_mutex_lock (m_mutex); // ignoring EINVAL ...
233 FileHandle_Impl::Guard::~Guard()
235 OSL_PRECOND (m_mutex != 0, "FileHandle_Impl::Guard::~Guard(): null pointer.");
236 (void) pthread_mutex_unlock (m_mutex);
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)
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);
257 FileHandle_Impl::~FileHandle_Impl()
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 ...
264 void* FileHandle_Impl::operator new (size_t n)
266 return rtl_allocateMemory(n);
268 void FileHandle_Impl::operator delete (void * p, size_t)
270 rtl_freeMemory(p);
273 size_t FileHandle_Impl::getpagesize()
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 */
282 sal_uInt64 FileHandle_Impl::getPos() const
284 return sal::static_int_cast< sal_uInt64 >(m_fileptr);
287 oslFileError FileHandle_Impl::setPos (sal_uInt64 uPos)
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;
294 sal_uInt64 FileHandle_Impl::getSize() const
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));
300 oslFileError FileHandle_Impl::setSize (sal_uInt64 uSize)
302 off_t const nSize = sal::static_int_cast< off_t >(uSize);
303 if (-1 == ftruncate (m_fd, nSize))
305 /* Failure. Save original result. Try fallback algorithm */
306 oslFileError result = oslTranslateFileError (OSL_FET_ERROR, errno);
308 /* Check against current size. Fail upon 'shrink' */
309 if (uSize <= getSize())
311 /* Failure upon 'shrink'. Return original result */
312 return (result);
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);
320 /* Try 'expand' via 'lseek()' and 'write()' */
321 if (-1 == lseek (m_fd, (off_t)(nSize - 1), SEEK_SET))
322 return (result);
324 if (-1 == write (m_fd, (char*)"", (size_t)1))
326 /* Failure. Restore saved position */
327 (void) lseek (m_fd, (off_t)(nCurPos), SEEK_SET);
328 return (result);
331 /* Success. Restore saved position */
332 if (-1 == lseek (m_fd, (off_t)nCurPos, SEEK_SET))
333 return (result);
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;
341 oslFileError FileHandle_Impl::readAt (
342 off_t nOffset,
343 void * pBuffer,
344 size_t nBytesRequested,
345 sal_uInt64 * pBytesRead)
347 OSL_PRECOND((m_state & STATE_SEEKABLE), "FileHandle_Impl::readAt(): not seekable");
348 if (!(m_state & STATE_SEEKABLE))
349 return osl_File_E_SPIPE;
351 OSL_PRECOND((m_state & STATE_READABLE), "FileHandle_Impl::readAt(): not readable");
352 if (!(m_state & STATE_READABLE))
353 return osl_File_E_BADF;
355 #if defined(LINUX) || defined(SOLARIS)
357 ssize_t nBytes = ::pread (m_fd, pBuffer, nBytesRequested, nOffset);
358 if ((-1 == nBytes) && (EOVERFLOW == errno))
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.
364 nBytes = 0;
366 if (-1 == nBytes)
367 return oslTranslateFileError (OSL_FET_ERROR, errno);
369 #else /* !(LINUX || SOLARIS) */
371 if (nOffset != m_offset)
373 if (-1 == ::lseek (m_fd, nOffset, SEEK_SET))
374 return oslTranslateFileError (OSL_FET_ERROR, errno);
375 m_offset = nOffset;
378 ssize_t nBytes = ::read (m_fd, pBuffer, nBytesRequested);
379 if (-1 == nBytes)
380 return oslTranslateFileError (OSL_FET_ERROR, errno);
381 m_offset += nBytes;
383 #endif /* !(LINUX || SOLARIS) */
385 OSL_FILE_TRACE("FileHandle_Impl::readAt(%d, %lld, %ld)", m_fd, nOffset, nBytes);
386 *pBytesRead = nBytes;
387 return osl_File_E_None;
390 oslFileError FileHandle_Impl::writeAt (
391 off_t nOffset,
392 void const * pBuffer,
393 size_t nBytesToWrite,
394 sal_uInt64 * pBytesWritten)
396 OSL_PRECOND((m_state & STATE_SEEKABLE), "FileHandle_Impl::writeAt(): not seekable");
397 if (!(m_state & STATE_SEEKABLE))
398 return osl_File_E_SPIPE;
400 OSL_PRECOND((m_state & STATE_WRITEABLE), "FileHandle_Impl::writeAt(): not writeable");
401 if (!(m_state & STATE_WRITEABLE))
402 return osl_File_E_BADF;
404 #if defined(LINUX) || defined(SOLARIS)
406 ssize_t nBytes = ::pwrite (m_fd, pBuffer, nBytesToWrite, nOffset);
407 if (-1 == nBytes)
408 return oslTranslateFileError (OSL_FET_ERROR, errno);
410 #else /* !(LINUX || SOLARIS) */
412 if (nOffset != m_offset)
414 if (-1 == ::lseek (m_fd, nOffset, SEEK_SET))
415 return oslTranslateFileError (OSL_FET_ERROR, errno);
416 m_offset = nOffset;
419 ssize_t nBytes = ::write (m_fd, pBuffer, nBytesToWrite);
420 if (-1 == nBytes)
421 return oslTranslateFileError (OSL_FET_ERROR, errno);
422 m_offset += nBytes;
424 #endif /* !(LINUX || SOLARIS) */
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));
429 *pBytesWritten = nBytes;
430 return osl_File_E_None;
433 oslFileError FileHandle_Impl::readFileAt (
434 off_t nOffset,
435 void * pBuffer,
436 size_t nBytesRequested,
437 sal_uInt64 * pBytesRead)
439 if (0 == (m_state & STATE_SEEKABLE))
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;
448 else if (0 == m_buffer)
450 // not buffered
451 return readAt (nOffset, pBuffer, nBytesRequested, pBytesRead);
453 else
455 sal_uInt8 * buffer = static_cast<sal_uInt8*>(pBuffer);
456 for (*pBytesRead = 0; nBytesRequested > 0; )
458 off_t const bufptr = (nOffset / m_bufsiz) * m_bufsiz;
459 size_t const bufpos = (nOffset % m_bufsiz);
461 if (bufptr != m_bufptr)
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;
469 if (nBytesRequested >= m_bufsiz)
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);
477 nBytesRequested -= uDone, *pBytesRead += uDone;
478 return osl_File_E_None;
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;
488 if (bufpos >= m_buflen)
490 // end of file
491 return osl_File_E_None;
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);
497 memcpy (&(buffer[*pBytesRead]), &(m_buffer[bufpos]), bytes);
498 nBytesRequested -= bytes, *pBytesRead += bytes, nOffset += bytes;
500 return osl_File_E_None;
504 oslFileError FileHandle_Impl::writeFileAt (
505 off_t nOffset,
506 void const * pBuffer,
507 size_t nBytesToWrite,
508 sal_uInt64 * pBytesWritten)
510 if (0 == (m_state & STATE_SEEKABLE))
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;
519 else if (0 == m_buffer)
521 // not buffered
522 return writeAt (nOffset, pBuffer, nBytesToWrite, pBytesWritten);
524 else
526 sal_uInt8 const * buffer = static_cast<sal_uInt8 const *>(pBuffer);
527 for (*pBytesWritten = 0; nBytesToWrite > 0; )
529 off_t const bufptr = (nOffset / m_bufsiz) * m_bufsiz;
530 size_t const bufpos = (nOffset % m_bufsiz);
531 if (bufptr != m_bufptr)
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;
539 if (nBytesToWrite >= m_bufsiz)
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;
549 nBytesToWrite -= uDone, *pBytesWritten += uDone;
550 return osl_File_E_None;
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;
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);
564 memcpy (&(m_buffer[bufpos]), &(buffer[*pBytesWritten]), bytes);
565 nBytesToWrite -= bytes, *pBytesWritten += bytes, nOffset += bytes;
567 m_buflen = std::max(m_buflen, bufpos + bytes);
568 m_state |= STATE_MODIFIED;
570 return osl_File_E_None;
574 oslFileError FileHandle_Impl::readLineAt (
575 off_t nOffset,
576 sal_Sequence ** ppSequence,
577 sal_uInt64 * pBytesRead)
579 oslFileError result = osl_File_E_None;
581 off_t bufptr = nOffset / m_bufsiz * m_bufsiz;
582 if (bufptr != m_bufptr)
584 /* flush current buffer */
585 result = syncFile();
586 if (result != osl_File_E_None)
587 return (result);
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);
595 m_bufptr = bufptr, m_buflen = uDone;
598 static int const LINE_STATE_BEGIN = 0;
599 static int const LINE_STATE_CR = 1;
600 static int const LINE_STATE_LF = 2;
602 size_t bufpos = nOffset - m_bufptr, curpos = bufpos, dstpos = 0;
603 int state = (bufpos >= m_buflen) ? LINE_STATE_LF : LINE_STATE_BEGIN;
605 for ( ; state != LINE_STATE_LF; )
607 if (curpos >= m_buflen)
609 /* buffer examined */
610 if (0 < (curpos - bufpos))
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;
620 bufptr = nOffset / m_bufsiz * m_bufsiz;
621 if (bufptr != m_bufptr)
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;
631 bufpos = nOffset - m_bufptr, curpos = bufpos;
632 if (bufpos >= m_buflen)
633 break;
635 switch (state)
637 case LINE_STATE_CR:
638 state = LINE_STATE_LF;
639 switch (m_buffer[curpos])
641 case 0x0A: /* CRLF */
642 /* eat current char */
643 curpos++;
644 break;
645 default: /* single CR */
646 /* keep current char */
647 break;
649 break;
650 default:
651 /* determine next state */
652 switch (m_buffer[curpos])
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;
664 if (state != LINE_STATE_BEGIN)
666 /* store (and eat) the newline char */
667 m_buffer[curpos] = 0x0A, curpos++;
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;
676 break;
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;
690 oslFileError FileHandle_Impl::writeSequence_Impl (
691 sal_Sequence ** ppSequence,
692 size_t * pnOffset,
693 const void * pBuffer,
694 size_t nBytes)
696 sal_Int32 nElements = *pnOffset + nBytes;
697 if (!*ppSequence)
699 /* construct sequence */
700 rtl_byte_sequence_constructNoDefault(ppSequence, nElements);
702 else if (nElements != (*ppSequence)->nElements)
704 /* resize sequence */
705 rtl_byte_sequence_realloc(ppSequence, nElements);
707 if (*ppSequence != 0)
709 /* fill sequence */
710 memcpy(&((*ppSequence)->elements[*pnOffset]), pBuffer, nBytes), *pnOffset += nBytes;
712 return (*ppSequence != 0) ? osl_File_E_None : osl_File_E_NOMEM;
715 oslFileError FileHandle_Impl::syncFile()
717 oslFileError result = osl_File_E_None;
718 if (m_state & STATE_MODIFIED)
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;
728 return (result);
731 /****************************************************************************
732 * osl_createFileHandleFromFD
733 ***************************************************************************/
734 extern "C" oslFileHandle osl_createFileHandleFromFD( int fd )
736 if (-1 == fd)
737 return 0; // EINVAL
739 struct stat aFileStat;
740 if (-1 == fstat (fd, &aFileStat))
741 return 0; // EBADF
743 FileHandle_Impl * pImpl = new FileHandle_Impl (fd);
744 if (0 == pImpl)
745 return 0; // ENOMEM
747 // assume writeable
748 pImpl->m_state |= FileHandle_Impl::STATE_WRITEABLE;
749 if (!S_ISREG(aFileStat.st_mode))
751 /* not a regular file, mark not seekable */
752 pImpl->m_state &= ~FileHandle_Impl::STATE_SEEKABLE;
754 else
756 /* regular file, init current size */
757 pImpl->m_size = sal::static_int_cast< sal_uInt64 >(aFileStat.st_size);
760 OSL_FILE_TRACE("osl_createFileHandleFromFD(%d, writeable) => %s",
761 pImpl->m_fd, rtl_string_getStr(pImpl->m_strFilePath));
762 return (oslFileHandle)(pImpl);
765 /*******************************************************************
766 * osl_file_adjustLockFlags
767 ******************************************************************/
768 static int osl_file_adjustLockFlags (const char * path, int flags)
770 #ifdef MACOSX
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.
778 struct statfs s;
779 if( 0 <= statfs( path, &s ) )
781 if( 0 == strncmp("afpfs", s.f_fstypename, 5) )
783 flags &= ~O_EXLOCK;
784 flags |= O_SHLOCK;
786 else
788 /* Needed flags to allow opening a webdav file */
789 flags &= ~(O_EXLOCK | O_SHLOCK | O_NONBLOCK);
792 #endif /* MACOSX */
794 (void) path;
795 return flags;
798 /****************************************************************************
799 * osl_file_queryLocking
800 ***************************************************************************/
801 struct Locking_Impl
803 int m_enabled;
804 Locking_Impl() : m_enabled(0)
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 */
811 static int osl_file_queryLocking (sal_uInt32 uFlags)
813 if (!(uFlags & osl_File_OpenFlag_NoLock))
815 if ((uFlags & osl_File_OpenFlag_Write) || (uFlags & osl_File_OpenFlag_Create))
817 static Locking_Impl g_locking;
818 return (g_locking.m_enabled != 0);
821 return 0;
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
835 oslFileError
836 SAL_CALL osl_openFile( rtl_uString* ustrFileURL, oslFileHandle* pHandle, sal_uInt32 uFlags )
838 oslFileError eRet;
840 if ((ustrFileURL == 0) || (ustrFileURL->length == 0) || (pHandle == 0))
841 return osl_File_E_INVAL;
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 */
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)
858 mode |= S_IWUSR | S_IWGRP | S_IWOTH;
859 flags = OPEN_WRITE_FLAGS;
861 if (uFlags & osl_File_OpenFlag_Create)
863 mode |= S_IWUSR | S_IWGRP | S_IWOTH;
864 flags = OPEN_CREATE_FLAGS;
866 if (uFlags & osl_File_OpenFlag_NoLock)
868 #ifdef HAVE_O_EXLOCK
869 flags &= ~(O_EXLOCK | O_SHLOCK | O_NONBLOCK);
870 #endif /* HAVE_O_EXLOCK */
872 else
874 flags = osl_file_adjustLockFlags (buffer, flags);
877 /* open the file */
878 int fd = open( buffer, flags, mode );
879 if (-1 == fd)
880 return oslTranslateFileError (OSL_FET_ERROR, errno);
882 /* reset O_NONBLOCK flag */
883 if (flags & O_NONBLOCK)
885 int f = fcntl (fd, F_GETFL, 0);
886 if (-1 == f)
888 eRet = oslTranslateFileError (OSL_FET_ERROR, errno);
889 (void) close(fd);
890 return eRet;
892 if (-1 == fcntl (fd, F_SETFL, (f & ~O_NONBLOCK)))
894 eRet = oslTranslateFileError (OSL_FET_ERROR, errno);
895 (void) close(fd);
896 return eRet;
900 /* get file status (mode, size) */
901 struct stat aFileStat;
902 if (-1 == fstat (fd, &aFileStat))
904 eRet = oslTranslateFileError (OSL_FET_ERROR, errno);
905 (void) close(fd);
906 return eRet;
908 if (!S_ISREG(aFileStat.st_mode))
910 /* we only open regular files here */
911 (void) close(fd);
912 return osl_File_E_INVAL;
915 if (osl_file_queryLocking (uFlags))
917 #ifdef MACOSX
918 if (-1 == flock (fd, LOCK_EX | LOCK_NB))
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)))
923 eRet = oslTranslateFileError (OSL_FET_ERROR, errno);
924 (void) close(fd);
925 return eRet;
928 #else /* F_SETLK */
930 struct flock aflock;
932 aflock.l_type = F_WRLCK;
933 aflock.l_whence = SEEK_SET;
934 aflock.l_start = 0;
935 aflock.l_len = 0;
937 if (-1 == fcntl (fd, F_SETLK, &aflock))
939 eRet = oslTranslateFileError (OSL_FET_ERROR, errno);
940 (void) close(fd);
941 return eRet;
944 #endif /* F_SETLK */
947 /* allocate memory for impl structure */
948 FileHandle_Impl * pImpl = new FileHandle_Impl (fd, buffer);
949 if (!pImpl)
951 eRet = oslTranslateFileError (OSL_FET_ERROR, ENOMEM);
952 (void) close(fd);
953 return eRet;
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);
959 OSL_TRACE("osl_openFile(%d, %s) => %s", pImpl->m_fd,
960 flags & O_RDWR ? "writeable":"readonly",
961 rtl_string_getStr(pImpl->m_strFilePath));
963 *pHandle = (oslFileHandle)(pImpl);
964 return osl_File_E_None;
967 /****************************************************************************/
968 /* osl_closeFile */
969 /****************************************************************************/
970 oslFileError
971 SAL_CALL osl_closeFile( oslFileHandle Handle )
973 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
975 if ((pImpl == 0) || (pImpl->m_fd < 0))
976 return osl_File_E_INVAL;
978 (void) pthread_mutex_lock (&(pImpl->m_mutex));
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)
985 /* close, ignoring double failure */
986 (void) close (pImpl->m_fd);
988 else if (-1 == close (pImpl->m_fd))
990 /* translate error code */
991 result = oslTranslateFileError (OSL_FET_ERROR, errno);
994 (void) pthread_mutex_unlock (&(pImpl->m_mutex));
995 delete pImpl;
996 return (result);
999 /************************************************
1000 * osl_syncFile
1001 ***********************************************/
1002 oslFileError
1003 SAL_CALL osl_syncFile(oslFileHandle Handle)
1005 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1007 if ((0 == pImpl) || (-1 == pImpl->m_fd))
1008 return osl_File_E_INVAL;
1010 FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
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);
1019 return osl_File_E_None;
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
1034 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1036 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == ppAddr))
1037 return osl_File_E_INVAL;
1038 *ppAddr = 0;
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);
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);
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;
1055 if (uFlags & osl_File_MapFlag_RandomAccess)
1057 // Determine memory pagesize.
1058 size_t const nPageSize = FileHandle_Impl::getpagesize();
1059 if (size_t(-1) != nPageSize)
1062 * Pagein, touching first byte of every memory page.
1063 * Note: volatile disables optimizing the loop away.
1065 sal_uInt8 * pData (reinterpret_cast<sal_uInt8*>(*ppAddr));
1066 size_t nSize (nLength);
1068 volatile sal_uInt8 c = 0;
1069 while (nSize > nPageSize)
1071 c ^= pData[0];
1072 pData += nPageSize;
1073 nSize -= nPageSize;
1075 if (nSize > 0)
1077 c^= pData[0];
1078 pData += nSize;
1079 nSize -= nSize;
1083 if (uFlags & osl_File_MapFlag_WillNeed)
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)
1096 OSL_TRACE(
1097 "posix_madvise(..., POSIX_MADV_WILLNEED) failed with %d", e);
1099 #elif defined SOLARIS
1100 if (madvise(static_cast< caddr_t >(p), nLength, MADV_WILLNEED) != 0)
1102 OSL_TRACE("madvise(..., MADV_WILLNEED) failed with %d", errno);
1104 #endif
1106 return osl_File_E_None;
1109 /*******************************************
1110 osl_unmapFile
1111 ********************************************/
1112 oslFileError
1113 SAL_CALL osl_unmapFile (void* pAddr, sal_uInt64 uLength)
1115 if (0 == pAddr)
1116 return osl_File_E_INVAL;
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);
1123 if (-1 == munmap(static_cast<char*>(pAddr), nLength))
1124 return oslTranslateFileError(OSL_FET_ERROR, errno);
1126 return osl_File_E_None;
1129 /*******************************************
1130 osl_readLine
1131 ********************************************/
1132 oslFileError
1133 SAL_CALL osl_readLine (
1134 oslFileHandle Handle,
1135 sal_Sequence ** ppSequence)
1137 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
1139 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == ppSequence))
1140 return osl_File_E_INVAL;
1141 sal_uInt64 uBytesRead = 0;
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);
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)
1162 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1164 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesRead))
1165 return osl_File_E_INVAL;
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);
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);
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)
1191 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
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;
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);
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);
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)
1223 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
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;
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);
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);
1240 // read at specified fileptr
1241 FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1242 return pImpl->readFileAt (nOffset, pBuffer, nBytesRequested, pBytesRead);
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)
1256 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
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;
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);
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);
1275 // write at specified fileptr
1276 FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1277 return pImpl->writeFileAt (nOffset, pBuffer, nBytesToWrite, pBytesWritten);
1280 /****************************************************************************/
1281 /* osl_isEndOfFile */
1282 /****************************************************************************/
1283 oslFileError
1284 SAL_CALL osl_isEndOfFile( oslFileHandle Handle, sal_Bool *pIsEOF )
1286 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1288 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pIsEOF))
1289 return osl_File_E_INVAL;
1291 FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1292 *pIsEOF = (pImpl->getPos() == pImpl->getSize());
1293 return osl_File_E_None;
1296 /************************************************
1297 * osl_getFilePos
1298 ***********************************************/
1299 oslFileError
1300 SAL_CALL osl_getFilePos( oslFileHandle Handle, sal_uInt64* pPos )
1302 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1304 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pPos))
1305 return osl_File_E_INVAL;
1307 FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1308 *pPos = pImpl->getPos();
1309 return osl_File_E_None;
1312 /*******************************************
1313 osl_setFilePos
1314 ********************************************/
1315 oslFileError
1316 SAL_CALL osl_setFilePos (oslFileHandle Handle, sal_uInt32 uHow, sal_Int64 uOffset)
1318 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1320 if ((0 == pImpl) || (-1 == pImpl->m_fd))
1321 return osl_File_E_INVAL;
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);
1328 FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1329 switch(uHow)
1331 case osl_Pos_Absolut:
1332 if (0 > nOffset)
1333 return osl_File_E_INVAL;
1334 break;
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;
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;
1352 default:
1353 return osl_File_E_INVAL;
1356 return pImpl->setPos (nPos + nOffset);
1359 /****************************************************************************
1360 * osl_getFileSize
1361 ****************************************************************************/
1362 oslFileError
1363 SAL_CALL osl_getFileSize( oslFileHandle Handle, sal_uInt64* pSize )
1365 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1367 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pSize))
1368 return osl_File_E_INVAL;
1370 FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1371 *pSize = pImpl->getSize();
1372 return osl_File_E_None;
1375 /************************************************
1376 * osl_setFileSize
1377 ***********************************************/
1378 oslFileError
1379 SAL_CALL osl_setFileSize( oslFileHandle Handle, sal_uInt64 uSize )
1381 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
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;
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;
1392 oslFileError result = pImpl->syncFile();
1393 if (result != osl_File_E_None)
1394 return (result);
1395 pImpl->m_bufptr = -1, pImpl->m_buflen = 0;
1397 return pImpl->setSize (uSize);