1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: strmunx.cxx,v $
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 // no include "precompiled_tools.hxx" because this file is included in strmsys.cxx
40 #include <stdlib.h> // fuer getenv()
42 #include <tools/debug.hxx>
43 #include <tools/fsys.hxx>
44 #include <tools/stream.hxx>
46 #include <vos/mutex.hxx>
47 #include <osl/thread.h> // osl_getThreadTextEncoding
50 #include <osl/file.hxx>
51 #include <rtl/instance.hxx>
55 // -----------------------------------------------------------------------
61 class InternalStreamLock
;
62 DECLARE_LIST( InternalStreamLockList
, InternalStreamLock
* )
63 namespace { struct LockList
: public rtl::Static
< InternalStreamLockList
, LockList
> {}; }
66 namespace { struct LockMutex
: public rtl::Static
< NAMESPACE_VOS(OMutex
), LockMutex
> {}; }
69 class InternalStreamLock
73 SvFileStream
* m_pStream
;
76 InternalStreamLock( sal_Size
, sal_Size
, SvFileStream
* );
77 ~InternalStreamLock();
79 static sal_Bool
LockFile( sal_Size nStart
, sal_Size nEnd
, SvFileStream
* );
80 static void UnlockFile( sal_Size nStart
, sal_Size nEnd
, SvFileStream
* );
83 InternalStreamLock::InternalStreamLock(
86 SvFileStream
* pStream
) :
87 m_nStartPos( nStart
),
91 ByteString
aFileName(m_pStream
->GetFileName(), osl_getThreadTextEncoding());
92 stat( aFileName
.GetBuffer(), &m_aStat
);
93 LockList::get().Insert( this, LIST_APPEND
);
94 #if OSL_DEBUG_LEVEL > 1
95 fprintf( stderr
, "locked %s", aFileName
.GetBuffer() );
96 if( m_nStartPos
|| m_nEndPos
)
97 fprintf(stderr
, " [ %d ... %d ]", m_nStartPos
, m_nEndPos
);
98 fprintf( stderr
, "\n" );
102 InternalStreamLock::~InternalStreamLock()
104 LockList::get().Remove( this );
105 #if OSL_DEBUG_LEVEL > 1
106 ByteString
aFileName(m_pStream
->GetFileName(), osl_getThreadTextEncoding());
107 fprintf( stderr
, "unlocked %s", aFileName
.GetBuffer() );
108 if( m_nStartPos
|| m_nEndPos
)
109 fprintf(stderr
, " [ %d ... %d ]", m_nStartPos
, m_nEndPos
);
110 fprintf( stderr
, "\n" );
114 sal_Bool
InternalStreamLock::LockFile( sal_Size nStart
, sal_Size nEnd
, SvFileStream
* pStream
)
117 NAMESPACE_VOS( OGuard
) aGuard( LockMutex::get() );
119 ByteString
aFileName(pStream
->GetFileName(), osl_getThreadTextEncoding());
121 if( stat( aFileName
.GetBuffer(), &aStat
) )
124 if( S_ISDIR( aStat
.st_mode
) )
127 InternalStreamLock
* pLock
= NULL
;
128 InternalStreamLockList
&rLockList
= LockList::get();
129 for( ULONG i
= 0; i
< rLockList
.Count(); ++i
)
131 pLock
= rLockList
.GetObject( i
);
132 if( aStat
.st_ino
== pLock
->m_aStat
.st_ino
)
134 sal_Bool bDenyByOptions
= sal_False
;
135 StreamMode nLockMode
= pLock
->m_pStream
->GetStreamMode();
136 StreamMode nNewMode
= pStream
->GetStreamMode();
138 if( nLockMode
& STREAM_SHARE_DENYALL
)
139 bDenyByOptions
= sal_True
;
140 else if( ( nLockMode
& STREAM_SHARE_DENYWRITE
) &&
141 ( nNewMode
& STREAM_WRITE
) )
142 bDenyByOptions
= sal_True
;
143 else if( ( nLockMode
& STREAM_SHARE_DENYREAD
) &&
144 ( nNewMode
& STREAM_READ
) )
145 bDenyByOptions
= sal_True
;
149 if( pLock
->m_nStartPos
== 0 && pLock
->m_nEndPos
== 0 ) // whole file is already locked
151 if( nStart
== 0 && nEnd
== 0) // cannot lock whole file
154 if( ( nStart
< pLock
->m_nStartPos
&& nEnd
> pLock
->m_nStartPos
) ||
155 ( nStart
< pLock
->m_nEndPos
&& nEnd
> pLock
->m_nEndPos
) )
160 pLock
= new InternalStreamLock( nStart
, nEnd
, pStream
);
164 void InternalStreamLock::UnlockFile( sal_Size nStart
, sal_Size nEnd
, SvFileStream
* pStream
)
167 NAMESPACE_VOS( OGuard
) aGuard( LockMutex::get() );
169 InternalStreamLock
* pLock
= NULL
;
170 InternalStreamLockList
&rLockList
= LockList::get();
171 if( nStart
== 0 && nEnd
== 0 )
173 for( ULONG i
= 0; i
< rLockList
.Count(); ++i
)
175 if( ( pLock
= rLockList
.GetObject( i
) )->m_pStream
== pStream
)
183 for( ULONG i
= 0; i
< rLockList
.Count(); ++i
)
185 if( ( pLock
= rLockList
.GetObject( i
) )->m_pStream
== pStream
&&
186 nStart
== pLock
->m_nStartPos
&& nEnd
== pLock
->m_nEndPos
)
203 StreamData() { nHandle
= 0; }
206 // -----------------------------------------------------------------------
208 static sal_uInt32
GetSvError( int nErrno
)
210 static struct { int nErr
; sal_uInt32 sv
; } errArr
[] =
213 { EACCES
, SVSTREAM_ACCESS_DENIED
},
214 { EBADF
, SVSTREAM_INVALID_HANDLE
},
215 #if defined( RS6000 ) || defined( ALPHA ) || defined( HP9000 ) || defined( NETBSD ) || defined(FREEBSD) || defined(MACOSX)
216 { EDEADLK
, SVSTREAM_LOCKING_VIOLATION
},
218 { EDEADLOCK
, SVSTREAM_LOCKING_VIOLATION
},
220 { EINVAL
, SVSTREAM_INVALID_PARAMETER
},
221 { EMFILE
, SVSTREAM_TOO_MANY_OPEN_FILES
},
222 { ENFILE
, SVSTREAM_TOO_MANY_OPEN_FILES
},
223 { ENOENT
, SVSTREAM_FILE_NOT_FOUND
},
224 { EPERM
, SVSTREAM_ACCESS_DENIED
},
225 { EROFS
, SVSTREAM_ACCESS_DENIED
},
226 { EAGAIN
, SVSTREAM_LOCKING_VIOLATION
},
227 { EISDIR
, SVSTREAM_PATH_NOT_FOUND
},
228 { ELOOP
, SVSTREAM_PATH_NOT_FOUND
},
229 #if ! defined( RS6000 ) && ! defined( ALPHA ) && ! defined( NETBSD ) && ! defined (FREEBSD) && ! defined (MACOSX)
230 { EMULTIHOP
, SVSTREAM_PATH_NOT_FOUND
},
231 { ENOLINK
, SVSTREAM_PATH_NOT_FOUND
},
233 { ENOTDIR
, SVSTREAM_PATH_NOT_FOUND
},
234 { ETXTBSY
, SVSTREAM_ACCESS_DENIED
},
235 { EEXIST
, SVSTREAM_CANNOT_MAKE
},
236 { ENOSPC
, SVSTREAM_DISK_FULL
},
237 { (int)0xFFFF, SVSTREAM_GENERALERROR
}
240 sal_uInt32 nRetVal
= SVSTREAM_GENERALERROR
; // Standardfehler
244 if ( errArr
[i
].nErr
== nErrno
)
246 nRetVal
= errArr
[i
].sv
;
251 while( errArr
[i
].nErr
!= 0xFFFF );
255 /*************************************************************************
257 |* SvFileStream::SvFileStream()
259 |* Beschreibung STREAM.SDW
260 |* Ersterstellung OV 08.06.94
261 |* Letzte Aenderung OV 08.06.94
263 *************************************************************************/
265 SvFileStream::SvFileStream( const String
& rFileName
, StreamMode nOpenMode
)
269 bIsWritable
= sal_False
;
270 pInstanceData
= new StreamData
;
272 SetBufferSize( 1024 );
273 // convert URL to SystemPath, if necessary
274 ::rtl::OUString aSystemFileName
;
275 if( FileBase::getSystemPathFromFileURL( rFileName
, aSystemFileName
)
276 != FileBase::E_None
)
278 aSystemFileName
= rFileName
;
280 Open( aSystemFileName
, nOpenMode
);
283 /*************************************************************************
285 |* SvFileStream::SvFileStream()
287 |* Beschreibung STREAM.SDW
288 |* Ersterstellung OV 22.11.94
289 |* Letzte Aenderung OV 22.11.94
291 *************************************************************************/
293 SvFileStream::SvFileStream()
297 bIsWritable
= sal_False
;
298 pInstanceData
= new StreamData
;
299 SetBufferSize( 1024 );
302 /*************************************************************************
304 |* SvFileStream::~SvFileStream()
306 |* Beschreibung STREAM.SDW
307 |* Ersterstellung OV 22.11.94
308 |* Letzte Aenderung OV 22.11.94
310 *************************************************************************/
312 SvFileStream::~SvFileStream()
316 InternalStreamLock::UnlockFile( 0, 0, this );
319 delete pInstanceData
;
322 /*************************************************************************
324 |* SvFileStream::GetFileHandle()
326 |* Beschreibung STREAM.SDW
327 |* Ersterstellung OV 22.11.94
328 |* Letzte Aenderung OV 22.11.94
330 *************************************************************************/
332 sal_uInt32
SvFileStream::GetFileHandle() const
334 return (sal_uInt32
)pInstanceData
->nHandle
;
337 /*************************************************************************
339 |* SvFileStream::IsA()
341 |* Beschreibung STREAM.SDW
342 |* Ersterstellung OV 14.06.94
343 |* Letzte Aenderung OV 14.06.94
345 *************************************************************************/
347 sal_uInt16
SvFileStream::IsA() const
349 return ID_FILESTREAM
;
352 /*************************************************************************
354 |* SvFileStream::GetData()
356 |* Beschreibung STREAM.SDW
357 |* Ersterstellung OV 15.06.94
358 |* Letzte Aenderung OV 15.06.94
360 *************************************************************************/
362 sal_Size
SvFileStream::GetData( void* pData
, sal_Size nSize
)
365 ByteString
aTraceStr( "SvFileStream::GetData(): " );
366 aTraceStr
+= ByteString::CreateFromInt64(nSize
);
367 aTraceStr
+= " Bytes from ";
368 aTraceStr
+= ByteString(aFilename
, osl_getThreadTextEncoding());
369 DBG_TRACE( aTraceStr
.GetBuffer() );
375 nRead
= read(pInstanceData
->nHandle
,pData
,(unsigned)nSize
);
377 SetError( ::GetSvError( errno
));
379 return (sal_Size
)nRead
;
382 /*************************************************************************
384 |* SvFileStream::PutData()
386 |* Beschreibung STREAM.SDW
387 |* Ersterstellung OV 15.06.94
388 |* Letzte Aenderung OV 15.06.94
390 *************************************************************************/
392 sal_Size
SvFileStream::PutData( const void* pData
, sal_Size nSize
)
395 ByteString
aTraceStr( "SvFileStrean::PutData: " );
396 aTraceStr
+= ByteString::CreateFromInt64(nSize
);
397 aTraceStr
+= " Bytes to ";
398 aTraceStr
+= ByteString(aFilename
, osl_getThreadTextEncoding());
399 DBG_TRACE( aTraceStr
.GetBuffer() );
405 nWrite
= write(pInstanceData
->nHandle
,pData
,(unsigned)nSize
);
407 SetError( ::GetSvError( errno
) );
409 SetError( SVSTREAM_DISK_FULL
);
411 return (sal_Size
)nWrite
;
414 /*************************************************************************
416 |* SvFileStream::SeekPos()
418 |* Beschreibung STREAM.SDW
419 |* Ersterstellung OV 15.06.94
420 |* Letzte Aenderung OV 15.06.94
422 *************************************************************************/
424 sal_Size
SvFileStream::SeekPos( sal_Size nPos
)
429 if ( nPos
!= STREAM_SEEK_TO_END
)
430 nNewPos
= lseek( pInstanceData
->nHandle
, (long)nPos
, SEEK_SET
);
432 nNewPos
= lseek( pInstanceData
->nHandle
, 0L, SEEK_END
);
436 SetError( SVSTREAM_SEEK_ERROR
);
439 // langsam aber sicherer als return nNewPos
440 return lseek(pInstanceData
->nHandle
,0L,SEEK_CUR
);
443 SetError( SVSTREAM_GENERALERROR
);
448 /*************************************************************************
450 |* SvFileStream::FlushData()
452 |* Beschreibung STREAM.SDW
453 |* Ersterstellung OV 15.06.94
454 |* Letzte Aenderung OV 15.06.94
456 *************************************************************************/
458 void SvFileStream::FlushData()
460 // lokal gibt es nicht
463 static char *pFileLockEnvVar
= (char*)1;
465 /*************************************************************************
467 |* SvFileStream::LockRange()
469 |* Beschreibung STREAM.SDW
470 |* Ersterstellung OV 15.06.94
471 |* Letzte Aenderung OV 15.06.94
473 *************************************************************************/
475 sal_Bool
SvFileStream::LockRange( sal_Size nByteOffset
, sal_Size nBytes
)
478 aflock
.l_start
= nByteOffset
;
479 aflock
.l_whence
= SEEK_SET
;
480 aflock
.l_len
= nBytes
;
487 if ( eStreamMode
& STREAM_SHARE_DENYALL
)
495 if ( eStreamMode
& STREAM_SHARE_DENYREAD
)
501 SetError(SVSTREAM_LOCKING_VIOLATION
);
506 if ( eStreamMode
& STREAM_SHARE_DENYWRITE
)
517 if( ! InternalStreamLock::LockFile( nByteOffset
, nByteOffset
+nBytes
, this ) )
519 #if OSL_DEBUG_LEVEL > 1
520 fprintf( stderr
, "InternalLock on %s [ %d ... %d ] failed\n",
521 ByteString(aFilename
, osl_getThreadTextEncoding()).GetBuffer(), nByteOffset
, nByteOffset
+nBytes
);
526 // HACK: File-Locking nur via Environmentvariable einschalten
527 // um einen Haenger im Zusammenspiel mit einem Linux
528 // NFS-2-Server (kein Lockdaemon) zu verhindern.
529 // File-Locking ?ber NFS ist generell ein Performancekiller.
530 // HR, 22.10.1997 fuer SOLARIS
531 // CP, 30.11.1997 fuer HPUX
532 // ER, 18.12.1997 fuer IRIX
533 // HR, 18.05.1998 Environmentvariable
535 if ( pFileLockEnvVar
== (char*)1 )
536 pFileLockEnvVar
= getenv("STAR_ENABLE_FILE_LOCKING");
537 if ( ! pFileLockEnvVar
)
540 aflock
.l_type
= nLockMode
;
541 if (fcntl(pInstanceData
->nHandle
, F_GETLK
, &aflock
) == -1)
543 #if ( defined HPUX && defined BAD_UNION )
545 fprintf( stderr
, "***** FCNTL(lock):errno = %d\n", errno
);
547 if ( errno
== EINVAL
|| errno
== ENOSYS
)
558 SetError( ::GetSvError( errno
));
561 if (aflock
.l_type
!= F_UNLCK
)
563 SetError(SVSTREAM_LOCKING_VIOLATION
);
567 aflock
.l_type
= nLockMode
;
568 if (fcntl(pInstanceData
->nHandle
, F_SETLK
, &aflock
) == -1)
570 SetError( ::GetSvError( errno
));
576 /*************************************************************************
578 |* SvFileStream::UnlockRange()
580 |* Beschreibung STREAM.SDW
581 |* Ersterstellung OV 15.06.94
582 |* Letzte Aenderung OV 15.06.94
584 *************************************************************************/
586 sal_Bool
SvFileStream::UnlockRange( sal_Size nByteOffset
, sal_Size nBytes
)
590 aflock
.l_type
= F_UNLCK
;
591 aflock
.l_start
= nByteOffset
;
592 aflock
.l_whence
= SEEK_SET
;
593 aflock
.l_len
= nBytes
;
598 InternalStreamLock::UnlockFile( nByteOffset
, nByteOffset
+nBytes
, this );
600 if ( ! (eStreamMode
&
601 (STREAM_SHARE_DENYALL
| STREAM_SHARE_DENYREAD
| STREAM_SHARE_DENYWRITE
)))
604 // wenn File Locking ausgeschaltet, siehe SvFileStream::LockRange
605 if ( ! pFileLockEnvVar
)
608 if (fcntl(pInstanceData
->nHandle
, F_SETLK
, &aflock
) != -1)
611 #if ( defined HPUX && defined BAD_UNION )
613 fprintf( stderr
, "***** FCNTL(unlock):errno = %d\n", errno
);
615 if ( errno
== EINVAL
|| errno
== ENOSYS
)
618 #if ( defined SINIX )
623 SetError( ::GetSvError( errno
));
627 /*************************************************************************
629 |* SvFileStream::LockFile()
631 |* Beschreibung STREAM.SDW
632 |* Ersterstellung OV 15.06.94
633 |* Letzte Aenderung OV 15.06.94
635 *************************************************************************/
637 sal_Bool
SvFileStream::LockFile()
639 return LockRange( 0UL, 0UL );
642 /*************************************************************************
644 |* SvFileStream::UnlockFile()
646 |* Beschreibung STREAM.SDW
647 |* Ersterstellung OV 15.06.94
648 |* Letzte Aenderung OV 15.06.94
650 *************************************************************************/
652 sal_Bool
SvFileStream::UnlockFile()
654 return UnlockRange( 0UL, 0UL );
657 /*************************************************************************
659 |* SvFileStream::Open()
661 |* Beschreibung STREAM.SDW
662 |* Ersterstellung OV 15.06.94
663 |* Letzte Aenderung OV 15.06.94
665 *************************************************************************/
667 void SvFileStream::Open( const String
& rFilename
, StreamMode nOpenMode
)
669 int nAccess
, nAccessRW
;
673 sal_Bool bStatValid
= sal_False
;
677 eStreamMode
= nOpenMode
;
678 eStreamMode
&= ~STREAM_TRUNC
; // beim ReOpen nicht cutten
680 // !!! NoOp: Ansonsten ToAbs() verwendern
681 // !!! DirEntry aDirEntry( rFilename );
682 // !!! aFilename = aDirEntry.GetFull();
683 aFilename
= rFilename
;
685 FSysRedirector::DoRedirect( aFilename
);
687 ByteString
aLocalFilename(aFilename
, osl_getThreadTextEncoding());
690 ByteString
aTraceStr( "SvFileStream::Open(): " );
691 aTraceStr
+= aLocalFilename
;
692 DBG_TRACE( aTraceStr
.GetBuffer() );
695 if ( lstat( aLocalFilename
.GetBuffer(), &buf
) == 0 )
697 bStatValid
= sal_True
;
698 // SvFileStream soll kein Directory oeffnen
699 if( S_ISDIR( buf
.st_mode
) )
701 SetError( ::GetSvError( EISDIR
) );
707 if ( !( nOpenMode
& STREAM_WRITE
) )
708 nAccessRW
= O_RDONLY
;
709 else if ( !( nOpenMode
& STREAM_READ
) )
710 nAccessRW
= O_WRONLY
;
715 // Fix (MDA, 18.01.95): Bei RD_ONLY nicht mit O_CREAT oeffnen
716 // Wichtig auf Read-Only-Dateisystemen (wie CDROM)
717 if ( (!( nOpenMode
& STREAM_NOCREATE
)) && ( nAccessRW
!= O_RDONLY
) )
719 if ( nOpenMode
& STREAM_TRUNC
)
722 nMode
= S_IREAD
| S_IROTH
| S_IRGRP
;
723 if ( nOpenMode
& STREAM_WRITE
)
725 nMode
|= (S_IWRITE
| S_IWOTH
| S_IWGRP
);
727 if ( nOpenMode
& STREAM_COPY_ON_SYMLINK
)
729 if ( bStatValid
&& S_ISLNK( buf
.st_mode
) < 0 )
731 char *pBuf
= new char[ 1024+1 ];
732 if ( readlink( aLocalFilename
.GetBuffer(), pBuf
, 1024 ) > 0 )
734 if ( unlink(aLocalFilename
.GetBuffer()) == 0 )
738 "Copying file on symbolic link (%s).\n",
739 aLocalFilename
.GetBuffer() );
741 String
aTmpString( pBuf
, osl_getThreadTextEncoding() );
742 const DirEntry
aSourceEntry( aTmpString
);
743 const DirEntry
aTargetEntry( aFilename
);
744 FileCopier
aFileCopier( aSourceEntry
, aTargetEntry
);
745 aFileCopier
.Execute();
754 nHandleTmp
= open(aLocalFilename
.GetBuffer(),nAccessRW
|nAccess
, nMode
);
756 if ( nHandleTmp
== -1 )
758 if ( nAccessRW
!= O_RDONLY
)
760 // auf Lesen runterschalten
761 nAccessRW
= O_RDONLY
;
763 nMode
= S_IREAD
| S_IROTH
| S_IRGRP
;
764 nHandleTmp
=open( aLocalFilename
.GetBuffer(),
769 if ( nHandleTmp
!= -1 )
771 pInstanceData
->nHandle
= nHandleTmp
;
773 if ( nAccessRW
!= O_RDONLY
)
774 bIsWritable
= sal_True
;
776 if ( !LockFile() ) // ganze Datei
780 bIsWritable
= sal_False
;
781 pInstanceData
->nHandle
= 0;
785 SetError( ::GetSvError( errno
) );
788 /*************************************************************************
790 |* SvFileStream::ReOpen()
792 |* Beschreibung STREAM.SDW
793 |* Ersterstellung OV 15.06.94
794 |* Letzte Aenderung OV 15.06.94
796 *************************************************************************/
798 void SvFileStream::ReOpen()
800 if ( !bIsOpen
&& aFilename
.Len() )
801 Open( aFilename
, eStreamMode
);
804 /*************************************************************************
806 |* SvFileStream::Close()
808 |* Beschreibung STREAM.SDW
809 |* Ersterstellung OV 15.06.94
810 |* Letzte Aenderung OV 15.06.94
812 *************************************************************************/
814 void SvFileStream::Close()
816 InternalStreamLock::UnlockFile( 0, 0, this );
821 ByteString
aTraceStr( "SvFileStream::Close(): " );
822 aTraceStr
+= ByteString(aFilename
, osl_getThreadTextEncoding());
823 DBG_TRACE( aTraceStr
.GetBuffer() );
827 close( pInstanceData
->nHandle
);
828 pInstanceData
->nHandle
= 0;
832 bIsWritable
= sal_False
;
833 SvStream::ClearBuffer();
834 SvStream::ClearError();
837 /*************************************************************************
839 |* SvFileStream::ResetError()
841 |* Beschreibung STREAM.SDW; Setzt Filepointer auf Dateianfang
842 |* Ersterstellung OV 15.06.94
843 |* Letzte Aenderung OV 15.06.94
845 *************************************************************************/
847 void SvFileStream::ResetError()
849 SvStream::ClearError();
853 /*************************************************************************
855 |* SvFileStream::SetSize()
857 |* Beschreibung STREAM.SDW;
858 |* Ersterstellung OV 15.06.94
859 |* Letzte Aenderung OV 15.06.94
861 *************************************************************************/
863 void SvFileStream::SetSize (sal_Size nSize
)
867 int fd
= pInstanceData
->nHandle
;
868 if (::ftruncate (fd
, (off_t
)nSize
) < 0)
870 // Save original error.
871 sal_uInt32 nErr
= ::GetSvError (errno
);
873 // Check against current size. Fail upon 'shrink'.
875 if (::fstat (fd
, &aStat
) < 0)
880 if ((sal::static_int_cast
< sal_sSize
>(nSize
) <= aStat
.st_size
))
882 // Failure upon 'shrink'. Return original error.
887 // Save current position.
888 sal_Size nCurPos
= (sal_Size
)::lseek (fd
, (off_t
)0, SEEK_CUR
);
889 if (nCurPos
== (sal_Size
)(-1))
895 // Try 'expand' via 'lseek()' and 'write()'.
896 if (::lseek (fd
, (off_t
)(nSize
- 1), SEEK_SET
) < 0)
901 if (::write (fd
, (char*)"", (size_t)1) < 0)
903 // Failure. Restore saved position.
904 if (::lseek (fd
, (off_t
)nCurPos
, SEEK_SET
) < 0)
913 // Success. Restore saved position.
914 if (::lseek (fd
, (off_t
)nCurPos
, SEEK_SET
) < 0)