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