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