1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_tools.hxx"
26
27
28 #if !defined UNX
29 #include <io.h>
30 #include <process.h>
31 #endif
32
33 #if defined(UNX) || defined(OS2)
34 #include <unistd.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #endif
38
39 #include <ctype.h>
40 #include <errno.h>
41 #include <stdlib.h>
42 #include <stdio.h>
43 #include <string.h>
44 #include <tools/debug.hxx>
45 #include <tools/list.hxx>
46 #include "comdep.hxx"
47 #include <tools/fsys.hxx>
48 #define _TOOLS_HXX
49 #include <tools/urlobj.hxx>
50
51 #ifdef UNX
52 #define _MAX_PATH 260
53 #endif
54 #include <tools/stream.hxx>
55
56 #ifndef _VOS_MUTEX_HXX
57 #include <vos/mutex.hxx>
58 #endif
59
60 #include <osl/file.hxx>
61 #include <rtl/instance.hxx>
62
63
64 using namespace osl;
65 using namespace rtl;
66
67 int ApiRet2ToSolarError_Impl( int nApiRet );
68
69 //--------------------------------------------------------------------
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 occured", nSysErr );
121 return FSYS_ERR_UNKNOWN;
122 }
123
124 //--------------------------------------------------------------------
125
126 #ifndef BOOTSTRAP
127
128 FSysRedirector* FSysRedirector::_pRedirector = 0;
129 sal_Bool FSysRedirector::_bEnabled = sal_True;
130 #ifdef UNX
131 sal_Bool bInRedirection = sal_True;
132 #else
133 sal_Bool bInRedirection = sal_False;
134 #endif
135 static vos:: OMutex * pRedirectMutex = 0;
136
137 //------------------------------------------------------------------------
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 acessible only by one thread per time
162 // dont move the guard behind the bInRedirection check!!!
163 // think of nested calls (when called from callback)
164 vos:: OGuard aGuard( pRedirectMutex );
165
166 // if already in redirection, dont redirect
167 if ( bInRedirection )
168 return;
169
170 // dont redirect on nested calls
171 bInRedirection = sal_True;
172
173 // convert to URL
174 #ifndef UNX
175 for ( sal_Unicode *p = (sal_Unicode*)aURL.GetBuffer(); *p; ++p )
176 if ( '\\' == *p ) *p = '/';
177 else if ( ':' == *p ) *p = '|';
178 #endif
179
180 aURL.Insert( String("file:///", osl_getThreadTextEncoding()), 0 );
181
182 // do redirection
183 Redirector();
184
185 bInRedirection = sal_False;
186 return;
187 }
188
189 //------------------------------------------------------------------------
190
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 wheather the contents are textual the same
1467
1468 if ( nError && ( nError == rEntry.nError ) )
1469 return sal_True;
1470 if ( nError || rEntry.nError ||
1471 ( eFlag == FSYS_FLAG_INVALID ) ||
1472 ( rEntry.eFlag == FSYS_FLAG_INVALID ) )
1473 return sal_False;
1474
1475 #ifndef OS2
1476 const
1477 #endif
1478 DirEntry *pThis = (DirEntry *)this;
1479 #ifndef OS2
1480 const
1481 #endif
1482 DirEntry *pWith = (DirEntry *)&rEntry;
1483 while( pThis && pWith && (pThis->eFlag == pWith->eFlag) )
1484 {
1485 if ( CMP_LOWER(pThis->aName) != CMP_LOWER(pWith->aName) )
1486 break;
1487 pThis = pThis->pParent;
1488 pWith = pWith->pParent;
1489 }
1490
1491 return ( !pThis && !pWith );
1492 }
1493
1494 /*************************************************************************
1495 |*
1496 |* DirEntry::operator=()
1497 |*
1498 |* Beschreibung FSYS.SDW
1499 |* Ersterstellung MI 26.04.91
1500 |* Letzte Aenderung MA 02.12.91
1501 |*
1502 *************************************************************************/
1503
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 // dertermine Directory, Prefix and Extension
2109 char pfx[6];
2110 char ext[5];
2111 const char *dir;
2112 const char *pWild = strchr( aName.GetBuffer(), '*' );
2113 if ( !pWild )
2114 pWild = strchr( aName.GetBuffer(), '?' );
2115
2116 if ( pWild )
2117 {
2118 if ( pParent )
2119 aDirName = ByteString(pParent->GetFull(), osl_getThreadTextEncoding());
2120 strncpy( pfx, aName.GetBuffer(), Min( (int)5, (int)(pWild-aName.GetBuffer()) ) );
2121 pfx[ pWild-aName.GetBuffer() ] = 0;
2122 const char *pExt = strchr( pWild, '.' );
2123 if ( pExt )
2124 {
2125 strncpy( ext, pExt, 4 );
2126 ext[4] = 0;
2127 }
2128 else
2129 strcpy( ext, ".tmp" );
2130 }
2131 else
2132 {
2133 aDirName = ByteString(GetFull(), osl_getThreadTextEncoding());
2134 strcpy( pfx, "sv" );
2135 strcpy( ext, ".tmp" );
2136 }
2137 dir = aDirName.GetBuffer();
2138
2139 // wurde kein Dir angegeben, dann nehmen wir ein passendes TEMP-Verz.
2140 char sBuf[_MAX_PATH];
2141 if ( eFlag == FSYS_FLAG_CURRENT || ( !pParent && pWild ) )
2142 dir = TempDirImpl(sBuf);
2143
2144 // ab hier leicht modifizierter Code von VB
2145 DirEntry aRet(FSYS_FLAG_INVALID);
2146 i = strlen(dir);
2147 // need to add ?\\? + prefix + number + pid + .ext + '\0'
2148 # define TMPNAME_SIZE ( 1 + 5 + 5 + 10 + 4 + 1 )
2149 ret_val = new char[i + TMPNAME_SIZE ];
2150 if (ret_val)
2151 {
2152 strcpy(ret_val,dir);
2153
2154 /* Make sure directory ends with a separator */
2155 #if defined(WNT) || defined(OS2)
2156 if ( i>0 && ret_val[i-1] != '\\' && ret_val[i-1] != '/' &&
2157 ret_val[i-1] != ':')
2158 ret_val[i++] = '\\';
2159 #elif defined UNX
2160 if (i>0 && ret_val[i-1] != '/')
2161 ret_val[i++] = '/';
2162 #else
2163 #error unknown operating system
2164 #endif
2165
2166 strncpy(ret_val + i, pfx, 5);
2167 ret_val[i + 5] = '\0'; /* strncpy doesn't put a 0 if more */
2168 i = strlen(ret_val); /* than 'n' chars. */
2169
2170 /* Prefix can have 5 chars, leaving 3 for numbers. 26 ** 3 == 17576
2171 * Welcome to the 21st century, we can have longer filenames now ;)
2172 * New format: pfx + "5 char milli/micro second res" + "current pid" + ".tmp"
2173 */
2174 #if (defined MSC || defined __MINGW32__) && defined WNT
2175 /* Milliseconds !! */
2176 static unsigned long u = GetTickCount();
2177 unsigned long mypid = static_cast<unsigned long>(_getpid());
2178 #else
2179 /* Microseconds !! */
2180 static unsigned long u = clock();
2181 unsigned long mypid = static_cast<unsigned long>(getpid());
2182 #endif
2183 for ( unsigned long nOld = u; ++u != nOld; ) /* Hae??? */
2184 {
2185 u %= 100000; /* on *NIX repeats every 100ms, maybe less if CLOCKS_PER_SEC > 10^6 */
2186 snprintf(ret_val+i, TMPNAME_SIZE, "%05lu%lu", u, mypid);
2187
2188 strcat(ret_val,ext);
2189
2190 if ( FSYS_KIND_FILE == eKind )
2191 {
2192 SvFileStream aStream( String( ret_val, osl_getThreadTextEncoding()),
2193 STREAM_WRITE|STREAM_SHARE_DENYALL );
2194 if ( aStream.IsOpen() )
2195 {
2196 aStream.Seek( STREAM_SEEK_TO_END );
2197 if ( 0 == aStream.Tell() )
2198 {
2199 aRet = DirEntry( String( ret_val, osl_getThreadTextEncoding()));
2200 break;
2201 }
2202 aStream.Close();
2203 }
2204 }
2205 else
2206 {
2207 // Redirect
2208 String aRetVal(ret_val, osl_getThreadTextEncoding());
2209 String aRedirected (aRetVal);
2210 #ifndef BOOTSTRAP
2211 FSysRedirector::DoRedirect( aRedirected );
2212 #endif
2213 if ( FSYS_KIND_DIR == eKind )
2214 {
2215 if ( 0 == _mkdir( ByteString(aRedirected.GetBuffer(), osl_getThreadTextEncoding()).GetBuffer() ) )
2216 {
2217 aRet = DirEntry( aRetVal );
2218 break;
2219 }
2220 }
2221 else
2222 {
2223 #if defined(UNX) || defined(OS2)
2224 if( access( ByteString(aRedirected, osl_getThreadTextEncoding()).GetBuffer(), F_OK ) )
2225 {
2226 aRet = DirEntry( aRetVal );
2227 break;
2228 }
2229 #else
2230 struct stat aStat;
2231 if ( stat( ByteString(aRedirected, osl_getThreadTextEncoding()).GetBuffer(), &aStat ) )
2232 {
2233 aRet = DirEntry( aRetVal );
2234 break;
2235 }
2236 #endif
2237 }
2238 }
2239 }
2240
2241 delete[] ret_val;
2242 ret_val = 0;
2243 }
2244
2245 return aRet;
2246 }
2247
2248 /*************************************************************************
2249 |*
2250 |* DirEntry::operator[]()
2251 |*
2252 |* Beschreibung FSYS.SDW
2253 |* Ersterstellung MI 03.03.92
2254 |* Letzte Aenderung MI 03.03.92
2255 |*
2256 *************************************************************************/
2257
operator [](sal_uInt16 nParentLevel) const2258 const DirEntry &DirEntry::operator[]( sal_uInt16 nParentLevel ) const
2259 {
2260 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
2261
2262 //TPF: maybe to be implemented (FastFSys)
2263
2264 const DirEntry *pRes = this;
2265 while ( pRes && nParentLevel-- )
2266 pRes = pRes->pParent;
2267
2268 return *pRes;
2269 }
2270
2271 /*************************************************************************
2272 |*
2273 |* DirEntry::ImpParseUnixName()
2274 |*
2275 |* Beschreibung FSYS.SDW
2276 |* Ersterstellung MI 26.04.91
2277 |* Letzte Aenderung MI 26.05.93
2278 |*
2279 *************************************************************************/
2280
ImpParseUnixName(const ByteString & rPfad,FSysPathStyle eStyle)2281 FSysError DirEntry::ImpParseUnixName( const ByteString& rPfad, FSysPathStyle eStyle )
2282 {
2283 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
2284
2285 // die einzelnen Namen auf einen Stack packen
2286 DirEntryStack aStack;
2287 ByteString aPfad( rPfad );
2288 do
2289 {
2290 // den Namen vor dem ersten "/" abspalten,
2291 // falls '/' am Anfang, ist der Name '/',
2292 // der Rest immer ohne die fuehrenden '/'.
2293 // den ersten '/' suchen
2294 sal_uInt16 nPos;
2295 for ( nPos = 0;
2296 nPos < aPfad.Len() && aPfad.GetChar(nPos) != '/';
2297 nPos++ )
2298 /* do nothing */;
2299
2300 // ist der Name die Root des aktuellen Drives?
2301 if ( nPos == 0 && aPfad.Len() > 0 && ( aPfad.GetChar(0) == '/' ) )
2302 {
2303 // Root-Directory des aktuellen Drives
2304 aStack.Push( new DirEntry( FSYS_FLAG_ABSROOT ) );
2305 }
2306 else
2307 {
2308 // den Namen ohne Trenner abspalten
2309 aName = aPfad.Copy( 0, nPos );
2310
2311 // stellt der Name die aktuelle Directory dar?
2312 if ( aName == "." )
2313 /* do nothing */;
2314
2315 #ifdef UNX
2316 // stellt der Name das User-Dir dar?
2317 else if ( aName == "~" )
2318 {
2319 DirEntry aHome( String( (const char *) getenv( "HOME" ), osl_getThreadTextEncoding()) );
2320 for ( sal_uInt16 n = aHome.Level(); n; --n )
2321 aStack.Push( new DirEntry( aHome[ (sal_uInt16) n-1 ] ) );
2322 }
2323 #endif
2324
2325 // stellt der Name die Parent-Directory dar?
2326 else if ( aName == ".." )
2327 {
2328 // ist nichts, ein Parent oder eine relative Root
2329 // auf dem Stack?
2330 if ( ( aStack.Count() == 0 ) ||
2331 ( aStack.Top()->eFlag == FSYS_FLAG_PARENT ) )
2332 // fuehrende Parents kommen auf den Stack
2333 aStack.Push( new DirEntry( ByteString(), FSYS_FLAG_PARENT, eStyle ) );
2334
2335 // ist es eine absolute Root
2336 else if ( aStack.Top()->eFlag == FSYS_FLAG_ABSROOT ) {
2337 // die hat keine Parent-Directory
2338 return FSYS_ERR_NOTEXISTS;
2339 }
2340 else
2341 // sonst hebt der Parent den TOS auf
2342 delete aStack.Pop();
2343 }
2344 else
2345 {
2346 DirEntry *pNew = NULL;
2347 // normalen Entries kommen auf den Stack
2348 pNew = new DirEntry( aName, FSYS_FLAG_NORMAL, eStyle );
2349 if ( !pNew->IsValid() )
2350 {
2351 aName = rPfad;
2352 ErrCode eErr = pNew->GetError();
2353 delete pNew;
2354 return eErr;
2355 }
2356 aStack.Push( pNew );
2357 }
2358 }
2359
2360 // den Restpfad bestimmen
2361 aPfad.Erase( 0, nPos + 1 );
2362 while ( aPfad.Len() && ( aPfad.GetChar(0) == '/' ) )
2363 aPfad.Erase( 0, 1 );
2364 }
2365 while ( aPfad.Len() );
2366
2367 // Haupt-Entry (selbst) zuweisen
2368 if ( aStack.Count() == 0 )
2369 {
2370 eFlag = FSYS_FLAG_CURRENT;
2371 aName.Erase();
2372 }
2373 else
2374 {
2375 eFlag = aStack.Top()->eFlag;
2376 aName = aStack.Top()->aName;
2377 delete aStack.Pop();
2378 }
2379
2380 // die Parent-Entries vom Stack holen
2381 DirEntry** pTemp = &pParent;
2382 while ( aStack.Count() )
2383 {
2384 *pTemp = aStack.Pop();
2385 pTemp = &( (*pTemp)->pParent );
2386 }
2387
2388 return FSYS_ERR_OK;
2389 }
2390
2391 /*************************************************************************
2392 |*
2393 |* DirEntry::MakeShortName()
2394 |*
2395 |* Beschreibung
2396 |* Ersterstellung TLX
2397 |* Letzte Aenderung PB 21.08.97 (in CreateEntry_Impl())
2398 |*
2399 *************************************************************************/
2400
CreateEntry_Impl(const DirEntry & rPath,DirEntryKind eKind)2401 ErrCode CreateEntry_Impl( const DirEntry &rPath, DirEntryKind eKind )
2402 {
2403 // versuchen, anzulegen (ausser bei FSYS_KIND_ALL)
2404 ErrCode eErr = ERRCODE_NONE;
2405 if ( FSYS_KIND_FILE == eKind )
2406 {
2407 SvFileStream aStream( rPath.GetFull(), STREAM_STD_WRITE );
2408 aStream.WriteLine( "" );
2409 eErr = aStream.GetError();
2410 }
2411 else if ( FSYS_KIND_ALL != eKind )
2412 eErr = rPath.MakeDir() ? ERRCODE_NONE : ERRCODE_IO_UNKNOWN;
2413
2414 // erfolgreich?
2415 if ( !rPath.Exists() )
2416 eErr = ERRCODE_IO_UNKNOWN; // Doch was schiefgegangen ?
2417
2418 // ggf. wieder l"oschen
2419 if ( FSYS_KIND_NONE == eKind )
2420 rPath.Kill();
2421
2422 // Fehlercode zur?ckliefern
2423 return eErr;
2424 }
2425
IsValidEntry_Impl(const DirEntry & rPath,const String & rLongName,DirEntryKind eKind,sal_Bool bIsShortened,sal_Bool bUseDelim)2426 sal_Bool IsValidEntry_Impl( const DirEntry &rPath,
2427 const String &rLongName,
2428 DirEntryKind eKind,
2429 sal_Bool bIsShortened,
2430 sal_Bool bUseDelim )
2431 {
2432 // Parameter-Pr"uefung
2433 DBG_ASSERT( eKind == FSYS_KIND_NONE || eKind == FSYS_KIND_ALL ||
2434 eKind == FSYS_KIND_FILE || eKind == FSYS_KIND_DIR,
2435 "invalid entry-kind" );
2436
2437 // Alle von MSDOS erreichbaren FSYS_STYLES muessen den
2438 // MSDOS Filenamenanforderungen genuegen. Sonst wird probiert,
2439 // ob sich eine Datei des gewuenschten Names anlegen laesst.
2440 FSysPathStyle eStyle = DirEntry::GetPathStyle( rPath.GetDevice().GetName() );
2441 DirEntry aPath(rPath);
2442 DirEntry aName(rLongName, eStyle);
2443 if ( !aName.IsValid() || aName.Level() != 1 )
2444 return sal_False;
2445 aPath += aName;
2446 if ( 1 == aPath.Level() )
2447 return sal_False;
2448 if ( eStyle == FSYS_STYLE_FAT || eStyle == FSYS_STYLE_NWFS ||
2449 eStyle == FSYS_STYLE_UNKNOWN )
2450 {
2451 DirEntry aDosEntry( rLongName, FSYS_STYLE_FAT );
2452 if ( !aDosEntry.IsValid() )
2453 return sal_False;
2454 }
2455
2456 // Pfad-Trenner sind nicht erlaubt (bei ungek"urzten auch nicht FSYS_SHORTNAME_DELIMITER)
2457 char cDelim = bUseDelim == 2 ? FSYS_SHORTNAME_DELIMITER : char(0);
2458 if (
2459 rLongName.Search(DirEntry::GetAccessDelimiter()) != STRING_NOTFOUND ||
2460 (!bIsShortened && rLongName.Search(cDelim) != STRING_NOTFOUND)
2461 )
2462 {
2463 return sal_False;
2464 }
2465
2466 // MI: Abfrage nach 'CON:' etc. wird jetzt in Exists() mitgemacht
2467 if ( aPath.Exists() )
2468 return sal_False;
2469
2470 return (ERRCODE_NONE == CreateEntry_Impl( aPath, eKind ));
2471 }
2472
2473 //-------------------------------------------------------------------------
2474
2475 #define MAX_EXT_FAT 3
2476 #define MAX_LEN_FAT 8
2477 #define INVALID_CHARS_FAT "\\/\"':|^<>[]?* "
2478
2479 #define MAX_EXT_MAC 16 // nur wegen sinnvoller Namensk"rzung
2480 #define MAX_LEN_MAC 31
2481 #define INVALID_CHARS_MAC "\":"
2482
2483 #define MAX_EXT_MAX 250
2484 #define MAX_LEN_MAX 255
2485 #define INVALID_CHARS_DEF "\\/\"':|^<>?*"
2486
MakeShortName(const String & rLongName,DirEntryKind eKind,sal_Bool bUseDelim,FSysPathStyle eStyle)2487 sal_Bool DirEntry::MakeShortName( const String& rLongName, DirEntryKind eKind,
2488 sal_Bool bUseDelim, FSysPathStyle eStyle )
2489 {
2490 String aLongName(rLongName);
2491
2492 // Alle '#' aus den Dateinamen entfernen, weil das INetURLObject
2493 // damit Probleme hat. Siehe auch #51246#
2494 aLongName.EraseAllChars( '#' );
2495 ByteString bLongName(aLongName, osl_getThreadTextEncoding());
2496
2497 // Auf Novell-Servern (wegen der rottigen Clients) nur 7bit ASCII
2498
2499 // HRO: #69627# Weg mit dem Scheiss. Wenn es Client gibt, die so einen
2500 // BUG haben, dann muss halt der Client ersetzt werden, aber doch nicht das
2501 // Office kastrieren !!!
2502
2503 #if 0
2504 if ( FSYS_STYLE_NWFS == GetPathStyle( ImpGetTopPtr()->GetName() ) )
2505 {
2506 for ( sal_uInt16 n = aLongName.Len(); n; --n )
2507 {
2508 short nChar = aLongName(n-1);
2509 if ( nChar < 32 || nChar >= 127 )
2510 aLongName.Erase( n-1, 1 );
2511 }
2512 }
2513 #endif
2514
2515 // bei FSYS_KIND_ALL den alten Namen merken und abh"angen (rename)
2516 ByteString aOldName;
2517 if ( FSYS_KIND_ALL == eKind )
2518 {
2519 aOldName = ByteString(CutName(), osl_getThreadTextEncoding());
2520 aOldName = CMP_LOWER(aOldName);
2521 }
2522
2523 // ist der Langname direkt verwendbar?
2524 if ( IsValidEntry_Impl( *this, aLongName, eKind, sal_False, bUseDelim ) )
2525 {
2526 operator+=( DirEntry(aLongName) );
2527 return sal_True;
2528 }
2529
2530 // max L"angen feststellen
2531 sal_uInt16 nMaxExt, nMaxLen;
2532 if ( FSYS_STYLE_DETECT == eStyle )
2533 eStyle = DirEntry::GetPathStyle( GetDevice().GetName() );
2534 ByteString aInvalidChars;
2535 switch ( eStyle )
2536 {
2537 case FSYS_STYLE_FAT:
2538 nMaxExt = MAX_EXT_FAT;
2539 nMaxLen = MAX_LEN_FAT;
2540 aInvalidChars = INVALID_CHARS_FAT;
2541 break;
2542
2543 case FSYS_STYLE_MAC:
2544 nMaxExt = MAX_EXT_MAC;
2545 nMaxLen = MAX_LEN_MAC;
2546 aInvalidChars = INVALID_CHARS_MAC;
2547 break;
2548
2549 default:
2550 nMaxExt = MAX_EXT_MAX;
2551 nMaxLen = MAX_LEN_MAX;
2552 aInvalidChars = INVALID_CHARS_DEF;
2553 }
2554
2555 // Extension abschneiden und kuerzen
2556 ByteString aExt;
2557 ByteString aFName = bLongName;
2558 if ( FSYS_STYLE_MAC != eStyle )
2559 {
2560 DirEntry aUnparsed;
2561 aUnparsed.aName = bLongName;
2562 aExt = ByteString(aUnparsed.CutExtension(), osl_getThreadTextEncoding());
2563 aFName = aUnparsed.aName;
2564 if ( aExt.Len() > nMaxExt )
2565 {
2566 char c = aExt.GetChar( aExt.Len() - 1 );
2567 aExt.Erase(nMaxExt-1);
2568 aExt += c;
2569 }
2570 }
2571
2572 if ( FSYS_STYLE_FAT != eStyle )
2573 {
2574 // ausser auf einem FAT-System geh"ort die Extension zur
2575 // Maxl"ange. Muss also vorher mit dem Punkt abgezogen werden.
2576 nMaxLen -= ( aExt.Len() + 1 );
2577 }
2578
2579 // Name k"urzen
2580 ByteString aSName;
2581 for ( const char *pc = aFName.GetBuffer(); aSName.Len() < nMaxLen && *pc; ++pc )
2582 {
2583 if ( STRING_NOTFOUND == aInvalidChars.Search( *pc ) &&
2584 (unsigned char) *pc >= (unsigned char) 32 &&
2585 ( !aSName.Len() || *pc != ' ' || aSName.GetChar(aSName.Len()-1) != ' ' ) )
2586 aSName += *pc;
2587 }
2588 aSName.EraseTrailingChars();
2589
2590 // HRO: #74246# Also cut leading spaces
2591 aSName.EraseLeadingChars();
2592
2593 if ( !aSName.Len() )
2594 aSName = "noname";
2595
2596 // kommt dabei der alte Name raus?
2597 ByteString aNewName = aSName;
2598 if ( aExt.Len() )
2599 ( aNewName += '.' ) += aExt;
2600 operator+=( DirEntry(String(aNewName, osl_getThreadTextEncoding())) );
2601 if ( FSYS_KIND_ALL == eKind && CMP_LOWER(aName) == aOldName )
2602 if ( FSYS_KIND_ALL == eKind && CMP_LOWER(ByteString(GetName(), osl_getThreadTextEncoding())) == aOldName )
2603 return sal_True;
2604
2605 // kann der gek"urzte Name direkt verwendet werden?
2606 if ( !Exists() && (ERRCODE_NONE == CreateEntry_Impl( *this, eKind )) )
2607 return sal_True;
2608
2609 // darf '?##' verwendet werden, um eindeutigen Name zu erzeugen?
2610 if ( bUseDelim )
2611 {
2612 // eindeutigen Namen per '?##' erzeugen
2613 aSName.Erase( nMaxLen-3 );
2614 if ( bUseDelim != 2 )
2615 aSName += FSYS_SHORTNAME_DELIMITER;
2616 for ( int n = 1; n < 99; ++n )
2617 {
2618 // Name zusammensetzen
2619 ByteString aTmpStr( aSName );
2620 aTmpStr += ByteString::CreateFromInt32(n);
2621 if ( aExt.Len() )
2622 ( aTmpStr += '.' ) += aExt;
2623
2624 // noch nicht vorhanden?
2625 SetName( String(aTmpStr, osl_getThreadTextEncoding()) );
2626
2627 if ( !Exists() )
2628 {
2629 // Fehler setzen !!!
2630 nError = CreateEntry_Impl( *this, eKind );
2631 return (ERRCODE_NONE == nError);
2632 }
2633 }
2634 }
2635
2636 // keine ## mehr frei / ?## soll nicht verwendet werden
2637 nError = ERRCODE_IO_ALREADYEXISTS;
2638 return sal_False;
2639 }
2640
2641 /*************************************************************************
2642 |*
2643 |* DirEntry::CreatePath()
2644 |*
2645 |* Beschreibung FSYS.SDW
2646 |* Ersterstellung MI 26.04.91
2647 |* Letzte Aenderung MA 02.12.91
2648 |*
2649 *************************************************************************/
2650
MakeDir(sal_Bool bSloppy) const2651 sal_Bool DirEntry::MakeDir( sal_Bool bSloppy ) const
2652 {
2653 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
2654
2655 // Schnellpruefung, ob vorhanden
2656 if ( FileStat( *this ).IsKind( FSYS_KIND_DIR ) )
2657 return sal_True;
2658 if ( bSloppy && pParent )
2659 if ( FileStat( *pParent ).IsKind( FSYS_KIND_DIR ) )
2660 return sal_True;
2661
2662 const DirEntry *pNewDir = bSloppy ? pParent : this;
2663 if ( pNewDir )
2664 {
2665 // den Path zum Dir erzeugen
2666 if ( pNewDir->pParent && !pNewDir->pParent->MakeDir(sal_False) )
2667 return sal_False;
2668
2669 // das Dir selbst erzeugen
2670 if ( pNewDir->eFlag == FSYS_FLAG_ABSROOT ||
2671 pNewDir->eFlag == FSYS_FLAG_ABSROOT ||
2672 pNewDir->eFlag == FSYS_FLAG_VOLUME )
2673 return sal_True;
2674 else
2675 {
2676 //? nError = ???
2677 if ( FileStat( *pNewDir ).IsKind( FSYS_KIND_DIR ) )
2678 return sal_True;
2679 else
2680 {
2681 FSysFailOnErrorImpl();
2682 String aDirName(pNewDir->GetFull());
2683 #ifndef BOOTSTRAP
2684 FSysRedirector::DoRedirect( aDirName );
2685 #endif
2686 ByteString bDirName( aDirName, osl_getThreadTextEncoding() );
2687 bDirName = GUI2FSYS( bDirName );
2688
2689 #ifdef WIN32
2690 SetLastError(0);
2691 #endif
2692 sal_Bool bResult = (0 == _mkdir( (char*) bDirName.GetBuffer() ));
2693 if ( !bResult )
2694 {
2695 // Wer hat diese Methode const gemacht ?
2696 #ifdef WIN32
2697 ((DirEntry *)this)->SetError( Sys2SolarError_Impl( GetLastError() ) );
2698 #else
2699 ((DirEntry *)this)->SetError( Sys2SolarError_Impl( errno ) );
2700 #endif
2701 }
2702
2703 return bResult;
2704 }
2705 }
2706 }
2707 return sal_True;
2708 }
2709
2710 /*************************************************************************
2711 |*
2712 |* DirEntry::CopyTo()
2713 |*
2714 |* Beschreibung FSYS.SDW
2715 |* Ersterstellung MI 26.04.91
2716 |* Letzte Aenderung MI 07.08.96
2717 |*
2718 *************************************************************************/
2719
CopyTo(const DirEntry & rDest,FSysAction nActions) const2720 FSysError DirEntry::CopyTo( const DirEntry& rDest, FSysAction nActions ) const
2721 {
2722 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
2723
2724 if ( FSYS_ACTION_COPYFILE != (nActions & FSYS_ACTION_COPYFILE) )
2725 #ifdef UNX
2726 {
2727 // Hardlink anlegen
2728 HACK(redirection missing)
2729 ByteString aThis(GUI2FSYS(GetFull()), osl_getThreadTextEncoding());
2730 ByteString aDest(GUI2FSYS(rDest.GetFull()), osl_getThreadTextEncoding());
2731 if (link( aThis.GetBuffer(), aDest.GetBuffer() ) == -1)
2732 return Sys2SolarError_Impl( errno );
2733 else
2734 return FSYS_ERR_OK;
2735 }
2736 #else
2737 return FSYS_ERR_NOTSUPPORTED;
2738 #endif
2739
2740 FileCopier fc(*this, rDest);
2741 return fc.Execute(nActions);
2742 }
2743
2744 /*************************************************************************
2745 |*
2746 |* DirEntry::MoveTo()
2747 |*
2748 |* Beschreibung FSYS.SDW
2749 |* Ersterstellung MI 26.04.91
2750 |* Letzte Aenderung HRO 24.03.99
2751 |*
2752 *************************************************************************/
2753
2754 #if defined WNT || defined UNX || defined OS2
2755
MoveTo(const DirEntry & rNewName) const2756 FSysError DirEntry::MoveTo( const DirEntry& rNewName ) const
2757 {
2758 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
2759
2760 /*
2761 FileStat aSourceStat(*this);
2762 if ( !aSourceStat.IsKind(FSYS_KIND_FILE) )
2763 return FSYS_ERR_NOTAFILE;
2764 */
2765
2766 DirEntry aDest(rNewName);
2767 FileStat aDestStat(rNewName);
2768 if ( aDestStat.IsKind(FSYS_KIND_DIR ) )
2769 {
2770 aDest += String(aName, osl_getThreadTextEncoding());
2771 }
2772 if ( aDest.Exists() )
2773 {
2774 return FSYS_ERR_ALREADYEXISTS;
2775 }
2776
2777 #if defined(OS2)
2778 if ( FileStat(*this).IsKind(FSYS_KIND_DIR) && aDest.GetPath() != GetPath() )
2779 {
2780 return FSYS_ERR_NOTSUPPORTED;
2781 }
2782 #endif
2783
2784 FSysFailOnErrorImpl();
2785 String aFrom( GetFull() );
2786
2787 #ifndef BOOTSTRAP
2788 FSysRedirector::DoRedirect(aFrom);
2789 #endif
2790
2791 String aTo( aDest.GetFull() );
2792
2793 #ifndef BOOTSTRAP
2794 FSysRedirector::DoRedirect(aTo);
2795 #endif
2796
2797 ByteString bFrom(aFrom, osl_getThreadTextEncoding());
2798 ByteString bTo(aTo, osl_getThreadTextEncoding());
2799 bFrom = GUI2FSYS(bFrom);
2800 bTo = GUI2FSYS(bTo);
2801
2802 #ifdef WNT
2803 // MoveTo nun atomar
2804 SetLastError(0);
2805
2806 DirEntry aFromDevice(String(bFrom, osl_getThreadTextEncoding()));
2807 DirEntry aToDevice(String(bTo,osl_getThreadTextEncoding()));
2808 aFromDevice.ToAbs();
2809 aToDevice.ToAbs();
2810 aFromDevice=aFromDevice.GetDevice();
2811 aToDevice=aToDevice.GetDevice();
2812
2813 //Quelle und Ziel auf gleichem device?
2814 if (aFromDevice==aToDevice)
2815 {
2816 // ja, also intra-device-move mit MoveFile
2817 MoveFile( bFrom.GetBuffer(), bTo.GetBuffer() );
2818 // MoveFile ist buggy bei cross-device operationen.
2819 // Der R?ckgabewert ist auch dann sal_True, wenn nur ein Teil der Operation geklappt hat.
2820 // Zudem zeigt MoveFile unterschiedliches Verhalten bei unterschiedlichen NT-Versionen.
2821 return Sys2SolarError_Impl( GetLastError() );
2822 }
2823 else
2824 {
2825 //nein, also inter-device-move mit copy/delete
2826 FSysError nCopyError = CopyTo(rNewName, FSYS_ACTION_COPYFILE);
2827
2828 DirEntry aKill(String(bTo, osl_getThreadTextEncoding()));
2829 FileStat aKillStat(String(bTo, osl_getThreadTextEncoding()));
2830 if ( aKillStat.IsKind(FSYS_KIND_DIR ) )
2831 {
2832 aKill += String(aName, osl_getThreadTextEncoding());
2833 }
2834
2835 if (nCopyError==FSYS_ERR_OK)
2836 {
2837 if (Kill()==FSYS_ERR_OK)
2838 {
2839 return FSYS_ERR_OK;
2840 }
2841 else
2842 {
2843 aKill.Kill();
2844 return FSYS_ERR_ACCESSDENIED;
2845 }
2846 }
2847 else
2848 {
2849 aKill.Kill();
2850 return nCopyError;
2851 }
2852 }
2853 #else
2854 // #68639#
2855 // on some nfs connections rename with from == to
2856 // leads to destruction of file
2857 if ( ( aFrom != aTo ) && ( 0 != rename( bFrom.GetBuffer(), bTo.GetBuffer() ) ) )
2858 #if !defined(UNX) && !defined(OS2)
2859 return Sys2SolarError_Impl( GetLastError() );
2860 #else
2861 {
2862 if( errno == EXDEV )
2863 // cross device geht latuernich nicht mit rename
2864 {
2865 FILE *fpIN = fopen( bFrom.GetBuffer(), "r" );
2866 FILE *fpOUT = fopen( bTo.GetBuffer(), "w" );
2867 if( fpIN && fpOUT )
2868 {
2869 char pBuf[ 16384 ];
2870 int nBytes, nWritten, nErr = 0;
2871 errno = 0;
2872 while( ( nBytes = fread( pBuf, 1, sizeof(pBuf), fpIN ) ) && ! nErr )
2873 {
2874 nWritten = fwrite( pBuf, 1, nBytes, fpOUT );
2875 // Fehler im fwrite ?
2876 if( nWritten < nBytes )
2877 {
2878 nErr = errno;
2879 break;
2880 }
2881 }
2882 fclose( fpIN );
2883 fclose( fpOUT );
2884 if ( nErr )
2885 {
2886 unlink( bTo.GetBuffer() );
2887 return Sys2SolarError_Impl( nErr );
2888 }
2889 else
2890 {
2891 unlink( bFrom.GetBuffer() );
2892 }
2893 }
2894 else
2895 {
2896 return Sys2SolarError_Impl( EXDEV );
2897 }
2898 }
2899 else
2900 {
2901 return Sys2SolarError_Impl( errno );
2902 }
2903 }
2904 #endif
2905 #endif
2906 return ERRCODE_NONE;
2907 }
2908
2909 #endif
2910
2911 /*************************************************************************
2912 |*
2913 |* DirEntry::Kill()
2914 |*
2915 |* Beschreibung FSYS.SDW
2916 |* Ersterstellung MI 26.04.91
2917 |* Letzte Aenderung MI 07.08.96
2918 |*
2919 *************************************************************************/
2920
Kill(FSysAction nActions) const2921 FSysError DirEntry::Kill( FSysAction nActions ) const
2922 {
2923 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
2924
2925 FSysError eError = FSYS_ERR_OK;
2926 FSysFailOnErrorImpl();
2927
2928 // Name als doppelt 0-terminierter String
2929 String aTmpName( GetFull() );
2930 #ifndef BOOTSTRAP
2931 FSysRedirector::DoRedirect( aTmpName );
2932 #endif
2933 ByteString bTmpName( aTmpName, osl_getThreadTextEncoding());
2934 bTmpName = GUI2FSYS(bTmpName);
2935
2936 char *pName = new char[bTmpName.Len()+2];
2937 strcpy( pName, bTmpName.GetBuffer() );
2938 pName[bTmpName.Len()+1] = (char) 0;
2939
2940 //read-only files sollen auch geloescht werden koennen
2941 sal_Bool isReadOnly = FileStat::GetReadOnlyFlag(*this);
2942 if (isReadOnly)
2943 {
2944 FileStat::SetReadOnlyFlag(*this, sal_False);
2945 }
2946
2947 // directory?
2948 if ( FileStat( *this ).IsKind(FSYS_KIND_DIR) )
2949 {
2950 // Inhalte recursiv loeschen?
2951 if ( FSYS_ACTION_RECURSIVE == (nActions & FSYS_ACTION_RECURSIVE) )
2952 {
2953 Dir aDir( *this, FSYS_KIND_DIR|FSYS_KIND_FILE );
2954 for ( sal_uInt16 n = 0; eError == FSYS_ERR_OK && n < aDir.Count(); ++n )
2955 {
2956 const DirEntry &rSubDir = aDir[n];
2957 DirEntryFlag flag = rSubDir.GetFlag();
2958 if ( flag != FSYS_FLAG_CURRENT && flag != FSYS_FLAG_PARENT )
2959 eError = rSubDir.Kill(nActions);
2960 }
2961 }
2962
2963 // das Dir selbst loeschen
2964 #ifdef WIN32
2965 SetLastError(0);
2966 #endif
2967 if ( eError == FSYS_ERR_OK && 0 != _rmdir( (char*) pName ) )
2968 //
2969 {
2970 // falls L"oschen nicht ging, CWD umsetzen
2971 #ifdef WIN32
2972 eError = Sys2SolarError_Impl( GetLastError() );
2973 #else
2974 eError = Sys2SolarError_Impl( errno );
2975 #endif
2976 if ( eError )
2977 {
2978 GetPath().SetCWD();
2979 #ifdef WIN32
2980 SetLastError(0);
2981 #endif
2982 if (_rmdir( (char*) pName) != 0)
2983 {
2984 #ifdef WIN32
2985 eError = Sys2SolarError_Impl( GetLastError() );
2986 #else
2987 eError = Sys2SolarError_Impl( errno );
2988 #endif
2989 }
2990 else
2991 {
2992 eError = FSYS_ERR_OK;
2993 }
2994 }
2995 }
2996 }
2997 else
2998 {
2999 if ( FSYS_ACTION_USERECYCLEBIN == (nActions & FSYS_ACTION_USERECYCLEBIN) )
3000 {
3001 #ifdef OS2
3002 eError = ApiRet2ToSolarError_Impl( DosDelete( (PSZ) pName ) );
3003 #elif defined(WNT)
3004 SHFILEOPSTRUCT aOp;
3005 aOp.hwnd = 0;
3006 aOp.wFunc = FO_DELETE;
3007 aOp.pFrom = pName;
3008 aOp.pTo = 0;
3009 aOp.fFlags = FOF_ALLOWUNDO|FOF_SILENT|FOF_NOCONFIRMATION;
3010 aOp.hNameMappings = 0;
3011 aOp.lpszProgressTitle = 0;
3012 eError = Sys2SolarError_Impl( SHFileOperation( &aOp ) );
3013 #else
3014 eError = ERRCODE_IO_NOTSUPPORTED;
3015 #endif
3016 }
3017 else
3018 {
3019 #ifdef WIN32
3020 SetLastError(0);
3021 #endif
3022 if ( 0 != _unlink( (char*) pName ) )
3023 {
3024 #ifdef WIN32
3025 eError = Sys2SolarError_Impl( GetLastError() );
3026 #else
3027 eError = Sys2SolarError_Impl( errno );
3028 #endif
3029 }
3030 else
3031 {
3032 eError = ERRCODE_NONE;
3033 }
3034 }
3035 }
3036
3037 //falls Fehler, originales read-only flag wieder herstellen
3038 if ( isReadOnly && (eError!=ERRCODE_NONE) )
3039 {
3040 FileStat::SetReadOnlyFlag(*this, isReadOnly);
3041 }
3042
3043 delete[] pName;
3044 return eError;
3045 }
3046
3047 /*************************************************************************
3048 |*
3049 |* DirEntry::Contains()
3050 |*
3051 |* Beschreibung ob rSubEntry direkt oder indirect in *this liegt
3052 |* Ersterstellung MI 20.03.97
3053 |* Letzte Aenderung MI 20.03.97
3054 |*
3055 *************************************************************************/
3056
Contains(const DirEntry & rSubEntry) const3057 sal_Bool DirEntry::Contains( const DirEntry &rSubEntry ) const
3058 {
3059 DBG_ASSERT( IsAbs() && rSubEntry.IsAbs(), "must be absolute entries" );
3060
3061 sal_uInt16 nThisLevel = Level();
3062 sal_uInt16 nSubLevel = rSubEntry.Level();
3063 if ( nThisLevel < nSubLevel )
3064 {
3065 for ( ; nThisLevel; --nThisLevel, --nSubLevel )
3066 if ( (*this)[nThisLevel-1] != rSubEntry[nSubLevel-1] )
3067 return sal_False;
3068 return sal_True;
3069 }
3070 return sal_False;
3071 }
3072
3073 /*************************************************************************
3074 |*
3075 |* DirEntry::Level()
3076 |*
3077 |* Beschreibung FSYS.SDW
3078 |* Ersterstellung MI 03.03.92
3079 |* Letzte Aenderung MI 03.03.92
3080 |*
3081 *************************************************************************/
3082
Level() const3083 sal_uInt16 DirEntry::Level() const
3084 {
3085 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
3086
3087 sal_uInt16 nLevel = 0;
3088 const DirEntry *pRes = this;
3089 while ( pRes )
3090 {
3091 pRes = pRes->pParent;
3092 nLevel++;
3093 }
3094
3095 return nLevel;
3096 }
3097
3098 /*************************************************************************
3099 |*
3100 |* DirEntry::ConvertNameToSystem()
3101 |*
3102 |* Beschreibung
3103 |* Ersterstellung DV 29.03.96
3104 |* Letzte Aenderung DV 29.03.96
3105 |*
3106 *************************************************************************/
3107
ConvertNameToSystem(const String & rName)3108 String DirEntry::ConvertNameToSystem( const String &rName )
3109 {
3110 return rName;
3111 }
3112
3113 /*************************************************************************
3114 |*
3115 |* DirEntry::ConvertSystemToName()
3116 |*
3117 |* Beschreibung
3118 |* Ersterstellung DV 29.03.96
3119 |* Letzte Aenderung DV 29.03.96
3120 |*
3121 *************************************************************************/
3122
ConvertSystemToName(const String & rName)3123 String DirEntry::ConvertSystemToName( const String &rName )
3124 {
3125 return rName;
3126 }
3127
3128 /*************************************************************************
3129 |*
3130 |* DirEntry::IsValid()
3131 |*
3132 |* Beschreibung
3133 |* Ersterstellung MI 18.09.93
3134 |* Letzte Aenderung TPF 18.09.98
3135 |*
3136 *************************************************************************/
3137
IsValid() const3138 sal_Bool DirEntry::IsValid() const
3139 {
3140 return (nError == FSYS_ERR_OK);
3141 }
3142
3143 /*************************************************************************
3144 |*
3145 |* DirEntry::IsRFSAvailable()
3146 |*
3147 |* Beschreibung
3148 |* Ersterstellung TPF 21.10.98
3149 |* Letzte Aenderung TPF 21.10.98
3150 |*
3151 *************************************************************************/
3152
IsRFSAvailable()3153 sal_Bool DirEntry::IsRFSAvailable()
3154 {
3155 return sal_False;
3156 }
3157
3158 /*************************************************************************
3159 |*
3160 |* IsLongNameOnFAT()
3161 |*
3162 |* Beschreibung ?berpr?ft , ob das DirEntry einen langen
3163 |* Filenamen auf einer FAT-Partition enth?lt (EAs).
3164 |* (eigentlich nur f?r OS2 interessant)
3165 |* Ersterstellung TPF 02.10.98
3166 |* Letzte Aenderung TPF 01.03.1999
3167 |*
3168 *************************************************************************/
3169
IsLongNameOnFAT() const3170 sal_Bool DirEntry::IsLongNameOnFAT() const
3171 {
3172 // FAT-System?
3173 DirEntry aTempDirEntry(*this);
3174 aTempDirEntry.ToAbs();
3175 if (DirEntry::GetPathStyle(aTempDirEntry.GetDevice().GetName().GetChar(0)) != FSYS_STYLE_FAT)
3176 {
3177 return sal_False; // nein, also false
3178 }
3179
3180 // DirEntry-Kette auf lange Dateinamen pr?fen
3181 for( sal_uInt16 iLevel = this->Level(); iLevel > 0; iLevel-- )
3182 {
3183 const DirEntry& rEntry = (const DirEntry&) (*this)[iLevel-1];
3184 String aBase( rEntry.GetBase() );
3185 String aExtension( rEntry.GetExtension() );
3186
3187 if (aBase.Len()>8) // Name > 8?
3188 {
3189 return sal_True;
3190 }
3191
3192 if (aExtension.Len()>3) // Extension > 3?
3193 {
3194 return sal_True;
3195 }
3196 }
3197 return sal_False;
3198 }
3199
3200 //========================================================================
3201
3202 #if defined(DBG_UTIL)
3203
FSysTest()3204 void FSysTest()
3205 {
3206 }
3207
3208 #endif
3209
3210