Version 4.2.0.1, tag libreoffice-4.2.0.1
[LibreOffice.git] / sal / osl / w32 / file.cxx
blob30a4f550a1f559aeb9fd759f7f2396ae38a38de6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
21 #define UNICODE
22 #define _UNICODE
23 #include "systools/win32/uwinapi.h"
25 #include "osl/file.hxx"
27 #include "file_url.h"
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"
35 #include <stdio.h>
36 #include <tchar.h>
38 #ifdef __MINGW32__
39 #include <wchar.h>
40 #include <ctype.h>
41 #endif
43 #include <algorithm>
44 #include <limits>
46 #ifdef max /* conflict w/ std::numeric_limits<T>::max() */
47 #undef max
48 #endif
49 #ifdef min
50 #undef min
51 #endif
53 //##################################################################
54 // File handle implementation
55 //##################################################################
56 struct FileHandle_Impl
58 CRITICAL_SECTION m_mutex;
59 HANDLE m_hFile;
61 /** State
63 enum StateBits
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 */
70 int m_state;
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] */
79 SIZE_T m_bufsiz;
80 sal_uInt8 * m_buffer;
82 explicit FileHandle_Impl (HANDLE hFile);
83 ~FileHandle_Impl();
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);
95 oslFileError readAt (
96 LONGLONG nOffset,
97 void * pBuffer,
98 DWORD nBytesRequested,
99 sal_uInt64 * pBytesRead);
101 oslFileError writeAt (
102 LONGLONG nOffset,
103 void const * pBuffer,
104 DWORD nBytesToWrite,
105 sal_uInt64 * pBytesWritten);
107 oslFileError readFileAt (
108 LONGLONG nOffset,
109 void * pBuffer,
110 sal_uInt64 uBytesRequested,
111 sal_uInt64 * pBytesRead);
113 oslFileError writeFileAt (
114 LONGLONG nOffset,
115 void const * pBuffer,
116 sal_uInt64 uBytesToWrite,
117 sal_uInt64 * pBytesWritten);
119 oslFileError readLineAt (
120 LONGLONG nOffset,
121 sal_Sequence ** ppSequence,
122 sal_uInt64 * pBytesRead);
124 oslFileError writeSequence_Impl (
125 sal_Sequence ** ppSequence,
126 SIZE_T * pnOffset,
127 const void * pBuffer,
128 SIZE_T nBytes);
130 oslFileError syncFile();
132 /** Buffer cache / allocator.
134 class Allocator
136 rtl_cache_type * m_cache;
137 SIZE_T m_bufsiz;
139 Allocator (Allocator const &);
140 Allocator & operator= (Allocator const &);
142 public:
143 static Allocator & get();
145 void allocate (sal_uInt8 ** ppBuffer, SIZE_T * pnSize);
146 void deallocate (sal_uInt8 * pBuffer);
148 protected:
149 Allocator();
150 ~Allocator();
153 /** Guard.
155 class Guard
157 LPCRITICAL_SECTION m_mutex;
159 public:
160 explicit Guard(LPCRITICAL_SECTION pMutex);
161 ~Guard();
165 FileHandle_Impl::Allocator &
166 FileHandle_Impl::Allocator::get()
168 static Allocator g_aBufferAllocator;
169 return g_aBufferAllocator;
172 FileHandle_Impl::Allocator::Allocator()
173 : m_cache (0),
174 m_bufsiz (0)
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);
179 if (0 != m_cache)
180 m_bufsiz = pagesize;
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)
196 if (0 != pBuffer)
197 rtl_cache_free (m_cache, pBuffer);
200 FileHandle_Impl::Guard::Guard(LPCRITICAL_SECTION pMutex)
201 : m_mutex (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)
213 : m_hFile (hFile),
214 m_state (STATE_READABLE | STATE_WRITEABLE),
215 m_size (0),
216 m_offset (0),
217 m_filepos (0),
218 m_bufptr (-1),
219 m_buflen (0),
220 m_bufsiz (0),
221 m_buffer (0)
223 ::InitializeCriticalSection (&m_mutex);
224 Allocator::get().allocate (&m_buffer, &m_bufsiz);
225 if (m_buffer != 0)
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)
242 rtl_freeMemory(p);
245 SIZE_T FileHandle_Impl::getpagesize()
247 SYSTEM_INFO info;
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() );
277 m_size = uSize;
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 (
287 LONGLONG nOffset,
288 void * pBuffer,
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() );
305 m_offset = nOffset;
308 DWORD dwDone = 0;
309 if (!::ReadFile(m_hFile, pBuffer, nBytesRequested, &dwDone, 0))
310 return oslTranslateFileError( GetLastError() );
311 m_offset += dwDone;
313 *pBytesRead = dwDone;
314 return osl_File_E_None;
317 oslFileError FileHandle_Impl::writeAt (
318 LONGLONG nOffset,
319 void const * pBuffer,
320 DWORD nBytesToWrite,
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() );
336 m_offset = nOffset;
339 DWORD dwDone = 0;
340 if (!::WriteFile(m_hFile, pBuffer, nBytesToWrite, &dwDone, 0))
341 return oslTranslateFileError( GetLastError() );
342 m_offset += dwDone;
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 (
351 LONGLONG nOffset,
352 void * pBuffer,
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)
364 DWORD dwDone = 0;
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)
372 // not buffered
373 return readAt (nOffset, pBuffer, nBytesRequested, pBytesRead);
375 else
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)
388 return (result);
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)
397 return (result);
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)
407 return (result);
408 m_bufptr = bufptr, m_buflen = sal::static_int_cast< SIZE_T >(uDone);
410 if (bufpos >= m_buflen)
412 // end of file
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 (
425 LONGLONG nOffset,
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)
438 DWORD dwDone = 0;
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)
446 // not buffered
447 return writeAt(nOffset, pBuffer, nBytesToWrite, pBytesWritten);
449 else
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)
461 return (result);
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)
470 return (result);
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)
482 return (result);
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 (
498 LONGLONG nOffset,
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 */
508 result = syncFile();
509 if (result != osl_File_E_None)
510 return (result);
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)
516 return (result);
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)
539 return (result);
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)
550 return (result);
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)
556 break;
558 switch (state)
560 case LINE_STATE_CR:
561 state = LINE_STATE_LF;
562 switch (m_buffer[curpos])
564 case 0x0A: /* CRLF */
565 /* eat current char */
566 curpos++;
567 break;
568 default: /* single CR */
569 /* keep current char */
570 break;
572 break;
573 default:
574 /* determine next state */
575 switch (m_buffer[curpos])
577 case 0x0A: /* single LF */
578 state = LINE_STATE_LF;
579 break;
580 case 0x0D: /* CR */
581 state = LINE_STATE_CR;
582 break;
583 default: /* advance to next char */
584 curpos++;
585 break;
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)
596 return (result);
597 *pBytesRead += curpos - bufpos, nOffset += curpos - bufpos;
599 break;
603 result = writeSequence_Impl (ppSequence, &dstpos, 0, 0);
604 if (result != osl_File_E_None)
605 return (result);
606 if (0 < dstpos)
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,
615 SIZE_T * pnOffset,
616 const void * pBuffer,
617 SIZE_T nBytes)
619 sal_Int32 nElements = *pnOffset + nBytes;
620 if (!*ppSequence)
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)
632 /* fill sequence */
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)
646 return (result);
647 if (uDone != m_buflen)
648 return osl_File_E_IO;
649 m_state &= ~STATE_MODIFIED;
651 return (result);
654 //##################################################################
655 // File I/O functions
656 //##################################################################
658 extern "C" oslFileHandle
659 SAL_CALL osl_createFileHandleFromOSHandle (
660 HANDLE hFile,
661 sal_uInt32 uFlags)
663 if ( !IsValidHandle(hFile) )
664 return 0; // EINVAL
666 FileHandle_Impl * pImpl = new FileHandle_Impl(hFile);
667 if (pImpl == 0)
669 // cleanup and fail
670 (void) ::CloseHandle(hFile);
671 return 0; // ENOMEM
674 /* check for regular file */
675 if (FILE_TYPE_DISK == GetFileType(hFile))
677 /* mark seekable */
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;
691 OSL_POSTCOND(
692 (uFlags & osl_File_OpenFlag_Read) || (uFlags & osl_File_OpenFlag_Write),
693 "osl_createFileHandleFromOSHandle(): missing read/write access flags");
694 return (oslFileHandle)(pImpl);
697 //#############################################
698 oslFileError
699 SAL_CALL osl_openFile(
700 rtl_uString * strPath,
701 oslFileHandle * pHandle,
702 sal_uInt32 uFlags )
704 rtl_uString * strSysPath = 0;
705 oslFileError result = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
706 if (result != osl_File_E_None)
707 return (result);
709 DWORD dwAccess = GENERIC_READ, dwShare = FILE_SHARE_READ, dwCreation = 0, dwAttributes = 0;
711 if ( uFlags & osl_File_OpenFlag_Write )
712 dwAccess |= GENERIC_WRITE;
713 else
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;
721 else
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 );
735 return (result);
738 //#############################################
739 oslFileError
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)
750 return result;
752 if (!FlushFileBuffers(pImpl->m_hFile))
753 return oslTranslateFileError(GetLastError());
755 return osl_File_E_None;
758 //#############################################
759 oslFileError
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 //#############################################
775 oslFileError
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));
797 delete pImpl;
798 return (result);
801 //#############################################
802 oslFileError
803 SAL_CALL osl_mapFile(
804 oslFileHandle Handle,
805 void** ppAddr,
806 sal_uInt64 uLength,
807 sal_uInt64 uOffset,
808 sal_uInt32 uFlags)
810 struct FileMapping
812 HANDLE m_handle;
814 explicit FileMapping (HANDLE hMap)
815 : m_handle (hMap)
818 ~FileMapping()
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;
827 *ppAddr = 0;
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 );
842 if (0 == *ppAddr)
843 return oslTranslateFileError( GetLastError() );
845 if (uFlags & osl_File_MapFlag_RandomAccess)
847 // Determine memory pagesize.
848 SYSTEM_INFO info;
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);
859 volatile BYTE c = 0;
860 while (nSize > dwPageSize)
862 c ^= pData[0];
863 pData += dwPageSize;
864 nSize -= dwPageSize;
866 if (nSize > 0)
868 c ^= pData[0];
871 return osl_File_E_None;
874 //#############################################
875 oslFileError
876 SAL_CALL osl_unmapFile(void* pAddr, sal_uInt64 /* uLength */)
878 if (0 == pAddr)
879 return osl_File_E_INVAL;
881 if (!::UnmapViewOfFile (pAddr))
882 return oslTranslateFileError( GetLastError() );
884 return osl_File_E_None;
887 //#############################################
888 oslFileError
889 SAL_CALL osl_unmapMappedFile(oslFileHandle /* Handle */, void* pAddr, sal_uInt64 uLength)
891 return osl_unmapFile( pAddr, uLength );
894 //#############################################
895 oslFileError
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;
911 return (result);
914 //#############################################
915 oslFileError
916 SAL_CALL osl_readFile(
917 oslFileHandle Handle,
918 void * pBuffer,
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;
932 return (result);
935 //#############################################
936 oslFileError
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;
954 return (result);
957 //#############################################
958 oslFileError
959 SAL_CALL osl_readFileAt(
960 oslFileHandle Handle,
961 sal_uInt64 uOffset,
962 void* pBuffer,
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 //#############################################
984 oslFileError
985 SAL_CALL osl_writeFileAt(
986 oslFileHandle Handle,
987 sal_uInt64 uOffset,
988 const void* pBuffer,
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 //#############################################
1010 oslFileError
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 //#############################################
1024 oslFileError
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 //#############################################
1037 oslFileError
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));
1050 switch (uHow)
1052 case osl_Pos_Absolut:
1053 if (0 > nOffset)
1054 return osl_File_E_INVAL;
1055 break;
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;
1063 break;
1065 case osl_Pos_End:
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;
1071 break;
1073 default:
1074 return osl_File_E_INVAL;
1077 return pImpl->setPos (nPos + nOffset);
1080 //#############################################
1081 oslFileError
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 //#############################################
1095 oslFileError
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)
1112 return (result);
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;
1132 else
1133 error = oslTranslateFileError( GetLastError() );
1135 rtl_uString_release( strSysPath );
1137 return error;
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;
1156 else
1157 error = oslTranslateFileError( GetLastError() );
1160 if ( strSysPath )
1161 rtl_uString_release( strSysPath );
1162 if ( strSysDestPath )
1163 rtl_uString_release( strSysDestPath );
1165 return error;
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;
1184 else
1185 error = oslTranslateFileError( GetLastError() );
1188 if ( strSysPath )
1189 rtl_uString_release( strSysPath );
1190 if ( strSysDestPath )
1191 rtl_uString_release( strSysDestPath );
1193 return error;
1196 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */