416543e829
...introduced witha64db11b6c
"Add some non-public API to be used by SvFileStream" ande541105b45
"Use osl API to access files in the SvFileStream code" but subsequently identified as dead code withab02fa6552
"callcatcher: update list,"05a8216d03
"STAR_ENABLE_FILE_LOCKING was a secret," and1d3483ed27
"Remove some unused code from unusedcode.easy." Change-Id: I9c8584890270a87e58b8d8021080ffe54bc97b93
1156 lines
34 KiB
C++
1156 lines
34 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#define UNICODE
|
|
#define _UNICODE
|
|
#include "systools/win32/uwinapi.h"
|
|
|
|
#include "osl/file.hxx"
|
|
|
|
#include "file_url.h"
|
|
#include "file_error.h"
|
|
|
|
#include "osl/diagnose.h"
|
|
#include "rtl/alloc.h"
|
|
#include "rtl/byteseq.h"
|
|
#include "rtl/ustring.hxx"
|
|
|
|
#include <stdio.h>
|
|
#include <tchar.h>
|
|
|
|
#ifdef __MINGW32__
|
|
#include <wchar.h>
|
|
#include <ctype.h>
|
|
#endif
|
|
|
|
#include <algorithm>
|
|
#include <limits>
|
|
|
|
#ifdef max /* conflict w/ std::numeric_limits<T>::max() */
|
|
#undef max
|
|
#endif
|
|
#ifdef min
|
|
#undef min
|
|
#endif
|
|
|
|
// File handle implementation
|
|
|
|
struct FileHandle_Impl
|
|
{
|
|
CRITICAL_SECTION m_mutex;
|
|
HANDLE m_hFile;
|
|
|
|
/** State
|
|
*/
|
|
enum StateBits
|
|
{
|
|
STATE_SEEKABLE = 1, /* open() sets, iff regular file */
|
|
STATE_READABLE = 2, /* open() sets, read() requires */
|
|
STATE_WRITEABLE = 4, /* open() sets, write() requires */
|
|
STATE_MODIFIED = 8 /* write() sets, flush() resets */
|
|
};
|
|
int m_state;
|
|
|
|
sal_uInt64 m_size; /* file size */
|
|
LONGLONG m_offset; /* physical offset from begin of file */
|
|
LONGLONG m_filepos; /* logical offset from begin of file */
|
|
|
|
LONGLONG m_bufptr; /* buffer offset from begin of file */
|
|
SIZE_T m_buflen; /* buffer filled [0, m_bufsiz - 1] */
|
|
|
|
SIZE_T m_bufsiz;
|
|
sal_uInt8 * m_buffer;
|
|
|
|
explicit FileHandle_Impl (HANDLE hFile);
|
|
~FileHandle_Impl();
|
|
|
|
static void* operator new(size_t n);
|
|
static void operator delete(void * p, size_t);
|
|
static SIZE_T getpagesize();
|
|
|
|
sal_uInt64 getPos() const;
|
|
oslFileError setPos (sal_uInt64 uPos);
|
|
|
|
sal_uInt64 getSize() const;
|
|
oslFileError setSize (sal_uInt64 uPos);
|
|
|
|
oslFileError readAt (
|
|
LONGLONG nOffset,
|
|
void * pBuffer,
|
|
DWORD nBytesRequested,
|
|
sal_uInt64 * pBytesRead);
|
|
|
|
oslFileError writeAt (
|
|
LONGLONG nOffset,
|
|
void const * pBuffer,
|
|
DWORD nBytesToWrite,
|
|
sal_uInt64 * pBytesWritten);
|
|
|
|
oslFileError readFileAt (
|
|
LONGLONG nOffset,
|
|
void * pBuffer,
|
|
sal_uInt64 uBytesRequested,
|
|
sal_uInt64 * pBytesRead);
|
|
|
|
oslFileError writeFileAt (
|
|
LONGLONG nOffset,
|
|
void const * pBuffer,
|
|
sal_uInt64 uBytesToWrite,
|
|
sal_uInt64 * pBytesWritten);
|
|
|
|
oslFileError readLineAt (
|
|
LONGLONG nOffset,
|
|
sal_Sequence ** ppSequence,
|
|
sal_uInt64 * pBytesRead);
|
|
|
|
oslFileError writeSequence_Impl (
|
|
sal_Sequence ** ppSequence,
|
|
SIZE_T * pnOffset,
|
|
const void * pBuffer,
|
|
SIZE_T nBytes);
|
|
|
|
oslFileError syncFile();
|
|
|
|
/** Buffer cache / allocator.
|
|
*/
|
|
class Allocator
|
|
{
|
|
rtl_cache_type * m_cache;
|
|
SIZE_T m_bufsiz;
|
|
|
|
Allocator (Allocator const &);
|
|
Allocator & operator= (Allocator const &);
|
|
|
|
public:
|
|
static Allocator & get();
|
|
|
|
void allocate (sal_uInt8 ** ppBuffer, SIZE_T * pnSize);
|
|
void deallocate (sal_uInt8 * pBuffer);
|
|
|
|
protected:
|
|
Allocator();
|
|
~Allocator();
|
|
};
|
|
|
|
/** Guard.
|
|
*/
|
|
class Guard
|
|
{
|
|
LPCRITICAL_SECTION m_mutex;
|
|
|
|
public:
|
|
explicit Guard(LPCRITICAL_SECTION pMutex);
|
|
~Guard();
|
|
};
|
|
};
|
|
|
|
FileHandle_Impl::Allocator &
|
|
FileHandle_Impl::Allocator::get()
|
|
{
|
|
static Allocator g_aBufferAllocator;
|
|
return g_aBufferAllocator;
|
|
}
|
|
|
|
FileHandle_Impl::Allocator::Allocator()
|
|
: m_cache (0),
|
|
m_bufsiz (0)
|
|
{
|
|
SIZE_T const pagesize = FileHandle_Impl::getpagesize();
|
|
m_cache = rtl_cache_create (
|
|
"osl_file_buffer_cache", pagesize, 0, 0, 0, 0, 0, 0, 0);
|
|
if (0 != m_cache)
|
|
m_bufsiz = pagesize;
|
|
}
|
|
|
|
FileHandle_Impl::Allocator::~Allocator()
|
|
{
|
|
rtl_cache_destroy(m_cache), m_cache = 0;
|
|
}
|
|
|
|
void FileHandle_Impl::Allocator::allocate (sal_uInt8 ** ppBuffer, SIZE_T * pnSize)
|
|
{
|
|
OSL_PRECOND((0 != ppBuffer) && (0 != pnSize), "FileHandle_Impl::Allocator::allocate(): contract violation");
|
|
*ppBuffer = static_cast< sal_uInt8* >(rtl_cache_alloc(m_cache)), *pnSize = m_bufsiz;
|
|
}
|
|
|
|
void FileHandle_Impl::Allocator::deallocate (sal_uInt8 * pBuffer)
|
|
{
|
|
if (0 != pBuffer)
|
|
rtl_cache_free (m_cache, pBuffer);
|
|
}
|
|
|
|
FileHandle_Impl::Guard::Guard(LPCRITICAL_SECTION pMutex)
|
|
: m_mutex (pMutex)
|
|
{
|
|
OSL_PRECOND (m_mutex != 0, "FileHandle_Impl::Guard::Guard(): null pointer.");
|
|
::EnterCriticalSection (m_mutex);
|
|
}
|
|
FileHandle_Impl::Guard::~Guard()
|
|
{
|
|
OSL_PRECOND (m_mutex != 0, "FileHandle_Impl::Guard::~Guard(): null pointer.");
|
|
::LeaveCriticalSection (m_mutex);
|
|
}
|
|
|
|
FileHandle_Impl::FileHandle_Impl(HANDLE hFile)
|
|
: m_hFile (hFile),
|
|
m_state (STATE_READABLE | STATE_WRITEABLE),
|
|
m_size (0),
|
|
m_offset (0),
|
|
m_filepos (0),
|
|
m_bufptr (-1),
|
|
m_buflen (0),
|
|
m_bufsiz (0),
|
|
m_buffer (0)
|
|
{
|
|
::InitializeCriticalSection (&m_mutex);
|
|
Allocator::get().allocate (&m_buffer, &m_bufsiz);
|
|
if (m_buffer != 0)
|
|
memset (m_buffer, 0, m_bufsiz);
|
|
}
|
|
|
|
FileHandle_Impl::~FileHandle_Impl()
|
|
{
|
|
Allocator::get().deallocate (m_buffer), m_buffer = 0;
|
|
::DeleteCriticalSection (&m_mutex);
|
|
}
|
|
|
|
void * FileHandle_Impl::operator new(size_t n)
|
|
{
|
|
return rtl_allocateMemory(n);
|
|
}
|
|
|
|
void FileHandle_Impl::operator delete(void * p, size_t)
|
|
{
|
|
rtl_freeMemory(p);
|
|
}
|
|
|
|
SIZE_T FileHandle_Impl::getpagesize()
|
|
{
|
|
SYSTEM_INFO info;
|
|
::GetSystemInfo (&info);
|
|
return sal::static_int_cast< SIZE_T >(info.dwPageSize);
|
|
}
|
|
|
|
sal_uInt64 FileHandle_Impl::getPos() const
|
|
{
|
|
return sal::static_int_cast< sal_uInt64 >(m_filepos);
|
|
}
|
|
|
|
oslFileError FileHandle_Impl::setPos (sal_uInt64 uPos)
|
|
{
|
|
m_filepos = sal::static_int_cast< LONGLONG >(uPos);
|
|
return osl_File_E_None;
|
|
}
|
|
|
|
sal_uInt64 FileHandle_Impl::getSize() const
|
|
{
|
|
LONGLONG bufend = std::max((LONGLONG)(0), m_bufptr) + m_buflen;
|
|
return std::max(m_size, sal::static_int_cast< sal_uInt64 >(bufend));
|
|
}
|
|
|
|
oslFileError FileHandle_Impl::setSize (sal_uInt64 uSize)
|
|
{
|
|
LARGE_INTEGER nDstPos; nDstPos.QuadPart = sal::static_int_cast< LONGLONG >(uSize);
|
|
if (!::SetFilePointerEx(m_hFile, nDstPos, 0, FILE_BEGIN))
|
|
return oslTranslateFileError( GetLastError() );
|
|
|
|
if (!::SetEndOfFile(m_hFile))
|
|
return oslTranslateFileError( GetLastError() );
|
|
m_size = uSize;
|
|
|
|
nDstPos.QuadPart = m_offset;
|
|
if (!::SetFilePointerEx(m_hFile, nDstPos, 0, FILE_BEGIN))
|
|
return oslTranslateFileError( GetLastError() );
|
|
|
|
return osl_File_E_None;
|
|
}
|
|
|
|
oslFileError FileHandle_Impl::readAt (
|
|
LONGLONG nOffset,
|
|
void * pBuffer,
|
|
DWORD nBytesRequested,
|
|
sal_uInt64 * pBytesRead)
|
|
{
|
|
OSL_PRECOND(m_state & STATE_SEEKABLE, "FileHandle_Impl::readAt(): not seekable");
|
|
if (!(m_state & STATE_SEEKABLE))
|
|
return osl_File_E_SPIPE;
|
|
|
|
OSL_PRECOND(m_state & STATE_READABLE, "FileHandle_Impl::readAt(): not readable");
|
|
if (!(m_state & STATE_READABLE))
|
|
return osl_File_E_BADF;
|
|
|
|
if (nOffset != m_offset)
|
|
{
|
|
LARGE_INTEGER liOffset; liOffset.QuadPart = nOffset;
|
|
if (!::SetFilePointerEx(m_hFile, liOffset, 0, FILE_BEGIN))
|
|
return oslTranslateFileError( GetLastError() );
|
|
m_offset = nOffset;
|
|
}
|
|
|
|
DWORD dwDone = 0;
|
|
if (!::ReadFile(m_hFile, pBuffer, nBytesRequested, &dwDone, 0))
|
|
return oslTranslateFileError( GetLastError() );
|
|
m_offset += dwDone;
|
|
|
|
*pBytesRead = dwDone;
|
|
return osl_File_E_None;
|
|
}
|
|
|
|
oslFileError FileHandle_Impl::writeAt (
|
|
LONGLONG nOffset,
|
|
void const * pBuffer,
|
|
DWORD nBytesToWrite,
|
|
sal_uInt64 * pBytesWritten)
|
|
{
|
|
OSL_PRECOND(m_state & STATE_SEEKABLE, "FileHandle_Impl::writeAt(): not seekable");
|
|
if (!(m_state & STATE_SEEKABLE))
|
|
return osl_File_E_SPIPE;
|
|
|
|
OSL_PRECOND(m_state & STATE_WRITEABLE, "FileHandle_Impl::writeAt(): not writeable");
|
|
if (!(m_state & STATE_WRITEABLE))
|
|
return osl_File_E_BADF;
|
|
|
|
if (nOffset != m_offset)
|
|
{
|
|
LARGE_INTEGER liOffset; liOffset.QuadPart = nOffset;
|
|
if (!::SetFilePointerEx (m_hFile, liOffset, 0, FILE_BEGIN))
|
|
return oslTranslateFileError( GetLastError() );
|
|
m_offset = nOffset;
|
|
}
|
|
|
|
DWORD dwDone = 0;
|
|
if (!::WriteFile(m_hFile, pBuffer, nBytesToWrite, &dwDone, 0))
|
|
return oslTranslateFileError( GetLastError() );
|
|
m_offset += dwDone;
|
|
|
|
m_size = std::max(m_size, sal::static_int_cast< sal_uInt64 >(m_offset));
|
|
|
|
*pBytesWritten = dwDone;
|
|
return osl_File_E_None;
|
|
}
|
|
|
|
oslFileError FileHandle_Impl::readFileAt (
|
|
LONGLONG nOffset,
|
|
void * pBuffer,
|
|
sal_uInt64 uBytesRequested,
|
|
sal_uInt64 * pBytesRead)
|
|
{
|
|
static sal_uInt64 const g_limit_dword = std::numeric_limits< DWORD >::max();
|
|
if (g_limit_dword < uBytesRequested)
|
|
return osl_File_E_OVERFLOW;
|
|
DWORD nBytesRequested = sal::static_int_cast< DWORD >(uBytesRequested);
|
|
|
|
if (0 == (m_state & STATE_SEEKABLE))
|
|
{
|
|
// not seekable (pipe)
|
|
DWORD dwDone = 0;
|
|
if (!::ReadFile(m_hFile, pBuffer, nBytesRequested, &dwDone, 0))
|
|
return oslTranslateFileError( GetLastError() );
|
|
*pBytesRead = dwDone;
|
|
return osl_File_E_None;
|
|
}
|
|
else if (0 == m_buffer)
|
|
{
|
|
// not buffered
|
|
return readAt (nOffset, pBuffer, nBytesRequested, pBytesRead);
|
|
}
|
|
else
|
|
{
|
|
sal_uInt8 * buffer = static_cast< sal_uInt8* >(pBuffer);
|
|
for (*pBytesRead = 0; nBytesRequested > 0; )
|
|
{
|
|
LONGLONG const bufptr = (nOffset / m_bufsiz) * m_bufsiz;
|
|
SIZE_T const bufpos = (nOffset % m_bufsiz);
|
|
|
|
if (bufptr != m_bufptr)
|
|
{
|
|
// flush current buffer
|
|
oslFileError result = syncFile();
|
|
if (result != osl_File_E_None)
|
|
return (result);
|
|
m_bufptr = -1, m_buflen = 0;
|
|
|
|
if (nBytesRequested >= m_bufsiz)
|
|
{
|
|
// buffer too small, read through from file
|
|
sal_uInt64 uDone = 0;
|
|
result = readAt (nOffset, &(buffer[*pBytesRead]), nBytesRequested, &uDone);
|
|
if (result != osl_File_E_None)
|
|
return (result);
|
|
|
|
nBytesRequested -= sal::static_int_cast< DWORD >(uDone), *pBytesRead += uDone;
|
|
return osl_File_E_None;
|
|
}
|
|
|
|
// update buffer (pointer)
|
|
sal_uInt64 uDone = 0;
|
|
result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
|
|
if (result != osl_File_E_None)
|
|
return (result);
|
|
m_bufptr = bufptr, m_buflen = sal::static_int_cast< SIZE_T >(uDone);
|
|
}
|
|
if (bufpos >= m_buflen)
|
|
{
|
|
// end of file
|
|
return osl_File_E_None;
|
|
}
|
|
|
|
SIZE_T const bytes = std::min(m_buflen - bufpos, (SIZE_T) nBytesRequested);
|
|
memcpy (&(buffer[*pBytesRead]), &(m_buffer[bufpos]), bytes);
|
|
nBytesRequested -= bytes, *pBytesRead += bytes, nOffset += bytes;
|
|
}
|
|
return osl_File_E_None;
|
|
}
|
|
}
|
|
|
|
oslFileError FileHandle_Impl::writeFileAt (
|
|
LONGLONG nOffset,
|
|
void const * pBuffer,
|
|
sal_uInt64 uBytesToWrite,
|
|
sal_uInt64 * pBytesWritten)
|
|
{
|
|
static sal_uInt64 const g_limit_dword = std::numeric_limits< DWORD >::max();
|
|
if (g_limit_dword < uBytesToWrite)
|
|
return osl_File_E_OVERFLOW;
|
|
DWORD nBytesToWrite = sal::static_int_cast< DWORD >(uBytesToWrite);
|
|
|
|
if (0 == (m_state & STATE_SEEKABLE))
|
|
{
|
|
// not seekable (pipe)
|
|
DWORD dwDone = 0;
|
|
if (!::WriteFile(m_hFile, pBuffer, nBytesToWrite, &dwDone, 0))
|
|
return oslTranslateFileError( GetLastError() );
|
|
*pBytesWritten = dwDone;
|
|
return osl_File_E_None;
|
|
}
|
|
else if (0 == m_buffer)
|
|
{
|
|
// not buffered
|
|
return writeAt(nOffset, pBuffer, nBytesToWrite, pBytesWritten);
|
|
}
|
|
else
|
|
{
|
|
sal_uInt8 const * buffer = static_cast< sal_uInt8 const* >(pBuffer);
|
|
for (*pBytesWritten = 0; nBytesToWrite > 0; )
|
|
{
|
|
LONGLONG const bufptr = (nOffset / m_bufsiz) * m_bufsiz;
|
|
SIZE_T const bufpos = (nOffset % m_bufsiz);
|
|
if (bufptr != m_bufptr)
|
|
{
|
|
// flush current buffer
|
|
oslFileError result = syncFile();
|
|
if (result != osl_File_E_None)
|
|
return (result);
|
|
m_bufptr = -1, m_buflen = 0;
|
|
|
|
if (nBytesToWrite >= m_bufsiz)
|
|
{
|
|
// buffer too small, write through to file
|
|
sal_uInt64 uDone = 0;
|
|
result = writeAt (nOffset, &(buffer[*pBytesWritten]), nBytesToWrite, &uDone);
|
|
if (result != osl_File_E_None)
|
|
return (result);
|
|
if (uDone != nBytesToWrite)
|
|
return osl_File_E_IO;
|
|
|
|
nBytesToWrite -= sal::static_int_cast< DWORD >(uDone), *pBytesWritten += uDone;
|
|
return osl_File_E_None;
|
|
}
|
|
|
|
// update buffer (pointer)
|
|
sal_uInt64 uDone = 0;
|
|
result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
|
|
if (result != osl_File_E_None)
|
|
return (result);
|
|
m_bufptr = bufptr, m_buflen = sal::static_int_cast< SIZE_T >(uDone);
|
|
}
|
|
|
|
SIZE_T const bytes = std::min(m_bufsiz - bufpos, (SIZE_T) nBytesToWrite);
|
|
memcpy (&(m_buffer[bufpos]), &(buffer[*pBytesWritten]), bytes);
|
|
nBytesToWrite -= bytes, *pBytesWritten += bytes, nOffset += bytes;
|
|
|
|
m_buflen = std::max(m_buflen, bufpos + bytes);
|
|
m_state |= STATE_MODIFIED;
|
|
}
|
|
return osl_File_E_None;
|
|
}
|
|
}
|
|
|
|
oslFileError FileHandle_Impl::readLineAt (
|
|
LONGLONG nOffset,
|
|
sal_Sequence ** ppSequence,
|
|
sal_uInt64 * pBytesRead)
|
|
{
|
|
oslFileError result = osl_File_E_None;
|
|
|
|
LONGLONG bufptr = (nOffset / m_bufsiz) * m_bufsiz;
|
|
if (bufptr != m_bufptr)
|
|
{
|
|
/* flush current buffer */
|
|
result = syncFile();
|
|
if (result != osl_File_E_None)
|
|
return (result);
|
|
|
|
/* update buffer (pointer) */
|
|
sal_uInt64 uDone = 0;
|
|
result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
|
|
if (result != osl_File_E_None)
|
|
return (result);
|
|
|
|
m_bufptr = bufptr, m_buflen = sal::static_int_cast< SIZE_T >(uDone);
|
|
}
|
|
|
|
static int const LINE_STATE_BEGIN = 0;
|
|
static int const LINE_STATE_CR = 1;
|
|
static int const LINE_STATE_LF = 2;
|
|
|
|
SIZE_T bufpos = sal::static_int_cast< SIZE_T >(nOffset - m_bufptr), curpos = bufpos, dstpos = 0;
|
|
int state = (bufpos >= m_buflen) ? LINE_STATE_LF : LINE_STATE_BEGIN;
|
|
|
|
for ( ; state != LINE_STATE_LF; )
|
|
{
|
|
if (curpos >= m_buflen)
|
|
{
|
|
/* buffer examined */
|
|
if (0 < (curpos - bufpos))
|
|
{
|
|
/* flush buffer to sequence */
|
|
result = writeSequence_Impl (
|
|
ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos);
|
|
if (result != osl_File_E_None)
|
|
return (result);
|
|
*pBytesRead += curpos - bufpos, nOffset += curpos - bufpos;
|
|
}
|
|
|
|
bufptr = nOffset / m_bufsiz * m_bufsiz;
|
|
if (bufptr != m_bufptr)
|
|
{
|
|
/* update buffer (pointer) */
|
|
sal_uInt64 uDone = 0;
|
|
result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
|
|
if (result != osl_File_E_None)
|
|
return (result);
|
|
m_bufptr = bufptr, m_buflen = sal::static_int_cast< SIZE_T >(uDone);
|
|
}
|
|
|
|
bufpos = sal::static_int_cast< SIZE_T >(nOffset - m_bufptr), curpos = bufpos;
|
|
if (bufpos >= m_buflen)
|
|
break;
|
|
}
|
|
switch (state)
|
|
{
|
|
case LINE_STATE_CR:
|
|
state = LINE_STATE_LF;
|
|
switch (m_buffer[curpos])
|
|
{
|
|
case 0x0A: /* CRLF */
|
|
/* eat current char */
|
|
curpos++;
|
|
break;
|
|
default: /* single CR */
|
|
/* keep current char */
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
/* determine next state */
|
|
switch (m_buffer[curpos])
|
|
{
|
|
case 0x0A: /* single LF */
|
|
state = LINE_STATE_LF;
|
|
break;
|
|
case 0x0D: /* CR */
|
|
state = LINE_STATE_CR;
|
|
break;
|
|
default: /* advance to next char */
|
|
curpos++;
|
|
break;
|
|
}
|
|
if (state != LINE_STATE_BEGIN)
|
|
{
|
|
/* store (and eat) the newline char */
|
|
m_buffer[curpos] = 0x0A, curpos++;
|
|
|
|
/* flush buffer to sequence */
|
|
result = writeSequence_Impl (
|
|
ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos - 1);
|
|
if (result != osl_File_E_None)
|
|
return (result);
|
|
*pBytesRead += curpos - bufpos, nOffset += curpos - bufpos;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
result = writeSequence_Impl (ppSequence, &dstpos, 0, 0);
|
|
if (result != osl_File_E_None)
|
|
return (result);
|
|
if (0 < dstpos)
|
|
return osl_File_E_None;
|
|
if (bufpos >= m_buflen)
|
|
return osl_File_E_AGAIN;
|
|
return osl_File_E_None;
|
|
}
|
|
|
|
oslFileError FileHandle_Impl::writeSequence_Impl (
|
|
sal_Sequence ** ppSequence,
|
|
SIZE_T * pnOffset,
|
|
const void * pBuffer,
|
|
SIZE_T nBytes)
|
|
{
|
|
sal_Int32 nElements = *pnOffset + nBytes;
|
|
if (!*ppSequence)
|
|
{
|
|
/* construct sequence */
|
|
rtl_byte_sequence_constructNoDefault(ppSequence, nElements);
|
|
}
|
|
else if (nElements != (*ppSequence)->nElements)
|
|
{
|
|
/* resize sequence */
|
|
rtl_byte_sequence_realloc(ppSequence, nElements);
|
|
}
|
|
if (*ppSequence != 0)
|
|
{
|
|
/* fill sequence */
|
|
memcpy(&((*ppSequence)->elements[*pnOffset]), pBuffer, nBytes), *pnOffset += nBytes;
|
|
}
|
|
return (*ppSequence != 0) ? osl_File_E_None : osl_File_E_NOMEM;
|
|
}
|
|
|
|
oslFileError FileHandle_Impl::syncFile()
|
|
{
|
|
oslFileError result = osl_File_E_None;
|
|
if (m_state & STATE_MODIFIED)
|
|
{
|
|
sal_uInt64 uDone = 0;
|
|
result = writeAt (m_bufptr, m_buffer, m_buflen, &uDone);
|
|
if (result != osl_File_E_None)
|
|
return (result);
|
|
if (uDone != m_buflen)
|
|
return osl_File_E_IO;
|
|
m_state &= ~STATE_MODIFIED;
|
|
}
|
|
return (result);
|
|
}
|
|
|
|
// File I/O functions
|
|
|
|
extern "C" oslFileHandle
|
|
SAL_CALL osl_createFileHandleFromOSHandle (
|
|
HANDLE hFile,
|
|
sal_uInt32 uFlags)
|
|
{
|
|
if ( !IsValidHandle(hFile) )
|
|
return 0; // EINVAL
|
|
|
|
FileHandle_Impl * pImpl = new FileHandle_Impl(hFile);
|
|
if (pImpl == 0)
|
|
{
|
|
// cleanup and fail
|
|
(void) ::CloseHandle(hFile);
|
|
return 0; // ENOMEM
|
|
}
|
|
|
|
/* check for regular file */
|
|
if (FILE_TYPE_DISK == GetFileType(hFile))
|
|
{
|
|
/* mark seekable */
|
|
pImpl->m_state |= FileHandle_Impl::STATE_SEEKABLE;
|
|
|
|
/* init current size */
|
|
LARGE_INTEGER uSize = { { 0, 0 } };
|
|
(void) ::GetFileSizeEx(hFile, &uSize);
|
|
pImpl->m_size = (sal::static_int_cast<sal_uInt64>(uSize.HighPart) << 32) + uSize.LowPart;
|
|
}
|
|
|
|
if (!(uFlags & osl_File_OpenFlag_Read))
|
|
pImpl->m_state &= ~FileHandle_Impl::STATE_READABLE;
|
|
if (!(uFlags & osl_File_OpenFlag_Write))
|
|
pImpl->m_state &= ~FileHandle_Impl::STATE_WRITEABLE;
|
|
|
|
SAL_WARN_IF(
|
|
!((uFlags & osl_File_OpenFlag_Read) || (uFlags & osl_File_OpenFlag_Write)),
|
|
"sal.osl",
|
|
"osl_createFileHandleFromOSHandle(): missing read/write access flags");
|
|
return (oslFileHandle)(pImpl);
|
|
}
|
|
|
|
oslFileError
|
|
SAL_CALL osl_openFile(
|
|
rtl_uString * strPath,
|
|
oslFileHandle * pHandle,
|
|
sal_uInt32 uFlags )
|
|
{
|
|
rtl_uString * strSysPath = 0;
|
|
oslFileError result = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
|
|
if (result != osl_File_E_None)
|
|
return (result);
|
|
|
|
DWORD dwAccess = GENERIC_READ, dwShare = FILE_SHARE_READ, dwCreation = 0, dwAttributes = 0;
|
|
|
|
if ( uFlags & osl_File_OpenFlag_Write )
|
|
dwAccess |= GENERIC_WRITE;
|
|
else
|
|
dwShare |= FILE_SHARE_WRITE;
|
|
|
|
if ( uFlags & osl_File_OpenFlag_NoLock )
|
|
dwShare |= FILE_SHARE_WRITE;
|
|
|
|
if ( uFlags & osl_File_OpenFlag_Create )
|
|
dwCreation |= CREATE_NEW;
|
|
else
|
|
dwCreation |= OPEN_EXISTING;
|
|
|
|
HANDLE hFile = CreateFileW(
|
|
reinterpret_cast<LPCWSTR>(rtl_uString_getStr( strSysPath )),
|
|
dwAccess, dwShare, NULL, dwCreation, dwAttributes, NULL );
|
|
|
|
// @@@ ERROR HANDLING @@@
|
|
if ( !IsValidHandle( hFile ) )
|
|
result = oslTranslateFileError( GetLastError() );
|
|
|
|
*pHandle = osl_createFileHandleFromOSHandle (hFile, uFlags | osl_File_OpenFlag_Read);
|
|
|
|
rtl_uString_release( strSysPath );
|
|
return (result);
|
|
}
|
|
|
|
oslFileError
|
|
SAL_CALL osl_syncFile(oslFileHandle Handle)
|
|
{
|
|
FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
|
|
if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile))
|
|
return osl_File_E_INVAL;
|
|
|
|
FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
|
|
|
|
oslFileError result = pImpl->syncFile();
|
|
if (result != osl_File_E_None)
|
|
return result;
|
|
|
|
if (!FlushFileBuffers(pImpl->m_hFile))
|
|
return oslTranslateFileError(GetLastError());
|
|
|
|
return osl_File_E_None;
|
|
}
|
|
|
|
oslFileError
|
|
SAL_CALL osl_closeFile(oslFileHandle Handle)
|
|
{
|
|
FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
|
|
if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile))
|
|
return osl_File_E_INVAL;
|
|
|
|
::EnterCriticalSection (&(pImpl->m_mutex));
|
|
|
|
oslFileError result = pImpl->syncFile();
|
|
if (result != osl_File_E_None)
|
|
{
|
|
/* ignore double failure */
|
|
(void)::CloseHandle(pImpl->m_hFile);
|
|
}
|
|
else if (!::CloseHandle(pImpl->m_hFile))
|
|
{
|
|
/* translate error code */
|
|
result = oslTranslateFileError( GetLastError() );
|
|
}
|
|
|
|
::LeaveCriticalSection (&(pImpl->m_mutex));
|
|
delete pImpl;
|
|
return (result);
|
|
}
|
|
|
|
oslFileError
|
|
SAL_CALL osl_mapFile(
|
|
oslFileHandle Handle,
|
|
void** ppAddr,
|
|
sal_uInt64 uLength,
|
|
sal_uInt64 uOffset,
|
|
sal_uInt32 uFlags)
|
|
{
|
|
struct FileMapping
|
|
{
|
|
HANDLE m_handle;
|
|
|
|
explicit FileMapping (HANDLE hMap)
|
|
: m_handle (hMap)
|
|
{}
|
|
|
|
~FileMapping()
|
|
{
|
|
(void)::CloseHandle(m_handle);
|
|
}
|
|
};
|
|
|
|
FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
|
|
if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == ppAddr))
|
|
return osl_File_E_INVAL;
|
|
*ppAddr = 0;
|
|
|
|
static SIZE_T const nLimit = std::numeric_limits< SIZE_T >::max();
|
|
if (uLength > nLimit)
|
|
return osl_File_E_OVERFLOW;
|
|
SIZE_T const nLength = sal::static_int_cast< SIZE_T >(uLength);
|
|
|
|
FileMapping aMap( ::CreateFileMapping (pImpl->m_hFile, NULL, SEC_COMMIT | PAGE_READONLY, 0, 0, NULL) );
|
|
if (!IsValidHandle(aMap.m_handle))
|
|
return oslTranslateFileError( GetLastError() );
|
|
|
|
DWORD const dwOffsetHi = sal::static_int_cast<DWORD>(uOffset >> 32);
|
|
DWORD const dwOffsetLo = sal::static_int_cast<DWORD>(uOffset & 0xFFFFFFFF);
|
|
|
|
*ppAddr = ::MapViewOfFile( aMap.m_handle, FILE_MAP_READ, dwOffsetHi, dwOffsetLo, nLength );
|
|
if (0 == *ppAddr)
|
|
return oslTranslateFileError( GetLastError() );
|
|
|
|
if (uFlags & osl_File_MapFlag_RandomAccess)
|
|
{
|
|
// Determine memory pagesize.
|
|
SYSTEM_INFO info;
|
|
::GetSystemInfo( &info );
|
|
DWORD const dwPageSize = info.dwPageSize;
|
|
|
|
/*
|
|
* Pagein, touching first byte of each memory page.
|
|
* Note: volatile disables optimizing the loop away.
|
|
*/
|
|
BYTE * pData (reinterpret_cast<BYTE*>(*ppAddr));
|
|
SIZE_T nSize (nLength);
|
|
|
|
volatile BYTE c = 0;
|
|
while (nSize > dwPageSize)
|
|
{
|
|
c ^= pData[0];
|
|
pData += dwPageSize;
|
|
nSize -= dwPageSize;
|
|
}
|
|
if (nSize > 0)
|
|
{
|
|
c ^= pData[0];
|
|
}
|
|
}
|
|
return osl_File_E_None;
|
|
}
|
|
|
|
oslFileError
|
|
SAL_CALL osl_unmapFile(void* pAddr, sal_uInt64 /* uLength */)
|
|
{
|
|
if (0 == pAddr)
|
|
return osl_File_E_INVAL;
|
|
|
|
if (!::UnmapViewOfFile (pAddr))
|
|
return oslTranslateFileError( GetLastError() );
|
|
|
|
return osl_File_E_None;
|
|
}
|
|
|
|
oslFileError
|
|
SAL_CALL osl_unmapMappedFile(oslFileHandle /* Handle */, void* pAddr, sal_uInt64 uLength)
|
|
{
|
|
return osl_unmapFile( pAddr, uLength );
|
|
}
|
|
|
|
oslFileError
|
|
SAL_CALL osl_readLine(
|
|
oslFileHandle Handle,
|
|
sal_Sequence ** ppSequence)
|
|
{
|
|
FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
|
|
if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == ppSequence))
|
|
return osl_File_E_INVAL;
|
|
sal_uInt64 uBytesRead = 0;
|
|
|
|
// read at current filepos; filepos += uBytesRead;
|
|
FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
|
|
oslFileError result = pImpl->readLineAt (
|
|
pImpl->m_filepos, ppSequence, &uBytesRead);
|
|
if (result == osl_File_E_None)
|
|
pImpl->m_filepos += uBytesRead;
|
|
return (result);
|
|
}
|
|
|
|
oslFileError
|
|
SAL_CALL osl_readFile(
|
|
oslFileHandle Handle,
|
|
void * pBuffer,
|
|
sal_uInt64 uBytesRequested,
|
|
sal_uInt64 * pBytesRead)
|
|
{
|
|
FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
|
|
if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pBuffer) || (0 == pBytesRead))
|
|
return osl_File_E_INVAL;
|
|
|
|
// read at current filepos; filepos += *pBytesRead;
|
|
FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
|
|
oslFileError result = pImpl->readFileAt (
|
|
pImpl->m_filepos, pBuffer, uBytesRequested, pBytesRead);
|
|
if (result == osl_File_E_None)
|
|
pImpl->m_filepos += *pBytesRead;
|
|
return (result);
|
|
}
|
|
|
|
oslFileError
|
|
SAL_CALL osl_writeFile(
|
|
oslFileHandle Handle,
|
|
const void * pBuffer,
|
|
sal_uInt64 uBytesToWrite,
|
|
sal_uInt64 * pBytesWritten )
|
|
{
|
|
FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
|
|
|
|
if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pBuffer) || (0 == pBytesWritten))
|
|
return osl_File_E_INVAL;
|
|
|
|
// write at current filepos; filepos += *pBytesWritten;
|
|
FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
|
|
oslFileError result = pImpl->writeFileAt (
|
|
pImpl->m_filepos, pBuffer, uBytesToWrite, pBytesWritten);
|
|
if (result == osl_File_E_None)
|
|
pImpl->m_filepos += *pBytesWritten;
|
|
return (result);
|
|
}
|
|
|
|
oslFileError
|
|
SAL_CALL osl_readFileAt(
|
|
oslFileHandle Handle,
|
|
sal_uInt64 uOffset,
|
|
void* pBuffer,
|
|
sal_uInt64 uBytesRequested,
|
|
sal_uInt64* pBytesRead)
|
|
{
|
|
FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
|
|
|
|
if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pBuffer) || (0 == pBytesRead))
|
|
return osl_File_E_INVAL;
|
|
if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE))
|
|
return osl_File_E_SPIPE;
|
|
|
|
static sal_uInt64 const g_limit_longlong = std::numeric_limits< LONGLONG >::max();
|
|
if (g_limit_longlong < uOffset)
|
|
return osl_File_E_OVERFLOW;
|
|
LONGLONG const nOffset = sal::static_int_cast< LONGLONG >(uOffset);
|
|
|
|
// read at specified fileptr
|
|
FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
|
|
return pImpl->readFileAt (nOffset, pBuffer, uBytesRequested, pBytesRead);
|
|
}
|
|
|
|
oslFileError
|
|
SAL_CALL osl_writeFileAt(
|
|
oslFileHandle Handle,
|
|
sal_uInt64 uOffset,
|
|
const void* pBuffer,
|
|
sal_uInt64 uBytesToWrite,
|
|
sal_uInt64* pBytesWritten)
|
|
{
|
|
FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
|
|
|
|
if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pBuffer) || (0 == pBytesWritten))
|
|
return osl_File_E_INVAL;
|
|
if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE))
|
|
return osl_File_E_SPIPE;
|
|
|
|
static sal_uInt64 const g_limit_longlong = std::numeric_limits< LONGLONG >::max();
|
|
if (g_limit_longlong < uOffset)
|
|
return osl_File_E_OVERFLOW;
|
|
LONGLONG const nOffset = sal::static_int_cast< LONGLONG >(uOffset);
|
|
|
|
// write at specified fileptr
|
|
FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
|
|
return pImpl->writeFileAt (nOffset, pBuffer, uBytesToWrite, pBytesWritten);
|
|
}
|
|
|
|
oslFileError
|
|
SAL_CALL osl_isEndOfFile (oslFileHandle Handle, sal_Bool *pIsEOF)
|
|
{
|
|
FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
|
|
|
|
if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pIsEOF))
|
|
return osl_File_E_INVAL;
|
|
|
|
FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
|
|
*pIsEOF = (pImpl->getPos() == pImpl->getSize());
|
|
return osl_File_E_None;
|
|
}
|
|
|
|
oslFileError
|
|
SAL_CALL osl_getFilePos(oslFileHandle Handle, sal_uInt64 *pPos)
|
|
{
|
|
FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
|
|
if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pPos))
|
|
return osl_File_E_INVAL;
|
|
|
|
FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
|
|
*pPos = pImpl->getPos();
|
|
return osl_File_E_None;
|
|
}
|
|
|
|
oslFileError
|
|
SAL_CALL osl_setFilePos(oslFileHandle Handle, sal_uInt32 uHow, sal_Int64 uOffset)
|
|
{
|
|
FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
|
|
if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile))
|
|
return osl_File_E_INVAL;
|
|
|
|
static sal_Int64 const g_limit_longlong = std::numeric_limits< LONGLONG >::max();
|
|
if (g_limit_longlong < uOffset)
|
|
return osl_File_E_OVERFLOW;
|
|
LONGLONG nPos = 0, nOffset = sal::static_int_cast< LONGLONG >(uOffset);
|
|
|
|
FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
|
|
switch (uHow)
|
|
{
|
|
case osl_Pos_Absolut:
|
|
if (0 > nOffset)
|
|
return osl_File_E_INVAL;
|
|
break;
|
|
|
|
case osl_Pos_Current:
|
|
nPos = sal::static_int_cast< LONGLONG >(pImpl->getPos());
|
|
if ((0 > nOffset) && (-1*nOffset > nPos))
|
|
return osl_File_E_INVAL;
|
|
if (g_limit_longlong < nPos + nOffset)
|
|
return osl_File_E_OVERFLOW;
|
|
break;
|
|
|
|
case osl_Pos_End:
|
|
nPos = sal::static_int_cast< LONGLONG >(pImpl->getSize());
|
|
if ((0 > nOffset) && (-1*nOffset > nPos))
|
|
return osl_File_E_INVAL;
|
|
if (g_limit_longlong < nPos + nOffset)
|
|
return osl_File_E_OVERFLOW;
|
|
break;
|
|
|
|
default:
|
|
return osl_File_E_INVAL;
|
|
}
|
|
|
|
return pImpl->setPos (nPos + nOffset);
|
|
}
|
|
|
|
oslFileError
|
|
SAL_CALL osl_getFileSize (oslFileHandle Handle, sal_uInt64 *pSize)
|
|
{
|
|
FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
|
|
|
|
if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pSize))
|
|
return osl_File_E_INVAL;
|
|
|
|
FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
|
|
*pSize = pImpl->getSize();
|
|
return osl_File_E_None;
|
|
}
|
|
|
|
oslFileError
|
|
SAL_CALL osl_setFileSize (oslFileHandle Handle, sal_uInt64 uSize)
|
|
{
|
|
FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
|
|
|
|
if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile))
|
|
return osl_File_E_INVAL;
|
|
if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE))
|
|
return osl_File_E_BADF;
|
|
|
|
static sal_uInt64 const g_limit_longlong = std::numeric_limits< LONGLONG >::max();
|
|
if (g_limit_longlong < uSize)
|
|
return osl_File_E_OVERFLOW;
|
|
|
|
FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
|
|
oslFileError result = pImpl->syncFile();
|
|
if (result != osl_File_E_None)
|
|
return (result);
|
|
pImpl->m_bufptr = -1, pImpl->m_buflen = 0;
|
|
|
|
return pImpl->setSize (uSize);
|
|
}
|
|
|
|
// File handling functions
|
|
|
|
oslFileError SAL_CALL osl_removeFile( rtl_uString* strPath )
|
|
{
|
|
rtl_uString *strSysPath = NULL;
|
|
oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
|
|
|
|
if ( osl_File_E_None == error )
|
|
{
|
|
if ( DeleteFile( reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath )) ) )
|
|
error = osl_File_E_None;
|
|
else
|
|
error = oslTranslateFileError( GetLastError() );
|
|
|
|
rtl_uString_release( strSysPath );
|
|
}
|
|
return error;
|
|
}
|
|
|
|
oslFileError SAL_CALL osl_copyFile( rtl_uString* strPath, rtl_uString *strDestPath )
|
|
{
|
|
rtl_uString *strSysPath = NULL, *strSysDestPath = NULL;
|
|
oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
|
|
|
|
if ( osl_File_E_None == error )
|
|
error = _osl_getSystemPathFromFileURL( strDestPath, &strSysDestPath, sal_False );
|
|
|
|
if ( osl_File_E_None == error )
|
|
{
|
|
LPCTSTR src = reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath ));
|
|
LPCTSTR dst = reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysDestPath ));
|
|
|
|
if ( CopyFile( src, dst, FALSE ) )
|
|
error = osl_File_E_None;
|
|
else
|
|
error = oslTranslateFileError( GetLastError() );
|
|
}
|
|
|
|
if ( strSysPath )
|
|
rtl_uString_release( strSysPath );
|
|
if ( strSysDestPath )
|
|
rtl_uString_release( strSysDestPath );
|
|
|
|
return error;
|
|
}
|
|
|
|
oslFileError SAL_CALL osl_moveFile( rtl_uString* strPath, rtl_uString *strDestPath )
|
|
{
|
|
rtl_uString *strSysPath = NULL, *strSysDestPath = NULL;
|
|
oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
|
|
|
|
if ( osl_File_E_None == error )
|
|
error = _osl_getSystemPathFromFileURL( strDestPath, &strSysDestPath, sal_False );
|
|
|
|
if ( osl_File_E_None == error )
|
|
{
|
|
LPCTSTR src = reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath ));
|
|
LPCTSTR dst = reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysDestPath ));
|
|
|
|
if ( MoveFileEx( src, dst, MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING ) )
|
|
error = osl_File_E_None;
|
|
else
|
|
error = oslTranslateFileError( GetLastError() );
|
|
}
|
|
|
|
if ( strSysPath )
|
|
rtl_uString_release( strSysPath );
|
|
if ( strSysDestPath )
|
|
rtl_uString_release( strSysDestPath );
|
|
|
|
return error;
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|