xref: /aoo42x/main/tools/source/stream/strmunx.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // no include "precompiled_tools.hxx" because this file is included in strmsys.cxx
29 
30 #include <stdio.h>
31 #include <string.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #include <errno.h>
35 #include <unistd.h>
36 #include <limits.h>
37 #include <stdlib.h>	// fuer getenv()
38 
39 #include <tools/debug.hxx>
40 #include <tools/fsys.hxx>
41 #include <tools/stream.hxx>
42 
43 #include <vos/mutex.hxx>
44 #include <osl/thread.h> // osl_getThreadTextEncoding
45 
46 // class FileBase
47 #include <osl/file.hxx>
48 #include <rtl/instance.hxx>
49 
50 using namespace osl;
51 
52 // -----------------------------------------------------------------------
53 
54 // ----------------
55 // - InternalLock -
56 // ----------------
57 
58 class InternalStreamLock;
59 DECLARE_LIST( InternalStreamLockList, InternalStreamLock* )
60 namespace { struct LockList : public rtl::Static< InternalStreamLockList, LockList > {}; }
61 
62 #ifndef BOOTSTRAP
63 namespace { struct LockMutex : public rtl::Static< vos::OMutex, LockMutex > {}; }
64 #endif
65 
66 class InternalStreamLock
67 {
68 	sal_Size			m_nStartPos;
69 	sal_Size			m_nEndPos;
70 	SvFileStream*	m_pStream;
71 	struct stat		m_aStat;
72 
73 	InternalStreamLock( sal_Size, sal_Size, SvFileStream* );
74 	~InternalStreamLock();
75 public:
76 	static sal_Bool LockFile( sal_Size nStart, sal_Size nEnd, SvFileStream* );
77 	static void UnlockFile( sal_Size nStart, sal_Size nEnd, SvFileStream* );
78 };
79 
80 InternalStreamLock::InternalStreamLock(
81 	sal_Size nStart,
82 	sal_Size nEnd,
83 	SvFileStream* pStream ) :
84 		m_nStartPos( nStart ),
85 		m_nEndPos( nEnd ),
86 		m_pStream( pStream )
87 {
88 	ByteString aFileName(m_pStream->GetFileName(), osl_getThreadTextEncoding());
89 	stat( aFileName.GetBuffer(), &m_aStat );
90 	LockList::get().Insert( this, LIST_APPEND );
91 #if OSL_DEBUG_LEVEL > 1
92 	fprintf( stderr, "locked %s", aFileName.GetBuffer() );
93 	if( m_nStartPos || m_nEndPos )
94 		fprintf(stderr, " [ %ld ... %ld ]", m_nStartPos, m_nEndPos );
95 	fprintf( stderr, "\n" );
96 #endif
97 }
98 
99 InternalStreamLock::~InternalStreamLock()
100 {
101 	LockList::get().Remove( this );
102 #if OSL_DEBUG_LEVEL > 1
103 	ByteString aFileName(m_pStream->GetFileName(), osl_getThreadTextEncoding());
104 	fprintf( stderr, "unlocked %s", aFileName.GetBuffer() );
105 	if( m_nStartPos || m_nEndPos )
106 		fprintf(stderr, " [ %ld ... %ld ]", m_nStartPos, m_nEndPos );
107 	fprintf( stderr, "\n" );
108 #endif
109 }
110 
111 sal_Bool InternalStreamLock::LockFile( sal_Size nStart, sal_Size nEnd, SvFileStream* pStream )
112 {
113 #ifndef BOOTSTRAP
114 	vos:: OGuard  aGuard( LockMutex::get() );
115 #endif
116 	ByteString aFileName(pStream->GetFileName(), osl_getThreadTextEncoding());
117 	struct stat aStat;
118 	if( stat( aFileName.GetBuffer(), &aStat ) )
119 		return sal_False;
120 
121 	if( S_ISDIR( aStat.st_mode ) )
122 		return sal_True;
123 
124 	InternalStreamLock* pLock = NULL;
125 	InternalStreamLockList &rLockList = LockList::get();
126 	for( sal_uIntPtr i = 0; i < rLockList.Count(); ++i )
127 	{
128 		pLock = rLockList.GetObject( i );
129 		if( aStat.st_ino == pLock->m_aStat.st_ino )
130 		{
131 			sal_Bool bDenyByOptions = sal_False;
132 			StreamMode nLockMode = pLock->m_pStream->GetStreamMode();
133 			StreamMode nNewMode = pStream->GetStreamMode();
134 
135 			if( nLockMode & STREAM_SHARE_DENYALL )
136 				bDenyByOptions = sal_True;
137 			else if( ( nLockMode & STREAM_SHARE_DENYWRITE ) &&
138 					 ( nNewMode & STREAM_WRITE ) )
139 				bDenyByOptions = sal_True;
140 			else if( ( nLockMode & STREAM_SHARE_DENYREAD ) &&
141 					 ( nNewMode & STREAM_READ ) )
142 				bDenyByOptions = sal_True;
143 
144 			if( bDenyByOptions )
145 			{
146 				if( pLock->m_nStartPos == 0 && pLock->m_nEndPos == 0 ) // whole file is already locked
147 					return sal_False;
148 				if( nStart == 0 && nEnd == 0) // cannot lock whole file
149 					return sal_False;
150 
151 				if( ( nStart < pLock->m_nStartPos && nEnd > pLock->m_nStartPos ) ||
152 					( nStart < pLock->m_nEndPos && nEnd > pLock->m_nEndPos ) )
153 					return sal_False;
154 			}
155 		}
156 	}
157 	pLock  = new InternalStreamLock( nStart, nEnd, pStream );
158 	return sal_True;
159 }
160 
161 void InternalStreamLock::UnlockFile( sal_Size nStart, sal_Size nEnd, SvFileStream* pStream )
162 {
163 #ifndef BOOTSTRAP
164 	vos:: OGuard  aGuard( LockMutex::get() );
165 #endif
166 	InternalStreamLock* pLock = NULL;
167 	InternalStreamLockList &rLockList = LockList::get();
168 	if( nStart == 0 && nEnd == 0 )
169 	{
170 		for( sal_uIntPtr i = 0; i < rLockList.Count(); ++i )
171 		{
172 			if( ( pLock = rLockList.GetObject( i ) )->m_pStream == pStream )
173 			{
174 				delete pLock;
175 				i--;
176 			}
177 		}
178 		return;
179 	}
180 	for( sal_uIntPtr i = 0; i < rLockList.Count(); ++i )
181 	{
182 		if( ( pLock = rLockList.GetObject( i ) )->m_pStream == pStream &&
183 			nStart == pLock->m_nStartPos && nEnd == pLock->m_nEndPos )
184 		{
185 			delete pLock;
186 			return;
187 		}
188 	}
189 }
190 
191 // --------------
192 // - StreamData -
193 // --------------
194 
195 class StreamData
196 {
197 public:
198     int     nHandle;
199 
200             StreamData() { nHandle = 0; }
201 };
202 
203 // -----------------------------------------------------------------------
204 
205 static sal_uInt32 GetSvError( int nErrno )
206 {
207     static struct { int nErr; sal_uInt32 sv; } errArr[] =
208     {
209         { 0,            SVSTREAM_OK },
210         { EACCES,       SVSTREAM_ACCESS_DENIED },
211         { EBADF,        SVSTREAM_INVALID_HANDLE },
212 #if defined( RS6000 ) || defined( ALPHA ) || defined( HP9000 ) || defined( NETBSD ) || defined(FREEBSD) || defined(MACOSX) || defined(__FreeBSD_kernel__)
213         { EDEADLK,      SVSTREAM_LOCKING_VIOLATION },
214 #else
215         { EDEADLOCK,    SVSTREAM_LOCKING_VIOLATION },
216 #endif
217         { EINVAL,       SVSTREAM_INVALID_PARAMETER },
218         { EMFILE,       SVSTREAM_TOO_MANY_OPEN_FILES },
219         { ENFILE,       SVSTREAM_TOO_MANY_OPEN_FILES },
220         { ENOENT,       SVSTREAM_FILE_NOT_FOUND },
221         { EPERM,        SVSTREAM_ACCESS_DENIED },
222         { EROFS,        SVSTREAM_ACCESS_DENIED },
223         { EAGAIN,       SVSTREAM_LOCKING_VIOLATION },
224         { EISDIR,       SVSTREAM_PATH_NOT_FOUND },
225         { ELOOP,        SVSTREAM_PATH_NOT_FOUND },
226 #if ! defined( RS6000 ) && ! defined( ALPHA ) && ! defined( NETBSD ) && ! defined (FREEBSD) && ! defined (MACOSX) && ! defined(__FreeBSD_kernel__)
227         { EMULTIHOP,    SVSTREAM_PATH_NOT_FOUND },
228         { ENOLINK,      SVSTREAM_PATH_NOT_FOUND },
229 #endif
230         { ENOTDIR,      SVSTREAM_PATH_NOT_FOUND },
231 		{ ETXTBSY,		SVSTREAM_ACCESS_DENIED	},
232 		{ EEXIST,		SVSTREAM_CANNOT_MAKE    },
233 		{ ENOSPC,		SVSTREAM_DISK_FULL 		},
234         { (int)0xFFFF,  SVSTREAM_GENERALERROR }
235     };
236 
237     sal_uInt32 nRetVal = SVSTREAM_GENERALERROR;    // Standardfehler
238     int i=0;
239     do
240     {
241         if ( errArr[i].nErr == nErrno )
242         {
243             nRetVal = errArr[i].sv;
244             break;
245         }
246         ++i;
247     }
248     while( errArr[i].nErr != 0xFFFF );
249     return nRetVal;
250 }
251 
252 /*************************************************************************
253 |*
254 |*    SvFileStream::SvFileStream()
255 |*
256 |*    Beschreibung      STREAM.SDW
257 |*    Ersterstellung    OV 08.06.94
258 |*    Letzte Aenderung  OV 08.06.94
259 |*
260 *************************************************************************/
261 
262 SvFileStream::SvFileStream( const String& rFileName, StreamMode nOpenMode )
263 {
264     bIsOpen             = sal_False;
265     nLockCounter        = 0;
266     bIsWritable         = sal_False;
267     pInstanceData       = new StreamData;
268 
269     SetBufferSize( 1024 );
270 	// convert URL to SystemPath, if necessary
271 	::rtl::OUString aSystemFileName;
272 	if( FileBase::getSystemPathFromFileURL( rFileName , aSystemFileName )
273         != FileBase::E_None )
274 	{
275 		aSystemFileName = rFileName;
276 	}
277 	Open( aSystemFileName, nOpenMode );
278 }
279 
280 /*************************************************************************
281 |*
282 |*    SvFileStream::SvFileStream()
283 |*
284 |*    Beschreibung      STREAM.SDW
285 |*    Ersterstellung    OV 22.11.94
286 |*    Letzte Aenderung  OV 22.11.94
287 |*
288 *************************************************************************/
289 
290 SvFileStream::SvFileStream()
291 {
292     bIsOpen             = sal_False;
293     nLockCounter        = 0;
294     bIsWritable         = sal_False;
295     pInstanceData       = new StreamData;
296     SetBufferSize( 1024 );
297 }
298 
299 /*************************************************************************
300 |*
301 |*    SvFileStream::~SvFileStream()
302 |*
303 |*    Beschreibung      STREAM.SDW
304 |*    Ersterstellung    OV 22.11.94
305 |*    Letzte Aenderung  OV 22.11.94
306 |*
307 *************************************************************************/
308 
309 SvFileStream::~SvFileStream()
310 {
311     Close();
312 
313 	InternalStreamLock::UnlockFile( 0, 0, this );
314 
315     if (pInstanceData)
316         delete pInstanceData;
317 }
318 
319 /*************************************************************************
320 |*
321 |*    SvFileStream::GetFileHandle()
322 |*
323 |*    Beschreibung      STREAM.SDW
324 |*    Ersterstellung    OV 22.11.94
325 |*    Letzte Aenderung  OV 22.11.94
326 |*
327 *************************************************************************/
328 
329 sal_uInt32 SvFileStream::GetFileHandle() const
330 {
331     return (sal_uInt32)pInstanceData->nHandle;
332 }
333 
334 /*************************************************************************
335 |*
336 |*    SvFileStream::IsA()
337 |*
338 |*    Beschreibung      STREAM.SDW
339 |*    Ersterstellung    OV 14.06.94
340 |*    Letzte Aenderung  OV 14.06.94
341 |*
342 *************************************************************************/
343 
344 sal_uInt16 SvFileStream::IsA() const
345 {
346     return ID_FILESTREAM;
347 }
348 
349 /*************************************************************************
350 |*
351 |*    SvFileStream::GetData()
352 |*
353 |*    Beschreibung      STREAM.SDW
354 |*    Ersterstellung    OV 15.06.94
355 |*    Letzte Aenderung  OV 15.06.94
356 |*
357 *************************************************************************/
358 
359 sal_Size SvFileStream::GetData( void* pData, sal_Size nSize )
360 {
361 #ifdef DBG_UTIL
362     ByteString aTraceStr( "SvFileStream::GetData(): " );
363     aTraceStr += ByteString::CreateFromInt64(nSize);
364     aTraceStr += " Bytes from ";
365     aTraceStr += ByteString(aFilename, osl_getThreadTextEncoding());
366     DBG_TRACE( aTraceStr.GetBuffer() );
367 #endif
368 
369 	int nRead = 0;
370 	if ( IsOpen() )
371 	{
372 		nRead = read(pInstanceData->nHandle,pData,(unsigned)nSize);
373 		if ( nRead == -1 )
374 			SetError( ::GetSvError( errno ));
375 	}
376 	return (sal_Size)nRead;
377 }
378 
379 /*************************************************************************
380 |*
381 |*    SvFileStream::PutData()
382 |*
383 |*    Beschreibung      STREAM.SDW
384 |*    Ersterstellung    OV 15.06.94
385 |*    Letzte Aenderung  OV 15.06.94
386 |*
387 *************************************************************************/
388 
389 sal_Size SvFileStream::PutData( const void* pData, sal_Size nSize )
390 {
391 #ifdef DBG_UTIL
392     ByteString aTraceStr( "SvFileStrean::PutData: " );
393     aTraceStr += ByteString::CreateFromInt64(nSize);
394     aTraceStr += " Bytes to ";
395     aTraceStr += ByteString(aFilename, osl_getThreadTextEncoding());
396     DBG_TRACE( aTraceStr.GetBuffer() );
397 #endif
398 
399 	int nWrite = 0;
400 	if ( IsOpen() )
401 	{
402 		nWrite = write(pInstanceData->nHandle,pData,(unsigned)nSize);
403 		if ( nWrite == -1 )
404 		SetError( ::GetSvError( errno ) );
405 		else if( !nWrite )
406 		SetError( SVSTREAM_DISK_FULL );
407 	}
408 	return (sal_Size)nWrite;
409 }
410 
411 /*************************************************************************
412 |*
413 |*    SvFileStream::SeekPos()
414 |*
415 |*    Beschreibung      STREAM.SDW
416 |*    Ersterstellung    OV 15.06.94
417 |*    Letzte Aenderung  OV 15.06.94
418 |*
419 *************************************************************************/
420 
421 sal_Size SvFileStream::SeekPos( sal_Size nPos )
422 {
423 	if ( IsOpen() )
424 	{
425 		long nNewPos;
426 		if ( nPos != STREAM_SEEK_TO_END )
427 			nNewPos = lseek( pInstanceData->nHandle, (long)nPos, SEEK_SET );
428 		else
429 			nNewPos = lseek( pInstanceData->nHandle, 0L, SEEK_END );
430 
431 		if ( nNewPos == -1 )
432 		{
433 			SetError( SVSTREAM_SEEK_ERROR );
434 			return 0L;
435 		}
436 		// langsam aber sicherer als return nNewPos
437 		return lseek(pInstanceData->nHandle,0L,SEEK_CUR);
438 		// return nNewPos;
439 	}
440     SetError( SVSTREAM_GENERALERROR );
441     return 0L;
442 }
443 
444 
445 /*************************************************************************
446 |*
447 |*    SvFileStream::FlushData()
448 |*
449 |*    Beschreibung      STREAM.SDW
450 |*    Ersterstellung    OV 15.06.94
451 |*    Letzte Aenderung  OV 15.06.94
452 |*
453 *************************************************************************/
454 
455 void SvFileStream::FlushData()
456 {
457 // lokal gibt es nicht
458 }
459 
460 static char *pFileLockEnvVar = (char*)1;
461 
462 /*************************************************************************
463 |*
464 |*    SvFileStream::LockRange()
465 |*
466 |*    Beschreibung      STREAM.SDW
467 |*    Ersterstellung    OV 15.06.94
468 |*    Letzte Aenderung  OV 15.06.94
469 |*
470 *************************************************************************/
471 
472 sal_Bool SvFileStream::LockRange( sal_Size nByteOffset, sal_Size nBytes )
473 {
474 	struct flock aflock;
475 	aflock.l_start = nByteOffset;
476 	aflock.l_whence = SEEK_SET;
477 	aflock.l_len = nBytes;
478 
479 	int nLockMode = 0;
480 
481 	if ( ! IsOpen() )
482 		return sal_False;
483 
484 	if ( eStreamMode & STREAM_SHARE_DENYALL )
485         {
486 		if (bIsWritable)
487 			nLockMode = F_WRLCK;
488 		else
489 			nLockMode = F_RDLCK;
490         }
491 
492 	if ( eStreamMode & STREAM_SHARE_DENYREAD )
493         {
494 		if (bIsWritable)
495 			nLockMode = F_WRLCK;
496 		else
497 		{
498 			SetError(SVSTREAM_LOCKING_VIOLATION);
499 			return sal_False;
500 		}
501         }
502 
503 	if ( eStreamMode & STREAM_SHARE_DENYWRITE )
504         {
505 		if (bIsWritable)
506 			nLockMode = F_WRLCK;
507 		else
508 			nLockMode = F_RDLCK;
509         }
510 
511 	if (!nLockMode)
512 		return sal_True;
513 
514 	if( ! InternalStreamLock::LockFile( nByteOffset, nByteOffset+nBytes, this ) )
515 	{
516 #if OSL_DEBUG_LEVEL > 1
517 		fprintf( stderr, "InternalLock on %s [ %ld ... %ld ] failed\n",
518 				 ByteString(aFilename, osl_getThreadTextEncoding()).GetBuffer(), nByteOffset, nByteOffset+nBytes );
519 #endif
520 		return sal_False;
521 	}
522 
523 	// HACK: File-Locking nur via Environmentvariable einschalten
524 	// um einen Haenger im Zusammenspiel mit einem Linux
525 	// NFS-2-Server (kein Lockdaemon) zu verhindern.
526 	// File-Locking ?ber NFS ist generell ein Performancekiller.
527 	//						HR, 22.10.1997 fuer SOLARIS
528 	//						CP, 30.11.1997 fuer HPUX
529 	//						ER, 18.12.1997 fuer IRIX
530 	//						HR, 18.05.1998 Environmentvariable
531 
532 	if ( pFileLockEnvVar == (char*)1 )
533 		pFileLockEnvVar = getenv("STAR_ENABLE_FILE_LOCKING");
534 	if ( ! pFileLockEnvVar )
535 		return sal_True;
536 
537 	aflock.l_type = nLockMode;
538 	if (fcntl(pInstanceData->nHandle, F_GETLK, &aflock) == -1)
539 	{
540 	#if ( defined HPUX && defined BAD_UNION )
541 	#ifdef DBG_UTIL
542 		fprintf( stderr, "***** FCNTL(lock):errno = %d\n", errno );
543 	#endif
544 		if ( errno == EINVAL || errno == ENOSYS )
545 			return sal_True;
546 	#endif
547 	#if defined SINIX
548 		if (errno == EINVAL)
549 			return sal_True;
550 	#endif
551 	#if defined SOLARIS
552 		if (errno == ENOSYS)
553 			return sal_True;
554 	#endif
555 		SetError( ::GetSvError( errno ));
556 		return sal_False;
557 	}
558 	if (aflock.l_type != F_UNLCK)
559 	{
560 		SetError(SVSTREAM_LOCKING_VIOLATION);
561 		return sal_False;
562 	}
563 
564 	aflock.l_type = nLockMode;
565 	if (fcntl(pInstanceData->nHandle, F_SETLK, &aflock) == -1)
566 	{
567 		SetError( ::GetSvError( errno ));
568 		return sal_False;
569 	}
570 	return sal_True;
571 }
572 
573 /*************************************************************************
574 |*
575 |*    SvFileStream::UnlockRange()
576 |*
577 |*    Beschreibung      STREAM.SDW
578 |*    Ersterstellung    OV 15.06.94
579 |*    Letzte Aenderung  OV 15.06.94
580 |*
581 *************************************************************************/
582 
583 sal_Bool SvFileStream::UnlockRange( sal_Size nByteOffset, sal_Size nBytes )
584 {
585 
586     struct flock aflock;
587     aflock.l_type = F_UNLCK;
588     aflock.l_start = nByteOffset;
589     aflock.l_whence = SEEK_SET;
590     aflock.l_len = nBytes;
591 
592     if ( ! IsOpen() )
593         return sal_False;
594 
595 	InternalStreamLock::UnlockFile( nByteOffset, nByteOffset+nBytes, this );
596 
597     if ( ! (eStreamMode &
598         (STREAM_SHARE_DENYALL | STREAM_SHARE_DENYREAD | STREAM_SHARE_DENYWRITE)))
599         return sal_True;
600 
601 	// wenn File Locking ausgeschaltet, siehe SvFileStream::LockRange
602 	if ( ! pFileLockEnvVar )
603 		return sal_True;
604 
605     if (fcntl(pInstanceData->nHandle, F_SETLK, &aflock) != -1)
606         return sal_True;
607 
608 #if ( defined HPUX && defined BAD_UNION )
609 #ifdef DBG_UTIL
610         fprintf( stderr, "***** FCNTL(unlock):errno = %d\n", errno );
611 #endif
612         if ( errno == EINVAL || errno == ENOSYS )
613             return sal_True;
614 #endif
615 #if ( defined SINIX )
616 	if (errno == EINVAL)
617 		return sal_True;
618 #endif
619 
620     SetError( ::GetSvError( errno ));
621     return sal_False;
622 }
623 
624 /*************************************************************************
625 |*
626 |*    SvFileStream::LockFile()
627 |*
628 |*    Beschreibung      STREAM.SDW
629 |*    Ersterstellung    OV 15.06.94
630 |*    Letzte Aenderung  OV 15.06.94
631 |*
632 *************************************************************************/
633 
634 sal_Bool SvFileStream::LockFile()
635 {
636   return LockRange( 0UL, 0UL );
637 }
638 
639 /*************************************************************************
640 |*
641 |*    SvFileStream::UnlockFile()
642 |*
643 |*    Beschreibung      STREAM.SDW
644 |*    Ersterstellung    OV 15.06.94
645 |*    Letzte Aenderung  OV 15.06.94
646 |*
647 *************************************************************************/
648 
649 sal_Bool SvFileStream::UnlockFile()
650 {
651     return UnlockRange( 0UL, 0UL );
652 }
653 
654 /*************************************************************************
655 |*
656 |*    SvFileStream::Open()
657 |*
658 |*    Beschreibung      STREAM.SDW
659 |*    Ersterstellung    OV 15.06.94
660 |*    Letzte Aenderung  OV 15.06.94
661 |*
662 *************************************************************************/
663 
664 void SvFileStream::Open( const String& rFilename, StreamMode nOpenMode )
665 {
666 	int nAccess, nAccessRW;
667 	int nMode;
668 	int nHandleTmp;
669 	struct stat buf;
670 	sal_Bool bStatValid = sal_False;
671 
672 	Close();
673 	errno = 0;
674 	eStreamMode = nOpenMode;
675 	eStreamMode &= ~STREAM_TRUNC; // beim ReOpen nicht cutten
676 
677 //    !!! NoOp: Ansonsten ToAbs() verwendern
678 //    !!! DirEntry aDirEntry( rFilename );
679 //    !!! aFilename = aDirEntry.GetFull();
680 	aFilename = rFilename;
681 #ifndef BOOTSTRAP
682 	FSysRedirector::DoRedirect( aFilename );
683 #endif
684 	ByteString aLocalFilename(aFilename, osl_getThreadTextEncoding());
685 
686 #ifdef DBG_UTIL
687 	ByteString aTraceStr( "SvFileStream::Open(): " );
688 	aTraceStr +=  aLocalFilename;
689 	DBG_TRACE( aTraceStr.GetBuffer() );
690 #endif
691 
692 	if ( lstat( aLocalFilename.GetBuffer(), &buf ) == 0 )
693 	  {
694 	    bStatValid = sal_True;
695 		// SvFileStream soll kein Directory oeffnen
696 		if( S_ISDIR( buf.st_mode ) )
697 		  {
698 			SetError( ::GetSvError( EISDIR ) );
699 			return;
700 		  }
701 	  }
702 
703 
704     if ( !( nOpenMode & STREAM_WRITE ) )
705         nAccessRW = O_RDONLY;
706     else if ( !( nOpenMode & STREAM_READ ) )
707         nAccessRW = O_WRONLY;
708     else
709         nAccessRW = O_RDWR;
710 
711     nAccess = 0;
712 	// Fix (MDA, 18.01.95): Bei RD_ONLY nicht mit O_CREAT oeffnen
713 	// Wichtig auf Read-Only-Dateisystemen (wie CDROM)
714     if ( (!( nOpenMode & STREAM_NOCREATE )) && ( nAccessRW != O_RDONLY ) )
715         nAccess |= O_CREAT;
716     if ( nOpenMode & STREAM_TRUNC )
717         nAccess |= O_TRUNC;
718 
719     nMode = S_IREAD | S_IROTH | S_IRGRP;
720     if ( nOpenMode & STREAM_WRITE)
721 	{
722 	  nMode |= (S_IWRITE | S_IWOTH | S_IWGRP);
723 
724 	  if ( nOpenMode & STREAM_COPY_ON_SYMLINK )
725 	  	{
726 		  if ( bStatValid  &&  S_ISLNK( buf.st_mode ) < 0 )
727 			{
728 		      char *pBuf = new char[ 1024+1 ];
729 		      if ( readlink( aLocalFilename.GetBuffer(), pBuf, 1024 ) > 0 )
730 				{
731 				  if (  unlink(aLocalFilename.GetBuffer())  == 0 )
732 		  		    {
733 #ifdef DBG_UTIL
734 					  fprintf( stderr,
735 							   "Copying file on symbolic link (%s).\n",
736 							   aLocalFilename.GetBuffer() );
737 #endif
738 					  String aTmpString( pBuf, osl_getThreadTextEncoding() );
739 					  const DirEntry aSourceEntry( aTmpString );
740 					  const DirEntry aTargetEntry( aFilename );
741 					  FileCopier aFileCopier( aSourceEntry, aTargetEntry );
742 					  aFileCopier.Execute();
743 					}
744 				}
745 			  delete [] pBuf;
746 			}
747 		}
748 	}
749 
750 
751 	nHandleTmp = open(aLocalFilename.GetBuffer(),nAccessRW|nAccess, nMode );
752 
753     if ( nHandleTmp == -1 )
754     {
755         if ( nAccessRW != O_RDONLY )
756         {
757             // auf Lesen runterschalten
758             nAccessRW = O_RDONLY;
759             nAccess = 0;
760             nMode = S_IREAD | S_IROTH | S_IRGRP;
761             nHandleTmp =open( aLocalFilename.GetBuffer(),
762                               nAccessRW|nAccess,
763                               nMode );
764 	        }
765     }
766     if ( nHandleTmp != -1 )
767     {
768         pInstanceData->nHandle = nHandleTmp;
769         bIsOpen = sal_True;
770         if ( nAccessRW != O_RDONLY )
771             bIsWritable = sal_True;
772 
773         if ( !LockFile() ) // ganze Datei
774         {
775 			close( nHandleTmp );
776             bIsOpen = sal_False;
777             bIsWritable = sal_False;
778             pInstanceData->nHandle = 0;
779         }
780     }
781     else
782         SetError( ::GetSvError( errno ) );
783 }
784 
785 /*************************************************************************
786 |*
787 |*    SvFileStream::ReOpen()
788 |*
789 |*    Beschreibung      STREAM.SDW
790 |*    Ersterstellung    OV 15.06.94
791 |*    Letzte Aenderung  OV 15.06.94
792 |*
793 *************************************************************************/
794 
795 void SvFileStream::ReOpen()
796 {
797     if ( !bIsOpen && aFilename.Len() )
798         Open( aFilename, eStreamMode );
799 }
800 
801 /*************************************************************************
802 |*
803 |*    SvFileStream::Close()
804 |*
805 |*    Beschreibung      STREAM.SDW
806 |*    Ersterstellung    OV 15.06.94
807 |*    Letzte Aenderung  OV 15.06.94
808 |*
809 *************************************************************************/
810 
811 void SvFileStream::Close()
812 {
813 	InternalStreamLock::UnlockFile( 0, 0, this );
814 
815   if ( IsOpen() )
816     {
817 #ifdef DBG_UTIL
818         ByteString aTraceStr( "SvFileStream::Close(): " );
819         aTraceStr += ByteString(aFilename, osl_getThreadTextEncoding());
820         DBG_TRACE( aTraceStr.GetBuffer() );
821 #endif
822 
823         Flush();
824         close( pInstanceData->nHandle );
825         pInstanceData->nHandle = 0;
826     }
827 
828     bIsOpen     = sal_False;
829     bIsWritable = sal_False;
830     SvStream::ClearBuffer();
831     SvStream::ClearError();
832 }
833 
834 /*************************************************************************
835 |*
836 |*    SvFileStream::ResetError()
837 |*
838 |*    Beschreibung      STREAM.SDW; Setzt Filepointer auf Dateianfang
839 |*    Ersterstellung    OV 15.06.94
840 |*    Letzte Aenderung  OV 15.06.94
841 |*
842 *************************************************************************/
843 
844 void SvFileStream::ResetError()
845 {
846     SvStream::ClearError();
847 }
848 
849 
850 /*************************************************************************
851 |*
852 |*    SvFileStream::SetSize()
853 |*
854 |*    Beschreibung      STREAM.SDW;
855 |*    Ersterstellung    OV 15.06.94
856 |*    Letzte Aenderung  OV 15.06.94
857 |*
858 *************************************************************************/
859 
860 void SvFileStream::SetSize (sal_Size nSize)
861 {
862 	if (IsOpen())
863     {
864 		int fd = pInstanceData->nHandle;
865 		if (::ftruncate (fd, (off_t)nSize) < 0)
866 		{
867 			// Save original error.
868 			sal_uInt32 nErr = ::GetSvError (errno);
869 
870 			// Check against current size. Fail upon 'shrink'.
871 			struct stat aStat;
872 			if (::fstat (fd, &aStat) < 0)
873 			{
874 				SetError (nErr);
875 				return;
876 			}
877 			if ((sal::static_int_cast< sal_sSize >(nSize) <= aStat.st_size))
878 			{
879 				// Failure upon 'shrink'. Return original error.
880 				SetError (nErr);
881 				return;
882 			}
883 
884 			// Save current position.
885 			sal_Size nCurPos = (sal_Size)::lseek (fd, (off_t)0, SEEK_CUR);
886 			if (nCurPos == (sal_Size)(-1))
887 			{
888 				SetError (nErr);
889 				return;
890 			}
891 
892 			// Try 'expand' via 'lseek()' and 'write()'.
893 			if (::lseek (fd, (off_t)(nSize - 1), SEEK_SET) < 0)
894 			{
895 				SetError (nErr);
896 				return;
897 			}
898 			if (::write (fd, (char*)"", (size_t)1) < 0)
899 			{
900 				// Failure. Restore saved position.
901 				if (::lseek (fd, (off_t)nCurPos, SEEK_SET) < 0)
902 				{
903 					// Double failure.
904 				}
905 
906 				SetError (nErr);
907 				return;
908 			}
909 
910 			// Success. Restore saved position.
911 			if (::lseek (fd, (off_t)nCurPos, SEEK_SET) < 0)
912 			{
913 				SetError (nErr);
914 				return;
915 			}
916 		}
917     }
918 }
919 
920 
921