LCOV - code coverage report
Current view: top level - libreoffice/tools/source/fsys - dirent.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 302 587 51.4 %
Date: 2012-12-27 Functions: 35 47 74.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #if !defined UNX
      21             : #ifdef WNT
      22             : #include <windows.h>
      23             : #undef GetObject
      24             : #endif
      25             : #include <io.h>
      26             : #include <process.h>
      27             : #endif
      28             : 
      29             : #if defined(UNX)
      30             : #include <unistd.h>
      31             : #include <sys/types.h>
      32             : #include <sys/stat.h>
      33             : #endif
      34             : 
      35             : #include <ctype.h>
      36             : #include <errno.h>
      37             : #include <stdlib.h>
      38             : #include <stdio.h>
      39             : #include <string.h>
      40             : #include <tools/debug.hxx>
      41             : #include "comdep.hxx"
      42             : #include <tools/fsys.hxx>
      43             : #define _TOOLS_HXX
      44             : #include <tools/urlobj.hxx>
      45             : #include <vector>
      46             : 
      47             : #ifdef UNX
      48             : #define _MAX_PATH 260
      49             : #endif
      50             : 
      51             : #include <tools/stream.hxx>
      52             : #include <osl/mutex.hxx>
      53             : #include <osl/file.hxx>
      54             : #include <rtl/instance.hxx>
      55             : #include <comphelper/string.hxx>
      56             : 
      57             : using namespace osl;
      58             : using ::rtl::OUString;
      59             : 
      60             : int ApiRet2ToSolarError_Impl( int nApiRet );
      61             : 
      62          32 : int Sys2SolarError_Impl( int nSysErr )
      63             : {
      64          32 :     switch ( nSysErr )
      65             :     {
      66             : #ifdef WNT
      67             :         case NO_ERROR:                  return ERRCODE_NONE;
      68             :         case ERROR_INVALID_FUNCTION:    return ERRCODE_IO_GENERAL;
      69             :         case ERROR_FILE_NOT_FOUND:      return ERRCODE_IO_NOTEXISTS;
      70             :         case ERROR_PATH_NOT_FOUND:      return ERRCODE_IO_NOTEXISTSPATH;
      71             :         case ERROR_TOO_MANY_OPEN_FILES: return ERRCODE_IO_TOOMANYOPENFILES;
      72             :         case ERROR_ACCESS_DENIED:       return ERRCODE_IO_ACCESSDENIED;
      73             :         case ERROR_INVALID_HANDLE:      return ERRCODE_IO_GENERAL;
      74             :         case ERROR_NOT_ENOUGH_MEMORY:   return ERRCODE_IO_OUTOFMEMORY;
      75             :         case ERROR_INVALID_BLOCK:       return ERRCODE_IO_GENERAL;
      76             :         case ERROR_BAD_FORMAT:          return ERRCODE_IO_WRONGFORMAT;
      77             :         case ERROR_INVALID_ACCESS:      return ERRCODE_IO_ACCESSDENIED;
      78             :         case ERROR_INVALID_DRIVE:       return ERRCODE_IO_INVALIDDEVICE;
      79             :         case ERROR_CURRENT_DIRECTORY:   return ERRCODE_IO_CURRENTDIR;
      80             :         case ERROR_NOT_SAME_DEVICE:     return ERRCODE_IO_NOTSAMEDEVICE;
      81             :         case ERROR_WRITE_PROTECT:       return ERRCODE_IO_CANTWRITE;
      82             :         case ERROR_BAD_UNIT:            return ERRCODE_IO_INVALIDDEVICE;
      83             :         case ERROR_NOT_READY:           return ERRCODE_IO_DEVICENOTREADY;
      84             :         case ERROR_BAD_COMMAND:         return ERRCODE_IO_GENERAL;
      85             :         case ERROR_CRC:                 return ERRCODE_IO_BADCRC;
      86             :         case ERROR_BAD_LENGTH:          return ERRCODE_IO_INVALIDLENGTH;
      87             :         case ERROR_SEEK:                return ERRCODE_IO_CANTSEEK;
      88             :         case ERROR_NOT_DOS_DISK:        return ERRCODE_IO_WRONGFORMAT;
      89             :         case ERROR_SECTOR_NOT_FOUND:    return ERRCODE_IO_GENERAL;
      90             :         case ERROR_WRITE_FAULT:         return ERRCODE_IO_CANTWRITE;
      91             :         case ERROR_READ_FAULT:          return ERRCODE_IO_CANTREAD;
      92             :         case ERROR_GEN_FAILURE:         return ERRCODE_IO_GENERAL;
      93             :         case ERROR_SHARING_VIOLATION:   return ERRCODE_IO_LOCKVIOLATION;
      94             :         case ERROR_LOCK_VIOLATION:      return ERRCODE_IO_LOCKVIOLATION;
      95             :         case ERROR_WRONG_DISK:          return ERRCODE_IO_INVALIDDEVICE;
      96             :         case ERROR_NOT_SUPPORTED:       return ERRCODE_IO_NOTSUPPORTED;
      97             : #else
      98           0 :         case 0:         return ERRCODE_NONE;
      99          32 :         case ENOENT:    return ERRCODE_IO_NOTEXISTS;
     100           0 :         case EACCES:    return ERRCODE_IO_ACCESSDENIED;
     101           0 :         case EEXIST:    return ERRCODE_IO_ALREADYEXISTS;
     102           0 :         case EINVAL:    return ERRCODE_IO_INVALIDPARAMETER;
     103           0 :         case EMFILE:    return ERRCODE_IO_TOOMANYOPENFILES;
     104           0 :         case ENOMEM:    return ERRCODE_IO_OUTOFMEMORY;
     105           0 :         case ENOSPC:    return ERRCODE_IO_OUTOFSPACE;
     106             : #endif
     107             :     }
     108             : 
     109             :     OSL_TRACE( "FSys: unknown system error %d occurred", nSysErr );
     110           0 :     return FSYS_ERR_UNKNOWN;
     111             : }
     112             : 
     113             : class DirEntryStack
     114             : {
     115             : private:
     116             :     ::std::vector< DirEntry* >  maStack;
     117             : 
     118             : public:
     119       36692 :                         DirEntryStack() {};
     120             :                         ~DirEntryStack();
     121             : 
     122             :     inline  void        Push( DirEntry *pEntry );
     123             :     inline  DirEntry*   Pop();
     124             :     inline  DirEntry*   Top();
     125             :     inline  DirEntry*   Bottom();
     126             :     inline  bool        Empty();
     127             :     inline  void        Clear();
     128             : };
     129             : 
     130      242282 : inline void DirEntryStack::Push( DirEntry *pEntry )
     131             : {
     132      242282 :     maStack.push_back( pEntry );
     133      242282 : }
     134             : 
     135      242282 : inline DirEntry* DirEntryStack::Pop()
     136             : {
     137      242282 :     DirEntry*   pEntry = NULL;
     138      242282 :     if ( !maStack.empty() ) {
     139      242282 :         pEntry = maStack.back();
     140      242282 :         maStack.pop_back();
     141             :     }
     142      242282 :     return pEntry;
     143             : }
     144             : 
     145       73384 : inline DirEntry* DirEntryStack::Top()
     146             : {
     147       73384 :     return maStack.empty() ? NULL : maStack.back();
     148             : }
     149             : 
     150             : inline DirEntry* DirEntryStack::Bottom()
     151             : {
     152             :     return maStack.empty() ? NULL : maStack.front();
     153             : }
     154             : 
     155      278974 : inline bool DirEntryStack::Empty()
     156             : {
     157      278974 :     return maStack.empty();
     158             : }
     159             : 
     160             : inline void DirEntryStack::Clear()
     161             : {
     162             :     maStack.clear();
     163             : }
     164             : 
     165             : DBG_NAME( DirEntry );
     166             : 
     167       73384 : DirEntryStack::~DirEntryStack()
     168             : {
     169       36692 :     maStack.clear();
     170       36692 : }
     171             : 
     172             : #ifdef DBG_UTIL
     173             : /** Check DirEntry for DBG_UTIL
     174             : 
     175             :     @param p Pointer to DirEntry
     176             :     @return char* Error-TExtension or NULL
     177             : */
     178             : const char* ImpCheckDirEntry( const void* p )
     179             : {
     180             :     DirEntry* p0 = (DirEntry*)p;
     181             : 
     182             :     if ( p0->pParent )
     183             :         DBG_CHKOBJ( p0->pParent, DirEntry, ImpCheckDirEntry );
     184             : 
     185             :     return NULL;
     186             : }
     187             : #endif
     188             : 
     189             : /** Insert "..." for max length of nMaxChars */
     190           0 : rtl::OString ImplCutPath( const rtl::OString& rStr, sal_Int32 nMax, char cAccDel )
     191             : {
     192           0 :     sal_Int32 nMaxPathLen = nMax;
     193           0 :     sal_Bool bInsertPrefix = sal_False;
     194           0 :     sal_Int32 nBegin = rStr.indexOf(cAccDel);
     195           0 :     rtl::OStringBuffer aCutPath(rStr);
     196             : 
     197           0 :     if( nBegin == -1 )
     198           0 :         nBegin = 0;
     199             :     else
     200           0 :         nMaxPathLen += 2;   // Prefix <Disk>:
     201             : 
     202           0 :     while( aCutPath.getLength() > nMaxPathLen )
     203             :     {
     204           0 :         sal_Int32 nEnd = aCutPath.toString().indexOf(cAccDel, nBegin + 1);
     205             :         sal_Int32 nCount;
     206             : 
     207           0 :         if ( nEnd != -1 )
     208             :         {
     209           0 :             nCount = nEnd - nBegin;
     210           0 :             aCutPath.remove(nBegin, nCount);
     211           0 :             bInsertPrefix = sal_True;
     212             :         }
     213             :         else
     214           0 :             break;
     215             :     }
     216             : 
     217           0 :     if ( aCutPath.getLength() > nMaxPathLen )
     218             :     {
     219           0 :         for ( sal_Int32 n = nMaxPathLen; n > nMaxPathLen/2; --n )
     220             :         {
     221           0 :             if (!comphelper::string::isalnumAscii(aCutPath[n]))
     222             :             {
     223           0 :                 comphelper::string::truncateToLength(aCutPath, n);
     224           0 :                 aCutPath.append(RTL_CONSTASCII_STRINGPARAM("..."));
     225           0 :                 break;
     226             :             }
     227             :         }
     228             :     }
     229             : 
     230           0 :     if ( bInsertPrefix )
     231             :     {
     232           0 :         rtl::OStringBuffer aIns;
     233           0 :         aIns.append(cAccDel).append(RTL_CONSTASCII_STRINGPARAM("..."));
     234           0 :         aCutPath.insert(nBegin, aIns.makeStringAndClear());
     235             :     }
     236             : 
     237           0 :     return aCutPath.makeStringAndClear();
     238             : }
     239             : 
     240       36692 : FSysError DirEntry::ImpParseName( const rtl::OString& rPfad )
     241             : {
     242             : #if defined(WNT)
     243             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
     244             : 
     245             :     // put single names onto stack
     246             :     String aPfad(rtl::OStringToOUString(rPfad, osl_getThreadTextEncoding()));
     247             :     DirEntryStack   aStack;
     248             : 
     249             :     do
     250             :     {
     251             :         // split name before first "\\",
     252             :         // if '\\' is at beginning of string, name is set to '\\'.
     253             :         // ":" also splits the string and belongs to the name.
     254             : 
     255             :         // search first occurance of '\\', '/' or ':'
     256             :         sal_uInt16 nPos;
     257             :         for ( nPos = 0;
     258             :               nPos < aPfad.Len() &&                             //?O
     259             :                   aPfad.GetChar(nPos) != '\\' && aPfad.GetChar(nPos) != '/' &&      //?O
     260             :                   aPfad.GetChar(nPos) != ':';                               //?O
     261             :               nPos++ )
     262             :             /* do nothing */;
     263             : 
     264             :         // is the name a UNC pathname?
     265             :         if ( nPos == 0 && aPfad.Len() > 1 &&
     266             :              ( ( aPfad.GetChar(0) == '\\' && aPfad.GetChar(1) == '\\' ) ||
     267             :                ( aPfad.GetChar(0) == '/' && aPfad.GetChar(1) == '/' ) ) )
     268             :         {
     269             :             for ( nPos = 2; aPfad.Len() > nPos; ++nPos )
     270             :                 if ( aPfad.GetChar(nPos) == '\\' || aPfad.GetChar(nPos) == '/' )
     271             :                     break;
     272             :             aName = rtl::OUStringToOString(aPfad.Copy( 2, nPos-2 ), osl_getThreadTextEncoding());
     273             :             aStack.Push( new DirEntry( aName, FSYS_FLAG_ABSROOT ) );
     274             :         }
     275             :         // Is the name the root of the current drive?
     276             :         else if ( nPos == 0 && aPfad.Len() > 0 &&
     277             :                   ( aPfad.GetChar(0) == '\\' || aPfad.GetChar(0) == '/' ) )
     278             :         {
     279             :             // Push root directory of current drive
     280             :             aStack.Push( new DirEntry( FSYS_FLAG_ABSROOT ) );
     281             :         }
     282             :         else
     283             :         {
     284             :             // Is the name itself a drive?
     285             :             if ( nPos < aPfad.Len() && aPfad.GetChar(nPos) == ':' )
     286             :             {
     287             :                 aName = rtl::OUStringToOString(aPfad.Copy( 0, nPos + 1 ), osl_getThreadTextEncoding());
     288             : 
     289             :                 // Is the name the root of a drive?
     290             :                 if ( (nPos + 1) < aPfad.Len() &&
     291             :                      ( aPfad.GetChar(nPos+1) == '\\' || aPfad.GetChar(nPos+1) == '/' ) )
     292             :                 {
     293             :                     // unsupported if stack not empty or is a Novell format (URL)
     294             :                     if ( !aStack.Empty() || aName.getLength() > 2 )
     295             :                     {
     296             :                         aName = rPfad;
     297             :                         return FSYS_ERR_MISPLACEDCHAR;
     298             :                     }
     299             :                     // Push as root directory of drive
     300             :                     aStack.Push( new DirEntry( aName, FSYS_FLAG_ABSROOT ) );
     301             :                 }
     302             :                 else
     303             :                 {
     304             :                     // clear stack if another drive is currently on it
     305             :                     if ( !aStack.Empty() )
     306             :                     {
     307             :                         rtl::OString aThis(aStack.Bottom()->aName);
     308             :                         aThis = aThis.toAsciiLowerCase();
     309             :                         rtl::OString aOther(aName);
     310             :                         aOther = aOther.toAsciiLowerCase();
     311             :                         if (aThis.compareTo(aOther) != 0)
     312             :                             aStack.Clear();
     313             :                     }
     314             : 
     315             :                     if ( aStack.Empty() )
     316             :                         aStack.Push( new DirEntry( aName, FSYS_FLAG_RELROOT ) );
     317             :                 }
     318             :             }
     319             :             // Name is not a drive
     320             :             else
     321             :             {
     322             :                 // split the name without seperator
     323             :                 aName = rtl::OUStringToOString(aPfad.Copy( 0, nPos ), osl_getThreadTextEncoding());
     324             : 
     325             :                 // Is the name the current directory?
     326             :                 if ( aName == "." )
     327             :                     /* do nothing */;
     328             : 
     329             :                 // Is the name the parent directory?
     330             :                 else if ( aName == ".." )
     331             :                 {
     332             :                     // Is the stack empty, or a parent (or relative root) on it?
     333             :                     if ( ( aStack.Empty() ) ||
     334             :                          ( aStack.Top()->eFlag == FSYS_FLAG_PARENT ) ||
     335             :                          ( aStack.Top()->eFlag == FSYS_FLAG_RELROOT ) )
     336             :                         // add leading parent to stack
     337             :                         aStack.Push( new DirEntry( FSYS_FLAG_PARENT ) );
     338             : 
     339             :                     // It's an absolute root path
     340             :                     else if ( aStack.Top()->eFlag == FSYS_FLAG_ABSROOT )
     341             :                     {
     342             :                         // Then there is no parent directory
     343             :                         aName = rPfad;
     344             :                         return FSYS_ERR_NOTEXISTS;
     345             :                     }
     346             :                     else
     347             :                         // Otherwise removee parent TOS
     348             :                         delete aStack.Pop();
     349             :                 }
     350             : 
     351             :                 else
     352             :                 {
     353             :                     // add ordinary entries to the stack
     354             :                     DirEntry *pNew = new DirEntry( aName, FSYS_FLAG_NORMAL );
     355             :                     if ( !pNew->IsValid() )
     356             :                     {
     357             :                         aName = rPfad;
     358             :                         ErrCode eErr = pNew->GetError();
     359             :                         delete pNew;
     360             :                         return eErr;
     361             :                     }
     362             :                     aStack.Push( pNew );
     363             :                 }
     364             :             }
     365             :         }
     366             : 
     367             :         // determine remainder of path
     368             :         aPfad.Erase( 0, nPos + 1 );
     369             :         while ( aPfad.Len() && ( aPfad.GetChar(0) == '\\' || aPfad.GetChar(0) == '/' ) )
     370             :             aPfad.Erase( 0, 1 );
     371             :     }
     372             :     while ( aPfad.Len() );
     373             : 
     374             :     sal_uIntPtr nErr = ERRCODE_NONE;
     375             :     // Set the main entry itself
     376             :     if ( aStack.Empty() )
     377             :     {
     378             :         eFlag = FSYS_FLAG_CURRENT;
     379             :         aName = rtl::OString();
     380             :     }
     381             :     else
     382             :     {
     383             :         eFlag = aStack.Top()->eFlag;
     384             :         aName = aStack.Top()->aName;
     385             :         nErr = aStack.Top()->nError;
     386             :         delete aStack.Pop();
     387             :     }
     388             : 
     389             :     // pop parent entry from stack
     390             :     DirEntry** pTemp = &pParent;
     391             :     while ( !aStack.Empty() )
     392             :     {
     393             :         *pTemp = aStack.Pop();
     394             : 
     395             :         // set member pointer to the pParent of the member's own parent
     396             :         pTemp = &( (*pTemp)->pParent );
     397             :     }
     398             : 
     399             :     // Does this describe a volume?
     400             :     if ( !pParent && eFlag == FSYS_FLAG_RELROOT && !aName.isEmpty() )
     401             :         eFlag = FSYS_FLAG_VOLUME;
     402             : 
     403             :     // use full aName if error code was set
     404             :     if ( nErr )
     405             :         aName = rPfad;
     406             :     return nErr;
     407             : #else
     408             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
     409             : 
     410             :     // Add single names to the stack
     411       36692 :     DirEntryStack   aStack;
     412       36692 :     rtl::OString aPfad(rPfad);
     413      242282 :     do
     414             :     {
     415             :         // split names on the first occurance of "/",
     416             :         // if '/' starts the string, it itself becomes the name
     417             : 
     418             :         // search first occurance of "/"
     419             :         sal_uInt16 nPos;
     420     3626943 :         for ( nPos = 0;
     421     3384661 :               nPos < aPfad.getLength() && aPfad[nPos] != '/';
     422             :               nPos++ )
     423             :             /* do nothing */;
     424             : 
     425             :         // is the name the root of the current drive?
     426      242282 :         if ( nPos == 0 && !aPfad.isEmpty() && ( aPfad[0] == '/' ) )
     427             :         {
     428             :             // push root directory of current drive to stack
     429       25261 :             aStack.Push( new DirEntry( FSYS_FLAG_ABSROOT ) );
     430             :         }
     431             :         else
     432             :         {
     433             :             // split name without seperator
     434      217021 :             aName = aPfad.copy(0, nPos);
     435             : 
     436             :             // Is the name the current directory?
     437      217021 :             if ( aName == "." )
     438             :                 /* do nothing */;
     439             : 
     440             : #ifdef UNX
     441             :             // Is the name the user's home directory?
     442      217021 :             else if ( aName == "~" )
     443             :             {
     444           0 :                 DirEntry aHome( String( (const char *) getenv( "HOME" ), osl_getThreadTextEncoding()) );
     445           0 :                 for ( sal_uInt16 n = aHome.Level(); n; --n )
     446           0 :                     aStack.Push( new DirEntry( aHome[ (sal_uInt16) n-1 ] ) );
     447             :             }
     448             : #endif
     449             :             // Is the name the current parent directory?
     450      217021 :             else if ( aName == ".." )
     451             :             {
     452             :                 // Is the stack empty, or a parent (or relative root) is on top?
     453           0 :                 if ( ( aStack.Empty() ) || ( aStack.Top()->eFlag == FSYS_FLAG_PARENT ) )
     454             :                 {
     455             :                     // push leading parents to stack
     456           0 :                     aStack.Push( new DirEntry(rtl::OString(), FSYS_FLAG_PARENT) );
     457             :                 }
     458             :                 // Is the name an absolute root?
     459           0 :                 else if ( aStack.Top()->eFlag == FSYS_FLAG_ABSROOT )
     460             :                 {
     461             :                     // they do not have parent directories
     462           0 :                     return FSYS_ERR_NOTEXISTS;
     463             :                 }
     464             :                 else
     465             :                     // otherwise remove parent TOS from stack
     466           0 :                     delete aStack.Pop();
     467             :             }
     468             :             else
     469             :             {
     470      217021 :                 DirEntry *pNew = NULL;
     471             :                 // push ordinary entries on the stack
     472      217021 :                 pNew = new DirEntry( aName, FSYS_FLAG_NORMAL );
     473      217021 :                 if ( !pNew->IsValid() )
     474             :                 {
     475           0 :                     aName = rPfad;
     476           0 :                     ErrCode eErr = pNew->GetError();
     477           0 :                     delete pNew;
     478           0 :                     return eErr;
     479             :                 }
     480      217021 :                 aStack.Push( pNew );
     481             :             }
     482             :         }
     483             : 
     484             :         // get remainder of path
     485      242282 :         aPfad = nPos < aPfad.getLength()
     486      484564 :             ? aPfad.copy(nPos + 1) : rtl::OString();
     487      484564 :         while ( !aPfad.isEmpty() && ( aPfad[0] == '/' ) )
     488           0 :             aPfad = aPfad.copy(1);
     489             :     }
     490      242282 :     while (!aPfad.isEmpty());
     491             : 
     492             :     // insert main entry itself
     493       36692 :     if ( aStack.Empty() )
     494             :     {
     495           0 :         eFlag = FSYS_FLAG_CURRENT;
     496           0 :         aName = rtl::OString();
     497             :     }
     498             :     else
     499             :     {
     500       36692 :         eFlag = aStack.Top()->eFlag;
     501       36692 :         aName = aStack.Top()->aName;
     502       36692 :         delete aStack.Pop();
     503             :     }
     504             : 
     505             :     // Get parent entries from stack
     506       36692 :     DirEntry** pTemp = &pParent;
     507      278974 :     while ( !aStack.Empty() )
     508             :     {
     509      205590 :         *pTemp = aStack.Pop();
     510      205590 :         pTemp = &( (*pTemp)->pParent );
     511             :     }
     512             : 
     513       36692 :     return FSYS_ERR_OK;
     514             : #endif
     515             : }
     516             : 
     517      546288 : static FSysPathStyle GetStyle( FSysPathStyle eStyle )
     518             : {
     519      546288 :     if ( eStyle == FSYS_STYLE_HOST || eStyle == FSYS_STYLE_DETECT )
     520       52015 :         return DEFSTYLE;
     521             :     else
     522      494273 :         return eStyle;
     523             : }
     524             : 
     525             : /** Convert name to match OS norm. */
     526      217021 : void DirEntry::ImpTrim()
     527             : {
     528             :     // Do not trim wildcard characters
     529      651063 :     if ( ( aName.indexOf( '*' ) != -1 ) ||
     530      217021 :          ( aName.indexOf( '?' ) != -1 ) ||
     531      217021 :          ( aName.indexOf( ';' ) != -1 ) )
     532      217021 :         return;
     533             : 
     534             : #if defined(WNT)
     535             :     if ( aName.getLength() > 254 )
     536             :     {
     537             :         nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
     538             :         aName = aName.copy(254);
     539             :     }
     540             : #else
     541      217021 :     if ( aName.getLength() > 250 )
     542             :     {
     543           0 :         nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
     544           0 :         aName = aName.copy(250);
     545             :     }
     546             : #endif
     547             : }
     548             : 
     549      217021 : DirEntry::DirEntry( const rtl::OString& rName, DirEntryFlag eDirFlag ) :
     550             : #ifdef FEAT_FSYS_DOUBLESPEED
     551             :             pStat( 0 ),
     552             : #endif
     553      217021 :             aName( rName )
     554             : {
     555             :     DBG_CTOR( DirEntry, ImpCheckDirEntry );
     556             : 
     557      217021 :     pParent         = NULL;
     558      217021 :     eFlag           = eDirFlag;
     559      217021 :     nError          = FSYS_ERR_OK;
     560             : 
     561      217021 :     ImpTrim();
     562      217021 : }
     563             : 
     564      524864 : DirEntry::DirEntry( const DirEntry& rOrig ) :
     565             : #ifdef FEAT_FSYS_DOUBLESPEED
     566           0 :             pStat( rOrig.pStat ? new FileStat(*rOrig.pStat) : 0 ),
     567             : #endif
     568      524864 :             aName( rOrig.aName )
     569             : {
     570             :     DBG_CTOR( DirEntry, ImpCheckDirEntry );
     571             : 
     572      524864 :     eFlag           = rOrig.eFlag;
     573      524864 :     nError          = rOrig.nError;
     574             : 
     575      524864 :     if ( rOrig.pParent )
     576             :     {
     577      457997 :         pParent = new DirEntry( *rOrig.pParent );
     578             :     }
     579             :     else
     580             :     {
     581       66867 :         pParent = NULL;
     582             :     }
     583      524864 : }
     584             : 
     585       36692 : DirEntry::DirEntry( const String& rInitName, FSysPathStyle eStyle )
     586             : #ifdef FEAT_FSYS_DOUBLESPEED
     587       36692 :             : pStat( 0 )
     588             : #endif
     589             : {
     590             :     DBG_CTOR( DirEntry, ImpCheckDirEntry );
     591             : 
     592             :     (void) eStyle; // only used for DBG_UTIL
     593             : 
     594       36692 :     pParent         = NULL;
     595             : 
     596             :     // faster check for empty string
     597       36692 :     if ( !rInitName.Len())
     598             :     {
     599           0 :         eFlag                   = FSYS_FLAG_CURRENT;
     600           0 :         nError                  = FSYS_ERR_OK;
     601       36692 :         return;
     602             :     }
     603             : 
     604       36692 :     rtl::OString aTmpName(rtl::OUStringToOString(rInitName, osl_getThreadTextEncoding()));
     605       36692 :     if (aTmpName.matchIgnoreAsciiCase(rtl::OString(RTL_CONSTASCII_STRINGPARAM("file:"))))
     606             :     {
     607             :         DBG_WARNING( "File URLs are not permitted but accepted" );
     608           0 :         aTmpName = rtl::OUStringToOString(INetURLObject( rInitName ).PathToFileName(), osl_getThreadTextEncoding());
     609             : #ifdef DBG_UTIL
     610             :                 eStyle = FSYS_STYLE_HOST;
     611             : #endif
     612             :     }
     613             :     else
     614             :     {
     615       36692 :         ::rtl::OUString aTmp;
     616       36692 :         ::rtl::OUString aOInitName;
     617       36692 :         if ( FileBase::getFileURLFromSystemPath( OUString( rInitName ), aTmp ) == FileBase::E_None )
     618             :         {
     619       36692 :             aOInitName = OUString( rInitName );
     620       36692 :             aTmpName = rtl::OUStringToOString(aOInitName, osl_getThreadTextEncoding());
     621       36692 :         }
     622             : 
     623             : #ifdef DBG_UTIL
     624             :         if (eStyle == FSYS_STYLE_HOST && aTmpName.indexOf( "://" ) != -1)
     625             :         {
     626             :             rtl::OStringBuffer aErr(RTL_CONSTASCII_STRINGPARAM("DirEntries akzeptieren nur File URLS: "));
     627             :             aErr.append(aTmpName);
     628             :             DBG_WARNING(aErr.getStr());
     629             :         }
     630             : #endif
     631             :     }
     632             : 
     633       36692 :     nError  = ImpParseName( aTmpName );
     634             : 
     635       36692 :     if ( nError != FSYS_ERR_OK )
     636           0 :         eFlag = FSYS_FLAG_INVALID;
     637             : }
     638             : 
     639           0 : DirEntry::DirEntry( const rtl::OString& rInitName, FSysPathStyle eStyle )
     640             : #ifdef FEAT_FSYS_DOUBLESPEED
     641           0 :             : pStat( 0 )
     642             : #endif
     643             : {
     644             :     DBG_CTOR( DirEntry, ImpCheckDirEntry );
     645             : 
     646             :     (void) eStyle; // only used for DBG_UTIL
     647             : 
     648           0 :     pParent         = NULL;
     649             : 
     650             :     // faster check for empty string
     651           0 :     if ( rInitName.isEmpty() )
     652             :     {
     653           0 :         eFlag                   = FSYS_FLAG_CURRENT;
     654           0 :         nError                  = FSYS_ERR_OK;
     655           0 :         return;
     656             :     }
     657             : 
     658           0 :     rtl::OString aTmpName( rInitName );
     659           0 :     if (aTmpName.matchIgnoreAsciiCase(rtl::OString(RTL_CONSTASCII_STRINGPARAM("file:"))))
     660             :     {
     661             :         DBG_WARNING( "File URLs are not permitted but accepted" );
     662           0 :         aTmpName = rtl::OUStringToOString(INetURLObject( rInitName ).PathToFileName(), osl_getThreadTextEncoding());
     663             : #ifdef DBG_UTIL
     664             :         eStyle = FSYS_STYLE_HOST;
     665             : #endif
     666             :     }
     667             : #ifdef DBG_UTIL
     668             :     else
     669             :     {
     670             :         if( eStyle == FSYS_STYLE_HOST && rInitName.indexOf("://") != -1 )
     671             :         {
     672             :             rtl::OStringBuffer aErr(RTL_CONSTASCII_STRINGPARAM("DirEntries akzeptieren nur File URLS: "));
     673             :             aErr.append(rInitName);
     674             :             DBG_WARNING(aErr.getStr());
     675             :         }
     676             :     }
     677             : #endif
     678             : 
     679           0 :     nError  = ImpParseName( aTmpName );
     680             : 
     681           0 :     if ( nError != FSYS_ERR_OK )
     682           0 :         eFlag = FSYS_FLAG_INVALID;
     683             : }
     684             : 
     685       26630 : DirEntry::DirEntry( DirEntryFlag eDirFlag )
     686             : #ifdef FEAT_FSYS_DOUBLESPEED
     687       26630 :             : pStat( 0 )
     688             : #endif
     689             : {
     690             :     DBG_CTOR( DirEntry, ImpCheckDirEntry );
     691             : 
     692       26630 :     eFlag           = eDirFlag;
     693       26630 :     nError          = ( eFlag == FSYS_FLAG_INVALID ) ? FSYS_ERR_UNKNOWN : FSYS_ERR_OK;
     694       26630 :     pParent         = NULL;
     695       26630 : }
     696             : 
     697     1610414 : DirEntry::~DirEntry()
     698             : {
     699             :     DBG_DTOR( DirEntry, ImpCheckDirEntry );
     700             : 
     701      805207 :     delete pParent;
     702             : #ifdef FEAT_FSYS_DOUBLESPEED
     703      805207 :     delete pStat;
     704             : #endif
     705             : 
     706      805207 : }
     707             : 
     708       22204 : const DirEntry* DirEntry::ImpGetTopPtr() const
     709             : {
     710             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
     711             : 
     712       22204 :     const DirEntry *pTemp = this;
     713      135235 :     while ( pTemp->pParent )
     714       90827 :         pTemp = pTemp->pParent;
     715             : 
     716       22204 :     return pTemp;
     717             : }
     718             : 
     719       11493 : DirEntry* DirEntry::ImpGetTopPtr()
     720             : {
     721             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
     722             : 
     723       11493 :     DirEntry *pTemp = this;
     724       23788 :     while ( pTemp->pParent )
     725         802 :         pTemp = pTemp->pParent;
     726             : 
     727       11493 :     return pTemp;
     728             : }
     729             : 
     730           0 : DirEntry* DirEntry::ImpChangeParent( DirEntry* pNewParent, sal_Bool bNormalize )
     731             : {
     732             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
     733             : 
     734           0 :     DirEntry *pTemp = pParent;
     735           0 :     if ( bNormalize && pNewParent &&
     736           0 :          pNewParent->eFlag == FSYS_FLAG_RELROOT && pNewParent->aName.isEmpty() )
     737             :     {
     738           0 :         pParent = 0;
     739           0 :         delete pNewParent;
     740             :     }
     741             :     else
     742           0 :         pParent = pNewParent;
     743             : 
     744           0 :     return pTemp;
     745             : }
     746             : 
     747        1183 : sal_Bool DirEntry::Exists( FSysAccess nAccess ) const
     748             : {
     749        1183 :     static osl::Mutex aLocalMutex;
     750        1183 :     osl::MutexGuard aGuard( aLocalMutex );
     751        1183 :         if ( !IsValid() )
     752           0 :                 return sal_False;
     753             : 
     754             : #if defined WNT
     755             :     // get special file names from system
     756             :     if ( aName.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("CLOCK$")) ||
     757             :            aName.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("CON")) ||
     758             :            aName.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("AUX")) ||
     759             :            aName.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("COM1")) ||
     760             :            aName.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("COM2")) ||
     761             :            aName.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("COM3")) ||
     762             :            aName.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("COM4")) ||
     763             :            aName.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("LPT1")) ||
     764             :            aName.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("LPT2")) ||
     765             :            aName.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("LPT3")) ||
     766             :            aName.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("NUL")) ||
     767             :            aName.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("PRN")) )
     768             :         return sal_True;
     769             : #endif
     770             : 
     771             :         FSysFailOnErrorImpl();
     772        1183 :         DirEntryKind eKind = FileStat( *this, nAccess ).GetKind();
     773        1183 :         if ( eKind & ( FSYS_KIND_FILE | FSYS_KIND_DIR ) )
     774             :         {
     775         329 :             return sal_True;
     776             :         }
     777             : 
     778             : #if defined WNT
     779             :         if ( 0 != ( eKind & FSYS_KIND_DEV ) )
     780             :         {
     781             :             return DRIVE_EXISTS( ImpGetTopPtr()->aName[0] );
     782             :         }
     783             : #endif
     784             : 
     785         854 :         return 0 != ( eKind & ( FSYS_KIND_FILE | FSYS_KIND_DIR ) );
     786             : }
     787             : 
     788           0 : sal_Bool DirEntry::First()
     789             : {
     790             :     FSysFailOnErrorImpl();
     791             : 
     792           0 :         String    aUniPathName( GetPath().GetFull() );
     793           0 :         rtl::OString aPathName(rtl::OUStringToOString(aUniPathName, osl_getThreadTextEncoding()));
     794             : 
     795           0 :         DIR *pDir = opendir(aPathName.getStr());
     796           0 :         if ( pDir )
     797             :         {
     798           0 :                 WildCard aWildeKarte(rtl::OStringToOUString(CMP_LOWER(aName), osl_getThreadTextEncoding()));
     799           0 :                 for ( dirent* pEntry = readdir( pDir );
     800             :                           pEntry;
     801             :                           pEntry = readdir( pDir ) )
     802             :                 {
     803           0 :                         rtl::OString aFound(pEntry->d_name);
     804           0 :                         if (aWildeKarte.Matches(rtl::OStringToOUString(CMP_LOWER(aFound), osl_getThreadTextEncoding())))
     805             :                         {
     806           0 :                                 aName = aFound;
     807           0 :                                 closedir( pDir );
     808           0 :                                 return sal_True;
     809             :                         }
     810           0 :                 }
     811           0 :                 closedir( pDir );
     812             :         }
     813           0 :         return sal_False;
     814             : }
     815             : 
     816      247713 : String DirEntry::GetFull( FSysPathStyle eStyle, sal_Bool bWithDelimiter,
     817             :                           sal_uInt16 nMaxChars ) const
     818             : {
     819             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
     820             : 
     821      247713 :     rtl::OStringBuffer aBuf;
     822      247713 :     eStyle = GetStyle( eStyle );
     823      247713 :     if ( pParent )
     824             :     {
     825      246560 :         if ( ( pParent->eFlag == FSYS_FLAG_ABSROOT ||
     826             :                pParent->eFlag == FSYS_FLAG_RELROOT ||
     827             :                pParent->eFlag == FSYS_FLAG_VOLUME ) )
     828             :         {
     829       32275 :             aBuf.append(rtl::OUStringToOString(pParent->GetName( eStyle ), osl_getThreadTextEncoding()));
     830       32275 :             aBuf.append(rtl::OUStringToOString(GetName( eStyle ), osl_getThreadTextEncoding()));
     831             :         }
     832             :         else
     833             :         {
     834      214285 :             aBuf.append(rtl::OUStringToOString(pParent->GetFull( eStyle ), osl_getThreadTextEncoding()));
     835      214285 :             aBuf.append(ACCESSDELIM_C(eStyle));
     836      214285 :             aBuf.append(rtl::OUStringToOString(GetName( eStyle ), osl_getThreadTextEncoding()));
     837             :         }
     838             :     }
     839             :     else
     840             :     {
     841        1153 :         aBuf.append(rtl::OUStringToOString(GetName(eStyle), osl_getThreadTextEncoding()));
     842             :     }
     843             : 
     844             :     //! Hack
     845      247713 :     if ( bWithDelimiter )
     846           0 :         if ( aBuf[aBuf.getLength()-1] != ACCESSDELIM_C(eStyle) )
     847           0 :             aBuf.append(ACCESSDELIM_C(eStyle));
     848             : 
     849      247713 :     rtl::OString aRet = aBuf.makeStringAndClear();
     850             : 
     851             :     // HACK
     852      247713 :     if ( nMaxChars < STRING_MAXLEN )
     853           0 :         aRet = ImplCutPath( aRet, nMaxChars, ACCESSDELIM_C(eStyle) );
     854             : 
     855      247713 :     return rtl::OStringToOUString(aRet, osl_getThreadTextEncoding());
     856             : }
     857             : 
     858          40 : DirEntry DirEntry::GetPath() const
     859             : {
     860             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
     861             : 
     862          40 :     if ( pParent )
     863          40 :         return DirEntry( *pParent );
     864             : 
     865           0 :     return DirEntry();
     866             : }
     867             : 
     868           0 : String DirEntry::GetExtension( char cSep ) const
     869             : {
     870             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
     871             : 
     872           0 :     const char *p0 = aName.getStr();
     873           0 :     const char *p1 = p0 + aName.getLength() - 1;
     874           0 :     while ( p1 >= p0 && *p1 != cSep )
     875           0 :         p1--;
     876             : 
     877           0 :     if ( p1 >= p0 )
     878             :     {
     879             :         // found a cSep at position p1
     880             :         return rtl::OStringToOUString(aName.copy(p1 - p0 + 1),
     881           0 :             osl_getThreadTextEncoding());
     882             :     }
     883             : 
     884           0 :     return String();
     885             : }
     886             : 
     887           0 : String DirEntry::GetBase( char cSep ) const
     888             : {
     889             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
     890             : 
     891           0 :     const char *p0 = aName.getStr();
     892           0 :     const char *p1 = p0 + aName.getLength() - 1;
     893           0 :     while ( p1 >= p0 && *p1 != cSep )
     894           0 :         p1--;
     895             : 
     896           0 :     if ( p1 >= p0 )
     897             :     {
     898             :         // found a cSep at position p1
     899             :         return rtl::OStringToOUString(aName.copy(0, p1 - p0),
     900           0 :             osl_getThreadTextEncoding());
     901             : 
     902             :     }
     903             :     // did not find a cSep
     904           0 :     return rtl::OStringToOUString(aName, osl_getThreadTextEncoding());
     905             : }
     906             : 
     907      288640 : String DirEntry::GetName( FSysPathStyle eStyle ) const
     908             : {
     909             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
     910             : 
     911      288640 :     rtl::OStringBuffer aRet;
     912      288640 :     eStyle = GetStyle( eStyle );
     913             : 
     914      288640 :     switch( eFlag )
     915             :     {
     916             :         case FSYS_FLAG_PARENT:
     917           0 :             aRet.append(ACTPARENT(eStyle));
     918           0 :             break;
     919             : 
     920             :         case FSYS_FLAG_ABSROOT:
     921             :         {
     922       32275 :             aRet.append(aName);
     923       32275 :             aRet.append(ACCESSDELIM_C(eStyle));
     924       32275 :             break;
     925             :         }
     926             : 
     927             :         case FSYS_FLAG_INVALID:
     928             :         case FSYS_FLAG_VOLUME:
     929             :         {
     930           0 :             aRet.append(aName);
     931           0 :             break;
     932             :         }
     933             : 
     934             :         case FSYS_FLAG_RELROOT:
     935         691 :             if ( aName.isEmpty() )
     936             :             {
     937         691 :                 aRet.append(ACTCURRENT(eStyle));
     938         691 :                 break;
     939             :             }
     940             : 
     941             :         default:
     942      255674 :             aRet.append(aName);
     943      255674 :             break;
     944             :     }
     945             : 
     946             :     return rtl::OStringToOUString(aRet.makeStringAndClear(),
     947      288640 :         osl_getThreadTextEncoding());
     948             : }
     949             : 
     950      116042 : bool DirEntry::IsAbs() const
     951             : {
     952             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
     953             : 
     954             : #ifdef UNX
     955      116042 :     return ( pParent ? pParent->IsAbs() : eFlag == FSYS_FLAG_ABSROOT );
     956             : #else
     957             :     return ( pParent ? pParent->IsAbs() : eFlag == FSYS_FLAG_ABSROOT && !aName.isEmpty() );
     958             : #endif
     959             : }
     960             : 
     961           0 : String DirEntry::CutName( FSysPathStyle eStyle )
     962             : {
     963             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
     964             : 
     965           0 :     eStyle = GetStyle( eStyle );
     966             : 
     967           0 :     String aOldName( GetName( eStyle ) );
     968             : 
     969           0 :     if ( pParent )
     970             :     {
     971           0 :         DirEntry *pOldParent = pParent;
     972           0 :         if ( pOldParent )
     973             :         {
     974           0 :             pParent = pOldParent->pParent;
     975           0 :             eFlag = pOldParent->eFlag;
     976           0 :             aName = pOldParent->aName;
     977           0 :             pOldParent->pParent = NULL;
     978           0 :             delete pOldParent;
     979             :         }
     980             :         else
     981             :         {
     982           0 :             eFlag = FSYS_FLAG_CURRENT;
     983           0 :             aName = rtl::OString();
     984             :         }
     985             :     }
     986             :     else
     987             :     {
     988           0 :         eFlag = FSYS_FLAG_CURRENT;
     989           0 :         aName = rtl::OString();
     990           0 :         delete pParent;
     991           0 :         pParent = NULL;
     992             :     }
     993             : 
     994           0 :     return aOldName;
     995             : }
     996             : 
     997         630 : sal_Bool DirEntry::operator==( const DirEntry& rEntry ) const
     998             : {
     999             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
    1000             : 
    1001             :     // test whether the contents are textual the same
    1002             : 
    1003         630 :     if ( nError && ( nError == rEntry.nError ) )
    1004           0 :         return sal_True;
    1005         630 :     if ( nError || rEntry.nError ||
    1006             :          ( eFlag == FSYS_FLAG_INVALID ) ||
    1007             :          ( rEntry.eFlag == FSYS_FLAG_INVALID ) )
    1008           0 :         return sal_False;
    1009             : 
    1010         630 :     const DirEntry *pThis = (DirEntry *)this;
    1011         630 :     const DirEntry *pWith = (DirEntry *)&rEntry;
    1012        1260 :     while( pThis && pWith && (pThis->eFlag == pWith->eFlag) )
    1013             :     {
    1014         630 :         if ( CMP_LOWER(pThis->aName) != CMP_LOWER(pWith->aName) )
    1015         630 :             break;
    1016           0 :         pThis = pThis->pParent;
    1017           0 :         pWith = pWith->pParent;
    1018             :     }
    1019             : 
    1020         630 :     return ( !pThis && !pWith );
    1021             : }
    1022             : 
    1023       12101 : DirEntry& DirEntry::operator=( const DirEntry& rEntry )
    1024             : {
    1025             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
    1026             : 
    1027       12101 :     if ( this == &rEntry )
    1028           0 :         return *this;
    1029       12101 :     if ( rEntry.nError != FSYS_ERR_OK ) {
    1030             :         OSL_FAIL("Zuweisung mit invalidem DirEntry");
    1031           0 :         nError = rEntry.nError;
    1032           0 :         return *this;
    1033             :     }
    1034             : 
    1035             :     // set name and type, but keep refs
    1036       12101 :     aName                       = rEntry.aName;
    1037       12101 :     eFlag                       = rEntry.eFlag;
    1038       12101 :     nError                      = FSYS_ERR_OK;
    1039             : 
    1040       12101 :     DirEntry *pOldParent = pParent;
    1041       12101 :     if ( rEntry.pParent )
    1042       12101 :         pParent = new DirEntry( *rEntry.pParent );
    1043             :     else
    1044           0 :         pParent = NULL;
    1045             : 
    1046       12101 :     if ( pOldParent )
    1047       11310 :         delete pOldParent;
    1048       12101 :     return *this;
    1049             : }
    1050             : 
    1051       11102 : DirEntry DirEntry::operator+( const DirEntry& rEntry ) const
    1052             : {
    1053             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
    1054             : #ifdef DBG_UTIL
    1055             :         static sal_Bool bTested = sal_False;
    1056             :         if ( !bTested )
    1057             :         {
    1058             :                 bTested = sal_True;
    1059             :                 FSysTest();
    1060             :         }
    1061             : #endif
    1062             : 
    1063       11102 :         const DirEntry *pEntryTop = rEntry.ImpGetTopPtr();
    1064       11102 :         const DirEntry *pThisTop = ImpGetTopPtr();
    1065             : 
    1066       22204 :     if (
    1067           0 :         (eFlag == FSYS_FLAG_RELROOT && aName.isEmpty()) ||
    1068             :         (
    1069       11102 :          (!pEntryTop->aName.isEmpty()  ||
    1070           0 :           ((rEntry.Level()>1)?(rEntry[rEntry.Level()-2].aName.equalsIgnoreAsciiCase(RFS_IDENTIFIER)):sal_False))
    1071             :           &&
    1072             :          (pEntryTop->eFlag == FSYS_FLAG_ABSROOT ||
    1073             :           pEntryTop->eFlag == FSYS_FLAG_RELROOT ||
    1074             :           pEntryTop->eFlag == FSYS_FLAG_VOLUME)
    1075             :         )
    1076             :        )
    1077             :     {
    1078           0 :                 return rEntry;
    1079             :     }
    1080             : 
    1081             :     // something + "." (=> pEntryTop == &rEntry)
    1082       11102 :     if (pEntryTop->eFlag == FSYS_FLAG_RELROOT && pEntryTop->aName.isEmpty())
    1083             :     {
    1084             :         DBG_ASSERT( pEntryTop == &rEntry, "DirEntry::op+ buggy" );
    1085           0 :         return *this;
    1086             :     }
    1087             : 
    1088             :     // root += ".." (=> impossible)
    1089       11102 :         if ( pEntryTop->eFlag == FSYS_FLAG_PARENT && pThisTop == this &&
    1090             :                 ( eFlag == FSYS_FLAG_ABSROOT ) )
    1091           0 :                 return DirEntry( FSYS_FLAG_INVALID );
    1092             : 
    1093             :         // something += abs (=> only append device if existant)
    1094       11102 :         if ( pEntryTop->eFlag == FSYS_FLAG_ABSROOT )
    1095             :         {
    1096           0 :                 rtl::OString aDevice;
    1097           0 :                 if ( pThisTop->eFlag == FSYS_FLAG_ABSROOT )
    1098           0 :                     aDevice = pThisTop->aName;
    1099           0 :                 DirEntry aRet = rEntry;
    1100           0 :                 if ( !aDevice.isEmpty() )
    1101           0 :                     aRet.ImpGetTopPtr()->aName = aDevice;
    1102           0 :                 return aRet;
    1103             :         }
    1104             : 
    1105             :         // something += ".." (=> break apart)
    1106       11102 :         if ( eFlag == FSYS_FLAG_NORMAL && pEntryTop->eFlag == FSYS_FLAG_PARENT )
    1107             :         {
    1108           0 :                 String aConcated( GetFull() );
    1109           0 :                 aConcated += ACCESSDELIM_C(FSYS_STYLE_HOST);
    1110           0 :                 aConcated += rEntry.GetFull();
    1111           0 :                 return DirEntry( aConcated );
    1112             :         }
    1113             : 
    1114             :         // otherwise append consecutively
    1115       11102 :         DirEntry aRet( rEntry );
    1116       11102 :         DirEntry *pTop = aRet.ImpGetTopPtr();
    1117       11102 :         pTop->pParent = new DirEntry( *this );
    1118             : 
    1119       11102 :         return aRet;
    1120             : }
    1121             : 
    1122       11102 : DirEntry &DirEntry::operator+=( const DirEntry& rEntry )
    1123             : {
    1124             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
    1125             : 
    1126       11102 :     return *this = *this + rEntry;
    1127             : }
    1128             : 
    1129          61 : String DirEntry::GetAccessDelimiter( FSysPathStyle eFormatter )
    1130             : {
    1131          61 :         return rtl::OUString( ACCESSDELIM_C( GetStyle( eFormatter ) ) );
    1132             : }
    1133             : 
    1134        1382 : void DirEntry::SetExtension( const String& rExtension, char cSep )
    1135             : {
    1136             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
    1137             : 
    1138             :     // do not set extensions for drives
    1139        1382 :     if(eFlag == FSYS_FLAG_ABSROOT)
    1140             :     {
    1141           0 :         nError = FSYS_ERR_NOTSUPPORTED;
    1142        1382 :         return;
    1143             :     }
    1144             : 
    1145        1382 :     rtl::OStringBuffer aBuf(aName);
    1146             : 
    1147             :     // search cSep within aName
    1148        1382 :     const sal_Char *p0 = aBuf.getStr();
    1149        1382 :     const sal_Char *p1 = p0 + aBuf.getLength() - 1;
    1150        8800 :     while ( p1 >= p0 && *p1 != cSep )
    1151        6036 :         p1--;
    1152        1382 :     if ( p1 >= p0 )
    1153             :     {
    1154             :         // found a cSep on position p1
    1155             : 
    1156             :         sal_Int32 n = static_cast<sal_Int32>(
    1157         752 :                 p1 - p0 + 1 - ( rExtension.Len() ? 0 : 1 ));
    1158             : 
    1159         752 :         aBuf.remove(n, aBuf.getLength()-n);
    1160             :     }
    1161         630 :     else if ( rExtension.Len() )
    1162             :     {
    1163             :         // no cSep was found
    1164         630 :         aBuf.append(cSep);
    1165             :     }
    1166             : 
    1167             :     aBuf.append(rtl::OUStringToOString(rExtension,
    1168        1382 :         osl_getThreadTextEncoding()));
    1169             : 
    1170        1382 :     aName = aBuf.makeStringAndClear();
    1171             : }
    1172             : 
    1173           0 : void DirEntry::SetName( const String& rName, FSysPathStyle eFormatter )
    1174             : {
    1175             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
    1176             : 
    1177           0 :     if ( eFormatter == FSYS_STYLE_HOST || eFormatter == FSYS_STYLE_DETECT )
    1178           0 :         eFormatter = DEFSTYLE;
    1179           0 :     sal_Char cAccDelim(ACCESSDELIM_C(eFormatter));
    1180             : 
    1181           0 :     if ( (eFlag != FSYS_FLAG_NORMAL) ||
    1182           0 :          (aName.indexOf(':') != -1) ||
    1183           0 :          (aName.indexOf(cAccDelim) != -1) )
    1184             :     {
    1185           0 :         eFlag = FSYS_FLAG_INVALID;
    1186             :     }
    1187             :     else
    1188             :     {
    1189           0 :         aName = rtl::OUStringToOString(rName, osl_getThreadTextEncoding());
    1190             :     }
    1191           0 : }
    1192             : 
    1193         391 : sal_Bool DirEntry::Find( const String& rPfad, char cDelim )
    1194             : {
    1195             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
    1196             : 
    1197         391 :     if ( ImpGetTopPtr()->eFlag == FSYS_FLAG_ABSROOT )
    1198          62 :             return sal_True;
    1199             : 
    1200         329 :     sal_Bool bWild = aName.indexOf( '*' ) != -1 ||
    1201         329 :                      aName.indexOf( '?' ) != -1;
    1202             : 
    1203         329 :     if ( !cDelim )
    1204         329 :             cDelim = SEARCHDELIM(DEFSTYLE)[0];
    1205             : 
    1206             :     rtl::OString aThis = rtl::OStringBuffer()
    1207         658 :         .append(ACCESSDELIM_C(DEFSTYLE))
    1208             :         .append(rtl::OUStringToOString(GetFull(),
    1209         987 :             osl_getThreadTextEncoding()))
    1210         329 :         .makeStringAndClear();
    1211         329 :     sal_Int32 nIndex = 0;
    1212         814 :     do
    1213             :     {
    1214             :         rtl::OStringBuffer aPath(rtl::OUStringToOString(rPfad,
    1215        1143 :             osl_getThreadTextEncoding()).getToken( 0, cDelim, nIndex ));
    1216             : 
    1217        1143 :         if ( aPath.getLength() )
    1218             :         {
    1219        1143 :             if (aPath[aPath.getLength()-1] == ACCESSDELIM_C(DEFSTYLE))
    1220         221 :                 aPath.remove(aPath.getLength()-1, 1);
    1221        1143 :             aPath.append(aThis);
    1222             :             DirEntry aEntry(rtl::OStringToOUString(
    1223        1143 :                 aPath.makeStringAndClear(), osl_getThreadTextEncoding()));
    1224        2286 :             if ( aEntry.ToAbs() &&
    1225        1143 :                      ( ( !bWild && aEntry.Exists() ) || ( bWild && aEntry.First() ) ) )
    1226             :             {
    1227         329 :                     (*this) = aEntry;
    1228         329 :                     return sal_True;
    1229        1143 :             }
    1230        1143 :         }
    1231             :     }
    1232             :     while ( nIndex >= 0 );
    1233           0 :     return sal_False;
    1234             : }
    1235             : 
    1236             : #ifndef UNX
    1237             : DirEntry DirEntry::GetDevice() const
    1238             : {
    1239             :         DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
    1240             : 
    1241             :         const DirEntry *pTop = ImpGetTopPtr();
    1242             : 
    1243             :         if ( ( pTop->eFlag == FSYS_FLAG_ABSROOT || pTop->eFlag == FSYS_FLAG_RELROOT ) &&
    1244             :                  !pTop->aName.isEmpty() )
    1245             :                 return DirEntry( pTop->aName, FSYS_FLAG_VOLUME );
    1246             :         else
    1247             :                 return DirEntry( rtl::OString(), FSYS_FLAG_INVALID );
    1248             : }
    1249             : #endif
    1250             : 
    1251        9874 : String DirEntry::GetSearchDelimiter( FSysPathStyle eFormatter )
    1252             : {
    1253        9874 :     return rtl::OStringToOUString(rtl::OString(SEARCHDELIM(GetStyle(eFormatter))), osl_getThreadTextEncoding());
    1254             : }
    1255             : 
    1256             : namespace
    1257             : {
    1258             :     struct TempNameBase_Impl : public rtl::Static< DirEntry, TempNameBase_Impl > {};
    1259             : }
    1260             : 
    1261          40 : DirEntry DirEntry::TempName( DirEntryKind eKind ) const
    1262             : {
    1263             :         // use base-temp-dir if necessary
    1264          40 :         const DirEntry &rEntry = TempNameBase_Impl::get();
    1265          40 :         if ( !pParent && FSYS_FLAG_CURRENT != rEntry.eFlag && FSYS_FLAG_ABSROOT != eFlag )
    1266             :         {
    1267           0 :                 DirEntry aFactory( rEntry );
    1268           0 :                 aFactory += GetName();
    1269           0 :                 return aFactory.TempName();
    1270             :         }
    1271             : 
    1272          40 :         rtl::OString aDirName;
    1273             :         char *ret_val;
    1274             :         size_t i;
    1275             : 
    1276             :         // determine Directory, Prefix and Extension
    1277             :         char pfx[6];
    1278             :         char ext[5];
    1279             :         const char *dir;
    1280          40 :         const char *pWild = strchr( aName.getStr(), '*' );
    1281          40 :         if ( !pWild )
    1282          40 :             pWild = strchr( aName.getStr(), '?' );
    1283             : 
    1284          40 :         if ( pWild )
    1285             :         {
    1286           0 :             if ( pParent )
    1287           0 :                 aDirName = rtl::OUStringToOString(pParent->GetFull(), osl_getThreadTextEncoding());
    1288           0 :             strncpy( pfx, aName.getStr(), Min( (int)5, (int)(pWild-aName.getStr()) ) );
    1289           0 :             pfx[ pWild-aName.getStr() ] = 0;
    1290           0 :             const char *pExt = strchr( pWild, '.' );
    1291           0 :             if ( pExt )
    1292             :             {
    1293           0 :                 strncpy( ext, pExt, 4 );
    1294           0 :                 ext[4] = 0;
    1295             :             }
    1296             :             else
    1297           0 :                 strcpy( ext, ".tmp" );
    1298             :         }
    1299             :         else
    1300             :         {
    1301          40 :             aDirName = rtl::OUStringToOString(GetFull(), osl_getThreadTextEncoding());
    1302          40 :             strcpy( pfx, "lo" );
    1303          40 :             strcpy( ext, ".tmp" );
    1304             :         }
    1305          40 :         dir = aDirName.getStr();
    1306             : 
    1307             :         char sBuf[_MAX_PATH];
    1308          40 :         if ( eFlag == FSYS_FLAG_CURRENT || ( !pParent && pWild ) )
    1309           0 :             dir = TempDirImpl(sBuf);
    1310             : 
    1311          40 :         DirEntry aRet(FSYS_FLAG_INVALID);
    1312          40 :         i = strlen(dir);
    1313             :         // need to add ?\\? + prefix + number + pid + .ext + '\0'
    1314             : #       define TMPNAME_SIZE  ( 1 + 5 + 5 + 10 + 4 + 1 )
    1315          40 :         ret_val = new char[i + TMPNAME_SIZE ];
    1316          40 :         if (ret_val)
    1317             :         {
    1318          40 :             strcpy(ret_val,dir);
    1319             : 
    1320             :             /* Make sure directory ends with a separator    */
    1321             : #if defined(WNT)
    1322             :             if ( i>0 && ret_val[i-1] != '\\' && ret_val[i-1] != '/' &&
    1323             :                  ret_val[i-1] != ':')
    1324             :                 ret_val[i++] = '\\';
    1325             : #elif defined UNX
    1326          40 :             if (i>0 && ret_val[i-1] != '/')
    1327          40 :                 ret_val[i++] = '/';
    1328             : #else
    1329             : #error unknown operating system
    1330             : #endif
    1331             : 
    1332          40 :             strncpy(ret_val + i, pfx, 5);
    1333          40 :             ret_val[i + 5] = '\0';      /* strncpy doesn't put a 0 if more  */
    1334          40 :             i = strlen(ret_val);        /* than 'n' chars.          */
    1335             : 
    1336             :             /* Prefix can have 5 chars, leaving 3 for numbers. 26 ** 3 == 17576
    1337             :              * Welcome to the 21st century, we can have longer filenames now ;)
    1338             :              * New format: pfx + "5 char milli/micro second res" + "current pid" + ".tmp"
    1339             :              */
    1340             : #if (defined MSC || defined __MINGW32__) && defined WNT
    1341             :             /* Milliseconds !! */
    1342             :             static unsigned long u = GetTickCount();
    1343             :             unsigned long mypid = static_cast<unsigned long>(_getpid());
    1344             : #else
    1345             :             /* Microseconds !! */
    1346          40 :             static unsigned long u = clock();
    1347          40 :             unsigned long mypid = static_cast<unsigned long>(getpid());
    1348             : #endif
    1349          80 :             for ( unsigned long nOld = u; ++u != nOld; ) /* Hae??? */
    1350             :             {
    1351          40 :                 u %= 100000;  /* on *NIX repeats every 100ms, maybe less if CLOCKS_PER_SEC > 10^6 */
    1352          40 :                 snprintf(ret_val+i, TMPNAME_SIZE, "%05lu%lu", u, mypid);
    1353             : 
    1354          40 :                 strcat(ret_val,ext);
    1355             : 
    1356          40 :                 if ( FSYS_KIND_FILE == eKind )
    1357             :                 {
    1358           0 :                     SvFileStream aStream( String( ret_val, osl_getThreadTextEncoding()),
    1359           0 :                                             STREAM_WRITE|STREAM_SHARE_DENYALL );
    1360           0 :                     if ( aStream.IsOpen() )
    1361             :                     {
    1362           0 :                         aStream.Seek( STREAM_SEEK_TO_END );
    1363           0 :                         if ( 0 == aStream.Tell() )
    1364             :                         {
    1365           0 :                                 aRet = DirEntry( String( ret_val, osl_getThreadTextEncoding()));
    1366             :                                 break;
    1367             :                         }
    1368           0 :                         aStream.Close();
    1369           0 :                     }
    1370             :                 }
    1371             :                 else
    1372             :                 {
    1373             :                     // Redirect
    1374          40 :                     String aRetVal(ret_val, osl_getThreadTextEncoding());
    1375          40 :                     String aRedirected (aRetVal);
    1376          40 :                     if ( FSYS_KIND_DIR == eKind )
    1377             :                     {
    1378           0 :                         if (0 == _mkdir(rtl::OUStringToOString(aRedirected, osl_getThreadTextEncoding()).getStr()))
    1379             :                         {
    1380           0 :                             aRet = DirEntry( aRetVal );
    1381             :                             break;
    1382             :                         }
    1383             :                     }
    1384             :                     else
    1385             :                     {
    1386             : #if defined(UNX)
    1387          40 :                         if (access(rtl::OUStringToOString(aRedirected, osl_getThreadTextEncoding()).getStr(), F_OK))
    1388             :                         {
    1389          40 :                                 aRet = DirEntry( aRetVal );
    1390             :                                 break;
    1391             :                         }
    1392             : #else
    1393             :                         struct stat aStat;
    1394             :                         if (stat(rtl::OUStringToOString(aRedirected, osl_getThreadTextEncoding()).getStr(), &aStat))
    1395             :                         {
    1396             :                             aRet = DirEntry( aRetVal );
    1397             :                             break;
    1398             :                         }
    1399             : #endif
    1400          40 :                     }
    1401             :                 }
    1402             :             }
    1403             : 
    1404          40 :             delete[] ret_val;
    1405          40 :             ret_val = 0;
    1406             :         }
    1407             : 
    1408          40 :         return aRet;
    1409             : }
    1410             : 
    1411           0 : const DirEntry &DirEntry::operator[]( sal_uInt16 nParentLevel ) const
    1412             : {
    1413             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
    1414             : 
    1415             :     //TPF: maybe to be implemented (FastFSys)
    1416             : 
    1417           0 :     const DirEntry *pRes = this;
    1418           0 :     while ( pRes && nParentLevel-- )
    1419           0 :         pRes = pRes->pParent;
    1420             : 
    1421           0 :     return *pRes;
    1422             : }
    1423             : 
    1424           0 : sal_Bool DirEntry::MakeDir( sal_Bool bSloppy ) const
    1425             : {
    1426             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
    1427             : 
    1428             :         // fast check if exists
    1429           0 :         if ( FileStat( *this ).IsKind( FSYS_KIND_DIR ) )
    1430           0 :                 return sal_True;
    1431           0 :         if ( bSloppy && pParent )
    1432           0 :                  if ( FileStat( *pParent ).IsKind( FSYS_KIND_DIR ) )
    1433           0 :                           return sal_True;
    1434             : 
    1435           0 :         const DirEntry *pNewDir = bSloppy ? pParent : this;
    1436           0 :         if ( pNewDir )
    1437             :         {
    1438             :                 // Create path to dir
    1439           0 :                 if ( pNewDir->pParent && !pNewDir->pParent->MakeDir(sal_False) )
    1440           0 :                         return sal_False;
    1441             : 
    1442             :                 // create dir ourselves
    1443           0 :                 if ( pNewDir->eFlag == FSYS_FLAG_ABSROOT ||
    1444             :                          pNewDir->eFlag == FSYS_FLAG_VOLUME )
    1445           0 :                         return sal_True;
    1446             :                 else
    1447             :                 {
    1448             :                         //? nError = ???
    1449           0 :                         if ( FileStat( *pNewDir ).IsKind( FSYS_KIND_DIR ) )
    1450           0 :                                 return sal_True;
    1451             :                         else
    1452             :                         {
    1453             :                                 FSysFailOnErrorImpl();
    1454           0 :                                 String aDirName(pNewDir->GetFull());
    1455           0 :                                 rtl::OString bDirName(rtl::OUStringToOString(aDirName, osl_getThreadTextEncoding()));
    1456             : 
    1457             : #ifdef WIN32
    1458             :                                 SetLastError(0);
    1459             : #endif
    1460           0 :                                 sal_Bool bResult = (0 == _mkdir(bDirName.getStr()));
    1461           0 :                                 if ( !bResult )
    1462             :                                 {
    1463             : #ifdef WIN32
    1464             :                                     ((DirEntry *)this)->SetError( Sys2SolarError_Impl(  GetLastError() ) );
    1465             : #else
    1466           0 :                                     ((DirEntry *)this)->SetError( Sys2SolarError_Impl(  errno ) );
    1467             : #endif
    1468             :                                 }
    1469             : 
    1470           0 :                                 return bResult;
    1471             :                         }
    1472             :                 }
    1473             :         }
    1474           0 :         return sal_True;
    1475             : }
    1476             : 
    1477         630 : FSysError DirEntry::CopyTo( const DirEntry& rDest, FSysAction nActions ) const
    1478             : {
    1479             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
    1480             : 
    1481         630 :         if ( FSYS_ACTION_COPYFILE != (nActions & FSYS_ACTION_COPYFILE) )
    1482             : #ifdef UNX
    1483             :     {
    1484             :         // create hardlink
    1485             :         // redirection missing
    1486           0 :         rtl::OString aThis(rtl::OUStringToOString(GetFull(), osl_getThreadTextEncoding()));
    1487           0 :         rtl::OString aDest(rtl::OUStringToOString(rDest.GetFull(), osl_getThreadTextEncoding()));
    1488           0 :         if (link(aThis.getStr(), aDest.getStr()) == -1)
    1489           0 :             return Sys2SolarError_Impl(  errno );
    1490             :         else
    1491           0 :             return FSYS_ERR_OK;
    1492             :     }
    1493             : #else
    1494             :         return FSYS_ERR_NOTSUPPORTED;
    1495             : #endif
    1496             : 
    1497         630 :         FileCopier fc(*this, rDest);
    1498         630 :         return fc.Execute(nActions);
    1499             : }
    1500             : 
    1501             : #if defined WNT || defined UNX
    1502          40 : FSysError DirEntry::MoveTo( const DirEntry& rNewName ) const
    1503             : {
    1504             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
    1505             : 
    1506          40 :     DirEntry aDest(rNewName);
    1507          40 :     FileStat aDestStat(rNewName);
    1508          40 :     if ( aDestStat.IsKind(FSYS_KIND_DIR ) )
    1509             :     {
    1510           0 :         aDest += DirEntry(rtl::OStringToOUString(aName, osl_getThreadTextEncoding()));
    1511             :     }
    1512          40 :     if ( aDest.Exists() )
    1513             :     {
    1514           0 :         return FSYS_ERR_ALREADYEXISTS;
    1515             :     }
    1516             : 
    1517             :         FSysFailOnErrorImpl();
    1518          40 :         String aFrom( GetFull() );
    1519             : 
    1520          40 :         String aTo( aDest.GetFull() );
    1521             : 
    1522          40 :         rtl::OString bFrom(rtl::OUStringToOString(aFrom, osl_getThreadTextEncoding()));
    1523          40 :         rtl::OString bTo(rtl::OUStringToOString(aTo, osl_getThreadTextEncoding()));
    1524             : 
    1525             : #ifdef WNT
    1526             :         // MoveTo nun atomar
    1527             :         SetLastError(0);
    1528             : 
    1529             :         DirEntry aFromDevice(rtl::OStringToOUString(bFrom, osl_getThreadTextEncoding()));
    1530             :         DirEntry aToDevice(rtl::OStringToOUString(bTo,osl_getThreadTextEncoding()));
    1531             :         aFromDevice.ToAbs();
    1532             :         aToDevice.ToAbs();
    1533             :         aFromDevice=aFromDevice.GetDevice();
    1534             :         aToDevice=aToDevice.GetDevice();
    1535             : 
    1536             :         if (aFromDevice==aToDevice)
    1537             :         {
    1538             :             // same device, use intra-device-move with MoveFile
    1539             :             MoveFile( bFrom.getStr(), bTo.getStr() );
    1540             :             // Note: MoveFile is buggy for cross-device operations.
    1541             :             // Return value is TRUE, even if the operation was only partially successful.
    1542             :             // MoveFile has varying behavior between differing NT-versions.
    1543             :             return Sys2SolarError_Impl( GetLastError() );
    1544             :         }
    1545             :         else
    1546             :         {
    1547             :             // Not the same device, use inter-device-move with copy/delete
    1548             :             FSysError nCopyError = CopyTo(rNewName, FSYS_ACTION_COPYFILE);
    1549             : 
    1550             :             DirEntry aKill(rtl::OStringToOUString(bTo, osl_getThreadTextEncoding()));
    1551             :             FileStat aKillStat(String(rtl::OStringToOUString(bTo, osl_getThreadTextEncoding())));
    1552             :             if ( aKillStat.IsKind(FSYS_KIND_DIR ) )
    1553             :             {
    1554             :                 aKill += String(rtl::OStringToOUString(aName, osl_getThreadTextEncoding()));
    1555             :             }
    1556             : 
    1557             :             if (nCopyError==FSYS_ERR_OK)
    1558             :             {
    1559             :                 if (Kill()==FSYS_ERR_OK)
    1560             :                 {
    1561             :                     return FSYS_ERR_OK;
    1562             :                 }
    1563             :                 else
    1564             :                 {
    1565             :                     aKill.Kill();
    1566             :                     return FSYS_ERR_ACCESSDENIED;
    1567             :                 }
    1568             :             }
    1569             :             else
    1570             :             {
    1571             :                 aKill.Kill();
    1572             :                 return nCopyError;
    1573             :             }
    1574             :         }
    1575             : #else
    1576             :         // #68639#
    1577             :         // on some nfs connections rename with from == to
    1578             :         // leads to destruction of file
    1579          40 :         if ( ( aFrom != aTo ) && ( 0 != rename( bFrom.getStr(), bTo.getStr() ) ) )
    1580             : #if !defined(UNX)
    1581             :             return Sys2SolarError_Impl( GetLastError() );
    1582             : #else
    1583             :         {
    1584           0 :                 if( errno == EXDEV )
    1585             :                 // simple rename does not work cross device
    1586             :                 {
    1587           0 :                         FILE *fpIN  = fopen( bFrom.getStr(), "r" );
    1588           0 :                         FILE *fpOUT = fopen( bTo.getStr(), "w" );
    1589           0 :                         if( fpIN && fpOUT )
    1590             :                         {
    1591             :                                 char pBuf[ 16384 ];
    1592           0 :                                 int nBytes, nWritten, nErr = 0;
    1593           0 :                                 errno = 0;
    1594           0 :                                 while( ( nBytes = fread( pBuf, 1, sizeof(pBuf), fpIN ) ) && ! nErr )
    1595             :                                 {
    1596           0 :                                     nWritten = fwrite( pBuf, 1, nBytes, fpOUT );
    1597             :                                     // Error in fwrite ?
    1598           0 :                                     if( nWritten < nBytes )
    1599             :                                     {
    1600           0 :                                         nErr = errno;
    1601           0 :                                         break;
    1602             :                                     }
    1603             :                                 }
    1604           0 :                                 fclose( fpIN );
    1605           0 :                                 fclose( fpOUT );
    1606           0 :                                 if ( nErr )
    1607             :                                 {
    1608           0 :                                     unlink( bTo.getStr() );
    1609           0 :                                     return Sys2SolarError_Impl( nErr );
    1610             :                                 }
    1611             :                                 else
    1612             :                                 {
    1613           0 :                                     unlink( bFrom.getStr() );
    1614           0 :                                 }
    1615             :                         }
    1616             :                         else
    1617             :                         {
    1618           0 :                             if ( fpIN )
    1619           0 :                                 fclose( fpIN );
    1620           0 :                             if ( fpOUT )
    1621           0 :                                 fclose( fpOUT );
    1622           0 :                             return Sys2SolarError_Impl( EXDEV );
    1623             :                         }
    1624             :                 }
    1625             :                 else
    1626             :                 {
    1627           0 :                     return Sys2SolarError_Impl( errno );
    1628             :                 }
    1629             :         }
    1630             : #endif
    1631             : #endif
    1632             : 
    1633             : // For the WNT case we always return already above, so avoid warning
    1634             : // C4702: unreachable code. Possibly also in non-WNT cases we always
    1635             : // return already above, but gcc apparently doesn't mind.
    1636             : #ifndef WNT
    1637          40 :         return ERRCODE_NONE;
    1638             : #endif
    1639             : }
    1640             : 
    1641             : #endif
    1642             : 
    1643         732 : FSysError DirEntry::Kill(  FSysAction nActions ) const
    1644             : {
    1645             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
    1646             : 
    1647         732 :         FSysError eError = FSYS_ERR_OK;
    1648             :         FSysFailOnErrorImpl();
    1649             : 
    1650             :         // Terminate name string with two '0'
    1651         732 :         String aTmpName( GetFull() );
    1652         732 :         rtl::OString bTmpName(rtl::OUStringToOString(aTmpName, osl_getThreadTextEncoding()));
    1653             : 
    1654         732 :         char *pName = new char[bTmpName.getLength()+2];
    1655         732 :         strcpy( pName, bTmpName.getStr() );
    1656         732 :         pName[bTmpName.getLength()+1] = (char) 0;
    1657             : 
    1658             :         // delete read-only files as well
    1659         732 :         sal_Bool isReadOnly = FileStat::GetReadOnlyFlag(*this);
    1660         732 :         if (isReadOnly)
    1661             :         {
    1662           0 :             FileStat::SetReadOnlyFlag(*this, sal_False);
    1663             :         }
    1664             : 
    1665             :         // directory?
    1666         732 :         if ( FileStat( *this ).IsKind(FSYS_KIND_DIR) )
    1667             :         {
    1668             :                 // Delete recursively?
    1669           0 :                 if ( FSYS_ACTION_RECURSIVE == (nActions & FSYS_ACTION_RECURSIVE) )
    1670             :                 {
    1671           0 :                         Dir aDir( *this, FSYS_KIND_DIR|FSYS_KIND_FILE );
    1672           0 :                         for ( sal_uInt16 n = 0; eError == FSYS_ERR_OK && n < aDir.Count(); ++n )
    1673             :                         {
    1674           0 :                                 const DirEntry &rSubDir = aDir[n];
    1675           0 :                                 DirEntryFlag flag = rSubDir.GetFlag();
    1676           0 :                                 if ( flag != FSYS_FLAG_CURRENT && flag != FSYS_FLAG_PARENT )
    1677           0 :                                         eError = rSubDir.Kill(nActions);
    1678           0 :                         }
    1679             :                 }
    1680             : 
    1681             :                 // remove Dir myself
    1682             : #ifdef WIN32
    1683             :                 SetLastError(0);
    1684             : #endif
    1685           0 :                 if ( eError == FSYS_ERR_OK && 0 != _rmdir( (char*) pName ) )
    1686             :                 {
    1687             :                         // Change CWD if deletion failed
    1688             : #ifdef WIN32
    1689             :                     eError = Sys2SolarError_Impl( GetLastError() );
    1690             : #else
    1691           0 :                     eError = Sys2SolarError_Impl( errno );
    1692             : #endif
    1693           0 :                         if ( eError )
    1694             :                         {
    1695           0 :                                 GetPath().SetCWD();
    1696             : #ifdef WIN32
    1697             :                                 SetLastError(0);
    1698             : #endif
    1699           0 :                                 if (_rmdir( (char*) pName) != 0)
    1700             :                                 {
    1701             : #ifdef WIN32
    1702             :                                     eError = Sys2SolarError_Impl( GetLastError() );
    1703             : #else
    1704           0 :                                     eError = Sys2SolarError_Impl( errno );
    1705             : #endif
    1706             :                                 }
    1707             :                                 else
    1708             :                                 {
    1709           0 :                                     eError = FSYS_ERR_OK;
    1710             :                                 }
    1711             :                         }
    1712             :                 }
    1713             :         }
    1714             :         else
    1715             :         {
    1716         732 :                 if ( FSYS_ACTION_USERECYCLEBIN == (nActions & FSYS_ACTION_USERECYCLEBIN) )
    1717             :                 {
    1718             : #if defined(WNT)
    1719             :                         SHFILEOPSTRUCT aOp;
    1720             :                         aOp.hwnd = 0;
    1721             :                         aOp.wFunc = FO_DELETE;
    1722             :                         aOp.pFrom = pName;
    1723             :                         aOp.pTo = 0;
    1724             :                         aOp.fFlags = FOF_ALLOWUNDO|FOF_SILENT|FOF_NOCONFIRMATION;
    1725             :                         aOp.hNameMappings = 0;
    1726             :                         aOp.lpszProgressTitle = 0;
    1727             :                         eError = Sys2SolarError_Impl( SHFileOperation( &aOp ) );
    1728             : #else
    1729           0 :                         eError = ERRCODE_IO_NOTSUPPORTED;
    1730             : #endif
    1731             :                 }
    1732             :                 else
    1733             :                 {
    1734             : #ifdef WIN32
    1735             :                     SetLastError(0);
    1736             : #endif
    1737         732 :                     if ( 0 != _unlink( (char*) pName ) )
    1738             :                     {
    1739             : #ifdef WIN32
    1740             :                         eError = Sys2SolarError_Impl( GetLastError() );
    1741             : #else
    1742          32 :                         eError = Sys2SolarError_Impl( errno );
    1743             : #endif
    1744             :                     }
    1745             :                     else
    1746             :                     {
    1747         700 :                         eError = ERRCODE_NONE;
    1748             :                     }
    1749             :                 }
    1750             :         }
    1751             : 
    1752             :         // restore original read-only flag upon error
    1753         732 :         if ( isReadOnly && (eError!=ERRCODE_NONE) )
    1754             :         {
    1755           0 :             FileStat::SetReadOnlyFlag(*this, isReadOnly);
    1756             :         }
    1757             : 
    1758         732 :         delete[] pName;
    1759         732 :         return eError;
    1760             : }
    1761             : 
    1762             : /** Check if rSubEntry is (in)directly beneath *this */
    1763           0 : sal_Bool DirEntry::Contains( const DirEntry &rSubEntry ) const
    1764             : {
    1765             :     DBG_ASSERT( IsAbs() && rSubEntry.IsAbs(), "must be absolute entries" );
    1766             : 
    1767           0 :         sal_uInt16 nThisLevel = Level();
    1768           0 :     sal_uInt16 nSubLevel = rSubEntry.Level();
    1769           0 :     if ( nThisLevel < nSubLevel )
    1770             :     {
    1771           0 :         for ( ; nThisLevel; --nThisLevel, --nSubLevel )
    1772           0 :             if ( (*this)[nThisLevel-1] != rSubEntry[nSubLevel-1] )
    1773           0 :                 return sal_False;
    1774           0 :         return sal_True;
    1775             :     }
    1776           0 :     return sal_False;
    1777             : }
    1778             : 
    1779           0 : sal_uInt16 DirEntry::Level() const
    1780             : {
    1781             :     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
    1782             : 
    1783           0 :     sal_uInt16 nLevel = 0;
    1784           0 :     const DirEntry *pRes = this;
    1785           0 :     while ( pRes )
    1786             :     {
    1787           0 :         pRes = pRes->pParent;
    1788           0 :         nLevel++;
    1789             :     }
    1790             : 
    1791           0 :     return nLevel;
    1792             : }
    1793             : 
    1794      231459 : sal_Bool DirEntry::IsValid() const
    1795             : {
    1796      231459 :         return (nError == FSYS_ERR_OK);
    1797             : }
    1798             : 
    1799             : #if defined(DBG_UTIL)
    1800             : void FSysTest()
    1801             : {
    1802             : }
    1803             : #endif
    1804             : 
    1805             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10