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 <systools/win32/uwinapi.h>
22 #include <osl/file.hxx>
23 #include <rtl/alloc.h>
24 #include <rtl/byteseq.h>
25 #include <sal/log.hxx>
26 #include <o3tl/char16_t2wchar_t.hxx>
28 #include "file-impl.hxx"
29 #include "file_url.hxx"
30 #include "file_error.hxx"
36 #ifdef max /* conflict w/ std::numeric_limits<T>::max() */
43 /** File handle implementation.
45 struct FileHandle_Impl
47 CRITICAL_SECTION m_mutex
;
54 STATE_SEEKABLE
= 1, /*< open() sets, iff regular file */
55 STATE_READABLE
= 2, /*< open() sets, read() requires */
56 STATE_WRITEABLE
= 4, /*< open() sets, write() requires */
57 STATE_MODIFIED
= 8 /* write() sets, flush() resets */
61 sal_uInt64 m_size
; /*< file size */
62 LONGLONG m_offset
; /*< physical offset from begin of file */
63 LONGLONG m_filepos
; /*< logical offset from begin of file */
65 LONGLONG m_bufptr
; /*< buffer offset from begin of file */
66 SIZE_T m_buflen
; /*< buffer filled [0, m_bufsiz - 1] */
71 explicit FileHandle_Impl (HANDLE hFile
);
74 static void* operator new(size_t n
);
75 static void operator delete(void * p
, size_t);
76 static SIZE_T
getpagesize();
78 sal_uInt64
getPos() const;
79 oslFileError
setPos (sal_uInt64 uPos
);
81 sal_uInt64
getSize() const;
82 oslFileError
setSize (sal_uInt64 uPos
);
87 DWORD nBytesRequested
,
88 sal_uInt64
* pBytesRead
);
94 sal_uInt64
* pBytesWritten
);
96 oslFileError
readFileAt(
99 sal_uInt64 uBytesRequested
,
100 sal_uInt64
* pBytesRead
);
102 oslFileError
writeFileAt(
104 void const * pBuffer
,
105 sal_uInt64 uBytesToWrite
,
106 sal_uInt64
* pBytesWritten
);
108 oslFileError
readLineAt(
110 sal_Sequence
** ppSequence
,
111 sal_uInt64
* pBytesRead
);
113 static oslFileError
writeSequence_Impl (
114 sal_Sequence
** ppSequence
,
116 const void * pBuffer
,
119 oslFileError
syncFile();
125 LPCRITICAL_SECTION m_mutex
;
128 explicit Guard(LPCRITICAL_SECTION pMutex
);
133 FileHandle_Impl::Guard::Guard(LPCRITICAL_SECTION pMutex
)
137 ::EnterCriticalSection (m_mutex
);
140 FileHandle_Impl::Guard::~Guard()
142 ::LeaveCriticalSection (m_mutex
);
145 FileHandle_Impl::FileHandle_Impl(HANDLE hFile
)
147 m_state (STATE_READABLE
| STATE_WRITEABLE
),
153 m_bufsiz (getpagesize()),
156 ::InitializeCriticalSection (&m_mutex
);
157 m_buffer
= static_cast<sal_uInt8
*>(malloc(m_bufsiz
));
159 memset (m_buffer
, 0, m_bufsiz
);
162 FileHandle_Impl::~FileHandle_Impl()
166 ::DeleteCriticalSection (&m_mutex
);
169 void * FileHandle_Impl::operator new(size_t n
)
174 void FileHandle_Impl::operator delete(void * p
, size_t)
179 SIZE_T
FileHandle_Impl::getpagesize()
182 ::GetSystemInfo(&info
);
183 return sal::static_int_cast
< SIZE_T
>(info
.dwPageSize
);
186 sal_uInt64
FileHandle_Impl::getPos() const
188 return sal::static_int_cast
< sal_uInt64
>(m_filepos
);
191 oslFileError
FileHandle_Impl::setPos(sal_uInt64 uPos
)
193 m_filepos
= sal::static_int_cast
< LONGLONG
>(uPos
);
194 return osl_File_E_None
;
197 sal_uInt64
FileHandle_Impl::getSize() const
199 LONGLONG bufend
= std::max(LONGLONG(0), m_bufptr
) + m_buflen
;
200 return std::max(m_size
, sal::static_int_cast
< sal_uInt64
>(bufend
));
203 oslFileError
FileHandle_Impl::setSize(sal_uInt64 uSize
)
205 LARGE_INTEGER nDstPos
; nDstPos
.QuadPart
= sal::static_int_cast
< LONGLONG
>(uSize
);
206 if (!::SetFilePointerEx(m_hFile
, nDstPos
, nullptr, FILE_BEGIN
))
207 return oslTranslateFileError(GetLastError());
209 if (!::SetEndOfFile(m_hFile
))
210 return oslTranslateFileError(GetLastError());
213 nDstPos
.QuadPart
= m_offset
;
214 if (!::SetFilePointerEx(m_hFile
, nDstPos
, nullptr, FILE_BEGIN
))
215 return oslTranslateFileError(GetLastError());
217 return osl_File_E_None
;
220 oslFileError
FileHandle_Impl::readAt(
223 DWORD nBytesRequested
,
224 sal_uInt64
* pBytesRead
)
226 SAL_WARN_IF(!(m_state
& STATE_SEEKABLE
), "sal.osl", "FileHandle_Impl::readAt(): not seekable");
227 if (!(m_state
& STATE_SEEKABLE
))
228 return osl_File_E_SPIPE
;
230 SAL_WARN_IF(!(m_state
& STATE_READABLE
), "sal.osl", "FileHandle_Impl::readAt(): not readable");
231 if (!(m_state
& STATE_READABLE
))
232 return osl_File_E_BADF
;
234 if (nOffset
!= m_offset
)
236 LARGE_INTEGER liOffset
; liOffset
.QuadPart
= nOffset
;
237 if (!::SetFilePointerEx(m_hFile
, liOffset
, nullptr, FILE_BEGIN
))
238 return oslTranslateFileError(GetLastError());
243 if (!::ReadFile(m_hFile
, pBuffer
, nBytesRequested
, &dwDone
, nullptr))
244 return oslTranslateFileError(GetLastError());
247 *pBytesRead
= dwDone
;
248 return osl_File_E_None
;
251 oslFileError
FileHandle_Impl::writeAt(
253 void const * pBuffer
,
255 sal_uInt64
* pBytesWritten
)
257 SAL_WARN_IF(!(m_state
& STATE_SEEKABLE
), "sal.osl", "FileHandle_Impl::writeAt(): not seekable");
258 if (!(m_state
& STATE_SEEKABLE
))
259 return osl_File_E_SPIPE
;
261 SAL_WARN_IF(!(m_state
& STATE_WRITEABLE
), "sal.osl", "FileHandle_Impl::writeAt(): not writeable");
262 if (!(m_state
& STATE_WRITEABLE
))
263 return osl_File_E_BADF
;
265 if (nOffset
!= m_offset
)
267 LARGE_INTEGER liOffset
; liOffset
.QuadPart
= nOffset
;
268 if (!::SetFilePointerEx (m_hFile
, liOffset
, nullptr, FILE_BEGIN
))
269 return oslTranslateFileError(GetLastError());
274 if (!::WriteFile(m_hFile
, pBuffer
, nBytesToWrite
, &dwDone
, nullptr))
275 return oslTranslateFileError(GetLastError());
278 m_size
= std::max(m_size
, sal::static_int_cast
< sal_uInt64
>(m_offset
));
280 *pBytesWritten
= dwDone
;
281 return osl_File_E_None
;
284 oslFileError
FileHandle_Impl::readFileAt(
287 sal_uInt64 uBytesRequested
,
288 sal_uInt64
* pBytesRead
)
290 static sal_uInt64
const g_limit_dword
= std::numeric_limits
< DWORD
>::max();
291 if (g_limit_dword
< uBytesRequested
)
292 return osl_File_E_OVERFLOW
;
293 DWORD nBytesRequested
= sal::static_int_cast
< DWORD
>(uBytesRequested
);
295 if ((m_state
& STATE_SEEKABLE
) == 0)
297 // not seekable (pipe)
299 if (!::ReadFile(m_hFile
, pBuffer
, nBytesRequested
, &dwDone
, nullptr))
300 return oslTranslateFileError(GetLastError());
301 *pBytesRead
= dwDone
;
302 return osl_File_E_None
;
307 return readAt (nOffset
, pBuffer
, nBytesRequested
, pBytesRead
);
311 sal_uInt8
* buffer
= static_cast< sal_uInt8
* >(pBuffer
);
312 for (*pBytesRead
= 0; nBytesRequested
> 0;)
314 LONGLONG
const bufptr
= (nOffset
/ m_bufsiz
) * m_bufsiz
;
315 SIZE_T
const bufpos
= (nOffset
% m_bufsiz
);
317 if (bufptr
!= m_bufptr
)
319 // flush current buffer
320 oslFileError result
= syncFile();
321 if (result
!= osl_File_E_None
)
326 if (nBytesRequested
>= m_bufsiz
)
328 // buffer too small, read through from file
329 sal_uInt64 uDone
= 0;
330 result
= readAt (nOffset
, &(buffer
[*pBytesRead
]), nBytesRequested
, &uDone
);
331 if (result
!= osl_File_E_None
)
334 nBytesRequested
-= sal::static_int_cast
< DWORD
>(uDone
);
335 *pBytesRead
+= uDone
;
336 return osl_File_E_None
;
339 // update buffer (pointer)
340 sal_uInt64 uDone
= 0;
341 result
= readAt(bufptr
, m_buffer
, m_bufsiz
, &uDone
);
342 if (result
!= osl_File_E_None
)
345 m_buflen
= sal::static_int_cast
< SIZE_T
>(uDone
);
347 if (bufpos
>= m_buflen
)
350 return osl_File_E_None
;
353 SIZE_T
const bytes
= std::min(m_buflen
- bufpos
, static_cast<SIZE_T
>(nBytesRequested
));
354 memcpy(&(buffer
[*pBytesRead
]), &(m_buffer
[bufpos
]), bytes
);
355 nBytesRequested
-= bytes
;
356 *pBytesRead
+= bytes
;
359 return osl_File_E_None
;
363 oslFileError
FileHandle_Impl::writeFileAt(
365 void const * pBuffer
,
366 sal_uInt64 uBytesToWrite
,
367 sal_uInt64
* pBytesWritten
)
369 static sal_uInt64
const g_limit_dword
= std::numeric_limits
< DWORD
>::max();
370 if (g_limit_dword
< uBytesToWrite
)
371 return osl_File_E_OVERFLOW
;
372 DWORD nBytesToWrite
= sal::static_int_cast
< DWORD
>(uBytesToWrite
);
374 if ((m_state
& STATE_SEEKABLE
) == 0)
376 // not seekable (pipe)
378 if (!::WriteFile(m_hFile
, pBuffer
, nBytesToWrite
, &dwDone
, nullptr))
379 return oslTranslateFileError(GetLastError());
380 *pBytesWritten
= dwDone
;
381 return osl_File_E_None
;
386 return writeAt(nOffset
, pBuffer
, nBytesToWrite
, pBytesWritten
);
390 sal_uInt8
const * buffer
= static_cast< sal_uInt8
const* >(pBuffer
);
391 for (*pBytesWritten
= 0; nBytesToWrite
> 0;)
393 LONGLONG
const bufptr
= (nOffset
/ m_bufsiz
) * m_bufsiz
;
394 SIZE_T
const bufpos
= (nOffset
% m_bufsiz
);
395 if (bufptr
!= m_bufptr
)
397 // flush current buffer
398 oslFileError result
= syncFile();
399 if (result
!= osl_File_E_None
)
404 if (nBytesToWrite
>= m_bufsiz
)
406 // buffer too small, write through to file
407 sal_uInt64 uDone
= 0;
408 result
= writeAt(nOffset
, &(buffer
[*pBytesWritten
]), nBytesToWrite
, &uDone
);
409 if (result
!= osl_File_E_None
)
411 if (uDone
!= nBytesToWrite
)
412 return osl_File_E_IO
;
414 nBytesToWrite
-= sal::static_int_cast
< DWORD
>(uDone
);
415 *pBytesWritten
+= uDone
;
416 return osl_File_E_None
;
419 // update buffer (pointer)
420 sal_uInt64 uDone
= 0;
421 result
= readAt(bufptr
, m_buffer
, m_bufsiz
, &uDone
);
422 if (result
!= osl_File_E_None
)
425 m_buflen
= sal::static_int_cast
< SIZE_T
>(uDone
);
428 SIZE_T
const bytes
= std::min(m_bufsiz
- bufpos
, static_cast<SIZE_T
>(nBytesToWrite
));
429 memcpy(&(m_buffer
[bufpos
]), &(buffer
[*pBytesWritten
]), bytes
);
430 nBytesToWrite
-= bytes
;
431 *pBytesWritten
+= bytes
;
434 m_buflen
= std::max(m_buflen
, bufpos
+ bytes
);
435 m_state
|= STATE_MODIFIED
;
437 return osl_File_E_None
;
441 oslFileError
FileHandle_Impl::readLineAt(
443 sal_Sequence
** ppSequence
,
444 sal_uInt64
* pBytesRead
)
446 oslFileError result
= osl_File_E_None
;
448 LONGLONG bufptr
= (nOffset
/ m_bufsiz
) * m_bufsiz
;
449 if (bufptr
!= m_bufptr
)
451 /* flush current buffer */
453 if (result
!= osl_File_E_None
)
456 /* update buffer (pointer) */
457 sal_uInt64 uDone
= 0;
458 result
= readAt(bufptr
, m_buffer
, m_bufsiz
, &uDone
);
459 if (result
!= osl_File_E_None
)
463 m_buflen
= sal::static_int_cast
< SIZE_T
>(uDone
);
466 static int const LINE_STATE_BEGIN
= 0;
467 static int const LINE_STATE_CR
= 1;
468 static int const LINE_STATE_LF
= 2;
470 SIZE_T bufpos
= sal::static_int_cast
< SIZE_T
>(nOffset
- m_bufptr
), curpos
= bufpos
, dstpos
= 0;
471 int state
= (bufpos
>= m_buflen
) ? LINE_STATE_LF
: LINE_STATE_BEGIN
;
473 for (; state
!= LINE_STATE_LF
;)
475 if (curpos
>= m_buflen
)
477 /* buffer examined */
478 if (curpos
> bufpos
) // actually, curpos can't become less than bufpos, so != could do
480 /* flush buffer to sequence */
481 result
= writeSequence_Impl(
482 ppSequence
, &dstpos
, &(m_buffer
[bufpos
]), curpos
- bufpos
);
483 if (result
!= osl_File_E_None
)
485 *pBytesRead
+= curpos
- bufpos
;
486 nOffset
+= curpos
- bufpos
;
489 bufptr
= nOffset
/ m_bufsiz
* m_bufsiz
;
490 if (bufptr
!= m_bufptr
)
492 /* update buffer (pointer) */
493 sal_uInt64 uDone
= 0;
494 result
= readAt(bufptr
, m_buffer
, m_bufsiz
, &uDone
);
495 if (result
!= osl_File_E_None
)
498 m_buflen
= sal::static_int_cast
< SIZE_T
>(uDone
);
501 bufpos
= sal::static_int_cast
< SIZE_T
>(nOffset
- m_bufptr
);
503 if (bufpos
>= m_buflen
)
509 state
= LINE_STATE_LF
;
510 switch (m_buffer
[curpos
])
512 case 0x0A: /* CRLF */
513 /* eat current char */
516 default: /* single CR */
517 /* keep current char */
522 /* determine next state */
523 switch (m_buffer
[curpos
])
525 case 0x0A: /* single LF */
526 state
= LINE_STATE_LF
;
529 state
= LINE_STATE_CR
;
531 default: /* advance to next char */
535 if (state
!= LINE_STATE_BEGIN
)
537 /* store (and eat) the newline char */
538 m_buffer
[curpos
] = 0x0A;
541 /* flush buffer to sequence */
542 result
= writeSequence_Impl(
543 ppSequence
, &dstpos
, &(m_buffer
[bufpos
]), curpos
- bufpos
- 1);
544 if (result
!= osl_File_E_None
)
546 *pBytesRead
+= curpos
- bufpos
;
547 nOffset
+= curpos
- bufpos
;
553 result
= writeSequence_Impl(ppSequence
, &dstpos
, nullptr, 0);
554 if (result
!= osl_File_E_None
)
557 return osl_File_E_None
;
558 if (bufpos
>= m_buflen
)
559 return osl_File_E_AGAIN
;
560 return osl_File_E_None
;
563 oslFileError
FileHandle_Impl::writeSequence_Impl(
564 sal_Sequence
** ppSequence
,
566 const void * pBuffer
,
569 sal_Int32 nElements
= *pnOffset
+ nBytes
;
572 /* construct sequence */
573 rtl_byte_sequence_constructNoDefault(ppSequence
, nElements
);
575 else if (nElements
!= (*ppSequence
)->nElements
)
577 /* resize sequence */
578 rtl_byte_sequence_realloc(ppSequence
, nElements
);
583 memcpy(&((*ppSequence
)->elements
[*pnOffset
]), pBuffer
, nBytes
);
586 return (*ppSequence
) ? osl_File_E_None
: osl_File_E_NOMEM
;
589 oslFileError
FileHandle_Impl::syncFile()
591 oslFileError result
= osl_File_E_None
;
592 if (m_state
& STATE_MODIFIED
)
594 sal_uInt64 uDone
= 0;
595 result
= writeAt(m_bufptr
, m_buffer
, m_buflen
, &uDone
);
596 if (result
!= osl_File_E_None
)
598 if (uDone
!= m_buflen
)
599 return osl_File_E_IO
;
600 m_state
&= ~STATE_MODIFIED
;
605 extern "C" oslFileHandle
osl_createFileHandleFromOSHandle(
609 if (!IsValidHandle(hFile
))
610 return nullptr; // EINVAL
612 FileHandle_Impl
* pImpl
= new FileHandle_Impl(hFile
);
614 /* check for regular file */
615 if (GetFileType(hFile
) == FILE_TYPE_DISK
)
618 pImpl
->m_state
|= FileHandle_Impl::STATE_SEEKABLE
;
620 /* init current size */
621 LARGE_INTEGER uSize
= { { 0, 0 } };
622 (void) ::GetFileSizeEx(hFile
, &uSize
);
623 pImpl
->m_size
= (sal::static_int_cast
<sal_uInt64
>(uSize
.HighPart
) << 32) + uSize
.LowPart
;
626 if (!(uFlags
& osl_File_OpenFlag_Read
))
627 pImpl
->m_state
&= ~FileHandle_Impl::STATE_READABLE
;
628 if (!(uFlags
& osl_File_OpenFlag_Write
))
629 pImpl
->m_state
&= ~FileHandle_Impl::STATE_WRITEABLE
;
632 !((uFlags
& osl_File_OpenFlag_Read
) || (uFlags
& osl_File_OpenFlag_Write
)),
634 "osl_createFileHandleFromOSHandle(): missing read/write access flags");
635 return static_cast<oslFileHandle
>(pImpl
);
638 oslFileError SAL_CALL
osl_openFile(
639 rtl_uString
* strPath
,
640 oslFileHandle
* pHandle
,
643 rtl_uString
* strSysPath
= nullptr;
644 oslFileError result
= osl_getSystemPathFromFileURL_(strPath
, &strSysPath
, false);
645 if (result
!= osl_File_E_None
)
648 DWORD dwAccess
= GENERIC_READ
, dwShare
= FILE_SHARE_READ
, dwCreation
= 0;
650 if (uFlags
& osl_File_OpenFlag_Write
)
651 dwAccess
|= GENERIC_WRITE
;
653 dwShare
|= FILE_SHARE_WRITE
;
655 if (uFlags
& osl_File_OpenFlag_NoLock
)
656 dwShare
|= FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
658 if (uFlags
& osl_File_OpenFlag_Create
)
659 dwCreation
|= CREATE_NEW
;
661 dwCreation
|= OPEN_EXISTING
;
663 HANDLE hFile
= CreateFileW(
664 o3tl::toW(rtl_uString_getStr(strSysPath
)),
665 dwAccess
, dwShare
, nullptr, dwCreation
, 0, nullptr);
667 // @@@ ERROR HANDLING @@@
668 if (!IsValidHandle(hFile
))
669 result
= oslTranslateFileError(GetLastError());
671 *pHandle
= osl_createFileHandleFromOSHandle(hFile
, uFlags
| osl_File_OpenFlag_Read
);
673 rtl_uString_release(strSysPath
);
677 oslFileError SAL_CALL
osl_syncFile(oslFileHandle Handle
)
679 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
680 if ((!pImpl
) || !IsValidHandle(pImpl
->m_hFile
))
681 return osl_File_E_INVAL
;
683 FileHandle_Impl::Guard
lock(&(pImpl
->m_mutex
));
685 oslFileError result
= pImpl
->syncFile();
686 if (result
!= osl_File_E_None
)
689 if (!FlushFileBuffers(pImpl
->m_hFile
))
690 return oslTranslateFileError(GetLastError());
692 return osl_File_E_None
;
695 oslFileError SAL_CALL
osl_closeFile(oslFileHandle Handle
)
697 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
698 if ((!pImpl
) || !IsValidHandle(pImpl
->m_hFile
))
699 return osl_File_E_INVAL
;
701 ::EnterCriticalSection(&(pImpl
->m_mutex
));
703 oslFileError result
= pImpl
->syncFile();
704 if (result
!= osl_File_E_None
)
706 /* ignore double failure */
707 (void)::CloseHandle(pImpl
->m_hFile
);
709 else if (!::CloseHandle(pImpl
->m_hFile
))
711 /* translate error code */
712 result
= oslTranslateFileError(GetLastError());
715 ::LeaveCriticalSection(&(pImpl
->m_mutex
));
722 // coverity[result_independent_of_operands] - crossplatform requirement
723 template<typename T
> bool exceedsMaxSIZE_T(T n
)
724 { return n
> std::numeric_limits
< SIZE_T
>::max(); }
728 oslFileError SAL_CALL
osl_mapFile(
729 oslFileHandle Handle
,
739 explicit FileMapping(HANDLE hMap
)
745 (void)::CloseHandle(m_handle
);
749 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
750 if ((!pImpl
) || !IsValidHandle(pImpl
->m_hFile
) || (!ppAddr
))
751 return osl_File_E_INVAL
;
754 if (exceedsMaxSIZE_T(uLength
))
755 return osl_File_E_OVERFLOW
;
756 SIZE_T
const nLength
= sal::static_int_cast
< SIZE_T
>(uLength
);
758 FileMapping
aMap(::CreateFileMappingW(pImpl
->m_hFile
, nullptr, SEC_COMMIT
| PAGE_READONLY
, 0, 0, nullptr));
759 if (!IsValidHandle(aMap
.m_handle
))
760 return oslTranslateFileError(GetLastError());
762 DWORD
const dwOffsetHi
= sal::static_int_cast
<DWORD
>(uOffset
>> 32);
763 DWORD
const dwOffsetLo
= sal::static_int_cast
<DWORD
>(uOffset
& 0xFFFFFFFF);
765 *ppAddr
= ::MapViewOfFile(aMap
.m_handle
, FILE_MAP_READ
, dwOffsetHi
, dwOffsetLo
, nLength
);
767 return oslTranslateFileError(GetLastError());
769 if (uFlags
& osl_File_MapFlag_RandomAccess
)
771 // Determine memory pagesize.
773 ::GetSystemInfo(&info
);
774 DWORD
const dwPageSize
= info
.dwPageSize
;
777 * Pagein, touching first byte of each memory page.
778 * Note: volatile disables optimizing the loop away.
780 BYTE
* pData(static_cast<BYTE
*>(*ppAddr
));
781 SIZE_T
nSize(nLength
);
784 while (nSize
> dwPageSize
)
795 return osl_File_E_None
;
798 oslFileError SAL_CALL
osl_unmapFile(void* pAddr
, sal_uInt64
/* uLength */)
801 return osl_File_E_INVAL
;
803 if (!::UnmapViewOfFile(pAddr
))
804 return oslTranslateFileError(GetLastError());
806 return osl_File_E_None
;
809 oslFileError SAL_CALL
osl_unmapMappedFile(oslFileHandle
/* Handle */, void* pAddr
, sal_uInt64 uLength
)
811 return osl_unmapFile(pAddr
, uLength
);
815 SAL_CALL
osl_readLine(
816 oslFileHandle Handle
,
817 sal_Sequence
** ppSequence
)
819 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
820 if ((!pImpl
) || !IsValidHandle(pImpl
->m_hFile
) || (!ppSequence
))
821 return osl_File_E_INVAL
;
822 sal_uInt64 uBytesRead
= 0;
824 // read at current filepos; filepos += uBytesRead;
825 FileHandle_Impl::Guard
lock(&(pImpl
->m_mutex
));
826 oslFileError result
= pImpl
->readLineAt(
827 pImpl
->m_filepos
, ppSequence
, &uBytesRead
);
828 if (result
== osl_File_E_None
)
829 pImpl
->m_filepos
+= uBytesRead
;
833 oslFileError SAL_CALL
osl_readFile(
834 oslFileHandle Handle
,
836 sal_uInt64 uBytesRequested
,
837 sal_uInt64
* pBytesRead
)
839 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
840 if ((!pImpl
) || !IsValidHandle(pImpl
->m_hFile
) || (!pBuffer
) || (!pBytesRead
))
841 return osl_File_E_INVAL
;
843 // read at current filepos; filepos += *pBytesRead;
844 FileHandle_Impl::Guard
lock(&(pImpl
->m_mutex
));
845 oslFileError result
= pImpl
->readFileAt(
846 pImpl
->m_filepos
, pBuffer
, uBytesRequested
, pBytesRead
);
847 if (result
== osl_File_E_None
)
848 pImpl
->m_filepos
+= *pBytesRead
;
852 oslFileError SAL_CALL
osl_writeFile(
853 oslFileHandle Handle
,
854 const void * pBuffer
,
855 sal_uInt64 uBytesToWrite
,
856 sal_uInt64
* pBytesWritten
)
858 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
860 if ((!pImpl
) || !IsValidHandle(pImpl
->m_hFile
) || (!pBuffer
) || (!pBytesWritten
))
861 return osl_File_E_INVAL
;
863 // write at current filepos; filepos += *pBytesWritten;
864 FileHandle_Impl::Guard
lock(&(pImpl
->m_mutex
));
865 oslFileError result
= pImpl
->writeFileAt(
866 pImpl
->m_filepos
, pBuffer
, uBytesToWrite
, pBytesWritten
);
867 if (result
== osl_File_E_None
)
868 pImpl
->m_filepos
+= *pBytesWritten
;
872 LONGLONG
const g_limit_longlong
= std::numeric_limits
< LONGLONG
>::max();
876 // coverity[result_independent_of_operands] - crossplatform requirement
877 template<typename T
> bool exceedsMaxLONGLONG(T n
)
878 { return n
> g_limit_longlong
; }
880 template<typename T
> bool exceedsMinLONGLONG(T n
)
881 { return n
< std::numeric_limits
<LONGLONG
>::min(); }
885 oslFileError SAL_CALL
osl_readFileAt(
886 oslFileHandle Handle
,
889 sal_uInt64 uBytesRequested
,
890 sal_uInt64
* pBytesRead
)
892 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
894 if ((!pImpl
) || !IsValidHandle(pImpl
->m_hFile
) || (!pBuffer
) || (!pBytesRead
))
895 return osl_File_E_INVAL
;
896 if ((pImpl
->m_state
& FileHandle_Impl::STATE_SEEKABLE
) == 0)
897 return osl_File_E_SPIPE
;
899 if (exceedsMaxLONGLONG(uOffset
))
900 return osl_File_E_OVERFLOW
;
901 LONGLONG
const nOffset
= sal::static_int_cast
< LONGLONG
>(uOffset
);
903 // read at specified fileptr
904 FileHandle_Impl::Guard
lock (&(pImpl
->m_mutex
));
905 return pImpl
->readFileAt(nOffset
, pBuffer
, uBytesRequested
, pBytesRead
);
908 oslFileError SAL_CALL
osl_writeFileAt(
909 oslFileHandle Handle
,
912 sal_uInt64 uBytesToWrite
,
913 sal_uInt64
* pBytesWritten
)
915 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
917 if ((!pImpl
) || !IsValidHandle(pImpl
->m_hFile
) || (!pBuffer
) || (!pBytesWritten
))
918 return osl_File_E_INVAL
;
919 if ((pImpl
->m_state
& FileHandle_Impl::STATE_SEEKABLE
) == 0)
920 return osl_File_E_SPIPE
;
922 if (exceedsMaxLONGLONG(uOffset
))
923 return osl_File_E_OVERFLOW
;
924 LONGLONG
const nOffset
= sal::static_int_cast
< LONGLONG
>(uOffset
);
926 // write at specified fileptr
927 FileHandle_Impl::Guard
lock(&(pImpl
->m_mutex
));
928 return pImpl
->writeFileAt(nOffset
, pBuffer
, uBytesToWrite
, pBytesWritten
);
931 oslFileError SAL_CALL
osl_isEndOfFile(oslFileHandle Handle
, sal_Bool
*pIsEOF
)
933 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
935 if ((!pImpl
) || !IsValidHandle(pImpl
->m_hFile
) || (!pIsEOF
))
936 return osl_File_E_INVAL
;
938 FileHandle_Impl::Guard
lock(&(pImpl
->m_mutex
));
939 *pIsEOF
= (pImpl
->getPos() == pImpl
->getSize());
940 return osl_File_E_None
;
943 oslFileError SAL_CALL
osl_getFilePos(oslFileHandle Handle
, sal_uInt64
*pPos
)
945 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
946 if ((!pImpl
) || !IsValidHandle(pImpl
->m_hFile
) || (!pPos
))
947 return osl_File_E_INVAL
;
949 FileHandle_Impl::Guard
lock(&(pImpl
->m_mutex
));
950 *pPos
= pImpl
->getPos();
951 return osl_File_E_None
;
954 oslFileError SAL_CALL
osl_setFilePos(oslFileHandle Handle
, sal_uInt32 uHow
, sal_Int64 uOffset
)
956 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
957 if ((!pImpl
) || !IsValidHandle(pImpl
->m_hFile
))
958 return osl_File_E_INVAL
;
960 if (exceedsMaxLONGLONG(uOffset
) || exceedsMinLONGLONG(uOffset
))
961 return osl_File_E_OVERFLOW
;
962 LONGLONG nPos
= 0, nOffset
= sal::static_int_cast
< LONGLONG
>(uOffset
);
964 FileHandle_Impl::Guard
lock(&(pImpl
->m_mutex
));
967 case osl_Pos_Absolut
:
969 return osl_File_E_INVAL
;
972 case osl_Pos_Current
:
973 nPos
= sal::static_int_cast
< LONGLONG
>(pImpl
->getPos());
974 if ((nOffset
< 0) && (nPos
< -1*nOffset
))
975 return osl_File_E_INVAL
;
977 if (nOffset
> g_limit_longlong
- nPos
)
978 return osl_File_E_OVERFLOW
;
982 nPos
= sal::static_int_cast
< LONGLONG
>(pImpl
->getSize());
983 if ((nOffset
< 0) && (nPos
< -1*nOffset
))
984 return osl_File_E_INVAL
;
986 if (nOffset
> g_limit_longlong
- nPos
)
987 return osl_File_E_OVERFLOW
;
991 return osl_File_E_INVAL
;
994 return pImpl
->setPos(nPos
+ nOffset
);
997 oslFileError SAL_CALL
osl_getFileSize(oslFileHandle Handle
, sal_uInt64
*pSize
)
999 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1001 if ((!pImpl
) || !IsValidHandle(pImpl
->m_hFile
) || (!pSize
))
1002 return osl_File_E_INVAL
;
1004 FileHandle_Impl::Guard
lock(&(pImpl
->m_mutex
));
1005 *pSize
= pImpl
->getSize();
1006 return osl_File_E_None
;
1009 oslFileError SAL_CALL
osl_setFileSize(oslFileHandle Handle
, sal_uInt64 uSize
)
1011 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1013 if ((!pImpl
) || !IsValidHandle(pImpl
->m_hFile
))
1014 return osl_File_E_INVAL
;
1015 if ((pImpl
->m_state
& FileHandle_Impl::STATE_WRITEABLE
) == 0)
1016 return osl_File_E_BADF
;
1018 if (exceedsMaxLONGLONG(uSize
))
1019 return osl_File_E_OVERFLOW
;
1021 FileHandle_Impl::Guard
lock(&(pImpl
->m_mutex
));
1022 oslFileError result
= pImpl
->syncFile();
1023 if (result
!= osl_File_E_None
)
1025 pImpl
->m_bufptr
= -1;
1026 pImpl
->m_buflen
= 0;
1028 return pImpl
->setSize(uSize
);
1031 oslFileError SAL_CALL
osl_removeFile(rtl_uString
* strPath
)
1033 rtl_uString
*strSysPath
= nullptr;
1034 oslFileError error
= osl_getSystemPathFromFileURL_(strPath
, &strSysPath
, false);
1036 if (error
== osl_File_E_None
)
1038 if (DeleteFileW(o3tl::toW(rtl_uString_getStr(strSysPath
))))
1039 error
= osl_File_E_None
;
1041 error
= oslTranslateFileError(GetLastError());
1043 rtl_uString_release(strSysPath
);
1048 oslFileError SAL_CALL
osl_copyFile(rtl_uString
* strPath
, rtl_uString
*strDestPath
)
1050 rtl_uString
*strSysPath
= nullptr, *strSysDestPath
= nullptr;
1051 oslFileError error
= osl_getSystemPathFromFileURL_(strPath
, &strSysPath
, false);
1053 if (error
== osl_File_E_None
)
1054 error
= osl_getSystemPathFromFileURL_(strDestPath
, &strSysDestPath
, false);
1056 if (error
== osl_File_E_None
)
1058 LPCWSTR src
= o3tl::toW(rtl_uString_getStr(strSysPath
));
1059 LPCWSTR dst
= o3tl::toW(rtl_uString_getStr(strSysDestPath
));
1061 if (CopyFileW(src
, dst
, FALSE
))
1062 error
= osl_File_E_None
;
1064 error
= oslTranslateFileError(GetLastError());
1068 rtl_uString_release(strSysPath
);
1070 rtl_uString_release(strSysDestPath
);
1075 oslFileError SAL_CALL
osl_moveFile(rtl_uString
* strPath
, rtl_uString
*strDestPath
)
1077 rtl_uString
*strSysPath
= nullptr, *strSysDestPath
= nullptr;
1078 oslFileError error
= osl_getSystemPathFromFileURL_(strPath
, &strSysPath
, false);
1080 if (error
== osl_File_E_None
)
1081 error
= osl_getSystemPathFromFileURL_(strDestPath
, &strSysDestPath
, false);
1083 if (error
== osl_File_E_None
)
1085 LPCWSTR src
= o3tl::toW(rtl_uString_getStr(strSysPath
));
1086 LPCWSTR dst
= o3tl::toW(rtl_uString_getStr(strSysDestPath
));
1088 if (MoveFileExW(src
, dst
, MOVEFILE_COPY_ALLOWED
| MOVEFILE_WRITE_THROUGH
| MOVEFILE_REPLACE_EXISTING
))
1089 error
= osl_File_E_None
;
1091 error
= oslTranslateFileError(GetLastError());
1095 rtl_uString_release(strSysPath
);
1097 rtl_uString_release(strSysDestPath
);
1102 oslFileError SAL_CALL
osl_replaceFile(rtl_uString
* strPath
, rtl_uString
* strDestPath
)
1104 rtl_uString
*strSysPath
= nullptr, *strSysDestPath
= nullptr;
1105 oslFileError error
= osl_getSystemPathFromFileURL_(strPath
, &strSysPath
, false);
1107 if (error
== osl_File_E_None
)
1108 error
= osl_getSystemPathFromFileURL_(strDestPath
, &strSysDestPath
, false);
1110 if (error
== osl_File_E_None
)
1112 LPCWSTR src
= o3tl::toW(rtl_uString_getStr(strSysPath
));
1113 LPCWSTR dst
= o3tl::toW(rtl_uString_getStr(strSysDestPath
));
1115 if (!ReplaceFileW(dst
, src
, nullptr,
1116 REPLACEFILE_WRITE_THROUGH
| REPLACEFILE_IGNORE_MERGE_ERRORS
1117 | REPLACEFILE_IGNORE_ACL_ERRORS
,
1120 DWORD dwError
= GetLastError();
1121 if (dwError
== ERROR_FILE_NOT_FOUND
) // no strDestPath file?
1122 error
= osl_moveFile(strPath
, strDestPath
);
1124 error
= oslTranslateFileError(dwError
);
1129 rtl_uString_release(strSysPath
);
1131 rtl_uString_release(strSysDestPath
);
1136 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */