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