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