1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
21 #include <o3tl/safeint.hxx>
22 #include <o3tl/string_view.hxx>
23 #include <o3tl/typed_flags_set.hxx>
24 #include <sal/log.hxx>
25 #include <osl/diagnose.h>
26 #include <osl/file.hxx>
27 #include <osl/detail/file.h>
28 #include <rtl/alloc.h>
29 #include <rtl/byteseq.hxx>
30 #include <rtl/string.hxx>
33 #include "createfilehandlefromfd.hxx"
34 #include "file_error_transl.hxx"
35 #include "file_impl.hxx"
36 #include "file_url.hxx"
37 #include "uunxapi.hxx"
38 #include "unixerrnostring.hxx"
52 #include <sys/param.h>
53 #include <sys/mount.h>
56 #include <CoreFoundation/CoreFoundation.h>
61 #include <osl/detail/android-bootstrap.h>
62 #include <android/log.h>
63 #include <android/asset_manager.h>
70 Seekable
= 1, /*< default */
71 Readable
= 2, /*< default */
72 Writeable
= 4, /*< open() sets, write() requires, else osl_File_E_BADF */
73 Modified
= 8 /*< write() sets, flush() resets */
78 template<> struct o3tl::typed_flags
<State
>: o3tl::is_typed_flags
<State
, 15> {};
82 struct FileHandle_Impl
84 pthread_mutex_t m_mutex
;
85 OString m_strFilePath
; /*< holds native file path */
98 sal_uInt64 m_size
; /*< file size */
99 off_t m_offset
; /*< physical offset from begin of file */
100 // m_fileptr is hit hard in some situations, where the overhead of a mutex starts to show up, so use an atomic
101 std::atomic
<off_t
> m_fileptr
; /*< logical offset from begin of file */
103 off_t m_bufptr
; /*< buffer offset from begin of file */
104 size_t m_buflen
; /*< buffer filled [0, m_bufsiz - 1] */
107 sal_uInt8
* m_buffer
;
109 rtl_String
* m_memstreambuf
; /*< used for in-memory streams */
112 explicit FileHandle_Impl(int fd
, Kind kind
= KIND_FD
, OString path
= "<anon>");
115 static size_t getpagesize();
117 sal_uInt64
getPos() const;
118 void setPos(sal_uInt64 uPos
);
120 sal_uInt64
getSize() const;
121 oslFileError
setSize(sal_uInt64 uSize
);
126 size_t nBytesRequested
,
127 sal_uInt64
* pBytesRead
);
129 oslFileError
writeAt(
132 size_t nBytesToWrite
,
133 sal_uInt64
* pBytesWritten
);
135 oslFileError
readFileAt(
138 size_t nBytesRequested
,
139 sal_uInt64
* pBytesRead
);
141 oslFileError
writeFileAt(
144 size_t nBytesToWrite
,
145 sal_uInt64
* pBytesWritten
);
147 oslFileError
readLineAt(
149 sal_Sequence
** ppSequence
,
150 sal_uInt64
* pBytesRead
);
152 static oslFileError
writeSequence_Impl(
153 sal_Sequence
** ppSequence
,
158 oslFileError
syncFile();
162 pthread_mutex_t
*m_mutex
;
165 explicit Guard(pthread_mutex_t
*pMutex
);
172 FileHandle_Impl::Guard::Guard(pthread_mutex_t
* pMutex
)
176 (void) pthread_mutex_lock(m_mutex
); // ignoring EINVAL if a null mutex is passed ...
179 FileHandle_Impl::Guard::~Guard()
182 (void) pthread_mutex_unlock(m_mutex
);
185 FileHandle_Impl::FileHandle_Impl(int fd
, enum Kind kind
, OString path
)
186 : m_strFilePath(std::move(path
)),
189 m_state (State::Seekable
| State::Readable
),
198 (void) pthread_mutex_init(&m_mutex
, nullptr);
199 if (m_kind
== KIND_FD
)
201 size_t const pagesize
= getpagesize();
202 if (pagesize
!= size_t(-1))
205 m_buffer
= static_cast<sal_uInt8
*>(calloc(1, m_bufsiz
));
210 FileHandle_Impl::~FileHandle_Impl()
212 if (m_kind
== KIND_FD
)
218 (void) pthread_mutex_destroy(&m_mutex
); // ignoring EBUSY ...
221 size_t FileHandle_Impl::getpagesize()
223 return sal::static_int_cast
< size_t >(::sysconf(_SC_PAGESIZE
));
226 sal_uInt64
FileHandle_Impl::getPos() const
228 return sal::static_int_cast
< sal_uInt64
>(m_fileptr
.load());
231 void FileHandle_Impl::setPos(sal_uInt64 uPos
)
233 m_fileptr
= sal::static_int_cast
< off_t
>(uPos
);
236 sal_uInt64
FileHandle_Impl::getSize() const
238 off_t
const bufend
= std::max(off_t(0), m_bufptr
) + m_buflen
;
239 return std::max(m_size
, sal::static_int_cast
< sal_uInt64
>(bufend
));
242 oslFileError
FileHandle_Impl::setSize(sal_uInt64 uSize
)
244 off_t
const nSize
= sal::static_int_cast
< off_t
>(uSize
);
245 if (ftruncate_with_name(m_fd
, nSize
, m_strFilePath
) == -1)
247 /* Failure. Save original result. Try fallback algorithm */
248 oslFileError result
= oslTranslateFileError(errno
);
250 /* Check against current size. Fail upon 'shrink' */
251 if (uSize
<= getSize())
253 /* Failure upon 'shrink'. Return original result */
257 /* Save current position */
258 off_t
const nCurPos
= lseek(m_fd
, off_t(0), SEEK_CUR
);
259 if (nCurPos
== off_t(-1))
262 SAL_INFO("sal.file", "lseek(" << m_fd
<< ",0,SEEK_CUR): " << UnixErrnoString(e
));
266 SAL_INFO("sal.file", "lseek(" << m_fd
<< ",0,SEEK_CUR): OK");
268 /* Try 'expand' via 'lseek()' and 'write()' */
269 if (lseek(m_fd
, static_cast<off_t
>(nSize
- 1), SEEK_SET
) == -1)
272 SAL_INFO("sal.file", "lseek(" << m_fd
<< "," << nSize
- 1 << ",SEEK_SET): " << UnixErrnoString(e
));
276 SAL_INFO("sal.file", "lseek(" << m_fd
<< "," << nSize
- 1 << ",SEEK_SET): OK");
278 if (write(m_fd
, "", size_t(1)) == -1)
280 /* Failure. Restore saved position */
282 SAL_INFO("sal.file", "write(" << m_fd
<< ",\"\",1): " << UnixErrnoString(e
));
283 (void) lseek(m_fd
, nCurPos
, SEEK_SET
);
287 SAL_INFO("sal.file", "write(" << m_fd
<< ",\"\",1): OK");
289 /* Success. Restore saved position */
290 if (lseek(m_fd
, nCurPos
, SEEK_SET
) == -1)
294 m_size
= sal::static_int_cast
< sal_uInt64
>(nSize
);
295 return osl_File_E_None
;
298 oslFileError
FileHandle_Impl::readAt(
301 size_t nBytesRequested
,
302 sal_uInt64
* pBytesRead
)
304 SAL_WARN_IF(!(m_state
& State::Seekable
), "sal.osl", "FileHandle_Impl::readAt(): not seekable");
305 if (!(m_state
& State::Seekable
))
306 return osl_File_E_SPIPE
;
308 SAL_WARN_IF(!(m_state
& State::Readable
), "sal.osl", "FileHandle_Impl::readAt(): not readable");
309 if (!(m_state
& State::Readable
))
310 return osl_File_E_BADF
;
312 if (m_kind
== KIND_MEM
)
318 if (o3tl::make_unsigned(m_offset
) >= m_size
)
324 nBytes
= std::min(nBytesRequested
, static_cast<size_t>(m_size
- m_offset
));
325 memmove(pBuffer
, m_buffer
+ m_offset
, nBytes
);
328 *pBytesRead
= nBytes
;
329 return osl_File_E_None
;
332 ssize_t nBytes
= ::pread(m_fd
, pBuffer
, nBytesRequested
, nOffset
);
333 if ((nBytes
== -1) && (errno
== EOVERFLOW
))
335 /* Some 'pread()'s fail with EOVERFLOW when reading at (or past)
336 * end-of-file, different from 'lseek() + read()' behaviour.
337 * Returning '0 bytes read' and 'osl_File_E_None' instead.
343 return oslTranslateFileError(errno
);
345 *pBytesRead
= nBytes
;
347 return osl_File_E_None
;
350 oslFileError
FileHandle_Impl::writeAt(
352 void const * pBuffer
,
353 size_t nBytesToWrite
,
354 sal_uInt64
* pBytesWritten
)
356 SAL_WARN_IF(!(m_state
& State::Seekable
), "sal.osl", "FileHandle_Impl::writeAt(): not seekable");
357 if (!(m_state
& State::Seekable
))
358 return osl_File_E_SPIPE
;
360 SAL_WARN_IF(!(m_state
& State::Writeable
), "sal.osl", "FileHandle_Impl::writeAt(): not writeable");
361 if (!(m_state
& State::Writeable
))
362 return osl_File_E_BADF
;
364 ssize_t nBytes
= ::pwrite(m_fd
, pBuffer
, nBytesToWrite
, nOffset
);
366 return oslTranslateFileError(errno
);
368 m_size
= std::max(m_size
, sal::static_int_cast
< sal_uInt64
>(nOffset
+ nBytes
));
370 *pBytesWritten
= nBytes
;
372 return osl_File_E_None
;
375 oslFileError
FileHandle_Impl::readFileAt(
378 size_t nBytesRequested
,
379 sal_uInt64
* pBytesRead
)
381 if (!(m_state
& State::Seekable
))
383 // not seekable (pipe)
384 ssize_t nBytes
= ::read(m_fd
, pBuffer
, nBytesRequested
);
386 return oslTranslateFileError(errno
);
388 *pBytesRead
= nBytes
;
390 return osl_File_E_None
;
393 if (m_kind
== KIND_MEM
|| !m_buffer
)
396 return readAt(nOffset
, pBuffer
, nBytesRequested
, pBytesRead
);
399 sal_uInt8
*buffer
= static_cast<sal_uInt8
*>(pBuffer
);
400 for (*pBytesRead
= 0; nBytesRequested
> 0; )
402 off_t
const bufptr
= (nOffset
/ m_bufsiz
) * m_bufsiz
;
403 size_t const bufpos
= nOffset
% m_bufsiz
;
405 if (bufptr
!= m_bufptr
)
407 // flush current buffer
408 oslFileError result
= syncFile();
409 if (result
!= osl_File_E_None
)
415 if (nBytesRequested
>= m_bufsiz
)
417 // buffer too small, read through from file
418 sal_uInt64 uDone
= 0;
419 result
= readAt(nOffset
, &(buffer
[*pBytesRead
]), nBytesRequested
, &uDone
);
420 if (result
!= osl_File_E_None
)
423 *pBytesRead
+= uDone
;
425 return osl_File_E_None
;
428 // update buffer (pointer)
429 sal_uInt64 uDone
= 0;
430 result
= readAt(bufptr
, m_buffer
, m_bufsiz
, &uDone
);
431 if (result
!= osl_File_E_None
)
438 if (bufpos
>= m_buflen
)
441 return osl_File_E_None
;
444 size_t const bytes
= std::min(m_buflen
- bufpos
, nBytesRequested
);
445 SAL_INFO("sal.fileio", "FileHandle_Impl::readFileAt(" << m_fd
<< ", " << nOffset
<< ", " << bytes
<< ")");
447 memcpy(&(buffer
[*pBytesRead
]), &(m_buffer
[bufpos
]), bytes
);
448 nBytesRequested
-= bytes
;
449 *pBytesRead
+= bytes
;
453 return osl_File_E_None
;
456 oslFileError
FileHandle_Impl::writeFileAt(
458 void const * pBuffer
,
459 size_t nBytesToWrite
,
460 sal_uInt64
* pBytesWritten
)
462 if (!(m_state
& State::Seekable
))
464 // not seekable (pipe)
465 ssize_t nBytes
= ::write(m_fd
, pBuffer
, nBytesToWrite
);
467 return oslTranslateFileError(errno
);
469 *pBytesWritten
= nBytes
;
471 return osl_File_E_None
;
476 return writeAt(nOffset
, pBuffer
, nBytesToWrite
, pBytesWritten
);
479 sal_uInt8
const * buffer
= static_cast<sal_uInt8
const *>(pBuffer
);
480 for (*pBytesWritten
= 0; nBytesToWrite
> 0;)
482 off_t
const bufptr
= (nOffset
/ m_bufsiz
) * m_bufsiz
;
483 size_t const bufpos
= nOffset
% m_bufsiz
;
484 if (bufptr
!= m_bufptr
)
486 // flush current buffer
487 oslFileError result
= syncFile();
488 if (result
!= osl_File_E_None
)
493 if (nBytesToWrite
>= m_bufsiz
)
495 // buffer too small, write through to file
496 sal_uInt64 uDone
= 0;
497 result
= writeAt(nOffset
, &(buffer
[*pBytesWritten
]), nBytesToWrite
, &uDone
);
498 if (result
!= osl_File_E_None
)
501 if (uDone
!= nBytesToWrite
)
502 return osl_File_E_IO
;
504 *pBytesWritten
+= uDone
;
506 return osl_File_E_None
;
509 // update buffer (pointer)
510 sal_uInt64 uDone
= 0;
511 result
= readAt(bufptr
, m_buffer
, m_bufsiz
, &uDone
);
512 if (result
!= osl_File_E_None
)
519 size_t const bytes
= std::min(m_bufsiz
- bufpos
, nBytesToWrite
);
520 SAL_INFO("sal.fileio", "FileHandle_Impl::writeFileAt(" << m_fd
<< ", " << nOffset
<< ", " << bytes
<< ")");
522 memcpy(&(m_buffer
[bufpos
]), &(buffer
[*pBytesWritten
]), bytes
);
523 nBytesToWrite
-= bytes
;
524 *pBytesWritten
+= bytes
;
527 m_buflen
= std::max(m_buflen
, bufpos
+ bytes
);
528 m_state
|= State::Modified
;
531 return osl_File_E_None
;
534 oslFileError
FileHandle_Impl::readLineAt(
536 sal_Sequence
** ppSequence
,
537 sal_uInt64
* pBytesRead
)
539 oslFileError result
= osl_File_E_None
;
541 off_t bufptr
= nOffset
/ m_bufsiz
* m_bufsiz
;
542 if (bufptr
!= m_bufptr
)
544 /* flush current buffer */
546 if (result
!= osl_File_E_None
)
549 /* update buffer (pointer) */
550 sal_uInt64 uDone
= 0;
551 result
= readAt(bufptr
, m_buffer
, m_bufsiz
, &uDone
);
552 if (result
!= osl_File_E_None
)
559 static int const LINE_STATE_BEGIN
= 0;
560 static int const LINE_STATE_CR
= 1;
561 static int const LINE_STATE_LF
= 2;
563 size_t bufpos
= nOffset
- m_bufptr
, curpos
= bufpos
, dstpos
= 0;
564 int state
= (bufpos
>= m_buflen
) ? LINE_STATE_LF
: LINE_STATE_BEGIN
;
566 while (state
!= LINE_STATE_LF
)
568 if (curpos
>= m_buflen
)
570 /* buffer examined */
571 if ((curpos
- bufpos
) > 0)
573 /* flush buffer to sequence */
574 result
= writeSequence_Impl(
575 ppSequence
, &dstpos
, &(m_buffer
[bufpos
]), curpos
- bufpos
);
576 if (result
!= osl_File_E_None
)
579 *pBytesRead
+= curpos
- bufpos
;
580 nOffset
+= curpos
- bufpos
;
583 bufptr
= nOffset
/ m_bufsiz
* m_bufsiz
;
584 if (bufptr
!= m_bufptr
)
586 /* update buffer (pointer) */
587 sal_uInt64 uDone
= 0;
588 result
= readAt(bufptr
, m_buffer
, m_bufsiz
, &uDone
);
589 if (result
!= osl_File_E_None
)
596 bufpos
= nOffset
- m_bufptr
;
598 if (bufpos
>= m_buflen
)
605 state
= LINE_STATE_LF
;
606 switch (m_buffer
[curpos
])
608 case 0x0A: /* CRLF */
609 /* eat current char */
612 default: /* single CR */
613 /* keep current char */
618 /* determine next state */
619 switch (m_buffer
[curpos
])
621 case 0x0A: /* single LF */
622 state
= LINE_STATE_LF
;
625 state
= LINE_STATE_CR
;
627 default: /* advance to next char */
631 if (state
!= LINE_STATE_BEGIN
)
633 /* skip the newline char */
636 /* flush buffer to sequence */
637 result
= writeSequence_Impl(
638 ppSequence
, &dstpos
, &(m_buffer
[bufpos
]), curpos
- bufpos
- 1);
639 if (result
!= osl_File_E_None
)
642 *pBytesRead
+= curpos
- bufpos
;
643 nOffset
+= curpos
- bufpos
;
649 result
= writeSequence_Impl(ppSequence
, &dstpos
, nullptr, 0);
650 if (result
!= osl_File_E_None
)
654 return osl_File_E_None
;
656 if (bufpos
>= m_buflen
)
657 return osl_File_E_AGAIN
;
659 return osl_File_E_None
;
662 oslFileError
FileHandle_Impl::writeSequence_Impl(
663 sal_Sequence
** ppSequence
,
665 const void * pBuffer
,
668 sal_Int32 nElements
= *pnOffset
+ nBytes
;
671 /* construct sequence */
672 rtl_byte_sequence_constructNoDefault(ppSequence
, nElements
);
674 else if (nElements
!= (*ppSequence
)->nElements
)
676 /* resize sequence */
677 rtl_byte_sequence_realloc(ppSequence
, nElements
);
680 if (*ppSequence
&& nBytes
!= 0)
683 memcpy(&((*ppSequence
)->elements
[*pnOffset
]), pBuffer
, nBytes
);
687 return (*ppSequence
) ? osl_File_E_None
: osl_File_E_NOMEM
;
690 oslFileError
FileHandle_Impl::syncFile()
692 oslFileError result
= osl_File_E_None
;
693 if (m_state
& State::Modified
)
695 sal_uInt64 uDone
= 0;
696 result
= writeAt(m_bufptr
, m_buffer
, m_buflen
, &uDone
);
697 if (result
!= osl_File_E_None
)
700 if (uDone
!= m_buflen
)
701 return osl_File_E_IO
;
703 m_state
&= ~State::Modified
;
709 oslFileHandle
osl::detail::createFileHandleFromFD(int fd
)
712 return nullptr; // EINVAL
714 struct stat aFileStat
;
715 if (fstat(fd
, &aFileStat
) == -1)
716 return nullptr; // EBADF
718 FileHandle_Impl
*pImpl
= new FileHandle_Impl(fd
);
721 pImpl
->m_state
|= State::Writeable
;
722 if (!S_ISREG(aFileStat
.st_mode
))
724 /* not a regular file, mark not seekable */
725 pImpl
->m_state
&= ~State::Seekable
;
729 /* regular file, init current size */
730 pImpl
->m_size
= sal::static_int_cast
< sal_uInt64
>(aFileStat
.st_size
);
733 SAL_INFO("sal.file", "osl::detail::createFileHandleFromFD(" << pImpl
->m_fd
<< ", writeable) => " << pImpl
->m_strFilePath
);
735 return static_cast<oslFileHandle
>(pImpl
);
738 static int osl_file_adjustLockFlags(const OString
& path
, int flags
)
742 * The AFP implementation of MacOS X 10.4 treats O_EXLOCK in a way
743 * that makes it impossible for OOo to create a backup copy of the
744 * file it keeps opened. OTOH O_SHLOCK for AFP behaves as desired by
745 * the OOo file handling, so we need to check the path of the file
746 * for the filesystem name.
749 if(statfs(path
.getStr(), &s
) >= 0)
751 if(strncmp("afpfs", s
.f_fstypename
, 5) == 0)
758 /* Needed flags to allow opening a webdav file */
759 flags
&= ~(O_EXLOCK
| O_SHLOCK
| O_NONBLOCK
);
769 static bool osl_file_queryLocking(sal_uInt32 uFlags
)
771 #if !defined HAVE_O_EXLOCK
772 if (!(uFlags
& osl_File_OpenFlag_NoLock
)
773 && ((uFlags
& osl_File_OpenFlag_Write
)
774 || (uFlags
& osl_File_OpenFlag_Create
)))
776 static bool enabled
= getenv("SAL_ENABLE_FILE_LOCKING") != nullptr;
777 // getenv is not thread safe, so minimize use of result
787 #define OPEN_WRITE_FLAGS ( O_RDWR | O_EXLOCK | O_NONBLOCK )
788 #define OPEN_CREATE_FLAGS ( O_CREAT | O_RDWR | O_EXLOCK | O_NONBLOCK )
790 #define OPEN_WRITE_FLAGS ( O_RDWR )
791 #define OPEN_CREATE_FLAGS ( O_CREAT | O_RDWR )
798 static oslFileError
openMemoryAsFile(const OString
&rData
,
799 oslFileHandle
*pHandle
,
802 const char *address
= rData
.getStr();
803 size_t size
= rData
.getLength();
805 FileHandle_Impl
*pImpl
= new FileHandle_Impl(-1, FileHandle_Impl::KIND_MEM
, path
);
806 pImpl
->m_size
= sal::static_int_cast
< sal_uInt64
>(size
);
808 *pHandle
= (oslFileHandle
)(pImpl
);
811 pImpl
->m_buflen
= size
;
812 pImpl
->m_memstreambuf
= rData
.pData
;
813 rtl_string_acquire(pImpl
->m_memstreambuf
);
815 pImpl
->m_bufsiz
= size
;
816 pImpl
->m_buffer
= reinterpret_cast<sal_uInt8
*>(const_cast<char *>(address
));
818 return osl_File_E_None
;
822 * Reading files from /assets/ on Android via a transition into the VM
823 * shows on profiles and is rather slow; so we cache small files as
824 * used by UNO, UI-builder etc.
826 class AndroidFileCache
{
832 AndroidFileCache(size_t nElements
)
835 maEntries
.resize(nElements
);
836 assert (maEntries
.size() == nElements
);
838 Entry
*find(const char *cpFilePath
)
840 for (auto &it
: maEntries
)
842 if (!strcmp(it
.maFilePath
.getStr(), cpFilePath
))
847 // no clever LRU - but - good enough for now.
848 void insert(const char *cpFilePath
, OString
&rData
)
850 assert (maEntries
.size() > 0);
851 if (++mnCur
>= maEntries
.size())
853 maEntries
[mnCur
].maFilePath
= OString(cpFilePath
, strlen(cpFilePath
));
854 maEntries
[mnCur
].maData
= rData
;
856 static AndroidFileCache
&getHitCache()
858 static AndroidFileCache
*pCache
= new AndroidFileCache(16);
861 static AndroidFileCache
&getMissCache()
863 static AndroidFileCache
*pCache
= new AndroidFileCache(32);
868 std::vector
<Entry
> maEntries
;
875 oslFileError
openFilePath(const OString
& filePath
, oslFileHandle
* pHandle
,
876 sal_uInt32 uFlags
, mode_t mode
)
881 /* Opening a file from /assets read-only means
882 * we should mmap it from the .apk file
884 if (o3tl::starts_with(filePath
, "/assets/"))
889 const char *cpAssetsPath
= filePath
.getStr() + sizeof("/assets/") - 1;
890 // some requests are /assets//foo...
891 if (cpAssetsPath
[0] == '/')
893 __android_log_print(ANDROID_LOG_DEBUG
,"libo:sal/osl/unx/file", "double-slash in path: %s", filePath
.getStr());
897 AndroidFileCache::Entry
*pHit
= AndroidFileCache::getHitCache().find(cpAssetsPath
);
899 aData
= pHit
->maData
;
904 AndroidFileCache::Entry
*pMiss
= AndroidFileCache::getMissCache().find(cpAssetsPath
);
908 __android_log_print(ANDROID_LOG_ERROR
,"libo:sal/osl/unx/file", "miss cache: failed to open %s", filePath
.getStr());
909 return osl_File_E_NOENT
;
911 AAssetManager
* mgr
= lo_get_native_assetmgr();
912 AAsset
* asset
= AAssetManager_open(mgr
, cpAssetsPath
, AASSET_MODE_BUFFER
);
915 AndroidFileCache::getMissCache().insert(cpAssetsPath
, aData
);
917 __android_log_print(ANDROID_LOG_ERROR
,"libo:sal/osl/unx/file", "failed to open %s", filePath
.getStr());
918 return osl_File_E_NOENT
;
922 rtl_String
*pData
= nullptr;
923 size_t size
= AAsset_getLength(asset
);
924 rtl_string_new_WithLength(&pData
, size
);
925 pData
->length
= size
;
926 AAsset_read(asset
, pData
->buffer
, size
);
929 aData
= OString(pData
, SAL_NO_ACQUIRE
);
931 if (pData
->length
< 50 * 1024)
932 AndroidFileCache::getHitCache().insert(cpAssetsPath
, aData
);
936 if (uFlags
& osl_File_OpenFlag_Write
)
938 // It seems to work better to silently "open" it read-only
939 // and let write attempts, if any, fail later. Otherwise
940 // loading a document from /assets fails with that idiotic
941 // "General Error" dialog...
943 SAL_INFO("sal.file", "osl_openFile(" << filePath
<< ") => '" << cpAssetsPath
<< "'"
944 << aData
.getLength() << " bytes from file " << (bCache
? "cache" : "system"));
945 return openMemoryAsFile(aData
, pHandle
, filePath
);
949 /* set mode and flags */
950 int defmode
= (uFlags
& osl_File_OpenFlag_Private
) ? S_IRUSR
: S_IRUSR
| S_IRGRP
| S_IROTH
;
951 int flags
= O_RDONLY
;
953 if (uFlags
& osl_File_OpenFlag_Write
)
955 defmode
|= (uFlags
& osl_File_OpenFlag_Private
) ? S_IWUSR
: S_IWUSR
| S_IWGRP
| S_IWOTH
;
956 flags
= OPEN_WRITE_FLAGS
;
959 if (uFlags
& osl_File_OpenFlag_Create
)
961 defmode
|= (uFlags
& osl_File_OpenFlag_Private
) ? S_IWUSR
: S_IWUSR
| S_IWGRP
| S_IWOTH
;
962 flags
= OPEN_CREATE_FLAGS
;
965 if (mode
== mode_t(-1))
968 /* Check for flags passed in from SvFileStream::Open() */
969 if (uFlags
& osl_File_OpenFlag_Trunc
)
972 if (!(uFlags
& osl_File_OpenFlag_NoExcl
))
975 if (uFlags
& osl_File_OpenFlag_NoLock
)
978 flags
&= ~(O_EXLOCK
| O_SHLOCK
| O_NONBLOCK
);
979 #endif /* HAVE_O_EXLOCK */
983 flags
= osl_file_adjustLockFlags (filePath
, flags
);
986 // O_EXCL can be set only when O_CREAT is set
987 if (flags
& O_EXCL
&& !(flags
& O_CREAT
))
991 int fd
= open_c( filePath
, flags
, mode
);
994 return oslTranslateFileError(errno
);
997 #if !HAVE_FEATURE_MACOSX_SANDBOX
998 /* reset O_NONBLOCK flag */
999 if (flags
& O_NONBLOCK
)
1001 int f
= fcntl(fd
, F_GETFL
, 0);
1005 SAL_INFO("sal.file", "fcntl(" << fd
<< ",F_GETFL,0): " << UnixErrnoString(e
));
1006 eRet
= oslTranslateFileError(e
);
1008 SAL_INFO("sal.file", "close(" << fd
<< ")");
1012 SAL_INFO("sal.file", "fcntl(" << fd
<< ",F_GETFL,0): OK");
1014 if (fcntl(fd
, F_SETFL
, (f
& ~O_NONBLOCK
)) == -1)
1017 SAL_INFO("sal.file", "fcntl(" << fd
<< ",F_SETFL,(f & ~O_NONBLOCK)): " << UnixErrnoString(e
));
1018 eRet
= oslTranslateFileError(e
);
1020 SAL_INFO("sal.file", "close(" << fd
<< ")");
1024 SAL_INFO("sal.file", "fcntl(" << fd
<< ",F_SETFL,(f & ~O_NONBLOCK)): OK");
1028 /* get file status (mode, size) */
1029 struct stat aFileStat
;
1030 if (fstat(fd
, &aFileStat
) == -1)
1033 SAL_INFO("sal.file", "fstat(" << fd
<< "): " << UnixErrnoString(e
));
1034 eRet
= oslTranslateFileError(e
);
1036 SAL_INFO("sal.file", "close(" << fd
<< ")");
1040 SAL_INFO("sal.file", "fstat(" << fd
<< "): OK");
1042 if (!S_ISREG(aFileStat
.st_mode
))
1044 /* we only open regular files here */
1045 SAL_INFO("sal.file", "osl_openFile(" << filePath
<< "): not a regular file");
1047 SAL_INFO("sal.file", "close(" << fd
<< ")");
1048 return osl_File_E_INVAL
;
1051 if (osl_file_queryLocking(uFlags
))
1054 if (flock(fd
, LOCK_EX
| LOCK_NB
) == -1)
1057 SAL_INFO("sal.file", "flock(" << fd
<< ",LOCK_EX|LOCK_NB): " << UnixErrnoString(e
));
1058 /* Mac OSX returns ENOTSUP for webdav drives. We should try read lock */
1060 // Restore errno after possibly having been overwritten by the SAL_INFO above...
1062 if ((errno
!= ENOTSUP
) || ((flock(fd
, LOCK_SH
| LOCK_NB
) == 1) && (errno
!= ENOTSUP
)))
1064 eRet
= oslTranslateFileError(errno
);
1066 SAL_INFO("sal.file", "close(" << fd
<< ")");
1071 SAL_INFO("sal.file", "flock(" << fd
<< ",LOCK_EX|LOCK_NB): OK");
1073 struct flock aflock
;
1075 aflock
.l_type
= F_WRLCK
;
1076 aflock
.l_whence
= SEEK_SET
;
1080 if (fcntl(fd
, F_SETLK
, &aflock
) == -1)
1083 SAL_INFO("sal.file", "fcntl(" << fd
<< ",F_SETLK): " << UnixErrnoString(e
));
1084 eRet
= oslTranslateFileError(e
);
1086 SAL_INFO("sal.file", "close(" << fd
<< ")");
1089 #endif /* F_SETLK */
1092 /* allocate memory for impl structure */
1093 FileHandle_Impl
*pImpl
= new FileHandle_Impl(fd
, FileHandle_Impl::KIND_FD
, filePath
);
1095 pImpl
->m_state
|= State::Writeable
;
1097 pImpl
->m_size
= sal::static_int_cast
< sal_uInt64
>(aFileStat
.st_size
);
1099 *pHandle
= static_cast<oslFileHandle
>(pImpl
);
1101 return osl_File_E_None
;
1104 oslFileError SAL_CALL
osl_openFile(rtl_uString
* ustrFileURL
, oslFileHandle
* pHandle
, sal_uInt32 uFlags
)
1106 return openFile(ustrFileURL
, pHandle
, uFlags
, mode_t(-1));
1109 oslFileError
openFile(rtl_uString
* ustrFileURL
, oslFileHandle
* pHandle
, sal_uInt32 uFlags
, mode_t mode
)
1113 if ((!ustrFileURL
) || (ustrFileURL
->length
== 0) || (!pHandle
))
1114 return osl_File_E_INVAL
;
1116 /* convert file URL to system path */
1117 char buffer
[PATH_MAX
];
1118 eRet
= FileURLToPath(buffer
, sizeof(buffer
), ustrFileURL
);
1119 if (eRet
!= osl_File_E_None
)
1123 if (macxp_resolveAlias(buffer
, sizeof(buffer
)) != 0)
1124 return oslTranslateFileError(errno
);
1127 return openFilePath(buffer
, pHandle
, uFlags
, mode
);
1130 oslFileError SAL_CALL
osl_closeFile(oslFileHandle Handle
)
1132 FileHandle_Impl
* pImpl
= static_cast< FileHandle_Impl
* >(Handle
);
1135 return osl_File_E_INVAL
;
1137 if (pImpl
->m_kind
== FileHandle_Impl::KIND_MEM
)
1140 rtl_string_release(pImpl
->m_memstreambuf
);
1141 pImpl
->m_memstreambuf
= nullptr;
1143 pImpl
->m_buffer
= NULL
;
1146 return osl_File_E_None
;
1149 if (pImpl
->m_fd
< 0)
1150 return osl_File_E_INVAL
;
1152 (void) pthread_mutex_lock(&(pImpl
->m_mutex
));
1154 /* close(2) implicitly (and unconditionally) unlocks */
1155 oslFileError result
= pImpl
->syncFile();
1156 if (result
!= osl_File_E_None
)
1158 /* close, ignoring double failure */
1159 (void) close(pImpl
->m_fd
);
1160 SAL_INFO("sal.file", "close(" << pImpl
->m_fd
<< ")");
1162 else if (close(pImpl
->m_fd
) == -1)
1165 SAL_INFO("sal.file", "close(" << pImpl
->m_fd
<< "): " << UnixErrnoString(e
));
1166 /* translate error code */
1167 result
= oslTranslateFileError(e
);
1170 SAL_INFO("sal.file", "close(" << pImpl
->m_fd
<< "): OK");
1172 (void) pthread_mutex_unlock(&(pImpl
->m_mutex
));
1177 oslFileError SAL_CALL
osl_syncFile(oslFileHandle Handle
)
1179 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1181 if ((!pImpl
) || ((pImpl
->m_kind
== FileHandle_Impl::KIND_FD
) && (pImpl
->m_fd
== -1)))
1182 return osl_File_E_INVAL
;
1184 if (pImpl
->m_kind
== FileHandle_Impl::KIND_MEM
)
1185 return osl_File_E_None
;
1187 FileHandle_Impl::Guard
lock(&(pImpl
->m_mutex
));
1189 oslFileError result
= pImpl
->syncFile();
1191 if (result
!= osl_File_E_None
)
1194 if (fsync(pImpl
->m_fd
) == -1)
1197 SAL_INFO("sal.file", "fsync(" << pImpl
->m_fd
<< "): " << UnixErrnoString(e
));
1198 return oslTranslateFileError(e
);
1201 SAL_INFO("sal.file", "fsync(" << pImpl
->m_fd
<< "): OK");
1203 return osl_File_E_None
;
1206 const off_t MAX_OFF_T
= std::numeric_limits
< off_t
>::max();
1210 // coverity[result_independent_of_operands] - crossplatform requirement
1211 template<typename T
> bool exceedsMaxOffT(T n
) { return n
> MAX_OFF_T
; }
1213 // coverity[result_independent_of_operands] - crossplatform requirement
1214 template<typename T
> bool exceedsMinOffT(T n
)
1215 { return n
< std::numeric_limits
<off_t
>::min(); }
1219 oslFileError SAL_CALL
osl_mapFile(
1220 oslFileHandle Handle
,
1227 FileHandle_Impl
* pImpl
= static_cast< FileHandle_Impl
* >(Handle
);
1229 if ((!pImpl
) || ((pImpl
->m_kind
== FileHandle_Impl::KIND_FD
) && (pImpl
->m_fd
== -1)) || (!ppAddr
))
1230 return osl_File_E_INVAL
;
1234 if (uLength
> SAL_MAX_SIZE
)
1235 return osl_File_E_OVERFLOW
;
1237 size_t const nLength
= sal::static_int_cast
< size_t >(uLength
);
1239 if (exceedsMaxOffT(uOffset
))
1240 return osl_File_E_OVERFLOW
;
1242 if (pImpl
->m_kind
== FileHandle_Impl::KIND_MEM
)
1244 *ppAddr
= pImpl
->m_buffer
+ uOffset
;
1245 return osl_File_E_None
;
1248 off_t
const nOffset
= sal::static_int_cast
< off_t
>(uOffset
);
1250 void* p
= mmap(nullptr, nLength
, PROT_READ
, MAP_SHARED
, pImpl
->m_fd
, nOffset
);
1252 if (p
== MAP_FAILED
)
1253 return oslTranslateFileError(errno
);
1257 if (uFlags
& osl_File_MapFlag_RandomAccess
)
1259 // Determine memory pagesize.
1260 size_t const nPageSize
= FileHandle_Impl::getpagesize();
1261 if (nPageSize
!= size_t(-1))
1264 * Pagein, touching first byte of every memory page.
1265 * Note: volatile disables optimizing the loop away.
1267 sal_uInt8
volatile *pData(static_cast<sal_uInt8
*>(*ppAddr
));
1268 size_t nSize(nLength
);
1270 while (nSize
> nPageSize
)
1282 if (uFlags
& osl_File_MapFlag_WillNeed
)
1284 // On Linux, madvise(..., MADV_WILLNEED) appears to have the undesirable
1285 // effect of not returning until the data has actually been paged in, so
1286 // that its net effect would typically be to slow down the process
1287 // (which could start processing at the beginning of the data while the
1288 // OS simultaneously pages in the rest); on other platforms, it remains
1289 // to be evaluated whether madvise or equivalent is available and
1291 #if defined MACOSX || (defined(__sun) && (!defined(__XOPEN_OR_POSIX) || defined(_XPG6) || defined(__EXTENSIONS__)))
1292 int e
= posix_madvise(p
, nLength
, POSIX_MADV_WILLNEED
);
1294 SAL_INFO("sal.file", "posix_madvise(..., POSIX_MADV_WILLNEED) failed with " << e
);
1297 if (madvise(static_cast< caddr_t
>(p
), nLength
, MADV_WILLNEED
) != 0)
1298 SAL_INFO("sal.file", "madvise(..., MADV_WILLNEED) failed with " << UnixErrnoString(errno
));
1302 return osl_File_E_None
;
1305 static oslFileError
unmapFile(void* pAddr
, sal_uInt64 uLength
)
1308 return osl_File_E_INVAL
;
1310 if (uLength
> SAL_MAX_SIZE
)
1311 return osl_File_E_OVERFLOW
;
1313 size_t const nLength
= sal::static_int_cast
< size_t >(uLength
);
1315 if (munmap(pAddr
, nLength
) == -1)
1316 return oslTranslateFileError(errno
);
1318 return osl_File_E_None
;
1323 // Note that osl_unmapFile() just won't work on Android in general
1324 // where for (uncompressed) files inside the .apk, in the /assets
1325 // folder osl_mapFile just returns a pointer to the file inside the
1326 // already mmapped .apk archive.
1328 oslFileError SAL_CALL
osl_unmapFile(void* pAddr
, sal_uInt64 uLength
)
1330 return unmapFile(pAddr
, uLength
);
1335 oslFileError SAL_CALL
osl_unmapMappedFile(oslFileHandle Handle
, void* pAddr
, sal_uInt64 uLength
)
1337 FileHandle_Impl
*pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1340 return osl_File_E_INVAL
;
1342 if (pImpl
->m_kind
== FileHandle_Impl::KIND_FD
)
1343 return unmapFile(pAddr
, uLength
);
1345 // For parts of already mmapped "parent" files, whose mapping we
1346 // can't change, not much we can or should do...
1347 return osl_File_E_None
;
1350 oslFileError SAL_CALL
osl_readLine(
1351 oslFileHandle Handle
,
1352 sal_Sequence
** ppSequence
)
1354 FileHandle_Impl
*pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1356 if ((!pImpl
) || ((pImpl
->m_kind
== FileHandle_Impl::KIND_FD
) && (pImpl
->m_fd
== -1)) || (!ppSequence
))
1357 return osl_File_E_INVAL
;
1359 sal_uInt64 uBytesRead
= 0;
1361 // read at current fileptr; fileptr += uBytesRead;
1362 FileHandle_Impl::Guard
lock(&(pImpl
->m_mutex
));
1363 oslFileError result
= pImpl
->readLineAt(pImpl
->m_fileptr
, ppSequence
, &uBytesRead
);
1365 if (result
== osl_File_E_None
)
1366 pImpl
->m_fileptr
+= uBytesRead
;
1371 oslFileError 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 ((!pImpl
) || ((pImpl
->m_kind
== FileHandle_Impl::KIND_FD
) && (pImpl
->m_fd
== -1)) || (!pBuffer
) || (!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
;
1386 size_t const nBytesRequested
= sal::static_int_cast
< size_t >(uBytesRequested
);
1388 // read at current fileptr; fileptr += *pBytesRead;
1389 FileHandle_Impl::Guard
lock(&(pImpl
->m_mutex
));
1390 oslFileError result
= pImpl
->readFileAt(pImpl
->m_fileptr
, pBuffer
, nBytesRequested
, pBytesRead
);
1392 if (result
== osl_File_E_None
)
1393 pImpl
->m_fileptr
+= *pBytesRead
;
1398 oslFileError SAL_CALL
osl_writeFile(
1399 oslFileHandle Handle
,
1400 const void * pBuffer
,
1401 sal_uInt64 uBytesToWrite
,
1402 sal_uInt64
* pBytesWritten
)
1404 FileHandle_Impl
* pImpl
= static_cast< FileHandle_Impl
* >(Handle
);
1406 if ((!pImpl
) || (pImpl
->m_fd
== -1) || (!pBuffer
) || (!pBytesWritten
))
1407 return osl_File_E_INVAL
;
1409 if (!(pImpl
->m_state
& State::Writeable
))
1410 return osl_File_E_BADF
;
1412 static sal_uInt64
const g_limit_ssize_t
= std::numeric_limits
< ssize_t
>::max();
1413 if (g_limit_ssize_t
< uBytesToWrite
)
1414 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(pImpl
->m_fileptr
, pBuffer
, nBytesToWrite
, pBytesWritten
);
1421 if (result
== osl_File_E_None
)
1422 pImpl
->m_fileptr
+= *pBytesWritten
;
1427 oslFileError SAL_CALL
osl_readFileAt(
1428 oslFileHandle Handle
,
1431 sal_uInt64 uBytesRequested
,
1432 sal_uInt64
* pBytesRead
)
1434 FileHandle_Impl
* pImpl
= static_cast< FileHandle_Impl
* >(Handle
);
1436 if ((!pImpl
) || ((pImpl
->m_kind
== FileHandle_Impl::KIND_FD
) && (pImpl
->m_fd
== -1)) || (!pBuffer
) || (!pBytesRead
))
1437 return osl_File_E_INVAL
;
1439 if (!(pImpl
->m_state
& State::Seekable
))
1440 return osl_File_E_SPIPE
;
1442 if (exceedsMaxOffT(uOffset
))
1443 return osl_File_E_OVERFLOW
;
1445 off_t
const nOffset
= sal::static_int_cast
< off_t
>(uOffset
);
1447 static sal_uInt64
const g_limit_ssize_t
= std::numeric_limits
< ssize_t
>::max();
1448 if (g_limit_ssize_t
< uBytesRequested
)
1449 return osl_File_E_OVERFLOW
;
1451 size_t const nBytesRequested
= sal::static_int_cast
< size_t >(uBytesRequested
);
1453 // read at specified fileptr
1454 FileHandle_Impl::Guard
lock(&(pImpl
->m_mutex
));
1456 return pImpl
->readFileAt(nOffset
, pBuffer
, nBytesRequested
, pBytesRead
);
1459 oslFileError SAL_CALL
osl_writeFileAt(
1460 oslFileHandle Handle
,
1462 const void* pBuffer
,
1463 sal_uInt64 uBytesToWrite
,
1464 sal_uInt64
* pBytesWritten
)
1466 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1468 if ((!pImpl
) || (pImpl
->m_fd
== -1) || (!pBuffer
) || (!pBytesWritten
))
1469 return osl_File_E_INVAL
;
1471 if (!(pImpl
->m_state
& State::Seekable
))
1472 return osl_File_E_SPIPE
;
1474 if (!(pImpl
->m_state
& State::Writeable
))
1475 return osl_File_E_BADF
;
1477 if (exceedsMaxOffT(uOffset
))
1478 return osl_File_E_OVERFLOW
;
1480 off_t
const nOffset
= sal::static_int_cast
< off_t
>(uOffset
);
1482 static sal_uInt64
const g_limit_ssize_t
= std::numeric_limits
< ssize_t
>::max();
1483 if (g_limit_ssize_t
< uBytesToWrite
)
1484 return osl_File_E_OVERFLOW
;
1486 size_t const nBytesToWrite
= sal::static_int_cast
< size_t >(uBytesToWrite
);
1488 // write at specified fileptr
1489 FileHandle_Impl::Guard
lock(&(pImpl
->m_mutex
));
1491 return pImpl
->writeFileAt(nOffset
, pBuffer
, nBytesToWrite
, pBytesWritten
);
1494 oslFileError SAL_CALL
osl_isEndOfFile(oslFileHandle Handle
, sal_Bool
*pIsEOF
)
1496 FileHandle_Impl
* pImpl
= static_cast< FileHandle_Impl
* >(Handle
);
1498 if ((!pImpl
) || ((pImpl
->m_kind
== FileHandle_Impl::KIND_FD
) && (pImpl
->m_fd
== -1)) || (!pIsEOF
))
1499 return osl_File_E_INVAL
;
1501 FileHandle_Impl::Guard
lock(&(pImpl
->m_mutex
));
1502 *pIsEOF
= (pImpl
->getPos() == pImpl
->getSize());
1504 return osl_File_E_None
;
1507 oslFileError SAL_CALL
osl_getFilePos(oslFileHandle Handle
, sal_uInt64
* pPos
)
1509 FileHandle_Impl
* pImpl
= static_cast< FileHandle_Impl
* >(Handle
);
1511 if ((!pImpl
) || ((pImpl
->m_kind
== FileHandle_Impl::KIND_FD
) && (pImpl
->m_fd
== -1)) || (!pPos
))
1512 return osl_File_E_INVAL
;
1514 // no need to lock because pos is atomic
1515 *pPos
= pImpl
->getPos();
1517 return osl_File_E_None
;
1520 oslFileError SAL_CALL
osl_setFilePos(oslFileHandle Handle
, sal_uInt32 uHow
, sal_Int64 uOffset
)
1522 FileHandle_Impl
* pImpl
= static_cast< FileHandle_Impl
* >(Handle
);
1524 if ((!pImpl
) || ((pImpl
->m_kind
== FileHandle_Impl::KIND_FD
) && (pImpl
->m_fd
== -1)))
1525 return osl_File_E_INVAL
;
1527 if (exceedsMaxOffT(uOffset
) || exceedsMinOffT(uOffset
))
1528 return osl_File_E_OVERFLOW
;
1530 off_t nPos
= 0, nOffset
= sal::static_int_cast
< off_t
>(uOffset
);
1532 FileHandle_Impl::Guard
lock(&(pImpl
->m_mutex
));
1535 case osl_Pos_Absolut
:
1537 return osl_File_E_INVAL
;
1540 case osl_Pos_Current
:
1541 nPos
= sal::static_int_cast
< off_t
>(pImpl
->getPos());
1542 if ((nOffset
< 0) && (nPos
< -1*nOffset
))
1543 return osl_File_E_INVAL
;
1546 if (nOffset
> MAX_OFF_T
- nPos
)
1547 return osl_File_E_OVERFLOW
;
1551 nPos
= sal::static_int_cast
< off_t
>(pImpl
->getSize());
1552 if ((nOffset
< 0) && (nPos
< -1*nOffset
))
1553 return osl_File_E_INVAL
;
1556 if (nOffset
> MAX_OFF_T
- nPos
)
1557 return osl_File_E_OVERFLOW
;
1561 return osl_File_E_INVAL
;
1564 pImpl
->setPos(nPos
+ nOffset
);
1565 return osl_File_E_None
;
1568 oslFileError SAL_CALL
osl_getFileSize(oslFileHandle Handle
, sal_uInt64
* pSize
)
1570 FileHandle_Impl
* pImpl
= static_cast< FileHandle_Impl
* >(Handle
);
1572 if ((!pImpl
) || ((pImpl
->m_kind
== FileHandle_Impl::KIND_FD
) && (pImpl
->m_fd
== -1)) || (!pSize
))
1573 return osl_File_E_INVAL
;
1575 FileHandle_Impl::Guard
lock(&(pImpl
->m_mutex
));
1576 *pSize
= pImpl
->getSize();
1578 return osl_File_E_None
;
1581 oslFileError SAL_CALL
osl_setFileSize(oslFileHandle Handle
, sal_uInt64 uSize
)
1583 FileHandle_Impl
* pImpl
= static_cast< FileHandle_Impl
* >(Handle
);
1585 if ((!pImpl
) || (pImpl
->m_fd
== -1))
1586 return osl_File_E_INVAL
;
1588 if (!(pImpl
->m_state
& State::Writeable
))
1589 return osl_File_E_BADF
;
1591 if (exceedsMaxOffT(uSize
))
1592 return osl_File_E_OVERFLOW
;
1594 oslFileError result
= pImpl
->syncFile();
1595 if (result
!= osl_File_E_None
)
1598 pImpl
->m_bufptr
= -1;
1599 pImpl
->m_buflen
= 0;
1601 return pImpl
->setSize(uSize
);
1604 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */