1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include "osl/file.hxx"
31 #include "osl/detail/file.h"
33 #include "osl/diagnose.h"
34 #include "rtl/alloc.h"
37 #include "createfilehandlefromfd.hxx"
38 #include "file_error_transl.h"
50 #include <sys/param.h>
51 #include <sys/mount.h>
54 // add MACOSX Time Value
55 #define TimeValue CFTimeValue
56 #include <CoreFoundation/CoreFoundation.h>
62 #include <osl/detail/android-bootstrap.h>
66 # define OSL_FILE_TRACE osl_trace
67 # define PERROR( a, b ) perror( a ); fprintf( stderr, b )
69 # define OSL_FILE_TRACE(fmt, ...)
70 # define PERROR( a, b )
75 /*******************************************************************
77 * FileHandle_Impl interface
79 ******************************************************************/
80 struct FileHandle_Impl
82 pthread_mutex_t m_mutex
;
83 rtl_String
* m_strFilePath
; /* holds native file path */
96 STATE_SEEKABLE
= 1, /* default */
97 STATE_READABLE
= 2, /* default */
98 STATE_WRITEABLE
= 4, /* open() sets, write() requires, else osl_File_E_BADF */
99 STATE_MODIFIED
= 8 /* write() sets, flush() resets */
103 sal_uInt64 m_size
; /* file size */
104 off_t m_offset
; /* physical offset from begin of file */
105 off_t m_fileptr
; /* logical offset from begin of file */
107 off_t m_bufptr
; /* buffer offset from begin of file */
108 size_t m_buflen
; /* buffer filled [0, m_bufsiz - 1] */
111 sal_uInt8
* m_buffer
;
113 explicit FileHandle_Impl (int fd
, Kind kind
= KIND_FD
, char const * path
= "<anon>");
116 static void* operator new (size_t n
);
117 static void operator delete (void * p
);
119 static size_t getpagesize();
121 sal_uInt64
getPos() const;
122 oslFileError
setPos (sal_uInt64 uPos
);
124 sal_uInt64
getSize() const;
125 oslFileError
setSize (sal_uInt64 uSize
);
127 oslFileError
readAt (
130 size_t nBytesRequested
,
131 sal_uInt64
* pBytesRead
);
133 oslFileError
writeAt (
135 void const * pBuffer
,
136 size_t nBytesToWrite
,
137 sal_uInt64
* pBytesWritten
);
139 oslFileError
readFileAt (
142 size_t nBytesRequested
,
143 sal_uInt64
* pBytesRead
);
145 oslFileError
writeFileAt (
147 void const * pBuffer
,
148 size_t nBytesToWrite
,
149 sal_uInt64
* pBytesWritten
);
151 oslFileError
readLineAt (
153 sal_Sequence
** ppSequence
,
154 sal_uInt64
* pBytesRead
);
156 oslFileError
writeSequence_Impl (
157 sal_Sequence
** ppSequence
,
159 const void * pBuffer
,
162 oslFileError
syncFile();
164 /** Buffer cache / allocator.
168 rtl_cache_type
* m_cache
;
171 Allocator (Allocator
const &);
172 Allocator
& operator= (Allocator
const &);
175 static Allocator
& get();
177 void allocate (sal_uInt8
** ppBuffer
, size_t * pnSize
);
178 void deallocate (sal_uInt8
* pBuffer
);
189 pthread_mutex_t
* m_mutex
;
192 explicit Guard(pthread_mutex_t
* pMutex
);
197 /*******************************************************************
199 * FileHandle_Impl implementation
201 ******************************************************************/
203 FileHandle_Impl::Allocator
&
204 FileHandle_Impl::Allocator::get()
206 static Allocator g_aBufferAllocator
;
207 return g_aBufferAllocator
;
210 FileHandle_Impl::Allocator::Allocator()
214 size_t const pagesize
= FileHandle_Impl::getpagesize();
215 if (size_t(-1) != pagesize
)
217 m_cache
= rtl_cache_create (
218 "osl_file_buffer_cache", pagesize
, 0, 0, 0, 0, 0, 0, 0);
223 FileHandle_Impl::Allocator::~Allocator()
225 rtl_cache_destroy (m_cache
), m_cache
= 0;
228 void FileHandle_Impl::Allocator::allocate (sal_uInt8
** ppBuffer
, size_t * pnSize
)
230 OSL_PRECOND((0 != ppBuffer
) && (0 != pnSize
), "FileHandle_Impl::Allocator::allocate(): contract violation");
231 if ((0 != ppBuffer
) && (0 != pnSize
))
232 *ppBuffer
= static_cast< sal_uInt8
* >(rtl_cache_alloc(m_cache
)), *pnSize
= m_bufsiz
;
234 void FileHandle_Impl::Allocator::deallocate (sal_uInt8
* pBuffer
)
237 rtl_cache_free (m_cache
, pBuffer
);
240 FileHandle_Impl::Guard::Guard(pthread_mutex_t
* pMutex
)
243 OSL_PRECOND (m_mutex
!= 0, "FileHandle_Impl::Guard::Guard(): null pointer.");
244 (void) pthread_mutex_lock (m_mutex
); // ignoring EINVAL ...
246 FileHandle_Impl::Guard::~Guard()
248 OSL_PRECOND (m_mutex
!= 0, "FileHandle_Impl::Guard::~Guard(): null pointer.");
249 (void) pthread_mutex_unlock (m_mutex
);
252 FileHandle_Impl::FileHandle_Impl (int fd
, enum Kind kind
, char const * path
)
256 m_state (STATE_SEEKABLE
| STATE_READABLE
),
265 (void) pthread_mutex_init(&m_mutex
, 0);
266 rtl_string_newFromStr (&m_strFilePath
, path
);
267 if (m_kind
== KIND_FD
) {
268 Allocator::get().allocate (&m_buffer
, &m_bufsiz
);
270 memset (m_buffer
, 0, m_bufsiz
);
273 FileHandle_Impl::~FileHandle_Impl()
275 if (m_kind
== KIND_FD
)
276 Allocator::get().deallocate (m_buffer
), m_buffer
= 0;
277 rtl_string_release (m_strFilePath
), m_strFilePath
= 0;
278 (void) pthread_mutex_destroy(&m_mutex
); // ignoring EBUSY ...
281 void* FileHandle_Impl::operator new (size_t n
)
283 return rtl_allocateMemory(n
);
285 void FileHandle_Impl::operator delete (void * p
)
290 size_t FileHandle_Impl::getpagesize()
292 #if defined(FREEBSD) || defined(NETBSD) || defined(MACOSX) || \
293 defined(OPENBSD) || defined(DRAGONFLY)
294 return sal::static_int_cast
< size_t >(::getpagesize());
296 return sal::static_int_cast
< size_t >(::sysconf(_SC_PAGESIZE
));
297 #endif /* xBSD || POSIX */
300 sal_uInt64
FileHandle_Impl::getPos() const
302 return sal::static_int_cast
< sal_uInt64
>(m_fileptr
);
305 oslFileError
FileHandle_Impl::setPos (sal_uInt64 uPos
)
307 OSL_FILE_TRACE("FileHandle_Impl::setPos(%d, %lld) => %lld", m_fd
, getPos(), uPos
);
308 m_fileptr
= sal::static_int_cast
< off_t
>(uPos
);
309 return osl_File_E_None
;
312 sal_uInt64
FileHandle_Impl::getSize() const
314 off_t
const bufend
= std::max((off_t
)(0), m_bufptr
) + m_buflen
;
315 return std::max(m_size
, sal::static_int_cast
< sal_uInt64
>(bufend
));
318 oslFileError
FileHandle_Impl::setSize (sal_uInt64 uSize
)
320 off_t
const nSize
= sal::static_int_cast
< off_t
>(uSize
);
321 if (-1 == ftruncate (m_fd
, nSize
))
323 /* Failure. Save original result. Try fallback algorithm */
324 oslFileError result
= oslTranslateFileError (OSL_FET_ERROR
, errno
);
326 /* Check against current size. Fail upon 'shrink' */
327 if (uSize
<= getSize())
329 /* Failure upon 'shrink'. Return original result */
333 /* Save current position */
334 off_t
const nCurPos
= (off_t
)lseek (m_fd
, (off_t
)0, SEEK_CUR
);
335 if (nCurPos
== (off_t
)(-1))
338 /* Try 'expand' via 'lseek()' and 'write()' */
339 if (-1 == lseek (m_fd
, (off_t
)(nSize
- 1), SEEK_SET
))
342 if (-1 == write (m_fd
, (char*)"", (size_t)1))
344 /* Failure. Restore saved position */
345 (void) lseek (m_fd
, (off_t
)(nCurPos
), SEEK_SET
);
349 /* Success. Restore saved position */
350 if (-1 == lseek (m_fd
, (off_t
)nCurPos
, SEEK_SET
))
354 OSL_FILE_TRACE("osl_setFileSize(%d, %lld) => %ld", m_fd
, getSize(), nSize
);
355 m_size
= sal::static_int_cast
< sal_uInt64
>(nSize
);
356 return osl_File_E_None
;
359 oslFileError
FileHandle_Impl::readAt (
362 size_t nBytesRequested
,
363 sal_uInt64
* pBytesRead
)
365 OSL_PRECOND((m_state
& STATE_SEEKABLE
), "FileHandle_Impl::readAt(): not seekable");
366 if (!(m_state
& STATE_SEEKABLE
))
367 return osl_File_E_SPIPE
;
369 OSL_PRECOND((m_state
& STATE_READABLE
), "FileHandle_Impl::readAt(): not readable");
370 if (!(m_state
& STATE_READABLE
))
371 return osl_File_E_BADF
;
373 if (m_kind
== KIND_MEM
)
379 if ((sal_uInt64
) m_offset
>= m_size
)
383 nBytes
= std::min(nBytesRequested
, (size_t) (m_size
- m_offset
));
384 memmove(pBuffer
, m_buffer
+ m_offset
, nBytes
);
387 *pBytesRead
= nBytes
;
388 return osl_File_E_None
;
391 #if defined(LINUX) || defined(SOLARIS)
393 ssize_t nBytes
= ::pread (m_fd
, pBuffer
, nBytesRequested
, nOffset
);
394 if ((-1 == nBytes
) && (EOVERFLOW
== errno
))
396 /* Some 'pread()'s fail with EOVERFLOW when reading at (or past)
397 * end-of-file, different from 'lseek() + read()' behaviour.
398 * Returning '0 bytes read' and 'osl_File_E_None' instead.
403 return oslTranslateFileError (OSL_FET_ERROR
, errno
);
405 #else /* !(LINUX || SOLARIS) */
407 if (nOffset
!= m_offset
)
409 if (-1 == ::lseek (m_fd
, nOffset
, SEEK_SET
))
410 return oslTranslateFileError (OSL_FET_ERROR
, errno
);
414 ssize_t nBytes
= ::read (m_fd
, pBuffer
, nBytesRequested
);
416 return oslTranslateFileError (OSL_FET_ERROR
, errno
);
419 #endif /* !(LINUX || SOLARIS) */
421 OSL_FILE_TRACE("FileHandle_Impl::readAt(%d, %lld, %ld)", m_fd
, nOffset
, nBytes
);
422 *pBytesRead
= nBytes
;
423 return osl_File_E_None
;
426 oslFileError
FileHandle_Impl::writeAt (
428 void const * pBuffer
,
429 size_t nBytesToWrite
,
430 sal_uInt64
* pBytesWritten
)
432 OSL_PRECOND((m_state
& STATE_SEEKABLE
), "FileHandle_Impl::writeAt(): not seekable");
433 if (!(m_state
& STATE_SEEKABLE
))
434 return osl_File_E_SPIPE
;
436 OSL_PRECOND((m_state
& STATE_WRITEABLE
), "FileHandle_Impl::writeAt(): not writeable");
437 if (!(m_state
& STATE_WRITEABLE
))
438 return osl_File_E_BADF
;
440 #if defined(LINUX) || defined(SOLARIS)
442 ssize_t nBytes
= ::pwrite (m_fd
, pBuffer
, nBytesToWrite
, nOffset
);
444 return oslTranslateFileError (OSL_FET_ERROR
, errno
);
446 #else /* !(LINUX || SOLARIS) */
448 if (nOffset
!= m_offset
)
450 if (-1 == ::lseek (m_fd
, nOffset
, SEEK_SET
))
451 return oslTranslateFileError (OSL_FET_ERROR
, errno
);
455 ssize_t nBytes
= ::write (m_fd
, pBuffer
, nBytesToWrite
);
457 return oslTranslateFileError (OSL_FET_ERROR
, errno
);
460 #endif /* !(LINUX || SOLARIS) */
462 OSL_FILE_TRACE("FileHandle_Impl::writeAt(%d, %lld, %ld)", m_fd
, nOffset
, nBytes
);
463 m_size
= std::max (m_size
, sal::static_int_cast
< sal_uInt64
>(nOffset
+ nBytes
));
465 *pBytesWritten
= nBytes
;
466 return osl_File_E_None
;
469 oslFileError
FileHandle_Impl::readFileAt (
472 size_t nBytesRequested
,
473 sal_uInt64
* pBytesRead
)
475 if (0 == (m_state
& STATE_SEEKABLE
))
477 // not seekable (pipe)
478 ssize_t nBytes
= ::read (m_fd
, pBuffer
, nBytesRequested
);
480 return oslTranslateFileError (OSL_FET_ERROR
, errno
);
481 *pBytesRead
= nBytes
;
482 return osl_File_E_None
;
484 else if (m_kind
== KIND_MEM
|| 0 == m_buffer
)
487 return readAt (nOffset
, pBuffer
, nBytesRequested
, pBytesRead
);
491 sal_uInt8
* buffer
= static_cast<sal_uInt8
*>(pBuffer
);
492 for (*pBytesRead
= 0; nBytesRequested
> 0; )
494 off_t
const bufptr
= (nOffset
/ m_bufsiz
) * m_bufsiz
;
495 size_t const bufpos
= (nOffset
% m_bufsiz
);
497 if (bufptr
!= m_bufptr
)
499 // flush current buffer
500 oslFileError result
= syncFile();
501 if (result
!= osl_File_E_None
)
503 m_bufptr
= -1, m_buflen
= 0;
505 if (nBytesRequested
>= m_bufsiz
)
507 // buffer too small, read through from file
508 sal_uInt64 uDone
= 0;
509 result
= readAt (nOffset
, &(buffer
[*pBytesRead
]), nBytesRequested
, &uDone
);
510 if (result
!= osl_File_E_None
)
513 nBytesRequested
-= uDone
, *pBytesRead
+= uDone
;
514 return osl_File_E_None
;
517 // update buffer (pointer)
518 sal_uInt64 uDone
= 0;
519 result
= readAt (bufptr
, m_buffer
, m_bufsiz
, &uDone
);
520 if (result
!= osl_File_E_None
)
522 m_bufptr
= bufptr
, m_buflen
= uDone
;
524 if (bufpos
>= m_buflen
)
527 return osl_File_E_None
;
530 size_t const bytes
= std::min (m_buflen
- bufpos
, nBytesRequested
);
531 OSL_FILE_TRACE("FileHandle_Impl::readFileAt(%d, %lld, %ld)", m_fd
, nOffset
, bytes
);
533 memcpy (&(buffer
[*pBytesRead
]), &(m_buffer
[bufpos
]), bytes
);
534 nBytesRequested
-= bytes
, *pBytesRead
+= bytes
, nOffset
+= bytes
;
536 return osl_File_E_None
;
540 oslFileError
FileHandle_Impl::writeFileAt (
542 void const * pBuffer
,
543 size_t nBytesToWrite
,
544 sal_uInt64
* pBytesWritten
)
546 if (0 == (m_state
& STATE_SEEKABLE
))
548 // not seekable (pipe)
549 ssize_t nBytes
= ::write (m_fd
, pBuffer
, nBytesToWrite
);
551 return oslTranslateFileError (OSL_FET_ERROR
, errno
);
552 *pBytesWritten
= nBytes
;
553 return osl_File_E_None
;
555 else if (0 == m_buffer
)
558 return writeAt (nOffset
, pBuffer
, nBytesToWrite
, pBytesWritten
);
562 sal_uInt8
const * buffer
= static_cast<sal_uInt8
const *>(pBuffer
);
563 for (*pBytesWritten
= 0; nBytesToWrite
> 0; )
565 off_t
const bufptr
= (nOffset
/ m_bufsiz
) * m_bufsiz
;
566 size_t const bufpos
= (nOffset
% m_bufsiz
);
567 if (bufptr
!= m_bufptr
)
569 // flush current buffer
570 oslFileError result
= syncFile();
571 if (result
!= osl_File_E_None
)
573 m_bufptr
= -1, m_buflen
= 0;
575 if (nBytesToWrite
>= m_bufsiz
)
577 // buffer to small, write through to file
578 sal_uInt64 uDone
= 0;
579 result
= writeAt (nOffset
, &(buffer
[*pBytesWritten
]), nBytesToWrite
, &uDone
);
580 if (result
!= osl_File_E_None
)
582 if (uDone
!= nBytesToWrite
)
583 return osl_File_E_IO
;
585 nBytesToWrite
-= uDone
, *pBytesWritten
+= uDone
;
586 return osl_File_E_None
;
589 // update buffer (pointer)
590 sal_uInt64 uDone
= 0;
591 result
= readAt (bufptr
, m_buffer
, m_bufsiz
, &uDone
);
592 if (result
!= osl_File_E_None
)
594 m_bufptr
= bufptr
, m_buflen
= uDone
;
597 size_t const bytes
= std::min (m_bufsiz
- bufpos
, nBytesToWrite
);
598 OSL_FILE_TRACE("FileHandle_Impl::writeFileAt(%d, %lld, %ld)", m_fd
, nOffset
, bytes
);
600 memcpy (&(m_buffer
[bufpos
]), &(buffer
[*pBytesWritten
]), bytes
);
601 nBytesToWrite
-= bytes
, *pBytesWritten
+= bytes
, nOffset
+= bytes
;
603 m_buflen
= std::max(m_buflen
, bufpos
+ bytes
);
604 m_state
|= STATE_MODIFIED
;
606 return osl_File_E_None
;
610 oslFileError
FileHandle_Impl::readLineAt (
612 sal_Sequence
** ppSequence
,
613 sal_uInt64
* pBytesRead
)
615 oslFileError result
= osl_File_E_None
;
617 off_t bufptr
= nOffset
/ m_bufsiz
* m_bufsiz
;
618 if (bufptr
!= m_bufptr
)
620 /* flush current buffer */
622 if (result
!= osl_File_E_None
)
625 /* update buffer (pointer) */
626 sal_uInt64 uDone
= 0;
627 result
= readAt (bufptr
, m_buffer
, m_bufsiz
, &uDone
);
628 if (result
!= osl_File_E_None
)
631 m_bufptr
= bufptr
, m_buflen
= uDone
;
634 static int const LINE_STATE_BEGIN
= 0;
635 static int const LINE_STATE_CR
= 1;
636 static int const LINE_STATE_LF
= 2;
638 size_t bufpos
= nOffset
- m_bufptr
, curpos
= bufpos
, dstpos
= 0;
639 int state
= (bufpos
>= m_buflen
) ? LINE_STATE_LF
: LINE_STATE_BEGIN
;
641 for ( ; state
!= LINE_STATE_LF
; )
643 if (curpos
>= m_buflen
)
645 /* buffer examined */
646 if (0 < (curpos
- bufpos
))
648 /* flush buffer to sequence */
649 result
= writeSequence_Impl (
650 ppSequence
, &dstpos
, &(m_buffer
[bufpos
]), curpos
- bufpos
);
651 if (result
!= osl_File_E_None
)
653 *pBytesRead
+= curpos
- bufpos
, nOffset
+= curpos
- bufpos
;
656 bufptr
= nOffset
/ m_bufsiz
* m_bufsiz
;
657 if (bufptr
!= m_bufptr
)
659 /* update buffer (pointer) */
660 sal_uInt64 uDone
= 0;
661 result
= readAt (bufptr
, m_buffer
, m_bufsiz
, &uDone
);
662 if (result
!= osl_File_E_None
)
664 m_bufptr
= bufptr
, m_buflen
= uDone
;
667 bufpos
= nOffset
- m_bufptr
, curpos
= bufpos
;
668 if (bufpos
>= m_buflen
)
674 state
= LINE_STATE_LF
;
675 switch (m_buffer
[curpos
])
677 case 0x0A: /* CRLF */
678 /* eat current char */
681 default: /* single CR */
682 /* keep current char */
687 /* determine next state */
688 switch (m_buffer
[curpos
])
690 case 0x0A: /* single LF */
691 state
= LINE_STATE_LF
;
694 state
= LINE_STATE_CR
;
696 default: /* advance to next char */
700 if (state
!= LINE_STATE_BEGIN
)
702 /* skip the newline char */
705 /* flush buffer to sequence */
706 result
= writeSequence_Impl (
707 ppSequence
, &dstpos
, &(m_buffer
[bufpos
]), curpos
- bufpos
- 1);
708 if (result
!= osl_File_E_None
)
710 *pBytesRead
+= curpos
- bufpos
, nOffset
+= curpos
- bufpos
;
716 result
= writeSequence_Impl (ppSequence
, &dstpos
, 0, 0);
717 if (result
!= osl_File_E_None
)
720 return osl_File_E_None
;
721 if (bufpos
>= m_buflen
)
722 return osl_File_E_AGAIN
;
723 return osl_File_E_None
;
726 oslFileError
FileHandle_Impl::writeSequence_Impl (
727 sal_Sequence
** ppSequence
,
729 const void * pBuffer
,
732 sal_Int32 nElements
= *pnOffset
+ nBytes
;
735 /* construct sequence */
736 rtl_byte_sequence_constructNoDefault(ppSequence
, nElements
);
738 else if (nElements
!= (*ppSequence
)->nElements
)
740 /* resize sequence */
741 rtl_byte_sequence_realloc(ppSequence
, nElements
);
743 if (*ppSequence
!= 0)
746 memcpy(&((*ppSequence
)->elements
[*pnOffset
]), pBuffer
, nBytes
), *pnOffset
+= nBytes
;
748 return (*ppSequence
!= 0) ? osl_File_E_None
: osl_File_E_NOMEM
;
751 oslFileError
FileHandle_Impl::syncFile()
753 oslFileError result
= osl_File_E_None
;
754 if (m_state
& STATE_MODIFIED
)
756 sal_uInt64 uDone
= 0;
757 result
= writeAt (m_bufptr
, m_buffer
, m_buflen
, &uDone
);
758 if (result
!= osl_File_E_None
)
760 if (uDone
!= m_buflen
)
761 return osl_File_E_IO
;
762 m_state
&= ~STATE_MODIFIED
;
767 oslFileHandle
osl::detail::createFileHandleFromFD( int fd
)
772 struct stat aFileStat
;
773 if (-1 == fstat (fd
, &aFileStat
))
776 FileHandle_Impl
* pImpl
= new FileHandle_Impl (fd
);
781 pImpl
->m_state
|= FileHandle_Impl::STATE_WRITEABLE
;
782 if (!S_ISREG(aFileStat
.st_mode
))
784 /* not a regular file, mark not seekable */
785 pImpl
->m_state
&= ~FileHandle_Impl::STATE_SEEKABLE
;
789 /* regular file, init current size */
790 pImpl
->m_size
= sal::static_int_cast
< sal_uInt64
>(aFileStat
.st_size
);
793 OSL_FILE_TRACE("osl::detail::createFileHandleFromFD(%d, writeable) => %s",
794 pImpl
->m_fd
, rtl_string_getStr(pImpl
->m_strFilePath
));
795 return (oslFileHandle
)(pImpl
);
798 /*******************************************************************
799 * osl_file_adjustLockFlags
800 ******************************************************************/
801 static int osl_file_adjustLockFlags (const char * path
, int flags
)
805 * The AFP implementation of MacOS X 10.4 treats O_EXLOCK in a way
806 * that makes it impossible for OOo to create a backup copy of the
807 * file it keeps opened. OTOH O_SHLOCK for AFP behaves as desired by
808 * the OOo file handling, so we need to check the path of the file
809 * for the filesystem name.
812 if( 0 <= statfs( path
, &s
) )
814 if( 0 == strncmp("afpfs", s
.f_fstypename
, 5) )
821 /* Needed flags to allow opening a webdav file */
822 flags
&= ~(O_EXLOCK
| O_SHLOCK
| O_NONBLOCK
);
831 /****************************************************************************
832 * osl_file_queryLocking
833 ***************************************************************************/
837 Locking_Impl() : m_enabled(0)
839 #ifndef HAVE_O_EXLOCK
840 m_enabled
= (getenv("SAL_ENABLE_FILE_LOCKING") != 0);
841 #endif /* HAVE_O_EXLOCK */
844 static int osl_file_queryLocking (sal_uInt32 uFlags
)
846 if (!(uFlags
& osl_File_OpenFlag_NoLock
))
848 if ((uFlags
& osl_File_OpenFlag_Write
) || (uFlags
& osl_File_OpenFlag_Create
))
850 static Locking_Impl g_locking
;
851 return (g_locking
.m_enabled
!= 0);
860 osl_openMemoryAsFile( void *address
, size_t size
, oslFileHandle
*pHandle
, const char *path
)
863 FileHandle_Impl
* pImpl
= new FileHandle_Impl (-1, FileHandle_Impl::KIND_MEM
, path
);
866 eRet
= oslTranslateFileError (OSL_FET_ERROR
, ENOMEM
);
869 pImpl
->m_size
= sal::static_int_cast
< sal_uInt64
>(size
);
871 *pHandle
= (oslFileHandle
)(pImpl
);
874 pImpl
->m_buflen
= size
;
876 pImpl
->m_bufsiz
= size
;
877 pImpl
->m_buffer
= (sal_uInt8
*) address
;
879 return osl_File_E_None
;
883 SAL_CALL
osl_openMemoryAsFile( void *address
, size_t size
, oslFileHandle
*pHandle
)
885 return osl_openMemoryAsFile( address
, size
, pHandle
, "<anon>" );
890 /****************************************************************************
892 ***************************************************************************/
894 #define OPEN_WRITE_FLAGS ( O_RDWR | O_EXLOCK | O_NONBLOCK )
895 #define OPEN_CREATE_FLAGS ( O_CREAT | O_RDWR | O_EXLOCK | O_NONBLOCK )
897 #define OPEN_WRITE_FLAGS ( O_RDWR )
898 #define OPEN_CREATE_FLAGS ( O_CREAT | O_RDWR )
902 SAL_CALL
osl_openFilePath( const char *cpFilePath
, oslFileHandle
* pHandle
, sal_uInt32 uFlags
)
907 /* Opening a file from /assets read-only means
908 * we should mmap it from the .apk file
910 if (strncmp (cpFilePath
, "/assets/", sizeof ("/assets/") - 1) == 0)
912 if (uFlags
& osl_File_OpenFlag_Write
)
914 // Or should we just silently "open" it read-only and let write
915 // attempts, if any, fail then later?
916 OSL_TRACE("osl_openFile(%s, writeable), not possible!", cpFilePath
);
918 return osl_File_E_PERM
;
922 address
= lo_apkentry(cpFilePath
, &size
);
923 OSL_TRACE("osl_openFile(%s) => %p",
924 cpFilePath
, address
);
928 return osl_File_E_NOENT
;
930 return osl_openMemoryAsFile(address
, size
, pHandle
, cpFilePath
);
934 /* set mode and flags */
935 int mode
= S_IRUSR
| S_IRGRP
| S_IROTH
;
936 int flags
= O_RDONLY
;
937 if (uFlags
& osl_File_OpenFlag_Write
)
939 mode
|= S_IWUSR
| S_IWGRP
| S_IWOTH
;
940 flags
= OPEN_WRITE_FLAGS
;
942 if (uFlags
& osl_File_OpenFlag_Create
)
944 mode
|= S_IWUSR
| S_IWGRP
| S_IWOTH
;
945 flags
= OPEN_CREATE_FLAGS
;
948 /* Check for flags passed in from SvFileStream::Open() */
949 if (uFlags
& osl_File_OpenFlag_Trunc
)
951 if (!(uFlags
& osl_File_OpenFlag_NoExcl
))
954 if (uFlags
& osl_File_OpenFlag_NoLock
)
957 flags
&= ~(O_EXLOCK
| O_SHLOCK
| O_NONBLOCK
);
958 #endif /* HAVE_O_EXLOCK */
962 flags
= osl_file_adjustLockFlags (cpFilePath
, flags
);
966 int fd
= open( cpFilePath
, flags
, mode
);
969 int saved_errno
= errno
;
970 OSL_TRACE("osl_openFile(%s, %s) failed: %s",
972 flags
& O_RDWR
? "writeable":"readonly",
973 strerror(saved_errno
));
974 return oslTranslateFileError (OSL_FET_ERROR
, saved_errno
);
977 /* reset O_NONBLOCK flag */
978 if (flags
& O_NONBLOCK
)
980 int f
= fcntl (fd
, F_GETFL
, 0);
983 int saved_errno
= errno
;
984 OSL_TRACE("osl_openFile(%s, %s): fcntl(%d, F_GETFL) failed: %s",
986 flags
& O_RDWR
? "writeable":"readonly",
988 strerror(saved_errno
));
989 eRet
= oslTranslateFileError (OSL_FET_ERROR
, saved_errno
);
993 if (-1 == fcntl (fd
, F_SETFL
, (f
& ~O_NONBLOCK
)))
995 int saved_errno
= errno
;
996 OSL_TRACE("osl_openFile(%s, %s): fcntl(%d, F_SETFL) failed: %s",
998 flags
& O_RDWR
? "writeable":"readonly",
1000 strerror(saved_errno
));
1001 eRet
= oslTranslateFileError (OSL_FET_ERROR
, saved_errno
);
1007 /* get file status (mode, size) */
1008 struct stat aFileStat
;
1009 if (-1 == fstat (fd
, &aFileStat
))
1011 int saved_errno
= errno
;
1012 OSL_TRACE("osl_openFile(%s, %s): fstat(%d) failed: %s",
1014 flags
& O_RDWR
? "writeable":"readonly",
1016 strerror(saved_errno
));
1017 eRet
= oslTranslateFileError (OSL_FET_ERROR
, saved_errno
);
1021 if (!S_ISREG(aFileStat
.st_mode
))
1023 /* we only open regular files here */
1024 OSL_TRACE("osl_openFile(%s): not a regular file",
1027 return osl_File_E_INVAL
;
1030 if (osl_file_queryLocking (uFlags
))
1033 if (-1 == flock (fd
, LOCK_EX
| LOCK_NB
))
1035 /* Mac OSX returns ENOTSUP for webdav drives. We should try read lock */
1036 if ((errno
!= ENOTSUP
) || ((-1 == flock (fd
, LOCK_SH
| LOCK_NB
)) && (errno
!= ENOTSUP
)))
1038 eRet
= oslTranslateFileError (OSL_FET_ERROR
, errno
);
1045 struct flock aflock
;
1047 aflock
.l_type
= F_WRLCK
;
1048 aflock
.l_whence
= SEEK_SET
;
1052 if (-1 == fcntl (fd
, F_SETLK
, &aflock
))
1054 int saved_errno
= errno
;
1055 OSL_TRACE("osl_openFile(%s, %s): fcntl(%d, F_SETLK) failed: %s",
1057 flags
& O_RDWR
? "writeable":"readonly",
1059 strerror(saved_errno
));
1060 eRet
= oslTranslateFileError (OSL_FET_ERROR
, saved_errno
);
1065 #endif /* F_SETLK */
1068 /* allocate memory for impl structure */
1069 FileHandle_Impl
* pImpl
= new FileHandle_Impl (fd
, FileHandle_Impl::KIND_FD
, cpFilePath
);
1072 eRet
= oslTranslateFileError (OSL_FET_ERROR
, ENOMEM
);
1077 pImpl
->m_state
|= FileHandle_Impl::STATE_WRITEABLE
;
1078 pImpl
->m_size
= sal::static_int_cast
< sal_uInt64
>(aFileStat
.st_size
);
1080 OSL_TRACE("osl_openFile(%s, %s) => %d",
1081 rtl_string_getStr(pImpl
->m_strFilePath
),
1082 flags
& O_RDWR
? "writeable":"readonly",
1085 *pHandle
= (oslFileHandle
)(pImpl
);
1086 return osl_File_E_None
;
1090 SAL_CALL
osl_openFile( rtl_uString
* ustrFileURL
, oslFileHandle
* pHandle
, sal_uInt32 uFlags
)
1094 if ((ustrFileURL
== 0) || (ustrFileURL
->length
== 0) || (pHandle
== 0))
1095 return osl_File_E_INVAL
;
1097 /* convert file URL to system path */
1098 char buffer
[PATH_MAX
];
1099 eRet
= FileURLToPath (buffer
, sizeof(buffer
), ustrFileURL
);
1100 if (eRet
!= osl_File_E_None
)
1104 if (macxp_resolveAlias (buffer
, sizeof(buffer
)) != 0)
1105 return oslTranslateFileError (OSL_FET_ERROR
, errno
);
1108 return osl_openFilePath (buffer
, pHandle
, uFlags
);
1111 /****************************************************************************/
1113 /****************************************************************************/
1115 SAL_CALL
osl_closeFile( oslFileHandle Handle
)
1117 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1120 return osl_File_E_INVAL
;
1122 OSL_TRACE("osl_closeFile(%s:%d)", rtl_string_getStr(pImpl
->m_strFilePath
), pImpl
->m_fd
);
1124 if (pImpl
->m_kind
== FileHandle_Impl::KIND_MEM
)
1127 return osl_File_E_None
;
1130 if (pImpl
->m_fd
< 0)
1131 return osl_File_E_INVAL
;
1133 (void) pthread_mutex_lock (&(pImpl
->m_mutex
));
1135 /* close(2) implicitly (and unconditionally) unlocks */
1136 oslFileError result
= pImpl
->syncFile();
1137 if (result
!= osl_File_E_None
)
1139 /* close, ignoring double failure */
1140 (void) close (pImpl
->m_fd
);
1142 else if (-1 == close (pImpl
->m_fd
))
1144 /* translate error code */
1145 result
= oslTranslateFileError (OSL_FET_ERROR
, errno
);
1148 (void) pthread_mutex_unlock (&(pImpl
->m_mutex
));
1153 /************************************************
1155 ***********************************************/
1157 SAL_CALL
osl_syncFile(oslFileHandle Handle
)
1159 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1161 if ((0 == pImpl
) || ((pImpl
->m_kind
== FileHandle_Impl::KIND_FD
) && (-1 == pImpl
->m_fd
)))
1162 return osl_File_E_INVAL
;
1164 if (pImpl
->m_kind
== FileHandle_Impl::KIND_MEM
)
1165 return osl_File_E_None
;
1167 FileHandle_Impl::Guard
lock (&(pImpl
->m_mutex
));
1169 OSL_TRACE("osl_syncFile(%d)", pImpl
->m_fd
);
1170 oslFileError result
= pImpl
->syncFile();
1171 if (result
!= osl_File_E_None
)
1173 if (-1 == fsync (pImpl
->m_fd
))
1174 return oslTranslateFileError (OSL_FET_ERROR
, errno
);
1176 return osl_File_E_None
;
1179 /************************************************
1180 * osl_fileGetOSHandle
1181 ***********************************************/
1183 SAL_CALL
osl_getFileOSHandle(
1184 oslFileHandle Handle
,
1185 sal_IntPtr
*piFileHandle
)
1187 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1189 if (0 == pImpl
|| pImpl
->m_kind
!= FileHandle_Impl::KIND_FD
|| -1 == pImpl
->m_fd
)
1190 return osl_File_E_INVAL
;
1192 *piFileHandle
= pImpl
->m_fd
;
1194 return osl_File_E_None
;
1197 /*******************************************
1199 ********************************************/
1201 SAL_CALL
osl_mapFile (
1202 oslFileHandle Handle
,
1209 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1211 if ((0 == pImpl
) || ((pImpl
->m_kind
== FileHandle_Impl::KIND_FD
) && (-1 == pImpl
->m_fd
)) || (0 == ppAddr
))
1212 return osl_File_E_INVAL
;
1215 static sal_uInt64
const g_limit_size_t
= std::numeric_limits
< size_t >::max();
1216 if (g_limit_size_t
< uLength
)
1217 return osl_File_E_OVERFLOW
;
1218 size_t const nLength
= sal::static_int_cast
< size_t >(uLength
);
1220 static sal_uInt64
const g_limit_off_t
= std::numeric_limits
< off_t
>::max();
1221 if (g_limit_off_t
< uOffset
)
1222 return osl_File_E_OVERFLOW
;
1224 if (pImpl
->m_kind
== FileHandle_Impl::KIND_MEM
)
1226 *ppAddr
= pImpl
->m_buffer
+ uOffset
;
1227 return osl_File_E_None
;
1230 off_t
const nOffset
= sal::static_int_cast
< off_t
>(uOffset
);
1232 void* p
= mmap(NULL
, nLength
, PROT_READ
, MAP_SHARED
, pImpl
->m_fd
, nOffset
);
1233 if (MAP_FAILED
== p
)
1234 return oslTranslateFileError(OSL_FET_ERROR
, errno
);
1237 if (uFlags
& osl_File_MapFlag_RandomAccess
)
1239 // Determine memory pagesize.
1240 size_t const nPageSize
= FileHandle_Impl::getpagesize();
1241 if (size_t(-1) != nPageSize
)
1244 * Pagein, touching first byte of every memory page.
1245 * Note: volatile disables optimizing the loop away.
1247 sal_uInt8
* pData (reinterpret_cast<sal_uInt8
*>(*ppAddr
));
1248 size_t nSize (nLength
);
1250 volatile sal_uInt8 c
= 0;
1251 while (nSize
> nPageSize
)
1263 if (uFlags
& osl_File_MapFlag_WillNeed
)
1265 // On Linux, madvise(..., MADV_WILLNEED) appears to have the undesirable
1266 // effect of not returning until the data has actually been paged in, so
1267 // that its net effect would typically be to slow down the process
1268 // (which could start processing at the beginning of the data while the
1269 // OS simultaneously pages in the rest); on other platforms, it remains
1270 // to be evaluated whether madvise or equivalent is available and
1273 int e
= posix_madvise(p
, nLength
, POSIX_MADV_WILLNEED
);
1277 "posix_madvise(..., POSIX_MADV_WILLNEED) failed with %d", e
);
1279 #elif defined SOLARIS
1280 if (madvise(static_cast< caddr_t
>(p
), nLength
, MADV_WILLNEED
) != 0)
1282 OSL_TRACE("madvise(..., MADV_WILLNEED) failed with %d", errno
);
1286 return osl_File_E_None
;
1291 unmapFile (void* pAddr
, sal_uInt64 uLength
)
1294 return osl_File_E_INVAL
;
1296 static sal_uInt64
const g_limit_size_t
= std::numeric_limits
< size_t >::max();
1297 if (g_limit_size_t
< uLength
)
1298 return osl_File_E_OVERFLOW
;
1299 size_t const nLength
= sal::static_int_cast
< size_t >(uLength
);
1301 if (-1 == munmap(static_cast<char*>(pAddr
), nLength
))
1302 return oslTranslateFileError(OSL_FET_ERROR
, errno
);
1304 return osl_File_E_None
;
1309 // Note that osl_unmapFile() just won't work on Android in general
1310 // where for (uncompressed) files inside the .apk, in the /assets
1311 // folder osl_mapFile just returns a pointer to the file inside the
1312 // already mmapped .apk archive.
1314 /*******************************************
1316 ********************************************/
1318 SAL_CALL
osl_unmapFile (void* pAddr
, sal_uInt64 uLength
)
1320 return unmapFile (pAddr
, uLength
);
1325 /*******************************************
1327 ********************************************/
1329 SAL_CALL
osl_unmapMappedFile (oslFileHandle Handle
, void* pAddr
, sal_uInt64 uLength
)
1331 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1334 return osl_File_E_INVAL
;
1336 if (pImpl
->m_kind
== FileHandle_Impl::KIND_FD
)
1337 return unmapFile (pAddr
, uLength
);
1339 // For parts of already mmapped "parent" files, whose mapping we
1340 // can't change, not much we can or should do...
1341 return osl_File_E_None
;
1344 /*******************************************
1346 ********************************************/
1348 SAL_CALL
osl_readLine (
1349 oslFileHandle Handle
,
1350 sal_Sequence
** ppSequence
)
1352 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1354 if ((0 == pImpl
) || ((pImpl
->m_kind
== FileHandle_Impl::KIND_FD
) && (-1 == pImpl
->m_fd
)) || (0 == ppSequence
))
1355 return osl_File_E_INVAL
;
1356 sal_uInt64 uBytesRead
= 0;
1358 // read at current fileptr; fileptr += uBytesRead;
1359 FileHandle_Impl::Guard
lock (&(pImpl
->m_mutex
));
1360 oslFileError result
= pImpl
->readLineAt (
1361 pImpl
->m_fileptr
, ppSequence
, &uBytesRead
);
1362 if (result
== osl_File_E_None
)
1363 pImpl
->m_fileptr
+= uBytesRead
;
1367 /*******************************************
1369 ********************************************/
1371 SAL_CALL
osl_readFile (
1372 oslFileHandle Handle
,
1374 sal_uInt64 uBytesRequested
,
1375 sal_uInt64
* pBytesRead
)
1377 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1379 if ((0 == pImpl
) || ((pImpl
->m_kind
== FileHandle_Impl::KIND_FD
) && (-1 == pImpl
->m_fd
)) || (0 == pBuffer
) || (0 == pBytesRead
))
1380 return osl_File_E_INVAL
;
1382 static sal_uInt64
const g_limit_ssize_t
= std::numeric_limits
< ssize_t
>::max();
1383 if (g_limit_ssize_t
< uBytesRequested
)
1384 return osl_File_E_OVERFLOW
;
1385 size_t const nBytesRequested
= sal::static_int_cast
< size_t >(uBytesRequested
);
1387 // read at current fileptr; fileptr += *pBytesRead;
1388 FileHandle_Impl::Guard
lock (&(pImpl
->m_mutex
));
1389 oslFileError result
= pImpl
->readFileAt (
1390 pImpl
->m_fileptr
, pBuffer
, nBytesRequested
, pBytesRead
);
1391 if (result
== osl_File_E_None
)
1392 pImpl
->m_fileptr
+= *pBytesRead
;
1396 /*******************************************
1398 ********************************************/
1400 SAL_CALL
osl_writeFile (
1401 oslFileHandle Handle
,
1402 const void * pBuffer
,
1403 sal_uInt64 uBytesToWrite
,
1404 sal_uInt64
* pBytesWritten
)
1406 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1408 if ((0 == pImpl
) || (-1 == pImpl
->m_fd
) || (0 == pBuffer
) || (0 == pBytesWritten
))
1409 return osl_File_E_INVAL
;
1410 if (0 == (pImpl
->m_state
& FileHandle_Impl::STATE_WRITEABLE
))
1411 return osl_File_E_BADF
;
1413 static sal_uInt64
const g_limit_ssize_t
= std::numeric_limits
< ssize_t
>::max();
1414 if (g_limit_ssize_t
< uBytesToWrite
)
1415 return osl_File_E_OVERFLOW
;
1416 size_t const nBytesToWrite
= sal::static_int_cast
< size_t >(uBytesToWrite
);
1418 // write at current fileptr; fileptr += *pBytesWritten;
1419 FileHandle_Impl::Guard
lock (&(pImpl
->m_mutex
));
1420 oslFileError result
= pImpl
->writeFileAt (
1421 pImpl
->m_fileptr
, pBuffer
, nBytesToWrite
, pBytesWritten
);
1422 if (result
== osl_File_E_None
)
1423 pImpl
->m_fileptr
+= *pBytesWritten
;
1427 /*******************************************
1429 ********************************************/
1431 SAL_CALL
osl_readFileAt (
1432 oslFileHandle Handle
,
1435 sal_uInt64 uBytesRequested
,
1436 sal_uInt64
* pBytesRead
)
1438 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1440 if ((0 == pImpl
) || ((pImpl
->m_kind
== FileHandle_Impl::KIND_FD
) && (-1 == pImpl
->m_fd
)) || (0 == pBuffer
) || (0 == pBytesRead
))
1441 return osl_File_E_INVAL
;
1442 if (0 == (pImpl
->m_state
& FileHandle_Impl::STATE_SEEKABLE
))
1443 return osl_File_E_SPIPE
;
1445 static sal_uInt64
const g_limit_off_t
= std::numeric_limits
< off_t
>::max();
1446 if (g_limit_off_t
< uOffset
)
1447 return osl_File_E_OVERFLOW
;
1448 off_t
const nOffset
= sal::static_int_cast
< off_t
>(uOffset
);
1450 static sal_uInt64
const g_limit_ssize_t
= std::numeric_limits
< ssize_t
>::max();
1451 if (g_limit_ssize_t
< uBytesRequested
)
1452 return osl_File_E_OVERFLOW
;
1453 size_t const nBytesRequested
= sal::static_int_cast
< size_t >(uBytesRequested
);
1455 // read at specified fileptr
1456 FileHandle_Impl::Guard
lock (&(pImpl
->m_mutex
));
1457 return pImpl
->readFileAt (nOffset
, pBuffer
, nBytesRequested
, pBytesRead
);
1460 /*******************************************
1462 ********************************************/
1464 SAL_CALL
osl_writeFileAt (
1465 oslFileHandle Handle
,
1467 const void* pBuffer
,
1468 sal_uInt64 uBytesToWrite
,
1469 sal_uInt64
* pBytesWritten
)
1471 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1473 if ((0 == pImpl
) || (-1 == pImpl
->m_fd
) || (0 == pBuffer
) || (0 == pBytesWritten
))
1474 return osl_File_E_INVAL
;
1475 if (0 == (pImpl
->m_state
& FileHandle_Impl::STATE_SEEKABLE
))
1476 return osl_File_E_SPIPE
;
1477 if (0 == (pImpl
->m_state
& FileHandle_Impl::STATE_WRITEABLE
))
1478 return osl_File_E_BADF
;
1480 static sal_uInt64
const g_limit_off_t
= std::numeric_limits
< off_t
>::max();
1481 if (g_limit_off_t
< uOffset
)
1482 return osl_File_E_OVERFLOW
;
1483 off_t
const nOffset
= sal::static_int_cast
< off_t
>(uOffset
);
1485 static sal_uInt64
const g_limit_ssize_t
= std::numeric_limits
< ssize_t
>::max();
1486 if (g_limit_ssize_t
< uBytesToWrite
)
1487 return osl_File_E_OVERFLOW
;
1488 size_t const nBytesToWrite
= sal::static_int_cast
< size_t >(uBytesToWrite
);
1490 // write at specified fileptr
1491 FileHandle_Impl::Guard
lock (&(pImpl
->m_mutex
));
1492 return pImpl
->writeFileAt (nOffset
, pBuffer
, nBytesToWrite
, pBytesWritten
);
1495 /****************************************************************************/
1496 /* osl_isEndOfFile */
1497 /****************************************************************************/
1499 SAL_CALL
osl_isEndOfFile( oslFileHandle Handle
, sal_Bool
*pIsEOF
)
1501 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1503 if ((0 == pImpl
) || ((pImpl
->m_kind
== FileHandle_Impl::KIND_FD
) && (-1 == pImpl
->m_fd
)) || (0 == pIsEOF
))
1504 return osl_File_E_INVAL
;
1506 FileHandle_Impl::Guard
lock (&(pImpl
->m_mutex
));
1507 *pIsEOF
= (pImpl
->getPos() == pImpl
->getSize());
1508 return osl_File_E_None
;
1511 /************************************************
1513 ***********************************************/
1515 SAL_CALL
osl_getFilePos( oslFileHandle Handle
, sal_uInt64
* pPos
)
1517 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1519 if ((0 == pImpl
) || ((pImpl
->m_kind
== FileHandle_Impl::KIND_FD
) && (-1 == pImpl
->m_fd
)) || (0 == pPos
))
1520 return osl_File_E_INVAL
;
1522 FileHandle_Impl::Guard
lock (&(pImpl
->m_mutex
));
1523 *pPos
= pImpl
->getPos();
1524 return osl_File_E_None
;
1527 /*******************************************
1529 ********************************************/
1531 SAL_CALL
osl_setFilePos (oslFileHandle Handle
, sal_uInt32 uHow
, sal_Int64 uOffset
)
1533 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1535 if ((0 == pImpl
) || ((pImpl
->m_kind
== FileHandle_Impl::KIND_FD
) && (-1 == pImpl
->m_fd
)))
1536 return osl_File_E_INVAL
;
1538 static sal_Int64
const g_limit_off_t
= std::numeric_limits
< off_t
>::max();
1539 if (g_limit_off_t
< uOffset
)
1540 return osl_File_E_OVERFLOW
;
1541 off_t nPos
= 0, nOffset
= sal::static_int_cast
< off_t
>(uOffset
);
1543 FileHandle_Impl::Guard
lock (&(pImpl
->m_mutex
));
1546 case osl_Pos_Absolut
:
1548 return osl_File_E_INVAL
;
1551 case osl_Pos_Current
:
1552 nPos
= sal::static_int_cast
< off_t
>(pImpl
->getPos());
1553 if ((0 > nOffset
) && (-1*nOffset
> nPos
))
1554 return osl_File_E_INVAL
;
1555 if (g_limit_off_t
< nPos
+ nOffset
)
1556 return osl_File_E_OVERFLOW
;
1560 nPos
= sal::static_int_cast
< off_t
>(pImpl
->getSize());
1561 if ((0 > nOffset
) && (-1*nOffset
> nPos
))
1562 return osl_File_E_INVAL
;
1563 if (g_limit_off_t
< nPos
+ nOffset
)
1564 return osl_File_E_OVERFLOW
;
1568 return osl_File_E_INVAL
;
1571 return pImpl
->setPos (nPos
+ nOffset
);
1574 /****************************************************************************
1576 ****************************************************************************/
1578 SAL_CALL
osl_getFileSize( oslFileHandle Handle
, sal_uInt64
* pSize
)
1580 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1582 if ((0 == pImpl
) || ((pImpl
->m_kind
== FileHandle_Impl::KIND_FD
) && (-1 == pImpl
->m_fd
)) || (0 == pSize
))
1583 return osl_File_E_INVAL
;
1585 FileHandle_Impl::Guard
lock (&(pImpl
->m_mutex
));
1586 *pSize
= pImpl
->getSize();
1587 return osl_File_E_None
;
1590 /************************************************
1592 ***********************************************/
1594 SAL_CALL
osl_setFileSize( oslFileHandle Handle
, sal_uInt64 uSize
)
1596 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1598 if ((0 == pImpl
) || (-1 == pImpl
->m_fd
))
1599 return osl_File_E_INVAL
;
1600 if (0 == (pImpl
->m_state
& FileHandle_Impl::STATE_WRITEABLE
))
1601 return osl_File_E_BADF
;
1603 static sal_uInt64
const g_limit_off_t
= std::numeric_limits
< off_t
>::max();
1604 if (g_limit_off_t
< uSize
)
1605 return osl_File_E_OVERFLOW
;
1607 oslFileError result
= pImpl
->syncFile();
1608 if (result
!= osl_File_E_None
)
1610 pImpl
->m_bufptr
= -1, pImpl
->m_buflen
= 0;
1612 return pImpl
->setSize (uSize
);
1615 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */