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 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 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 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 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 196 StreamData() { nHandle = 0; } 197 }; 198 199 // ----------------------------------------------------------------------- 200 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 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 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 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 325 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 340 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 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 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 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 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 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 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 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 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 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 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 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 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 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