summaryrefslogtreecommitdiff
path: root/sal/osl/unx/file.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sal/osl/unx/file.cxx')
-rw-r--r--sal/osl/unx/file.cxx1397
1 files changed, 1397 insertions, 0 deletions
diff --git a/sal/osl/unx/file.cxx b/sal/osl/unx/file.cxx
new file mode 100644
index 000000000000..cc0c041bc328
--- /dev/null
+++ b/sal/osl/unx/file.cxx
@@ -0,0 +1,1397 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#include "osl/file.hxx"
+
+#include "osl/diagnose.h"
+#include "rtl/alloc.h"
+
+#include "system.h"
+#include "file_error_transl.h"
+#include "file_url.h"
+
+#include <algorithm>
+#include <limits>
+
+#include <string.h>
+#include <pthread.h>
+#include <sys/mman.h>
+
+#if defined(MACOSX)
+
+#include <sys/param.h>
+#include <sys/mount.h>
+#define HAVE_O_EXLOCK
+
+// add MACOSX Time Value
+#define TimeValue CFTimeValue
+#include <CoreFoundation/CoreFoundation.h>
+#undef TimeValue
+
+#endif /* MACOSX */
+
+#ifdef DEBUG_OSL_FILE
+# define OSL_FILE_TRACE 0 ? (void)(0) : osl_trace
+# define PERROR( a, b ) perror( a ); fprintf( stderr, b )
+#else
+# define OSL_FILE_TRACE 1 ? (void)(0) : osl_trace
+# define PERROR( a, b )
+#endif
+
+/*******************************************************************
+ *
+ * FileHandle_Impl interface
+ *
+ ******************************************************************/
+struct FileHandle_Impl
+{
+ pthread_mutex_t m_mutex;
+ rtl_String * m_strFilePath; /* holds native file path */
+ int m_fd;
+
+ /** State
+ */
+ enum StateBits
+ {
+ STATE_SEEKABLE = 1, /* default */
+ STATE_READABLE = 2, /* default */
+ STATE_WRITEABLE = 4, /* open() sets, write() requires, else osl_File_E_BADF */
+ STATE_MODIFIED = 8 /* write() sets, flush() resets */
+ };
+ int m_state;
+
+ sal_uInt64 m_size; /* file size */
+ off_t m_offset; /* physical offset from begin of file */
+ off_t m_fileptr; /* logical offset from begin of file */
+
+ off_t m_bufptr; /* buffer offset from begin of file */
+ size_t m_buflen; /* buffer filled [0, m_bufsiz - 1] */
+
+ size_t m_bufsiz;
+ sal_uInt8 * m_buffer;
+
+ explicit FileHandle_Impl (int fd, char const * path = "<anon>");
+ ~FileHandle_Impl();
+
+ static void* operator new (size_t n);
+ static void operator delete (void * p, size_t);
+
+ static size_t getpagesize();
+
+ sal_uInt64 getPos() const;
+ oslFileError setPos (sal_uInt64 uPos);
+
+ sal_uInt64 getSize() const;
+ oslFileError setSize (sal_uInt64 uSize);
+
+ oslFileError readAt (
+ off_t nOffset,
+ void * pBuffer,
+ size_t nBytesRequested,
+ sal_uInt64 * pBytesRead);
+
+ oslFileError writeAt (
+ off_t nOffset,
+ void const * pBuffer,
+ size_t nBytesToWrite,
+ sal_uInt64 * pBytesWritten);
+
+ oslFileError readFileAt (
+ off_t nOffset,
+ void * pBuffer,
+ size_t nBytesRequested,
+ sal_uInt64 * pBytesRead);
+
+ oslFileError writeFileAt (
+ off_t nOffset,
+ void const * pBuffer,
+ size_t nBytesToWrite,
+ sal_uInt64 * pBytesWritten);
+
+ oslFileError readLineAt (
+ off_t nOffset,
+ sal_Sequence ** ppSequence,
+ sal_uInt64 * pBytesRead);
+
+ oslFileError writeSequence_Impl (
+ sal_Sequence ** ppSequence,
+ size_t * pnOffset,
+ const void * pBuffer,
+ size_t nBytes);
+
+ oslFileError syncFile();
+
+ /** Buffer cache / allocator.
+ */
+ class Allocator
+ {
+ rtl_cache_type * m_cache;
+ size_t m_bufsiz;
+
+ Allocator (Allocator const &);
+ Allocator & operator= (Allocator const &);
+
+ public:
+ static Allocator & get();
+
+ void allocate (sal_uInt8 ** ppBuffer, size_t * pnSize);
+ void deallocate (sal_uInt8 * pBuffer);
+
+ protected:
+ Allocator();
+ ~Allocator();
+ };
+
+ /** Guard.
+ */
+ class Guard
+ {
+ pthread_mutex_t * m_mutex;
+
+ public:
+ explicit Guard(pthread_mutex_t * pMutex);
+ ~Guard();
+ };
+};
+
+/*******************************************************************
+ *
+ * FileHandle_Impl implementation
+ *
+ ******************************************************************/
+
+FileHandle_Impl::Allocator &
+FileHandle_Impl::Allocator::get()
+{
+ static Allocator g_aBufferAllocator;
+ return g_aBufferAllocator;
+}
+
+FileHandle_Impl::Allocator::Allocator()
+ : m_cache (0),
+ m_bufsiz (0)
+{
+ size_t const pagesize = FileHandle_Impl::getpagesize();
+ if (size_t(-1) != pagesize)
+ {
+ m_cache = rtl_cache_create (
+ "osl_file_buffer_cache", pagesize, 0, 0, 0, 0, 0, 0, 0);
+ if (0 != m_cache)
+ m_bufsiz = pagesize;
+ }
+}
+FileHandle_Impl::Allocator::~Allocator()
+{
+ rtl_cache_destroy (m_cache), m_cache = 0;
+}
+
+void FileHandle_Impl::Allocator::allocate (sal_uInt8 ** ppBuffer, size_t * pnSize)
+{
+ OSL_PRECOND((0 != ppBuffer) && (0 != pnSize), "FileHandle_Impl::Allocator::allocate(): contract violation");
+ *ppBuffer = static_cast< sal_uInt8* >(rtl_cache_alloc(m_cache)), *pnSize = m_bufsiz;
+}
+void FileHandle_Impl::Allocator::deallocate (sal_uInt8 * pBuffer)
+{
+ if (0 != pBuffer)
+ rtl_cache_free (m_cache, pBuffer);
+}
+
+FileHandle_Impl::Guard::Guard(pthread_mutex_t * pMutex)
+ : m_mutex (pMutex)
+{
+ OSL_PRECOND (m_mutex != 0, "FileHandle_Impl::Guard::Guard(): null pointer.");
+ (void) pthread_mutex_lock (m_mutex); // ignoring EINVAL ...
+}
+FileHandle_Impl::Guard::~Guard()
+{
+ OSL_PRECOND (m_mutex != 0, "FileHandle_Impl::Guard::~Guard(): null pointer.");
+ (void) pthread_mutex_unlock (m_mutex);
+}
+
+FileHandle_Impl::FileHandle_Impl (int fd, char const * path)
+ : m_strFilePath (0),
+ m_fd (fd),
+ m_state (STATE_SEEKABLE | STATE_READABLE),
+ m_size (0),
+ m_offset (0),
+ m_fileptr (0),
+ m_bufptr (-1),
+ m_buflen (0),
+ m_bufsiz (0),
+ m_buffer (0)
+{
+ (void) pthread_mutex_init(&m_mutex, 0);
+ rtl_string_newFromStr (&m_strFilePath, path);
+ Allocator::get().allocate (&m_buffer, &m_bufsiz);
+ if (0 != m_buffer)
+ memset (m_buffer, 0, m_bufsiz);
+}
+FileHandle_Impl::~FileHandle_Impl()
+{
+ Allocator::get().deallocate (m_buffer), m_buffer = 0;
+ rtl_string_release (m_strFilePath), m_strFilePath = 0;
+ (void) pthread_mutex_destroy(&m_mutex); // ignoring EBUSY ...
+}
+
+void* FileHandle_Impl::operator new (size_t n)
+{
+ return rtl_allocateMemory(n);
+}
+void FileHandle_Impl::operator delete (void * p, size_t)
+{
+ rtl_freeMemory(p);
+}
+
+size_t FileHandle_Impl::getpagesize()
+{
+#if defined(FREEBSD) || defined(NETBSD) || defined(MACOSX)
+ return sal::static_int_cast< size_t >(::getpagesize());
+#else /* POSIX */
+ return sal::static_int_cast< size_t >(::sysconf(_SC_PAGESIZE));
+#endif /* xBSD || POSIX */
+}
+
+sal_uInt64 FileHandle_Impl::getPos() const
+{
+ return sal::static_int_cast< sal_uInt64 >(m_fileptr);
+}
+
+oslFileError FileHandle_Impl::setPos (sal_uInt64 uPos)
+{
+ OSL_FILE_TRACE("FileHandle_Impl::setPos(%d, %lld) => %lld", m_fd, getPos(), uPos);
+ m_fileptr = sal::static_int_cast< off_t >(uPos);
+ return osl_File_E_None;
+}
+
+sal_uInt64 FileHandle_Impl::getSize() const
+{
+ off_t const bufend = std::max((off_t)(0), m_bufptr) + m_buflen;
+ return std::max(m_size, sal::static_int_cast< sal_uInt64 >(bufend));
+}
+
+oslFileError FileHandle_Impl::setSize (sal_uInt64 uSize)
+{
+ off_t const nSize = sal::static_int_cast< off_t >(uSize);
+ if (-1 == ftruncate (m_fd, nSize))
+ {
+ /* Failure. Save original result. Try fallback algorithm */
+ oslFileError result = oslTranslateFileError (OSL_FET_ERROR, errno);
+
+ /* Check against current size. Fail upon 'shrink' */
+ if (uSize <= getSize())
+ {
+ /* Failure upon 'shrink'. Return original result */
+ return (result);
+ }
+
+ /* Save current position */
+ off_t const nCurPos = (off_t)lseek (m_fd, (off_t)0, SEEK_CUR);
+ if (nCurPos == (off_t)(-1))
+ return (result);
+
+ /* Try 'expand' via 'lseek()' and 'write()' */
+ if (-1 == lseek (m_fd, (off_t)(nSize - 1), SEEK_SET))
+ return (result);
+
+ if (-1 == write (m_fd, (char*)"", (size_t)1))
+ {
+ /* Failure. Restore saved position */
+ (void) lseek (m_fd, (off_t)(nCurPos), SEEK_SET);
+ return (result);
+ }
+
+ /* Success. Restore saved position */
+ if (-1 == lseek (m_fd, (off_t)nCurPos, SEEK_SET))
+ return (result);
+ }
+
+ OSL_FILE_TRACE("osl_setFileSize(%d, %lld) => %ld", m_fd, getSize(), nSize);
+ m_size = sal::static_int_cast< sal_uInt64 >(nSize);
+ return osl_File_E_None;
+}
+
+oslFileError FileHandle_Impl::readAt (
+ off_t nOffset,
+ void * pBuffer,
+ size_t nBytesRequested,
+ sal_uInt64 * pBytesRead)
+{
+ OSL_PRECOND((m_state & STATE_SEEKABLE), "FileHandle_Impl::readAt(): not seekable");
+ if (!(m_state & STATE_SEEKABLE))
+ return osl_File_E_SPIPE;
+
+ OSL_PRECOND((m_state & STATE_READABLE), "FileHandle_Impl::readAt(): not readable");
+ if (!(m_state & STATE_READABLE))
+ return osl_File_E_BADF;
+
+#if defined(LINUX) || defined(SOLARIS)
+
+ ssize_t nBytes = ::pread (m_fd, pBuffer, nBytesRequested, nOffset);
+ if ((-1 == nBytes) && (EOVERFLOW == errno))
+ {
+ /* Some 'pread()'s fail with EOVERFLOW when reading at (or past)
+ * end-of-file, different from 'lseek() + read()' behaviour.
+ * Returning '0 bytes read' and 'osl_File_E_None' instead.
+ */
+ nBytes = 0;
+ }
+ if (-1 == nBytes)
+ return oslTranslateFileError (OSL_FET_ERROR, errno);
+
+#else /* !(LINUX || SOLARIS) */
+
+ if (nOffset != m_offset)
+ {
+ if (-1 == ::lseek (m_fd, nOffset, SEEK_SET))
+ return oslTranslateFileError (OSL_FET_ERROR, errno);
+ m_offset = nOffset;
+ }
+
+ ssize_t nBytes = ::read (m_fd, pBuffer, nBytesRequested);
+ if (-1 == nBytes)
+ return oslTranslateFileError (OSL_FET_ERROR, errno);
+ m_offset += nBytes;
+
+#endif /* !(LINUX || SOLARIS) */
+
+ OSL_FILE_TRACE("FileHandle_Impl::readAt(%d, %lld, %ld)", m_fd, nOffset, nBytes);
+ *pBytesRead = nBytes;
+ return osl_File_E_None;
+}
+
+oslFileError FileHandle_Impl::writeAt (
+ off_t nOffset,
+ void const * pBuffer,
+ size_t nBytesToWrite,
+ sal_uInt64 * pBytesWritten)
+{
+ OSL_PRECOND((m_state & STATE_SEEKABLE), "FileHandle_Impl::writeAt(): not seekable");
+ if (!(m_state & STATE_SEEKABLE))
+ return osl_File_E_SPIPE;
+
+ OSL_PRECOND((m_state & STATE_WRITEABLE), "FileHandle_Impl::writeAt(): not writeable");
+ if (!(m_state & STATE_WRITEABLE))
+ return osl_File_E_BADF;
+
+#if defined(LINUX) || defined(SOLARIS)
+
+ ssize_t nBytes = ::pwrite (m_fd, pBuffer, nBytesToWrite, nOffset);
+ if (-1 == nBytes)
+ return oslTranslateFileError (OSL_FET_ERROR, errno);
+
+#else /* !(LINUX || SOLARIS) */
+
+ if (nOffset != m_offset)
+ {
+ if (-1 == ::lseek (m_fd, nOffset, SEEK_SET))
+ return oslTranslateFileError (OSL_FET_ERROR, errno);
+ m_offset = nOffset;
+ }
+
+ ssize_t nBytes = ::write (m_fd, pBuffer, nBytesToWrite);
+ if (-1 == nBytes)
+ return oslTranslateFileError (OSL_FET_ERROR, errno);
+ m_offset += nBytes;
+
+#endif /* !(LINUX || SOLARIS) */
+
+ OSL_FILE_TRACE("FileHandle_Impl::writeAt(%d, %lld, %ld)", m_fd, nOffset, nBytes);
+ m_size = std::max (m_size, sal::static_int_cast< sal_uInt64 >(nOffset + nBytes));
+
+ *pBytesWritten = nBytes;
+ return osl_File_E_None;
+}
+
+oslFileError FileHandle_Impl::readFileAt (
+ off_t nOffset,
+ void * pBuffer,
+ size_t nBytesRequested,
+ sal_uInt64 * pBytesRead)
+{
+ if (0 == (m_state & STATE_SEEKABLE))
+ {
+ // not seekable (pipe)
+ ssize_t nBytes = ::read (m_fd, pBuffer, nBytesRequested);
+ if (-1 == nBytes)
+ return oslTranslateFileError (OSL_FET_ERROR, errno);
+ *pBytesRead = nBytes;
+ return osl_File_E_None;
+ }
+ else if (0 == m_buffer)
+ {
+ // not buffered
+ return readAt (nOffset, pBuffer, nBytesRequested, pBytesRead);
+ }
+ else
+ {
+ sal_uInt8 * buffer = static_cast<sal_uInt8*>(pBuffer);
+ for (*pBytesRead = 0; nBytesRequested > 0; )
+ {
+ off_t const bufptr = (nOffset / m_bufsiz) * m_bufsiz;
+ size_t const bufpos = (nOffset % m_bufsiz);
+
+ if (bufptr != m_bufptr)
+ {
+ // flush current buffer
+ oslFileError result = syncFile();
+ if (result != osl_File_E_None)
+ return (result);
+ m_bufptr = -1, m_buflen = 0;
+
+ if (nBytesRequested >= m_bufsiz)
+ {
+ // buffer too small, read through from file
+ sal_uInt64 uDone = 0;
+ result = readAt (nOffset, &(buffer[*pBytesRead]), nBytesRequested, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+
+ nBytesRequested -= uDone, *pBytesRead += uDone;
+ return osl_File_E_None;
+ }
+
+ // update buffer (pointer)
+ sal_uInt64 uDone = 0;
+ result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+ m_bufptr = bufptr, m_buflen = uDone;
+ }
+ if (bufpos >= m_buflen)
+ {
+ // end of file
+ return osl_File_E_None;
+ }
+
+ size_t const bytes = std::min (m_buflen - bufpos, nBytesRequested);
+ OSL_FILE_TRACE("FileHandle_Impl::readFileAt(%d, %lld, %ld)", m_fd, nOffset, bytes);
+
+ memcpy (&(buffer[*pBytesRead]), &(m_buffer[bufpos]), bytes);
+ nBytesRequested -= bytes, *pBytesRead += bytes, nOffset += bytes;
+ }
+ return osl_File_E_None;
+ }
+}
+
+oslFileError FileHandle_Impl::writeFileAt (
+ off_t nOffset,
+ void const * pBuffer,
+ size_t nBytesToWrite,
+ sal_uInt64 * pBytesWritten)
+{
+ if (0 == (m_state & STATE_SEEKABLE))
+ {
+ // not seekable (pipe)
+ ssize_t nBytes = ::write (m_fd, pBuffer, nBytesToWrite);
+ if (-1 == nBytes)
+ return oslTranslateFileError (OSL_FET_ERROR, errno);
+ *pBytesWritten = nBytes;
+ return osl_File_E_None;
+ }
+ else if (0 == m_buffer)
+ {
+ // not buffered
+ return writeAt (nOffset, pBuffer, nBytesToWrite, pBytesWritten);
+ }
+ else
+ {
+ sal_uInt8 const * buffer = static_cast<sal_uInt8 const *>(pBuffer);
+ for (*pBytesWritten = 0; nBytesToWrite > 0; )
+ {
+ off_t const bufptr = (nOffset / m_bufsiz) * m_bufsiz;
+ size_t const bufpos = (nOffset % m_bufsiz);
+ if (bufptr != m_bufptr)
+ {
+ // flush current buffer
+ oslFileError result = syncFile();
+ if (result != osl_File_E_None)
+ return (result);
+ m_bufptr = -1, m_buflen = 0;
+
+ if (nBytesToWrite >= m_bufsiz)
+ {
+ // buffer to small, write through to file
+ sal_uInt64 uDone = 0;
+ result = writeAt (nOffset, &(buffer[*pBytesWritten]), nBytesToWrite, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+ if (uDone != nBytesToWrite)
+ return osl_File_E_IO;
+
+ nBytesToWrite -= uDone, *pBytesWritten += uDone;
+ return osl_File_E_None;
+ }
+
+ // update buffer (pointer)
+ sal_uInt64 uDone = 0;
+ result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+ m_bufptr = bufptr, m_buflen = uDone;
+ }
+
+ size_t const bytes = std::min (m_bufsiz - bufpos, nBytesToWrite);
+ OSL_FILE_TRACE("FileHandle_Impl::writeFileAt(%d, %lld, %ld)", m_fd, nOffset, bytes);
+
+ memcpy (&(m_buffer[bufpos]), &(buffer[*pBytesWritten]), bytes);
+ nBytesToWrite -= bytes, *pBytesWritten += bytes, nOffset += bytes;
+
+ m_buflen = std::max(m_buflen, bufpos + bytes);
+ m_state |= STATE_MODIFIED;
+ }
+ return osl_File_E_None;
+ }
+}
+
+oslFileError FileHandle_Impl::readLineAt (
+ off_t nOffset,
+ sal_Sequence ** ppSequence,
+ sal_uInt64 * pBytesRead)
+{
+ oslFileError result = osl_File_E_None;
+
+ off_t bufptr = nOffset / m_bufsiz * m_bufsiz;
+ if (bufptr != m_bufptr)
+ {
+ /* flush current buffer */
+ result = syncFile();
+ if (result != osl_File_E_None)
+ return (result);
+
+ /* update buffer (pointer) */
+ sal_uInt64 uDone = 0;
+ result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+
+ m_bufptr = bufptr, m_buflen = uDone;
+ }
+
+ static int const LINE_STATE_BEGIN = 0;
+ static int const LINE_STATE_CR = 1;
+ static int const LINE_STATE_LF = 2;
+
+ size_t bufpos = nOffset - m_bufptr, curpos = bufpos, dstpos = 0;
+ int state = (bufpos >= m_buflen) ? LINE_STATE_LF : LINE_STATE_BEGIN;
+
+ for ( ; state != LINE_STATE_LF; )
+ {
+ if (curpos >= m_buflen)
+ {
+ /* buffer examined */
+ if (0 < (curpos - bufpos))
+ {
+ /* flush buffer to sequence */
+ result = writeSequence_Impl (
+ ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos);
+ if (result != osl_File_E_None)
+ return (result);
+ *pBytesRead += curpos - bufpos, nOffset += curpos - bufpos;
+ }
+
+ bufptr = nOffset / m_bufsiz * m_bufsiz;
+ if (bufptr != m_bufptr)
+ {
+ /* update buffer (pointer) */
+ sal_uInt64 uDone = 0;
+ result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+ m_bufptr = bufptr, m_buflen = uDone;
+ }
+
+ bufpos = nOffset - m_bufptr, curpos = bufpos;
+ if (bufpos >= m_buflen)
+ break;
+ }
+ switch (state)
+ {
+ case LINE_STATE_CR:
+ state = LINE_STATE_LF;
+ switch (m_buffer[curpos])
+ {
+ case 0x0A: /* CRLF */
+ /* eat current char */
+ curpos++;
+ break;
+ default: /* single CR */
+ /* keep current char */
+ break;
+ }
+ break;
+ default:
+ /* determine next state */
+ switch (m_buffer[curpos])
+ {
+ case 0x0A: /* single LF */
+ state = LINE_STATE_LF;
+ break;
+ case 0x0D: /* CR */
+ state = LINE_STATE_CR;
+ break;
+ default: /* advance to next char */
+ curpos++;
+ break;
+ }
+ if (state != LINE_STATE_BEGIN)
+ {
+ /* store (and eat) the newline char */
+ m_buffer[curpos] = 0x0A, curpos++;
+
+ /* flush buffer to sequence */
+ result = writeSequence_Impl (
+ ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos - 1);
+ if (result != osl_File_E_None)
+ return (result);
+ *pBytesRead += curpos - bufpos, nOffset += curpos - bufpos;
+ }
+ break;
+ }
+ }
+
+ result = writeSequence_Impl (ppSequence, &dstpos, 0, 0);
+ if (result != osl_File_E_None)
+ return (result);
+ if (0 < dstpos)
+ return osl_File_E_None;
+ if (bufpos >= m_buflen)
+ return osl_File_E_AGAIN;
+ return osl_File_E_None;
+}
+
+oslFileError FileHandle_Impl::writeSequence_Impl (
+ sal_Sequence ** ppSequence,
+ size_t * pnOffset,
+ const void * pBuffer,
+ size_t nBytes)
+{
+ sal_Int32 nElements = *pnOffset + nBytes;
+ if (!*ppSequence)
+ {
+ /* construct sequence */
+ rtl_byte_sequence_constructNoDefault(ppSequence, nElements);
+ }
+ else if (nElements != (*ppSequence)->nElements)
+ {
+ /* resize sequence */
+ rtl_byte_sequence_realloc(ppSequence, nElements);
+ }
+ if (*ppSequence != 0)
+ {
+ /* fill sequence */
+ memcpy(&((*ppSequence)->elements[*pnOffset]), pBuffer, nBytes), *pnOffset += nBytes;
+ }
+ return (*ppSequence != 0) ? osl_File_E_None : osl_File_E_NOMEM;
+}
+
+oslFileError FileHandle_Impl::syncFile()
+{
+ oslFileError result = osl_File_E_None;
+ if (m_state & STATE_MODIFIED)
+ {
+ sal_uInt64 uDone = 0;
+ result = writeAt (m_bufptr, m_buffer, m_buflen, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+ if (uDone != m_buflen)
+ return osl_File_E_IO;
+ m_state &= ~STATE_MODIFIED;
+ }
+ return (result);
+}
+
+/****************************************************************************
+ * osl_createFileHandleFromFD
+ ***************************************************************************/
+extern "C" oslFileHandle osl_createFileHandleFromFD( int fd )
+{
+ if (-1 == fd)
+ return 0; // EINVAL
+
+ struct stat aFileStat;
+ if (-1 == fstat (fd, &aFileStat))
+ return 0; // EBADF
+
+ FileHandle_Impl * pImpl = new FileHandle_Impl (fd);
+ if (0 == pImpl)
+ return 0; // ENOMEM
+
+ // assume writeable
+ pImpl->m_state |= FileHandle_Impl::STATE_WRITEABLE;
+ if (!S_ISREG(aFileStat.st_mode))
+ {
+ /* not a regular file, mark not seekable */
+ pImpl->m_state &= ~FileHandle_Impl::STATE_SEEKABLE;
+ }
+ else
+ {
+ /* regular file, init current size */
+ pImpl->m_size = sal::static_int_cast< sal_uInt64 >(aFileStat.st_size);
+ }
+
+ OSL_FILE_TRACE("osl_createFileHandleFromFD(%d, writeable) => %s",
+ pImpl->m_fd, rtl_string_getStr(pImpl->m_strFilePath));
+ return (oslFileHandle)(pImpl);
+}
+
+/*******************************************************************
+ * osl_file_adjustLockFlags
+ ******************************************************************/
+static int osl_file_adjustLockFlags (const char * path, int flags)
+{
+#ifdef MACOSX
+ /*
+ * The AFP implementation of MacOS X 10.4 treats O_EXLOCK in a way
+ * that makes it impossible for OOo to create a backup copy of the
+ * file it keeps opened. OTOH O_SHLOCK for AFP behaves as desired by
+ * the OOo file handling, so we need to check the path of the file
+ * for the filesystem name.
+ */
+ struct statfs s;
+ if( 0 <= statfs( path, &s ) )
+ {
+ if( 0 == strncmp("afpfs", s.f_fstypename, 5) )
+ {
+ flags &= ~O_EXLOCK;
+ flags |= O_SHLOCK;
+ }
+ else
+ {
+ /* Needed flags to allow opening a webdav file */
+ flags &= ~(O_EXLOCK | O_SHLOCK | O_NONBLOCK);
+ }
+ }
+#endif /* MACOSX */
+
+ (void) path;
+ return flags;
+}
+
+/****************************************************************************
+ * osl_file_queryLocking
+ ***************************************************************************/
+struct Locking_Impl
+{
+ int m_enabled;
+ Locking_Impl() : m_enabled(0)
+ {
+#ifndef HAVE_O_EXLOCK
+ m_enabled = ((getenv("SAL_ENABLE_FILE_LOCKING") != 0) || (getenv("STAR_ENABLE_FILE_LOCKING") != 0));
+#endif /* HAVE_O_EXLOCK */
+ }
+};
+static int osl_file_queryLocking (sal_uInt32 uFlags)
+{
+ if (!(uFlags & osl_File_OpenFlag_NoLock))
+ {
+ if ((uFlags & osl_File_OpenFlag_Write) || (uFlags & osl_File_OpenFlag_Create))
+ {
+ static Locking_Impl g_locking;
+ return (g_locking.m_enabled != 0);
+ }
+ }
+ return 0;
+}
+
+/****************************************************************************
+ * osl_openFile
+ ***************************************************************************/
+#ifdef HAVE_O_EXLOCK
+#define OPEN_WRITE_FLAGS ( O_RDWR | O_EXLOCK | O_NONBLOCK )
+#define OPEN_CREATE_FLAGS ( O_CREAT | O_EXCL | O_RDWR | O_EXLOCK | O_NONBLOCK )
+#else
+#define OPEN_WRITE_FLAGS ( O_RDWR )
+#define OPEN_CREATE_FLAGS ( O_CREAT | O_EXCL | O_RDWR )
+#endif
+
+oslFileError
+SAL_CALL osl_openFile( rtl_uString* ustrFileURL, oslFileHandle* pHandle, sal_uInt32 uFlags )
+{
+ oslFileError eRet;
+
+ if ((ustrFileURL == 0) || (ustrFileURL->length == 0) || (pHandle == 0))
+ return osl_File_E_INVAL;
+
+ /* convert file URL to system path */
+ char buffer[PATH_MAX];
+ eRet = FileURLToPath (buffer, sizeof(buffer), ustrFileURL);
+ if (eRet != osl_File_E_None)
+ return eRet;
+#ifdef MACOSX
+ if (macxp_resolveAlias (buffer, sizeof(buffer)) != 0)
+ return oslTranslateFileError (OSL_FET_ERROR, errno);
+#endif /* MACOSX */
+
+ /* set mode and flags */
+ int mode = S_IRUSR | S_IRGRP | S_IROTH;
+ int flags = O_RDONLY;
+ if (uFlags & osl_File_OpenFlag_Write)
+ {
+ mode |= S_IWUSR | S_IWGRP | S_IWOTH;
+ flags = OPEN_WRITE_FLAGS;
+ }
+ if (uFlags & osl_File_OpenFlag_Create)
+ {
+ mode |= S_IWUSR | S_IWGRP | S_IWOTH;
+ flags = OPEN_CREATE_FLAGS;
+ }
+ if (uFlags & osl_File_OpenFlag_NoLock)
+ {
+#ifdef HAVE_O_EXLOCK
+ flags &= ~(O_EXLOCK | O_SHLOCK | O_NONBLOCK);
+#endif /* HAVE_O_EXLOCK */
+ }
+ else
+ {
+ flags = osl_file_adjustLockFlags (buffer, flags);
+ }
+
+ /* open the file */
+ int fd = open( buffer, flags, mode );
+ if (-1 == fd)
+ return oslTranslateFileError (OSL_FET_ERROR, errno);
+
+ /* reset O_NONBLOCK flag */
+ if (flags & O_NONBLOCK)
+ {
+ int f = fcntl (fd, F_GETFL, 0);
+ if (-1 == f)
+ {
+ eRet = oslTranslateFileError (OSL_FET_ERROR, errno);
+ (void) close(fd);
+ return eRet;
+ }
+ if (-1 == fcntl (fd, F_SETFL, (f & ~O_NONBLOCK)))
+ {
+ eRet = oslTranslateFileError (OSL_FET_ERROR, errno);
+ (void) close(fd);
+ return eRet;
+ }
+ }
+
+ /* get file status (mode, size) */
+ struct stat aFileStat;
+ if (-1 == fstat (fd, &aFileStat))
+ {
+ eRet = oslTranslateFileError (OSL_FET_ERROR, errno);
+ (void) close(fd);
+ return eRet;
+ }
+ if (!S_ISREG(aFileStat.st_mode))
+ {
+ /* we only open regular files here */
+ (void) close(fd);
+ return osl_File_E_INVAL;
+ }
+
+ if (osl_file_queryLocking (uFlags))
+ {
+#ifdef MACOSX
+ if (-1 == flock (fd, LOCK_EX | LOCK_NB))
+ {
+ /* Mac OSX returns ENOTSUP for webdav drives. We should try read lock */
+ if ((errno != ENOTSUP) || ((-1 == flock (fd, LOCK_SH | LOCK_NB)) && (errno != ENOTSUP)))
+ {
+ eRet = oslTranslateFileError (OSL_FET_ERROR, errno);
+ (void) close(fd);
+ return eRet;
+ }
+ }
+#else /* F_SETLK */
+ {
+ struct flock aflock;
+
+ aflock.l_type = F_WRLCK;
+ aflock.l_whence = SEEK_SET;
+ aflock.l_start = 0;
+ aflock.l_len = 0;
+
+ if (-1 == fcntl (fd, F_SETLK, &aflock))
+ {
+ eRet = oslTranslateFileError (OSL_FET_ERROR, errno);
+ (void) close(fd);
+ return eRet;
+ }
+ }
+#endif /* F_SETLK */
+ }
+
+ /* allocate memory for impl structure */
+ FileHandle_Impl * pImpl = new FileHandle_Impl (fd, buffer);
+ if (!pImpl)
+ {
+ eRet = oslTranslateFileError (OSL_FET_ERROR, ENOMEM);
+ (void) close(fd);
+ return eRet;
+ }
+ if (flags & O_RDWR)
+ pImpl->m_state |= FileHandle_Impl::STATE_WRITEABLE;
+ pImpl->m_size = sal::static_int_cast< sal_uInt64 >(aFileStat.st_size);
+
+ OSL_TRACE("osl_openFile(%d, %s) => %s", pImpl->m_fd,
+ flags & O_RDWR ? "writeable":"readonly",
+ rtl_string_getStr(pImpl->m_strFilePath));
+
+ *pHandle = (oslFileHandle)(pImpl);
+ return osl_File_E_None;
+}
+
+/****************************************************************************/
+/* osl_closeFile */
+/****************************************************************************/
+oslFileError
+SAL_CALL osl_closeFile( oslFileHandle Handle )
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((pImpl == 0) || (pImpl->m_fd < 0))
+ return osl_File_E_INVAL;
+
+ (void) pthread_mutex_lock (&(pImpl->m_mutex));
+
+ /* close(2) implicitly (and unconditionally) unlocks */
+ OSL_TRACE("osl_closeFile(%d) => %s", pImpl->m_fd, rtl_string_getStr(pImpl->m_strFilePath));
+ oslFileError result = pImpl->syncFile();
+ if (result != osl_File_E_None)
+ {
+ /* close, ignoring double failure */
+ (void) close (pImpl->m_fd);
+ }
+ else if (-1 == close (pImpl->m_fd))
+ {
+ /* translate error code */
+ result = oslTranslateFileError (OSL_FET_ERROR, errno);
+ }
+
+ (void) pthread_mutex_unlock (&(pImpl->m_mutex));
+ delete pImpl;
+ return (result);
+}
+
+/************************************************
+ * osl_syncFile
+ ***********************************************/
+oslFileError
+SAL_CALL osl_syncFile(oslFileHandle Handle)
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd))
+ return osl_File_E_INVAL;
+
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+
+ OSL_TRACE("osl_syncFile(%d)", pImpl->m_fd);
+ oslFileError result = pImpl->syncFile();
+ if (result != osl_File_E_None)
+ return (result);
+ if (-1 == fsync (pImpl->m_fd))
+ return oslTranslateFileError (OSL_FET_ERROR, errno);
+
+ return osl_File_E_None;
+}
+
+/*******************************************
+ osl_mapFile
+********************************************/
+oslFileError
+SAL_CALL osl_mapFile (
+ oslFileHandle Handle,
+ void** ppAddr,
+ sal_uInt64 uLength,
+ sal_uInt64 uOffset,
+ sal_uInt32 uFlags
+)
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == ppAddr))
+ return osl_File_E_INVAL;
+ *ppAddr = 0;
+
+ static sal_uInt64 const g_limit_size_t = std::numeric_limits< size_t >::max();
+ if (g_limit_size_t < uLength)
+ return osl_File_E_OVERFLOW;
+ size_t const nLength = sal::static_int_cast< size_t >(uLength);
+
+ static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max();
+ if (g_limit_off_t < uOffset)
+ return osl_File_E_OVERFLOW;
+ off_t const nOffset = sal::static_int_cast< off_t >(uOffset);
+
+ void* p = mmap(NULL, nLength, PROT_READ, MAP_SHARED, pImpl->m_fd, nOffset);
+ if (MAP_FAILED == p)
+ return oslTranslateFileError(OSL_FET_ERROR, errno);
+ *ppAddr = p;
+
+ if (uFlags & osl_File_MapFlag_RandomAccess)
+ {
+ // Determine memory pagesize.
+ size_t const nPageSize = FileHandle_Impl::getpagesize();
+ if (size_t(-1) != nPageSize)
+ {
+ /*
+ * Pagein, touching first byte of every memory page.
+ * Note: volatile disables optimizing the loop away.
+ */
+ sal_uInt8 * pData (reinterpret_cast<sal_uInt8*>(*ppAddr));
+ size_t nSize (nLength);
+
+ volatile sal_uInt8 c = 0;
+ while (nSize > nPageSize)
+ {
+ c ^= pData[0];
+ pData += nPageSize;
+ nSize -= nPageSize;
+ }
+ if (nSize > 0)
+ {
+ c^= pData[0];
+ pData += nSize;
+ nSize -= nSize;
+ }
+ }
+ }
+ if (uFlags & osl_File_MapFlag_WillNeed)
+ {
+ // On Linux, madvise(..., MADV_WILLNEED) appears to have the undesirable
+ // effect of not returning until the data has actually been paged in, so
+ // that its net effect would typically be to slow down the process
+ // (which could start processing at the beginning of the data while the
+ // OS simultaneously pages in the rest); on other platforms, it remains
+ // to be evaluated whether madvise or equivalent is available and
+ // actually useful:
+#if defined MACOSX
+ int e = posix_madvise(p, nLength, POSIX_MADV_WILLNEED);
+ if (e != 0)
+ {
+ OSL_TRACE(
+ "posix_madvise(..., POSIX_MADV_WILLNEED) failed with %d", e);
+ }
+#elif defined SOLARIS
+ if (madvise(static_cast< caddr_t >(p), nLength, MADV_WILLNEED) != 0)
+ {
+ OSL_TRACE("madvise(..., MADV_WILLNEED) failed with %d", errno);
+ }
+#endif
+ }
+ return osl_File_E_None;
+}
+
+/*******************************************
+ osl_unmapFile
+********************************************/
+oslFileError
+SAL_CALL osl_unmapFile (void* pAddr, sal_uInt64 uLength)
+{
+ if (0 == pAddr)
+ return osl_File_E_INVAL;
+
+ static sal_uInt64 const g_limit_size_t = std::numeric_limits< size_t >::max();
+ if (g_limit_size_t < uLength)
+ return osl_File_E_OVERFLOW;
+ size_t const nLength = sal::static_int_cast< size_t >(uLength);
+
+ if (-1 == munmap(static_cast<char*>(pAddr), nLength))
+ return oslTranslateFileError(OSL_FET_ERROR, errno);
+
+ return osl_File_E_None;
+}
+
+/*******************************************
+ osl_readLine
+********************************************/
+oslFileError
+SAL_CALL osl_readLine (
+ oslFileHandle Handle,
+ sal_Sequence ** ppSequence)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == ppSequence))
+ return osl_File_E_INVAL;
+ sal_uInt64 uBytesRead = 0;
+
+ // read at current fileptr; fileptr += uBytesRead;
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ oslFileError result = pImpl->readLineAt (
+ pImpl->m_fileptr, ppSequence, &uBytesRead);
+ if (result == osl_File_E_None)
+ pImpl->m_fileptr += uBytesRead;
+ return (result);
+}
+
+/*******************************************
+ osl_readFile
+********************************************/
+oslFileError
+SAL_CALL osl_readFile (
+ oslFileHandle Handle,
+ void * pBuffer,
+ sal_uInt64 uBytesRequested,
+ sal_uInt64 * pBytesRead)
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesRead))
+ return osl_File_E_INVAL;
+
+ static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max();
+ if (g_limit_ssize_t < uBytesRequested)
+ return osl_File_E_OVERFLOW;
+ size_t const nBytesRequested = sal::static_int_cast< size_t >(uBytesRequested);
+
+ // read at current fileptr; fileptr += *pBytesRead;
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ oslFileError result = pImpl->readFileAt (
+ pImpl->m_fileptr, pBuffer, nBytesRequested, pBytesRead);
+ if (result == osl_File_E_None)
+ pImpl->m_fileptr += *pBytesRead;
+ return (result);
+}
+
+/*******************************************
+ osl_writeFile
+********************************************/
+oslFileError
+SAL_CALL osl_writeFile (
+ oslFileHandle Handle,
+ const void * pBuffer,
+ sal_uInt64 uBytesToWrite,
+ sal_uInt64 * pBytesWritten)
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesWritten))
+ return osl_File_E_INVAL;
+ if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE))
+ return osl_File_E_BADF;
+
+ static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max();
+ if (g_limit_ssize_t < uBytesToWrite)
+ return osl_File_E_OVERFLOW;
+ size_t const nBytesToWrite = sal::static_int_cast< size_t >(uBytesToWrite);
+
+ // write at current fileptr; fileptr += *pBytesWritten;
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ oslFileError result = pImpl->writeFileAt (
+ pImpl->m_fileptr, pBuffer, nBytesToWrite, pBytesWritten);
+ if (result == osl_File_E_None)
+ pImpl->m_fileptr += *pBytesWritten;
+ return (result);
+}
+
+/*******************************************
+ osl_readFileAt
+********************************************/
+oslFileError
+SAL_CALL osl_readFileAt (
+ oslFileHandle Handle,
+ sal_uInt64 uOffset,
+ void* pBuffer,
+ sal_uInt64 uBytesRequested,
+ sal_uInt64* pBytesRead)
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesRead))
+ return osl_File_E_INVAL;
+ if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE))
+ return osl_File_E_SPIPE;
+
+ static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max();
+ if (g_limit_off_t < uOffset)
+ return osl_File_E_OVERFLOW;
+ off_t const nOffset = sal::static_int_cast< off_t >(uOffset);
+
+ static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max();
+ if (g_limit_ssize_t < uBytesRequested)
+ return osl_File_E_OVERFLOW;
+ size_t const nBytesRequested = sal::static_int_cast< size_t >(uBytesRequested);
+
+ // read at specified fileptr
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ return pImpl->readFileAt (nOffset, pBuffer, nBytesRequested, pBytesRead);
+}
+
+/*******************************************
+ osl_writeFileAt
+********************************************/
+oslFileError
+SAL_CALL osl_writeFileAt (
+ oslFileHandle Handle,
+ sal_uInt64 uOffset,
+ const void* pBuffer,
+ sal_uInt64 uBytesToWrite,
+ sal_uInt64* pBytesWritten)
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesWritten))
+ return osl_File_E_INVAL;
+ if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE))
+ return osl_File_E_SPIPE;
+ if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE))
+ return osl_File_E_BADF;
+
+ static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max();
+ if (g_limit_off_t < uOffset)
+ return osl_File_E_OVERFLOW;
+ off_t const nOffset = sal::static_int_cast< off_t >(uOffset);
+
+ static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max();
+ if (g_limit_ssize_t < uBytesToWrite)
+ return osl_File_E_OVERFLOW;
+ size_t const nBytesToWrite = sal::static_int_cast< size_t >(uBytesToWrite);
+
+ // write at specified fileptr
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ return pImpl->writeFileAt (nOffset, pBuffer, nBytesToWrite, pBytesWritten);
+}
+
+/****************************************************************************/
+/* osl_isEndOfFile */
+/****************************************************************************/
+oslFileError
+SAL_CALL osl_isEndOfFile( oslFileHandle Handle, sal_Bool *pIsEOF )
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pIsEOF))
+ return osl_File_E_INVAL;
+
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ *pIsEOF = (pImpl->getPos() == pImpl->getSize());
+ return osl_File_E_None;
+}
+
+/************************************************
+ * osl_getFilePos
+ ***********************************************/
+oslFileError
+SAL_CALL osl_getFilePos( oslFileHandle Handle, sal_uInt64* pPos )
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pPos))
+ return osl_File_E_INVAL;
+
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ *pPos = pImpl->getPos();
+ return osl_File_E_None;
+}
+
+/*******************************************
+ osl_setFilePos
+********************************************/
+oslFileError
+SAL_CALL osl_setFilePos (oslFileHandle Handle, sal_uInt32 uHow, sal_Int64 uOffset)
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd))
+ return osl_File_E_INVAL;
+
+ static sal_Int64 const g_limit_off_t = std::numeric_limits< off_t >::max();
+ if (g_limit_off_t < uOffset)
+ return osl_File_E_OVERFLOW;
+ off_t nPos = 0, nOffset = sal::static_int_cast< off_t >(uOffset);
+
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ switch(uHow)
+ {
+ case osl_Pos_Absolut:
+ if (0 > nOffset)
+ return osl_File_E_INVAL;
+ break;
+
+ case osl_Pos_Current:
+ nPos = sal::static_int_cast< off_t >(pImpl->getPos());
+ if ((0 > nOffset) && (-1*nOffset > nPos))
+ return osl_File_E_INVAL;
+ if (g_limit_off_t < nPos + nOffset)
+ return osl_File_E_OVERFLOW;
+ break;
+
+ case osl_Pos_End:
+ nPos = sal::static_int_cast< off_t >(pImpl->getSize());
+ if ((0 > nOffset) && (-1*nOffset > nPos))
+ return osl_File_E_INVAL;
+ if (g_limit_off_t < nPos + nOffset)
+ return osl_File_E_OVERFLOW;
+ break;
+
+ default:
+ return osl_File_E_INVAL;
+ }
+
+ return pImpl->setPos (nPos + nOffset);
+}
+
+/****************************************************************************
+ * osl_getFileSize
+ ****************************************************************************/
+oslFileError
+SAL_CALL osl_getFileSize( oslFileHandle Handle, sal_uInt64* pSize )
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pSize))
+ return osl_File_E_INVAL;
+
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ *pSize = pImpl->getSize();
+ return osl_File_E_None;
+}
+
+/************************************************
+ * osl_setFileSize
+ ***********************************************/
+oslFileError
+SAL_CALL osl_setFileSize( oslFileHandle Handle, sal_uInt64 uSize )
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd))
+ return osl_File_E_INVAL;
+ if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE))
+ return osl_File_E_BADF;
+
+ static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max();
+ if (g_limit_off_t < uSize)
+ return osl_File_E_OVERFLOW;
+
+ oslFileError result = pImpl->syncFile();
+ if (result != osl_File_E_None)
+ return (result);
+ pImpl->m_bufptr = -1, pImpl->m_buflen = 0;
+
+ return pImpl->setSize (uSize);
+}