xref: /AOO41X/main/tools/source/stream/strmunx.cxx (revision 89b56da77b74925c286b3e777681ba8dda16bf41)
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