blob: c526083c34f33a006843f1d6c553cf7c8ea8c6c9 [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// no include "precompiled_tools.hxx" because this file is included in strmsys.cxx
#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 <vos/mutex.hxx>
#include <osl/thread.h> // osl_getThreadTextEncoding
// class FileBase
#include <osl/file.hxx>
#include <rtl/instance.hxx>
using namespace osl;
// -----------------------------------------------------------------------
// ----------------
// - InternalLock -
// ----------------
class InternalStreamLock;
DECLARE_LIST( InternalStreamLockList, InternalStreamLock* )
namespace { struct LockList : public rtl::Static< InternalStreamLockList, LockList > {}; }
#ifndef BOOTSTRAP
namespace { struct LockMutex : public rtl::Static< vos::OMutex, LockMutex > {}; }
#endif
class InternalStreamLock
{
sal_Size m_nStartPos;
sal_Size m_nEndPos;
SvFileStream* m_pStream;
struct stat m_aStat;
InternalStreamLock( sal_Size, sal_Size, SvFileStream* );
~InternalStreamLock();
public:
static sal_Bool LockFile( sal_Size nStart, sal_Size nEnd, SvFileStream* );
static void UnlockFile( sal_Size nStart, sal_Size nEnd, SvFileStream* );
};
InternalStreamLock::InternalStreamLock(
sal_Size nStart,
sal_Size nEnd,
SvFileStream* pStream ) :
m_nStartPos( nStart ),
m_nEndPos( nEnd ),
m_pStream( pStream )
{
ByteString aFileName(m_pStream->GetFileName(), osl_getThreadTextEncoding());
stat( aFileName.GetBuffer(), &m_aStat );
LockList::get().Insert( this, LIST_APPEND );
#if OSL_DEBUG_LEVEL > 1
fprintf( stderr, "locked %s", aFileName.GetBuffer() );
if( m_nStartPos || m_nEndPos )
fprintf(stderr, " [ %ld ... %ld ]", m_nStartPos, m_nEndPos );
fprintf( stderr, "\n" );
#endif
}
InternalStreamLock::~InternalStreamLock()
{
LockList::get().Remove( this );
#if OSL_DEBUG_LEVEL > 1
ByteString aFileName(m_pStream->GetFileName(), osl_getThreadTextEncoding());
fprintf( stderr, "unlocked %s", aFileName.GetBuffer() );
if( m_nStartPos || m_nEndPos )
fprintf(stderr, " [ %ld ... %ld ]", m_nStartPos, m_nEndPos );
fprintf( stderr, "\n" );
#endif
}
sal_Bool InternalStreamLock::LockFile( sal_Size nStart, sal_Size nEnd, SvFileStream* pStream )
{
#ifndef BOOTSTRAP
vos:: OGuard aGuard( LockMutex::get() );
#endif
ByteString aFileName(pStream->GetFileName(), osl_getThreadTextEncoding());
struct stat aStat;
if( stat( aFileName.GetBuffer(), &aStat ) )
return sal_False;
if( S_ISDIR( aStat.st_mode ) )
return sal_True;
InternalStreamLock* pLock = NULL;
InternalStreamLockList &rLockList = LockList::get();
for( sal_uIntPtr i = 0; i < rLockList.Count(); ++i )
{
pLock = rLockList.GetObject( i );
if( aStat.st_ino == pLock->m_aStat.st_ino )
{
sal_Bool bDenyByOptions = sal_False;
StreamMode nLockMode = pLock->m_pStream->GetStreamMode();
StreamMode nNewMode = pStream->GetStreamMode();
if( nLockMode & STREAM_SHARE_DENYALL )
bDenyByOptions = sal_True;
else if( ( nLockMode & STREAM_SHARE_DENYWRITE ) &&
( nNewMode & STREAM_WRITE ) )
bDenyByOptions = sal_True;
else if( ( nLockMode & STREAM_SHARE_DENYREAD ) &&
( nNewMode & STREAM_READ ) )
bDenyByOptions = sal_True;
if( bDenyByOptions )
{
if( pLock->m_nStartPos == 0 && pLock->m_nEndPos == 0 ) // whole file is already locked
return sal_False;
if( nStart == 0 && nEnd == 0) // cannot lock whole file
return sal_False;
if( ( nStart < pLock->m_nStartPos && nEnd > pLock->m_nStartPos ) ||
( nStart < pLock->m_nEndPos && nEnd > pLock->m_nEndPos ) )
return sal_False;
}
}
}
pLock = new InternalStreamLock( nStart, nEnd, pStream );
return sal_True;
}
void InternalStreamLock::UnlockFile( sal_Size nStart, sal_Size nEnd, SvFileStream* pStream )
{
#ifndef BOOTSTRAP
vos:: OGuard aGuard( LockMutex::get() );
#endif
InternalStreamLock* pLock = NULL;
InternalStreamLockList &rLockList = LockList::get();
if( nStart == 0 && nEnd == 0 )
{
for( sal_uIntPtr i = 0; i < rLockList.Count(); ++i )
{
if( ( pLock = rLockList.GetObject( i ) )->m_pStream == pStream )
{
delete pLock;
i--;
}
}
return;
}
for( sal_uIntPtr i = 0; i < rLockList.Count(); ++i )
{
if( ( pLock = rLockList.GetObject( i ) )->m_pStream == pStream &&
nStart == pLock->m_nStartPos && nEnd == pLock->m_nEndPos )
{
delete pLock;
return;
}
}
}
// --------------
// - StreamData -
// --------------
class StreamData
{
public:
int nHandle;
StreamData() { nHandle = 0; }
};
// -----------------------------------------------------------------------
static sal_uInt32 GetSvError( int nErrno )
{
static struct { int nErr; sal_uInt32 sv; } errArr[] =
{
{ 0, SVSTREAM_OK },
{ EACCES, SVSTREAM_ACCESS_DENIED },
{ EBADF, SVSTREAM_INVALID_HANDLE },
#if defined( RS6000 ) || defined( ALPHA ) || defined( HP9000 ) || defined( NETBSD ) || defined(FREEBSD) || defined(MACOSX) || defined(__FreeBSD_kernel__)
{ 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( ALPHA ) && ! defined( NETBSD ) && ! defined (FREEBSD) && ! defined (MACOSX) && ! defined(__FreeBSD_kernel__)
{ 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
int i=0;
do
{
if ( errArr[i].nErr == nErrno )
{
nRetVal = errArr[i].sv;
break;
}
++i;
}
while( errArr[i].nErr != 0xFFFF );
return nRetVal;
}
/*************************************************************************
|*
|* SvFileStream::SvFileStream()
|*
|* Beschreibung STREAM.SDW
|* Ersterstellung OV 08.06.94
|* Letzte Aenderung OV 08.06.94
|*
*************************************************************************/
SvFileStream::SvFileStream( const String& rFileName, StreamMode nOpenMode )
{
bIsOpen = sal_False;
nLockCounter = 0;
bIsWritable = sal_False;
pInstanceData = new StreamData;
SetBufferSize( 1024 );
// convert URL to SystemPath, if necessary
::rtl::OUString aSystemFileName;
if( FileBase::getSystemPathFromFileURL( rFileName , aSystemFileName )
!= FileBase::E_None )
{
aSystemFileName = rFileName;
}
Open( aSystemFileName, nOpenMode );
}
/*************************************************************************
|*
|* SvFileStream::SvFileStream()
|*
|* Beschreibung STREAM.SDW
|* Ersterstellung OV 22.11.94
|* Letzte Aenderung OV 22.11.94
|*
*************************************************************************/
SvFileStream::SvFileStream()
{
bIsOpen = sal_False;
nLockCounter = 0;
bIsWritable = sal_False;
pInstanceData = new StreamData;
SetBufferSize( 1024 );
}
/*************************************************************************
|*
|* SvFileStream::~SvFileStream()
|*
|* Beschreibung STREAM.SDW
|* Ersterstellung OV 22.11.94
|* Letzte Aenderung OV 22.11.94
|*
*************************************************************************/
SvFileStream::~SvFileStream()
{
Close();
InternalStreamLock::UnlockFile( 0, 0, this );
if (pInstanceData)
delete pInstanceData;
}
/*************************************************************************
|*
|* SvFileStream::GetFileHandle()
|*
|* Beschreibung STREAM.SDW
|* Ersterstellung OV 22.11.94
|* Letzte Aenderung OV 22.11.94
|*
*************************************************************************/
sal_uInt32 SvFileStream::GetFileHandle() const
{
return (sal_uInt32)pInstanceData->nHandle;
}
/*************************************************************************
|*
|* SvFileStream::IsA()
|*
|* Beschreibung STREAM.SDW
|* Ersterstellung OV 14.06.94
|* Letzte Aenderung OV 14.06.94
|*
*************************************************************************/
sal_uInt16 SvFileStream::IsA() const
{
return ID_FILESTREAM;
}
/*************************************************************************
|*
|* SvFileStream::GetData()
|*
|* Beschreibung STREAM.SDW
|* Ersterstellung OV 15.06.94
|* Letzte Aenderung OV 15.06.94
|*
*************************************************************************/
sal_Size SvFileStream::GetData( void* pData, sal_Size nSize )
{
#ifdef DBG_UTIL
ByteString aTraceStr( "SvFileStream::GetData(): " );
aTraceStr += ByteString::CreateFromInt64(nSize);
aTraceStr += " Bytes from ";
aTraceStr += ByteString(aFilename, osl_getThreadTextEncoding());
DBG_TRACE( aTraceStr.GetBuffer() );
#endif
int nRead = 0;
if ( IsOpen() )
{
nRead = read(pInstanceData->nHandle,pData,(unsigned)nSize);
if ( nRead == -1 )
SetError( ::GetSvError( errno ));
}
return (sal_Size)nRead;
}
/*************************************************************************
|*
|* SvFileStream::PutData()
|*
|* Beschreibung STREAM.SDW
|* Ersterstellung OV 15.06.94
|* Letzte Aenderung OV 15.06.94
|*
*************************************************************************/
sal_Size SvFileStream::PutData( const void* pData, sal_Size nSize )
{
#ifdef DBG_UTIL
ByteString aTraceStr( "SvFileStrean::PutData: " );
aTraceStr += ByteString::CreateFromInt64(nSize);
aTraceStr += " Bytes to ";
aTraceStr += ByteString(aFilename, osl_getThreadTextEncoding());
DBG_TRACE( aTraceStr.GetBuffer() );
#endif
int nWrite = 0;
if ( IsOpen() )
{
nWrite = write(pInstanceData->nHandle,pData,(unsigned)nSize);
if ( nWrite == -1 )
SetError( ::GetSvError( errno ) );
else if( !nWrite )
SetError( SVSTREAM_DISK_FULL );
}
return (sal_Size)nWrite;
}
/*************************************************************************
|*
|* SvFileStream::SeekPos()
|*
|* Beschreibung STREAM.SDW
|* Ersterstellung OV 15.06.94
|* Letzte Aenderung OV 15.06.94
|*
*************************************************************************/
sal_Size SvFileStream::SeekPos( sal_Size nPos )
{
if ( IsOpen() )
{
long nNewPos;
if ( nPos != STREAM_SEEK_TO_END )
nNewPos = lseek( pInstanceData->nHandle, (long)nPos, SEEK_SET );
else
nNewPos = lseek( pInstanceData->nHandle, 0L, SEEK_END );
if ( nNewPos == -1 )
{
SetError( SVSTREAM_SEEK_ERROR );
return 0L;
}
// langsam aber sicherer als return nNewPos
return lseek(pInstanceData->nHandle,0L,SEEK_CUR);
// return nNewPos;
}
SetError( SVSTREAM_GENERALERROR );
return 0L;
}
/*************************************************************************
|*
|* SvFileStream::FlushData()
|*
|* Beschreibung STREAM.SDW
|* Ersterstellung OV 15.06.94
|* Letzte Aenderung OV 15.06.94
|*
*************************************************************************/
void SvFileStream::FlushData()
{
// lokal gibt es nicht
}
static char *pFileLockEnvVar = (char*)1;
/*************************************************************************
|*
|* SvFileStream::LockRange()
|*
|* Beschreibung STREAM.SDW
|* Ersterstellung OV 15.06.94
|* Letzte Aenderung OV 15.06.94
|*
*************************************************************************/
sal_Bool SvFileStream::LockRange( sal_Size nByteOffset, sal_Size nBytes )
{
struct flock aflock;
aflock.l_start = nByteOffset;
aflock.l_whence = SEEK_SET;
aflock.l_len = nBytes;
int nLockMode = 0;
if ( ! IsOpen() )
return sal_False;
if ( eStreamMode & STREAM_SHARE_DENYALL )
{
if (bIsWritable)
nLockMode = F_WRLCK;
else
nLockMode = F_RDLCK;
}
if ( eStreamMode & STREAM_SHARE_DENYREAD )
{
if (bIsWritable)
nLockMode = F_WRLCK;
else
{
SetError(SVSTREAM_LOCKING_VIOLATION);
return sal_False;
}
}
if ( eStreamMode & STREAM_SHARE_DENYWRITE )
{
if (bIsWritable)
nLockMode = F_WRLCK;
else
nLockMode = F_RDLCK;
}
if (!nLockMode)
return sal_True;
if( ! InternalStreamLock::LockFile( nByteOffset, nByteOffset+nBytes, this ) )
{
#if OSL_DEBUG_LEVEL > 1
fprintf( stderr, "InternalLock on %s [ %ld ... %ld ] failed\n",
ByteString(aFilename, osl_getThreadTextEncoding()).GetBuffer(), nByteOffset, nByteOffset+nBytes );
#endif
return sal_False;
}
// 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
// CP, 30.11.1997 fuer HPUX
// ER, 18.12.1997 fuer IRIX
// HR, 18.05.1998 Environmentvariable
if ( pFileLockEnvVar == (char*)1 )
pFileLockEnvVar = getenv("STAR_ENABLE_FILE_LOCKING");
if ( ! pFileLockEnvVar )
return sal_True;
aflock.l_type = nLockMode;
if (fcntl(pInstanceData->nHandle, F_GETLK, &aflock) == -1)
{
#if ( defined HPUX && defined BAD_UNION )
#ifdef DBG_UTIL
fprintf( stderr, "***** FCNTL(lock):errno = %d\n", errno );
#endif
if ( errno == EINVAL || errno == ENOSYS )
return sal_True;
#endif
#if defined SINIX
if (errno == EINVAL)
return sal_True;
#endif
#if defined SOLARIS
if (errno == ENOSYS)
return sal_True;
#endif
SetError( ::GetSvError( errno ));
return sal_False;
}
if (aflock.l_type != F_UNLCK)
{
SetError(SVSTREAM_LOCKING_VIOLATION);
return sal_False;
}
aflock.l_type = nLockMode;
if (fcntl(pInstanceData->nHandle, F_SETLK, &aflock) == -1)
{
SetError( ::GetSvError( errno ));
return sal_False;
}
return sal_True;
}
/*************************************************************************
|*
|* SvFileStream::UnlockRange()
|*
|* Beschreibung STREAM.SDW
|* Ersterstellung OV 15.06.94
|* Letzte Aenderung OV 15.06.94
|*
*************************************************************************/
sal_Bool SvFileStream::UnlockRange( sal_Size nByteOffset, sal_Size nBytes )
{
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;
InternalStreamLock::UnlockFile( nByteOffset, nByteOffset+nBytes, this );
if ( ! (eStreamMode &
(STREAM_SHARE_DENYALL | STREAM_SHARE_DENYREAD | STREAM_SHARE_DENYWRITE)))
return sal_True;
// wenn File Locking ausgeschaltet, siehe SvFileStream::LockRange
if ( ! pFileLockEnvVar )
return sal_True;
if (fcntl(pInstanceData->nHandle, F_SETLK, &aflock) != -1)
return sal_True;
#if ( defined HPUX && defined BAD_UNION )
#ifdef DBG_UTIL
fprintf( stderr, "***** FCNTL(unlock):errno = %d\n", errno );
#endif
if ( errno == EINVAL || errno == ENOSYS )
return sal_True;
#endif
#if ( defined SINIX )
if (errno == EINVAL)
return sal_True;
#endif
SetError( ::GetSvError( errno ));
return sal_False;
}
/*************************************************************************
|*
|* SvFileStream::LockFile()
|*
|* Beschreibung STREAM.SDW
|* Ersterstellung OV 15.06.94
|* Letzte Aenderung OV 15.06.94
|*
*************************************************************************/
sal_Bool SvFileStream::LockFile()
{
return LockRange( 0UL, 0UL );
}
/*************************************************************************
|*
|* SvFileStream::UnlockFile()
|*
|* Beschreibung STREAM.SDW
|* Ersterstellung OV 15.06.94
|* Letzte Aenderung OV 15.06.94
|*
*************************************************************************/
sal_Bool SvFileStream::UnlockFile()
{
return UnlockRange( 0UL, 0UL );
}
/*************************************************************************
|*
|* SvFileStream::Open()
|*
|* Beschreibung STREAM.SDW
|* Ersterstellung OV 15.06.94
|* Letzte Aenderung OV 15.06.94
|*
*************************************************************************/
void SvFileStream::Open( const String& rFilename, StreamMode nOpenMode )
{
int nAccess, nAccessRW;
int nMode;
int nHandleTmp;
struct stat buf;
sal_Bool bStatValid = sal_False;
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
ByteString aLocalFilename(aFilename, osl_getThreadTextEncoding());
#ifdef DBG_UTIL
ByteString aTraceStr( "SvFileStream::Open(): " );
aTraceStr += aLocalFilename;
DBG_TRACE( aTraceStr.GetBuffer() );
#endif
if ( lstat( aLocalFilename.GetBuffer(), &buf ) == 0 )
{
bStatValid = sal_True;
// SvFileStream soll kein Directory oeffnen
if( S_ISDIR( buf.st_mode ) )
{
SetError( ::GetSvError( EISDIR ) );
return;
}
}
if ( !( nOpenMode & STREAM_WRITE ) )
nAccessRW = O_RDONLY;
else if ( !( nOpenMode & STREAM_READ ) )
nAccessRW = O_WRONLY;
else
nAccessRW = O_RDWR;
nAccess = 0;
// Fix (MDA, 18.01.95): Bei RD_ONLY nicht mit O_CREAT oeffnen
// Wichtig auf Read-Only-Dateisystemen (wie CDROM)
if ( (!( nOpenMode & STREAM_NOCREATE )) && ( nAccessRW != O_RDONLY ) )
nAccess |= O_CREAT;
if ( nOpenMode & STREAM_TRUNC )
nAccess |= O_TRUNC;
nMode = S_IREAD | S_IROTH | S_IRGRP;
if ( nOpenMode & STREAM_WRITE)
{
nMode |= (S_IWRITE | S_IWOTH | S_IWGRP);
if ( nOpenMode & STREAM_COPY_ON_SYMLINK )
{
if ( bStatValid && S_ISLNK( buf.st_mode ) < 0 )
{
char *pBuf = new char[ 1024+1 ];
if ( readlink( aLocalFilename.GetBuffer(), pBuf, 1024 ) > 0 )
{
if ( unlink(aLocalFilename.GetBuffer()) == 0 )
{
#ifdef DBG_UTIL
fprintf( stderr,
"Copying file on symbolic link (%s).\n",
aLocalFilename.GetBuffer() );
#endif
String aTmpString( pBuf, osl_getThreadTextEncoding() );
const DirEntry aSourceEntry( aTmpString );
const DirEntry aTargetEntry( aFilename );
FileCopier aFileCopier( aSourceEntry, aTargetEntry );
aFileCopier.Execute();
}
}
delete [] pBuf;
}
}
}
nHandleTmp = open(aLocalFilename.GetBuffer(),nAccessRW|nAccess, nMode );
if ( nHandleTmp == -1 )
{
if ( nAccessRW != O_RDONLY )
{
// auf Lesen runterschalten
nAccessRW = O_RDONLY;
nAccess = 0;
nMode = S_IREAD | S_IROTH | S_IRGRP;
nHandleTmp =open( aLocalFilename.GetBuffer(),
nAccessRW|nAccess,
nMode );
}
}
if ( nHandleTmp != -1 )
{
pInstanceData->nHandle = nHandleTmp;
bIsOpen = sal_True;
if ( nAccessRW != O_RDONLY )
bIsWritable = sal_True;
if ( !LockFile() ) // ganze Datei
{
close( nHandleTmp );
bIsOpen = sal_False;
bIsWritable = sal_False;
pInstanceData->nHandle = 0;
}
}
else
SetError( ::GetSvError( errno ) );
}
/*************************************************************************
|*
|* SvFileStream::ReOpen()
|*
|* Beschreibung STREAM.SDW
|* Ersterstellung OV 15.06.94
|* Letzte Aenderung OV 15.06.94
|*
*************************************************************************/
void SvFileStream::ReOpen()
{
if ( !bIsOpen && aFilename.Len() )
Open( aFilename, eStreamMode );
}
/*************************************************************************
|*
|* SvFileStream::Close()
|*
|* Beschreibung STREAM.SDW
|* Ersterstellung OV 15.06.94
|* Letzte Aenderung OV 15.06.94
|*
*************************************************************************/
void SvFileStream::Close()
{
InternalStreamLock::UnlockFile( 0, 0, this );
if ( IsOpen() )
{
#ifdef DBG_UTIL
ByteString aTraceStr( "SvFileStream::Close(): " );
aTraceStr += ByteString(aFilename, osl_getThreadTextEncoding());
DBG_TRACE( aTraceStr.GetBuffer() );
#endif
Flush();
close( pInstanceData->nHandle );
pInstanceData->nHandle = 0;
}
bIsOpen = sal_False;
bIsWritable = sal_False;
SvStream::ClearBuffer();
SvStream::ClearError();
}
/*************************************************************************
|*
|* SvFileStream::ResetError()
|*
|* Beschreibung STREAM.SDW; Setzt Filepointer auf Dateianfang
|* Ersterstellung OV 15.06.94
|* Letzte Aenderung OV 15.06.94
|*
*************************************************************************/
void SvFileStream::ResetError()
{
SvStream::ClearError();
}
/*************************************************************************
|*
|* SvFileStream::SetSize()
|*
|* Beschreibung STREAM.SDW;
|* Ersterstellung OV 15.06.94
|* Letzte Aenderung OV 15.06.94
|*
*************************************************************************/
void SvFileStream::SetSize (sal_Size nSize)
{
if (IsOpen())
{
int fd = pInstanceData->nHandle;
if (::ftruncate (fd, (off_t)nSize) < 0)
{
// Save original error.
sal_uInt32 nErr = ::GetSvError (errno);
// Check against current size. Fail upon 'shrink'.
struct stat aStat;
if (::fstat (fd, &aStat) < 0)
{
SetError (nErr);
return;
}
if ((sal::static_int_cast< sal_sSize >(nSize) <= aStat.st_size))
{
// Failure upon 'shrink'. Return original error.
SetError (nErr);
return;
}
// Save current position.
sal_Size nCurPos = (sal_Size)::lseek (fd, (off_t)0, SEEK_CUR);
if (nCurPos == (sal_Size)(-1))
{
SetError (nErr);
return;
}
// Try 'expand' via 'lseek()' and 'write()'.
if (::lseek (fd, (off_t)(nSize - 1), SEEK_SET) < 0)
{
SetError (nErr);
return;
}
if (::write (fd, (char*)"", (size_t)1) < 0)
{
// Failure. Restore saved position.
if (::lseek (fd, (off_t)nCurPos, SEEK_SET) < 0)
{
// Double failure.
}
SetError (nErr);
return;
}
// Success. Restore saved position.
if (::lseek (fd, (off_t)nCurPos, SEEK_SET) < 0)
{
SetError (nErr);
return;
}
}
}
}