Files
libreoffice/tools/source/stream/strmunx.cxx

863 lines
26 KiB
C++
Raw Normal View History

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2000-09-18 16:07:07 +00:00
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2000-09-18 16:07:07 +00:00
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
2000-09-18 16:07:07 +00:00
*
* OpenOffice.org - a multi-platform office productivity suite
2000-09-18 16:07:07 +00:00
*
* This file is part of OpenOffice.org.
2000-09-18 16:07:07 +00:00
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
2000-09-18 16:07:07 +00:00
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
2000-09-18 16:07:07 +00:00
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
2000-09-18 16:07:07 +00:00
*
************************************************************************/
2000-09-18 16:07:07 +00:00
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <limits.h>
#include <stdlib.h> // fuer getenv()
#include <tools/debug.hxx>
#include <tools/fsys.hxx>
#include <tools/stream.hxx>
#include <vector>
2000-09-18 16:07:07 +00:00
#include <osl/mutex.hxx>
2000-09-18 16:07:07 +00:00
#include <osl/thread.h> // osl_getThreadTextEncoding
// class FileBase
#include <osl/file.hxx>
#include <osl/detail/file.h>
#include <rtl/instance.hxx>
#include <rtl/strbuf.hxx>
2000-09-18 16:07:07 +00:00
using namespace osl;
// -----------------------------------------------------------------------
// ----------------
// - InternalLock -
// ----------------
#ifndef BOOTSTRAP
namespace { struct LockMutex : public rtl::Static< osl::Mutex, LockMutex > {}; }
#endif
2000-09-18 16:07:07 +00:00
class InternalStreamLock
{
sal_Size m_nStartPos;
sal_Size m_nEndPos;
SvFileStream* m_pStream;
osl::DirectoryItem m_aItem;
2000-09-18 16:07:07 +00:00
InternalStreamLock( sal_Size, sal_Size, SvFileStream* );
2000-09-18 16:07:07 +00:00
~InternalStreamLock();
public:
static sal_Bool LockFile( sal_Size nStart, sal_Size nEnd, SvFileStream* );
static void UnlockFile( sal_Size nStart, sal_Size nEnd, SvFileStream* );
2000-09-18 16:07:07 +00:00
};
typedef ::std::vector< InternalStreamLock* > InternalStreamLockList;
namespace { struct LockList : public rtl::Static< InternalStreamLockList, LockList > {}; }
2000-09-18 16:07:07 +00:00
InternalStreamLock::InternalStreamLock(
sal_Size nStart,
sal_Size nEnd,
2000-09-18 16:07:07 +00:00
SvFileStream* pStream ) :
m_nStartPos( nStart ),
m_nEndPos( nEnd ),
m_pStream( pStream )
{
osl::DirectoryItem::get( m_pStream->GetFileName(), m_aItem );
LockList::get().push_back( this );
#if OSL_DEBUG_LEVEL > 1
rtl::OString aFileName(rtl::OUStringToOString(m_pStream->GetFileName(),
osl_getThreadTextEncoding()));
2011-08-30 23:42:11 +01:00
fprintf( stderr, "locked %s", aFileName.getStr() );
2000-09-18 16:07:07 +00:00
if( m_nStartPos || m_nEndPos )
2010-03-18 14:24:20 +01:00
fprintf(stderr, " [ %ld ... %ld ]", m_nStartPos, m_nEndPos );
2000-09-18 16:07:07 +00:00
fprintf( stderr, "\n" );
#endif
}
InternalStreamLock::~InternalStreamLock()
{
for ( InternalStreamLockList::iterator it = LockList::get().begin();
it < LockList::get().end();
++it
) {
if ( this == *it ) {
LockList::get().erase( it );
break;
}
}
#if OSL_DEBUG_LEVEL > 1
2011-08-30 23:42:11 +01:00
rtl::OString aFileName(rtl::OUStringToOString(m_pStream->GetFileName(),
osl_getThreadTextEncoding()));
2011-08-30 23:42:11 +01:00
fprintf( stderr, "unlocked %s", aFileName.getStr() );
2000-09-18 16:07:07 +00:00
if( m_nStartPos || m_nEndPos )
2010-03-18 14:24:20 +01:00
fprintf(stderr, " [ %ld ... %ld ]", m_nStartPos, m_nEndPos );
2000-09-18 16:07:07 +00:00
fprintf( stderr, "\n" );
#endif
}
sal_Bool InternalStreamLock::LockFile( sal_Size nStart, sal_Size nEnd, SvFileStream* pStream )
2000-09-18 16:07:07 +00:00
{
#ifndef BOOTSTRAP
osl::MutexGuard aGuard( LockMutex::get() );
2000-09-18 16:07:07 +00:00
#endif
osl::DirectoryItem aItem;
if (osl::DirectoryItem::get( pStream->GetFileName(), aItem) != osl::FileBase::RC::E_None )
{
SAL_INFO("tools", "Failed to lookup stream for locking");
return sal_True;
}
2000-09-18 16:07:07 +00:00
osl::FileStatus aStatus( osl_FileStatus_Mask_Type );
if ( aItem.getFileStatus( aStatus ) != osl::FileBase::RC::E_None )
{
SAL_INFO("tools", "Failed to stat stream for locking");
return sal_True;
}
if( aStatus.getFileType() == osl::FileStatus::Type::Directory )
return sal_True;
2000-09-18 16:07:07 +00:00
InternalStreamLock* pLock = NULL;
InternalStreamLockList &rLockList = LockList::get();
for( size_t i = 0; i < rLockList.size(); ++i )
2000-09-18 16:07:07 +00:00
{
pLock = rLockList[ i ];
if( osl_identicalDirectoryItem( aItem._pData, pLock->m_aItem._pData) )
2000-09-18 16:07:07 +00:00
{
sal_Bool bDenyByOptions = sal_False;
2000-09-18 16:07:07 +00:00
StreamMode nLockMode = pLock->m_pStream->GetStreamMode();
StreamMode nNewMode = pStream->GetStreamMode();
if( nLockMode & STREAM_SHARE_DENYALL )
bDenyByOptions = sal_True;
2000-09-18 16:07:07 +00:00
else if( ( nLockMode & STREAM_SHARE_DENYWRITE ) &&
( nNewMode & STREAM_WRITE ) )
bDenyByOptions = sal_True;
2000-09-18 16:07:07 +00:00
else if( ( nLockMode & STREAM_SHARE_DENYREAD ) &&
( nNewMode & STREAM_READ ) )
bDenyByOptions = sal_True;
2000-09-18 16:07:07 +00:00
if( bDenyByOptions )
{
if( pLock->m_nStartPos == 0 && pLock->m_nEndPos == 0 ) // whole file is already locked
return sal_False;
2000-09-18 16:07:07 +00:00
if( nStart == 0 && nEnd == 0) // cannot lock whole file
return sal_False;
2000-09-18 16:07:07 +00:00
if( ( nStart < pLock->m_nStartPos && nEnd > pLock->m_nStartPos ) ||
( nStart < pLock->m_nEndPos && nEnd > pLock->m_nEndPos ) )
return sal_False;
2000-09-18 16:07:07 +00:00
}
}
}
// hint: new InternalStreamLock() adds the entry to the global list
2000-09-18 16:07:07 +00:00
pLock = new InternalStreamLock( nStart, nEnd, pStream );
return sal_True;
2000-09-18 16:07:07 +00:00
}
void InternalStreamLock::UnlockFile( sal_Size nStart, sal_Size nEnd, SvFileStream* pStream )
2000-09-18 16:07:07 +00:00
{
#ifndef BOOTSTRAP
osl::MutexGuard aGuard( LockMutex::get() );
2000-09-18 16:07:07 +00:00
#endif
InternalStreamLock* pLock = NULL;
InternalStreamLockList &rLockList = LockList::get();
2000-09-18 16:07:07 +00:00
if( nStart == 0 && nEnd == 0 )
{
// nStart & nEnd = 0, so delete all locks
for( size_t i = 0; i < rLockList.size(); ++i )
2000-09-18 16:07:07 +00:00
{
if( ( pLock = rLockList[ i ] )->m_pStream == pStream )
2000-09-18 16:07:07 +00:00
{
// hint: delete will remove pLock from the global list
2000-09-18 16:07:07 +00:00
delete pLock;
i--;
}
}
return;
}
for( size_t i = 0; i < rLockList.size(); ++i )
2000-09-18 16:07:07 +00:00
{
if ( ( pLock = rLockList[ i ] )->m_pStream == pStream
&& nStart == pLock->m_nStartPos
&& nEnd == pLock->m_nEndPos
) {
// hint: delete will remove pLock from the global list
2000-09-18 16:07:07 +00:00
delete pLock;
return;
}
}
}
2000-09-18 16:07:07 +00:00
// --------------
// - StreamData -
// --------------
class StreamData
{
public:
oslFileHandle rHandle;
2000-09-18 16:07:07 +00:00
StreamData() { }
2000-09-18 16:07:07 +00:00
};
// -----------------------------------------------------------------------
static sal_uInt32 GetSvError( int nErrno )
2000-09-18 16:07:07 +00:00
{
static struct { int nErr; sal_uInt32 sv; } errArr[] =
2000-09-18 16:07:07 +00:00
{
{ 0, SVSTREAM_OK },
{ EACCES, SVSTREAM_ACCESS_DENIED },
{ EBADF, SVSTREAM_INVALID_HANDLE },
#if defined(RS6000) || defined(NETBSD) || \
2011-02-15 12:12:14 +00:00
defined(FREEBSD) || defined(MACOSX) || defined(OPENBSD) || \
2011-06-15 17:59:53 +03:00
defined(__FreeBSD_kernel__) || defined (AIX) || defined(DRAGONFLY) || \
defined(IOS)
2000-09-18 16:07:07 +00:00
{ EDEADLK, SVSTREAM_LOCKING_VIOLATION },
#else
{ EDEADLOCK, SVSTREAM_LOCKING_VIOLATION },
#endif
{ EINVAL, SVSTREAM_INVALID_PARAMETER },
{ EMFILE, SVSTREAM_TOO_MANY_OPEN_FILES },
{ ENFILE, SVSTREAM_TOO_MANY_OPEN_FILES },
{ ENOENT, SVSTREAM_FILE_NOT_FOUND },
{ EPERM, SVSTREAM_ACCESS_DENIED },
{ EROFS, SVSTREAM_ACCESS_DENIED },
{ EAGAIN, SVSTREAM_LOCKING_VIOLATION },
{ EISDIR, SVSTREAM_PATH_NOT_FOUND },
{ ELOOP, SVSTREAM_PATH_NOT_FOUND },
#if !defined(RS6000) && !defined(NETBSD) && !defined (FREEBSD) && \
2011-02-15 12:12:14 +00:00
!defined(MACOSX) && !defined(OPENBSD) && !defined(__FreeBSD_kernel__) && \
!defined(DRAGONFLY)
2000-09-18 16:07:07 +00:00
{ EMULTIHOP, SVSTREAM_PATH_NOT_FOUND },
{ ENOLINK, SVSTREAM_PATH_NOT_FOUND },
#endif
{ ENOTDIR, SVSTREAM_PATH_NOT_FOUND },
{ ETXTBSY, SVSTREAM_ACCESS_DENIED },
{ EEXIST, SVSTREAM_CANNOT_MAKE },
{ ENOSPC, SVSTREAM_DISK_FULL },
{ (int)0xFFFF, SVSTREAM_GENERALERROR }
};
sal_uInt32 nRetVal = SVSTREAM_GENERALERROR; // Standardfehler
2000-09-18 16:07:07 +00:00
int i=0;
do
{
if ( errArr[i].nErr == nErrno )
{
nRetVal = errArr[i].sv;
break;
}
++i;
2000-09-18 16:07:07 +00:00
}
while( errArr[i].nErr != 0xFFFF );
return nRetVal;
}
static sal_uInt32 GetSvError( oslFileError nErrno )
{
static struct { oslFileError nErr; sal_uInt32 sv; } errArr[] =
{
{ osl_File_E_None, SVSTREAM_OK },
{ osl_File_E_ACCES, SVSTREAM_ACCESS_DENIED },
{ osl_File_E_BADF, SVSTREAM_INVALID_HANDLE },
{ osl_File_E_DEADLK, SVSTREAM_LOCKING_VIOLATION },
{ osl_File_E_INVAL, SVSTREAM_INVALID_PARAMETER },
{ osl_File_E_MFILE, SVSTREAM_TOO_MANY_OPEN_FILES },
{ osl_File_E_NFILE, SVSTREAM_TOO_MANY_OPEN_FILES },
{ osl_File_E_NOENT, SVSTREAM_FILE_NOT_FOUND },
{ osl_File_E_PERM, SVSTREAM_ACCESS_DENIED },
{ osl_File_E_ROFS, SVSTREAM_ACCESS_DENIED },
{ osl_File_E_AGAIN, SVSTREAM_LOCKING_VIOLATION },
{ osl_File_E_ISDIR, SVSTREAM_PATH_NOT_FOUND },
{ osl_File_E_LOOP, SVSTREAM_PATH_NOT_FOUND },
{ osl_File_E_MULTIHOP, SVSTREAM_PATH_NOT_FOUND },
{ osl_File_E_NOLINK, SVSTREAM_PATH_NOT_FOUND },
{ osl_File_E_NOTDIR, SVSTREAM_PATH_NOT_FOUND },
{ osl_File_E_EXIST, SVSTREAM_CANNOT_MAKE },
{ osl_File_E_NOSPC, SVSTREAM_DISK_FULL },
{ (oslFileError)0xFFFF, SVSTREAM_GENERALERROR }
};
sal_uInt32 nRetVal = SVSTREAM_GENERALERROR; // Standardfehler
int i=0;
do
{
if ( errArr[i].nErr == nErrno )
{
nRetVal = errArr[i].sv;
break;
}
++i;
}
while( errArr[i].nErr != (oslFileError)0xFFFF );
return nRetVal;
}
2000-09-18 16:07:07 +00:00
/*************************************************************************
|*
|* SvFileStream::SvFileStream()
|*
*************************************************************************/
SvFileStream::SvFileStream( const String& rFileName, StreamMode nOpenMode )
{
bIsOpen = sal_False;
2000-09-18 16:07:07 +00:00
nLockCounter = 0;
bIsWritable = sal_False;
2000-09-18 16:07:07 +00:00
pInstanceData = new StreamData;
SetBufferSize( 1024 );
// convert URL to SystemPath, if necessary
2001-05-10 13:20:57 +00:00
::rtl::OUString aSystemFileName;
if( FileBase::getSystemPathFromFileURL( rFileName , aSystemFileName )
!= FileBase::E_None )
2001-05-10 13:20:57 +00:00
{
aSystemFileName = rFileName;
}
Open( aSystemFileName, nOpenMode );
2000-09-18 16:07:07 +00:00
}
/*************************************************************************
|*
|* SvFileStream::SvFileStream()
|*
*************************************************************************/
SvFileStream::SvFileStream()
{
bIsOpen = sal_False;
2000-09-18 16:07:07 +00:00
nLockCounter = 0;
bIsWritable = sal_False;
2000-09-18 16:07:07 +00:00
pInstanceData = new StreamData;
SetBufferSize( 1024 );
}
/*************************************************************************
|*
|* SvFileStream::~SvFileStream()
|*
*************************************************************************/
SvFileStream::~SvFileStream()
{
Close();
InternalStreamLock::UnlockFile( 0, 0, this );
if (pInstanceData)
delete pInstanceData;
}
/*************************************************************************
|*
|* SvFileStream::GetFileHandle()
|*
*************************************************************************/
sal_uInt32 SvFileStream::GetFileHandle() const
2000-09-18 16:07:07 +00:00
{
sal_IntPtr handle;
if (osl_getFileOSHandle(pInstanceData->rHandle, &handle) == osl_File_E_None)
return (sal_uInt32) handle;
else
return (sal_uInt32) -1;
2000-09-18 16:07:07 +00:00
}
/*************************************************************************
|*
|* SvFileStream::IsA()
|*
*************************************************************************/
sal_uInt16 SvFileStream::IsA() const
2000-09-18 16:07:07 +00:00
{
return ID_FILESTREAM;
}
/*************************************************************************
|*
|* SvFileStream::GetData()
|*
*************************************************************************/
sal_Size SvFileStream::GetData( void* pData, sal_Size nSize )
2000-09-18 16:07:07 +00:00
{
#ifdef DBG_UTIL
rtl::OStringBuffer aTraceStr(
RTL_CONSTASCII_STRINGPARAM("SvFileStream::GetData(): "));
aTraceStr.append(static_cast<sal_Int64>(nSize));
aTraceStr.append(RTL_CONSTASCII_STRINGPARAM(" Bytes from "));
aTraceStr.append(rtl::OUStringToOString(aFilename,
osl_getThreadTextEncoding()));
OSL_TRACE("%s", aTraceStr.getStr());
2000-09-18 16:07:07 +00:00
#endif
sal_uInt64 nRead = 0;
2000-09-18 16:07:07 +00:00
if ( IsOpen() )
{
oslFileError rc = osl_readFile(pInstanceData->rHandle,pData,(sal_uInt64)nSize,&nRead);
if ( rc != osl_File_E_None )
{
SetError( ::GetSvError( rc ));
return -1;
}
2000-09-18 16:07:07 +00:00
}
return (sal_Size)nRead;
2000-09-18 16:07:07 +00:00
}
/*************************************************************************
|*
|* SvFileStream::PutData()
|*
*************************************************************************/
sal_Size SvFileStream::PutData( const void* pData, sal_Size nSize )
2000-09-18 16:07:07 +00:00
{
#ifdef DBG_UTIL
rtl::OStringBuffer aTraceStr(
RTL_CONSTASCII_STRINGPARAM("SvFileStream::PutData(): "));
aTraceStr.append(static_cast<sal_Int64>(nSize));
aTraceStr.append(RTL_CONSTASCII_STRINGPARAM(" Bytes to "));
aTraceStr.append(rtl::OUStringToOString(aFilename,
osl_getThreadTextEncoding()));
OSL_TRACE("%s", aTraceStr.getStr());
2000-09-18 16:07:07 +00:00
#endif
sal_uInt64 nWrite = 0;
2000-09-18 16:07:07 +00:00
if ( IsOpen() )
{
oslFileError rc = osl_writeFile(pInstanceData->rHandle,pData,(sal_uInt64)nSize,&nWrite);
if ( rc != osl_File_E_None )
{
SetError( ::GetSvError( rc ) );
return -1;
}
2000-09-18 16:07:07 +00:00
else if( !nWrite )
SetError( SVSTREAM_DISK_FULL );
2000-09-18 16:07:07 +00:00
}
return (sal_Size)nWrite;
2000-09-18 16:07:07 +00:00
}
/*************************************************************************
|*
|* SvFileStream::SeekPos()
|*
*************************************************************************/
sal_Size SvFileStream::SeekPos( sal_Size nPos )
2000-09-18 16:07:07 +00:00
{
if ( IsOpen() )
{
oslFileError rc;
sal_uInt64 nNewPos;
2000-09-18 16:07:07 +00:00
if ( nPos != STREAM_SEEK_TO_END )
rc = osl_setFilePos( pInstanceData->rHandle, osl_Pos_Absolut, nPos );
2000-09-18 16:07:07 +00:00
else
rc = osl_setFilePos( pInstanceData->rHandle, osl_Pos_End, 0 );
2000-09-18 16:07:07 +00:00
if ( rc != osl_File_E_None )
2000-09-18 16:07:07 +00:00
{
SetError( SVSTREAM_SEEK_ERROR );
return 0L;
}
rc = osl_getFilePos( pInstanceData->rHandle, &nNewPos );
return (sal_Size) nNewPos;
2000-09-18 16:07:07 +00:00
}
SetError( SVSTREAM_GENERALERROR );
return 0L;
}
/*************************************************************************
|*
|* SvFileStream::FlushData()
|*
*************************************************************************/
void SvFileStream::FlushData()
{
// lokal gibt es nicht
}
static char *pFileLockEnvVar = (char*)1;
/*************************************************************************
|*
|* SvFileStream::LockRange()
|*
*************************************************************************/
sal_Bool SvFileStream::LockRange( sal_Size nByteOffset, sal_Size nBytes )
2000-09-18 16:07:07 +00:00
{
struct flock aflock;
aflock.l_start = nByteOffset;
aflock.l_whence = SEEK_SET;
aflock.l_len = nBytes;
int nLockMode = 0;
if ( ! IsOpen() )
return sal_False;
2000-09-18 16:07:07 +00:00
if ( eStreamMode & STREAM_SHARE_DENYALL )
{
2000-09-18 16:07:07 +00:00
if (bIsWritable)
nLockMode = F_WRLCK;
else
nLockMode = F_RDLCK;
}
2000-09-18 16:07:07 +00:00
if ( eStreamMode & STREAM_SHARE_DENYREAD )
{
2000-09-18 16:07:07 +00:00
if (bIsWritable)
nLockMode = F_WRLCK;
else
{
SetError(SVSTREAM_LOCKING_VIOLATION);
return sal_False;
2000-09-18 16:07:07 +00:00
}
}
2000-09-18 16:07:07 +00:00
if ( eStreamMode & STREAM_SHARE_DENYWRITE )
{
2000-09-18 16:07:07 +00:00
if (bIsWritable)
nLockMode = F_WRLCK;
else
nLockMode = F_RDLCK;
}
2000-09-18 16:07:07 +00:00
if (!nLockMode)
return sal_True;
2000-09-18 16:07:07 +00:00
if( ! InternalStreamLock::LockFile( nByteOffset, nByteOffset+nBytes, this ) )
{
#if OSL_DEBUG_LEVEL > 1
2010-03-18 14:24:20 +01:00
fprintf( stderr, "InternalLock on %s [ %ld ... %ld ] failed\n",
2011-11-25 20:51:38 +00:00
rtl::OUStringToOString(aFilename, osl_getThreadTextEncoding()).getStr(), nByteOffset, nByteOffset+nBytes );
2000-09-18 16:07:07 +00:00
#endif
return sal_False;
2000-09-18 16:07:07 +00:00
}
// HACK: File-Locking nur via Environmentvariable einschalten
// um einen Haenger im Zusammenspiel mit einem Linux
// NFS-2-Server (kein Lockdaemon) zu verhindern.
// File-Locking ?ber NFS ist generell ein Performancekiller.
// HR, 22.10.1997 fuer SOLARIS
// HR, 18.05.1998 Environmentvariable
if ( pFileLockEnvVar == (char*)1 )
pFileLockEnvVar = getenv("STAR_ENABLE_FILE_LOCKING");
if ( ! pFileLockEnvVar )
return sal_True;
2000-09-18 16:07:07 +00:00
aflock.l_type = nLockMode;
sal_IntPtr iFileHandle;
oslFileError rc = osl_getFileOSHandle(pInstanceData->rHandle, &iFileHandle);
if (rc != osl_File_E_None)
{
SetError( ::GetSvError( rc ));
return sal_False;
}
if (fcntl((int)iFileHandle, F_GETLK, &aflock) == -1)
2000-09-18 16:07:07 +00:00
{
#if defined SOLARIS
if (errno == ENOSYS)
return sal_True;
2000-09-18 16:07:07 +00:00
#endif
SetError( ::GetSvError( errno ));
return sal_False;
2000-09-18 16:07:07 +00:00
}
if (aflock.l_type != F_UNLCK)
{
SetError(SVSTREAM_LOCKING_VIOLATION);
return sal_False;
2000-09-18 16:07:07 +00:00
}
aflock.l_type = nLockMode;
if (fcntl((int)iFileHandle, F_SETLK, &aflock) == -1)
2000-09-18 16:07:07 +00:00
{
SetError( ::GetSvError( errno ));
return sal_False;
2000-09-18 16:07:07 +00:00
}
return sal_True;
2000-09-18 16:07:07 +00:00
}
/*************************************************************************
|*
|* SvFileStream::UnlockRange()
|*
*************************************************************************/
sal_Bool SvFileStream::UnlockRange( sal_Size nByteOffset, sal_Size nBytes )
2000-09-18 16:07:07 +00:00
{
struct flock aflock;
aflock.l_type = F_UNLCK;
aflock.l_start = nByteOffset;
aflock.l_whence = SEEK_SET;
aflock.l_len = nBytes;
if ( ! IsOpen() )
return sal_False;
2000-09-18 16:07:07 +00:00
InternalStreamLock::UnlockFile( nByteOffset, nByteOffset+nBytes, this );
if ( ! (eStreamMode &
(STREAM_SHARE_DENYALL | STREAM_SHARE_DENYREAD | STREAM_SHARE_DENYWRITE)))
return sal_True;
2000-09-18 16:07:07 +00:00
// wenn File Locking ausgeschaltet, siehe SvFileStream::LockRange
if ( ! pFileLockEnvVar )
return sal_True;
2000-09-18 16:07:07 +00:00
sal_IntPtr iFileHandle;
oslFileError rc = osl_getFileOSHandle(pInstanceData->rHandle, &iFileHandle);
if (rc != osl_File_E_None)
{
SetError( ::GetSvError( rc ));
return sal_False;
}
if (fcntl((int)iFileHandle, F_SETLK, &aflock) != -1)
return sal_True;
2000-09-18 16:07:07 +00:00
SetError( ::GetSvError( errno ));
return sal_False;
2000-09-18 16:07:07 +00:00
}
/*************************************************************************
|*
|* SvFileStream::LockFile()
|*
*************************************************************************/
sal_Bool SvFileStream::LockFile()
2000-09-18 16:07:07 +00:00
{
return LockRange( 0UL, 0UL );
}
/*************************************************************************
|*
|* SvFileStream::UnlockFile()
|*
*************************************************************************/
sal_Bool SvFileStream::UnlockFile()
{
return UnlockRange( 0UL, 0UL );
}
2000-09-18 16:07:07 +00:00
/*************************************************************************
|*
|* SvFileStream::Open()
|*
*************************************************************************/
void SvFileStream::Open( const String& rFilename, StreamMode nOpenMode )
{
sal_uInt32 uFlags;
oslFileHandle nHandleTmp;
2000-09-18 16:07:07 +00:00
struct stat buf;
sal_Bool bStatValid = sal_False;
2000-09-18 16:07:07 +00:00
Close();
errno = 0;
eStreamMode = nOpenMode;
eStreamMode &= ~STREAM_TRUNC; // beim ReOpen nicht cutten
// !!! NoOp: Ansonsten ToAbs() verwendern
// !!! DirEntry aDirEntry( rFilename );
// !!! aFilename = aDirEntry.GetFull();
aFilename = rFilename;
#ifndef BOOTSTRAP
FSysRedirector::DoRedirect( aFilename );
#endif
2011-08-30 23:42:11 +01:00
rtl::OString aLocalFilename(rtl::OUStringToOString(aFilename, osl_getThreadTextEncoding()));
2000-09-18 16:07:07 +00:00
#ifdef DBG_UTIL
2011-08-30 23:42:11 +01:00
rtl::OStringBuffer aTraceStr(RTL_CONSTASCII_STRINGPARAM(
"SvFileStream::Open(): "));
aTraceStr.append(aLocalFilename);
OSL_TRACE( "%s", aTraceStr.getStr() );
2000-09-18 16:07:07 +00:00
#endif
if ( osl_lstatFilePath( aLocalFilename.getStr(), &buf ) == osl_File_E_None )
2000-09-18 16:07:07 +00:00
{
bStatValid = sal_True;
2000-09-18 16:07:07 +00:00
// SvFileStream soll kein Directory oeffnen
if( S_ISDIR( buf.st_mode ) )
{
SetError( ::GetSvError( EISDIR ) );
return;
}
}
if ( !( nOpenMode & STREAM_WRITE ) )
uFlags = osl_File_OpenFlag_Read;
2000-09-18 16:07:07 +00:00
else if ( !( nOpenMode & STREAM_READ ) )
uFlags = osl_File_OpenFlag_Write;
2000-09-18 16:07:07 +00:00
else
uFlags = osl_File_OpenFlag_Read | osl_File_OpenFlag_Write;
2000-09-18 16:07:07 +00:00
// Fix (MDA, 18.01.95): Bei RD_ONLY nicht mit O_CREAT oeffnen
// Wichtig auf Read-Only-Dateisystemen (wie CDROM)
if ( (!( nOpenMode & STREAM_NOCREATE )) && ( uFlags != osl_File_OpenFlag_Read ) )
uFlags |= osl_File_OpenFlag_Create;
2000-09-18 16:07:07 +00:00
if ( nOpenMode & STREAM_TRUNC )
uFlags |= osl_File_OpenFlag_Trunc;
uFlags |= osl_File_OpenFlag_NoExcl | osl_File_OpenFlag_NoLock;
2000-09-18 16:07:07 +00:00
if ( nOpenMode & STREAM_WRITE)
{
if ( nOpenMode & STREAM_COPY_ON_SYMLINK )
{
if ( bStatValid && S_ISLNK( buf.st_mode ) < 0 )
{
char *pBuf = new char[ 1024+1 ];
2011-08-30 23:42:11 +01:00
if ( readlink( aLocalFilename.getStr(), pBuf, 1024 ) > 0 )
2000-09-18 16:07:07 +00:00
{
2011-08-30 23:42:11 +01:00
if ( unlink(aLocalFilename.getStr()) == 0 )
2000-09-18 16:07:07 +00:00
{
#ifdef DBG_UTIL
fprintf( stderr,
"Copying file on symbolic link (%s).\n",
2011-08-30 23:42:11 +01:00
aLocalFilename.getStr() );
2000-09-18 16:07:07 +00:00
#endif
String aTmpString( pBuf, osl_getThreadTextEncoding() );
const DirEntry aSourceEntry( aTmpString );
const DirEntry aTargetEntry( aFilename );
FileCopier aFileCopier( aSourceEntry, aTargetEntry );
aFileCopier.Execute();
}
}
delete [] pBuf;
2000-09-18 16:07:07 +00:00
}
}
}
oslFileError rc = osl_openFilePath( aLocalFilename.getStr(),&nHandleTmp, uFlags );
2000-09-18 16:07:07 +00:00
if ( rc != osl_File_E_None )
2000-09-18 16:07:07 +00:00
{
if ( uFlags & osl_File_OpenFlag_Write )
2000-09-18 16:07:07 +00:00
{
// auf Lesen runterschalten
uFlags &= ~osl_File_OpenFlag_Write;
rc = osl_openFilePath( aLocalFilename.getStr(),
&nHandleTmp,
uFlags );
2000-09-18 16:07:07 +00:00
}
}
if ( rc == osl_File_E_None )
2000-09-18 16:07:07 +00:00
{
pInstanceData->rHandle = nHandleTmp;
bIsOpen = sal_True;
if ( uFlags & osl_File_OpenFlag_Write )
bIsWritable = sal_True;
2000-09-18 16:07:07 +00:00
if ( !LockFile() ) // ganze Datei
{
rc = osl_closeFile( nHandleTmp );
bIsOpen = sal_False;
bIsWritable = sal_False;
pInstanceData->rHandle = 0;
2000-09-18 16:07:07 +00:00
}
}
else
SetError( ::GetSvError( rc ) );
2000-09-18 16:07:07 +00:00
}
/*************************************************************************
|*
|* SvFileStream::Close()
|*
*************************************************************************/
void SvFileStream::Close()
{
InternalStreamLock::UnlockFile( 0, 0, this );
2011-08-23 00:38:42 +01:00
if ( IsOpen() )
2000-09-18 16:07:07 +00:00
{
#ifdef DBG_UTIL
2011-08-23 00:38:42 +01:00
rtl::OStringBuffer aTraceStr(
RTL_CONSTASCII_STRINGPARAM("SvFileStream::Close(): "));
aTraceStr.append(rtl::OUStringToOString(aFilename,
osl_getThreadTextEncoding()));
OSL_TRACE("%s", aTraceStr.getStr());
2000-09-18 16:07:07 +00:00
#endif
Flush();
osl_closeFile( pInstanceData->rHandle );
pInstanceData->rHandle = 0;
2000-09-18 16:07:07 +00:00
}
bIsOpen = sal_False;
bIsWritable = sal_False;
2000-09-18 16:07:07 +00:00
SvStream::ClearBuffer();
SvStream::ClearError();
}
/*************************************************************************
|*
|* SvFileStream::ResetError()
|*
|* Beschreibung STREAM.SDW; Setzt Filepointer auf Dateianfang
|*
*************************************************************************/
void SvFileStream::ResetError()
{
SvStream::ClearError();
}
/*************************************************************************
|*
|* SvFileStream::SetSize()
|*
|* Beschreibung STREAM.SDW;
|*
*************************************************************************/
void SvFileStream::SetSize (sal_Size nSize)
2000-09-18 16:07:07 +00:00
{
if (IsOpen())
2000-09-18 16:07:07 +00:00
{
oslFileError rc = osl_setFileSize( pInstanceData->rHandle, nSize );
if (rc != osl_File_E_None )
{
SetError ( ::GetSvError( rc ));
}
2000-09-18 16:07:07 +00:00
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */