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 .
23 #include "systools/win32/uwinapi.h"
25 #include "osl/file.hxx"
28 #include "file_error.h"
30 #include "osl/diagnose.h"
31 #include "rtl/alloc.h"
32 #include "rtl/byteseq.h"
33 #include "rtl/ustring.hxx"
46 #ifdef max /* conflict w/ std::numeric_limits<T>::max() */
53 //##################################################################
54 // File handle implementation
55 //##################################################################
56 struct FileHandle_Impl
58 CRITICAL_SECTION m_mutex
;
65 STATE_SEEKABLE
= 1, /* open() sets, iff regular file */
66 STATE_READABLE
= 2, /* open() sets, read() requires */
67 STATE_WRITEABLE
= 4, /* open() sets, write() requires */
68 STATE_MODIFIED
= 8 /* write() sets, flush() resets */
72 sal_uInt64 m_size
; /* file size */
73 LONGLONG m_offset
; /* physical offset from begin of file */
74 LONGLONG m_filepos
; /* logical offset from begin of file */
76 LONGLONG m_bufptr
; /* buffer offset from begin of file */
77 SIZE_T m_buflen
; /* buffer filled [0, m_bufsiz - 1] */
82 explicit FileHandle_Impl (HANDLE hFile
);
85 static void* operator new(size_t n
);
86 static void operator delete(void * p
, size_t);
87 static SIZE_T
getpagesize();
89 sal_uInt64
getPos() const;
90 oslFileError
setPos (sal_uInt64 uPos
);
92 sal_uInt64
getSize() const;
93 oslFileError
setSize (sal_uInt64 uPos
);
98 DWORD nBytesRequested
,
99 sal_uInt64
* pBytesRead
);
101 oslFileError
writeAt (
103 void const * pBuffer
,
105 sal_uInt64
* pBytesWritten
);
107 oslFileError
readFileAt (
110 sal_uInt64 uBytesRequested
,
111 sal_uInt64
* pBytesRead
);
113 oslFileError
writeFileAt (
115 void const * pBuffer
,
116 sal_uInt64 uBytesToWrite
,
117 sal_uInt64
* pBytesWritten
);
119 oslFileError
readLineAt (
121 sal_Sequence
** ppSequence
,
122 sal_uInt64
* pBytesRead
);
124 oslFileError
writeSequence_Impl (
125 sal_Sequence
** ppSequence
,
127 const void * pBuffer
,
130 oslFileError
syncFile();
132 /** Buffer cache / allocator.
136 rtl_cache_type
* m_cache
;
139 Allocator (Allocator
const &);
140 Allocator
& operator= (Allocator
const &);
143 static Allocator
& get();
145 void allocate (sal_uInt8
** ppBuffer
, SIZE_T
* pnSize
);
146 void deallocate (sal_uInt8
* pBuffer
);
157 LPCRITICAL_SECTION m_mutex
;
160 explicit Guard(LPCRITICAL_SECTION pMutex
);
165 FileHandle_Impl::Allocator
&
166 FileHandle_Impl::Allocator::get()
168 static Allocator g_aBufferAllocator
;
169 return g_aBufferAllocator
;
172 FileHandle_Impl::Allocator::Allocator()
176 SIZE_T
const pagesize
= FileHandle_Impl::getpagesize();
177 m_cache
= rtl_cache_create (
178 "osl_file_buffer_cache", pagesize
, 0, 0, 0, 0, 0, 0, 0);
183 FileHandle_Impl::Allocator::~Allocator()
185 rtl_cache_destroy(m_cache
), m_cache
= 0;
188 void FileHandle_Impl::Allocator::allocate (sal_uInt8
** ppBuffer
, SIZE_T
* pnSize
)
190 OSL_PRECOND((0 != ppBuffer
) && (0 != pnSize
), "FileHandle_Impl::Allocator::allocate(): contract violation");
191 *ppBuffer
= static_cast< sal_uInt8
* >(rtl_cache_alloc(m_cache
)), *pnSize
= m_bufsiz
;
194 void FileHandle_Impl::Allocator::deallocate (sal_uInt8
* pBuffer
)
197 rtl_cache_free (m_cache
, pBuffer
);
200 FileHandle_Impl::Guard::Guard(LPCRITICAL_SECTION pMutex
)
203 OSL_PRECOND (m_mutex
!= 0, "FileHandle_Impl::Guard::Guard(): null pointer.");
204 ::EnterCriticalSection (m_mutex
);
206 FileHandle_Impl::Guard::~Guard()
208 OSL_PRECOND (m_mutex
!= 0, "FileHandle_Impl::Guard::~Guard(): null pointer.");
209 ::LeaveCriticalSection (m_mutex
);
212 FileHandle_Impl::FileHandle_Impl(HANDLE hFile
)
214 m_state (STATE_READABLE
| STATE_WRITEABLE
),
223 ::InitializeCriticalSection (&m_mutex
);
224 Allocator::get().allocate (&m_buffer
, &m_bufsiz
);
226 memset (m_buffer
, 0, m_bufsiz
);
229 FileHandle_Impl::~FileHandle_Impl()
231 Allocator::get().deallocate (m_buffer
), m_buffer
= 0;
232 ::DeleteCriticalSection (&m_mutex
);
235 void * FileHandle_Impl::operator new(size_t n
)
237 return rtl_allocateMemory(n
);
240 void FileHandle_Impl::operator delete(void * p
, size_t)
245 SIZE_T
FileHandle_Impl::getpagesize()
248 ::GetSystemInfo (&info
);
249 return sal::static_int_cast
< SIZE_T
>(info
.dwPageSize
);
252 sal_uInt64
FileHandle_Impl::getPos() const
254 return sal::static_int_cast
< sal_uInt64
>(m_filepos
);
257 oslFileError
FileHandle_Impl::setPos (sal_uInt64 uPos
)
259 m_filepos
= sal::static_int_cast
< LONGLONG
>(uPos
);
260 return osl_File_E_None
;
263 sal_uInt64
FileHandle_Impl::getSize() const
265 LONGLONG bufend
= std::max((LONGLONG
)(0), m_bufptr
) + m_buflen
;
266 return std::max(m_size
, sal::static_int_cast
< sal_uInt64
>(bufend
));
269 oslFileError
FileHandle_Impl::setSize (sal_uInt64 uSize
)
271 LARGE_INTEGER nDstPos
; nDstPos
.QuadPart
= sal::static_int_cast
< LONGLONG
>(uSize
);
272 if (!::SetFilePointerEx(m_hFile
, nDstPos
, 0, FILE_BEGIN
))
273 return oslTranslateFileError( GetLastError() );
275 if (!::SetEndOfFile(m_hFile
))
276 return oslTranslateFileError( GetLastError() );
279 nDstPos
.QuadPart
= m_offset
;
280 if (!::SetFilePointerEx(m_hFile
, nDstPos
, 0, FILE_BEGIN
))
281 return oslTranslateFileError( GetLastError() );
283 return osl_File_E_None
;
286 oslFileError
FileHandle_Impl::readAt (
289 DWORD nBytesRequested
,
290 sal_uInt64
* pBytesRead
)
292 OSL_PRECOND(m_state
& STATE_SEEKABLE
, "FileHandle_Impl::readAt(): not seekable");
293 if (!(m_state
& STATE_SEEKABLE
))
294 return osl_File_E_SPIPE
;
296 OSL_PRECOND(m_state
& STATE_READABLE
, "FileHandle_Impl::readAt(): not readable");
297 if (!(m_state
& STATE_READABLE
))
298 return osl_File_E_BADF
;
300 if (nOffset
!= m_offset
)
302 LARGE_INTEGER liOffset
; liOffset
.QuadPart
= nOffset
;
303 if (!::SetFilePointerEx(m_hFile
, liOffset
, 0, FILE_BEGIN
))
304 return oslTranslateFileError( GetLastError() );
309 if (!::ReadFile(m_hFile
, pBuffer
, nBytesRequested
, &dwDone
, 0))
310 return oslTranslateFileError( GetLastError() );
313 *pBytesRead
= dwDone
;
314 return osl_File_E_None
;
317 oslFileError
FileHandle_Impl::writeAt (
319 void const * pBuffer
,
321 sal_uInt64
* pBytesWritten
)
323 OSL_PRECOND(m_state
& STATE_SEEKABLE
, "FileHandle_Impl::writeAt(): not seekable");
324 if (!(m_state
& STATE_SEEKABLE
))
325 return osl_File_E_SPIPE
;
327 OSL_PRECOND(m_state
& STATE_WRITEABLE
, "FileHandle_Impl::writeAt(): not writeable");
328 if (!(m_state
& STATE_WRITEABLE
))
329 return osl_File_E_BADF
;
331 if (nOffset
!= m_offset
)
333 LARGE_INTEGER liOffset
; liOffset
.QuadPart
= nOffset
;
334 if (!::SetFilePointerEx (m_hFile
, liOffset
, 0, FILE_BEGIN
))
335 return oslTranslateFileError( GetLastError() );
340 if (!::WriteFile(m_hFile
, pBuffer
, nBytesToWrite
, &dwDone
, 0))
341 return oslTranslateFileError( GetLastError() );
344 m_size
= std::max(m_size
, sal::static_int_cast
< sal_uInt64
>(m_offset
));
346 *pBytesWritten
= dwDone
;
347 return osl_File_E_None
;
350 oslFileError
FileHandle_Impl::readFileAt (
353 sal_uInt64 uBytesRequested
,
354 sal_uInt64
* pBytesRead
)
356 static sal_uInt64
const g_limit_dword
= std::numeric_limits
< DWORD
>::max();
357 if (g_limit_dword
< uBytesRequested
)
358 return osl_File_E_OVERFLOW
;
359 DWORD nBytesRequested
= sal::static_int_cast
< DWORD
>(uBytesRequested
);
361 if (0 == (m_state
& STATE_SEEKABLE
))
363 // not seekable (pipe)
365 if (!::ReadFile(m_hFile
, pBuffer
, nBytesRequested
, &dwDone
, 0))
366 return oslTranslateFileError( GetLastError() );
367 *pBytesRead
= dwDone
;
368 return osl_File_E_None
;
370 else if (0 == m_buffer
)
373 return readAt (nOffset
, pBuffer
, nBytesRequested
, pBytesRead
);
377 sal_uInt8
* buffer
= static_cast< sal_uInt8
* >(pBuffer
);
378 for (*pBytesRead
= 0; nBytesRequested
> 0; )
380 LONGLONG
const bufptr
= (nOffset
/ m_bufsiz
) * m_bufsiz
;
381 SIZE_T
const bufpos
= (nOffset
% m_bufsiz
);
383 if (bufptr
!= m_bufptr
)
385 // flush current buffer
386 oslFileError result
= syncFile();
387 if (result
!= osl_File_E_None
)
389 m_bufptr
= -1, m_buflen
= 0;
391 if (nBytesRequested
>= m_bufsiz
)
393 // buffer too small, read through from file
394 sal_uInt64 uDone
= 0;
395 result
= readAt (nOffset
, &(buffer
[*pBytesRead
]), nBytesRequested
, &uDone
);
396 if (result
!= osl_File_E_None
)
399 nBytesRequested
-= sal::static_int_cast
< DWORD
>(uDone
), *pBytesRead
+= uDone
;
400 return osl_File_E_None
;
403 // update buffer (pointer)
404 sal_uInt64 uDone
= 0;
405 result
= readAt (bufptr
, m_buffer
, m_bufsiz
, &uDone
);
406 if (result
!= osl_File_E_None
)
408 m_bufptr
= bufptr
, m_buflen
= sal::static_int_cast
< SIZE_T
>(uDone
);
410 if (bufpos
>= m_buflen
)
413 return osl_File_E_None
;
416 SIZE_T
const bytes
= std::min(m_buflen
- bufpos
, (SIZE_T
) nBytesRequested
);
417 memcpy (&(buffer
[*pBytesRead
]), &(m_buffer
[bufpos
]), bytes
);
418 nBytesRequested
-= bytes
, *pBytesRead
+= bytes
, nOffset
+= bytes
;
420 return osl_File_E_None
;
424 oslFileError
FileHandle_Impl::writeFileAt (
426 void const * pBuffer
,
427 sal_uInt64 uBytesToWrite
,
428 sal_uInt64
* pBytesWritten
)
430 static sal_uInt64
const g_limit_dword
= std::numeric_limits
< DWORD
>::max();
431 if (g_limit_dword
< uBytesToWrite
)
432 return osl_File_E_OVERFLOW
;
433 DWORD nBytesToWrite
= sal::static_int_cast
< DWORD
>(uBytesToWrite
);
435 if (0 == (m_state
& STATE_SEEKABLE
))
437 // not seekable (pipe)
439 if (!::WriteFile(m_hFile
, pBuffer
, nBytesToWrite
, &dwDone
, 0))
440 return oslTranslateFileError( GetLastError() );
441 *pBytesWritten
= dwDone
;
442 return osl_File_E_None
;
444 else if (0 == m_buffer
)
447 return writeAt(nOffset
, pBuffer
, nBytesToWrite
, pBytesWritten
);
451 sal_uInt8
const * buffer
= static_cast< sal_uInt8
const* >(pBuffer
);
452 for (*pBytesWritten
= 0; nBytesToWrite
> 0; )
454 LONGLONG
const bufptr
= (nOffset
/ m_bufsiz
) * m_bufsiz
;
455 SIZE_T
const bufpos
= (nOffset
% m_bufsiz
);
456 if (bufptr
!= m_bufptr
)
458 // flush current buffer
459 oslFileError result
= syncFile();
460 if (result
!= osl_File_E_None
)
462 m_bufptr
= -1, m_buflen
= 0;
464 if (nBytesToWrite
>= m_bufsiz
)
466 // buffer too small, write through to file
467 sal_uInt64 uDone
= 0;
468 result
= writeAt (nOffset
, &(buffer
[*pBytesWritten
]), nBytesToWrite
, &uDone
);
469 if (result
!= osl_File_E_None
)
471 if (uDone
!= nBytesToWrite
)
472 return osl_File_E_IO
;
474 nBytesToWrite
-= sal::static_int_cast
< DWORD
>(uDone
), *pBytesWritten
+= uDone
;
475 return osl_File_E_None
;
478 // update buffer (pointer)
479 sal_uInt64 uDone
= 0;
480 result
= readAt (bufptr
, m_buffer
, m_bufsiz
, &uDone
);
481 if (result
!= osl_File_E_None
)
483 m_bufptr
= bufptr
, m_buflen
= sal::static_int_cast
< SIZE_T
>(uDone
);
486 SIZE_T
const bytes
= std::min(m_bufsiz
- bufpos
, (SIZE_T
) nBytesToWrite
);
487 memcpy (&(m_buffer
[bufpos
]), &(buffer
[*pBytesWritten
]), bytes
);
488 nBytesToWrite
-= bytes
, *pBytesWritten
+= bytes
, nOffset
+= bytes
;
490 m_buflen
= std::max(m_buflen
, bufpos
+ bytes
);
491 m_state
|= STATE_MODIFIED
;
493 return osl_File_E_None
;
497 oslFileError
FileHandle_Impl::readLineAt (
499 sal_Sequence
** ppSequence
,
500 sal_uInt64
* pBytesRead
)
502 oslFileError result
= osl_File_E_None
;
504 LONGLONG bufptr
= (nOffset
/ m_bufsiz
) * m_bufsiz
;
505 if (bufptr
!= m_bufptr
)
507 /* flush current buffer */
509 if (result
!= osl_File_E_None
)
512 /* update buffer (pointer) */
513 sal_uInt64 uDone
= 0;
514 result
= readAt (bufptr
, m_buffer
, m_bufsiz
, &uDone
);
515 if (result
!= osl_File_E_None
)
518 m_bufptr
= bufptr
, m_buflen
= sal::static_int_cast
< SIZE_T
>(uDone
);
521 static int const LINE_STATE_BEGIN
= 0;
522 static int const LINE_STATE_CR
= 1;
523 static int const LINE_STATE_LF
= 2;
525 SIZE_T bufpos
= sal::static_int_cast
< SIZE_T
>(nOffset
- m_bufptr
), curpos
= bufpos
, dstpos
= 0;
526 int state
= (bufpos
>= m_buflen
) ? LINE_STATE_LF
: LINE_STATE_BEGIN
;
528 for ( ; state
!= LINE_STATE_LF
; )
530 if (curpos
>= m_buflen
)
532 /* buffer examined */
533 if (0 < (curpos
- bufpos
))
535 /* flush buffer to sequence */
536 result
= writeSequence_Impl (
537 ppSequence
, &dstpos
, &(m_buffer
[bufpos
]), curpos
- bufpos
);
538 if (result
!= osl_File_E_None
)
540 *pBytesRead
+= curpos
- bufpos
, nOffset
+= curpos
- bufpos
;
543 bufptr
= nOffset
/ m_bufsiz
* m_bufsiz
;
544 if (bufptr
!= m_bufptr
)
546 /* update buffer (pointer) */
547 sal_uInt64 uDone
= 0;
548 result
= readAt (bufptr
, m_buffer
, m_bufsiz
, &uDone
);
549 if (result
!= osl_File_E_None
)
551 m_bufptr
= bufptr
, m_buflen
= sal::static_int_cast
< SIZE_T
>(uDone
);
554 bufpos
= sal::static_int_cast
< SIZE_T
>(nOffset
- m_bufptr
), curpos
= bufpos
;
555 if (bufpos
>= m_buflen
)
561 state
= LINE_STATE_LF
;
562 switch (m_buffer
[curpos
])
564 case 0x0A: /* CRLF */
565 /* eat current char */
568 default: /* single CR */
569 /* keep current char */
574 /* determine next state */
575 switch (m_buffer
[curpos
])
577 case 0x0A: /* single LF */
578 state
= LINE_STATE_LF
;
581 state
= LINE_STATE_CR
;
583 default: /* advance to next char */
587 if (state
!= LINE_STATE_BEGIN
)
589 /* store (and eat) the newline char */
590 m_buffer
[curpos
] = 0x0A, curpos
++;
592 /* flush buffer to sequence */
593 result
= writeSequence_Impl (
594 ppSequence
, &dstpos
, &(m_buffer
[bufpos
]), curpos
- bufpos
- 1);
595 if (result
!= osl_File_E_None
)
597 *pBytesRead
+= curpos
- bufpos
, nOffset
+= curpos
- bufpos
;
603 result
= writeSequence_Impl (ppSequence
, &dstpos
, 0, 0);
604 if (result
!= osl_File_E_None
)
607 return osl_File_E_None
;
608 if (bufpos
>= m_buflen
)
609 return osl_File_E_AGAIN
;
610 return osl_File_E_None
;
613 oslFileError
FileHandle_Impl::writeSequence_Impl (
614 sal_Sequence
** ppSequence
,
616 const void * pBuffer
,
619 sal_Int32 nElements
= *pnOffset
+ nBytes
;
622 /* construct sequence */
623 rtl_byte_sequence_constructNoDefault(ppSequence
, nElements
);
625 else if (nElements
!= (*ppSequence
)->nElements
)
627 /* resize sequence */
628 rtl_byte_sequence_realloc(ppSequence
, nElements
);
630 if (*ppSequence
!= 0)
633 memcpy(&((*ppSequence
)->elements
[*pnOffset
]), pBuffer
, nBytes
), *pnOffset
+= nBytes
;
635 return (*ppSequence
!= 0) ? osl_File_E_None
: osl_File_E_NOMEM
;
638 oslFileError
FileHandle_Impl::syncFile()
640 oslFileError result
= osl_File_E_None
;
641 if (m_state
& STATE_MODIFIED
)
643 sal_uInt64 uDone
= 0;
644 result
= writeAt (m_bufptr
, m_buffer
, m_buflen
, &uDone
);
645 if (result
!= osl_File_E_None
)
647 if (uDone
!= m_buflen
)
648 return osl_File_E_IO
;
649 m_state
&= ~STATE_MODIFIED
;
654 //##################################################################
655 // File I/O functions
656 //##################################################################
658 extern "C" oslFileHandle
659 SAL_CALL
osl_createFileHandleFromOSHandle (
663 if ( !IsValidHandle(hFile
) )
666 FileHandle_Impl
* pImpl
= new FileHandle_Impl(hFile
);
670 (void) ::CloseHandle(hFile
);
674 /* check for regular file */
675 if (FILE_TYPE_DISK
== GetFileType(hFile
))
678 pImpl
->m_state
|= FileHandle_Impl::STATE_SEEKABLE
;
680 /* init current size */
681 LARGE_INTEGER uSize
= { { 0, 0 } };
682 (void) ::GetFileSizeEx(hFile
, &uSize
);
683 pImpl
->m_size
= (sal::static_int_cast
<sal_uInt64
>(uSize
.HighPart
) << 32) + uSize
.LowPart
;
686 if (!(uFlags
& osl_File_OpenFlag_Read
))
687 pImpl
->m_state
&= ~FileHandle_Impl::STATE_READABLE
;
688 if (!(uFlags
& osl_File_OpenFlag_Write
))
689 pImpl
->m_state
&= ~FileHandle_Impl::STATE_WRITEABLE
;
692 (uFlags
& osl_File_OpenFlag_Read
) || (uFlags
& osl_File_OpenFlag_Write
),
693 "osl_createFileHandleFromOSHandle(): missing read/write access flags");
694 return (oslFileHandle
)(pImpl
);
697 //#############################################
699 SAL_CALL
osl_openFile(
700 rtl_uString
* strPath
,
701 oslFileHandle
* pHandle
,
704 rtl_uString
* strSysPath
= 0;
705 oslFileError result
= _osl_getSystemPathFromFileURL( strPath
, &strSysPath
, sal_False
);
706 if (result
!= osl_File_E_None
)
709 DWORD dwAccess
= GENERIC_READ
, dwShare
= FILE_SHARE_READ
, dwCreation
= 0, dwAttributes
= 0;
711 if ( uFlags
& osl_File_OpenFlag_Write
)
712 dwAccess
|= GENERIC_WRITE
;
714 dwShare
|= FILE_SHARE_WRITE
;
716 if ( uFlags
& osl_File_OpenFlag_NoLock
)
717 dwShare
|= FILE_SHARE_WRITE
;
719 if ( uFlags
& osl_File_OpenFlag_Create
)
720 dwCreation
|= CREATE_NEW
;
722 dwCreation
|= OPEN_EXISTING
;
724 HANDLE hFile
= CreateFileW(
725 reinterpret_cast<LPCWSTR
>(rtl_uString_getStr( strSysPath
)),
726 dwAccess
, dwShare
, NULL
, dwCreation
, dwAttributes
, NULL
);
728 // @@@ ERROR HANDLING @@@
729 if ( !IsValidHandle( hFile
) )
730 result
= oslTranslateFileError( GetLastError() );
732 *pHandle
= osl_createFileHandleFromOSHandle (hFile
, uFlags
| osl_File_OpenFlag_Read
);
734 rtl_uString_release( strSysPath
);
738 //#############################################
740 SAL_CALL
osl_syncFile(oslFileHandle Handle
)
742 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
743 if ((0 == pImpl
) || !IsValidHandle(pImpl
->m_hFile
))
744 return osl_File_E_INVAL
;
746 FileHandle_Impl::Guard
lock (&(pImpl
->m_mutex
));
748 oslFileError result
= pImpl
->syncFile();
749 if (result
!= osl_File_E_None
)
752 if (!FlushFileBuffers(pImpl
->m_hFile
))
753 return oslTranslateFileError(GetLastError());
755 return osl_File_E_None
;
758 //#############################################
760 SAL_CALL
osl_getFileOSHandle(
761 oslFileHandle Handle
,
762 sal_IntPtr
*piFileHandle
)
764 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
766 if (0 == pImpl
|| !IsValidHandle(pImpl
->m_hFile
))
767 return osl_File_E_INVAL
;
769 *piFileHandle
= (sal_IntPtr
) pImpl
->m_hFile
;
771 return osl_File_E_None
;
774 //#############################################
776 SAL_CALL
osl_closeFile(oslFileHandle Handle
)
778 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
779 if ((0 == pImpl
) || !IsValidHandle(pImpl
->m_hFile
))
780 return osl_File_E_INVAL
;
782 ::EnterCriticalSection (&(pImpl
->m_mutex
));
784 oslFileError result
= pImpl
->syncFile();
785 if (result
!= osl_File_E_None
)
787 /* ignore double failure */
788 (void)::CloseHandle(pImpl
->m_hFile
);
790 else if (!::CloseHandle(pImpl
->m_hFile
))
792 /* translate error code */
793 result
= oslTranslateFileError( GetLastError() );
796 ::LeaveCriticalSection (&(pImpl
->m_mutex
));
801 //#############################################
803 SAL_CALL
osl_mapFile(
804 oslFileHandle Handle
,
814 explicit FileMapping (HANDLE hMap
)
820 (void)::CloseHandle(m_handle
);
824 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
825 if ((0 == pImpl
) || !IsValidHandle(pImpl
->m_hFile
) || (0 == ppAddr
))
826 return osl_File_E_INVAL
;
829 static SIZE_T
const nLimit
= std::numeric_limits
< SIZE_T
>::max();
830 if (uLength
> nLimit
)
831 return osl_File_E_OVERFLOW
;
832 SIZE_T
const nLength
= sal::static_int_cast
< SIZE_T
>(uLength
);
834 FileMapping
aMap( ::CreateFileMapping (pImpl
->m_hFile
, NULL
, SEC_COMMIT
| PAGE_READONLY
, 0, 0, NULL
) );
835 if (!IsValidHandle(aMap
.m_handle
))
836 return oslTranslateFileError( GetLastError() );
838 DWORD
const dwOffsetHi
= sal::static_int_cast
<DWORD
>(uOffset
>> 32);
839 DWORD
const dwOffsetLo
= sal::static_int_cast
<DWORD
>(uOffset
& 0xFFFFFFFF);
841 *ppAddr
= ::MapViewOfFile( aMap
.m_handle
, FILE_MAP_READ
, dwOffsetHi
, dwOffsetLo
, nLength
);
843 return oslTranslateFileError( GetLastError() );
845 if (uFlags
& osl_File_MapFlag_RandomAccess
)
847 // Determine memory pagesize.
849 ::GetSystemInfo( &info
);
850 DWORD
const dwPageSize
= info
.dwPageSize
;
853 * Pagein, touching first byte of each memory page.
854 * Note: volatile disables optimizing the loop away.
856 BYTE
* pData (reinterpret_cast<BYTE
*>(*ppAddr
));
857 SIZE_T
nSize (nLength
);
860 while (nSize
> dwPageSize
)
871 return osl_File_E_None
;
874 //#############################################
876 SAL_CALL
osl_unmapFile(void* pAddr
, sal_uInt64
/* uLength */)
879 return osl_File_E_INVAL
;
881 if (!::UnmapViewOfFile (pAddr
))
882 return oslTranslateFileError( GetLastError() );
884 return osl_File_E_None
;
887 //#############################################
889 SAL_CALL
osl_unmapMappedFile(oslFileHandle
/* Handle */, void* pAddr
, sal_uInt64 uLength
)
891 return osl_unmapFile( pAddr
, uLength
);
894 //#############################################
896 SAL_CALL
osl_readLine(
897 oslFileHandle Handle
,
898 sal_Sequence
** ppSequence
)
900 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
901 if ((0 == pImpl
) || !IsValidHandle(pImpl
->m_hFile
) || (0 == ppSequence
))
902 return osl_File_E_INVAL
;
903 sal_uInt64 uBytesRead
= 0;
905 // read at current filepos; filepos += uBytesRead;
906 FileHandle_Impl::Guard
lock (&(pImpl
->m_mutex
));
907 oslFileError result
= pImpl
->readLineAt (
908 pImpl
->m_filepos
, ppSequence
, &uBytesRead
);
909 if (result
== osl_File_E_None
)
910 pImpl
->m_filepos
+= uBytesRead
;
914 //#############################################
916 SAL_CALL
osl_readFile(
917 oslFileHandle Handle
,
919 sal_uInt64 uBytesRequested
,
920 sal_uInt64
* pBytesRead
)
922 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
923 if ((0 == pImpl
) || !IsValidHandle(pImpl
->m_hFile
) || (0 == pBuffer
) || (0 == pBytesRead
))
924 return osl_File_E_INVAL
;
926 // read at current filepos; filepos += *pBytesRead;
927 FileHandle_Impl::Guard
lock (&(pImpl
->m_mutex
));
928 oslFileError result
= pImpl
->readFileAt (
929 pImpl
->m_filepos
, pBuffer
, uBytesRequested
, pBytesRead
);
930 if (result
== osl_File_E_None
)
931 pImpl
->m_filepos
+= *pBytesRead
;
935 //#############################################
937 SAL_CALL
osl_writeFile(
938 oslFileHandle Handle
,
939 const void * pBuffer
,
940 sal_uInt64 uBytesToWrite
,
941 sal_uInt64
* pBytesWritten
)
943 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
945 if ((0 == pImpl
) || !IsValidHandle(pImpl
->m_hFile
) || (0 == pBuffer
) || (0 == pBytesWritten
))
946 return osl_File_E_INVAL
;
948 // write at current filepos; filepos += *pBytesWritten;
949 FileHandle_Impl::Guard
lock (&(pImpl
->m_mutex
));
950 oslFileError result
= pImpl
->writeFileAt (
951 pImpl
->m_filepos
, pBuffer
, uBytesToWrite
, pBytesWritten
);
952 if (result
== osl_File_E_None
)
953 pImpl
->m_filepos
+= *pBytesWritten
;
957 //#############################################
959 SAL_CALL
osl_readFileAt(
960 oslFileHandle Handle
,
963 sal_uInt64 uBytesRequested
,
964 sal_uInt64
* pBytesRead
)
966 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
968 if ((0 == pImpl
) || !IsValidHandle(pImpl
->m_hFile
) || (0 == pBuffer
) || (0 == pBytesRead
))
969 return osl_File_E_INVAL
;
970 if (0 == (pImpl
->m_state
& FileHandle_Impl::STATE_SEEKABLE
))
971 return osl_File_E_SPIPE
;
973 static sal_uInt64
const g_limit_longlong
= std::numeric_limits
< LONGLONG
>::max();
974 if (g_limit_longlong
< uOffset
)
975 return osl_File_E_OVERFLOW
;
976 LONGLONG
const nOffset
= sal::static_int_cast
< LONGLONG
>(uOffset
);
978 // read at specified fileptr
979 FileHandle_Impl::Guard
lock (&(pImpl
->m_mutex
));
980 return pImpl
->readFileAt (nOffset
, pBuffer
, uBytesRequested
, pBytesRead
);
983 //#############################################
985 SAL_CALL
osl_writeFileAt(
986 oslFileHandle Handle
,
989 sal_uInt64 uBytesToWrite
,
990 sal_uInt64
* pBytesWritten
)
992 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
994 if ((0 == pImpl
) || !IsValidHandle(pImpl
->m_hFile
) || (0 == pBuffer
) || (0 == pBytesWritten
))
995 return osl_File_E_INVAL
;
996 if (0 == (pImpl
->m_state
& FileHandle_Impl::STATE_SEEKABLE
))
997 return osl_File_E_SPIPE
;
999 static sal_uInt64
const g_limit_longlong
= std::numeric_limits
< LONGLONG
>::max();
1000 if (g_limit_longlong
< uOffset
)
1001 return osl_File_E_OVERFLOW
;
1002 LONGLONG
const nOffset
= sal::static_int_cast
< LONGLONG
>(uOffset
);
1004 // write at specified fileptr
1005 FileHandle_Impl::Guard
lock (&(pImpl
->m_mutex
));
1006 return pImpl
->writeFileAt (nOffset
, pBuffer
, uBytesToWrite
, pBytesWritten
);
1009 //#############################################
1011 SAL_CALL
osl_isEndOfFile (oslFileHandle Handle
, sal_Bool
*pIsEOF
)
1013 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1015 if ((0 == pImpl
) || !IsValidHandle(pImpl
->m_hFile
) || (0 == pIsEOF
))
1016 return osl_File_E_INVAL
;
1018 FileHandle_Impl::Guard
lock (&(pImpl
->m_mutex
));
1019 *pIsEOF
= (pImpl
->getPos() == pImpl
->getSize());
1020 return osl_File_E_None
;
1023 //#############################################
1025 SAL_CALL
osl_getFilePos(oslFileHandle Handle
, sal_uInt64
*pPos
)
1027 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1028 if ((0 == pImpl
) || !IsValidHandle(pImpl
->m_hFile
) || (0 == pPos
))
1029 return osl_File_E_INVAL
;
1031 FileHandle_Impl::Guard
lock (&(pImpl
->m_mutex
));
1032 *pPos
= pImpl
->getPos();
1033 return osl_File_E_None
;
1036 //#############################################
1038 SAL_CALL
osl_setFilePos(oslFileHandle Handle
, sal_uInt32 uHow
, sal_Int64 uOffset
)
1040 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1041 if ((0 == pImpl
) || !IsValidHandle(pImpl
->m_hFile
))
1042 return osl_File_E_INVAL
;
1044 static sal_Int64
const g_limit_longlong
= std::numeric_limits
< LONGLONG
>::max();
1045 if (g_limit_longlong
< uOffset
)
1046 return osl_File_E_OVERFLOW
;
1047 LONGLONG nPos
= 0, nOffset
= sal::static_int_cast
< LONGLONG
>(uOffset
);
1049 FileHandle_Impl::Guard
lock (&(pImpl
->m_mutex
));
1052 case osl_Pos_Absolut
:
1054 return osl_File_E_INVAL
;
1057 case osl_Pos_Current
:
1058 nPos
= sal::static_int_cast
< LONGLONG
>(pImpl
->getPos());
1059 if ((0 > nOffset
) && (-1*nOffset
> nPos
))
1060 return osl_File_E_INVAL
;
1061 if (g_limit_longlong
< nPos
+ nOffset
)
1062 return osl_File_E_OVERFLOW
;
1066 nPos
= sal::static_int_cast
< LONGLONG
>(pImpl
->getSize());
1067 if ((0 > nOffset
) && (-1*nOffset
> nPos
))
1068 return osl_File_E_INVAL
;
1069 if (g_limit_longlong
< nPos
+ nOffset
)
1070 return osl_File_E_OVERFLOW
;
1074 return osl_File_E_INVAL
;
1077 return pImpl
->setPos (nPos
+ nOffset
);
1080 //#############################################
1082 SAL_CALL
osl_getFileSize (oslFileHandle Handle
, sal_uInt64
*pSize
)
1084 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1086 if ((0 == pImpl
) || !IsValidHandle(pImpl
->m_hFile
) || (0 == pSize
))
1087 return osl_File_E_INVAL
;
1089 FileHandle_Impl::Guard
lock (&(pImpl
->m_mutex
));
1090 *pSize
= pImpl
->getSize();
1091 return osl_File_E_None
;
1094 //#############################################
1096 SAL_CALL
osl_setFileSize (oslFileHandle Handle
, sal_uInt64 uSize
)
1098 FileHandle_Impl
* pImpl
= static_cast<FileHandle_Impl
*>(Handle
);
1100 if ((0 == pImpl
) || !IsValidHandle(pImpl
->m_hFile
))
1101 return osl_File_E_INVAL
;
1102 if (0 == (pImpl
->m_state
& FileHandle_Impl::STATE_WRITEABLE
))
1103 return osl_File_E_BADF
;
1105 static sal_uInt64
const g_limit_longlong
= std::numeric_limits
< LONGLONG
>::max();
1106 if (g_limit_longlong
< uSize
)
1107 return osl_File_E_OVERFLOW
;
1109 FileHandle_Impl::Guard
lock (&(pImpl
->m_mutex
));
1110 oslFileError result
= pImpl
->syncFile();
1111 if (result
!= osl_File_E_None
)
1113 pImpl
->m_bufptr
= -1, pImpl
->m_buflen
= 0;
1115 return pImpl
->setSize (uSize
);
1118 //##################################################################
1119 // File handling functions
1120 //##################################################################
1122 //#############################################
1123 oslFileError SAL_CALL
osl_removeFile( rtl_uString
* strPath
)
1125 rtl_uString
*strSysPath
= NULL
;
1126 oslFileError error
= _osl_getSystemPathFromFileURL( strPath
, &strSysPath
, sal_False
);
1128 if ( osl_File_E_None
== error
)
1130 if ( DeleteFile( reinterpret_cast<LPCTSTR
>(rtl_uString_getStr( strSysPath
)) ) )
1131 error
= osl_File_E_None
;
1133 error
= oslTranslateFileError( GetLastError() );
1135 rtl_uString_release( strSysPath
);
1140 //#############################################
1141 oslFileError SAL_CALL
osl_copyFile( rtl_uString
* strPath
, rtl_uString
*strDestPath
)
1143 rtl_uString
*strSysPath
= NULL
, *strSysDestPath
= NULL
;
1144 oslFileError error
= _osl_getSystemPathFromFileURL( strPath
, &strSysPath
, sal_False
);
1146 if ( osl_File_E_None
== error
)
1147 error
= _osl_getSystemPathFromFileURL( strDestPath
, &strSysDestPath
, sal_False
);
1149 if ( osl_File_E_None
== error
)
1151 LPCTSTR src
= reinterpret_cast<LPCTSTR
>(rtl_uString_getStr( strSysPath
));
1152 LPCTSTR dst
= reinterpret_cast<LPCTSTR
>(rtl_uString_getStr( strSysDestPath
));
1154 if ( CopyFile( src
, dst
, FALSE
) )
1155 error
= osl_File_E_None
;
1157 error
= oslTranslateFileError( GetLastError() );
1161 rtl_uString_release( strSysPath
);
1162 if ( strSysDestPath
)
1163 rtl_uString_release( strSysDestPath
);
1168 //#############################################
1169 oslFileError SAL_CALL
osl_moveFile( rtl_uString
* strPath
, rtl_uString
*strDestPath
)
1171 rtl_uString
*strSysPath
= NULL
, *strSysDestPath
= NULL
;
1172 oslFileError error
= _osl_getSystemPathFromFileURL( strPath
, &strSysPath
, sal_False
);
1174 if ( osl_File_E_None
== error
)
1175 error
= _osl_getSystemPathFromFileURL( strDestPath
, &strSysDestPath
, sal_False
);
1177 if ( osl_File_E_None
== error
)
1179 LPCTSTR src
= reinterpret_cast<LPCTSTR
>(rtl_uString_getStr( strSysPath
));
1180 LPCTSTR dst
= reinterpret_cast<LPCTSTR
>(rtl_uString_getStr( strSysDestPath
));
1182 if ( MoveFileEx( src
, dst
, MOVEFILE_COPY_ALLOWED
| MOVEFILE_WRITE_THROUGH
| MOVEFILE_REPLACE_EXISTING
) )
1183 error
= osl_File_E_None
;
1185 error
= oslTranslateFileError( GetLastError() );
1189 rtl_uString_release( strSysPath
);
1190 if ( strSysDestPath
)
1191 rtl_uString_release( strSysDestPath
);
1196 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */