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