merge the formfield patch from ooo-build
[ooovba.git] / sal / osl / w32 / file.cxx
blob763fddd682bf469a301c40e56f1c0ca672a70a3c
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: file.cxx,v $
10 * $Revision: 1.0 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sal.hxx"
34 #define UNICODE
35 #define _UNICODE
36 #define _WIN32_WINNT 0x0500
37 #include "systools/win32/uwinapi.h"
39 #include "osl/file.hxx"
41 #include "file_url.h"
42 #include "file_error.h"
44 #include "osl/diagnose.h"
45 #include "rtl/alloc.h"
46 #include "rtl/byteseq.h"
47 #include "rtl/ustring.hxx"
49 #include <stdio.h>
50 #include <tchar.h>
52 #ifdef __MINGW32__
53 #include <wchar.h>
54 #include <ctype.h>
55 #endif
57 #include <algorithm>
58 #include <limits>
60 #ifdef max /* conflict w/ std::numeric_limits<T>::max() */
61 #undef max
62 #endif
63 #ifdef min
64 #undef min
65 #endif
67 //##################################################################
68 // File handle implementation
69 //##################################################################
70 struct FileHandle_Impl
72 HANDLE m_hFile;
74 /** State
76 enum StateBits
78 STATE_SEEKABLE = 1, /* open() sets, iff regular file */
79 STATE_READABLE = 2, /* open() sets, read() requires */
80 STATE_WRITEABLE = 4, /* open() sets, write() requires */
81 STATE_MODIFIED = 8 /* write() sets, flush() resets */
83 int m_state;
85 sal_uInt64 m_size; /* file size */
86 LONGLONG m_offset; /* physical offset from begin of file */
87 LONGLONG m_filepos; /* logical offset from begin of file */
89 LONGLONG m_bufptr; /* buffer offset from begin of file */
90 SIZE_T m_buflen; /* buffer filled [0, m_bufsiz - 1] */
92 SIZE_T m_bufsiz;
93 sal_uInt8 * m_buffer;
95 explicit FileHandle_Impl (HANDLE hFile);
96 ~FileHandle_Impl();
98 static void* operator new(size_t n);
99 static void operator delete(void * p, size_t);
100 static SIZE_T getpagesize();
102 sal_uInt64 getPos() const;
103 oslFileError setPos (sal_uInt64 uPos);
105 sal_uInt64 getSize() const;
106 oslFileError setSize (sal_uInt64 uPos);
108 oslFileError readAt (
109 LONGLONG nOffset,
110 void * pBuffer,
111 DWORD nBytesRequested,
112 sal_uInt64 * pBytesRead);
114 oslFileError writeAt (
115 LONGLONG nOffset,
116 void const * pBuffer,
117 DWORD nBytesToWrite,
118 sal_uInt64 * pBytesWritten);
120 oslFileError readFileAt (
121 LONGLONG nOffset,
122 void * pBuffer,
123 sal_uInt64 uBytesRequested,
124 sal_uInt64 * pBytesRead);
126 oslFileError writeFileAt (
127 LONGLONG nOffset,
128 void const * pBuffer,
129 sal_uInt64 uBytesToWrite,
130 sal_uInt64 * pBytesWritten);
132 oslFileError readLineAt (
133 LONGLONG nOffset,
134 sal_Sequence ** ppSequence,
135 sal_uInt64 * pBytesRead);
137 oslFileError writeSequence_Impl (
138 sal_Sequence ** ppSequence,
139 SIZE_T * pnOffset,
140 const void * pBuffer,
141 SIZE_T nBytes);
143 oslFileError syncFile();
145 /** Buffer cache / allocator.
147 class Allocator
149 rtl_cache_type * m_cache;
150 SIZE_T m_bufsiz;
152 Allocator (Allocator const &);
153 Allocator & operator= (Allocator const &);
155 public:
156 static Allocator & get();
158 void allocate (sal_uInt8 ** ppBuffer, SIZE_T * pnSize);
159 void deallocate (sal_uInt8 * pBuffer);
161 protected:
162 Allocator();
163 ~Allocator();
167 FileHandle_Impl::Allocator &
168 FileHandle_Impl::Allocator::get()
170 static Allocator g_aBufferAllocator;
171 return g_aBufferAllocator;
174 FileHandle_Impl::Allocator::Allocator()
175 : m_cache (0),
176 m_bufsiz (0)
178 SIZE_T const pagesize = FileHandle_Impl::getpagesize();
179 m_cache = rtl_cache_create (
180 "osl_file_buffer_cache", pagesize, 0, 0, 0, 0, 0, 0, 0);
181 if (0 != m_cache)
182 m_bufsiz = pagesize;
185 FileHandle_Impl::Allocator::~Allocator()
187 rtl_cache_destroy(m_cache), m_cache = 0;
190 void FileHandle_Impl::Allocator::allocate (sal_uInt8 ** ppBuffer, SIZE_T * pnSize)
192 OSL_PRECOND((0 != ppBuffer) && (0 != pnSize), "FileHandle_Impl::Allocator::allocate(): contract violation");
193 *ppBuffer = static_cast< sal_uInt8* >(rtl_cache_alloc(m_cache)), *pnSize = m_bufsiz;
196 void FileHandle_Impl::Allocator::deallocate (sal_uInt8 * pBuffer)
198 if (0 != pBuffer)
199 rtl_cache_free (m_cache, pBuffer);
202 FileHandle_Impl::FileHandle_Impl(HANDLE hFile)
203 : m_hFile (hFile),
204 m_state (STATE_READABLE | STATE_WRITEABLE),
205 m_size (0),
206 m_offset (0),
207 m_filepos (0),
208 m_bufptr (-1),
209 m_buflen (0),
210 m_bufsiz (0),
211 m_buffer (0)
213 Allocator::get().allocate (&m_buffer, &m_bufsiz);
214 if (m_buffer != 0)
215 memset (m_buffer, 0, m_bufsiz);
218 FileHandle_Impl::~FileHandle_Impl()
220 Allocator::get().deallocate (m_buffer), m_buffer = 0;
223 void * FileHandle_Impl::operator new(size_t n)
225 return rtl_allocateMemory(n);
228 void FileHandle_Impl::operator delete(void * p, size_t)
230 rtl_freeMemory(p);
233 SIZE_T FileHandle_Impl::getpagesize()
235 SYSTEM_INFO info;
236 ::GetSystemInfo (&info);
237 return sal::static_int_cast< SIZE_T >(info.dwPageSize);
240 sal_uInt64 FileHandle_Impl::getPos() const
242 return sal::static_int_cast< sal_uInt64 >(m_filepos);
245 oslFileError FileHandle_Impl::setPos (sal_uInt64 uPos)
247 m_filepos = sal::static_int_cast< LONGLONG >(uPos);
248 return osl_File_E_None;
251 sal_uInt64 FileHandle_Impl::getSize() const
253 LONGLONG bufend = std::max((LONGLONG)(0), m_bufptr) + m_buflen;
254 return std::max(m_size, sal::static_int_cast< sal_uInt64 >(bufend));
257 oslFileError FileHandle_Impl::setSize (sal_uInt64 uSize)
259 LARGE_INTEGER nDstPos; nDstPos.QuadPart = sal::static_int_cast< LONGLONG >(uSize);
260 if (!::SetFilePointerEx(m_hFile, nDstPos, 0, FILE_BEGIN))
261 return oslTranslateFileError( GetLastError() );
263 if (!::SetEndOfFile(m_hFile))
264 return oslTranslateFileError( GetLastError() );
265 m_size = uSize;
267 nDstPos.QuadPart = m_offset;
268 if (!::SetFilePointerEx(m_hFile, nDstPos, 0, FILE_BEGIN))
269 return oslTranslateFileError( GetLastError() );
271 return osl_File_E_None;
274 oslFileError FileHandle_Impl::readAt (
275 LONGLONG nOffset,
276 void * pBuffer,
277 DWORD nBytesRequested,
278 sal_uInt64 * pBytesRead)
280 OSL_PRECOND(m_state & STATE_SEEKABLE, "FileHandle_Impl::readAt(): not seekable");
281 if (!(m_state & STATE_SEEKABLE))
282 return osl_File_E_SPIPE;
284 OSL_PRECOND(m_state & STATE_READABLE, "FileHandle_Impl::readAt(): not readable");
285 if (!(m_state & STATE_READABLE))
286 return osl_File_E_BADF;
288 if (nOffset != m_offset)
290 LARGE_INTEGER liOffset; liOffset.QuadPart = nOffset;
291 if (!::SetFilePointerEx(m_hFile, liOffset, 0, FILE_BEGIN))
292 return oslTranslateFileError( GetLastError() );
293 m_offset = nOffset;
296 DWORD dwDone = 0;
297 if (!::ReadFile(m_hFile, pBuffer, nBytesRequested, &dwDone, 0))
298 return oslTranslateFileError( GetLastError() );
299 m_offset += dwDone;
301 *pBytesRead = dwDone;
302 return osl_File_E_None;
305 oslFileError FileHandle_Impl::writeAt (
306 LONGLONG nOffset,
307 void const * pBuffer,
308 DWORD nBytesToWrite,
309 sal_uInt64 * pBytesWritten)
311 OSL_PRECOND(m_state & STATE_SEEKABLE, "FileHandle_Impl::writeAt(): not seekable");
312 if (!(m_state & STATE_SEEKABLE))
313 return osl_File_E_SPIPE;
315 OSL_PRECOND(m_state & STATE_WRITEABLE, "FileHandle_Impl::writeAt(): not writeable");
316 if (!(m_state & STATE_WRITEABLE))
317 return osl_File_E_BADF;
319 if (nOffset != m_offset)
321 LARGE_INTEGER liOffset; liOffset.QuadPart = nOffset;
322 if (!::SetFilePointerEx (m_hFile, liOffset, 0, FILE_BEGIN))
323 return oslTranslateFileError( GetLastError() );
324 m_offset = nOffset;
327 DWORD dwDone = 0;
328 if (!::WriteFile(m_hFile, pBuffer, nBytesToWrite, &dwDone, 0))
329 return oslTranslateFileError( GetLastError() );
330 m_offset += dwDone;
332 m_size = std::max(m_size, sal::static_int_cast< sal_uInt64 >(m_offset));
334 *pBytesWritten = dwDone;
335 return osl_File_E_None;
338 oslFileError FileHandle_Impl::readFileAt (
339 LONGLONG nOffset,
340 void * pBuffer,
341 sal_uInt64 uBytesRequested,
342 sal_uInt64 * pBytesRead)
344 static sal_uInt64 const g_limit_dword = std::numeric_limits< DWORD >::max();
345 if (g_limit_dword < uBytesRequested)
346 return osl_File_E_OVERFLOW;
347 DWORD nBytesRequested = sal::static_int_cast< DWORD >(uBytesRequested);
349 if (0 == (m_state & STATE_SEEKABLE))
351 // not seekable (pipe)
352 DWORD dwDone = 0;
353 if (!::ReadFile(m_hFile, pBuffer, nBytesRequested, &dwDone, 0))
354 return oslTranslateFileError( GetLastError() );
355 *pBytesRead = dwDone;
356 return osl_File_E_None;
358 else if (0 == m_buffer)
360 // not buffered
361 return readAt (nOffset, pBuffer, nBytesRequested, pBytesRead);
363 else
365 sal_uInt8 * buffer = static_cast< sal_uInt8* >(pBuffer);
366 for (*pBytesRead = 0; nBytesRequested > 0; )
368 LONGLONG const bufptr = (nOffset / m_bufsiz) * m_bufsiz;
369 SIZE_T const bufpos = (nOffset % m_bufsiz);
371 if (bufptr != m_bufptr)
373 // flush current buffer
374 oslFileError result = syncFile();
375 if (result != osl_File_E_None)
376 return (result);
378 if (nBytesRequested >= m_bufsiz)
380 // buffer too small, read through from file
381 sal_uInt64 uDone = 0;
382 result = readAt (nOffset, &(buffer[*pBytesRead]), nBytesRequested, &uDone);
383 if (result != osl_File_E_None)
384 return (result);
386 nBytesRequested -= sal::static_int_cast< DWORD >(uDone), *pBytesRead += uDone;
387 return osl_File_E_None;
390 // update buffer (pointer)
391 sal_uInt64 uDone = 0;
392 result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
393 if (result != osl_File_E_None)
394 return (result);
395 m_bufptr = bufptr, m_buflen = sal::static_int_cast< SIZE_T >(uDone);
397 if (bufpos >= m_buflen)
399 // end of file
400 return osl_File_E_None;
403 SIZE_T const bytes = std::min(m_buflen - bufpos, nBytesRequested);
404 memcpy (&(buffer[*pBytesRead]), &(m_buffer[bufpos]), bytes);
405 nBytesRequested -= bytes, *pBytesRead += bytes, nOffset += bytes;
407 return osl_File_E_None;
411 oslFileError FileHandle_Impl::writeFileAt (
412 LONGLONG nOffset,
413 void const * pBuffer,
414 sal_uInt64 uBytesToWrite,
415 sal_uInt64 * pBytesWritten)
417 static sal_uInt64 const g_limit_dword = std::numeric_limits< DWORD >::max();
418 if (g_limit_dword < uBytesToWrite)
419 return osl_File_E_OVERFLOW;
420 DWORD nBytesToWrite = sal::static_int_cast< DWORD >(uBytesToWrite);
422 if (0 == (m_state & STATE_SEEKABLE))
424 // not seekable (pipe)
425 DWORD dwDone = 0;
426 if (!::WriteFile(m_hFile, pBuffer, nBytesToWrite, &dwDone, 0))
427 return oslTranslateFileError( GetLastError() );
428 *pBytesWritten = dwDone;
429 return osl_File_E_None;
431 else if (0 == m_buffer)
433 // not buffered
434 return writeAt(nOffset, pBuffer, nBytesToWrite, pBytesWritten);
436 else
438 sal_uInt8 const * buffer = static_cast< sal_uInt8 const* >(pBuffer);
439 for (*pBytesWritten = 0; nBytesToWrite > 0; )
441 LONGLONG const bufptr = (nOffset / m_bufsiz) * m_bufsiz;
442 SIZE_T const bufpos = (nOffset % m_bufsiz);
443 if (bufptr != m_bufptr)
445 // flush current buffer
446 oslFileError result = syncFile();
447 if (result != osl_File_E_None)
448 return (result);
450 if (nBytesToWrite >= m_bufsiz)
452 // buffer too small, write through to file
453 sal_uInt64 uDone = 0;
454 result = writeAt (nOffset, &(buffer[*pBytesWritten]), nBytesToWrite, &uDone);
455 if (result != osl_File_E_None)
456 return (result);
457 if (uDone != nBytesToWrite)
458 return osl_File_E_IO;
460 nBytesToWrite -= sal::static_int_cast< DWORD >(uDone), *pBytesWritten += uDone;
461 return osl_File_E_None;
464 // update buffer (pointer)
465 sal_uInt64 uDone = 0;
466 result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
467 if (result != osl_File_E_None)
468 return (result);
469 m_bufptr = bufptr, m_buflen = sal::static_int_cast< SIZE_T >(uDone);
472 SIZE_T const bytes = std::min(m_bufsiz - bufpos, nBytesToWrite);
473 memcpy (&(m_buffer[bufpos]), &(buffer[*pBytesWritten]), bytes);
474 nBytesToWrite -= bytes, *pBytesWritten += bytes, nOffset += bytes;
476 m_buflen = std::max(m_buflen, bufpos + bytes);
477 m_state |= STATE_MODIFIED;
479 return osl_File_E_None;
483 oslFileError FileHandle_Impl::readLineAt (
484 LONGLONG nOffset,
485 sal_Sequence ** ppSequence,
486 sal_uInt64 * pBytesRead)
488 oslFileError result = osl_File_E_None;
490 LONGLONG bufptr = (nOffset / m_bufsiz) * m_bufsiz;
491 if (bufptr != m_bufptr)
493 /* flush current buffer */
494 result = syncFile();
495 if (result != osl_File_E_None)
496 return (result);
498 /* update buffer (pointer) */
499 sal_uInt64 uDone = 0;
500 result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
501 if (result != osl_File_E_None)
502 return (result);
504 m_bufptr = bufptr, m_buflen = sal::static_int_cast< SIZE_T >(uDone);
507 static int const LINE_STATE_BEGIN = 0;
508 static int const LINE_STATE_CR = 1;
509 static int const LINE_STATE_LF = 2;
511 SIZE_T bufpos = sal::static_int_cast< SIZE_T >(nOffset - m_bufptr), curpos = bufpos, dstpos = 0;
512 int state = (bufpos >= m_buflen) ? LINE_STATE_LF : LINE_STATE_BEGIN;
514 for ( ; state != LINE_STATE_LF; )
516 if (curpos >= m_buflen)
518 /* buffer examined */
519 if (0 < (curpos - bufpos))
521 /* flush buffer to sequence */
522 result = writeSequence_Impl (
523 ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos);
524 if (result != osl_File_E_None)
525 return (result);
526 *pBytesRead += curpos - bufpos, nOffset += curpos - bufpos;
529 bufptr = nOffset / m_bufsiz * m_bufsiz;
530 if (bufptr != m_bufptr)
532 /* update buffer (pointer) */
533 sal_uInt64 uDone = 0;
534 result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
535 if (result != osl_File_E_None)
536 return (result);
537 m_bufptr = bufptr, m_buflen = sal::static_int_cast< SIZE_T >(uDone);
540 bufpos = sal::static_int_cast< SIZE_T >(nOffset - m_bufptr), curpos = bufpos;
541 if (bufpos >= m_buflen)
542 break;
544 switch (state)
546 case LINE_STATE_CR:
547 state = LINE_STATE_LF;
548 switch (m_buffer[curpos])
550 case 0x0A: /* CRLF */
551 /* eat current char */
552 curpos++;
553 break;
554 default: /* single CR */
555 /* keep current char */
556 break;
558 break;
559 default:
560 /* determine next state */
561 switch (m_buffer[curpos])
563 case 0x0A: /* single LF */
564 state = LINE_STATE_LF;
565 break;
566 case 0x0D: /* CR */
567 state = LINE_STATE_CR;
568 break;
569 default: /* advance to next char */
570 curpos++;
571 break;
573 if (state != LINE_STATE_BEGIN)
575 /* store (and eat) the newline char */
576 m_buffer[curpos] = 0x0A, curpos++;
578 /* flush buffer to sequence */
579 result = writeSequence_Impl (
580 ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos - 1);
581 if (result != osl_File_E_None)
582 return (result);
583 *pBytesRead += curpos - bufpos, nOffset += curpos - bufpos;
585 break;
589 result = writeSequence_Impl (ppSequence, &dstpos, 0, 0);
590 if (result != osl_File_E_None)
591 return (result);
592 if (0 < dstpos)
593 return osl_File_E_None;
594 if (bufpos >= m_buflen)
595 return osl_File_E_AGAIN;
596 return osl_File_E_None;
599 oslFileError FileHandle_Impl::writeSequence_Impl (
600 sal_Sequence ** ppSequence,
601 SIZE_T * pnOffset,
602 const void * pBuffer,
603 SIZE_T nBytes)
605 sal_Int32 nElements = *pnOffset + nBytes;
606 if (!*ppSequence)
608 /* construct sequence */
609 rtl_byte_sequence_constructNoDefault(ppSequence, nElements);
611 else if (nElements != (*ppSequence)->nElements)
613 /* resize sequence */
614 rtl_byte_sequence_realloc(ppSequence, nElements);
616 if (*ppSequence != 0)
618 /* fill sequence */
619 memcpy(&((*ppSequence)->elements[*pnOffset]), pBuffer, nBytes), *pnOffset += nBytes;
621 return (*ppSequence != 0) ? osl_File_E_None : osl_File_E_NOMEM;
624 oslFileError FileHandle_Impl::syncFile()
626 oslFileError result = osl_File_E_None;
627 if (m_state & STATE_MODIFIED)
629 sal_uInt64 uDone = 0;
630 result = writeAt (m_bufptr, m_buffer, m_buflen, &uDone);
631 if (result != osl_File_E_None)
632 return (result);
633 if (uDone != m_buflen)
634 return osl_File_E_IO;
635 m_state &= ~STATE_MODIFIED;
637 return (result);
640 //##################################################################
641 // File I/O functions
642 //##################################################################
644 extern "C" oslFileHandle
645 SAL_CALL osl_createFileHandleFromOSHandle (
646 HANDLE hFile,
647 sal_uInt32 uFlags)
649 if ( !IsValidHandle(hFile) )
650 return 0; // EINVAL
652 FileHandle_Impl * pImpl = new FileHandle_Impl(hFile);
653 if (pImpl == 0)
655 // cleanup and fail
656 (void) ::CloseHandle(hFile);
657 return 0; // ENOMEM
660 /* check for regular file */
661 if (FILE_TYPE_DISK == GetFileType(hFile))
663 /* mark seekable */
664 pImpl->m_state |= FileHandle_Impl::STATE_SEEKABLE;
666 /* init current size */
667 LARGE_INTEGER uSize = { 0, 0 };
668 (void) ::GetFileSizeEx(hFile, &uSize);
669 pImpl->m_size = (sal::static_int_cast<sal_uInt64>(uSize.HighPart) << 32) + uSize.LowPart;
672 if (!(uFlags & osl_File_OpenFlag_Read))
673 pImpl->m_state &= ~FileHandle_Impl::STATE_READABLE;
674 if (!(uFlags & osl_File_OpenFlag_Write))
675 pImpl->m_state &= ~FileHandle_Impl::STATE_WRITEABLE;
677 OSL_POSTCOND(
678 (uFlags & osl_File_OpenFlag_Read) || (uFlags & osl_File_OpenFlag_Write),
679 "osl_createFileHandleFromOSHandle(): missing read/write access flags");
680 return (oslFileHandle)(pImpl);
683 //#############################################
684 oslFileError
685 SAL_CALL osl_openFile(
686 rtl_uString * strPath,
687 oslFileHandle * pHandle,
688 sal_uInt32 uFlags )
690 rtl_uString * strSysPath = 0;
691 oslFileError result = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
692 if (result != osl_File_E_None)
693 return (result);
695 DWORD dwAccess = GENERIC_READ, dwShare = FILE_SHARE_READ, dwCreation = 0, dwAttributes = 0;
697 if ( uFlags & osl_File_OpenFlag_Write )
698 dwAccess |= GENERIC_WRITE;
699 else
700 dwShare |= FILE_SHARE_WRITE;
702 if ( uFlags & osl_File_OpenFlag_NoLock )
703 dwShare |= FILE_SHARE_WRITE;
705 if ( uFlags & osl_File_OpenFlag_Create )
706 dwCreation |= CREATE_NEW;
707 else
708 dwCreation |= OPEN_EXISTING;
710 HANDLE hFile = CreateFileW(
711 reinterpret_cast<LPCWSTR>(rtl_uString_getStr( strSysPath )),
712 dwAccess, dwShare, NULL, dwCreation, dwAttributes, NULL );
714 // @@@ ERROR HANDLING @@@
715 if ( !IsValidHandle( hFile ) )
716 result = oslTranslateFileError( GetLastError() );
718 *pHandle = osl_createFileHandleFromOSHandle (hFile, uFlags | osl_File_OpenFlag_Read);
720 rtl_uString_release( strSysPath );
721 return (result);
724 //#############################################
725 oslFileError
726 SAL_CALL osl_syncFile(oslFileHandle Handle)
728 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
729 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile))
730 return osl_File_E_INVAL;
732 oslFileError result = pImpl->syncFile();
733 if (result != osl_File_E_None)
734 return result;
736 if (!FlushFileBuffers(pImpl->m_hFile))
737 return oslTranslateFileError(GetLastError());
739 return osl_File_E_None;
742 //#############################################
743 oslFileError
744 SAL_CALL osl_closeFile(oslFileHandle Handle)
746 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
747 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile))
748 return osl_File_E_INVAL;
750 oslFileError result = pImpl->syncFile();
751 if (result != osl_File_E_None)
753 /* ignore double failure */
754 (void)::CloseHandle(pImpl->m_hFile);
756 else if (!::CloseHandle(pImpl->m_hFile))
758 /* translate error code */
759 result = oslTranslateFileError( GetLastError() );
762 delete pImpl;
763 return (result);
766 //#############################################
767 oslFileError
768 SAL_CALL osl_mapFile(
769 oslFileHandle Handle,
770 void** ppAddr,
771 sal_uInt64 uLength,
772 sal_uInt64 uOffset,
773 sal_uInt32 uFlags)
775 struct FileMapping
777 HANDLE m_handle;
779 explicit FileMapping (HANDLE hMap)
780 : m_handle (hMap)
783 ~FileMapping()
785 (void)::CloseHandle(m_handle);
789 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
790 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == ppAddr))
791 return osl_File_E_INVAL;
792 *ppAddr = 0;
794 static SIZE_T const nLimit = std::numeric_limits< SIZE_T >::max();
795 if (uLength > nLimit)
796 return osl_File_E_OVERFLOW;
797 SIZE_T const nLength = sal::static_int_cast< SIZE_T >(uLength);
799 OSVERSIONINFO osinfo;
800 osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
801 (void)::GetVersionEx(&osinfo);
803 if (VER_PLATFORM_WIN32_NT != osinfo.dwPlatformId)
804 return osl_File_E_NOSYS; // Unsupported
806 FileMapping aMap( ::CreateFileMapping (pImpl->m_hFile, NULL, SEC_COMMIT | PAGE_READONLY, 0, 0, NULL) );
807 if (!IsValidHandle(aMap.m_handle))
808 return oslTranslateFileError( GetLastError() );
810 DWORD const dwOffsetHi = sal::static_int_cast<DWORD>(uOffset >> 32);
811 DWORD const dwOffsetLo = sal::static_int_cast<DWORD>(uOffset & 0xFFFFFFFF);
813 *ppAddr = ::MapViewOfFile( aMap.m_handle, FILE_MAP_READ, dwOffsetHi, dwOffsetLo, nLength );
814 if (0 == *ppAddr)
815 return oslTranslateFileError( GetLastError() );
817 if (uFlags & osl_File_MapFlag_RandomAccess)
819 // Determine memory pagesize.
820 SYSTEM_INFO info;
821 ::GetSystemInfo( &info );
822 DWORD const dwPageSize = info.dwPageSize;
825 * Pagein, touching first byte of each memory page.
826 * Note: volatile disables optimizing the loop away.
828 BYTE * pData (reinterpret_cast<BYTE*>(*ppAddr));
829 SIZE_T nSize (nLength);
831 volatile BYTE c = 0;
832 while (nSize > dwPageSize)
834 c ^= pData[0];
835 pData += dwPageSize;
836 nSize -= dwPageSize;
838 if (nSize > 0)
840 c ^= pData[0];
841 pData += nSize;
842 nSize -= nSize;
845 return osl_File_E_None;
848 //#############################################
849 oslFileError
850 SAL_CALL osl_unmapFile(void* pAddr, sal_uInt64 /* uLength */)
852 if (0 == pAddr)
853 return osl_File_E_INVAL;
855 if (!::UnmapViewOfFile (pAddr))
856 return oslTranslateFileError( GetLastError() );
858 return osl_File_E_None;
861 //#############################################
862 oslFileError
863 SAL_CALL osl_readLine(
864 oslFileHandle Handle,
865 sal_Sequence ** ppSequence)
867 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
868 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == ppSequence))
869 return osl_File_E_INVAL;
870 sal_uInt64 uBytesRead = 0;
872 // read at current filepos; filepos += uBytesRead;
873 oslFileError result = pImpl->readLineAt (
874 pImpl->m_filepos, ppSequence, &uBytesRead);
875 if (result == osl_File_E_None)
876 pImpl->m_filepos += uBytesRead;
877 return (result);
880 //#############################################
881 oslFileError
882 SAL_CALL osl_readFile(
883 oslFileHandle Handle,
884 void * pBuffer,
885 sal_uInt64 uBytesRequested,
886 sal_uInt64 * pBytesRead)
888 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
889 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pBuffer) || (0 == pBytesRead))
890 return osl_File_E_INVAL;
892 // read at current filepos; filepos += *pBytesRead;
893 oslFileError result = pImpl->readFileAt (
894 pImpl->m_filepos, pBuffer, uBytesRequested, pBytesRead);
895 if (result == osl_File_E_None)
896 pImpl->m_filepos += *pBytesRead;
897 return (result);
900 //#############################################
901 oslFileError
902 SAL_CALL osl_writeFile(
903 oslFileHandle Handle,
904 const void * pBuffer,
905 sal_uInt64 uBytesToWrite,
906 sal_uInt64 * pBytesWritten )
908 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
910 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pBuffer) || (0 == pBytesWritten))
911 return osl_File_E_INVAL;
913 // write at current filepos; filepos += *pBytesWritten;
914 oslFileError result = pImpl->writeFileAt (
915 pImpl->m_filepos, pBuffer, uBytesToWrite, pBytesWritten);
916 if (result == osl_File_E_None)
917 pImpl->m_filepos += *pBytesWritten;
918 return (result);
921 //#############################################
922 oslFileError
923 SAL_CALL osl_readFileAt(
924 oslFileHandle Handle,
925 sal_uInt64 uOffset,
926 void* pBuffer,
927 sal_uInt64 uBytesRequested,
928 sal_uInt64* pBytesRead)
930 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
932 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pBuffer) || (0 == pBytesRead))
933 return osl_File_E_INVAL;
934 if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE))
935 return osl_File_E_SPIPE;
937 static sal_uInt64 const g_limit_longlong = std::numeric_limits< LONGLONG >::max();
938 if (g_limit_longlong < uOffset)
939 return osl_File_E_OVERFLOW;
940 LONGLONG const nOffset = sal::static_int_cast< LONGLONG >(uOffset);
942 // read at specified fileptr
943 return pImpl->readFileAt (nOffset, pBuffer, uBytesRequested, pBytesRead);
946 //#############################################
947 oslFileError
948 SAL_CALL osl_writeFileAt(
949 oslFileHandle Handle,
950 sal_uInt64 uOffset,
951 const void* pBuffer,
952 sal_uInt64 uBytesToWrite,
953 sal_uInt64* pBytesWritten)
955 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
957 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pBuffer) || (0 == pBytesWritten))
958 return osl_File_E_INVAL;
959 if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE))
960 return osl_File_E_SPIPE;
962 static sal_uInt64 const g_limit_longlong = std::numeric_limits< LONGLONG >::max();
963 if (g_limit_longlong < uOffset)
964 return osl_File_E_OVERFLOW;
965 LONGLONG const nOffset = sal::static_int_cast< LONGLONG >(uOffset);
967 // write at specified fileptr
968 return pImpl->writeFileAt (nOffset, pBuffer, uBytesToWrite, pBytesWritten);
971 //#############################################
972 oslFileError
973 SAL_CALL osl_isEndOfFile (oslFileHandle Handle, sal_Bool *pIsEOF)
975 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
977 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pIsEOF))
978 return osl_File_E_INVAL;
980 *pIsEOF = (pImpl->getPos() == pImpl->getSize());
981 return osl_File_E_None;
984 //#############################################
985 oslFileError
986 SAL_CALL osl_getFilePos(oslFileHandle Handle, sal_uInt64 *pPos)
988 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
989 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pPos))
990 return osl_File_E_INVAL;
992 *pPos = pImpl->getPos();
993 return osl_File_E_None;
996 //#############################################
997 oslFileError
998 SAL_CALL osl_setFilePos(oslFileHandle Handle, sal_uInt32 uHow, sal_Int64 uOffset)
1000 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
1001 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile))
1002 return osl_File_E_INVAL;
1004 static sal_Int64 const g_limit_longlong = std::numeric_limits< LONGLONG >::max();
1005 if (g_limit_longlong < uOffset)
1006 return osl_File_E_OVERFLOW;
1007 LONGLONG nPos = 0, nOffset = sal::static_int_cast< LONGLONG >(uOffset);
1009 switch (uHow)
1011 case osl_Pos_Absolut:
1012 if (0 > nOffset)
1013 return osl_File_E_INVAL;
1014 break;
1016 case osl_Pos_Current:
1017 nPos = sal::static_int_cast< LONGLONG >(pImpl->getPos());
1018 if ((0 > nOffset) && (-1*nOffset > nPos))
1019 return osl_File_E_INVAL;
1020 if (g_limit_longlong < nPos + nOffset)
1021 return osl_File_E_OVERFLOW;
1022 break;
1024 case osl_Pos_End:
1025 nPos = sal::static_int_cast< LONGLONG >(pImpl->getSize());
1026 if ((0 > nOffset) && (-1*nOffset > nPos))
1027 return osl_File_E_INVAL;
1028 if (g_limit_longlong < nPos + nOffset)
1029 return osl_File_E_OVERFLOW;
1030 break;
1032 default:
1033 return osl_File_E_INVAL;
1036 return pImpl->setPos (nPos + nOffset);
1039 //#############################################
1040 oslFileError
1041 SAL_CALL osl_getFileSize (oslFileHandle Handle, sal_uInt64 *pSize)
1043 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
1045 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pSize))
1046 return osl_File_E_INVAL;
1048 *pSize = pImpl->getSize();
1049 return osl_File_E_None;
1052 //#############################################
1053 oslFileError
1054 SAL_CALL osl_setFileSize (oslFileHandle Handle, sal_uInt64 uSize)
1056 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
1058 if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile))
1059 return osl_File_E_INVAL;
1060 if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE))
1061 return osl_File_E_BADF;
1063 static sal_uInt64 const g_limit_longlong = std::numeric_limits< LONGLONG >::max();
1064 if (g_limit_longlong < uSize)
1065 return osl_File_E_OVERFLOW;
1067 oslFileError result = pImpl->syncFile();
1068 if (result != osl_File_E_None)
1069 return (result);
1070 pImpl->m_bufptr = -1, pImpl->m_buflen = 0;
1072 return pImpl->setSize (uSize);
1075 //##################################################################
1076 // File handling functions
1077 //##################################################################
1079 //#############################################
1080 oslFileError SAL_CALL osl_removeFile( rtl_uString* strPath )
1082 rtl_uString *strSysPath = NULL;
1083 oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
1085 if ( osl_File_E_None == error )
1087 if ( DeleteFile( reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath )) ) )
1088 error = osl_File_E_None;
1089 else
1090 error = oslTranslateFileError( GetLastError() );
1092 rtl_uString_release( strSysPath );
1094 return error;
1097 //#############################################
1098 #define osl_File_CopyRecursive 0x0001
1099 #define osl_File_CopyOverwrite 0x0002
1101 oslFileError SAL_CALL osl_copyFile( rtl_uString* strPath, rtl_uString *strDestPath )
1103 rtl_uString *strSysPath = NULL, *strSysDestPath = NULL;
1104 oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
1106 if ( osl_File_E_None == error )
1107 error = _osl_getSystemPathFromFileURL( strDestPath, &strSysDestPath, sal_False );
1109 if ( osl_File_E_None == error )
1111 LPCTSTR src = reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath ));
1112 LPCTSTR dst = reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysDestPath ));
1114 if ( CopyFile( src, dst, FALSE ) )
1115 error = osl_File_E_None;
1116 else
1117 error = oslTranslateFileError( GetLastError() );
1120 if ( strSysPath )
1121 rtl_uString_release( strSysPath );
1122 if ( strSysDestPath )
1123 rtl_uString_release( strSysDestPath );
1125 return error;
1128 //#############################################
1129 oslFileError SAL_CALL osl_moveFile( rtl_uString* strPath, rtl_uString *strDestPath )
1131 rtl_uString *strSysPath = NULL, *strSysDestPath = NULL;
1132 oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
1134 if ( osl_File_E_None == error )
1135 error = _osl_getSystemPathFromFileURL( strDestPath, &strSysDestPath, sal_False );
1137 if ( osl_File_E_None == error )
1139 LPCTSTR src = reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath ));
1140 LPCTSTR dst = reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysDestPath ));
1142 if ( MoveFileEx( src, dst, MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING ) )
1143 error = osl_File_E_None;
1144 else
1145 error = oslTranslateFileError( GetLastError() );
1148 if ( strSysPath )
1149 rtl_uString_release( strSysPath );
1150 if ( strSysDestPath )
1151 rtl_uString_release( strSysDestPath );
1153 return error;