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