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