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 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_tools.hxx" 30 31 32 #if !defined UNX 33 #include <io.h> 34 #include <process.h> 35 #endif 36 37 #if defined(UNX) || defined(OS2) 38 #include <unistd.h> 39 #include <sys/types.h> 40 #include <sys/stat.h> 41 #endif 42 43 #include <ctype.h> 44 #include <errno.h> 45 #include <stdlib.h> 46 #include <stdio.h> 47 #include <string.h> 48 #include <tools/debug.hxx> 49 #include <tools/list.hxx> 50 #include "comdep.hxx" 51 #include <tools/fsys.hxx> 52 #define _TOOLS_HXX 53 #include <tools/urlobj.hxx> 54 55 #ifdef UNX 56 #define _MAX_PATH 260 57 #endif 58 #include <tools/stream.hxx> 59 60 #ifndef _VOS_MUTEX_HXX 61 #include <vos/mutex.hxx> 62 #endif 63 64 #include <osl/file.hxx> 65 #include <rtl/instance.hxx> 66 67 68 using namespace osl; 69 using namespace rtl; 70 71 int ApiRet2ToSolarError_Impl( int nApiRet ); 72 73 //-------------------------------------------------------------------- 74 int Sys2SolarError_Impl( int nSysErr ) 75 { 76 switch ( nSysErr ) 77 { 78 #ifdef WNT 79 case NO_ERROR: return ERRCODE_NONE; 80 case ERROR_INVALID_FUNCTION: return ERRCODE_IO_GENERAL; 81 case ERROR_FILE_NOT_FOUND: return ERRCODE_IO_NOTEXISTS; 82 case ERROR_PATH_NOT_FOUND: return ERRCODE_IO_NOTEXISTSPATH; 83 case ERROR_TOO_MANY_OPEN_FILES: return ERRCODE_IO_TOOMANYOPENFILES; 84 case ERROR_ACCESS_DENIED: return ERRCODE_IO_ACCESSDENIED; 85 case ERROR_INVALID_HANDLE: return ERRCODE_IO_GENERAL; 86 case ERROR_NOT_ENOUGH_MEMORY: return ERRCODE_IO_OUTOFMEMORY; 87 case ERROR_INVALID_BLOCK: return ERRCODE_IO_GENERAL; 88 // case ERROR_BAD_ENVIRONMENT: return ERRCODE_IO_; 89 case ERROR_BAD_FORMAT: return ERRCODE_IO_WRONGFORMAT; 90 case ERROR_INVALID_ACCESS: return ERRCODE_IO_ACCESSDENIED; 91 // case ERROR_INVALID_DATA: return ERRCODE_IO_; 92 case ERROR_INVALID_DRIVE: return ERRCODE_IO_INVALIDDEVICE; 93 case ERROR_CURRENT_DIRECTORY: return ERRCODE_IO_CURRENTDIR; 94 case ERROR_NOT_SAME_DEVICE: return ERRCODE_IO_NOTSAMEDEVICE; 95 // case ERROR_NO_MORE_FILES: return ERRCODE_IO_; 96 case ERROR_WRITE_PROTECT: return ERRCODE_IO_CANTWRITE; 97 case ERROR_BAD_UNIT: return ERRCODE_IO_INVALIDDEVICE; 98 case ERROR_NOT_READY: return ERRCODE_IO_DEVICENOTREADY; 99 case ERROR_BAD_COMMAND: return ERRCODE_IO_GENERAL; 100 case ERROR_CRC: return ERRCODE_IO_BADCRC; 101 case ERROR_BAD_LENGTH: return ERRCODE_IO_INVALIDLENGTH; 102 case ERROR_SEEK: return ERRCODE_IO_CANTSEEK; 103 case ERROR_NOT_DOS_DISK: return ERRCODE_IO_WRONGFORMAT; 104 case ERROR_SECTOR_NOT_FOUND: return ERRCODE_IO_GENERAL; 105 case ERROR_WRITE_FAULT: return ERRCODE_IO_CANTWRITE; 106 case ERROR_READ_FAULT: return ERRCODE_IO_CANTREAD; 107 case ERROR_GEN_FAILURE: return ERRCODE_IO_GENERAL; 108 case ERROR_SHARING_VIOLATION: return ERRCODE_IO_LOCKVIOLATION; 109 case ERROR_LOCK_VIOLATION: return ERRCODE_IO_LOCKVIOLATION; 110 case ERROR_WRONG_DISK: return ERRCODE_IO_INVALIDDEVICE; 111 case ERROR_NOT_SUPPORTED: return ERRCODE_IO_NOTSUPPORTED; 112 #else 113 case 0: return ERRCODE_NONE; 114 case ENOENT: return ERRCODE_IO_NOTEXISTS; 115 case EACCES: return ERRCODE_IO_ACCESSDENIED; 116 case EEXIST: return ERRCODE_IO_ALREADYEXISTS; 117 case EINVAL: return ERRCODE_IO_INVALIDPARAMETER; 118 case EMFILE: return ERRCODE_IO_TOOMANYOPENFILES; 119 case ENOMEM: return ERRCODE_IO_OUTOFMEMORY; 120 case ENOSPC: return ERRCODE_IO_OUTOFSPACE; 121 #endif 122 } 123 124 DBG_TRACE1( "FSys: unknown system error %d occured", nSysErr ); 125 return FSYS_ERR_UNKNOWN; 126 } 127 128 //-------------------------------------------------------------------- 129 130 #ifndef BOOTSTRAP 131 132 FSysRedirector* FSysRedirector::_pRedirector = 0; 133 sal_Bool FSysRedirector::_bEnabled = sal_True; 134 #ifdef UNX 135 sal_Bool bInRedirection = sal_True; 136 #else 137 sal_Bool bInRedirection = sal_False; 138 #endif 139 static vos:: OMutex * pRedirectMutex = 0; 140 141 //------------------------------------------------------------------------ 142 void FSysRedirector::Register( FSysRedirector *pRedirector ) 143 { 144 if ( pRedirector ) 145 pRedirectMutex = new vos:: OMutex ; 146 else 147 DELETEZ( pRedirectMutex ); 148 _pRedirector = pRedirector; 149 } 150 151 //------------------------------------------------------------------------ 152 153 void FSysRedirector::DoRedirect( String &rPath ) 154 { 155 String aURL(rPath); 156 157 // if redirection is disabled or not even registered do nothing 158 if ( !_bEnabled || !pRedirectMutex ) 159 return; 160 161 // redirect only removable or remote volumes 162 if ( !IsRedirectable_Impl( ByteString( aURL, osl_getThreadTextEncoding() ) ) ) 163 return; 164 165 // Redirection is acessible only by one thread per time 166 // dont move the guard behind the bInRedirection check!!! 167 // think of nested calls (when called from callback) 168 vos:: OGuard aGuard( pRedirectMutex ); 169 170 // if already in redirection, dont redirect 171 if ( bInRedirection ) 172 return; 173 174 // dont redirect on nested calls 175 bInRedirection = sal_True; 176 177 // convert to URL 178 #ifndef UNX 179 for ( sal_Unicode *p = (sal_Unicode*)aURL.GetBuffer(); *p; ++p ) 180 if ( '\\' == *p ) *p = '/'; 181 else if ( ':' == *p ) *p = '|'; 182 #endif 183 184 aURL.Insert( String("file:///", osl_getThreadTextEncoding()), 0 ); 185 186 // do redirection 187 Redirector(); 188 189 bInRedirection = sal_False; 190 return; 191 } 192 193 //------------------------------------------------------------------------ 194 195 FSysRedirector* FSysRedirector::Redirector() 196 { 197 if ( !_pRedirector ) 198 Register( new FSysRedirector ); 199 return _pRedirector; 200 } 201 202 #endif // BOOTSTRAP 203 204 //-------------------------------------------------------------------- 205 206 class DirEntryStack: public List 207 { 208 public: 209 DirEntryStack() {}; 210 ~DirEntryStack(); 211 212 inline void Push( DirEntry *pEntry ); 213 inline DirEntry* Pop(); 214 inline DirEntry* Top(); 215 inline DirEntry* Bottom(); 216 }; 217 218 inline void DirEntryStack::Push( DirEntry *pEntry ) 219 { 220 List::Insert( pEntry, LIST_APPEND ); 221 } 222 223 inline DirEntry* DirEntryStack::Pop() 224 { 225 return (DirEntry*) List::Remove( Count() - 1 ); 226 } 227 228 inline DirEntry* DirEntryStack::Top() 229 { 230 return (DirEntry*) List::GetObject( Count() - 1 ); 231 } 232 233 inline DirEntry* DirEntryStack::Bottom() 234 { 235 return (DirEntry*) List::GetObject( 0 ); 236 } 237 238 //-------------------------------------------------------------------- 239 240 DBG_NAME( DirEntry ); 241 242 /************************************************************************* 243 |* 244 |* DirEntry::~DirEntryStack() 245 |* 246 |* Beschreibung FSYS.SDW 247 |* Ersterstellung MI 26.04.91 248 |* Letzte Aenderung MI 04.07.91 249 |* 250 *************************************************************************/ 251 252 DirEntryStack::~DirEntryStack() 253 { 254 while ( Count() ) 255 delete Pop(); 256 } 257 258 /************************************************************************* 259 |* 260 |* ImpCheckDirEntry() 261 |* 262 |* Beschreibung Pruefung eines DirEntry fuer DBG_UTIL 263 |* Parameter void* p Zeiger auf den DirEntry 264 |* Return-Wert char* Fehlermeldungs-TExtension oder NULL 265 |* Ersterstellung MI 16.07.91 266 |* Letzte Aenderung MI 26.05.93 267 |* 268 *************************************************************************/ 269 270 #ifdef DBG_UTIL 271 const char* ImpCheckDirEntry( const void* p ) 272 { 273 DirEntry* p0 = (DirEntry*)p; 274 275 if ( p0->pParent ) 276 DBG_CHKOBJ( p0->pParent, DirEntry, ImpCheckDirEntry ); 277 278 return NULL; 279 } 280 #endif 281 282 /************************************************************************* 283 |* 284 |* ImplCutPath() 285 |* 286 |* Beschreibung Fuegt ... ein, damit maximal nMaxChars lang 287 |* Ersterstellung MI 06.04.94 288 |* Letzte Aenderung DV 24.06.96 289 |* 290 *************************************************************************/ 291 292 ByteString ImplCutPath( const ByteString& rStr, sal_uInt16 nMax, char cAccDel ) 293 { 294 sal_uInt16 nMaxPathLen = nMax; 295 ByteString aCutPath( rStr ); 296 sal_Bool bInsertPrefix = sal_False; 297 sal_uInt16 nBegin = aCutPath.Search( cAccDel ); 298 299 if( nBegin == STRING_NOTFOUND ) 300 nBegin = 0; 301 else 302 nMaxPathLen += 2; // fuer Prefix <Laufwerk>: 303 304 while( aCutPath.Len() > nMaxPathLen ) 305 { 306 sal_uInt16 nEnd = aCutPath.Search( cAccDel, nBegin + 1 ); 307 sal_uInt16 nCount; 308 309 if ( nEnd != STRING_NOTFOUND ) 310 { 311 nCount = nEnd - nBegin; 312 aCutPath.Erase( nBegin, nCount ); 313 bInsertPrefix = sal_True; 314 } 315 else 316 break; 317 } 318 319 if ( aCutPath.Len() > nMaxPathLen ) 320 { 321 for ( sal_uInt16 n = nMaxPathLen; n > nMaxPathLen/2; --n ) 322 if ( !ByteString(aCutPath.GetChar(n)).IsAlphaNumericAscii() ) 323 { 324 aCutPath.Erase( n ); 325 aCutPath += "..."; 326 break; 327 } 328 } 329 330 if ( bInsertPrefix ) 331 { 332 ByteString aIns( cAccDel ); 333 aIns += "..."; 334 aCutPath.Insert( aIns, nBegin ); 335 } 336 337 return aCutPath; 338 } 339 340 /************************************************************************* 341 |* 342 |* DirEntry::ImpParseOs2Name() 343 |* 344 |* Beschreibung FSYS.SDW 345 |* Ersterstellung MI 26.04.91 346 |* Letzte Aenderung MI 23.06.95 347 |* 348 *************************************************************************/ 349 350 FSysError DirEntry::ImpParseOs2Name( const ByteString& rPfad, FSysPathStyle eStyle ) 351 { 352 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 353 354 // die einzelnen Namen auf einen Stack packen 355 String aPfad( rPfad, osl_getThreadTextEncoding() ); 356 DirEntryStack aStack; 357 358 do 359 { 360 // den Namen vor dem ersten "\\" abspalten, 361 // falls '\\' am Anfang, ist der Name '\\', 362 // der Rest immer ohne die fuehrenden '\\'. 363 // ein ":" trennt ebenfalls, gehoert aber zum Namen 364 // den ersten '\\', '/' oder ':' suchen 365 sal_uInt16 nPos; 366 for ( nPos = 0; 367 nPos < aPfad.Len() && //?O 368 aPfad.GetChar(nPos) != '\\' && aPfad.GetChar(nPos) != '/' && //?O 369 aPfad.GetChar(nPos) != ':'; //?O 370 nPos++ ) 371 /* do nothing */; 372 373 // ist der Name ein UNC Pathname? 374 if ( nPos == 0 && aPfad.Len() > 1 && 375 ( ( aPfad.GetChar(0) == '\\' && aPfad.GetChar(1) == '\\' ) || 376 ( aPfad.GetChar(0) == '/' && aPfad.GetChar(1) == '/' ) ) ) 377 { 378 for ( nPos = 2; aPfad.Len() > nPos; ++nPos ) 379 if ( aPfad.GetChar(nPos) == '\\' || aPfad.GetChar(nPos) == '/' ) 380 break; 381 aName = ByteString( aPfad.Copy( 2, nPos-2 ), osl_getThreadTextEncoding() ); 382 aStack.Push( new DirEntry( aName, FSYS_FLAG_ABSROOT, eStyle ) ); 383 } 384 // ist der Name die Root des aktuellen Drives? 385 else if ( nPos == 0 && aPfad.Len() > 0 && 386 ( aPfad.GetChar(0) == '\\' || aPfad.GetChar(0) == '/' ) ) 387 { 388 // Root-Directory des aktuellen Drives 389 aStack.Push( new DirEntry( FSYS_FLAG_ABSROOT ) ); 390 } 391 else 392 { 393 // ist der Name ein Drive? 394 if ( nPos < aPfad.Len() && aPfad.GetChar(nPos) == ':' ) 395 { 396 aName = ByteString( aPfad.Copy( 0, nPos + 1 ), osl_getThreadTextEncoding() ); 397 398 // ist der Name die Root des Drives 399 if ( (nPos + 1) < aPfad.Len() && 400 ( aPfad.GetChar(nPos+1) == '\\' || aPfad.GetChar(nPos+1) == '/' ) ) 401 { 402 // schon was auf dem Stack? 403 // oder Novell-Format? (not supported wegen URLs) 404 if ( aStack.Count() || aName.Len() > 2 ) 405 { 406 aName = rPfad; 407 return FSYS_ERR_MISPLACEDCHAR; 408 } 409 // Root-Directory des Drive 410 aStack.Push( new DirEntry( aName, FSYS_FLAG_ABSROOT, eStyle ) ); 411 } 412 else 413 { 414 // liegt ein anderes Drive auf dem Stack? 415 if ( aStack.Count() && 416 COMPARE_EQUAL != aStack.Bottom()->aName.CompareIgnoreCaseToAscii(aName) ) 417 aStack.Clear(); 418 419 // liegt jetzt nichts mehr auf dem Stack? 420 if ( !aStack.Count() ) 421 aStack.Push( new DirEntry( aName, FSYS_FLAG_RELROOT, eStyle ) ); 422 } 423 } 424 425 // es ist kein Drive 426 else 427 { 428 // den Namen ohne Trenner abspalten 429 aName = ByteString( aPfad.Copy( 0, nPos ), osl_getThreadTextEncoding() ); 430 431 // stellt der Name die aktuelle Directory dar? 432 if ( aName == "." ) 433 /* do nothing */; 434 435 // stellt der Name die Parent-Directory dar? 436 else if ( aName == ".." ) 437 { 438 // ist nichts, ein Parent oder eine relative Root 439 // auf dem Stack? 440 if ( ( aStack.Count() == 0 ) || 441 ( aStack.Top()->eFlag == FSYS_FLAG_PARENT ) || 442 ( aStack.Top()->eFlag == FSYS_FLAG_RELROOT ) ) 443 // fuehrende Parents kommen auf den Stack 444 aStack.Push( new DirEntry( FSYS_FLAG_PARENT ) ); 445 446 // ist es eine absolute Root 447 else if ( aStack.Top()->eFlag == FSYS_FLAG_ABSROOT ) 448 { 449 // die hat keine Parent-Directory 450 aName = rPfad; 451 return FSYS_ERR_NOTEXISTS; 452 } 453 else 454 // sonst hebt der Parent den TOS auf 455 delete aStack.Pop(); 456 } 457 458 else 459 { 460 if ( eStyle == FSYS_STYLE_FAT ) 461 { 462 // ist der Name grundsaetzlich ungueltig? 463 int nPunkte = 0; 464 const char *pChar; 465 for ( pChar = aName.GetBuffer(); 466 nPunkte < 2 && *pChar != 0; 467 pChar++ ) 468 { 469 if ( *pChar == ';' ) 470 nPunkte = 0; 471 else 472 nPunkte += ( *pChar == '.' ) ? 1 : 0; 473 } 474 if ( nPunkte > 1 ) 475 { 476 aName = rPfad; 477 return FSYS_ERR_MISPLACEDCHAR; 478 } 479 } 480 481 // normalen Entries kommen auf den Stack 482 DirEntry *pNew = new DirEntry( aName, FSYS_FLAG_NORMAL, eStyle ); 483 if ( !pNew->IsValid() ) 484 { 485 aName = rPfad; 486 ErrCode eErr = pNew->GetError(); 487 delete pNew; 488 return eErr; 489 } 490 aStack.Push( pNew ); 491 } 492 } 493 } 494 495 // den Restpfad bestimmen 496 aPfad.Erase( 0, nPos + 1 ); 497 while ( aPfad.Len() && ( aPfad.GetChar(0) == '\\' || aPfad.GetChar(0) == '/' ) ) 498 aPfad.Erase( 0, 1 ); 499 } 500 while ( aPfad.Len() ); 501 502 sal_uIntPtr nErr = ERRCODE_NONE; 503 // Haupt-Entry (selbst) zuweisen 504 if ( aStack.Count() == 0 ) 505 { 506 eFlag = FSYS_FLAG_CURRENT; 507 aName.Erase(); 508 } 509 else 510 { 511 eFlag = aStack.Top()->eFlag; 512 aName = aStack.Top()->aName; 513 nErr = aStack.Top()->nError; 514 delete aStack.Pop(); 515 } 516 517 // die Parent-Entries vom Stack holen 518 DirEntry** pTemp = &pParent; // Zeiger auf den Member pParent setzen 519 while ( aStack.Count() ) 520 { 521 *pTemp = aStack.Pop(); 522 523 // Zeiger auf den Member pParent des eigenen Parent setzen 524 pTemp = &( (*pTemp)->pParent ); 525 } 526 527 // wird damit ein Volume beschrieben? 528 if ( !pParent && eFlag == FSYS_FLAG_RELROOT && aName.Len() ) 529 eFlag = FSYS_FLAG_VOLUME; 530 531 // bei gesetztem ErrorCode den Namen komplett "ubernehmen 532 if ( nErr ) 533 aName = rPfad; 534 return nErr; 535 } 536 537 /************************************************************************* 538 |* 539 |* DirEntry::ImpParseName() 540 |* 541 |* Beschreibung FSYS.SDW 542 |* Ersterstellung MI 26.08.91 543 |* Letzte Aenderung MI 26.05.93 544 |* 545 *************************************************************************/ 546 547 FSysError DirEntry::ImpParseName( const ByteString& rbInitName, 548 FSysPathStyle eStyle ) 549 { 550 String rInitName( rbInitName, osl_getThreadTextEncoding() ); 551 if ( eStyle == FSYS_STYLE_HOST ) 552 eStyle = DEFSTYLE; 553 554 // KI-Division of FSys 555 if ( eStyle == FSYS_STYLE_DETECT ) 556 { 557 sal_Unicode cFirst = rInitName.GetChar(0); 558 if ( rInitName.Len() == 2 && rInitName.GetChar(1) == ':' && 559 ((cFirst >= 'A' && cFirst <= 'Z') || 560 (cFirst >= 'a' && cFirst <= 'z'))) 561 eStyle = FSYS_STYLE_HPFS; 562 else if ( rInitName.Len() > 2 && rInitName.GetChar(1) == ':' ) 563 { 564 if ( rInitName.Search( ':', 2 ) == STRING_NOTFOUND ) 565 eStyle = FSYS_STYLE_HPFS; 566 else 567 eStyle = FSYS_STYLE_MAC; 568 } 569 else if ( rInitName.Search( '/' ) != STRING_NOTFOUND ) 570 eStyle = FSYS_STYLE_BSD; 571 else if ( rInitName.Search( '\\' ) != STRING_NOTFOUND ) 572 eStyle = FSYS_STYLE_HPFS; 573 else if ( rInitName.Search( ':' ) != STRING_NOTFOUND ) 574 eStyle = FSYS_STYLE_MAC; 575 else 576 eStyle = FSYS_STYLE_HPFS; 577 } 578 579 switch ( eStyle ) 580 { 581 case FSYS_STYLE_FAT: 582 case FSYS_STYLE_VFAT: 583 case FSYS_STYLE_HPFS: 584 case FSYS_STYLE_NTFS: 585 case FSYS_STYLE_NWFS: 586 return ImpParseOs2Name( rbInitName, eStyle ); 587 588 case FSYS_STYLE_BSD: 589 case FSYS_STYLE_SYSV: 590 return ImpParseUnixName( rbInitName, eStyle ); 591 592 case FSYS_STYLE_MAC: 593 return FSYS_ERR_OK; 594 595 default: 596 return FSYS_ERR_UNKNOWN; 597 } 598 } 599 600 /************************************************************************* 601 |* 602 |* GetStyle() 603 |* 604 |* Beschreibung FSYS.SDW 605 |* Ersterstellung MI 15.11.91 606 |* Letzte Aenderung MI 15.11.91 607 |* 608 *************************************************************************/ 609 610 static FSysPathStyle GetStyle( FSysPathStyle eStyle ) 611 { 612 if ( eStyle == FSYS_STYLE_HOST || eStyle == FSYS_STYLE_DETECT ) 613 return DEFSTYLE; 614 else 615 return eStyle; 616 } 617 618 /************************************************************************* 619 |* 620 |* DirEntry::ImpTrim() 621 |* 622 |* Beschreibung bringt den Namen auf Betriebssystem-Norm 623 |* z.B. 8.3 lower beim MS-DOS Formatter 624 |* wirkt nicht rekursiv 625 |* Ersterstellung MI 12.08.91 626 |* Letzte Aenderung MI 21.05.92 627 |* 628 *************************************************************************/ 629 630 void DirEntry::ImpTrim( FSysPathStyle eStyle ) 631 { 632 // Wildcards werden nicht geclipt 633 if ( ( aName.Search( '*' ) != STRING_NOTFOUND ) || 634 ( aName.Search( '?' ) != STRING_NOTFOUND ) || 635 ( aName.Search( ';' ) != STRING_NOTFOUND ) ) 636 return; 637 638 switch ( eStyle ) 639 { 640 case FSYS_STYLE_FAT: 641 { 642 sal_uInt16 nPunktPos = aName.Search( '.' ); 643 if ( nPunktPos == STRING_NOTFOUND ) 644 { 645 if ( aName.Len() > 8 ) 646 { 647 nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK; 648 aName.Erase( 8 ); 649 } 650 } 651 else 652 { 653 if ( nPunktPos > 8 ) 654 { 655 nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK; 656 aName.Erase( 8, nPunktPos - 8 ); 657 nPunktPos = 8; 658 } 659 if ( aName.Len() > nPunktPos + 3 ) 660 { 661 if ( aName.Len() - nPunktPos > 4 ) 662 { 663 nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK; 664 aName.Erase( nPunktPos + 4 ); 665 } 666 } 667 } 668 aName.ToLowerAscii(); 669 break; 670 } 671 672 case FSYS_STYLE_VFAT: 673 case FSYS_STYLE_HPFS: 674 case FSYS_STYLE_NTFS: 675 case FSYS_STYLE_NWFS: 676 if ( aName.Len() > 254 ) 677 { 678 nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK; 679 aName.Erase( 254 ); 680 } 681 682 if ( eStyle == FSYS_STYLE_HPFS && 683 ( eFlag == FSYS_FLAG_ABSROOT || eFlag == FSYS_FLAG_RELROOT ) ) 684 aName.ToUpperAscii(); 685 break; 686 687 case FSYS_STYLE_SYSV: 688 if ( aName.Len() > 14 ) 689 { 690 nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK; 691 aName.Erase( 14 ); 692 } 693 break; 694 695 case FSYS_STYLE_BSD: 696 if ( aName.Len() > 250 ) 697 { 698 nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK; 699 aName.Erase( 250 ); 700 } 701 break; 702 703 case FSYS_STYLE_MAC: 704 if ( eFlag & ( FSYS_FLAG_ABSROOT | FSYS_FLAG_VOLUME ) ) 705 { 706 if ( aName.Len() > 27 ) 707 { 708 nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK; 709 aName.Erase( 27 ); 710 } 711 } 712 else 713 { 714 if ( aName.Len() > 31 ) 715 { 716 nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK; 717 aName.Erase( 31 ); 718 } 719 } 720 break; 721 722 default: 723 /* kann nicht sein */; 724 } 725 } 726 727 /************************************************************************* 728 |* 729 |* DirEntry::DirEntry() 730 |* 731 |* Beschreibung FSYS.SDW 732 |* Ersterstellung MI 26.04.91 733 |* Letzte Aenderung MA 02.12.91 734 |* 735 *************************************************************************/ 736 737 DirEntry::DirEntry( const ByteString& rName, DirEntryFlag eDirFlag, 738 FSysPathStyle eStyle ) : 739 #ifdef FEAT_FSYS_DOUBLESPEED 740 pStat( 0 ), 741 #endif 742 aName( rName ) 743 { 744 DBG_CTOR( DirEntry, ImpCheckDirEntry ); 745 746 pParent = NULL; 747 eFlag = eDirFlag; 748 nError = FSYS_ERR_OK; 749 750 ImpTrim( eStyle ); 751 } 752 753 /************************************************************************* 754 |* 755 |* DirEntry::DirEntry() 756 |* 757 |* Beschreibung FSYS.SDW 758 |* Ersterstellung MI 26.04.91 759 |* Letzte Aenderung MA 02.12.91 760 |* 761 *************************************************************************/ 762 763 DirEntry::DirEntry( const DirEntry& rOrig ) : 764 #ifdef FEAT_FSYS_DOUBLESPEED 765 pStat( rOrig.pStat ? new FileStat(*rOrig.pStat) : 0 ), 766 #endif 767 aName( rOrig.aName ) 768 { 769 DBG_CTOR( DirEntry, ImpCheckDirEntry ); 770 771 eFlag = rOrig.eFlag; 772 nError = rOrig.nError; 773 774 if ( rOrig.pParent ) 775 { 776 pParent = new DirEntry( *rOrig.pParent ); 777 } 778 else 779 { 780 pParent = NULL; 781 } 782 } 783 784 /************************************************************************* 785 |* 786 |* DirEntry::DirEntry() 787 |* 788 |* Beschreibung FSYS.SDW 789 |* Ersterstellung MI 26.04.91 790 |* Letzte Aenderung MA 02.12.91 791 |* 792 *************************************************************************/ 793 794 DirEntry::DirEntry( const String& rInitName, FSysPathStyle eStyle ) 795 #ifdef FEAT_FSYS_DOUBLESPEED 796 : pStat( 0 ) 797 #endif 798 { 799 DBG_CTOR( DirEntry, ImpCheckDirEntry ); 800 801 pParent = NULL; 802 803 // schnelle Loesung fuer Leerstring 804 if ( !rInitName.Len()) 805 { 806 eFlag = FSYS_FLAG_CURRENT; 807 nError = FSYS_ERR_OK; 808 return; 809 } 810 811 ByteString aTmpName(rInitName, osl_getThreadTextEncoding()); 812 if( eStyle == FSYS_STYLE_URL || aTmpName.CompareIgnoreCaseToAscii("file:",5 ) == COMPARE_EQUAL ) 813 { 814 #ifndef BOOTSTRAP 815 DBG_WARNING( "File URLs are not permitted but accepted" ); 816 aTmpName = ByteString(String(INetURLObject( rInitName ).PathToFileName()), osl_getThreadTextEncoding()); 817 eStyle = FSYS_STYLE_HOST; 818 #endif // BOOTSTRAP 819 } 820 else 821 { 822 ::rtl::OUString aTmp; 823 ::rtl::OUString aOInitName; 824 if ( FileBase::getFileURLFromSystemPath( OUString( rInitName ), aTmp ) == FileBase::E_None ) 825 { 826 aOInitName = OUString( rInitName ); 827 aTmpName = ByteString( String(aOInitName), osl_getThreadTextEncoding() ); 828 } 829 830 #ifdef DBG_UTIL 831 // ASF nur bei Default eStyle, nicht z.B. aus MakeShortName() 832 if( eStyle == FSYS_STYLE_HOST && 833 aTmpName.Search( "://" ) != STRING_NOTFOUND ) 834 { 835 ByteString aErr = "DirEntries akzeptieren nur File URLS: "; 836 aErr += aTmpName; 837 DBG_WARNING( aErr.GetBuffer() ); 838 } 839 #endif 840 } 841 842 nError = ImpParseName( aTmpName, eStyle ); 843 844 if ( nError != FSYS_ERR_OK ) 845 eFlag = FSYS_FLAG_INVALID; 846 } 847 848 /*************************************************************************/ 849 850 DirEntry::DirEntry( const ByteString& rInitName, FSysPathStyle eStyle ) 851 #ifdef FEAT_FSYS_DOUBLESPEED 852 : pStat( 0 ) 853 #endif 854 { 855 DBG_CTOR( DirEntry, ImpCheckDirEntry ); 856 857 pParent = NULL; 858 859 // schnelle Loesung fuer Leerstring 860 if ( !rInitName.Len() ) 861 { 862 eFlag = FSYS_FLAG_CURRENT; 863 nError = FSYS_ERR_OK; 864 return; 865 } 866 867 ByteString aTmpName( rInitName ); 868 if( eStyle == FSYS_STYLE_URL || rInitName.CompareIgnoreCaseToAscii("file:",5 ) == COMPARE_EQUAL ) 869 { 870 #ifndef BOOTSTRAP 871 DBG_WARNING( "File URLs are not permitted but accepted" ); 872 aTmpName = ByteString(String(INetURLObject( rInitName ).PathToFileName()), osl_getThreadTextEncoding()); 873 eStyle = FSYS_STYLE_HOST; 874 #endif 875 } 876 #ifdef DBG_UTIL 877 else 878 // ASF nur bei Default eStyle, nicht z.B. aus MakeShortName() 879 if( eStyle == FSYS_STYLE_HOST && 880 rInitName.Search( "://" ) != STRING_NOTFOUND ) 881 { 882 ByteString aErr = "DirEntries akzeptieren nur File URLS: "; 883 aErr += rInitName; 884 DBG_WARNING( aErr.GetBuffer() ); 885 } 886 #endif 887 888 nError = ImpParseName( aTmpName, eStyle ); 889 890 if ( nError != FSYS_ERR_OK ) 891 eFlag = FSYS_FLAG_INVALID; 892 } 893 894 /************************************************************************* 895 |* 896 |* DirEntry::DirEntry() 897 |* 898 |* Beschreibung FSYS.SDW 899 |* Ersterstellung MI 26.04.91 900 |* Letzte Aenderung MA 02.12.91 901 |* 902 *************************************************************************/ 903 904 DirEntry::DirEntry( DirEntryFlag eDirFlag ) 905 #ifdef FEAT_FSYS_DOUBLESPEED 906 : pStat( 0 ) 907 #endif 908 { 909 DBG_CTOR( DirEntry, ImpCheckDirEntry ); 910 911 eFlag = eDirFlag; 912 nError = ( eFlag == FSYS_FLAG_INVALID ) ? FSYS_ERR_UNKNOWN : FSYS_ERR_OK; 913 pParent = NULL; 914 } 915 916 /************************************************************************* 917 |* 918 |* DirEntry::~DirEntry() 919 |* 920 |* Beschreibung FSYS.SDW 921 |* Ersterstellung MI 26.04.91 922 |* Letzte Aenderung MA 02.12.91 923 |* 924 *************************************************************************/ 925 926 DirEntry::~DirEntry() 927 { 928 DBG_DTOR( DirEntry, ImpCheckDirEntry ); 929 930 delete pParent; 931 #ifdef FEAT_FSYS_DOUBLESPEED 932 delete pStat; 933 #endif 934 935 } 936 937 /************************************************************************* 938 |* 939 |* DirEntry::ImpGetTopPtr() const 940 |* 941 |* Beschreibung FSYS.SDW 942 |* Ersterstellung MI 26.04.91 943 |* Letzte Aenderung MA 02.12.91 944 |* 945 *************************************************************************/ 946 947 const DirEntry* DirEntry::ImpGetTopPtr() const 948 { 949 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 950 951 const DirEntry *pTemp = this; 952 while ( pTemp->pParent ) 953 pTemp = pTemp->pParent; 954 955 return pTemp; 956 } 957 958 /************************************************************************* 959 |* 960 |* DirEntry::ImpGetTopPtr() 961 |* 962 |* Beschreibung FSYS.SDW 963 |* Ersterstellung MI 13.11.91 964 |* Letzte Aenderung MA 02.12.91 965 |* 966 *************************************************************************/ 967 968 DirEntry* DirEntry::ImpGetTopPtr() 969 { 970 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 971 972 DirEntry *pTemp = this; 973 while ( pTemp->pParent ) 974 pTemp = pTemp->pParent; 975 976 return pTemp; 977 } 978 979 /************************************************************************* 980 |* 981 |* DirEntry::ImpGetPreTopPtr() 982 |* 983 |* Beschreibung liefert einen Pointer auf den vorletzten Entry 984 |* Ersterstellung MI 01.11.91 985 |* Letzte Aenderung MA 02.12.91 986 |* 987 *************************************************************************/ 988 989 DirEntry* DirEntry::ImpGetPreTopPtr() 990 { 991 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 992 993 DirEntry *pTemp = this; 994 if ( pTemp->pParent ) 995 { 996 while ( pTemp->pParent->pParent ) 997 pTemp = pTemp->pParent; 998 } 999 1000 return pTemp; 1001 } 1002 1003 /************************************************************************* 1004 |* 1005 |* DirEntry::ImpChangeParent() 1006 |* 1007 |* Beschreibung FSYS.SDW 1008 |* Ersterstellung MI 26.04.91 1009 |* Letzte Aenderung MI 21.05.92 1010 |* 1011 *************************************************************************/ 1012 1013 DirEntry* DirEntry::ImpChangeParent( DirEntry* pNewParent, sal_Bool bNormalize ) 1014 { 1015 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 1016 1017 DirEntry *pTemp = pParent; 1018 if ( bNormalize && pNewParent && 1019 pNewParent->eFlag == FSYS_FLAG_RELROOT && !pNewParent->aName.Len() ) 1020 { 1021 pParent = 0; 1022 delete pNewParent; 1023 } 1024 else 1025 pParent = pNewParent; 1026 1027 return pTemp; 1028 } 1029 1030 /************************************************************************* 1031 |* 1032 |* DirEntry::Exists() 1033 |* 1034 |* Beschreibung FSYS.SDW 1035 |* Ersterstellung MI 26.04.91 1036 |* Letzte Aenderung MI 24.09.91 1037 |* 1038 *************************************************************************/ 1039 1040 sal_Bool DirEntry::Exists( FSysAccess nAccess ) const 1041 { 1042 #ifndef BOOTSTRAP 1043 static vos::OMutex aLocalMutex; 1044 vos::OGuard aGuard( aLocalMutex ); 1045 #endif 1046 if ( !IsValid() ) 1047 return sal_False; 1048 1049 #if defined WNT || defined OS2 1050 // spezielle Filenamen sind vom System da 1051 if ( ( aName.CompareIgnoreCaseToAscii("CLOCK$") == COMPARE_EQUAL || 1052 aName.CompareIgnoreCaseToAscii("CON") == COMPARE_EQUAL || 1053 aName.CompareIgnoreCaseToAscii("AUX") == COMPARE_EQUAL || 1054 aName.CompareIgnoreCaseToAscii("COM1") == COMPARE_EQUAL || 1055 aName.CompareIgnoreCaseToAscii("COM2") == COMPARE_EQUAL || 1056 aName.CompareIgnoreCaseToAscii("COM3") == COMPARE_EQUAL || 1057 aName.CompareIgnoreCaseToAscii("COM4") == COMPARE_EQUAL || 1058 aName.CompareIgnoreCaseToAscii("LPT1") == COMPARE_EQUAL || 1059 aName.CompareIgnoreCaseToAscii("LPT2") == COMPARE_EQUAL || 1060 aName.CompareIgnoreCaseToAscii("LPT3") == COMPARE_EQUAL || 1061 aName.CompareIgnoreCaseToAscii("NUL") == COMPARE_EQUAL || 1062 aName.CompareIgnoreCaseToAscii("PRN") == COMPARE_EQUAL ) ) 1063 return sal_True; 1064 #endif 1065 1066 FSysFailOnErrorImpl(); 1067 DirEntryKind eKind = FileStat( *this, nAccess ).GetKind(); 1068 if ( eKind & ( FSYS_KIND_FILE | FSYS_KIND_DIR ) ) 1069 { 1070 return sal_True; 1071 } 1072 1073 #if defined WNT || defined OS2 1074 if ( 0 != ( eKind & FSYS_KIND_DEV ) ) 1075 { 1076 return DRIVE_EXISTS( ImpGetTopPtr()->aName.GetChar(0) ); 1077 } 1078 #endif 1079 1080 return 0 != ( eKind & ( FSYS_KIND_FILE | FSYS_KIND_DIR ) ); 1081 } 1082 1083 /************************************************************************* 1084 |* 1085 |* DirEntry::First() 1086 |* 1087 |* Beschreibung FSYS.SDW 1088 |* Ersterstellung MI 26.04.91 1089 |* Letzte Aenderung MA 15.01.92 1090 |* 1091 *************************************************************************/ 1092 1093 sal_Bool DirEntry::First() 1094 { 1095 FSysFailOnErrorImpl(); 1096 1097 String aUniPathName( GetPath().GetFull() ); 1098 #ifndef BOOTSTRAP 1099 FSysRedirector::DoRedirect( aUniPathName ); 1100 ByteString aPathName(aUniPathName, osl_getThreadTextEncoding()); 1101 #else 1102 ByteString aPathName(aUniPathName, gsl_getSystemTextEncoding()); 1103 #endif 1104 aPathName = GUI2FSYS( aPathName ); 1105 1106 DIR *pDir = opendir( (char*) aPathName.GetBuffer() ); 1107 if ( pDir ) 1108 { 1109 #ifndef BOOTSTRAP 1110 WildCard aWildeKarte( String(CMP_LOWER( aName ), osl_getThreadTextEncoding()) ); 1111 #else 1112 WildCard aWildeKarte( String(CMP_LOWER( aName ), gsl_getSystemTextEncoding()) ); 1113 #endif 1114 for ( dirent* pEntry = readdir( pDir ); 1115 pEntry; 1116 pEntry = readdir( pDir ) ) 1117 { 1118 ByteString aFound( FSYS2GUI( ByteString( pEntry->d_name ) ) ); 1119 if ( aWildeKarte.Matches( String(CMP_LOWER( aFound ), osl_getThreadTextEncoding()))) 1120 { 1121 aName = aFound; 1122 closedir( pDir ); 1123 return sal_True; 1124 } 1125 } 1126 closedir( pDir ); 1127 } 1128 return sal_False; 1129 } 1130 1131 /************************************************************************* 1132 |* 1133 |* DirEntry::GetFull() 1134 |* 1135 |* Beschreibung FSYS.SDW 1136 |* Ersterstellung MI 26.04.91 1137 |* Letzte Aenderung MA 02.12.91 1138 |* 1139 *************************************************************************/ 1140 1141 String DirEntry::GetFull( FSysPathStyle eStyle, sal_Bool bWithDelimiter, 1142 sal_uInt16 nMaxChars ) const 1143 { 1144 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 1145 1146 ByteString aRet; 1147 eStyle = GetStyle( eStyle ); 1148 if ( pParent ) 1149 { 1150 if ( ( pParent->eFlag == FSYS_FLAG_ABSROOT || 1151 pParent->eFlag == FSYS_FLAG_RELROOT || 1152 pParent->eFlag == FSYS_FLAG_VOLUME ) ) 1153 { 1154 aRet = ByteString(pParent->GetName( eStyle ), osl_getThreadTextEncoding()); 1155 aRet += ByteString(GetName( eStyle ), osl_getThreadTextEncoding()); 1156 } 1157 else 1158 { 1159 aRet = ByteString(pParent->GetFull( eStyle ), osl_getThreadTextEncoding()); 1160 aRet += ACCESSDELIM_C(eStyle); 1161 aRet += ByteString(GetName( eStyle ), osl_getThreadTextEncoding()); 1162 } 1163 } 1164 else 1165 { 1166 aRet = ByteString(GetName( eStyle ), osl_getThreadTextEncoding()); 1167 } 1168 1169 if ( ( eStyle == FSYS_STYLE_MAC ) && 1170 ( ImpGetTopPtr()->eFlag != FSYS_FLAG_VOLUME ) && 1171 ( ImpGetTopPtr()->eFlag != FSYS_FLAG_ABSROOT ) && 1172 ( aRet.GetChar(0) != ':' ) ) 1173 aRet.Insert( ACCESSDELIM_C(eStyle), 0 ); 1174 1175 //! Hack 1176 if ( bWithDelimiter ) 1177 if ( aRet.GetChar( aRet.Len()-1 ) != ACCESSDELIM_C(eStyle) ) 1178 aRet += ACCESSDELIM_C(eStyle); 1179 1180 //! noch ein Hack 1181 if ( nMaxChars < STRING_MAXLEN ) 1182 aRet = ImplCutPath( aRet, nMaxChars, ACCESSDELIM_C(eStyle) ); 1183 1184 return String(aRet, osl_getThreadTextEncoding()); 1185 } 1186 1187 /************************************************************************* 1188 |* 1189 |* DirEntry::GetPath() 1190 |* 1191 |* Beschreibung FSYS.SDW 1192 |* Ersterstellung MI 26.04.91 1193 |* Letzte Aenderung MA 02.12.91 1194 |* 1195 *************************************************************************/ 1196 1197 DirEntry DirEntry::GetPath() const 1198 { 1199 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 1200 1201 if ( pParent ) 1202 return DirEntry( *pParent ); 1203 1204 return DirEntry(); 1205 } 1206 1207 /************************************************************************* 1208 |* 1209 |* DirEntry::GetExtension() 1210 |* 1211 |* Beschreibung FSYS.SDW 1212 |* Ersterstellung MI 26.04.91 1213 |* Letzte Aenderung MA 02.12.91 1214 |* 1215 *************************************************************************/ 1216 1217 String DirEntry::GetExtension( char cSep ) const 1218 { 1219 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 1220 1221 const char *p0 = ( aName.GetBuffer() ); 1222 const char *p1 = p0 + aName.Len() - 1; 1223 while ( p1 >= p0 && *p1 != cSep ) 1224 p1--; 1225 1226 if ( p1 >= p0 ) 1227 // es wurde ein cSep an der Position p1 gefunden 1228 return String( 1229 aName.Copy( static_cast< xub_StrLen >(p1 - p0 + 1) ), 1230 osl_getThreadTextEncoding()); 1231 return String(); 1232 } 1233 1234 /************************************************************************* 1235 |* 1236 |* DirEntry::GetBase() 1237 |* 1238 |* Beschreibung FSYS.SDW 1239 |* Ersterstellung MI 26.04.91 1240 |* Letzte Aenderung MA 02.12.91 1241 |* 1242 *************************************************************************/ 1243 1244 String DirEntry::GetBase( char cSep ) const 1245 { 1246 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 1247 1248 const char *p0 = ( aName.GetBuffer() ); 1249 const char *p1 = p0 + aName.Len() - 1; 1250 while ( p1 >= p0 && *p1 != cSep ) 1251 p1--; 1252 1253 if ( p1 >= p0 ) 1254 // es wurde ein cSep an der Position p1 gefunden 1255 return String( 1256 aName.Copy( 0, static_cast< xub_StrLen >(p1 - p0) ), 1257 osl_getThreadTextEncoding()); 1258 1259 else 1260 // es wurde kein cSep gefunden 1261 return String(aName, osl_getThreadTextEncoding()); 1262 } 1263 1264 /************************************************************************* 1265 |* 1266 |* DirEntry::GetName() 1267 |* 1268 |* Beschreibung FSYS.SDW 1269 |* Ersterstellung MI 26.04.91 1270 |* Letzte Aenderung MA 02.12.91 13:47 1271 |* 1272 *************************************************************************/ 1273 1274 String DirEntry::GetName( FSysPathStyle eStyle ) const 1275 { 1276 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 1277 1278 ByteString aRet; 1279 eStyle = GetStyle( eStyle ); 1280 1281 switch( eFlag ) 1282 { 1283 case FSYS_FLAG_PARENT: 1284 aRet = ACTPARENT(eStyle); 1285 break; 1286 1287 case FSYS_FLAG_ABSROOT: 1288 { 1289 if ( eStyle == FSYS_STYLE_URL ) 1290 { 1291 aRet = "file:///"; 1292 aRet += aName; 1293 1294 #ifndef UNX 1295 if ( aName.Len()) 1296 { 1297 if ( aName.GetChar(aName.Len()-1) == ':' ) 1298 { 1299 aRet.SetChar(aRet.Len()-1, '|'); 1300 } 1301 else 1302 { 1303 aRet.Insert( '/', 5 ); 1304 } 1305 aRet += "/"; 1306 } 1307 #endif 1308 } 1309 else if ( eStyle != FSYS_STYLE_MAC && 1310 aName.Len() > 1 && aName.GetChar( 1 ) != ':' ) 1311 { 1312 // UNC-Pathname 1313 aRet = ACCESSDELIM_C(eStyle); 1314 aRet += ACCESSDELIM_C(eStyle); 1315 aRet += aName ; 1316 aRet += ACCESSDELIM_C(eStyle); 1317 } 1318 else 1319 { 1320 aRet = aName; 1321 aRet += ACCESSDELIM_C(eStyle); 1322 } 1323 break; 1324 } 1325 1326 case FSYS_FLAG_INVALID: 1327 case FSYS_FLAG_VOLUME: 1328 { 1329 if ( eStyle == FSYS_STYLE_URL ) 1330 { 1331 aRet = "file:///"; 1332 aRet += aName; 1333 #ifndef UNX 1334 if ( aName.Len() && aName.GetChar(aName.Len()-1) == ':' ) 1335 { 1336 aRet.SetChar(aRet.Len()-1, '|'); 1337 } 1338 #endif 1339 } 1340 else 1341 { 1342 aRet = aName; 1343 } 1344 1345 break; 1346 } 1347 1348 case FSYS_FLAG_RELROOT: 1349 if ( !aName.Len() ) 1350 { 1351 aRet = ACTCURRENT(eStyle); 1352 break; 1353 } 1354 1355 default: 1356 aRet = aName; 1357 } 1358 1359 return String(aRet, osl_getThreadTextEncoding()); 1360 } 1361 1362 /************************************************************************* 1363 |* 1364 |* DirEntry::IsAbs() 1365 |* 1366 |* Beschreibung FSYS.SDW 1367 |* Ersterstellung MI 26.04.91 1368 |* Letzte Aenderung MA 02.12.91 1369 |* 1370 *************************************************************************/ 1371 1372 bool DirEntry::IsAbs() const 1373 { 1374 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 1375 1376 #ifdef UNX 1377 return ( pParent ? pParent->IsAbs() : eFlag == FSYS_FLAG_ABSROOT ); 1378 #else 1379 return ( pParent ? pParent->IsAbs() : eFlag == FSYS_FLAG_ABSROOT && aName.Len() > 0 ); 1380 #endif 1381 } 1382 1383 /************************************************************************* 1384 |* 1385 |* DirEntry::CutName() 1386 |* 1387 |* Beschreibung FSYS.SDW 1388 |* Ersterstellung MI 26.04.91 1389 |* Letzte Aenderung MA 02.12.91 1390 |* 1391 *************************************************************************/ 1392 1393 String DirEntry::CutName( FSysPathStyle eStyle ) 1394 { 1395 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 1396 1397 eStyle = GetStyle( eStyle ); 1398 1399 String aOldName( GetName( eStyle ) ); 1400 1401 if ( pParent ) 1402 { 1403 DirEntry *pOldParent = pParent; 1404 if ( pOldParent ) 1405 { 1406 pParent = pOldParent->pParent; 1407 eFlag = pOldParent->eFlag; 1408 aName = pOldParent->aName; 1409 pOldParent->pParent = NULL; 1410 delete pOldParent; 1411 } 1412 else 1413 { 1414 eFlag = FSYS_FLAG_CURRENT; 1415 aName.Erase(); 1416 } 1417 } 1418 else 1419 { 1420 eFlag = FSYS_FLAG_CURRENT; 1421 aName.Erase(); 1422 delete pParent; 1423 pParent = NULL; 1424 } 1425 1426 return aOldName; 1427 } 1428 1429 /************************************************************************* 1430 |* 1431 |* DirEntry::NameCompare 1432 |* 1433 |* Beschreibung Vergleich nur die Namen (ohne Pfad, aber mit Gross/Klein) 1434 |* Ersterstellung MI 26.04.91 1435 |* Letzte Aenderung MA 02.12.91 1436 |* 1437 *************************************************************************/ 1438 1439 StringCompare DirEntry::NameCompare( const DirEntry &rWith ) const 1440 { 1441 ByteString aThisName; 1442 ByteString aParameterName; 1443 1444 #ifdef UNX 1445 aThisName = aName; 1446 aParameterName = rWith.aName; 1447 #else 1448 aThisName = ByteString(aName).ToLowerAscii(); 1449 aParameterName = ByteString(rWith.aName).ToLowerAscii(); 1450 #endif 1451 1452 return aThisName.CompareTo( aParameterName ); 1453 } 1454 1455 1456 /************************************************************************* 1457 |* 1458 |* DirEntry::operator==() 1459 |* 1460 |* Beschreibung FSYS.SDW 1461 |* Ersterstellung MI 26.04.91 1462 |* Letzte Aenderung MA 02.12.91 1463 |* 1464 *************************************************************************/ 1465 1466 sal_Bool DirEntry::operator==( const DirEntry& rEntry ) const 1467 { 1468 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 1469 1470 // test wheather the contents are textual the same 1471 1472 if ( nError && ( nError == rEntry.nError ) ) 1473 return sal_True; 1474 if ( nError || rEntry.nError || 1475 ( eFlag == FSYS_FLAG_INVALID ) || 1476 ( rEntry.eFlag == FSYS_FLAG_INVALID ) ) 1477 return sal_False; 1478 1479 #ifndef OS2 1480 const 1481 #endif 1482 DirEntry *pThis = (DirEntry *)this; 1483 #ifndef OS2 1484 const 1485 #endif 1486 DirEntry *pWith = (DirEntry *)&rEntry; 1487 while( pThis && pWith && (pThis->eFlag == pWith->eFlag) ) 1488 { 1489 if ( CMP_LOWER(pThis->aName) != CMP_LOWER(pWith->aName) ) 1490 break; 1491 pThis = pThis->pParent; 1492 pWith = pWith->pParent; 1493 } 1494 1495 return ( !pThis && !pWith ); 1496 } 1497 1498 /************************************************************************* 1499 |* 1500 |* DirEntry::operator=() 1501 |* 1502 |* Beschreibung FSYS.SDW 1503 |* Ersterstellung MI 26.04.91 1504 |* Letzte Aenderung MA 02.12.91 1505 |* 1506 *************************************************************************/ 1507 1508 DirEntry& DirEntry::operator=( const DirEntry& rEntry ) 1509 { 1510 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 1511 1512 if ( this == &rEntry ) 1513 return *this; 1514 if ( rEntry.nError != FSYS_ERR_OK ) { 1515 DBG_ERROR("Zuweisung mit invalidem DirEntry"); 1516 nError = rEntry.nError; 1517 return *this; 1518 } 1519 1520 // Name und Typ uebernehmen, Refs beibehalten 1521 aName = rEntry.aName; 1522 eFlag = rEntry.eFlag; 1523 nError = FSYS_ERR_OK; 1524 1525 DirEntry *pOldParent = pParent; 1526 if ( rEntry.pParent ) 1527 pParent = new DirEntry( *rEntry.pParent ); 1528 else 1529 pParent = NULL; 1530 1531 if ( pOldParent ) 1532 delete pOldParent; 1533 return *this; 1534 } 1535 1536 /************************************************************************* 1537 |* 1538 |* DirEntry::operator+() 1539 |* 1540 |* Beschreibung FSYS.SDW 1541 |* Ersterstellung MI 26.04.91 1542 |* Letzte Aenderung MA 02.12.91 1543 |* 1544 *************************************************************************/ 1545 1546 DirEntry DirEntry::operator+( const DirEntry& rEntry ) const 1547 { 1548 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 1549 #ifdef DBG_UTIL 1550 static sal_Bool bTested = sal_False; 1551 if ( !bTested ) 1552 { 1553 bTested = sal_True; 1554 FSysTest(); 1555 } 1556 #endif 1557 1558 const DirEntry *pEntryTop = rEntry.ImpGetTopPtr(); 1559 const DirEntry *pThisTop = ImpGetTopPtr(); 1560 1561 // "." + irgendwas oder irgendwas + "d:irgendwas" 1562 /* TPF:org 1563 if ( ( eFlag == FSYS_FLAG_RELROOT && !aName ) || 1564 ( pEntryTop->aName.Len() && 1565 ( pEntryTop->eFlag == FSYS_FLAG_ABSROOT || 1566 pEntryTop->eFlag == FSYS_FLAG_RELROOT || 1567 pEntryTop->eFlag == FSYS_FLAG_VOLUME ) ) ) 1568 return rEntry; 1569 */ 1570 1571 if ( 1572 (eFlag == FSYS_FLAG_RELROOT && !aName.Len()) || 1573 ( 1574 (pEntryTop->aName.Len() || 1575 ((rEntry.Level()>1)?(rEntry[rEntry.Level()-2].aName.CompareIgnoreCaseToAscii(RFS_IDENTIFIER)==COMPARE_EQUAL):sal_False)) 1576 && 1577 (pEntryTop->eFlag == FSYS_FLAG_ABSROOT || 1578 pEntryTop->eFlag == FSYS_FLAG_RELROOT || 1579 pEntryTop->eFlag == FSYS_FLAG_VOLUME) 1580 ) 1581 ) 1582 { 1583 return rEntry; 1584 } 1585 1586 // irgendwas + "." (=> pEntryTop == &rEntry) 1587 if ( pEntryTop->eFlag == FSYS_FLAG_RELROOT && !pEntryTop->aName.Len() ) 1588 { 1589 DBG_ASSERT( pEntryTop == &rEntry, "DirEntry::op+ buggy" ); 1590 return *this; 1591 } 1592 1593 // root += ".." (=> unmoeglich) 1594 if ( pEntryTop->eFlag == FSYS_FLAG_PARENT && pThisTop == this && 1595 ( eFlag == FSYS_FLAG_ABSROOT ) ) 1596 return DirEntry( FSYS_FLAG_INVALID ); 1597 1598 // irgendwas += abs (=> nur Device uebernehmen falls vorhanden) 1599 if ( pEntryTop->eFlag == FSYS_FLAG_ABSROOT ) 1600 { 1601 ByteString aDevice; 1602 if ( pThisTop->eFlag == FSYS_FLAG_ABSROOT ) 1603 aDevice = pThisTop->aName; 1604 DirEntry aRet = rEntry; 1605 if ( aDevice.Len() ) 1606 aRet.ImpGetTopPtr()->aName = aDevice; 1607 return aRet; 1608 } 1609 1610 // irgendwas += ".." (=> aufloesen) 1611 if ( eFlag == FSYS_FLAG_NORMAL && pEntryTop->eFlag == FSYS_FLAG_PARENT ) 1612 { 1613 String aConcated( GetFull() ); 1614 aConcated += ACCESSDELIM_C(FSYS_STYLE_HOST); 1615 aConcated += rEntry.GetFull(); 1616 return DirEntry( aConcated ); 1617 } 1618 1619 // sonst einfach hintereinander haengen 1620 DirEntry aRet( rEntry ); 1621 DirEntry *pTop = aRet.ImpGetTopPtr(); 1622 pTop->pParent = new DirEntry( *this ); 1623 1624 return aRet; 1625 } 1626 1627 /************************************************************************* 1628 |* 1629 |* DirEntry::operator+=() 1630 |* 1631 |* Beschreibung FSYS.SDW 1632 |* Ersterstellung MI 26.04.91 1633 |* Letzte Aenderung MA 02.12.91 1634 |* 1635 *************************************************************************/ 1636 1637 DirEntry &DirEntry::operator+=( const DirEntry& rEntry ) 1638 { 1639 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 1640 1641 return *this = *this + rEntry; 1642 } 1643 1644 /************************************************************************* 1645 |* 1646 |* DirEntry::GetAccessDelimiter() 1647 |* 1648 |* Beschreibung FSYS.SDW 1649 |* Ersterstellung MI 27.05.93 1650 |* Letzte Aenderung MI 10.06.93 1651 |* 1652 *************************************************************************/ 1653 1654 String DirEntry::GetAccessDelimiter( FSysPathStyle eFormatter ) 1655 { 1656 return String( ACCESSDELIM_C( GetStyle( eFormatter ) ) ); 1657 } 1658 1659 /************************************************************************* 1660 |* 1661 |* DirEntry::SetExtension() 1662 |* 1663 |* Beschreibung FSYS.SDW 1664 |* Ersterstellung MI 02.08.91 1665 |* Letzte Aenderung MA 02.12.91 1666 |* 1667 *************************************************************************/ 1668 1669 void DirEntry::SetExtension( const String& rExtension, char cSep ) 1670 { 1671 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 1672 1673 // do not set extensions for drives 1674 if(eFlag == FSYS_FLAG_ABSROOT) 1675 { 1676 nError = FSYS_ERR_NOTSUPPORTED; 1677 return; 1678 } 1679 1680 // cSep im Namen suchen 1681 const char *p0 = ( aName.GetBuffer() ); 1682 const char *p1 = p0 + aName.Len() - 1; 1683 while ( p1 >= p0 && *p1 != cSep ) 1684 p1--; 1685 if ( p1 >= p0 ) 1686 { 1687 // es wurde ein cSep an der Position p1 gefunden 1688 aName.Erase( 1689 static_cast< xub_StrLen >( 1690 p1 - p0 + 1 - ( rExtension.Len() ? 0 : 1 )) ); 1691 aName += ByteString(rExtension, osl_getThreadTextEncoding()); 1692 } 1693 else if ( rExtension.Len() ) 1694 { 1695 // es wurde kein cSep gefunden 1696 aName += cSep; 1697 aName += ByteString(rExtension, osl_getThreadTextEncoding()); 1698 } 1699 } 1700 1701 /************************************************************************* 1702 |* 1703 |* DirEntry::CutExtension() 1704 |* 1705 |* Beschreibung FSYS.SDW 1706 |* Ersterstellung MI 23.07.93 1707 |* Letzte Aenderung MI 23.07.93 1708 |* 1709 *************************************************************************/ 1710 1711 String DirEntry::CutExtension( char cSep ) 1712 { 1713 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 1714 1715 const char *p0 = ( aName.GetBuffer() ); 1716 const char *p1 = p0 + aName.Len() - 1; 1717 while ( p1 >= p0 && *p1 != cSep ) 1718 p1--; 1719 1720 if ( p1 >= p0 ) 1721 { 1722 // es wurde ein cSep an der Position p1 gefunden 1723 aName.Erase( static_cast< xub_StrLen >(p1-p0) ); 1724 return String(p1 + 1, osl_getThreadTextEncoding()); 1725 } 1726 1727 return String(); 1728 } 1729 1730 /************************************************************************* 1731 |* 1732 |* DirEntry::SetName() 1733 |* 1734 |* Beschreibung FSYS.SDW 1735 |* Ersterstellung MI 04.09.93 1736 |* Letzte Aenderung MI 04.09.93 1737 |* 1738 *************************************************************************/ 1739 1740 void DirEntry::SetName( const String& rName, FSysPathStyle eFormatter ) 1741 { 1742 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 1743 1744 if ( eFormatter == FSYS_STYLE_HOST || eFormatter == FSYS_STYLE_DETECT ) 1745 eFormatter = DEFSTYLE; 1746 ByteString aAccDelim( ACCESSDELIM_C( eFormatter ) ); 1747 1748 if ( (eFlag != FSYS_FLAG_NORMAL) || 1749 (aName.Search( ':' ) != STRING_NOTFOUND) || 1750 (aName.Search( aAccDelim ) != STRING_NOTFOUND) || 1751 (eFormatter == FSYS_STYLE_FAT && (aName.GetTokenCount( '.' ) > 2) ) ) 1752 { 1753 eFlag = FSYS_FLAG_INVALID; 1754 } 1755 else 1756 { 1757 aName = ByteString(rName, osl_getThreadTextEncoding()); 1758 } 1759 } 1760 1761 /************************************************************************* 1762 |* 1763 |* DirEntry::Find() 1764 |* 1765 |* Beschreibung FSYS.SDW 1766 |* Ersterstellung MI 26.04.91 1767 |* Letzte Aenderung MA 02.12.91 1768 |* 1769 *************************************************************************/ 1770 sal_Bool DirEntry::Find( const String& rPfad, char cDelim ) 1771 { 1772 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 1773 1774 if ( ImpGetTopPtr()->eFlag == FSYS_FLAG_ABSROOT ) 1775 return sal_True; 1776 1777 sal_Bool bWild = aName.Search( '*' ) != STRING_NOTFOUND || 1778 aName.Search( '?' ) != STRING_NOTFOUND; 1779 if ( !cDelim ) 1780 cDelim = SEARCHDELIM(DEFSTYLE)[0]; 1781 1782 sal_uInt16 nTokenCount = rPfad.GetTokenCount( cDelim ); 1783 sal_uInt16 nIndex = 0; 1784 ByteString aThis = ACCESSDELIM(DEFSTYLE); 1785 aThis += ByteString(GetFull(), osl_getThreadTextEncoding()); 1786 for ( sal_uInt16 nToken = 0; nToken < nTokenCount; ++nToken ) 1787 { 1788 ByteString aPath = ByteString(rPfad, osl_getThreadTextEncoding()).GetToken( 0, cDelim, nIndex ); 1789 1790 if ( aPath.Len() ) 1791 { 1792 if (aPath.GetChar(aPath.Len()-1)== ACCESSDELIM(DEFSTYLE)[0]) 1793 aPath.Erase(aPath.Len()-1); 1794 aPath += aThis; 1795 DirEntry aEntry( String(aPath, osl_getThreadTextEncoding())); 1796 if ( aEntry.ToAbs() && 1797 ( ( !bWild && aEntry.Exists() ) || ( bWild && aEntry.First() ) ) ) 1798 { 1799 (*this) = aEntry; 1800 return sal_True; 1801 } 1802 } 1803 } 1804 return sal_False; 1805 } 1806 1807 /************************************************************************* 1808 |* 1809 |* DirEntry::ImpToRel() 1810 |* 1811 |* Beschreibung 1812 |* Ersterstellung MI 17.06.93 1813 |* Letzte Aenderung MI 17.06.93 1814 |* 1815 *************************************************************************/ 1816 1817 sal_Bool DirEntry::ImpToRel( String aCurStr ) 1818 { 1819 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 1820 1821 DirEntry aThis(*this); 1822 aThis.ToAbs(); 1823 String aThisStr( aThis.GetFull( FSYS_STYLE_HPFS ) ); 1824 1825 // #109512 preserve case of path even if caseinsensitive 1826 String aThisCompareStr( aThisStr ), aCurCompareStr( aCurStr ); 1827 if ( ! IsCaseSensitive() ) 1828 { 1829 aThisCompareStr.ToLowerAscii(); 1830 aCurCompareStr.ToLowerAscii(); 1831 } 1832 1833 // "Ubereinstimmung pr"ufen 1834 sal_uInt16 nPos = aThisCompareStr.Match( aCurCompareStr ); 1835 if ( nPos == STRING_MATCH && aThisStr.Len() != aCurStr.Len() ) 1836 nPos = Min( aThisStr.Len(), aCurStr.Len() ); 1837 1838 // Sonderfall, die DirEntries sind identisch 1839 if ( nPos == STRING_MATCH ) 1840 { 1841 // dann ist der relative Pfad das aktuelle Verzeichnis 1842 *this = DirEntry(); 1843 return sal_True; 1844 } 1845 1846 // Sonderfall, die DirEntries sind total verschieden 1847 if ( nPos == 0 ) 1848 { 1849 // dann ist der relativste Pfad absolut 1850 *this = aThis; 1851 return sal_False; 1852 } 1853 1854 // sonst nehmen wir die identischen Einzelteile vorne weg 1855 while ( nPos > 0 && aThisStr.GetChar(nPos) != '\\' ) 1856 --nPos; 1857 aThisStr.Erase( 0, nPos + ( ( aThisStr.GetChar(nPos) == '\\' ) ? 1 : 0 ) ); 1858 aCurStr.Erase( 0, nPos + ( ( aCurStr.GetChar(nPos) == '\\' ) ? 1 : 0 ) ); 1859 1860 // und fuellen mit dem Level der Directories auf 1861 for ( nPos = 0; nPos < aCurStr.Len(); ++nPos ) 1862 if ( aCurStr.GetChar(nPos) == '\\' ) 1863 aThisStr.Insert( String( "..\\", osl_getThreadTextEncoding() ), 0 ); 1864 1865 // das ist dann unser relativer Pfad 1866 *this = DirEntry( aThisStr, FSYS_STYLE_HPFS ); 1867 return sal_True; 1868 } 1869 1870 /************************************************************************* 1871 |* 1872 |* DirEntry::CutRelParents() 1873 |* 1874 |* Beschreibung 1875 |* Ersterstellung MI 01.08.95 1876 |* Letzte Aenderung MI 01.08.95 1877 |* 1878 *************************************************************************/ 1879 1880 sal_uInt16 DirEntry::CutRelParents() 1881 { 1882 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 1883 1884 // erstes '..' finden 1885 DirEntry *pDir = 0; 1886 DirEntry *pPar; 1887 1888 for ( pPar = this; 1889 pPar && pPar->eFlag != FSYS_FLAG_PARENT; 1890 pPar = pPar->pParent ) 1891 pDir = pPar; 1892 1893 // '..' zaehlen 1894 sal_uInt16 nParCount = 0; 1895 while ( pPar && pPar->eFlag == FSYS_FLAG_PARENT ) 1896 { 1897 ++nParCount; 1898 pPar = pPar->pParent; 1899 } 1900 1901 // cutten 1902 if ( pDir ) 1903 DELETEZ(pDir->pParent); 1904 else 1905 eFlag = FSYS_FLAG_CURRENT; 1906 1907 return nParCount; 1908 } 1909 1910 /************************************************************************* 1911 |* 1912 |* DirEntry::ToRel() 1913 |* 1914 |* Beschreibung FSYS.SDW 1915 |* Ersterstellung MI 26.06.93 1916 |* Letzte Aenderung MI 17.06.93 1917 |* 1918 *************************************************************************/ 1919 1920 sal_Bool DirEntry::ToRel() 1921 { 1922 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 1923 1924 DirEntry aCur; 1925 aCur.ToAbs(); 1926 return ImpToRel( aCur.GetFull( FSYS_STYLE_HPFS ) ); 1927 } 1928 1929 /************************************************************************* 1930 |* 1931 |* DirEntry::ToRel() 1932 |* 1933 |* Beschreibung FSYS.SDW 1934 |* Ersterstellung MI 26.04.91 1935 |* Letzte Aenderung MA 02.12.91 1936 |* 1937 *************************************************************************/ 1938 1939 sal_Bool DirEntry::ToRel( const DirEntry& rStart ) 1940 { 1941 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 1942 1943 DirEntry aStart( rStart ); 1944 aStart.ToAbs(); 1945 return ImpToRel( aStart.GetFull( FSYS_STYLE_HPFS ) ); 1946 } 1947 1948 /************************************************************************* 1949 |* 1950 |* DirEntry::GetDevice() 1951 |* 1952 |* Beschreibung FSYS.SDW 1953 |* Ersterstellung MI 26.04.91 1954 |* Letzte Aenderung MA 02.12.91 1955 |* 1956 *************************************************************************/ 1957 1958 #ifndef UNX 1959 1960 DirEntry DirEntry::GetDevice() const 1961 { 1962 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 1963 1964 const DirEntry *pTop = ImpGetTopPtr(); 1965 1966 if ( ( pTop->eFlag == FSYS_FLAG_ABSROOT || pTop->eFlag == FSYS_FLAG_RELROOT ) && 1967 pTop->aName.Len() ) 1968 return DirEntry( pTop->aName, FSYS_FLAG_VOLUME, FSYS_STYLE_HOST ); 1969 else 1970 return DirEntry( ByteString(), FSYS_FLAG_INVALID, FSYS_STYLE_HOST ); 1971 } 1972 1973 #endif 1974 1975 /************************************************************************* 1976 |* 1977 |* DirEntry::SetBase() 1978 |* 1979 |* Beschreibung FSYS.SDW 1980 |* Ersterstellung MI 23.10.91 1981 |* Letzte Aenderung MA 02.12.91 1982 |* 1983 *************************************************************************/ 1984 1985 void DirEntry::SetBase( const String& rBase, char cSep ) 1986 { 1987 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 1988 1989 const char *p0 = ( aName.GetBuffer() ); 1990 const char *p1 = p0 + aName.Len() - 1; 1991 while ( p1 >= p0 && *p1 != cSep ) 1992 p1--; 1993 1994 if ( p1 >= p0 ) 1995 { 1996 // es wurde ein cSep an der Position p1 gefunden 1997 aName.Erase( 0, static_cast< xub_StrLen >(p1 - p0) ); 1998 aName.Insert( ByteString(rBase, osl_getThreadTextEncoding()), 0 ); 1999 } 2000 else 2001 aName = ByteString(rBase, osl_getThreadTextEncoding()); 2002 } 2003 2004 /************************************************************************* 2005 |* 2006 |* DirEntry::GetSearchDelimiter() 2007 |* 2008 |* Beschreibung FSYS.SDW 2009 |* Ersterstellung MI 10.06.93 2010 |* Letzte Aenderung MI 10.06.93 2011 |* 2012 *************************************************************************/ 2013 2014 String DirEntry::GetSearchDelimiter( FSysPathStyle eFormatter ) 2015 { 2016 return String( ByteString(SEARCHDELIM( GetStyle( eFormatter ) ) ), osl_getThreadTextEncoding()); 2017 } 2018 2019 /************************************************************************* 2020 |* 2021 |* DirEntry::GetMaxNameLen() 2022 |* 2023 |* Beschreibung Liefert die maximale Anzahl von Zeichen in 2024 |* einzelnen Namensteile. Bei FileSystmen mit 2025 |* fester Extension (FAT) zaehlt diese nicht mit. 2026 |* Bei unbekannten FileSytemen und FSYS_STYLE_URL 2027 |* wird USHRT_MAX zurueckgegeben. 2028 |* Ersterstellung MI 17.06.97 2029 |* Letzte Aenderung MI 17.06.97 2030 |* 2031 *************************************************************************/ 2032 2033 sal_uInt16 DirEntry::GetMaxNameLen( FSysPathStyle eFormatter ) 2034 { 2035 eFormatter = GetStyle( eFormatter ); 2036 switch ( eFormatter ) 2037 { 2038 case FSYS_STYLE_MAC: return 31; 2039 2040 case FSYS_STYLE_FAT: return 8; 2041 2042 case FSYS_STYLE_VFAT: 2043 case FSYS_STYLE_NTFS: 2044 case FSYS_STYLE_NWFS: 2045 case FSYS_STYLE_HPFS: return 255; 2046 2047 2048 case FSYS_STYLE_SYSV: return 14; 2049 2050 case FSYS_STYLE_BSD: return 250; 2051 2052 default: 2053 return USHRT_MAX; 2054 } 2055 } 2056 2057 /************************************************************************* 2058 |* 2059 |* DirEntry::TempName() 2060 |* 2061 |* Beschreibung FSYS.SDW - Aha, wo? 2062 |* Ersterstellung VB 06.09.93 (im SWG) 2063 |* Letzte Aenderung MI 06.02.98 2064 |* 2065 *************************************************************************/ 2066 namespace { struct TempNameBase_Impl : public rtl::Static< DirEntry, TempNameBase_Impl > {}; } 2067 2068 const DirEntry& DirEntry::SetTempNameBase( const String &rBase ) 2069 { 2070 DirEntry aTempDir = DirEntry().TempName().GetPath(); 2071 aTempDir += DirEntry( rBase ); 2072 #ifdef UNX 2073 ByteString aName( aTempDir.GetFull(), osl_getThreadTextEncoding()); 2074 if ( access( aName.GetBuffer(), W_OK | X_OK | R_OK ) ) 2075 { 2076 // Create the directory and only on success give all rights to 2077 // everyone. Use mkdir instead of DirEntry::MakeDir because 2078 // this returns sal_True even if directory already exists. 2079 2080 if ( !mkdir( aName.GetBuffer(), S_IRWXU | S_IRWXG | S_IRWXO ) ) 2081 chmod( aName.GetBuffer(), S_IRWXU | S_IRWXG | S_IRWXO ); 2082 2083 // This will not create a directory but perhaps FileStat called 2084 // there modifies the DirEntry 2085 2086 aTempDir.MakeDir(); 2087 } 2088 #else 2089 aTempDir.MakeDir(); 2090 #endif 2091 DirEntry &rEntry = TempNameBase_Impl::get(); 2092 rEntry = aTempDir.TempName( FSYS_KIND_DIR ); 2093 return rEntry; 2094 } 2095 2096 DirEntry DirEntry::TempName( DirEntryKind eKind ) const 2097 { 2098 // ggf. Base-Temp-Dir verwenden (macht Remote keinen Sinn => vorher) 2099 const DirEntry &rEntry = TempNameBase_Impl::get(); 2100 if ( !pParent && FSYS_FLAG_CURRENT != rEntry.eFlag && FSYS_FLAG_ABSROOT != eFlag ) 2101 2102 { 2103 DirEntry aFactory( rEntry ); 2104 aFactory += GetName(); 2105 return aFactory.TempName(); 2106 } 2107 2108 ByteString aDirName; // hiermit hatte MPW C++ Probleme - immmer noch?? 2109 char *ret_val; 2110 size_t i; 2111 2112 // dertermine Directory, Prefix and Extension 2113 char pfx[6]; 2114 char ext[5]; 2115 const char *dir; 2116 const char *pWild = strchr( aName.GetBuffer(), '*' ); 2117 if ( !pWild ) 2118 pWild = strchr( aName.GetBuffer(), '?' ); 2119 2120 if ( pWild ) 2121 { 2122 if ( pParent ) 2123 aDirName = ByteString(pParent->GetFull(), osl_getThreadTextEncoding()); 2124 strncpy( pfx, aName.GetBuffer(), Min( (int)5, (int)(pWild-aName.GetBuffer()) ) ); 2125 pfx[ pWild-aName.GetBuffer() ] = 0; 2126 const char *pExt = strchr( pWild, '.' ); 2127 if ( pExt ) 2128 { 2129 strncpy( ext, pExt, 4 ); 2130 ext[4] = 0; 2131 } 2132 else 2133 strcpy( ext, ".tmp" ); 2134 } 2135 else 2136 { 2137 aDirName = ByteString(GetFull(), osl_getThreadTextEncoding()); 2138 strcpy( pfx, "sv" ); 2139 strcpy( ext, ".tmp" ); 2140 } 2141 dir = aDirName.GetBuffer(); 2142 2143 // wurde kein Dir angegeben, dann nehmen wir ein passendes TEMP-Verz. 2144 char sBuf[_MAX_PATH]; 2145 if ( eFlag == FSYS_FLAG_CURRENT || ( !pParent && pWild ) ) 2146 dir = TempDirImpl(sBuf); 2147 2148 // ab hier leicht modifizierter Code von VB 2149 DirEntry aRet(FSYS_FLAG_INVALID); 2150 i = strlen(dir); 2151 // need to add ?\\? + prefix + number + pid + .ext + '\0' 2152 # define TMPNAME_SIZE ( 1 + 5 + 5 + 10 + 4 + 1 ) 2153 ret_val = new char[i + TMPNAME_SIZE ]; 2154 if (ret_val) 2155 { 2156 strcpy(ret_val,dir); 2157 2158 /* Make sure directory ends with a separator */ 2159 #if defined(WNT) || defined(OS2) 2160 if ( i>0 && ret_val[i-1] != '\\' && ret_val[i-1] != '/' && 2161 ret_val[i-1] != ':') 2162 ret_val[i++] = '\\'; 2163 #elif defined UNX 2164 if (i>0 && ret_val[i-1] != '/') 2165 ret_val[i++] = '/'; 2166 #else 2167 #error unknown operating system 2168 #endif 2169 2170 strncpy(ret_val + i, pfx, 5); 2171 ret_val[i + 5] = '\0'; /* strncpy doesn't put a 0 if more */ 2172 i = strlen(ret_val); /* than 'n' chars. */ 2173 2174 /* Prefix can have 5 chars, leaving 3 for numbers. 26 ** 3 == 17576 2175 * Welcome to the 21st century, we can have longer filenames now ;) 2176 * New format: pfx + "5 char milli/micro second res" + "current pid" + ".tmp" 2177 */ 2178 #if (defined MSC || defined __MINGW32__) && defined WNT 2179 /* Milliseconds !! */ 2180 static unsigned long u = GetTickCount(); 2181 unsigned long mypid = static_cast<unsigned long>(_getpid()); 2182 #else 2183 /* Microseconds !! */ 2184 static unsigned long u = clock(); 2185 unsigned long mypid = static_cast<unsigned long>(getpid()); 2186 #endif 2187 for ( unsigned long nOld = u; ++u != nOld; ) /* Hae??? */ 2188 { 2189 u %= 100000; /* on *NIX repeats every 100ms, maybe less if CLOCKS_PER_SEC > 10^6 */ 2190 snprintf(ret_val+i, TMPNAME_SIZE, "%05lu%lu", u, mypid); 2191 2192 strcat(ret_val,ext); 2193 2194 if ( FSYS_KIND_FILE == eKind ) 2195 { 2196 SvFileStream aStream( String( ret_val, osl_getThreadTextEncoding()), 2197 STREAM_WRITE|STREAM_SHARE_DENYALL ); 2198 if ( aStream.IsOpen() ) 2199 { 2200 aStream.Seek( STREAM_SEEK_TO_END ); 2201 if ( 0 == aStream.Tell() ) 2202 { 2203 aRet = DirEntry( String( ret_val, osl_getThreadTextEncoding())); 2204 break; 2205 } 2206 aStream.Close(); 2207 } 2208 } 2209 else 2210 { 2211 // Redirect 2212 String aRetVal(ret_val, osl_getThreadTextEncoding()); 2213 String aRedirected (aRetVal); 2214 #ifndef BOOTSTRAP 2215 FSysRedirector::DoRedirect( aRedirected ); 2216 #endif 2217 if ( FSYS_KIND_DIR == eKind ) 2218 { 2219 if ( 0 == _mkdir( ByteString(aRedirected.GetBuffer(), osl_getThreadTextEncoding()).GetBuffer() ) ) 2220 { 2221 aRet = DirEntry( aRetVal ); 2222 break; 2223 } 2224 } 2225 else 2226 { 2227 #if defined(UNX) || defined(OS2) 2228 if( access( ByteString(aRedirected, osl_getThreadTextEncoding()).GetBuffer(), F_OK ) ) 2229 { 2230 aRet = DirEntry( aRetVal ); 2231 break; 2232 } 2233 #else 2234 struct stat aStat; 2235 if ( stat( ByteString(aRedirected, osl_getThreadTextEncoding()).GetBuffer(), &aStat ) ) 2236 { 2237 aRet = DirEntry( aRetVal ); 2238 break; 2239 } 2240 #endif 2241 } 2242 } 2243 } 2244 2245 delete[] ret_val; 2246 ret_val = 0; 2247 } 2248 2249 return aRet; 2250 } 2251 2252 /************************************************************************* 2253 |* 2254 |* DirEntry::operator[]() 2255 |* 2256 |* Beschreibung FSYS.SDW 2257 |* Ersterstellung MI 03.03.92 2258 |* Letzte Aenderung MI 03.03.92 2259 |* 2260 *************************************************************************/ 2261 2262 const DirEntry &DirEntry::operator[]( sal_uInt16 nParentLevel ) const 2263 { 2264 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 2265 2266 //TPF: maybe to be implemented (FastFSys) 2267 2268 const DirEntry *pRes = this; 2269 while ( pRes && nParentLevel-- ) 2270 pRes = pRes->pParent; 2271 2272 return *pRes; 2273 } 2274 2275 /************************************************************************* 2276 |* 2277 |* DirEntry::ImpParseUnixName() 2278 |* 2279 |* Beschreibung FSYS.SDW 2280 |* Ersterstellung MI 26.04.91 2281 |* Letzte Aenderung MI 26.05.93 2282 |* 2283 *************************************************************************/ 2284 2285 FSysError DirEntry::ImpParseUnixName( const ByteString& rPfad, FSysPathStyle eStyle ) 2286 { 2287 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 2288 2289 // die einzelnen Namen auf einen Stack packen 2290 DirEntryStack aStack; 2291 ByteString aPfad( rPfad ); 2292 do 2293 { 2294 // den Namen vor dem ersten "/" abspalten, 2295 // falls '/' am Anfang, ist der Name '/', 2296 // der Rest immer ohne die fuehrenden '/'. 2297 // den ersten '/' suchen 2298 sal_uInt16 nPos; 2299 for ( nPos = 0; 2300 nPos < aPfad.Len() && aPfad.GetChar(nPos) != '/'; 2301 nPos++ ) 2302 /* do nothing */; 2303 2304 // ist der Name die Root des aktuellen Drives? 2305 if ( nPos == 0 && aPfad.Len() > 0 && ( aPfad.GetChar(0) == '/' ) ) 2306 { 2307 // Root-Directory des aktuellen Drives 2308 aStack.Push( new DirEntry( FSYS_FLAG_ABSROOT ) ); 2309 } 2310 else 2311 { 2312 // den Namen ohne Trenner abspalten 2313 aName = aPfad.Copy( 0, nPos ); 2314 2315 // stellt der Name die aktuelle Directory dar? 2316 if ( aName == "." ) 2317 /* do nothing */; 2318 2319 #ifdef UNX 2320 // stellt der Name das User-Dir dar? 2321 else if ( aName == "~" ) 2322 { 2323 DirEntry aHome( String( (const char *) getenv( "HOME" ), osl_getThreadTextEncoding()) ); 2324 for ( sal_uInt16 n = aHome.Level(); n; --n ) 2325 aStack.Push( new DirEntry( aHome[ (sal_uInt16) n-1 ] ) ); 2326 } 2327 #endif 2328 2329 // stellt der Name die Parent-Directory dar? 2330 else if ( aName == ".." ) 2331 { 2332 // ist nichts, ein Parent oder eine relative Root 2333 // auf dem Stack? 2334 if ( ( aStack.Count() == 0 ) || 2335 ( aStack.Top()->eFlag == FSYS_FLAG_PARENT ) ) 2336 // fuehrende Parents kommen auf den Stack 2337 aStack.Push( new DirEntry( ByteString(), FSYS_FLAG_PARENT, eStyle ) ); 2338 2339 // ist es eine absolute Root 2340 else if ( aStack.Top()->eFlag == FSYS_FLAG_ABSROOT ) { 2341 // die hat keine Parent-Directory 2342 return FSYS_ERR_NOTEXISTS; 2343 } 2344 else 2345 // sonst hebt der Parent den TOS auf 2346 delete aStack.Pop(); 2347 } 2348 else 2349 { 2350 DirEntry *pNew = NULL; 2351 // normalen Entries kommen auf den Stack 2352 pNew = new DirEntry( aName, FSYS_FLAG_NORMAL, eStyle ); 2353 if ( !pNew->IsValid() ) 2354 { 2355 aName = rPfad; 2356 ErrCode eErr = pNew->GetError(); 2357 delete pNew; 2358 return eErr; 2359 } 2360 aStack.Push( pNew ); 2361 } 2362 } 2363 2364 // den Restpfad bestimmen 2365 aPfad.Erase( 0, nPos + 1 ); 2366 while ( aPfad.Len() && ( aPfad.GetChar(0) == '/' ) ) 2367 aPfad.Erase( 0, 1 ); 2368 } 2369 while ( aPfad.Len() ); 2370 2371 // Haupt-Entry (selbst) zuweisen 2372 if ( aStack.Count() == 0 ) 2373 { 2374 eFlag = FSYS_FLAG_CURRENT; 2375 aName.Erase(); 2376 } 2377 else 2378 { 2379 eFlag = aStack.Top()->eFlag; 2380 aName = aStack.Top()->aName; 2381 delete aStack.Pop(); 2382 } 2383 2384 // die Parent-Entries vom Stack holen 2385 DirEntry** pTemp = &pParent; 2386 while ( aStack.Count() ) 2387 { 2388 *pTemp = aStack.Pop(); 2389 pTemp = &( (*pTemp)->pParent ); 2390 } 2391 2392 return FSYS_ERR_OK; 2393 } 2394 2395 /************************************************************************* 2396 |* 2397 |* DirEntry::MakeShortName() 2398 |* 2399 |* Beschreibung 2400 |* Ersterstellung TLX 2401 |* Letzte Aenderung PB 21.08.97 (in CreateEntry_Impl()) 2402 |* 2403 *************************************************************************/ 2404 2405 ErrCode CreateEntry_Impl( const DirEntry &rPath, DirEntryKind eKind ) 2406 { 2407 // versuchen, anzulegen (ausser bei FSYS_KIND_ALL) 2408 ErrCode eErr = ERRCODE_NONE; 2409 if ( FSYS_KIND_FILE == eKind ) 2410 { 2411 SvFileStream aStream( rPath.GetFull(), STREAM_STD_WRITE ); 2412 aStream.WriteLine( "" ); 2413 eErr = aStream.GetError(); 2414 } 2415 else if ( FSYS_KIND_ALL != eKind ) 2416 eErr = rPath.MakeDir() ? ERRCODE_NONE : ERRCODE_IO_UNKNOWN; 2417 2418 // erfolgreich? 2419 if ( !rPath.Exists() ) 2420 eErr = ERRCODE_IO_UNKNOWN; // Doch was schiefgegangen ? 2421 2422 // ggf. wieder l"oschen 2423 if ( FSYS_KIND_NONE == eKind ) 2424 rPath.Kill(); 2425 2426 // Fehlercode zur?ckliefern 2427 return eErr; 2428 } 2429 2430 sal_Bool IsValidEntry_Impl( const DirEntry &rPath, 2431 const String &rLongName, 2432 DirEntryKind eKind, 2433 sal_Bool bIsShortened, 2434 sal_Bool bUseDelim ) 2435 { 2436 // Parameter-Pr"uefung 2437 DBG_ASSERT( eKind == FSYS_KIND_NONE || eKind == FSYS_KIND_ALL || 2438 eKind == FSYS_KIND_FILE || eKind == FSYS_KIND_DIR, 2439 "invalid entry-kind" ); 2440 2441 // Alle von MSDOS erreichbaren FSYS_STYLES muessen den 2442 // MSDOS Filenamenanforderungen genuegen. Sonst wird probiert, 2443 // ob sich eine Datei des gewuenschten Names anlegen laesst. 2444 FSysPathStyle eStyle = DirEntry::GetPathStyle( rPath.GetDevice().GetName() ); 2445 DirEntry aPath(rPath); 2446 DirEntry aName(rLongName, eStyle); 2447 if ( !aName.IsValid() || aName.Level() != 1 ) 2448 return sal_False; 2449 aPath += aName; 2450 if ( 1 == aPath.Level() ) 2451 return sal_False; 2452 if ( eStyle == FSYS_STYLE_FAT || eStyle == FSYS_STYLE_NWFS || 2453 eStyle == FSYS_STYLE_UNKNOWN ) 2454 { 2455 DirEntry aDosEntry( rLongName, FSYS_STYLE_FAT ); 2456 if ( !aDosEntry.IsValid() ) 2457 return sal_False; 2458 } 2459 2460 // Pfad-Trenner sind nicht erlaubt (bei ungek"urzten auch nicht FSYS_SHORTNAME_DELIMITER) 2461 char cDelim = bUseDelim == 2 ? FSYS_SHORTNAME_DELIMITER : char(0); 2462 if ( 2463 rLongName.Search(DirEntry::GetAccessDelimiter()) != STRING_NOTFOUND || 2464 (!bIsShortened && rLongName.Search(cDelim) != STRING_NOTFOUND) 2465 ) 2466 { 2467 return sal_False; 2468 } 2469 2470 // MI: Abfrage nach 'CON:' etc. wird jetzt in Exists() mitgemacht 2471 if ( aPath.Exists() ) 2472 return sal_False; 2473 2474 return (ERRCODE_NONE == CreateEntry_Impl( aPath, eKind )); 2475 } 2476 2477 //------------------------------------------------------------------------- 2478 2479 #define MAX_EXT_FAT 3 2480 #define MAX_LEN_FAT 8 2481 #define INVALID_CHARS_FAT "\\/\"':|^<>[]?* " 2482 2483 #define MAX_EXT_MAC 16 // nur wegen sinnvoller Namensk"rzung 2484 #define MAX_LEN_MAC 31 2485 #define INVALID_CHARS_MAC "\":" 2486 2487 #define MAX_EXT_MAX 250 2488 #define MAX_LEN_MAX 255 2489 #define INVALID_CHARS_DEF "\\/\"':|^<>?*" 2490 2491 sal_Bool DirEntry::MakeShortName( const String& rLongName, DirEntryKind eKind, 2492 sal_Bool bUseDelim, FSysPathStyle eStyle ) 2493 { 2494 String aLongName(rLongName); 2495 2496 // Alle '#' aus den Dateinamen entfernen, weil das INetURLObject 2497 // damit Probleme hat. Siehe auch #51246# 2498 aLongName.EraseAllChars( '#' ); 2499 ByteString bLongName(aLongName, osl_getThreadTextEncoding()); 2500 2501 // Auf Novell-Servern (wegen der rottigen Clients) nur 7bit ASCII 2502 2503 // HRO: #69627# Weg mit dem Scheiss. Wenn es Client gibt, die so einen 2504 // BUG haben, dann muss halt der Client ersetzt werden, aber doch nicht das 2505 // Office kastrieren !!! 2506 2507 #if 0 2508 if ( FSYS_STYLE_NWFS == GetPathStyle( ImpGetTopPtr()->GetName() ) ) 2509 { 2510 for ( sal_uInt16 n = aLongName.Len(); n; --n ) 2511 { 2512 short nChar = aLongName(n-1); 2513 if ( nChar < 32 || nChar >= 127 ) 2514 aLongName.Erase( n-1, 1 ); 2515 } 2516 } 2517 #endif 2518 2519 // bei FSYS_KIND_ALL den alten Namen merken und abh"angen (rename) 2520 ByteString aOldName; 2521 if ( FSYS_KIND_ALL == eKind ) 2522 { 2523 aOldName = ByteString(CutName(), osl_getThreadTextEncoding()); 2524 aOldName = CMP_LOWER(aOldName); 2525 } 2526 2527 // ist der Langname direkt verwendbar? 2528 if ( IsValidEntry_Impl( *this, aLongName, eKind, sal_False, bUseDelim ) ) 2529 { 2530 operator+=( DirEntry(aLongName) ); 2531 return sal_True; 2532 } 2533 2534 // max L"angen feststellen 2535 sal_uInt16 nMaxExt, nMaxLen; 2536 if ( FSYS_STYLE_DETECT == eStyle ) 2537 eStyle = DirEntry::GetPathStyle( GetDevice().GetName() ); 2538 ByteString aInvalidChars; 2539 switch ( eStyle ) 2540 { 2541 case FSYS_STYLE_FAT: 2542 nMaxExt = MAX_EXT_FAT; 2543 nMaxLen = MAX_LEN_FAT; 2544 aInvalidChars = INVALID_CHARS_FAT; 2545 break; 2546 2547 case FSYS_STYLE_MAC: 2548 nMaxExt = MAX_EXT_MAC; 2549 nMaxLen = MAX_LEN_MAC; 2550 aInvalidChars = INVALID_CHARS_MAC; 2551 break; 2552 2553 default: 2554 nMaxExt = MAX_EXT_MAX; 2555 nMaxLen = MAX_LEN_MAX; 2556 aInvalidChars = INVALID_CHARS_DEF; 2557 } 2558 2559 // Extension abschneiden und kuerzen 2560 ByteString aExt; 2561 ByteString aFName = bLongName; 2562 if ( FSYS_STYLE_MAC != eStyle ) 2563 { 2564 DirEntry aUnparsed; 2565 aUnparsed.aName = bLongName; 2566 aExt = ByteString(aUnparsed.CutExtension(), osl_getThreadTextEncoding()); 2567 aFName = aUnparsed.aName; 2568 if ( aExt.Len() > nMaxExt ) 2569 { 2570 char c = aExt.GetChar( aExt.Len() - 1 ); 2571 aExt.Erase(nMaxExt-1); 2572 aExt += c; 2573 } 2574 } 2575 2576 if ( FSYS_STYLE_FAT != eStyle ) 2577 { 2578 // ausser auf einem FAT-System geh"ort die Extension zur 2579 // Maxl"ange. Muss also vorher mit dem Punkt abgezogen werden. 2580 nMaxLen -= ( aExt.Len() + 1 ); 2581 } 2582 2583 // Name k"urzen 2584 ByteString aSName; 2585 for ( const char *pc = aFName.GetBuffer(); aSName.Len() < nMaxLen && *pc; ++pc ) 2586 { 2587 if ( STRING_NOTFOUND == aInvalidChars.Search( *pc ) && 2588 (unsigned char) *pc >= (unsigned char) 32 && 2589 ( !aSName.Len() || *pc != ' ' || aSName.GetChar(aSName.Len()-1) != ' ' ) ) 2590 aSName += *pc; 2591 } 2592 aSName.EraseTrailingChars(); 2593 2594 // HRO: #74246# Also cut leading spaces 2595 aSName.EraseLeadingChars(); 2596 2597 if ( !aSName.Len() ) 2598 aSName = "noname"; 2599 2600 // kommt dabei der alte Name raus? 2601 ByteString aNewName = aSName; 2602 if ( aExt.Len() ) 2603 ( aNewName += '.' ) += aExt; 2604 operator+=( DirEntry(String(aNewName, osl_getThreadTextEncoding())) ); 2605 if ( FSYS_KIND_ALL == eKind && CMP_LOWER(aName) == aOldName ) 2606 if ( FSYS_KIND_ALL == eKind && CMP_LOWER(ByteString(GetName(), osl_getThreadTextEncoding())) == aOldName ) 2607 return sal_True; 2608 2609 // kann der gek"urzte Name direkt verwendet werden? 2610 if ( !Exists() && (ERRCODE_NONE == CreateEntry_Impl( *this, eKind )) ) 2611 return sal_True; 2612 2613 // darf '?##' verwendet werden, um eindeutigen Name zu erzeugen? 2614 if ( bUseDelim ) 2615 { 2616 // eindeutigen Namen per '?##' erzeugen 2617 aSName.Erase( nMaxLen-3 ); 2618 if ( bUseDelim != 2 ) 2619 aSName += FSYS_SHORTNAME_DELIMITER; 2620 for ( int n = 1; n < 99; ++n ) 2621 { 2622 // Name zusammensetzen 2623 ByteString aTmpStr( aSName ); 2624 aTmpStr += ByteString::CreateFromInt32(n); 2625 if ( aExt.Len() ) 2626 ( aTmpStr += '.' ) += aExt; 2627 2628 // noch nicht vorhanden? 2629 SetName( String(aTmpStr, osl_getThreadTextEncoding()) ); 2630 2631 if ( !Exists() ) 2632 { 2633 // Fehler setzen !!! 2634 nError = CreateEntry_Impl( *this, eKind ); 2635 return (ERRCODE_NONE == nError); 2636 } 2637 } 2638 } 2639 2640 // keine ## mehr frei / ?## soll nicht verwendet werden 2641 nError = ERRCODE_IO_ALREADYEXISTS; 2642 return sal_False; 2643 } 2644 2645 /************************************************************************* 2646 |* 2647 |* DirEntry::CreatePath() 2648 |* 2649 |* Beschreibung FSYS.SDW 2650 |* Ersterstellung MI 26.04.91 2651 |* Letzte Aenderung MA 02.12.91 2652 |* 2653 *************************************************************************/ 2654 2655 sal_Bool DirEntry::MakeDir( sal_Bool bSloppy ) const 2656 { 2657 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 2658 2659 // Schnellpruefung, ob vorhanden 2660 if ( FileStat( *this ).IsKind( FSYS_KIND_DIR ) ) 2661 return sal_True; 2662 if ( bSloppy && pParent ) 2663 if ( FileStat( *pParent ).IsKind( FSYS_KIND_DIR ) ) 2664 return sal_True; 2665 2666 const DirEntry *pNewDir = bSloppy ? pParent : this; 2667 if ( pNewDir ) 2668 { 2669 // den Path zum Dir erzeugen 2670 if ( pNewDir->pParent && !pNewDir->pParent->MakeDir(sal_False) ) 2671 return sal_False; 2672 2673 // das Dir selbst erzeugen 2674 if ( pNewDir->eFlag == FSYS_FLAG_ABSROOT || 2675 pNewDir->eFlag == FSYS_FLAG_ABSROOT || 2676 pNewDir->eFlag == FSYS_FLAG_VOLUME ) 2677 return sal_True; 2678 else 2679 { 2680 //? nError = ??? 2681 if ( FileStat( *pNewDir ).IsKind( FSYS_KIND_DIR ) ) 2682 return sal_True; 2683 else 2684 { 2685 FSysFailOnErrorImpl(); 2686 String aDirName(pNewDir->GetFull()); 2687 #ifndef BOOTSTRAP 2688 FSysRedirector::DoRedirect( aDirName ); 2689 #endif 2690 ByteString bDirName( aDirName, osl_getThreadTextEncoding() ); 2691 bDirName = GUI2FSYS( bDirName ); 2692 2693 #ifdef WIN32 2694 SetLastError(0); 2695 #endif 2696 sal_Bool bResult = (0 == _mkdir( (char*) bDirName.GetBuffer() )); 2697 if ( !bResult ) 2698 { 2699 // Wer hat diese Methode const gemacht ? 2700 #ifdef WIN32 2701 ((DirEntry *)this)->SetError( Sys2SolarError_Impl( GetLastError() ) ); 2702 #else 2703 ((DirEntry *)this)->SetError( Sys2SolarError_Impl( errno ) ); 2704 #endif 2705 } 2706 2707 return bResult; 2708 } 2709 } 2710 } 2711 return sal_True; 2712 } 2713 2714 /************************************************************************* 2715 |* 2716 |* DirEntry::CopyTo() 2717 |* 2718 |* Beschreibung FSYS.SDW 2719 |* Ersterstellung MI 26.04.91 2720 |* Letzte Aenderung MI 07.08.96 2721 |* 2722 *************************************************************************/ 2723 2724 FSysError DirEntry::CopyTo( const DirEntry& rDest, FSysAction nActions ) const 2725 { 2726 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 2727 2728 if ( FSYS_ACTION_COPYFILE != (nActions & FSYS_ACTION_COPYFILE) ) 2729 #ifdef UNX 2730 { 2731 // Hardlink anlegen 2732 HACK(redirection missing) 2733 ByteString aThis(GUI2FSYS(GetFull()), osl_getThreadTextEncoding()); 2734 ByteString aDest(GUI2FSYS(rDest.GetFull()), osl_getThreadTextEncoding()); 2735 if (link( aThis.GetBuffer(), aDest.GetBuffer() ) == -1) 2736 return Sys2SolarError_Impl( errno ); 2737 else 2738 return FSYS_ERR_OK; 2739 } 2740 #else 2741 return FSYS_ERR_NOTSUPPORTED; 2742 #endif 2743 2744 FileCopier fc(*this, rDest); 2745 return fc.Execute(nActions); 2746 } 2747 2748 /************************************************************************* 2749 |* 2750 |* DirEntry::MoveTo() 2751 |* 2752 |* Beschreibung FSYS.SDW 2753 |* Ersterstellung MI 26.04.91 2754 |* Letzte Aenderung HRO 24.03.99 2755 |* 2756 *************************************************************************/ 2757 2758 #if defined WNT || defined UNX || defined OS2 2759 2760 FSysError DirEntry::MoveTo( const DirEntry& rNewName ) const 2761 { 2762 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 2763 2764 /* 2765 FileStat aSourceStat(*this); 2766 if ( !aSourceStat.IsKind(FSYS_KIND_FILE) ) 2767 return FSYS_ERR_NOTAFILE; 2768 */ 2769 2770 DirEntry aDest(rNewName); 2771 FileStat aDestStat(rNewName); 2772 if ( aDestStat.IsKind(FSYS_KIND_DIR ) ) 2773 { 2774 aDest += String(aName, osl_getThreadTextEncoding()); 2775 } 2776 if ( aDest.Exists() ) 2777 { 2778 return FSYS_ERR_ALREADYEXISTS; 2779 } 2780 2781 #if defined(OS2) 2782 if ( FileStat(*this).IsKind(FSYS_KIND_DIR) && aDest.GetPath() != GetPath() ) 2783 { 2784 return FSYS_ERR_NOTSUPPORTED; 2785 } 2786 #endif 2787 2788 FSysFailOnErrorImpl(); 2789 String aFrom( GetFull() ); 2790 2791 #ifndef BOOTSTRAP 2792 FSysRedirector::DoRedirect(aFrom); 2793 #endif 2794 2795 String aTo( aDest.GetFull() ); 2796 2797 #ifndef BOOTSTRAP 2798 FSysRedirector::DoRedirect(aTo); 2799 #endif 2800 2801 ByteString bFrom(aFrom, osl_getThreadTextEncoding()); 2802 ByteString bTo(aTo, osl_getThreadTextEncoding()); 2803 bFrom = GUI2FSYS(bFrom); 2804 bTo = GUI2FSYS(bTo); 2805 2806 #ifdef WNT 2807 // MoveTo nun atomar 2808 SetLastError(0); 2809 2810 DirEntry aFromDevice(String(bFrom, osl_getThreadTextEncoding())); 2811 DirEntry aToDevice(String(bTo,osl_getThreadTextEncoding())); 2812 aFromDevice.ToAbs(); 2813 aToDevice.ToAbs(); 2814 aFromDevice=aFromDevice.GetDevice(); 2815 aToDevice=aToDevice.GetDevice(); 2816 2817 //Quelle und Ziel auf gleichem device? 2818 if (aFromDevice==aToDevice) 2819 { 2820 // ja, also intra-device-move mit MoveFile 2821 MoveFile( bFrom.GetBuffer(), bTo.GetBuffer() ); 2822 // MoveFile ist buggy bei cross-device operationen. 2823 // Der R?ckgabewert ist auch dann sal_True, wenn nur ein Teil der Operation geklappt hat. 2824 // Zudem zeigt MoveFile unterschiedliches Verhalten bei unterschiedlichen NT-Versionen. 2825 return Sys2SolarError_Impl( GetLastError() ); 2826 } 2827 else 2828 { 2829 //nein, also inter-device-move mit copy/delete 2830 FSysError nCopyError = CopyTo(rNewName, FSYS_ACTION_COPYFILE); 2831 2832 DirEntry aKill(String(bTo, osl_getThreadTextEncoding())); 2833 FileStat aKillStat(String(bTo, osl_getThreadTextEncoding())); 2834 if ( aKillStat.IsKind(FSYS_KIND_DIR ) ) 2835 { 2836 aKill += String(aName, osl_getThreadTextEncoding()); 2837 } 2838 2839 if (nCopyError==FSYS_ERR_OK) 2840 { 2841 if (Kill()==FSYS_ERR_OK) 2842 { 2843 return FSYS_ERR_OK; 2844 } 2845 else 2846 { 2847 aKill.Kill(); 2848 return FSYS_ERR_ACCESSDENIED; 2849 } 2850 } 2851 else 2852 { 2853 aKill.Kill(); 2854 return nCopyError; 2855 } 2856 } 2857 #else 2858 // #68639# 2859 // on some nfs connections rename with from == to 2860 // leads to destruction of file 2861 if ( ( aFrom != aTo ) && ( 0 != rename( bFrom.GetBuffer(), bTo.GetBuffer() ) ) ) 2862 #if !defined(UNX) && !defined(OS2) 2863 return Sys2SolarError_Impl( GetLastError() ); 2864 #else 2865 { 2866 if( errno == EXDEV ) 2867 // cross device geht latuernich nicht mit rename 2868 { 2869 FILE *fpIN = fopen( bFrom.GetBuffer(), "r" ); 2870 FILE *fpOUT = fopen( bTo.GetBuffer(), "w" ); 2871 if( fpIN && fpOUT ) 2872 { 2873 char pBuf[ 16384 ]; 2874 int nBytes, nWritten, nErr = 0; 2875 errno = 0; 2876 while( ( nBytes = fread( pBuf, 1, sizeof(pBuf), fpIN ) ) && ! nErr ) 2877 { 2878 nWritten = fwrite( pBuf, 1, nBytes, fpOUT ); 2879 // Fehler im fwrite ? 2880 if( nWritten < nBytes ) 2881 { 2882 nErr = errno; 2883 break; 2884 } 2885 } 2886 fclose( fpIN ); 2887 fclose( fpOUT ); 2888 if ( nErr ) 2889 { 2890 unlink( bTo.GetBuffer() ); 2891 return Sys2SolarError_Impl( nErr ); 2892 } 2893 else 2894 { 2895 unlink( bFrom.GetBuffer() ); 2896 } 2897 } 2898 else 2899 { 2900 return Sys2SolarError_Impl( EXDEV ); 2901 } 2902 } 2903 else 2904 { 2905 return Sys2SolarError_Impl( errno ); 2906 } 2907 } 2908 #endif 2909 #endif 2910 return ERRCODE_NONE; 2911 } 2912 2913 #endif 2914 2915 /************************************************************************* 2916 |* 2917 |* DirEntry::Kill() 2918 |* 2919 |* Beschreibung FSYS.SDW 2920 |* Ersterstellung MI 26.04.91 2921 |* Letzte Aenderung MI 07.08.96 2922 |* 2923 *************************************************************************/ 2924 2925 FSysError DirEntry::Kill( FSysAction nActions ) const 2926 { 2927 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 2928 2929 FSysError eError = FSYS_ERR_OK; 2930 FSysFailOnErrorImpl(); 2931 2932 // Name als doppelt 0-terminierter String 2933 String aTmpName( GetFull() ); 2934 #ifndef BOOTSTRAP 2935 FSysRedirector::DoRedirect( aTmpName ); 2936 #endif 2937 ByteString bTmpName( aTmpName, osl_getThreadTextEncoding()); 2938 bTmpName = GUI2FSYS(bTmpName); 2939 2940 char *pName = new char[bTmpName.Len()+2]; 2941 strcpy( pName, bTmpName.GetBuffer() ); 2942 pName[bTmpName.Len()+1] = (char) 0; 2943 2944 //read-only files sollen auch geloescht werden koennen 2945 sal_Bool isReadOnly = FileStat::GetReadOnlyFlag(*this); 2946 if (isReadOnly) 2947 { 2948 FileStat::SetReadOnlyFlag(*this, sal_False); 2949 } 2950 2951 // directory? 2952 if ( FileStat( *this ).IsKind(FSYS_KIND_DIR) ) 2953 { 2954 // Inhalte recursiv loeschen? 2955 if ( FSYS_ACTION_RECURSIVE == (nActions & FSYS_ACTION_RECURSIVE) ) 2956 { 2957 Dir aDir( *this, FSYS_KIND_DIR|FSYS_KIND_FILE ); 2958 for ( sal_uInt16 n = 0; eError == FSYS_ERR_OK && n < aDir.Count(); ++n ) 2959 { 2960 const DirEntry &rSubDir = aDir[n]; 2961 DirEntryFlag flag = rSubDir.GetFlag(); 2962 if ( flag != FSYS_FLAG_CURRENT && flag != FSYS_FLAG_PARENT ) 2963 eError = rSubDir.Kill(nActions); 2964 } 2965 } 2966 2967 // das Dir selbst loeschen 2968 #ifdef WIN32 2969 SetLastError(0); 2970 #endif 2971 if ( eError == FSYS_ERR_OK && 0 != _rmdir( (char*) pName ) ) 2972 // 2973 { 2974 // falls L"oschen nicht ging, CWD umsetzen 2975 #ifdef WIN32 2976 eError = Sys2SolarError_Impl( GetLastError() ); 2977 #else 2978 eError = Sys2SolarError_Impl( errno ); 2979 #endif 2980 if ( eError ) 2981 { 2982 GetPath().SetCWD(); 2983 #ifdef WIN32 2984 SetLastError(0); 2985 #endif 2986 if (_rmdir( (char*) pName) != 0) 2987 { 2988 #ifdef WIN32 2989 eError = Sys2SolarError_Impl( GetLastError() ); 2990 #else 2991 eError = Sys2SolarError_Impl( errno ); 2992 #endif 2993 } 2994 else 2995 { 2996 eError = FSYS_ERR_OK; 2997 } 2998 } 2999 } 3000 } 3001 else 3002 { 3003 if ( FSYS_ACTION_USERECYCLEBIN == (nActions & FSYS_ACTION_USERECYCLEBIN) ) 3004 { 3005 #ifdef OS2 3006 eError = ApiRet2ToSolarError_Impl( DosDelete( (PSZ) pName ) ); 3007 #elif defined(WNT) 3008 SHFILEOPSTRUCT aOp; 3009 aOp.hwnd = 0; 3010 aOp.wFunc = FO_DELETE; 3011 aOp.pFrom = pName; 3012 aOp.pTo = 0; 3013 aOp.fFlags = FOF_ALLOWUNDO|FOF_SILENT|FOF_NOCONFIRMATION; 3014 aOp.hNameMappings = 0; 3015 aOp.lpszProgressTitle = 0; 3016 eError = Sys2SolarError_Impl( SHFileOperation( &aOp ) ); 3017 #else 3018 eError = ERRCODE_IO_NOTSUPPORTED; 3019 #endif 3020 } 3021 else 3022 { 3023 #ifdef WIN32 3024 SetLastError(0); 3025 #endif 3026 if ( 0 != _unlink( (char*) pName ) ) 3027 { 3028 #ifdef WIN32 3029 eError = Sys2SolarError_Impl( GetLastError() ); 3030 #else 3031 eError = Sys2SolarError_Impl( errno ); 3032 #endif 3033 } 3034 else 3035 { 3036 eError = ERRCODE_NONE; 3037 } 3038 } 3039 } 3040 3041 //falls Fehler, originales read-only flag wieder herstellen 3042 if ( isReadOnly && (eError!=ERRCODE_NONE) ) 3043 { 3044 FileStat::SetReadOnlyFlag(*this, isReadOnly); 3045 } 3046 3047 delete[] pName; 3048 return eError; 3049 } 3050 3051 /************************************************************************* 3052 |* 3053 |* DirEntry::Contains() 3054 |* 3055 |* Beschreibung ob rSubEntry direkt oder indirect in *this liegt 3056 |* Ersterstellung MI 20.03.97 3057 |* Letzte Aenderung MI 20.03.97 3058 |* 3059 *************************************************************************/ 3060 3061 sal_Bool DirEntry::Contains( const DirEntry &rSubEntry ) const 3062 { 3063 DBG_ASSERT( IsAbs() && rSubEntry.IsAbs(), "must be absolute entries" ); 3064 3065 sal_uInt16 nThisLevel = Level(); 3066 sal_uInt16 nSubLevel = rSubEntry.Level(); 3067 if ( nThisLevel < nSubLevel ) 3068 { 3069 for ( ; nThisLevel; --nThisLevel, --nSubLevel ) 3070 if ( (*this)[nThisLevel-1] != rSubEntry[nSubLevel-1] ) 3071 return sal_False; 3072 return sal_True; 3073 } 3074 return sal_False; 3075 } 3076 3077 /************************************************************************* 3078 |* 3079 |* DirEntry::Level() 3080 |* 3081 |* Beschreibung FSYS.SDW 3082 |* Ersterstellung MI 03.03.92 3083 |* Letzte Aenderung MI 03.03.92 3084 |* 3085 *************************************************************************/ 3086 3087 sal_uInt16 DirEntry::Level() const 3088 { 3089 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 3090 3091 sal_uInt16 nLevel = 0; 3092 const DirEntry *pRes = this; 3093 while ( pRes ) 3094 { 3095 pRes = pRes->pParent; 3096 nLevel++; 3097 } 3098 3099 return nLevel; 3100 } 3101 3102 /************************************************************************* 3103 |* 3104 |* DirEntry::ConvertNameToSystem() 3105 |* 3106 |* Beschreibung 3107 |* Ersterstellung DV 29.03.96 3108 |* Letzte Aenderung DV 29.03.96 3109 |* 3110 *************************************************************************/ 3111 3112 String DirEntry::ConvertNameToSystem( const String &rName ) 3113 { 3114 return rName; 3115 } 3116 3117 /************************************************************************* 3118 |* 3119 |* DirEntry::ConvertSystemToName() 3120 |* 3121 |* Beschreibung 3122 |* Ersterstellung DV 29.03.96 3123 |* Letzte Aenderung DV 29.03.96 3124 |* 3125 *************************************************************************/ 3126 3127 String DirEntry::ConvertSystemToName( const String &rName ) 3128 { 3129 return rName; 3130 } 3131 3132 /************************************************************************* 3133 |* 3134 |* DirEntry::IsValid() 3135 |* 3136 |* Beschreibung 3137 |* Ersterstellung MI 18.09.93 3138 |* Letzte Aenderung TPF 18.09.98 3139 |* 3140 *************************************************************************/ 3141 3142 sal_Bool DirEntry::IsValid() const 3143 { 3144 return (nError == FSYS_ERR_OK); 3145 } 3146 3147 /************************************************************************* 3148 |* 3149 |* DirEntry::IsRFSAvailable() 3150 |* 3151 |* Beschreibung 3152 |* Ersterstellung TPF 21.10.98 3153 |* Letzte Aenderung TPF 21.10.98 3154 |* 3155 *************************************************************************/ 3156 3157 sal_Bool DirEntry::IsRFSAvailable() 3158 { 3159 return sal_False; 3160 } 3161 3162 /************************************************************************* 3163 |* 3164 |* IsLongNameOnFAT() 3165 |* 3166 |* Beschreibung ?berpr?ft , ob das DirEntry einen langen 3167 |* Filenamen auf einer FAT-Partition enth?lt (EAs). 3168 |* (eigentlich nur f?r OS2 interessant) 3169 |* Ersterstellung TPF 02.10.98 3170 |* Letzte Aenderung TPF 01.03.1999 3171 |* 3172 *************************************************************************/ 3173 3174 sal_Bool DirEntry::IsLongNameOnFAT() const 3175 { 3176 // FAT-System? 3177 DirEntry aTempDirEntry(*this); 3178 aTempDirEntry.ToAbs(); 3179 if (DirEntry::GetPathStyle(aTempDirEntry.GetDevice().GetName().GetChar(0)) != FSYS_STYLE_FAT) 3180 { 3181 return sal_False; // nein, also false 3182 } 3183 3184 // DirEntry-Kette auf lange Dateinamen pr?fen 3185 for( sal_uInt16 iLevel = this->Level(); iLevel > 0; iLevel-- ) 3186 { 3187 const DirEntry& rEntry = (const DirEntry&) (*this)[iLevel-1]; 3188 String aBase( rEntry.GetBase() ); 3189 String aExtension( rEntry.GetExtension() ); 3190 3191 if (aBase.Len()>8) // Name > 8? 3192 { 3193 return sal_True; 3194 } 3195 3196 if (aExtension.Len()>3) // Extension > 3? 3197 { 3198 return sal_True; 3199 } 3200 } 3201 return sal_False; 3202 } 3203 3204 //======================================================================== 3205 3206 #if defined(DBG_UTIL) 3207 3208 void FSysTest() 3209 { 3210 } 3211 3212 #endif 3213 3214