Update ooo320-m1
[ooovba.git] / tools / source / fsys / dirent.cxx
blob5fdbcfa22267ba8472fc9216806ee69efe16d322
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dirent.cxx,v $
10 * $Revision: 1.27 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_tools.hxx"
35 #if !defined UNX
36 #include <io.h>
37 #include <process.h>
38 #endif
40 #if defined(UNX) || defined(OS2)
41 #include <unistd.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #endif
46 #include <ctype.h>
47 #include <errno.h>
48 #include <stdlib.h>
49 #include <stdio.h>
50 #include <string.h>
51 #include <tools/debug.hxx>
52 #include <tools/list.hxx>
53 #include "comdep.hxx"
54 #include <tools/fsys.hxx>
55 #define _TOOLS_HXX
56 #include <tools/urlobj.hxx>
58 #ifdef UNX
59 #define _MAX_PATH 260
60 #endif
61 #include <tools/stream.hxx>
63 #ifndef _VOS_MUTEX_HXX
64 #include <vos/mutex.hxx>
65 #endif
67 #include <osl/file.hxx>
68 #include <rtl/instance.hxx>
71 using namespace osl;
72 using namespace rtl;
74 int ApiRet2ToSolarError_Impl( int nApiRet );
76 //--------------------------------------------------------------------
77 int Sys2SolarError_Impl( int nSysErr )
79 switch ( nSysErr )
81 #ifdef WNT
82 case NO_ERROR: return ERRCODE_NONE;
83 case ERROR_INVALID_FUNCTION: return ERRCODE_IO_GENERAL;
84 case ERROR_FILE_NOT_FOUND: return ERRCODE_IO_NOTEXISTS;
85 case ERROR_PATH_NOT_FOUND: return ERRCODE_IO_NOTEXISTSPATH;
86 case ERROR_TOO_MANY_OPEN_FILES: return ERRCODE_IO_TOOMANYOPENFILES;
87 case ERROR_ACCESS_DENIED: return ERRCODE_IO_ACCESSDENIED;
88 case ERROR_INVALID_HANDLE: return ERRCODE_IO_GENERAL;
89 case ERROR_NOT_ENOUGH_MEMORY: return ERRCODE_IO_OUTOFMEMORY;
90 case ERROR_INVALID_BLOCK: return ERRCODE_IO_GENERAL;
91 // case ERROR_BAD_ENVIRONMENT: return ERRCODE_IO_;
92 case ERROR_BAD_FORMAT: return ERRCODE_IO_WRONGFORMAT;
93 case ERROR_INVALID_ACCESS: return ERRCODE_IO_ACCESSDENIED;
94 // case ERROR_INVALID_DATA: return ERRCODE_IO_;
95 case ERROR_INVALID_DRIVE: return ERRCODE_IO_INVALIDDEVICE;
96 case ERROR_CURRENT_DIRECTORY: return ERRCODE_IO_CURRENTDIR;
97 case ERROR_NOT_SAME_DEVICE: return ERRCODE_IO_NOTSAMEDEVICE;
98 // case ERROR_NO_MORE_FILES: return ERRCODE_IO_;
99 case ERROR_WRITE_PROTECT: return ERRCODE_IO_CANTWRITE;
100 case ERROR_BAD_UNIT: return ERRCODE_IO_INVALIDDEVICE;
101 case ERROR_NOT_READY: return ERRCODE_IO_DEVICENOTREADY;
102 case ERROR_BAD_COMMAND: return ERRCODE_IO_GENERAL;
103 case ERROR_CRC: return ERRCODE_IO_BADCRC;
104 case ERROR_BAD_LENGTH: return ERRCODE_IO_INVALIDLENGTH;
105 case ERROR_SEEK: return ERRCODE_IO_CANTSEEK;
106 case ERROR_NOT_DOS_DISK: return ERRCODE_IO_WRONGFORMAT;
107 case ERROR_SECTOR_NOT_FOUND: return ERRCODE_IO_GENERAL;
108 case ERROR_WRITE_FAULT: return ERRCODE_IO_CANTWRITE;
109 case ERROR_READ_FAULT: return ERRCODE_IO_CANTREAD;
110 case ERROR_GEN_FAILURE: return ERRCODE_IO_GENERAL;
111 case ERROR_SHARING_VIOLATION: return ERRCODE_IO_LOCKVIOLATION;
112 case ERROR_LOCK_VIOLATION: return ERRCODE_IO_LOCKVIOLATION;
113 case ERROR_WRONG_DISK: return ERRCODE_IO_INVALIDDEVICE;
114 case ERROR_NOT_SUPPORTED: return ERRCODE_IO_NOTSUPPORTED;
115 #else
116 case 0: return ERRCODE_NONE;
117 case ENOENT: return ERRCODE_IO_NOTEXISTS;
118 case EACCES: return ERRCODE_IO_ACCESSDENIED;
119 case EEXIST: return ERRCODE_IO_ALREADYEXISTS;
120 case EINVAL: return ERRCODE_IO_INVALIDPARAMETER;
121 case EMFILE: return ERRCODE_IO_TOOMANYOPENFILES;
122 case ENOMEM: return ERRCODE_IO_OUTOFMEMORY;
123 case ENOSPC: return ERRCODE_IO_OUTOFSPACE;
124 #endif
127 DBG_TRACE1( "FSys: unknown system error %d occured", nSysErr );
128 return FSYS_ERR_UNKNOWN;
131 //--------------------------------------------------------------------
133 #ifndef BOOTSTRAP
135 FSysRedirector* FSysRedirector::_pRedirector = 0;
136 BOOL FSysRedirector::_bEnabled = TRUE;
137 #ifdef UNX
138 BOOL bInRedirection = TRUE;
139 #else
140 BOOL bInRedirection = FALSE;
141 #endif
142 static NAMESPACE_VOS( OMutex )* pRedirectMutex = 0;
144 //------------------------------------------------------------------------
145 void FSysRedirector::Register( FSysRedirector *pRedirector )
147 if ( pRedirector )
148 pRedirectMutex = new NAMESPACE_VOS( OMutex );
149 else
150 DELETEZ( pRedirectMutex );
151 _pRedirector = pRedirector;
154 //------------------------------------------------------------------------
156 void FSysRedirector::DoRedirect( String &rPath )
158 String aURL(rPath);
160 // if redirection is disabled or not even registered do nothing
161 if ( !_bEnabled || !pRedirectMutex )
162 return;
164 // redirect only removable or remote volumes
165 if ( !IsRedirectable_Impl( ByteString( aURL, osl_getThreadTextEncoding() ) ) )
166 return;
168 // Redirection is acessible only by one thread per time
169 // dont move the guard behind the bInRedirection check!!!
170 // think of nested calls (when called from callback)
171 NAMESPACE_VOS( OGuard ) aGuard( pRedirectMutex );
173 // if already in redirection, dont redirect
174 if ( bInRedirection )
175 return;
177 // dont redirect on nested calls
178 bInRedirection = TRUE;
180 // convert to URL
181 #ifndef UNX
182 for ( sal_Unicode *p = (sal_Unicode*)aURL.GetBuffer(); *p; ++p )
183 if ( '\\' == *p ) *p = '/';
184 else if ( ':' == *p ) *p = '|';
185 #endif
187 aURL.Insert( String("file:///", osl_getThreadTextEncoding()), 0 );
189 // do redirection
190 Redirector();
192 bInRedirection = FALSE;
193 return;
196 //------------------------------------------------------------------------
198 FSysRedirector* FSysRedirector::Redirector()
200 if ( !_pRedirector )
201 Register( new FSysRedirector );
202 return _pRedirector;
205 #endif // BOOTSTRAP
207 //--------------------------------------------------------------------
209 class DirEntryStack: public List
211 public:
212 DirEntryStack() {};
213 ~DirEntryStack();
215 inline void Push( DirEntry *pEntry );
216 inline DirEntry* Pop();
217 inline DirEntry* Top();
218 inline DirEntry* Bottom();
221 inline void DirEntryStack::Push( DirEntry *pEntry )
223 List::Insert( pEntry, LIST_APPEND );
226 inline DirEntry* DirEntryStack::Pop()
228 return (DirEntry*) List::Remove( Count() - 1 );
231 inline DirEntry* DirEntryStack::Top()
233 return (DirEntry*) List::GetObject( Count() - 1 );
236 inline DirEntry* DirEntryStack::Bottom()
238 return (DirEntry*) List::GetObject( 0 );
241 //--------------------------------------------------------------------
243 DBG_NAME( DirEntry );
245 /*************************************************************************
247 |* DirEntry::~DirEntryStack()
249 |* Beschreibung FSYS.SDW
250 |* Ersterstellung MI 26.04.91
251 |* Letzte Aenderung MI 04.07.91
253 *************************************************************************/
255 DirEntryStack::~DirEntryStack()
257 while ( Count() )
258 delete Pop();
261 /*************************************************************************
263 |* ImpCheckDirEntry()
265 |* Beschreibung Pruefung eines DirEntry fuer DBG_UTIL
266 |* Parameter void* p Zeiger auf den DirEntry
267 |* Return-Wert char* Fehlermeldungs-TExtension oder NULL
268 |* Ersterstellung MI 16.07.91
269 |* Letzte Aenderung MI 26.05.93
271 *************************************************************************/
273 #ifdef DBG_UTIL
274 const char* ImpCheckDirEntry( const void* p )
276 DirEntry* p0 = (DirEntry*)p;
278 if ( p0->pParent )
279 DBG_CHKOBJ( p0->pParent, DirEntry, ImpCheckDirEntry );
281 return NULL;
283 #endif
285 /*************************************************************************
287 |* ImplCutPath()
289 |* Beschreibung Fuegt ... ein, damit maximal nMaxChars lang
290 |* Ersterstellung MI 06.04.94
291 |* Letzte Aenderung DV 24.06.96
293 *************************************************************************/
295 ByteString ImplCutPath( const ByteString& rStr, USHORT nMax, char cAccDel )
297 USHORT nMaxPathLen = nMax;
298 ByteString aCutPath( rStr );
299 BOOL bInsertPrefix = FALSE;
300 USHORT nBegin = aCutPath.Search( cAccDel );
302 if( nBegin == STRING_NOTFOUND )
303 nBegin = 0;
304 else
305 nMaxPathLen += 2; // fuer Prefix <Laufwerk>:
307 while( aCutPath.Len() > nMaxPathLen )
309 USHORT nEnd = aCutPath.Search( cAccDel, nBegin + 1 );
310 USHORT nCount;
312 if ( nEnd != STRING_NOTFOUND )
314 nCount = nEnd - nBegin;
315 aCutPath.Erase( nBegin, nCount );
316 bInsertPrefix = TRUE;
318 else
319 break;
322 if ( aCutPath.Len() > nMaxPathLen )
324 for ( USHORT n = nMaxPathLen; n > nMaxPathLen/2; --n )
325 if ( !ByteString(aCutPath.GetChar(n)).IsAlphaNumericAscii() )
327 aCutPath.Erase( n );
328 aCutPath += "...";
329 break;
333 if ( bInsertPrefix )
335 ByteString aIns( cAccDel );
336 aIns += "...";
337 aCutPath.Insert( aIns, nBegin );
340 return aCutPath;
343 /*************************************************************************
345 |* DirEntry::ImpParseOs2Name()
347 |* Beschreibung FSYS.SDW
348 |* Ersterstellung MI 26.04.91
349 |* Letzte Aenderung MI 23.06.95
351 *************************************************************************/
353 FSysError DirEntry::ImpParseOs2Name( const ByteString& rPfad, FSysPathStyle eStyle )
355 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
357 // die einzelnen Namen auf einen Stack packen
358 String aPfad( rPfad, osl_getThreadTextEncoding() );
359 DirEntryStack aStack;
363 // den Namen vor dem ersten "\\" abspalten,
364 // falls '\\' am Anfang, ist der Name '\\',
365 // der Rest immer ohne die fuehrenden '\\'.
366 // ein ":" trennt ebenfalls, gehoert aber zum Namen
367 // den ersten '\\', '/' oder ':' suchen
368 USHORT nPos;
369 for ( nPos = 0;
370 nPos < aPfad.Len() && //?O
371 aPfad.GetChar(nPos) != '\\' && aPfad.GetChar(nPos) != '/' && //?O
372 aPfad.GetChar(nPos) != ':'; //?O
373 nPos++ )
374 /* do nothing */;
376 // ist der Name ein UNC Pathname?
377 if ( nPos == 0 && aPfad.Len() > 1 &&
378 ( ( aPfad.GetChar(0) == '\\' && aPfad.GetChar(1) == '\\' ) ||
379 ( aPfad.GetChar(0) == '/' && aPfad.GetChar(1) == '/' ) ) )
381 for ( nPos = 2; aPfad.Len() > nPos; ++nPos )
382 if ( aPfad.GetChar(nPos) == '\\' || aPfad.GetChar(nPos) == '/' )
383 break;
384 aName = ByteString( aPfad.Copy( 2, nPos-2 ), osl_getThreadTextEncoding() );
385 aStack.Push( new DirEntry( aName, FSYS_FLAG_ABSROOT, eStyle ) );
387 // ist der Name die Root des aktuellen Drives?
388 else if ( nPos == 0 && aPfad.Len() > 0 &&
389 ( aPfad.GetChar(0) == '\\' || aPfad.GetChar(0) == '/' ) )
391 // Root-Directory des aktuellen Drives
392 aStack.Push( new DirEntry( FSYS_FLAG_ABSROOT ) );
394 else
396 // ist der Name ein Drive?
397 if ( nPos < aPfad.Len() && aPfad.GetChar(nPos) == ':' )
399 aName = ByteString( aPfad.Copy( 0, nPos + 1 ), osl_getThreadTextEncoding() );
401 // ist der Name die Root des Drives
402 if ( (nPos + 1) < aPfad.Len() &&
403 ( aPfad.GetChar(nPos+1) == '\\' || aPfad.GetChar(nPos+1) == '/' ) )
405 // schon was auf dem Stack?
406 // oder Novell-Format? (not supported wegen URLs)
407 if ( aStack.Count() || aName.Len() > 2 )
409 aName = rPfad;
410 return FSYS_ERR_MISPLACEDCHAR;
412 // Root-Directory des Drive
413 aStack.Push( new DirEntry( aName, FSYS_FLAG_ABSROOT, eStyle ) );
415 else
417 // liegt ein anderes Drive auf dem Stack?
418 if ( aStack.Count() &&
419 COMPARE_EQUAL != aStack.Bottom()->aName.CompareIgnoreCaseToAscii(aName) )
420 aStack.Clear();
422 // liegt jetzt nichts mehr auf dem Stack?
423 if ( !aStack.Count() )
424 aStack.Push( new DirEntry( aName, FSYS_FLAG_RELROOT, eStyle ) );
428 // es ist kein Drive
429 else
431 // den Namen ohne Trenner abspalten
432 aName = ByteString( aPfad.Copy( 0, nPos ), osl_getThreadTextEncoding() );
434 // stellt der Name die aktuelle Directory dar?
435 if ( aName == "." )
436 /* do nothing */;
438 // stellt der Name die Parent-Directory dar?
439 else if ( aName == ".." )
441 // ist nichts, ein Parent oder eine relative Root
442 // auf dem Stack?
443 if ( ( aStack.Count() == 0 ) ||
444 ( aStack.Top()->eFlag == FSYS_FLAG_PARENT ) ||
445 ( aStack.Top()->eFlag == FSYS_FLAG_RELROOT ) )
446 // fuehrende Parents kommen auf den Stack
447 aStack.Push( new DirEntry( FSYS_FLAG_PARENT ) );
449 // ist es eine absolute Root
450 else if ( aStack.Top()->eFlag == FSYS_FLAG_ABSROOT )
452 // die hat keine Parent-Directory
453 aName = rPfad;
454 return FSYS_ERR_NOTEXISTS;
456 else
457 // sonst hebt der Parent den TOS auf
458 delete aStack.Pop();
461 else
463 if ( eStyle == FSYS_STYLE_FAT )
465 // ist der Name grundsaetzlich ungueltig?
466 int nPunkte = 0;
467 const char *pChar;
468 for ( pChar = aName.GetBuffer();
469 nPunkte < 2 && *pChar != 0;
470 pChar++ )
472 if ( *pChar == ';' )
473 nPunkte = 0;
474 else
475 nPunkte += ( *pChar == '.' ) ? 1 : 0;
477 if ( nPunkte > 1 )
479 aName = rPfad;
480 return FSYS_ERR_MISPLACEDCHAR;
484 // normalen Entries kommen auf den Stack
485 DirEntry *pNew = new DirEntry( aName, FSYS_FLAG_NORMAL, eStyle );
486 if ( !pNew->IsValid() )
488 aName = rPfad;
489 ErrCode eErr = pNew->GetError();
490 delete pNew;
491 return eErr;
493 aStack.Push( pNew );
498 // den Restpfad bestimmen
499 aPfad.Erase( 0, nPos + 1 );
500 while ( aPfad.Len() && ( aPfad.GetChar(0) == '\\' || aPfad.GetChar(0) == '/' ) )
501 aPfad.Erase( 0, 1 );
503 while ( aPfad.Len() );
505 ULONG nErr = ERRCODE_NONE;
506 // Haupt-Entry (selbst) zuweisen
507 if ( aStack.Count() == 0 )
509 eFlag = FSYS_FLAG_CURRENT;
510 aName.Erase();
512 else
514 eFlag = aStack.Top()->eFlag;
515 aName = aStack.Top()->aName;
516 nErr = aStack.Top()->nError;
517 delete aStack.Pop();
520 // die Parent-Entries vom Stack holen
521 DirEntry** pTemp = &pParent; // Zeiger auf den Member pParent setzen
522 while ( aStack.Count() )
524 *pTemp = aStack.Pop();
526 // Zeiger auf den Member pParent des eigenen Parent setzen
527 pTemp = &( (*pTemp)->pParent );
530 // wird damit ein Volume beschrieben?
531 if ( !pParent && eFlag == FSYS_FLAG_RELROOT && aName.Len() )
532 eFlag = FSYS_FLAG_VOLUME;
534 // bei gesetztem ErrorCode den Namen komplett "ubernehmen
535 if ( nErr )
536 aName = rPfad;
537 return nErr;
540 /*************************************************************************
542 |* DirEntry::ImpParseName()
544 |* Beschreibung FSYS.SDW
545 |* Ersterstellung MI 26.08.91
546 |* Letzte Aenderung MI 26.05.93
548 *************************************************************************/
550 FSysError DirEntry::ImpParseName( const ByteString& rbInitName,
551 FSysPathStyle eStyle )
553 String rInitName( rbInitName, osl_getThreadTextEncoding() );
554 if ( eStyle == FSYS_STYLE_HOST )
555 eStyle = DEFSTYLE;
557 // KI-Division of FSys
558 if ( eStyle == FSYS_STYLE_DETECT )
560 sal_Unicode cFirst = rInitName.GetChar(0);
561 if ( rInitName.Len() == 2 && rInitName.GetChar(1) == ':' &&
562 ((cFirst >= 'A' && cFirst <= 'Z') ||
563 (cFirst >= 'a' && cFirst <= 'z')))
564 eStyle = FSYS_STYLE_HPFS;
565 else if ( rInitName.Len() > 2 && rInitName.GetChar(1) == ':' )
567 if ( rInitName.Search( ':', 2 ) == STRING_NOTFOUND )
568 eStyle = FSYS_STYLE_HPFS;
569 else
570 eStyle = FSYS_STYLE_MAC;
572 else if ( rInitName.Search( '/' ) != STRING_NOTFOUND )
573 eStyle = FSYS_STYLE_BSD;
574 else if ( rInitName.Search( '\\' ) != STRING_NOTFOUND )
575 eStyle = FSYS_STYLE_HPFS;
576 else if ( rInitName.Search( ':' ) != STRING_NOTFOUND )
577 eStyle = FSYS_STYLE_MAC;
578 else
579 eStyle = FSYS_STYLE_HPFS;
582 switch ( eStyle )
584 case FSYS_STYLE_FAT:
585 case FSYS_STYLE_VFAT:
586 case FSYS_STYLE_HPFS:
587 case FSYS_STYLE_NTFS:
588 case FSYS_STYLE_NWFS:
589 return ImpParseOs2Name( rbInitName, eStyle );
591 case FSYS_STYLE_BSD:
592 case FSYS_STYLE_SYSV:
593 return ImpParseUnixName( rbInitName, eStyle );
595 case FSYS_STYLE_MAC:
596 return FSYS_ERR_OK;
598 default:
599 return FSYS_ERR_UNKNOWN;
603 /*************************************************************************
605 |* GetStyle()
607 |* Beschreibung FSYS.SDW
608 |* Ersterstellung MI 15.11.91
609 |* Letzte Aenderung MI 15.11.91
611 *************************************************************************/
613 static FSysPathStyle GetStyle( FSysPathStyle eStyle )
615 if ( eStyle == FSYS_STYLE_HOST || eStyle == FSYS_STYLE_DETECT )
616 return DEFSTYLE;
617 else
618 return eStyle;
621 /*************************************************************************
623 |* DirEntry::ImpTrim()
625 |* Beschreibung bringt den Namen auf Betriebssystem-Norm
626 |* z.B. 8.3 lower beim MS-DOS Formatter
627 |* wirkt nicht rekursiv
628 |* Ersterstellung MI 12.08.91
629 |* Letzte Aenderung MI 21.05.92
631 *************************************************************************/
633 void DirEntry::ImpTrim( FSysPathStyle eStyle )
635 // Wildcards werden nicht geclipt
636 if ( ( aName.Search( '*' ) != STRING_NOTFOUND ) ||
637 ( aName.Search( '?' ) != STRING_NOTFOUND ) ||
638 ( aName.Search( ';' ) != STRING_NOTFOUND ) )
639 return;
641 switch ( eStyle )
643 case FSYS_STYLE_FAT:
645 USHORT nPunktPos = aName.Search( '.' );
646 if ( nPunktPos == STRING_NOTFOUND )
648 if ( aName.Len() > 8 )
650 nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
651 aName.Erase( 8 );
654 else
656 if ( nPunktPos > 8 )
658 nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
659 aName.Erase( 8, nPunktPos - 8 );
660 nPunktPos = 8;
662 if ( aName.Len() > nPunktPos + 3 )
664 if ( aName.Len() - nPunktPos > 4 )
666 nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
667 aName.Erase( nPunktPos + 4 );
671 aName.ToLowerAscii();
672 break;
675 case FSYS_STYLE_VFAT:
676 case FSYS_STYLE_HPFS:
677 case FSYS_STYLE_NTFS:
678 case FSYS_STYLE_NWFS:
679 if ( aName.Len() > 254 )
681 nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
682 aName.Erase( 254 );
685 if ( eStyle == FSYS_STYLE_HPFS &&
686 ( eFlag == FSYS_FLAG_ABSROOT || eFlag == FSYS_FLAG_RELROOT ) )
687 aName.ToUpperAscii();
688 break;
690 case FSYS_STYLE_SYSV:
691 if ( aName.Len() > 14 )
693 nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
694 aName.Erase( 14 );
696 break;
698 case FSYS_STYLE_BSD:
699 if ( aName.Len() > 250 )
701 nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
702 aName.Erase( 250 );
704 break;
706 case FSYS_STYLE_MAC:
707 if ( eFlag & ( FSYS_FLAG_ABSROOT | FSYS_FLAG_VOLUME ) )
709 if ( aName.Len() > 27 )
711 nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
712 aName.Erase( 27 );
715 else
717 if ( aName.Len() > 31 )
719 nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
720 aName.Erase( 31 );
723 break;
725 default:
726 /* kann nicht sein */;
730 /*************************************************************************
732 |* DirEntry::DirEntry()
734 |* Beschreibung FSYS.SDW
735 |* Ersterstellung MI 26.04.91
736 |* Letzte Aenderung MA 02.12.91
738 *************************************************************************/
740 DirEntry::DirEntry( const ByteString& rName, DirEntryFlag eDirFlag,
741 FSysPathStyle eStyle ) :
742 #ifdef FEAT_FSYS_DOUBLESPEED
743 pStat( 0 ),
744 #endif
745 aName( rName )
747 DBG_CTOR( DirEntry, ImpCheckDirEntry );
749 pParent = NULL;
750 eFlag = eDirFlag;
751 nError = FSYS_ERR_OK;
753 ImpTrim( eStyle );
756 /*************************************************************************
758 |* DirEntry::DirEntry()
760 |* Beschreibung FSYS.SDW
761 |* Ersterstellung MI 26.04.91
762 |* Letzte Aenderung MA 02.12.91
764 *************************************************************************/
766 DirEntry::DirEntry( const DirEntry& rOrig ) :
767 #ifdef FEAT_FSYS_DOUBLESPEED
768 pStat( rOrig.pStat ? new FileStat(*rOrig.pStat) : 0 ),
769 #endif
770 aName( rOrig.aName )
772 DBG_CTOR( DirEntry, ImpCheckDirEntry );
774 eFlag = rOrig.eFlag;
775 nError = rOrig.nError;
777 if ( rOrig.pParent )
779 pParent = new DirEntry( *rOrig.pParent );
781 else
783 pParent = NULL;
787 /*************************************************************************
789 |* DirEntry::DirEntry()
791 |* Beschreibung FSYS.SDW
792 |* Ersterstellung MI 26.04.91
793 |* Letzte Aenderung MA 02.12.91
795 *************************************************************************/
797 DirEntry::DirEntry( const String& rInitName, FSysPathStyle eStyle )
798 #ifdef FEAT_FSYS_DOUBLESPEED
799 : pStat( 0 )
800 #endif
802 DBG_CTOR( DirEntry, ImpCheckDirEntry );
804 pParent = NULL;
806 // schnelle Loesung fuer Leerstring
807 if ( !rInitName.Len())
809 eFlag = FSYS_FLAG_CURRENT;
810 nError = FSYS_ERR_OK;
811 return;
814 ByteString aTmpName(rInitName, osl_getThreadTextEncoding());
815 if( eStyle == FSYS_STYLE_URL || aTmpName.CompareIgnoreCaseToAscii("file:",5 ) == COMPARE_EQUAL )
817 #ifndef BOOTSTRAP
818 DBG_WARNING( "File URLs are not permitted but accepted" );
819 aTmpName = ByteString(String(INetURLObject( rInitName ).PathToFileName()), osl_getThreadTextEncoding());
820 eStyle = FSYS_STYLE_HOST;
821 #endif // BOOTSTRAP
823 else
825 ::rtl::OUString aTmp;
826 ::rtl::OUString aOInitName;
827 if ( FileBase::getFileURLFromSystemPath( OUString( rInitName ), aTmp ) == FileBase::E_None )
829 aOInitName = OUString( rInitName );
830 aTmpName = ByteString( String(aOInitName), osl_getThreadTextEncoding() );
833 #ifdef DBG_UTIL
834 // ASF nur bei Default eStyle, nicht z.B. aus MakeShortName()
835 if( eStyle == FSYS_STYLE_HOST &&
836 aTmpName.Search( "://" ) != STRING_NOTFOUND )
838 ByteString aErr = "DirEntries akzeptieren nur File URLS: ";
839 aErr += aTmpName;
840 DBG_WARNING( aErr.GetBuffer() );
842 #endif
845 nError = ImpParseName( aTmpName, eStyle );
847 if ( nError != FSYS_ERR_OK )
848 eFlag = FSYS_FLAG_INVALID;
851 /*************************************************************************/
853 DirEntry::DirEntry( const ByteString& rInitName, FSysPathStyle eStyle )
854 #ifdef FEAT_FSYS_DOUBLESPEED
855 : pStat( 0 )
856 #endif
858 DBG_CTOR( DirEntry, ImpCheckDirEntry );
860 pParent = NULL;
862 // schnelle Loesung fuer Leerstring
863 if ( !rInitName.Len() )
865 eFlag = FSYS_FLAG_CURRENT;
866 nError = FSYS_ERR_OK;
867 return;
870 ByteString aTmpName( rInitName );
871 if( eStyle == FSYS_STYLE_URL || rInitName.CompareIgnoreCaseToAscii("file:",5 ) == COMPARE_EQUAL )
873 #ifndef BOOTSTRAP
874 DBG_WARNING( "File URLs are not permitted but accepted" );
875 aTmpName = ByteString(String(INetURLObject( rInitName ).PathToFileName()), osl_getThreadTextEncoding());
876 eStyle = FSYS_STYLE_HOST;
877 #endif
879 #ifdef DBG_UTIL
880 else
881 // ASF nur bei Default eStyle, nicht z.B. aus MakeShortName()
882 if( eStyle == FSYS_STYLE_HOST &&
883 rInitName.Search( "://" ) != STRING_NOTFOUND )
885 ByteString aErr = "DirEntries akzeptieren nur File URLS: ";
886 aErr += rInitName;
887 DBG_WARNING( aErr.GetBuffer() );
889 #endif
891 nError = ImpParseName( aTmpName, eStyle );
893 if ( nError != FSYS_ERR_OK )
894 eFlag = FSYS_FLAG_INVALID;
897 /*************************************************************************
899 |* DirEntry::DirEntry()
901 |* Beschreibung FSYS.SDW
902 |* Ersterstellung MI 26.04.91
903 |* Letzte Aenderung MA 02.12.91
905 *************************************************************************/
907 DirEntry::DirEntry( DirEntryFlag eDirFlag )
908 #ifdef FEAT_FSYS_DOUBLESPEED
909 : pStat( 0 )
910 #endif
912 DBG_CTOR( DirEntry, ImpCheckDirEntry );
914 eFlag = eDirFlag;
915 nError = ( eFlag == FSYS_FLAG_INVALID ) ? FSYS_ERR_UNKNOWN : FSYS_ERR_OK;
916 pParent = NULL;
919 /*************************************************************************
921 |* DirEntry::~DirEntry()
923 |* Beschreibung FSYS.SDW
924 |* Ersterstellung MI 26.04.91
925 |* Letzte Aenderung MA 02.12.91
927 *************************************************************************/
929 DirEntry::~DirEntry()
931 DBG_DTOR( DirEntry, ImpCheckDirEntry );
933 delete pParent;
934 #ifdef FEAT_FSYS_DOUBLESPEED
935 delete pStat;
936 #endif
940 /*************************************************************************
942 |* DirEntry::ImpGetTopPtr() const
944 |* Beschreibung FSYS.SDW
945 |* Ersterstellung MI 26.04.91
946 |* Letzte Aenderung MA 02.12.91
948 *************************************************************************/
950 const DirEntry* DirEntry::ImpGetTopPtr() const
952 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
954 const DirEntry *pTemp = this;
955 while ( pTemp->pParent )
956 pTemp = pTemp->pParent;
958 return pTemp;
961 /*************************************************************************
963 |* DirEntry::ImpGetTopPtr()
965 |* Beschreibung FSYS.SDW
966 |* Ersterstellung MI 13.11.91
967 |* Letzte Aenderung MA 02.12.91
969 *************************************************************************/
971 DirEntry* DirEntry::ImpGetTopPtr()
973 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
975 DirEntry *pTemp = this;
976 while ( pTemp->pParent )
977 pTemp = pTemp->pParent;
979 return pTemp;
982 /*************************************************************************
984 |* DirEntry::ImpGetPreTopPtr()
986 |* Beschreibung liefert einen Pointer auf den vorletzten Entry
987 |* Ersterstellung MI 01.11.91
988 |* Letzte Aenderung MA 02.12.91
990 *************************************************************************/
992 DirEntry* DirEntry::ImpGetPreTopPtr()
994 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
996 DirEntry *pTemp = this;
997 if ( pTemp->pParent )
999 while ( pTemp->pParent->pParent )
1000 pTemp = pTemp->pParent;
1003 return pTemp;
1006 /*************************************************************************
1008 |* DirEntry::ImpChangeParent()
1010 |* Beschreibung FSYS.SDW
1011 |* Ersterstellung MI 26.04.91
1012 |* Letzte Aenderung MI 21.05.92
1014 *************************************************************************/
1016 DirEntry* DirEntry::ImpChangeParent( DirEntry* pNewParent, BOOL bNormalize )
1018 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
1020 DirEntry *pTemp = pParent;
1021 if ( bNormalize && pNewParent &&
1022 pNewParent->eFlag == FSYS_FLAG_RELROOT && !pNewParent->aName.Len() )
1024 pParent = 0;
1025 delete pNewParent;
1027 else
1028 pParent = pNewParent;
1030 return pTemp;
1033 /*************************************************************************
1035 |* DirEntry::Exists()
1037 |* Beschreibung FSYS.SDW
1038 |* Ersterstellung MI 26.04.91
1039 |* Letzte Aenderung MI 24.09.91
1041 *************************************************************************/
1043 BOOL DirEntry::Exists( FSysAccess nAccess ) const
1045 #ifndef BOOTSTRAP
1046 static NAMESPACE_VOS(OMutex) aLocalMutex;
1047 NAMESPACE_VOS(OGuard) aGuard( aLocalMutex );
1048 #endif
1049 if ( !IsValid() )
1050 return FALSE;
1052 #if defined WNT || defined OS2
1053 // spezielle Filenamen sind vom System da
1054 if ( ( aName.CompareIgnoreCaseToAscii("CLOCK$") == COMPARE_EQUAL ||
1055 aName.CompareIgnoreCaseToAscii("CON") == COMPARE_EQUAL ||
1056 aName.CompareIgnoreCaseToAscii("AUX") == COMPARE_EQUAL ||
1057 aName.CompareIgnoreCaseToAscii("COM1") == COMPARE_EQUAL ||
1058 aName.CompareIgnoreCaseToAscii("COM2") == COMPARE_EQUAL ||
1059 aName.CompareIgnoreCaseToAscii("COM3") == COMPARE_EQUAL ||
1060 aName.CompareIgnoreCaseToAscii("COM4") == COMPARE_EQUAL ||
1061 aName.CompareIgnoreCaseToAscii("LPT1") == COMPARE_EQUAL ||
1062 aName.CompareIgnoreCaseToAscii("LPT2") == COMPARE_EQUAL ||
1063 aName.CompareIgnoreCaseToAscii("LPT3") == COMPARE_EQUAL ||
1064 aName.CompareIgnoreCaseToAscii("NUL") == COMPARE_EQUAL ||
1065 aName.CompareIgnoreCaseToAscii("PRN") == COMPARE_EQUAL ) )
1066 return TRUE;
1067 #endif
1069 FSysFailOnErrorImpl();
1070 DirEntryKind eKind = FileStat( *this, nAccess ).GetKind();
1071 if ( eKind & ( FSYS_KIND_FILE | FSYS_KIND_DIR ) )
1073 return TRUE;
1076 #if defined WNT || defined OS2
1077 if ( 0 != ( eKind & FSYS_KIND_DEV ) )
1079 return DRIVE_EXISTS( ImpGetTopPtr()->aName.GetChar(0) );
1081 #endif
1083 return 0 != ( eKind & ( FSYS_KIND_FILE | FSYS_KIND_DIR ) );
1086 /*************************************************************************
1088 |* DirEntry::First()
1090 |* Beschreibung FSYS.SDW
1091 |* Ersterstellung MI 26.04.91
1092 |* Letzte Aenderung MA 15.01.92
1094 *************************************************************************/
1096 BOOL DirEntry::First()
1098 FSysFailOnErrorImpl();
1100 String aUniPathName( GetPath().GetFull() );
1101 #ifndef BOOTSTRAP
1102 FSysRedirector::DoRedirect( aUniPathName );
1103 ByteString aPathName(aUniPathName, osl_getThreadTextEncoding());
1104 #else
1105 ByteString aPathName(aUniPathName, gsl_getSystemTextEncoding());
1106 #endif
1107 aPathName = GUI2FSYS( aPathName );
1109 DIR *pDir = opendir( (char*) aPathName.GetBuffer() );
1110 if ( pDir )
1112 #ifndef BOOTSTRAP
1113 WildCard aWildeKarte( String(CMP_LOWER( aName ), osl_getThreadTextEncoding()) );
1114 #else
1115 WildCard aWildeKarte( String(CMP_LOWER( aName ), gsl_getSystemTextEncoding()) );
1116 #endif
1117 for ( dirent* pEntry = readdir( pDir );
1118 pEntry;
1119 pEntry = readdir( pDir ) )
1121 ByteString aFound( FSYS2GUI( ByteString( pEntry->d_name ) ) );
1122 if ( aWildeKarte.Matches( String(CMP_LOWER( aFound ), osl_getThreadTextEncoding())))
1124 aName = aFound;
1125 closedir( pDir );
1126 return TRUE;
1129 closedir( pDir );
1131 return FALSE;
1134 /*************************************************************************
1136 |* DirEntry::GetFull()
1138 |* Beschreibung FSYS.SDW
1139 |* Ersterstellung MI 26.04.91
1140 |* Letzte Aenderung MA 02.12.91
1142 *************************************************************************/
1144 String DirEntry::GetFull( FSysPathStyle eStyle, BOOL bWithDelimiter,
1145 USHORT nMaxChars ) const
1147 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
1149 ByteString aRet;
1150 eStyle = GetStyle( eStyle );
1151 if ( pParent )
1153 if ( ( pParent->eFlag == FSYS_FLAG_ABSROOT ||
1154 pParent->eFlag == FSYS_FLAG_RELROOT ||
1155 pParent->eFlag == FSYS_FLAG_VOLUME ) )
1157 aRet = ByteString(pParent->GetName( eStyle ), osl_getThreadTextEncoding());
1158 aRet += ByteString(GetName( eStyle ), osl_getThreadTextEncoding());
1160 else
1162 aRet = ByteString(pParent->GetFull( eStyle ), osl_getThreadTextEncoding());
1163 aRet += ACCESSDELIM_C(eStyle);
1164 aRet += ByteString(GetName( eStyle ), osl_getThreadTextEncoding());
1167 else
1169 aRet = ByteString(GetName( eStyle ), osl_getThreadTextEncoding());
1172 if ( ( eStyle == FSYS_STYLE_MAC ) &&
1173 ( ImpGetTopPtr()->eFlag != FSYS_FLAG_VOLUME ) &&
1174 ( ImpGetTopPtr()->eFlag != FSYS_FLAG_ABSROOT ) &&
1175 ( aRet.GetChar(0) != ':' ) )
1176 aRet.Insert( ACCESSDELIM_C(eStyle), 0 );
1178 //! Hack
1179 if ( bWithDelimiter )
1180 if ( aRet.GetChar( aRet.Len()-1 ) != ACCESSDELIM_C(eStyle) )
1181 aRet += ACCESSDELIM_C(eStyle);
1183 //! noch ein Hack
1184 if ( nMaxChars < STRING_MAXLEN )
1185 aRet = ImplCutPath( aRet, nMaxChars, ACCESSDELIM_C(eStyle) );
1187 return String(aRet, osl_getThreadTextEncoding());
1190 /*************************************************************************
1192 |* DirEntry::GetPath()
1194 |* Beschreibung FSYS.SDW
1195 |* Ersterstellung MI 26.04.91
1196 |* Letzte Aenderung MA 02.12.91
1198 *************************************************************************/
1200 DirEntry DirEntry::GetPath() const
1202 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
1204 if ( pParent )
1205 return DirEntry( *pParent );
1207 return DirEntry();
1210 /*************************************************************************
1212 |* DirEntry::GetExtension()
1214 |* Beschreibung FSYS.SDW
1215 |* Ersterstellung MI 26.04.91
1216 |* Letzte Aenderung MA 02.12.91
1218 *************************************************************************/
1220 String DirEntry::GetExtension( char cSep ) const
1222 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
1224 const char *p0 = ( aName.GetBuffer() );
1225 const char *p1 = p0 + aName.Len() - 1;
1226 while ( p1 >= p0 && *p1 != cSep )
1227 p1--;
1229 if ( p1 >= p0 )
1230 // es wurde ein cSep an der Position p1 gefunden
1231 return String(
1232 aName.Copy( static_cast< xub_StrLen >(p1 - p0 + 1) ),
1233 osl_getThreadTextEncoding());
1234 return String();
1237 /*************************************************************************
1239 |* DirEntry::GetBase()
1241 |* Beschreibung FSYS.SDW
1242 |* Ersterstellung MI 26.04.91
1243 |* Letzte Aenderung MA 02.12.91
1245 *************************************************************************/
1247 String DirEntry::GetBase( char cSep ) const
1249 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
1251 const char *p0 = ( aName.GetBuffer() );
1252 const char *p1 = p0 + aName.Len() - 1;
1253 while ( p1 >= p0 && *p1 != cSep )
1254 p1--;
1256 if ( p1 >= p0 )
1257 // es wurde ein cSep an der Position p1 gefunden
1258 return String(
1259 aName.Copy( 0, static_cast< xub_StrLen >(p1 - p0) ),
1260 osl_getThreadTextEncoding());
1262 else
1263 // es wurde kein cSep gefunden
1264 return String(aName, osl_getThreadTextEncoding());
1267 /*************************************************************************
1269 |* DirEntry::GetName()
1271 |* Beschreibung FSYS.SDW
1272 |* Ersterstellung MI 26.04.91
1273 |* Letzte Aenderung MA 02.12.91 13:47
1275 *************************************************************************/
1277 String DirEntry::GetName( FSysPathStyle eStyle ) const
1279 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
1281 ByteString aRet;
1282 eStyle = GetStyle( eStyle );
1284 switch( eFlag )
1286 case FSYS_FLAG_PARENT:
1287 aRet = ACTPARENT(eStyle);
1288 break;
1290 case FSYS_FLAG_ABSROOT:
1292 if ( eStyle == FSYS_STYLE_URL )
1294 aRet = "file:///";
1295 aRet += aName;
1297 #ifndef UNX
1298 if ( aName.Len())
1300 if ( aName.GetChar(aName.Len()-1) == ':' )
1302 aRet.SetChar(aRet.Len()-1, '|');
1304 else
1306 aRet.Insert( '/', 5 );
1308 aRet += "/";
1310 #endif
1312 else if ( eStyle != FSYS_STYLE_MAC &&
1313 aName.Len() > 1 && aName.GetChar( 1 ) != ':' )
1315 // UNC-Pathname
1316 aRet = ACCESSDELIM_C(eStyle);
1317 aRet += ACCESSDELIM_C(eStyle);
1318 aRet += aName ;
1319 aRet += ACCESSDELIM_C(eStyle);
1321 else
1323 aRet = aName;
1324 aRet += ACCESSDELIM_C(eStyle);
1326 break;
1329 case FSYS_FLAG_INVALID:
1330 case FSYS_FLAG_VOLUME:
1332 if ( eStyle == FSYS_STYLE_URL )
1334 aRet = "file:///";
1335 aRet += aName;
1336 #ifndef UNX
1337 if ( aName.Len() && aName.GetChar(aName.Len()-1) == ':' )
1339 aRet.SetChar(aRet.Len()-1, '|');
1341 #endif
1343 else
1345 aRet = aName;
1348 break;
1351 case FSYS_FLAG_RELROOT:
1352 if ( !aName.Len() )
1354 aRet = ACTCURRENT(eStyle);
1355 break;
1358 default:
1359 aRet = aName;
1362 return String(aRet, osl_getThreadTextEncoding());
1365 /*************************************************************************
1367 |* DirEntry::IsAbs()
1369 |* Beschreibung FSYS.SDW
1370 |* Ersterstellung MI 26.04.91
1371 |* Letzte Aenderung MA 02.12.91
1373 *************************************************************************/
1375 bool DirEntry::IsAbs() const
1377 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
1379 #ifdef UNX
1380 return ( pParent ? pParent->IsAbs() : eFlag == FSYS_FLAG_ABSROOT );
1381 #else
1382 return ( pParent ? pParent->IsAbs() : eFlag == FSYS_FLAG_ABSROOT && aName.Len() > 0 );
1383 #endif
1386 /*************************************************************************
1388 |* DirEntry::CutName()
1390 |* Beschreibung FSYS.SDW
1391 |* Ersterstellung MI 26.04.91
1392 |* Letzte Aenderung MA 02.12.91
1394 *************************************************************************/
1396 String DirEntry::CutName( FSysPathStyle eStyle )
1398 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
1400 eStyle = GetStyle( eStyle );
1402 String aOldName( GetName( eStyle ) );
1404 if ( pParent )
1406 DirEntry *pOldParent = pParent;
1407 if ( pOldParent )
1409 pParent = pOldParent->pParent;
1410 eFlag = pOldParent->eFlag;
1411 aName = pOldParent->aName;
1412 pOldParent->pParent = NULL;
1413 delete pOldParent;
1415 else
1417 eFlag = FSYS_FLAG_CURRENT;
1418 aName.Erase();
1421 else
1423 eFlag = FSYS_FLAG_CURRENT;
1424 aName.Erase();
1425 delete pParent;
1426 pParent = NULL;
1429 return aOldName;
1432 /*************************************************************************
1434 |* DirEntry::NameCompare
1436 |* Beschreibung Vergleich nur die Namen (ohne Pfad, aber mit Gross/Klein)
1437 |* Ersterstellung MI 26.04.91
1438 |* Letzte Aenderung MA 02.12.91
1440 *************************************************************************/
1442 StringCompare DirEntry::NameCompare( const DirEntry &rWith ) const
1444 ByteString aThisName;
1445 ByteString aParameterName;
1447 #ifdef UNX
1448 aThisName = aName;
1449 aParameterName = rWith.aName;
1450 #else
1451 aThisName = ByteString(aName).ToLowerAscii();
1452 aParameterName = ByteString(rWith.aName).ToLowerAscii();
1453 #endif
1455 return aThisName.CompareTo( aParameterName );
1459 /*************************************************************************
1461 |* DirEntry::operator==()
1463 |* Beschreibung FSYS.SDW
1464 |* Ersterstellung MI 26.04.91
1465 |* Letzte Aenderung MA 02.12.91
1467 *************************************************************************/
1469 BOOL DirEntry::operator==( const DirEntry& rEntry ) const
1471 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
1473 // test wheather the contents are textual the same
1475 if ( nError && ( nError == rEntry.nError ) )
1476 return TRUE;
1477 if ( nError || rEntry.nError ||
1478 ( eFlag == FSYS_FLAG_INVALID ) ||
1479 ( rEntry.eFlag == FSYS_FLAG_INVALID ) )
1480 return FALSE;
1482 #ifndef OS2
1483 const
1484 #endif
1485 DirEntry *pThis = (DirEntry *)this;
1486 #ifndef OS2
1487 const
1488 #endif
1489 DirEntry *pWith = (DirEntry *)&rEntry;
1490 while( pThis && pWith && (pThis->eFlag == pWith->eFlag) )
1492 if ( CMP_LOWER(pThis->aName) != CMP_LOWER(pWith->aName) )
1493 break;
1494 pThis = pThis->pParent;
1495 pWith = pWith->pParent;
1498 return ( !pThis && !pWith );
1501 /*************************************************************************
1503 |* DirEntry::operator=()
1505 |* Beschreibung FSYS.SDW
1506 |* Ersterstellung MI 26.04.91
1507 |* Letzte Aenderung MA 02.12.91
1509 *************************************************************************/
1511 DirEntry& DirEntry::operator=( const DirEntry& rEntry )
1513 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
1515 if ( this == &rEntry )
1516 return *this;
1517 if ( rEntry.nError != FSYS_ERR_OK ) {
1518 DBG_ERROR("Zuweisung mit invalidem DirEntry");
1519 nError = rEntry.nError;
1520 return *this;
1523 // Name und Typ uebernehmen, Refs beibehalten
1524 aName = rEntry.aName;
1525 eFlag = rEntry.eFlag;
1526 nError = FSYS_ERR_OK;
1528 DirEntry *pOldParent = pParent;
1529 if ( rEntry.pParent )
1530 pParent = new DirEntry( *rEntry.pParent );
1531 else
1532 pParent = NULL;
1534 if ( pOldParent )
1535 delete pOldParent;
1536 return *this;
1539 /*************************************************************************
1541 |* DirEntry::operator+()
1543 |* Beschreibung FSYS.SDW
1544 |* Ersterstellung MI 26.04.91
1545 |* Letzte Aenderung MA 02.12.91
1547 *************************************************************************/
1549 DirEntry DirEntry::operator+( const DirEntry& rEntry ) const
1551 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
1552 #ifdef DBG_UTIL
1553 static BOOL bTested = FALSE;
1554 if ( !bTested )
1556 bTested = TRUE;
1557 FSysTest();
1559 #endif
1561 const DirEntry *pEntryTop = rEntry.ImpGetTopPtr();
1562 const DirEntry *pThisTop = ImpGetTopPtr();
1564 // "." + irgendwas oder irgendwas + "d:irgendwas"
1565 /* TPF:org
1566 if ( ( eFlag == FSYS_FLAG_RELROOT && !aName ) ||
1567 ( pEntryTop->aName.Len() &&
1568 ( pEntryTop->eFlag == FSYS_FLAG_ABSROOT ||
1569 pEntryTop->eFlag == FSYS_FLAG_RELROOT ||
1570 pEntryTop->eFlag == FSYS_FLAG_VOLUME ) ) )
1571 return rEntry;
1574 if (
1575 (eFlag == FSYS_FLAG_RELROOT && !aName.Len()) ||
1577 (pEntryTop->aName.Len() ||
1578 ((rEntry.Level()>1)?(rEntry[rEntry.Level()-2].aName.CompareIgnoreCaseToAscii(RFS_IDENTIFIER)==COMPARE_EQUAL):FALSE))
1580 (pEntryTop->eFlag == FSYS_FLAG_ABSROOT ||
1581 pEntryTop->eFlag == FSYS_FLAG_RELROOT ||
1582 pEntryTop->eFlag == FSYS_FLAG_VOLUME)
1586 return rEntry;
1589 // irgendwas + "." (=> pEntryTop == &rEntry)
1590 if ( pEntryTop->eFlag == FSYS_FLAG_RELROOT && !pEntryTop->aName.Len() )
1592 DBG_ASSERT( pEntryTop == &rEntry, "DirEntry::op+ buggy" );
1593 return *this;
1596 // root += ".." (=> unmoeglich)
1597 if ( pEntryTop->eFlag == FSYS_FLAG_PARENT && pThisTop == this &&
1598 ( eFlag == FSYS_FLAG_ABSROOT ) )
1599 return DirEntry( FSYS_FLAG_INVALID );
1601 // irgendwas += abs (=> nur Device uebernehmen falls vorhanden)
1602 if ( pEntryTop->eFlag == FSYS_FLAG_ABSROOT )
1604 ByteString aDevice;
1605 if ( pThisTop->eFlag == FSYS_FLAG_ABSROOT )
1606 aDevice = pThisTop->aName;
1607 DirEntry aRet = rEntry;
1608 if ( aDevice.Len() )
1609 aRet.ImpGetTopPtr()->aName = aDevice;
1610 return aRet;
1613 // irgendwas += ".." (=> aufloesen)
1614 if ( eFlag == FSYS_FLAG_NORMAL && pEntryTop->eFlag == FSYS_FLAG_PARENT )
1616 String aConcated( GetFull() );
1617 aConcated += ACCESSDELIM_C(FSYS_STYLE_HOST);
1618 aConcated += rEntry.GetFull();
1619 return DirEntry( aConcated );
1622 // sonst einfach hintereinander haengen
1623 DirEntry aRet( rEntry );
1624 DirEntry *pTop = aRet.ImpGetTopPtr();
1625 pTop->pParent = new DirEntry( *this );
1627 return aRet;
1630 /*************************************************************************
1632 |* DirEntry::operator+=()
1634 |* Beschreibung FSYS.SDW
1635 |* Ersterstellung MI 26.04.91
1636 |* Letzte Aenderung MA 02.12.91
1638 *************************************************************************/
1640 DirEntry &DirEntry::operator+=( const DirEntry& rEntry )
1642 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
1644 return *this = *this + rEntry;
1647 /*************************************************************************
1649 |* DirEntry::GetAccessDelimiter()
1651 |* Beschreibung FSYS.SDW
1652 |* Ersterstellung MI 27.05.93
1653 |* Letzte Aenderung MI 10.06.93
1655 *************************************************************************/
1657 String DirEntry::GetAccessDelimiter( FSysPathStyle eFormatter )
1659 return String( ACCESSDELIM_C( GetStyle( eFormatter ) ) );
1662 /*************************************************************************
1664 |* DirEntry::SetExtension()
1666 |* Beschreibung FSYS.SDW
1667 |* Ersterstellung MI 02.08.91
1668 |* Letzte Aenderung MA 02.12.91
1670 *************************************************************************/
1672 void DirEntry::SetExtension( const String& rExtension, char cSep )
1674 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
1676 // do not set extensions for drives
1677 if(eFlag == FSYS_FLAG_ABSROOT)
1679 nError = FSYS_ERR_NOTSUPPORTED;
1680 return;
1683 // cSep im Namen suchen
1684 const char *p0 = ( aName.GetBuffer() );
1685 const char *p1 = p0 + aName.Len() - 1;
1686 while ( p1 >= p0 && *p1 != cSep )
1687 p1--;
1688 if ( p1 >= p0 )
1690 // es wurde ein cSep an der Position p1 gefunden
1691 aName.Erase(
1692 static_cast< xub_StrLen >(
1693 p1 - p0 + 1 - ( rExtension.Len() ? 0 : 1 )) );
1694 aName += ByteString(rExtension, osl_getThreadTextEncoding());
1696 else if ( rExtension.Len() )
1698 // es wurde kein cSep gefunden
1699 aName += cSep;
1700 aName += ByteString(rExtension, osl_getThreadTextEncoding());
1704 /*************************************************************************
1706 |* DirEntry::CutExtension()
1708 |* Beschreibung FSYS.SDW
1709 |* Ersterstellung MI 23.07.93
1710 |* Letzte Aenderung MI 23.07.93
1712 *************************************************************************/
1714 String DirEntry::CutExtension( char cSep )
1716 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
1718 const char *p0 = ( aName.GetBuffer() );
1719 const char *p1 = p0 + aName.Len() - 1;
1720 while ( p1 >= p0 && *p1 != cSep )
1721 p1--;
1723 if ( p1 >= p0 )
1725 // es wurde ein cSep an der Position p1 gefunden
1726 aName.Erase( static_cast< xub_StrLen >(p1-p0) );
1727 return String(p1 + 1, osl_getThreadTextEncoding());
1730 return String();
1733 /*************************************************************************
1735 |* DirEntry::SetName()
1737 |* Beschreibung FSYS.SDW
1738 |* Ersterstellung MI 04.09.93
1739 |* Letzte Aenderung MI 04.09.93
1741 *************************************************************************/
1743 void DirEntry::SetName( const String& rName, FSysPathStyle eFormatter )
1745 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
1747 if ( eFormatter == FSYS_STYLE_HOST || eFormatter == FSYS_STYLE_DETECT )
1748 eFormatter = DEFSTYLE;
1749 ByteString aAccDelim( ACCESSDELIM_C( eFormatter ) );
1751 if ( (eFlag != FSYS_FLAG_NORMAL) ||
1752 (aName.Search( ':' ) != STRING_NOTFOUND) ||
1753 (aName.Search( aAccDelim ) != STRING_NOTFOUND) ||
1754 (eFormatter == FSYS_STYLE_FAT && (aName.GetTokenCount( '.' ) > 2) ) )
1756 eFlag = FSYS_FLAG_INVALID;
1758 else
1760 aName = ByteString(rName, osl_getThreadTextEncoding());
1764 /*************************************************************************
1766 |* DirEntry::Find()
1768 |* Beschreibung FSYS.SDW
1769 |* Ersterstellung MI 26.04.91
1770 |* Letzte Aenderung MA 02.12.91
1772 *************************************************************************/
1773 BOOL DirEntry::Find( const String& rPfad, char cDelim )
1775 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
1777 if ( ImpGetTopPtr()->eFlag == FSYS_FLAG_ABSROOT )
1778 return TRUE;
1780 BOOL bWild = aName.Search( '*' ) != STRING_NOTFOUND ||
1781 aName.Search( '?' ) != STRING_NOTFOUND;
1782 if ( !cDelim )
1783 cDelim = SEARCHDELIM(DEFSTYLE)[0];
1785 USHORT nTokenCount = rPfad.GetTokenCount( cDelim );
1786 USHORT nIndex = 0;
1787 ByteString aThis = ACCESSDELIM(DEFSTYLE);
1788 aThis += ByteString(GetFull(), osl_getThreadTextEncoding());
1789 for ( USHORT nToken = 0; nToken < nTokenCount; ++nToken )
1791 ByteString aPath = ByteString(rPfad, osl_getThreadTextEncoding()).GetToken( 0, cDelim, nIndex );
1793 if ( aPath.Len() )
1795 if (aPath.GetChar(aPath.Len()-1)== ACCESSDELIM(DEFSTYLE)[0])
1796 aPath.Erase(aPath.Len()-1);
1797 aPath += aThis;
1798 DirEntry aEntry( String(aPath, osl_getThreadTextEncoding()));
1799 if ( aEntry.ToAbs() &&
1800 ( ( !bWild && aEntry.Exists() ) || ( bWild && aEntry.First() ) ) )
1802 (*this) = aEntry;
1803 return TRUE;
1807 return FALSE;
1810 /*************************************************************************
1812 |* DirEntry::ImpToRel()
1814 |* Beschreibung
1815 |* Ersterstellung MI 17.06.93
1816 |* Letzte Aenderung MI 17.06.93
1818 *************************************************************************/
1820 BOOL DirEntry::ImpToRel( String aCurStr )
1822 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
1824 DirEntry aThis(*this);
1825 aThis.ToAbs();
1826 String aThisStr( aThis.GetFull( FSYS_STYLE_HPFS ) );
1828 // #109512 preserve case of path even if caseinsensitive
1829 String aThisCompareStr( aThisStr ), aCurCompareStr( aCurStr );
1830 if ( ! IsCaseSensitive() )
1832 aThisCompareStr.ToLowerAscii();
1833 aCurCompareStr.ToLowerAscii();
1836 // "Ubereinstimmung pr"ufen
1837 USHORT nPos = aThisCompareStr.Match( aCurCompareStr );
1838 if ( nPos == STRING_MATCH && aThisStr.Len() != aCurStr.Len() )
1839 nPos = Min( aThisStr.Len(), aCurStr.Len() );
1841 // Sonderfall, die DirEntries sind identisch
1842 if ( nPos == STRING_MATCH )
1844 // dann ist der relative Pfad das aktuelle Verzeichnis
1845 *this = DirEntry();
1846 return TRUE;
1849 // Sonderfall, die DirEntries sind total verschieden
1850 if ( nPos == 0 )
1852 // dann ist der relativste Pfad absolut
1853 *this = aThis;
1854 return FALSE;
1857 // sonst nehmen wir die identischen Einzelteile vorne weg
1858 while ( nPos > 0 && aThisStr.GetChar(nPos) != '\\' )
1859 --nPos;
1860 aThisStr.Erase( 0, nPos + ( ( aThisStr.GetChar(nPos) == '\\' ) ? 1 : 0 ) );
1861 aCurStr.Erase( 0, nPos + ( ( aCurStr.GetChar(nPos) == '\\' ) ? 1 : 0 ) );
1863 // und fuellen mit dem Level der Directories auf
1864 for ( nPos = 0; nPos < aCurStr.Len(); ++nPos )
1865 if ( aCurStr.GetChar(nPos) == '\\' )
1866 aThisStr.Insert( String( "..\\", osl_getThreadTextEncoding() ), 0 );
1868 // das ist dann unser relativer Pfad
1869 *this = DirEntry( aThisStr, FSYS_STYLE_HPFS );
1870 return TRUE;
1873 /*************************************************************************
1875 |* DirEntry::CutRelParents()
1877 |* Beschreibung
1878 |* Ersterstellung MI 01.08.95
1879 |* Letzte Aenderung MI 01.08.95
1881 *************************************************************************/
1883 USHORT DirEntry::CutRelParents()
1885 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
1887 // erstes '..' finden
1888 DirEntry *pDir = 0;
1889 DirEntry *pPar;
1891 for ( pPar = this;
1892 pPar && pPar->eFlag != FSYS_FLAG_PARENT;
1893 pPar = pPar->pParent )
1894 pDir = pPar;
1896 // '..' zaehlen
1897 USHORT nParCount = 0;
1898 while ( pPar && pPar->eFlag == FSYS_FLAG_PARENT )
1900 ++nParCount;
1901 pPar = pPar->pParent;
1904 // cutten
1905 if ( pDir )
1906 DELETEZ(pDir->pParent);
1907 else
1908 eFlag = FSYS_FLAG_CURRENT;
1910 return nParCount;
1913 /*************************************************************************
1915 |* DirEntry::ToRel()
1917 |* Beschreibung FSYS.SDW
1918 |* Ersterstellung MI 26.06.93
1919 |* Letzte Aenderung MI 17.06.93
1921 *************************************************************************/
1923 BOOL DirEntry::ToRel()
1925 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
1927 DirEntry aCur;
1928 aCur.ToAbs();
1929 return ImpToRel( aCur.GetFull( FSYS_STYLE_HPFS ) );
1932 /*************************************************************************
1934 |* DirEntry::ToRel()
1936 |* Beschreibung FSYS.SDW
1937 |* Ersterstellung MI 26.04.91
1938 |* Letzte Aenderung MA 02.12.91
1940 *************************************************************************/
1942 BOOL DirEntry::ToRel( const DirEntry& rStart )
1944 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
1946 DirEntry aStart( rStart );
1947 aStart.ToAbs();
1948 return ImpToRel( aStart.GetFull( FSYS_STYLE_HPFS ) );
1951 /*************************************************************************
1953 |* DirEntry::GetDevice()
1955 |* Beschreibung FSYS.SDW
1956 |* Ersterstellung MI 26.04.91
1957 |* Letzte Aenderung MA 02.12.91
1959 *************************************************************************/
1961 #ifndef UNX
1963 DirEntry DirEntry::GetDevice() const
1965 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
1967 const DirEntry *pTop = ImpGetTopPtr();
1969 if ( ( pTop->eFlag == FSYS_FLAG_ABSROOT || pTop->eFlag == FSYS_FLAG_RELROOT ) &&
1970 pTop->aName.Len() )
1971 return DirEntry( pTop->aName, FSYS_FLAG_VOLUME, FSYS_STYLE_HOST );
1972 else
1973 return DirEntry( ByteString(), FSYS_FLAG_INVALID, FSYS_STYLE_HOST );
1976 #endif
1978 /*************************************************************************
1980 |* DirEntry::SetBase()
1982 |* Beschreibung FSYS.SDW
1983 |* Ersterstellung MI 23.10.91
1984 |* Letzte Aenderung MA 02.12.91
1986 *************************************************************************/
1988 void DirEntry::SetBase( const String& rBase, char cSep )
1990 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
1992 const char *p0 = ( aName.GetBuffer() );
1993 const char *p1 = p0 + aName.Len() - 1;
1994 while ( p1 >= p0 && *p1 != cSep )
1995 p1--;
1997 if ( p1 >= p0 )
1999 // es wurde ein cSep an der Position p1 gefunden
2000 aName.Erase( 0, static_cast< xub_StrLen >(p1 - p0) );
2001 aName.Insert( ByteString(rBase, osl_getThreadTextEncoding()), 0 );
2003 else
2004 aName = ByteString(rBase, osl_getThreadTextEncoding());
2007 /*************************************************************************
2009 |* DirEntry::GetSearchDelimiter()
2011 |* Beschreibung FSYS.SDW
2012 |* Ersterstellung MI 10.06.93
2013 |* Letzte Aenderung MI 10.06.93
2015 *************************************************************************/
2017 String DirEntry::GetSearchDelimiter( FSysPathStyle eFormatter )
2019 return String( ByteString(SEARCHDELIM( GetStyle( eFormatter ) ) ), osl_getThreadTextEncoding());
2022 /*************************************************************************
2024 |* DirEntry::GetMaxNameLen()
2026 |* Beschreibung Liefert die maximale Anzahl von Zeichen in
2027 |* einzelnen Namensteile. Bei FileSystmen mit
2028 |* fester Extension (FAT) zaehlt diese nicht mit.
2029 |* Bei unbekannten FileSytemen und FSYS_STYLE_URL
2030 |* wird USHRT_MAX zurueckgegeben.
2031 |* Ersterstellung MI 17.06.97
2032 |* Letzte Aenderung MI 17.06.97
2034 *************************************************************************/
2036 USHORT DirEntry::GetMaxNameLen( FSysPathStyle eFormatter )
2038 eFormatter = GetStyle( eFormatter );
2039 switch ( eFormatter )
2041 case FSYS_STYLE_MAC: return 31;
2043 case FSYS_STYLE_FAT: return 8;
2045 case FSYS_STYLE_VFAT:
2046 case FSYS_STYLE_NTFS:
2047 case FSYS_STYLE_NWFS:
2048 case FSYS_STYLE_HPFS: return 255;
2051 case FSYS_STYLE_SYSV: return 14;
2053 case FSYS_STYLE_BSD: return 250;
2055 default:
2056 return USHRT_MAX;
2060 /*************************************************************************
2062 |* DirEntry::TempName()
2064 |* Beschreibung FSYS.SDW - Aha, wo?
2065 |* Ersterstellung VB 06.09.93 (im SWG)
2066 |* Letzte Aenderung MI 06.02.98
2068 *************************************************************************/
2069 namespace { struct TempNameBase_Impl : public rtl::Static< DirEntry, TempNameBase_Impl > {}; }
2071 const DirEntry& DirEntry::SetTempNameBase( const String &rBase )
2073 DirEntry aTempDir = DirEntry().TempName().GetPath();
2074 aTempDir += DirEntry( rBase );
2075 #ifdef UNX
2076 ByteString aName( aTempDir.GetFull(), osl_getThreadTextEncoding());
2077 if ( access( aName.GetBuffer(), W_OK | X_OK | R_OK ) )
2079 // Create the directory and only on success give all rights to
2080 // everyone. Use mkdir instead of DirEntry::MakeDir because
2081 // this returns TRUE even if directory already exists.
2083 if ( !mkdir( aName.GetBuffer(), S_IRWXU | S_IRWXG | S_IRWXO ) )
2084 chmod( aName.GetBuffer(), S_IRWXU | S_IRWXG | S_IRWXO );
2086 // This will not create a directory but perhaps FileStat called
2087 // there modifies the DirEntry
2089 aTempDir.MakeDir();
2091 #else
2092 aTempDir.MakeDir();
2093 #endif
2094 DirEntry &rEntry = TempNameBase_Impl::get();
2095 rEntry = aTempDir.TempName( FSYS_KIND_DIR );
2096 return rEntry;
2099 DirEntry DirEntry::TempName( DirEntryKind eKind ) const
2101 // ggf. Base-Temp-Dir verwenden (macht Remote keinen Sinn => vorher)
2102 const DirEntry &rEntry = TempNameBase_Impl::get();
2103 if ( !pParent && FSYS_FLAG_CURRENT != rEntry.eFlag && FSYS_FLAG_ABSROOT != eFlag )
2106 DirEntry aFactory( rEntry );
2107 aFactory += GetName();
2108 return aFactory.TempName();
2111 ByteString aDirName; // hiermit hatte MPW C++ Probleme - immmer noch??
2112 char *ret_val;
2113 size_t i;
2115 // dertermine Directory, Prefix and Extension
2116 char pfx[6];
2117 char ext[5];
2118 const char *dir;
2119 const char *pWild = strchr( aName.GetBuffer(), '*' );
2120 if ( !pWild )
2121 pWild = strchr( aName.GetBuffer(), '?' );
2123 if ( pWild )
2125 if ( pParent )
2126 aDirName = ByteString(pParent->GetFull(), osl_getThreadTextEncoding());
2127 strncpy( pfx, aName.GetBuffer(), Min( (int)5, (int)(pWild-aName.GetBuffer()) ) );
2128 pfx[ pWild-aName.GetBuffer() ] = 0;
2129 const char *pExt = strchr( pWild, '.' );
2130 if ( pExt )
2132 strncpy( ext, pExt, 4 );
2133 ext[4] = 0;
2135 else
2136 strcpy( ext, ".tmp" );
2138 else
2140 aDirName = ByteString(GetFull(), osl_getThreadTextEncoding());
2141 strcpy( pfx, "sv" );
2142 strcpy( ext, ".tmp" );
2144 dir = aDirName.GetBuffer();
2146 // wurde kein Dir angegeben, dann nehmen wir ein passendes TEMP-Verz.
2147 char sBuf[_MAX_PATH];
2148 if ( eFlag == FSYS_FLAG_CURRENT || ( !pParent && pWild ) )
2149 dir = TempDirImpl(sBuf);
2151 // ab hier leicht modifizierter Code von VB
2152 DirEntry aRet(FSYS_FLAG_INVALID);
2153 i = strlen(dir);
2154 // need to add ?\\? + prefix + number + pid + .ext + '\0'
2155 # define TMPNAME_SIZE ( 1 + 5 + 5 + 10 + 4 + 1 )
2156 ret_val = new char[i + TMPNAME_SIZE ];
2157 if (ret_val)
2159 strcpy(ret_val,dir);
2161 /* Make sure directory ends with a separator */
2162 #if defined(WNT) || defined(OS2)
2163 if ( i>0 && ret_val[i-1] != '\\' && ret_val[i-1] != '/' &&
2164 ret_val[i-1] != ':')
2165 ret_val[i++] = '\\';
2166 #elif defined UNX
2167 if (i>0 && ret_val[i-1] != '/')
2168 ret_val[i++] = '/';
2169 #else
2170 #error unknown operating system
2171 #endif
2173 strncpy(ret_val + i, pfx, 5);
2174 ret_val[i + 5] = '\0'; /* strncpy doesn't put a 0 if more */
2175 i = strlen(ret_val); /* than 'n' chars. */
2177 /* Prefix can have 5 chars, leaving 3 for numbers. 26 ** 3 == 17576
2178 * Welcome to the 21st century, we can have longer filenames now ;)
2179 * New format: pfx + "5 char milli/micro second res" + "current pid" + ".tmp"
2181 #if (defined MSC || defined __MINGW32__) && defined WNT
2182 /* Milliseconds !! */
2183 static unsigned long u = GetTickCount();
2184 unsigned long mypid = static_cast<unsigned long>(_getpid());
2185 #else
2186 /* Microseconds !! */
2187 static unsigned long u = clock();
2188 unsigned long mypid = static_cast<unsigned long>(getpid());
2189 #endif
2190 for ( unsigned long nOld = u; ++u != nOld; ) /* Hae??? */
2192 u %= 100000; /* on *NIX repeats every 100ms, maybe less if CLOCKS_PER_SEC > 10^6 */
2193 snprintf(ret_val+i, TMPNAME_SIZE, "%05lu%lu", u, mypid);
2195 strcat(ret_val,ext);
2197 if ( FSYS_KIND_FILE == eKind )
2199 SvFileStream aStream( String( ret_val, osl_getThreadTextEncoding()),
2200 STREAM_WRITE|STREAM_SHARE_DENYALL );
2201 if ( aStream.IsOpen() )
2203 aStream.Seek( STREAM_SEEK_TO_END );
2204 if ( 0 == aStream.Tell() )
2206 aRet = DirEntry( String( ret_val, osl_getThreadTextEncoding()));
2207 break;
2209 aStream.Close();
2212 else
2214 // Redirect
2215 String aRetVal(ret_val, osl_getThreadTextEncoding());
2216 String aRedirected (aRetVal);
2217 #ifndef BOOTSTRAP
2218 FSysRedirector::DoRedirect( aRedirected );
2219 #endif
2220 if ( FSYS_KIND_DIR == eKind )
2222 if ( 0 == _mkdir( ByteString(aRedirected.GetBuffer(), osl_getThreadTextEncoding()).GetBuffer() ) )
2224 aRet = DirEntry( aRetVal );
2225 break;
2228 else
2230 #if defined(UNX) || defined(OS2)
2231 if( access( ByteString(aRedirected, osl_getThreadTextEncoding()).GetBuffer(), F_OK ) )
2233 aRet = DirEntry( aRetVal );
2234 break;
2236 #else
2237 struct stat aStat;
2238 if ( stat( ByteString(aRedirected, osl_getThreadTextEncoding()).GetBuffer(), &aStat ) )
2240 aRet = DirEntry( aRetVal );
2241 break;
2243 #endif
2248 delete[] ret_val;
2249 ret_val = 0;
2252 return aRet;
2255 /*************************************************************************
2257 |* DirEntry::operator[]()
2259 |* Beschreibung FSYS.SDW
2260 |* Ersterstellung MI 03.03.92
2261 |* Letzte Aenderung MI 03.03.92
2263 *************************************************************************/
2265 const DirEntry &DirEntry::operator[]( USHORT nParentLevel ) const
2267 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
2269 //TPF: maybe to be implemented (FastFSys)
2271 const DirEntry *pRes = this;
2272 while ( pRes && nParentLevel-- )
2273 pRes = pRes->pParent;
2275 return *pRes;
2278 /*************************************************************************
2280 |* DirEntry::ImpParseUnixName()
2282 |* Beschreibung FSYS.SDW
2283 |* Ersterstellung MI 26.04.91
2284 |* Letzte Aenderung MI 26.05.93
2286 *************************************************************************/
2288 FSysError DirEntry::ImpParseUnixName( const ByteString& rPfad, FSysPathStyle eStyle )
2290 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
2292 // die einzelnen Namen auf einen Stack packen
2293 DirEntryStack aStack;
2294 ByteString aPfad( rPfad );
2297 // den Namen vor dem ersten "/" abspalten,
2298 // falls '/' am Anfang, ist der Name '/',
2299 // der Rest immer ohne die fuehrenden '/'.
2300 // den ersten '/' suchen
2301 USHORT nPos;
2302 for ( nPos = 0;
2303 nPos < aPfad.Len() && aPfad.GetChar(nPos) != '/';
2304 nPos++ )
2305 /* do nothing */;
2307 // ist der Name die Root des aktuellen Drives?
2308 if ( nPos == 0 && aPfad.Len() > 0 && ( aPfad.GetChar(0) == '/' ) )
2310 // Root-Directory des aktuellen Drives
2311 aStack.Push( new DirEntry( FSYS_FLAG_ABSROOT ) );
2313 else
2315 // den Namen ohne Trenner abspalten
2316 aName = aPfad.Copy( 0, nPos );
2318 // stellt der Name die aktuelle Directory dar?
2319 if ( aName == "." )
2320 /* do nothing */;
2322 #ifdef UNX
2323 // stellt der Name das User-Dir dar?
2324 else if ( aName == "~" )
2326 DirEntry aHome( String( (const char *) getenv( "HOME" ), osl_getThreadTextEncoding()) );
2327 for ( USHORT n = aHome.Level(); n; --n )
2328 aStack.Push( new DirEntry( aHome[ (USHORT) n-1 ] ) );
2330 #endif
2332 // stellt der Name die Parent-Directory dar?
2333 else if ( aName == ".." )
2335 // ist nichts, ein Parent oder eine relative Root
2336 // auf dem Stack?
2337 if ( ( aStack.Count() == 0 ) ||
2338 ( aStack.Top()->eFlag == FSYS_FLAG_PARENT ) )
2339 // fuehrende Parents kommen auf den Stack
2340 aStack.Push( new DirEntry( ByteString(), FSYS_FLAG_PARENT, eStyle ) );
2342 // ist es eine absolute Root
2343 else if ( aStack.Top()->eFlag == FSYS_FLAG_ABSROOT ) {
2344 // die hat keine Parent-Directory
2345 return FSYS_ERR_NOTEXISTS;
2347 else
2348 // sonst hebt der Parent den TOS auf
2349 delete aStack.Pop();
2351 else
2353 DirEntry *pNew = NULL;
2354 // normalen Entries kommen auf den Stack
2355 pNew = new DirEntry( aName, FSYS_FLAG_NORMAL, eStyle );
2356 if ( !pNew->IsValid() )
2358 aName = rPfad;
2359 ErrCode eErr = pNew->GetError();
2360 delete pNew;
2361 return eErr;
2363 aStack.Push( pNew );
2367 // den Restpfad bestimmen
2368 aPfad.Erase( 0, nPos + 1 );
2369 while ( aPfad.Len() && ( aPfad.GetChar(0) == '/' ) )
2370 aPfad.Erase( 0, 1 );
2372 while ( aPfad.Len() );
2374 // Haupt-Entry (selbst) zuweisen
2375 if ( aStack.Count() == 0 )
2377 eFlag = FSYS_FLAG_CURRENT;
2378 aName.Erase();
2380 else
2382 eFlag = aStack.Top()->eFlag;
2383 aName = aStack.Top()->aName;
2384 delete aStack.Pop();
2387 // die Parent-Entries vom Stack holen
2388 DirEntry** pTemp = &pParent;
2389 while ( aStack.Count() )
2391 *pTemp = aStack.Pop();
2392 pTemp = &( (*pTemp)->pParent );
2395 return FSYS_ERR_OK;
2398 /*************************************************************************
2400 |* DirEntry::MakeShortName()
2402 |* Beschreibung
2403 |* Ersterstellung TLX
2404 |* Letzte Aenderung PB 21.08.97 (in CreateEntry_Impl())
2406 *************************************************************************/
2408 ErrCode CreateEntry_Impl( const DirEntry &rPath, DirEntryKind eKind )
2410 // versuchen, anzulegen (ausser bei FSYS_KIND_ALL)
2411 ErrCode eErr = ERRCODE_NONE;
2412 if ( FSYS_KIND_FILE == eKind )
2414 SvFileStream aStream( rPath.GetFull(), STREAM_STD_WRITE );
2415 aStream.WriteLine( "" );
2416 eErr = aStream.GetError();
2418 else if ( FSYS_KIND_ALL != eKind )
2419 eErr = rPath.MakeDir() ? ERRCODE_NONE : ERRCODE_IO_UNKNOWN;
2421 // erfolgreich?
2422 if ( !rPath.Exists() )
2423 eErr = ERRCODE_IO_UNKNOWN; // Doch was schiefgegangen ?
2425 // ggf. wieder l"oschen
2426 if ( FSYS_KIND_NONE == eKind )
2427 rPath.Kill();
2429 // Fehlercode zur?ckliefern
2430 return eErr;
2433 BOOL IsValidEntry_Impl( const DirEntry &rPath,
2434 const String &rLongName,
2435 DirEntryKind eKind,
2436 BOOL bIsShortened,
2437 BOOL bUseDelim )
2439 // Parameter-Pr"uefung
2440 DBG_ASSERT( eKind == FSYS_KIND_NONE || eKind == FSYS_KIND_ALL ||
2441 eKind == FSYS_KIND_FILE || eKind == FSYS_KIND_DIR,
2442 "invalid entry-kind" );
2444 // Alle von MSDOS erreichbaren FSYS_STYLES muessen den
2445 // MSDOS Filenamenanforderungen genuegen. Sonst wird probiert,
2446 // ob sich eine Datei des gewuenschten Names anlegen laesst.
2447 FSysPathStyle eStyle = DirEntry::GetPathStyle( rPath.GetDevice().GetName() );
2448 DirEntry aPath(rPath);
2449 DirEntry aName(rLongName, eStyle);
2450 if ( !aName.IsValid() || aName.Level() != 1 )
2451 return FALSE;
2452 aPath += aName;
2453 if ( 1 == aPath.Level() )
2454 return FALSE;
2455 if ( eStyle == FSYS_STYLE_FAT || eStyle == FSYS_STYLE_NWFS ||
2456 eStyle == FSYS_STYLE_UNKNOWN )
2458 DirEntry aDosEntry( rLongName, FSYS_STYLE_FAT );
2459 if ( !aDosEntry.IsValid() )
2460 return FALSE;
2463 // Pfad-Trenner sind nicht erlaubt (bei ungek"urzten auch nicht FSYS_SHORTNAME_DELIMITER)
2464 char cDelim = bUseDelim == 2 ? FSYS_SHORTNAME_DELIMITER : char(0);
2465 if (
2466 rLongName.Search(DirEntry::GetAccessDelimiter()) != STRING_NOTFOUND ||
2467 (!bIsShortened && rLongName.Search(cDelim) != STRING_NOTFOUND)
2470 return FALSE;
2473 // MI: Abfrage nach 'CON:' etc. wird jetzt in Exists() mitgemacht
2474 if ( aPath.Exists() )
2475 return FALSE;
2477 return (ERRCODE_NONE == CreateEntry_Impl( aPath, eKind ));
2480 //-------------------------------------------------------------------------
2482 #define MAX_EXT_FAT 3
2483 #define MAX_LEN_FAT 8
2484 #define INVALID_CHARS_FAT "\\/\"':|^<>[]?* "
2486 #define MAX_EXT_MAC 16 // nur wegen sinnvoller Namensk"rzung
2487 #define MAX_LEN_MAC 31
2488 #define INVALID_CHARS_MAC "\":"
2490 #define MAX_EXT_MAX 250
2491 #define MAX_LEN_MAX 255
2492 #define INVALID_CHARS_DEF "\\/\"':|^<>?*"
2494 BOOL DirEntry::MakeShortName( const String& rLongName, DirEntryKind eKind,
2495 BOOL bUseDelim, FSysPathStyle eStyle )
2497 String aLongName(rLongName);
2499 // Alle '#' aus den Dateinamen entfernen, weil das INetURLObject
2500 // damit Probleme hat. Siehe auch #51246#
2501 aLongName.EraseAllChars( '#' );
2502 ByteString bLongName(aLongName, osl_getThreadTextEncoding());
2504 // Auf Novell-Servern (wegen der rottigen Clients) nur 7bit ASCII
2506 // HRO: #69627# Weg mit dem Scheiss. Wenn es Client gibt, die so einen
2507 // BUG haben, dann muss halt der Client ersetzt werden, aber doch nicht das
2508 // Office kastrieren !!!
2510 #if 0
2511 if ( FSYS_STYLE_NWFS == GetPathStyle( ImpGetTopPtr()->GetName() ) )
2513 for ( USHORT n = aLongName.Len(); n; --n )
2515 short nChar = aLongName(n-1);
2516 if ( nChar < 32 || nChar >= 127 )
2517 aLongName.Erase( n-1, 1 );
2520 #endif
2522 // bei FSYS_KIND_ALL den alten Namen merken und abh"angen (rename)
2523 ByteString aOldName;
2524 if ( FSYS_KIND_ALL == eKind )
2526 aOldName = ByteString(CutName(), osl_getThreadTextEncoding());
2527 aOldName = CMP_LOWER(aOldName);
2530 // ist der Langname direkt verwendbar?
2531 if ( IsValidEntry_Impl( *this, aLongName, eKind, FALSE, bUseDelim ) )
2533 operator+=( DirEntry(aLongName) );
2534 return TRUE;
2537 // max L"angen feststellen
2538 USHORT nMaxExt, nMaxLen;
2539 if ( FSYS_STYLE_DETECT == eStyle )
2540 eStyle = DirEntry::GetPathStyle( GetDevice().GetName() );
2541 ByteString aInvalidChars;
2542 switch ( eStyle )
2544 case FSYS_STYLE_FAT:
2545 nMaxExt = MAX_EXT_FAT;
2546 nMaxLen = MAX_LEN_FAT;
2547 aInvalidChars = INVALID_CHARS_FAT;
2548 break;
2550 case FSYS_STYLE_MAC:
2551 nMaxExt = MAX_EXT_MAC;
2552 nMaxLen = MAX_LEN_MAC;
2553 aInvalidChars = INVALID_CHARS_MAC;
2554 break;
2556 default:
2557 nMaxExt = MAX_EXT_MAX;
2558 nMaxLen = MAX_LEN_MAX;
2559 aInvalidChars = INVALID_CHARS_DEF;
2562 // Extension abschneiden und kuerzen
2563 ByteString aExt;
2564 ByteString aFName = bLongName;
2565 if ( FSYS_STYLE_MAC != eStyle )
2567 DirEntry aUnparsed;
2568 aUnparsed.aName = bLongName;
2569 aExt = ByteString(aUnparsed.CutExtension(), osl_getThreadTextEncoding());
2570 aFName = aUnparsed.aName;
2571 if ( aExt.Len() > nMaxExt )
2573 char c = aExt.GetChar( aExt.Len() - 1 );
2574 aExt.Erase(nMaxExt-1);
2575 aExt += c;
2579 if ( FSYS_STYLE_FAT != eStyle )
2581 // ausser auf einem FAT-System geh"ort die Extension zur
2582 // Maxl"ange. Muss also vorher mit dem Punkt abgezogen werden.
2583 nMaxLen -= ( aExt.Len() + 1 );
2586 // Name k"urzen
2587 ByteString aSName;
2588 for ( const char *pc = aFName.GetBuffer(); aSName.Len() < nMaxLen && *pc; ++pc )
2590 if ( STRING_NOTFOUND == aInvalidChars.Search( *pc ) &&
2591 (unsigned char) *pc >= (unsigned char) 32 &&
2592 ( !aSName.Len() || *pc != ' ' || aSName.GetChar(aSName.Len()-1) != ' ' ) )
2593 aSName += *pc;
2595 aSName.EraseTrailingChars();
2597 // HRO: #74246# Also cut leading spaces
2598 aSName.EraseLeadingChars();
2600 if ( !aSName.Len() )
2601 aSName = "noname";
2603 // kommt dabei der alte Name raus?
2604 ByteString aNewName = aSName;
2605 if ( aExt.Len() )
2606 ( aNewName += '.' ) += aExt;
2607 operator+=( DirEntry(String(aNewName, osl_getThreadTextEncoding())) );
2608 if ( FSYS_KIND_ALL == eKind && CMP_LOWER(aName) == aOldName )
2609 if ( FSYS_KIND_ALL == eKind && CMP_LOWER(ByteString(GetName(), osl_getThreadTextEncoding())) == aOldName )
2610 return TRUE;
2612 // kann der gek"urzte Name direkt verwendet werden?
2613 if ( !Exists() && (ERRCODE_NONE == CreateEntry_Impl( *this, eKind )) )
2614 return TRUE;
2616 // darf '?##' verwendet werden, um eindeutigen Name zu erzeugen?
2617 if ( bUseDelim )
2619 // eindeutigen Namen per '?##' erzeugen
2620 aSName.Erase( nMaxLen-3 );
2621 if ( bUseDelim != 2 )
2622 aSName += FSYS_SHORTNAME_DELIMITER;
2623 for ( int n = 1; n < 99; ++n )
2625 // Name zusammensetzen
2626 ByteString aTmpStr( aSName );
2627 aTmpStr += ByteString::CreateFromInt32(n);
2628 if ( aExt.Len() )
2629 ( aTmpStr += '.' ) += aExt;
2631 // noch nicht vorhanden?
2632 SetName( String(aTmpStr, osl_getThreadTextEncoding()) );
2634 if ( !Exists() )
2636 // Fehler setzen !!!
2637 nError = CreateEntry_Impl( *this, eKind );
2638 return (ERRCODE_NONE == nError);
2643 // keine ## mehr frei / ?## soll nicht verwendet werden
2644 nError = ERRCODE_IO_ALREADYEXISTS;
2645 return FALSE;
2648 /*************************************************************************
2650 |* DirEntry::CreatePath()
2652 |* Beschreibung FSYS.SDW
2653 |* Ersterstellung MI 26.04.91
2654 |* Letzte Aenderung MA 02.12.91
2656 *************************************************************************/
2658 BOOL DirEntry::MakeDir( BOOL bSloppy ) const
2660 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
2662 // Schnellpruefung, ob vorhanden
2663 if ( FileStat( *this ).IsKind( FSYS_KIND_DIR ) )
2664 return TRUE;
2665 if ( bSloppy && pParent )
2666 if ( FileStat( *pParent ).IsKind( FSYS_KIND_DIR ) )
2667 return TRUE;
2669 const DirEntry *pNewDir = bSloppy ? pParent : this;
2670 if ( pNewDir )
2672 // den Path zum Dir erzeugen
2673 if ( pNewDir->pParent && !pNewDir->pParent->MakeDir(FALSE) )
2674 return FALSE;
2676 // das Dir selbst erzeugen
2677 if ( pNewDir->eFlag == FSYS_FLAG_ABSROOT ||
2678 pNewDir->eFlag == FSYS_FLAG_ABSROOT ||
2679 pNewDir->eFlag == FSYS_FLAG_VOLUME )
2680 return TRUE;
2681 else
2683 //? nError = ???
2684 if ( FileStat( *pNewDir ).IsKind( FSYS_KIND_DIR ) )
2685 return TRUE;
2686 else
2688 FSysFailOnErrorImpl();
2689 String aDirName(pNewDir->GetFull());
2690 #ifndef BOOTSTRAP
2691 FSysRedirector::DoRedirect( aDirName );
2692 #endif
2693 ByteString bDirName( aDirName, osl_getThreadTextEncoding() );
2694 bDirName = GUI2FSYS( bDirName );
2696 #ifdef WIN32
2697 SetLastError(0);
2698 #endif
2699 BOOL bResult = (0 == _mkdir( (char*) bDirName.GetBuffer() ));
2700 if ( !bResult )
2702 // Wer hat diese Methode const gemacht ?
2703 #ifdef WIN32
2704 ((DirEntry *)this)->SetError( Sys2SolarError_Impl( GetLastError() ) );
2705 #else
2706 ((DirEntry *)this)->SetError( Sys2SolarError_Impl( errno ) );
2707 #endif
2710 return bResult;
2714 return TRUE;
2717 /*************************************************************************
2719 |* DirEntry::CopyTo()
2721 |* Beschreibung FSYS.SDW
2722 |* Ersterstellung MI 26.04.91
2723 |* Letzte Aenderung MI 07.08.96
2725 *************************************************************************/
2727 FSysError DirEntry::CopyTo( const DirEntry& rDest, FSysAction nActions ) const
2729 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
2731 if ( FSYS_ACTION_COPYFILE != (nActions & FSYS_ACTION_COPYFILE) )
2732 #ifdef UNX
2734 // Hardlink anlegen
2735 HACK(redirection missing)
2736 ByteString aThis(GUI2FSYS(GetFull()), osl_getThreadTextEncoding());
2737 ByteString aDest(GUI2FSYS(rDest.GetFull()), osl_getThreadTextEncoding());
2738 if (link( aThis.GetBuffer(), aDest.GetBuffer() ) == -1)
2739 return Sys2SolarError_Impl( errno );
2740 else
2741 return FSYS_ERR_OK;
2743 #else
2744 return FSYS_ERR_NOTSUPPORTED;
2745 #endif
2747 FileCopier fc(*this, rDest);
2748 return fc.Execute(nActions);
2751 /*************************************************************************
2753 |* DirEntry::MoveTo()
2755 |* Beschreibung FSYS.SDW
2756 |* Ersterstellung MI 26.04.91
2757 |* Letzte Aenderung HRO 24.03.99
2759 *************************************************************************/
2761 #if defined WNT || defined UNX || defined OS2
2763 FSysError DirEntry::MoveTo( const DirEntry& rNewName ) const
2765 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
2768 FileStat aSourceStat(*this);
2769 if ( !aSourceStat.IsKind(FSYS_KIND_FILE) )
2770 return FSYS_ERR_NOTAFILE;
2773 DirEntry aDest(rNewName);
2774 FileStat aDestStat(rNewName);
2775 if ( aDestStat.IsKind(FSYS_KIND_DIR ) )
2777 aDest += String(aName, osl_getThreadTextEncoding());
2779 if ( aDest.Exists() )
2781 return FSYS_ERR_ALREADYEXISTS;
2784 #if defined(OS2)
2785 if ( FileStat(*this).IsKind(FSYS_KIND_DIR) && aDest.GetPath() != GetPath() )
2787 return FSYS_ERR_NOTSUPPORTED;
2789 #endif
2791 FSysFailOnErrorImpl();
2792 String aFrom( GetFull() );
2794 #ifndef BOOTSTRAP
2795 FSysRedirector::DoRedirect(aFrom);
2796 #endif
2798 String aTo( aDest.GetFull() );
2800 #ifndef BOOTSTRAP
2801 FSysRedirector::DoRedirect(aTo);
2802 #endif
2804 ByteString bFrom(aFrom, osl_getThreadTextEncoding());
2805 ByteString bTo(aTo, osl_getThreadTextEncoding());
2806 bFrom = GUI2FSYS(bFrom);
2807 bTo = GUI2FSYS(bTo);
2809 #ifdef WNT
2810 // MoveTo nun atomar
2811 SetLastError(0);
2813 DirEntry aFromDevice(String(bFrom, osl_getThreadTextEncoding()));
2814 DirEntry aToDevice(String(bTo,osl_getThreadTextEncoding()));
2815 aFromDevice.ToAbs();
2816 aToDevice.ToAbs();
2817 aFromDevice=aFromDevice.GetDevice();
2818 aToDevice=aToDevice.GetDevice();
2820 //Quelle und Ziel auf gleichem device?
2821 if (aFromDevice==aToDevice)
2823 // ja, also intra-device-move mit MoveFile
2824 MoveFile( bFrom.GetBuffer(), bTo.GetBuffer() );
2825 // MoveFile ist buggy bei cross-device operationen.
2826 // Der R?ckgabewert ist auch dann TRUE, wenn nur ein Teil der Operation geklappt hat.
2827 // Zudem zeigt MoveFile unterschiedliches Verhalten bei unterschiedlichen NT-Versionen.
2828 return Sys2SolarError_Impl( GetLastError() );
2830 else
2832 //nein, also inter-device-move mit copy/delete
2833 FSysError nCopyError = CopyTo(rNewName, FSYS_ACTION_COPYFILE);
2835 DirEntry aKill(String(bTo, osl_getThreadTextEncoding()));
2836 FileStat aKillStat(String(bTo, osl_getThreadTextEncoding()));
2837 if ( aKillStat.IsKind(FSYS_KIND_DIR ) )
2839 aKill += String(aName, osl_getThreadTextEncoding());
2842 if (nCopyError==FSYS_ERR_OK)
2844 if (Kill()==FSYS_ERR_OK)
2846 return FSYS_ERR_OK;
2848 else
2850 aKill.Kill();
2851 return FSYS_ERR_ACCESSDENIED;
2854 else
2856 aKill.Kill();
2857 return nCopyError;
2860 #else
2861 // #68639#
2862 // on some nfs connections rename with from == to
2863 // leads to destruction of file
2864 if ( ( aFrom != aTo ) && ( 0 != rename( bFrom.GetBuffer(), bTo.GetBuffer() ) ) )
2865 #if !defined(UNX) && !defined(OS2)
2866 return Sys2SolarError_Impl( GetLastError() );
2867 #else
2869 if( errno == EXDEV )
2870 // cross device geht latuernich nicht mit rename
2872 FILE *fpIN = fopen( bFrom.GetBuffer(), "r" );
2873 FILE *fpOUT = fopen( bTo.GetBuffer(), "w" );
2874 if( fpIN && fpOUT )
2876 char pBuf[ 16384 ];
2877 int nBytes, nWritten, nErr = 0;
2878 errno = 0;
2879 while( ( nBytes = fread( pBuf, 1, sizeof(pBuf), fpIN ) ) && ! nErr )
2881 nWritten = fwrite( pBuf, 1, nBytes, fpOUT );
2882 // Fehler im fwrite ?
2883 if( nWritten < nBytes )
2885 nErr = errno;
2886 break;
2889 fclose( fpIN );
2890 fclose( fpOUT );
2891 if ( nErr )
2893 unlink( bTo.GetBuffer() );
2894 return Sys2SolarError_Impl( nErr );
2896 else
2898 unlink( bFrom.GetBuffer() );
2901 else
2903 return Sys2SolarError_Impl( EXDEV );
2906 else
2908 return Sys2SolarError_Impl( errno );
2911 #endif
2912 #endif
2913 return ERRCODE_NONE;
2916 #endif
2918 /*************************************************************************
2920 |* DirEntry::Kill()
2922 |* Beschreibung FSYS.SDW
2923 |* Ersterstellung MI 26.04.91
2924 |* Letzte Aenderung MI 07.08.96
2926 *************************************************************************/
2928 FSysError DirEntry::Kill( FSysAction nActions ) const
2930 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
2932 FSysError eError = FSYS_ERR_OK;
2933 FSysFailOnErrorImpl();
2935 // Name als doppelt 0-terminierter String
2936 String aTmpName( GetFull() );
2937 #ifndef BOOTSTRAP
2938 FSysRedirector::DoRedirect( aTmpName );
2939 #endif
2940 ByteString bTmpName( aTmpName, osl_getThreadTextEncoding());
2941 bTmpName = GUI2FSYS(bTmpName);
2943 char *pName = new char[bTmpName.Len()+2];
2944 strcpy( pName, bTmpName.GetBuffer() );
2945 pName[bTmpName.Len()+1] = (char) 0;
2947 //read-only files sollen auch geloescht werden koennen
2948 BOOL isReadOnly = FileStat::GetReadOnlyFlag(*this);
2949 if (isReadOnly)
2951 FileStat::SetReadOnlyFlag(*this, FALSE);
2954 // directory?
2955 if ( FileStat( *this ).IsKind(FSYS_KIND_DIR) )
2957 // Inhalte recursiv loeschen?
2958 if ( FSYS_ACTION_RECURSIVE == (nActions & FSYS_ACTION_RECURSIVE) )
2960 Dir aDir( *this, FSYS_KIND_DIR|FSYS_KIND_FILE );
2961 for ( USHORT n = 0; eError == FSYS_ERR_OK && n < aDir.Count(); ++n )
2963 const DirEntry &rSubDir = aDir[n];
2964 DirEntryFlag flag = rSubDir.GetFlag();
2965 if ( flag != FSYS_FLAG_CURRENT && flag != FSYS_FLAG_PARENT )
2966 eError = rSubDir.Kill(nActions);
2970 // das Dir selbst loeschen
2971 #ifdef WIN32
2972 SetLastError(0);
2973 #endif
2974 if ( eError == FSYS_ERR_OK && 0 != _rmdir( (char*) pName ) )
2977 // falls L"oschen nicht ging, CWD umsetzen
2978 #ifdef WIN32
2979 eError = Sys2SolarError_Impl( GetLastError() );
2980 #else
2981 eError = Sys2SolarError_Impl( errno );
2982 #endif
2983 if ( eError )
2985 GetPath().SetCWD();
2986 #ifdef WIN32
2987 SetLastError(0);
2988 #endif
2989 if (_rmdir( (char*) pName) != 0)
2991 #ifdef WIN32
2992 eError = Sys2SolarError_Impl( GetLastError() );
2993 #else
2994 eError = Sys2SolarError_Impl( errno );
2995 #endif
2997 else
2999 eError = FSYS_ERR_OK;
3004 else
3006 if ( FSYS_ACTION_USERECYCLEBIN == (nActions & FSYS_ACTION_USERECYCLEBIN) )
3008 #ifdef OS2
3009 eError = ApiRet2ToSolarError_Impl( DosDelete( (PSZ) pName ) );
3010 #elif defined(WNT)
3011 SHFILEOPSTRUCT aOp;
3012 aOp.hwnd = 0;
3013 aOp.wFunc = FO_DELETE;
3014 aOp.pFrom = pName;
3015 aOp.pTo = 0;
3016 aOp.fFlags = FOF_ALLOWUNDO|FOF_SILENT|FOF_NOCONFIRMATION;
3017 aOp.hNameMappings = 0;
3018 aOp.lpszProgressTitle = 0;
3019 eError = Sys2SolarError_Impl( SHFileOperation( &aOp ) );
3020 #else
3021 eError = ERRCODE_IO_NOTSUPPORTED;
3022 #endif
3024 else
3026 #ifdef WIN32
3027 SetLastError(0);
3028 #endif
3029 if ( 0 != _unlink( (char*) pName ) )
3031 #ifdef WIN32
3032 eError = Sys2SolarError_Impl( GetLastError() );
3033 #else
3034 eError = Sys2SolarError_Impl( errno );
3035 #endif
3037 else
3039 eError = ERRCODE_NONE;
3044 //falls Fehler, originales read-only flag wieder herstellen
3045 if ( isReadOnly && (eError!=ERRCODE_NONE) )
3047 FileStat::SetReadOnlyFlag(*this, isReadOnly);
3050 delete[] pName;
3051 return eError;
3054 /*************************************************************************
3056 |* DirEntry::Contains()
3058 |* Beschreibung ob rSubEntry direkt oder indirect in *this liegt
3059 |* Ersterstellung MI 20.03.97
3060 |* Letzte Aenderung MI 20.03.97
3062 *************************************************************************/
3064 BOOL DirEntry::Contains( const DirEntry &rSubEntry ) const
3066 DBG_ASSERT( IsAbs() && rSubEntry.IsAbs(), "must be absolute entries" );
3068 USHORT nThisLevel = Level();
3069 USHORT nSubLevel = rSubEntry.Level();
3070 if ( nThisLevel < nSubLevel )
3072 for ( ; nThisLevel; --nThisLevel, --nSubLevel )
3073 if ( (*this)[nThisLevel-1] != rSubEntry[nSubLevel-1] )
3074 return FALSE;
3075 return TRUE;
3077 return FALSE;
3080 /*************************************************************************
3082 |* DirEntry::Level()
3084 |* Beschreibung FSYS.SDW
3085 |* Ersterstellung MI 03.03.92
3086 |* Letzte Aenderung MI 03.03.92
3088 *************************************************************************/
3090 USHORT DirEntry::Level() const
3092 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
3094 USHORT nLevel = 0;
3095 const DirEntry *pRes = this;
3096 while ( pRes )
3098 pRes = pRes->pParent;
3099 nLevel++;
3102 return nLevel;
3105 /*************************************************************************
3107 |* DirEntry::ConvertNameToSystem()
3109 |* Beschreibung
3110 |* Ersterstellung DV 29.03.96
3111 |* Letzte Aenderung DV 29.03.96
3113 *************************************************************************/
3115 String DirEntry::ConvertNameToSystem( const String &rName )
3117 return rName;
3120 /*************************************************************************
3122 |* DirEntry::ConvertSystemToName()
3124 |* Beschreibung
3125 |* Ersterstellung DV 29.03.96
3126 |* Letzte Aenderung DV 29.03.96
3128 *************************************************************************/
3130 String DirEntry::ConvertSystemToName( const String &rName )
3132 return rName;
3135 /*************************************************************************
3137 |* DirEntry::IsValid()
3139 |* Beschreibung
3140 |* Ersterstellung MI 18.09.93
3141 |* Letzte Aenderung TPF 18.09.98
3143 *************************************************************************/
3145 BOOL DirEntry::IsValid() const
3147 return (nError == FSYS_ERR_OK);
3150 /*************************************************************************
3152 |* DirEntry::IsRFSAvailable()
3154 |* Beschreibung
3155 |* Ersterstellung TPF 21.10.98
3156 |* Letzte Aenderung TPF 21.10.98
3158 *************************************************************************/
3160 BOOL DirEntry::IsRFSAvailable()
3162 return FALSE;
3165 /*************************************************************************
3167 |* IsLongNameOnFAT()
3169 |* Beschreibung ?berpr?ft , ob das DirEntry einen langen
3170 |* Filenamen auf einer FAT-Partition enth?lt (EAs).
3171 |* (eigentlich nur f?r OS2 interessant)
3172 |* Ersterstellung TPF 02.10.98
3173 |* Letzte Aenderung TPF 01.03.1999
3175 *************************************************************************/
3177 BOOL DirEntry::IsLongNameOnFAT() const
3179 // FAT-System?
3180 DirEntry aTempDirEntry(*this);
3181 aTempDirEntry.ToAbs();
3182 if (DirEntry::GetPathStyle(aTempDirEntry.GetDevice().GetName().GetChar(0)) != FSYS_STYLE_FAT)
3184 return FALSE; // nein, also false
3187 // DirEntry-Kette auf lange Dateinamen pr?fen
3188 for( USHORT iLevel = this->Level(); iLevel > 0; iLevel-- )
3190 const DirEntry& rEntry = (const DirEntry&) (*this)[iLevel-1];
3191 String aBase( rEntry.GetBase() );
3192 String aExtension( rEntry.GetExtension() );
3194 if (aBase.Len()>8) // Name > 8?
3196 return TRUE;
3199 if (aExtension.Len()>3) // Extension > 3?
3201 return TRUE;
3204 return FALSE;
3207 //========================================================================
3209 #if defined(DBG_UTIL)
3211 void FSysTest()
3215 #endif