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