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