summaryrefslogtreecommitdiff
path: root/tools/source/fsys/dirent.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'tools/source/fsys/dirent.cxx')
-rw-r--r--tools/source/fsys/dirent.cxx3213
1 files changed, 3213 insertions, 0 deletions
diff --git a/tools/source/fsys/dirent.cxx b/tools/source/fsys/dirent.cxx
new file mode 100644
index 000000000000..1bd43bffc4e7
--- /dev/null
+++ b/tools/source/fsys/dirent.cxx
@@ -0,0 +1,3213 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_tools.hxx"
+
+
+#if !defined UNX
+#include <io.h>
+#include <process.h>
+#endif
+
+#if defined(UNX) || defined(OS2)
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <tools/debug.hxx>
+#include <tools/list.hxx>
+#include "comdep.hxx"
+#include <tools/fsys.hxx>
+#define _TOOLS_HXX
+#include <tools/urlobj.hxx>
+
+#ifdef UNX
+#define _MAX_PATH 260
+#endif
+#include <tools/stream.hxx>
+
+#ifndef _VOS_MUTEX_HXX
+#include <vos/mutex.hxx>
+#endif
+
+#include <osl/file.hxx>
+#include <rtl/instance.hxx>
+
+
+using namespace osl;
+using namespace rtl;
+
+int ApiRet2ToSolarError_Impl( int nApiRet );
+
+//--------------------------------------------------------------------
+int Sys2SolarError_Impl( int nSysErr )
+{
+ switch ( nSysErr )
+ {
+#ifdef WNT
+ case NO_ERROR: return ERRCODE_NONE;
+ case ERROR_INVALID_FUNCTION: return ERRCODE_IO_GENERAL;
+ case ERROR_FILE_NOT_FOUND: return ERRCODE_IO_NOTEXISTS;
+ case ERROR_PATH_NOT_FOUND: return ERRCODE_IO_NOTEXISTSPATH;
+ case ERROR_TOO_MANY_OPEN_FILES: return ERRCODE_IO_TOOMANYOPENFILES;
+ case ERROR_ACCESS_DENIED: return ERRCODE_IO_ACCESSDENIED;
+ case ERROR_INVALID_HANDLE: return ERRCODE_IO_GENERAL;
+ case ERROR_NOT_ENOUGH_MEMORY: return ERRCODE_IO_OUTOFMEMORY;
+ case ERROR_INVALID_BLOCK: return ERRCODE_IO_GENERAL;
+// case ERROR_BAD_ENVIRONMENT: return ERRCODE_IO_;
+ case ERROR_BAD_FORMAT: return ERRCODE_IO_WRONGFORMAT;
+ case ERROR_INVALID_ACCESS: return ERRCODE_IO_ACCESSDENIED;
+// case ERROR_INVALID_DATA: return ERRCODE_IO_;
+ case ERROR_INVALID_DRIVE: return ERRCODE_IO_INVALIDDEVICE;
+ case ERROR_CURRENT_DIRECTORY: return ERRCODE_IO_CURRENTDIR;
+ case ERROR_NOT_SAME_DEVICE: return ERRCODE_IO_NOTSAMEDEVICE;
+// case ERROR_NO_MORE_FILES: return ERRCODE_IO_;
+ case ERROR_WRITE_PROTECT: return ERRCODE_IO_CANTWRITE;
+ case ERROR_BAD_UNIT: return ERRCODE_IO_INVALIDDEVICE;
+ case ERROR_NOT_READY: return ERRCODE_IO_DEVICENOTREADY;
+ case ERROR_BAD_COMMAND: return ERRCODE_IO_GENERAL;
+ case ERROR_CRC: return ERRCODE_IO_BADCRC;
+ case ERROR_BAD_LENGTH: return ERRCODE_IO_INVALIDLENGTH;
+ case ERROR_SEEK: return ERRCODE_IO_CANTSEEK;
+ case ERROR_NOT_DOS_DISK: return ERRCODE_IO_WRONGFORMAT;
+ case ERROR_SECTOR_NOT_FOUND: return ERRCODE_IO_GENERAL;
+ case ERROR_WRITE_FAULT: return ERRCODE_IO_CANTWRITE;
+ case ERROR_READ_FAULT: return ERRCODE_IO_CANTREAD;
+ case ERROR_GEN_FAILURE: return ERRCODE_IO_GENERAL;
+ case ERROR_SHARING_VIOLATION: return ERRCODE_IO_LOCKVIOLATION;
+ case ERROR_LOCK_VIOLATION: return ERRCODE_IO_LOCKVIOLATION;
+ case ERROR_WRONG_DISK: return ERRCODE_IO_INVALIDDEVICE;
+ case ERROR_NOT_SUPPORTED: return ERRCODE_IO_NOTSUPPORTED;
+#else
+ case 0: return ERRCODE_NONE;
+ case ENOENT: return ERRCODE_IO_NOTEXISTS;
+ case EACCES: return ERRCODE_IO_ACCESSDENIED;
+ case EEXIST: return ERRCODE_IO_ALREADYEXISTS;
+ case EINVAL: return ERRCODE_IO_INVALIDPARAMETER;
+ case EMFILE: return ERRCODE_IO_TOOMANYOPENFILES;
+ case ENOMEM: return ERRCODE_IO_OUTOFMEMORY;
+ case ENOSPC: return ERRCODE_IO_OUTOFSPACE;
+#endif
+ }
+
+ DBG_TRACE1( "FSys: unknown system error %d occured", nSysErr );
+ return FSYS_ERR_UNKNOWN;
+}
+
+//--------------------------------------------------------------------
+
+#ifndef BOOTSTRAP
+
+FSysRedirector* FSysRedirector::_pRedirector = 0;
+BOOL FSysRedirector::_bEnabled = TRUE;
+#ifdef UNX
+BOOL bInRedirection = TRUE;
+#else
+BOOL bInRedirection = FALSE;
+#endif
+static NAMESPACE_VOS( OMutex )* pRedirectMutex = 0;
+
+//------------------------------------------------------------------------
+void FSysRedirector::Register( FSysRedirector *pRedirector )
+{
+ if ( pRedirector )
+ pRedirectMutex = new NAMESPACE_VOS( OMutex );
+ else
+ DELETEZ( pRedirectMutex );
+ _pRedirector = pRedirector;
+}
+
+//------------------------------------------------------------------------
+
+void FSysRedirector::DoRedirect( String &rPath )
+{
+ String aURL(rPath);
+
+ // if redirection is disabled or not even registered do nothing
+ if ( !_bEnabled || !pRedirectMutex )
+ return;
+
+ // redirect only removable or remote volumes
+ if ( !IsRedirectable_Impl( ByteString( aURL, osl_getThreadTextEncoding() ) ) )
+ return;
+
+ // Redirection is acessible only by one thread per time
+ // dont move the guard behind the bInRedirection check!!!
+ // think of nested calls (when called from callback)
+ NAMESPACE_VOS( OGuard ) aGuard( pRedirectMutex );
+
+ // if already in redirection, dont redirect
+ if ( bInRedirection )
+ return;
+
+ // dont redirect on nested calls
+ bInRedirection = TRUE;
+
+ // convert to URL
+#ifndef UNX
+ for ( sal_Unicode *p = (sal_Unicode*)aURL.GetBuffer(); *p; ++p )
+ if ( '\\' == *p ) *p = '/';
+ else if ( ':' == *p ) *p = '|';
+#endif
+
+ aURL.Insert( String("file:///", osl_getThreadTextEncoding()), 0 );
+
+ // do redirection
+ Redirector();
+
+ bInRedirection = FALSE;
+ return;
+}
+
+//------------------------------------------------------------------------
+
+FSysRedirector* FSysRedirector::Redirector()
+{
+ if ( !_pRedirector )
+ Register( new FSysRedirector );
+ return _pRedirector;
+}
+
+#endif // BOOTSTRAP
+
+//--------------------------------------------------------------------
+
+class DirEntryStack: public List
+{
+public:
+ DirEntryStack() {};
+ ~DirEntryStack();
+
+ inline void Push( DirEntry *pEntry );
+ inline DirEntry* Pop();
+ inline DirEntry* Top();
+ inline DirEntry* Bottom();
+};
+
+inline void DirEntryStack::Push( DirEntry *pEntry )
+{
+ List::Insert( pEntry, LIST_APPEND );
+}
+
+inline DirEntry* DirEntryStack::Pop()
+{
+ return (DirEntry*) List::Remove( Count() - 1 );
+}
+
+inline DirEntry* DirEntryStack::Top()
+{
+ return (DirEntry*) List::GetObject( Count() - 1 );
+}
+
+inline DirEntry* DirEntryStack::Bottom()
+{
+ return (DirEntry*) List::GetObject( 0 );
+}
+
+//--------------------------------------------------------------------
+
+DBG_NAME( DirEntry );
+
+/*************************************************************************
+|*
+|* DirEntry::~DirEntryStack()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 04.07.91
+|*
+*************************************************************************/
+
+DirEntryStack::~DirEntryStack()
+{
+ while ( Count() )
+ delete Pop();
+}
+
+/*************************************************************************
+|*
+|* ImpCheckDirEntry()
+|*
+|* Beschreibung Pruefung eines DirEntry fuer DBG_UTIL
+|* Parameter void* p Zeiger auf den DirEntry
+|* Return-Wert char* Fehlermeldungs-TExtension oder NULL
+|* Ersterstellung MI 16.07.91
+|* Letzte Aenderung MI 26.05.93
+|*
+*************************************************************************/
+
+#ifdef DBG_UTIL
+const char* ImpCheckDirEntry( const void* p )
+{
+ DirEntry* p0 = (DirEntry*)p;
+
+ if ( p0->pParent )
+ DBG_CHKOBJ( p0->pParent, DirEntry, ImpCheckDirEntry );
+
+ return NULL;
+}
+#endif
+
+/*************************************************************************
+|*
+|* ImplCutPath()
+|*
+|* Beschreibung Fuegt ... ein, damit maximal nMaxChars lang
+|* Ersterstellung MI 06.04.94
+|* Letzte Aenderung DV 24.06.96
+|*
+*************************************************************************/
+
+ByteString ImplCutPath( const ByteString& rStr, USHORT nMax, char cAccDel )
+{
+ USHORT nMaxPathLen = nMax;
+ ByteString aCutPath( rStr );
+ BOOL bInsertPrefix = FALSE;
+ USHORT nBegin = aCutPath.Search( cAccDel );
+
+ if( nBegin == STRING_NOTFOUND )
+ nBegin = 0;
+ else
+ nMaxPathLen += 2; // fuer Prefix <Laufwerk>:
+
+ while( aCutPath.Len() > nMaxPathLen )
+ {
+ USHORT nEnd = aCutPath.Search( cAccDel, nBegin + 1 );
+ USHORT nCount;
+
+ if ( nEnd != STRING_NOTFOUND )
+ {
+ nCount = nEnd - nBegin;
+ aCutPath.Erase( nBegin, nCount );
+ bInsertPrefix = TRUE;
+ }
+ else
+ break;
+ }
+
+ if ( aCutPath.Len() > nMaxPathLen )
+ {
+ for ( USHORT n = nMaxPathLen; n > nMaxPathLen/2; --n )
+ if ( !ByteString(aCutPath.GetChar(n)).IsAlphaNumericAscii() )
+ {
+ aCutPath.Erase( n );
+ aCutPath += "...";
+ break;
+ }
+ }
+
+ if ( bInsertPrefix )
+ {
+ ByteString aIns( cAccDel );
+ aIns += "...";
+ aCutPath.Insert( aIns, nBegin );
+ }
+
+ return aCutPath;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpParseOs2Name()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 23.06.95
+|*
+*************************************************************************/
+
+FSysError DirEntry::ImpParseOs2Name( const ByteString& rPfad, FSysPathStyle eStyle )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ // die einzelnen Namen auf einen Stack packen
+ String aPfad( rPfad, osl_getThreadTextEncoding() );
+ DirEntryStack aStack;
+
+ do
+ {
+ // den Namen vor dem ersten "\\" abspalten,
+ // falls '\\' am Anfang, ist der Name '\\',
+ // der Rest immer ohne die fuehrenden '\\'.
+ // ein ":" trennt ebenfalls, gehoert aber zum Namen
+ // den ersten '\\', '/' oder ':' suchen
+ USHORT nPos;
+ for ( nPos = 0;
+ nPos < aPfad.Len() && //?O
+ aPfad.GetChar(nPos) != '\\' && aPfad.GetChar(nPos) != '/' && //?O
+ aPfad.GetChar(nPos) != ':'; //?O
+ nPos++ )
+ /* do nothing */;
+
+ // ist der Name ein UNC Pathname?
+ if ( nPos == 0 && aPfad.Len() > 1 &&
+ ( ( aPfad.GetChar(0) == '\\' && aPfad.GetChar(1) == '\\' ) ||
+ ( aPfad.GetChar(0) == '/' && aPfad.GetChar(1) == '/' ) ) )
+ {
+ for ( nPos = 2; aPfad.Len() > nPos; ++nPos )
+ if ( aPfad.GetChar(nPos) == '\\' || aPfad.GetChar(nPos) == '/' )
+ break;
+ aName = ByteString( aPfad.Copy( 2, nPos-2 ), osl_getThreadTextEncoding() );
+ aStack.Push( new DirEntry( aName, FSYS_FLAG_ABSROOT, eStyle ) );
+ }
+ // ist der Name die Root des aktuellen Drives?
+ else if ( nPos == 0 && aPfad.Len() > 0 &&
+ ( aPfad.GetChar(0) == '\\' || aPfad.GetChar(0) == '/' ) )
+ {
+ // Root-Directory des aktuellen Drives
+ aStack.Push( new DirEntry( FSYS_FLAG_ABSROOT ) );
+ }
+ else
+ {
+ // ist der Name ein Drive?
+ if ( nPos < aPfad.Len() && aPfad.GetChar(nPos) == ':' )
+ {
+ aName = ByteString( aPfad.Copy( 0, nPos + 1 ), osl_getThreadTextEncoding() );
+
+ // ist der Name die Root des Drives
+ if ( (nPos + 1) < aPfad.Len() &&
+ ( aPfad.GetChar(nPos+1) == '\\' || aPfad.GetChar(nPos+1) == '/' ) )
+ {
+ // schon was auf dem Stack?
+ // oder Novell-Format? (not supported wegen URLs)
+ if ( aStack.Count() || aName.Len() > 2 )
+ {
+ aName = rPfad;
+ return FSYS_ERR_MISPLACEDCHAR;
+ }
+ // Root-Directory des Drive
+ aStack.Push( new DirEntry( aName, FSYS_FLAG_ABSROOT, eStyle ) );
+ }
+ else
+ {
+ // liegt ein anderes Drive auf dem Stack?
+ if ( aStack.Count() &&
+ COMPARE_EQUAL != aStack.Bottom()->aName.CompareIgnoreCaseToAscii(aName) )
+ aStack.Clear();
+
+ // liegt jetzt nichts mehr auf dem Stack?
+ if ( !aStack.Count() )
+ aStack.Push( new DirEntry( aName, FSYS_FLAG_RELROOT, eStyle ) );
+ }
+ }
+
+ // es ist kein Drive
+ else
+ {
+ // den Namen ohne Trenner abspalten
+ aName = ByteString( aPfad.Copy( 0, nPos ), osl_getThreadTextEncoding() );
+
+ // stellt der Name die aktuelle Directory dar?
+ if ( aName == "." )
+ /* do nothing */;
+
+ // stellt der Name die Parent-Directory dar?
+ else if ( aName == ".." )
+ {
+ // ist nichts, ein Parent oder eine relative Root
+ // auf dem Stack?
+ if ( ( aStack.Count() == 0 ) ||
+ ( aStack.Top()->eFlag == FSYS_FLAG_PARENT ) ||
+ ( aStack.Top()->eFlag == FSYS_FLAG_RELROOT ) )
+ // fuehrende Parents kommen auf den Stack
+ aStack.Push( new DirEntry( FSYS_FLAG_PARENT ) );
+
+ // ist es eine absolute Root
+ else if ( aStack.Top()->eFlag == FSYS_FLAG_ABSROOT )
+ {
+ // die hat keine Parent-Directory
+ aName = rPfad;
+ return FSYS_ERR_NOTEXISTS;
+ }
+ else
+ // sonst hebt der Parent den TOS auf
+ delete aStack.Pop();
+ }
+
+ else
+ {
+ if ( eStyle == FSYS_STYLE_FAT )
+ {
+ // ist der Name grundsaetzlich ungueltig?
+ int nPunkte = 0;
+ const char *pChar;
+ for ( pChar = aName.GetBuffer();
+ nPunkte < 2 && *pChar != 0;
+ pChar++ )
+ {
+ if ( *pChar == ';' )
+ nPunkte = 0;
+ else
+ nPunkte += ( *pChar == '.' ) ? 1 : 0;
+ }
+ if ( nPunkte > 1 )
+ {
+ aName = rPfad;
+ return FSYS_ERR_MISPLACEDCHAR;
+ }
+ }
+
+ // normalen Entries kommen auf den Stack
+ DirEntry *pNew = new DirEntry( aName, FSYS_FLAG_NORMAL, eStyle );
+ if ( !pNew->IsValid() )
+ {
+ aName = rPfad;
+ ErrCode eErr = pNew->GetError();
+ delete pNew;
+ return eErr;
+ }
+ aStack.Push( pNew );
+ }
+ }
+ }
+
+ // den Restpfad bestimmen
+ aPfad.Erase( 0, nPos + 1 );
+ while ( aPfad.Len() && ( aPfad.GetChar(0) == '\\' || aPfad.GetChar(0) == '/' ) )
+ aPfad.Erase( 0, 1 );
+ }
+ while ( aPfad.Len() );
+
+ ULONG nErr = ERRCODE_NONE;
+ // Haupt-Entry (selbst) zuweisen
+ if ( aStack.Count() == 0 )
+ {
+ eFlag = FSYS_FLAG_CURRENT;
+ aName.Erase();
+ }
+ else
+ {
+ eFlag = aStack.Top()->eFlag;
+ aName = aStack.Top()->aName;
+ nErr = aStack.Top()->nError;
+ delete aStack.Pop();
+ }
+
+ // die Parent-Entries vom Stack holen
+ DirEntry** pTemp = &pParent; // Zeiger auf den Member pParent setzen
+ while ( aStack.Count() )
+ {
+ *pTemp = aStack.Pop();
+
+ // Zeiger auf den Member pParent des eigenen Parent setzen
+ pTemp = &( (*pTemp)->pParent );
+ }
+
+ // wird damit ein Volume beschrieben?
+ if ( !pParent && eFlag == FSYS_FLAG_RELROOT && aName.Len() )
+ eFlag = FSYS_FLAG_VOLUME;
+
+ // bei gesetztem ErrorCode den Namen komplett "ubernehmen
+ if ( nErr )
+ aName = rPfad;
+ return nErr;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpParseName()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.08.91
+|* Letzte Aenderung MI 26.05.93
+|*
+*************************************************************************/
+
+FSysError DirEntry::ImpParseName( const ByteString& rbInitName,
+ FSysPathStyle eStyle )
+{
+ String rInitName( rbInitName, osl_getThreadTextEncoding() );
+ if ( eStyle == FSYS_STYLE_HOST )
+ eStyle = DEFSTYLE;
+
+ // KI-Division of FSys
+ if ( eStyle == FSYS_STYLE_DETECT )
+ {
+ sal_Unicode cFirst = rInitName.GetChar(0);
+ if ( rInitName.Len() == 2 && rInitName.GetChar(1) == ':' &&
+ ((cFirst >= 'A' && cFirst <= 'Z') ||
+ (cFirst >= 'a' && cFirst <= 'z')))
+ eStyle = FSYS_STYLE_HPFS;
+ else if ( rInitName.Len() > 2 && rInitName.GetChar(1) == ':' )
+ {
+ if ( rInitName.Search( ':', 2 ) == STRING_NOTFOUND )
+ eStyle = FSYS_STYLE_HPFS;
+ else
+ eStyle = FSYS_STYLE_MAC;
+ }
+ else if ( rInitName.Search( '/' ) != STRING_NOTFOUND )
+ eStyle = FSYS_STYLE_BSD;
+ else if ( rInitName.Search( '\\' ) != STRING_NOTFOUND )
+ eStyle = FSYS_STYLE_HPFS;
+ else if ( rInitName.Search( ':' ) != STRING_NOTFOUND )
+ eStyle = FSYS_STYLE_MAC;
+ else
+ eStyle = FSYS_STYLE_HPFS;
+ }
+
+ switch ( eStyle )
+ {
+ case FSYS_STYLE_FAT:
+ case FSYS_STYLE_VFAT:
+ case FSYS_STYLE_HPFS:
+ case FSYS_STYLE_NTFS:
+ case FSYS_STYLE_NWFS:
+ return ImpParseOs2Name( rbInitName, eStyle );
+
+ case FSYS_STYLE_BSD:
+ case FSYS_STYLE_SYSV:
+ return ImpParseUnixName( rbInitName, eStyle );
+
+ case FSYS_STYLE_MAC:
+ return FSYS_ERR_OK;
+
+ default:
+ return FSYS_ERR_UNKNOWN;
+ }
+}
+
+/*************************************************************************
+|*
+|* GetStyle()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 15.11.91
+|* Letzte Aenderung MI 15.11.91
+|*
+*************************************************************************/
+
+static FSysPathStyle GetStyle( FSysPathStyle eStyle )
+{
+ if ( eStyle == FSYS_STYLE_HOST || eStyle == FSYS_STYLE_DETECT )
+ return DEFSTYLE;
+ else
+ return eStyle;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpTrim()
+|*
+|* Beschreibung bringt den Namen auf Betriebssystem-Norm
+|* z.B. 8.3 lower beim MS-DOS Formatter
+|* wirkt nicht rekursiv
+|* Ersterstellung MI 12.08.91
+|* Letzte Aenderung MI 21.05.92
+|*
+*************************************************************************/
+
+void DirEntry::ImpTrim( FSysPathStyle eStyle )
+{
+ // Wildcards werden nicht geclipt
+ if ( ( aName.Search( '*' ) != STRING_NOTFOUND ) ||
+ ( aName.Search( '?' ) != STRING_NOTFOUND ) ||
+ ( aName.Search( ';' ) != STRING_NOTFOUND ) )
+ return;
+
+ switch ( eStyle )
+ {
+ case FSYS_STYLE_FAT:
+ {
+ USHORT nPunktPos = aName.Search( '.' );
+ if ( nPunktPos == STRING_NOTFOUND )
+ {
+ if ( aName.Len() > 8 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( 8 );
+ }
+ }
+ else
+ {
+ if ( nPunktPos > 8 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( 8, nPunktPos - 8 );
+ nPunktPos = 8;
+ }
+ if ( aName.Len() > nPunktPos + 3 )
+ {
+ if ( aName.Len() - nPunktPos > 4 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( nPunktPos + 4 );
+ }
+ }
+ }
+ aName.ToLowerAscii();
+ break;
+ }
+
+ case FSYS_STYLE_VFAT:
+ case FSYS_STYLE_HPFS:
+ case FSYS_STYLE_NTFS:
+ case FSYS_STYLE_NWFS:
+ if ( aName.Len() > 254 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( 254 );
+ }
+
+ if ( eStyle == FSYS_STYLE_HPFS &&
+ ( eFlag == FSYS_FLAG_ABSROOT || eFlag == FSYS_FLAG_RELROOT ) )
+ aName.ToUpperAscii();
+ break;
+
+ case FSYS_STYLE_SYSV:
+ if ( aName.Len() > 14 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( 14 );
+ }
+ break;
+
+ case FSYS_STYLE_BSD:
+ if ( aName.Len() > 250 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( 250 );
+ }
+ break;
+
+ case FSYS_STYLE_MAC:
+ if ( eFlag & ( FSYS_FLAG_ABSROOT | FSYS_FLAG_VOLUME ) )
+ {
+ if ( aName.Len() > 27 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( 27 );
+ }
+ }
+ else
+ {
+ if ( aName.Len() > 31 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( 31 );
+ }
+ }
+ break;
+
+ default:
+ /* kann nicht sein */;
+ }
+}
+
+/*************************************************************************
+|*
+|* DirEntry::DirEntry()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry::DirEntry( const ByteString& rName, DirEntryFlag eDirFlag,
+ FSysPathStyle eStyle ) :
+#ifdef FEAT_FSYS_DOUBLESPEED
+ pStat( 0 ),
+#endif
+ aName( rName )
+{
+ DBG_CTOR( DirEntry, ImpCheckDirEntry );
+
+ pParent = NULL;
+ eFlag = eDirFlag;
+ nError = FSYS_ERR_OK;
+
+ ImpTrim( eStyle );
+}
+
+/*************************************************************************
+|*
+|* DirEntry::DirEntry()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry::DirEntry( const DirEntry& rOrig ) :
+#ifdef FEAT_FSYS_DOUBLESPEED
+ pStat( rOrig.pStat ? new FileStat(*rOrig.pStat) : 0 ),
+#endif
+ aName( rOrig.aName )
+{
+ DBG_CTOR( DirEntry, ImpCheckDirEntry );
+
+ eFlag = rOrig.eFlag;
+ nError = rOrig.nError;
+
+ if ( rOrig.pParent )
+ {
+ pParent = new DirEntry( *rOrig.pParent );
+ }
+ else
+ {
+ pParent = NULL;
+ }
+}
+
+/*************************************************************************
+|*
+|* DirEntry::DirEntry()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry::DirEntry( const String& rInitName, FSysPathStyle eStyle )
+#ifdef FEAT_FSYS_DOUBLESPEED
+ : pStat( 0 )
+#endif
+{
+ DBG_CTOR( DirEntry, ImpCheckDirEntry );
+
+ pParent = NULL;
+
+ // schnelle Loesung fuer Leerstring
+ if ( !rInitName.Len())
+ {
+ eFlag = FSYS_FLAG_CURRENT;
+ nError = FSYS_ERR_OK;
+ return;
+ }
+
+ ByteString aTmpName(rInitName, osl_getThreadTextEncoding());
+ if( eStyle == FSYS_STYLE_URL || aTmpName.CompareIgnoreCaseToAscii("file:",5 ) == COMPARE_EQUAL )
+ {
+#ifndef BOOTSTRAP
+ DBG_WARNING( "File URLs are not permitted but accepted" );
+ aTmpName = ByteString(String(INetURLObject( rInitName ).PathToFileName()), osl_getThreadTextEncoding());
+ eStyle = FSYS_STYLE_HOST;
+#endif // BOOTSTRAP
+ }
+ else
+ {
+ ::rtl::OUString aTmp;
+ ::rtl::OUString aOInitName;
+ if ( FileBase::getFileURLFromSystemPath( OUString( rInitName ), aTmp ) == FileBase::E_None )
+ {
+ aOInitName = OUString( rInitName );
+ aTmpName = ByteString( String(aOInitName), osl_getThreadTextEncoding() );
+ }
+
+#ifdef DBG_UTIL
+ // ASF nur bei Default eStyle, nicht z.B. aus MakeShortName()
+ if( eStyle == FSYS_STYLE_HOST &&
+ aTmpName.Search( "://" ) != STRING_NOTFOUND )
+ {
+ ByteString aErr = "DirEntries akzeptieren nur File URLS: ";
+ aErr += aTmpName;
+ DBG_WARNING( aErr.GetBuffer() );
+ }
+#endif
+ }
+
+ nError = ImpParseName( aTmpName, eStyle );
+
+ if ( nError != FSYS_ERR_OK )
+ eFlag = FSYS_FLAG_INVALID;
+}
+
+/*************************************************************************/
+
+DirEntry::DirEntry( const ByteString& rInitName, FSysPathStyle eStyle )
+#ifdef FEAT_FSYS_DOUBLESPEED
+ : pStat( 0 )
+#endif
+{
+ DBG_CTOR( DirEntry, ImpCheckDirEntry );
+
+ pParent = NULL;
+
+ // schnelle Loesung fuer Leerstring
+ if ( !rInitName.Len() )
+ {
+ eFlag = FSYS_FLAG_CURRENT;
+ nError = FSYS_ERR_OK;
+ return;
+ }
+
+ ByteString aTmpName( rInitName );
+ if( eStyle == FSYS_STYLE_URL || rInitName.CompareIgnoreCaseToAscii("file:",5 ) == COMPARE_EQUAL )
+ {
+#ifndef BOOTSTRAP
+ DBG_WARNING( "File URLs are not permitted but accepted" );
+ aTmpName = ByteString(String(INetURLObject( rInitName ).PathToFileName()), osl_getThreadTextEncoding());
+ eStyle = FSYS_STYLE_HOST;
+#endif
+ }
+#ifdef DBG_UTIL
+ else
+ // ASF nur bei Default eStyle, nicht z.B. aus MakeShortName()
+ if( eStyle == FSYS_STYLE_HOST &&
+ rInitName.Search( "://" ) != STRING_NOTFOUND )
+ {
+ ByteString aErr = "DirEntries akzeptieren nur File URLS: ";
+ aErr += rInitName;
+ DBG_WARNING( aErr.GetBuffer() );
+ }
+#endif
+
+ nError = ImpParseName( aTmpName, eStyle );
+
+ if ( nError != FSYS_ERR_OK )
+ eFlag = FSYS_FLAG_INVALID;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::DirEntry()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry::DirEntry( DirEntryFlag eDirFlag )
+#ifdef FEAT_FSYS_DOUBLESPEED
+ : pStat( 0 )
+#endif
+{
+ DBG_CTOR( DirEntry, ImpCheckDirEntry );
+
+ eFlag = eDirFlag;
+ nError = ( eFlag == FSYS_FLAG_INVALID ) ? FSYS_ERR_UNKNOWN : FSYS_ERR_OK;
+ pParent = NULL;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::~DirEntry()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry::~DirEntry()
+{
+ DBG_DTOR( DirEntry, ImpCheckDirEntry );
+
+ delete pParent;
+#ifdef FEAT_FSYS_DOUBLESPEED
+ delete pStat;
+#endif
+
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpGetTopPtr() const
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+const DirEntry* DirEntry::ImpGetTopPtr() const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ const DirEntry *pTemp = this;
+ while ( pTemp->pParent )
+ pTemp = pTemp->pParent;
+
+ return pTemp;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpGetTopPtr()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 13.11.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry* DirEntry::ImpGetTopPtr()
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntry *pTemp = this;
+ while ( pTemp->pParent )
+ pTemp = pTemp->pParent;
+
+ return pTemp;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpGetPreTopPtr()
+|*
+|* Beschreibung liefert einen Pointer auf den vorletzten Entry
+|* Ersterstellung MI 01.11.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry* DirEntry::ImpGetPreTopPtr()
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntry *pTemp = this;
+ if ( pTemp->pParent )
+ {
+ while ( pTemp->pParent->pParent )
+ pTemp = pTemp->pParent;
+ }
+
+ return pTemp;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpChangeParent()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 21.05.92
+|*
+*************************************************************************/
+
+DirEntry* DirEntry::ImpChangeParent( DirEntry* pNewParent, BOOL bNormalize )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntry *pTemp = pParent;
+ if ( bNormalize && pNewParent &&
+ pNewParent->eFlag == FSYS_FLAG_RELROOT && !pNewParent->aName.Len() )
+ {
+ pParent = 0;
+ delete pNewParent;
+ }
+ else
+ pParent = pNewParent;
+
+ return pTemp;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::Exists()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 24.09.91
+|*
+*************************************************************************/
+
+BOOL DirEntry::Exists( FSysAccess nAccess ) const
+{
+#ifndef BOOTSTRAP
+ static NAMESPACE_VOS(OMutex) aLocalMutex;
+ NAMESPACE_VOS(OGuard) aGuard( aLocalMutex );
+#endif
+ if ( !IsValid() )
+ return FALSE;
+
+#if defined WNT || defined OS2
+ // spezielle Filenamen sind vom System da
+ if ( ( aName.CompareIgnoreCaseToAscii("CLOCK$") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("CON") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("AUX") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("COM1") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("COM2") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("COM3") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("COM4") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("LPT1") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("LPT2") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("LPT3") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("NUL") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("PRN") == COMPARE_EQUAL ) )
+ return TRUE;
+#endif
+
+ FSysFailOnErrorImpl();
+ DirEntryKind eKind = FileStat( *this, nAccess ).GetKind();
+ if ( eKind & ( FSYS_KIND_FILE | FSYS_KIND_DIR ) )
+ {
+ return TRUE;
+ }
+
+#if defined WNT || defined OS2
+ if ( 0 != ( eKind & FSYS_KIND_DEV ) )
+ {
+ return DRIVE_EXISTS( ImpGetTopPtr()->aName.GetChar(0) );
+ }
+#endif
+
+ return 0 != ( eKind & ( FSYS_KIND_FILE | FSYS_KIND_DIR ) );
+}
+
+/*************************************************************************
+|*
+|* DirEntry::First()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 15.01.92
+|*
+*************************************************************************/
+
+BOOL DirEntry::First()
+{
+ FSysFailOnErrorImpl();
+
+ String aUniPathName( GetPath().GetFull() );
+#ifndef BOOTSTRAP
+ FSysRedirector::DoRedirect( aUniPathName );
+ ByteString aPathName(aUniPathName, osl_getThreadTextEncoding());
+#else
+ ByteString aPathName(aUniPathName, gsl_getSystemTextEncoding());
+#endif
+ aPathName = GUI2FSYS( aPathName );
+
+ DIR *pDir = opendir( (char*) aPathName.GetBuffer() );
+ if ( pDir )
+ {
+#ifndef BOOTSTRAP
+ WildCard aWildeKarte( String(CMP_LOWER( aName ), osl_getThreadTextEncoding()) );
+#else
+ WildCard aWildeKarte( String(CMP_LOWER( aName ), gsl_getSystemTextEncoding()) );
+#endif
+ for ( dirent* pEntry = readdir( pDir );
+ pEntry;
+ pEntry = readdir( pDir ) )
+ {
+ ByteString aFound( FSYS2GUI( ByteString( pEntry->d_name ) ) );
+ if ( aWildeKarte.Matches( String(CMP_LOWER( aFound ), osl_getThreadTextEncoding())))
+ {
+ aName = aFound;
+ closedir( pDir );
+ return TRUE;
+ }
+ }
+ closedir( pDir );
+ }
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetFull()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+String DirEntry::GetFull( FSysPathStyle eStyle, BOOL bWithDelimiter,
+ USHORT nMaxChars ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ ByteString aRet;
+ eStyle = GetStyle( eStyle );
+ if ( pParent )
+ {
+ if ( ( pParent->eFlag == FSYS_FLAG_ABSROOT ||
+ pParent->eFlag == FSYS_FLAG_RELROOT ||
+ pParent->eFlag == FSYS_FLAG_VOLUME ) )
+ {
+ aRet = ByteString(pParent->GetName( eStyle ), osl_getThreadTextEncoding());
+ aRet += ByteString(GetName( eStyle ), osl_getThreadTextEncoding());
+ }
+ else
+ {
+ aRet = ByteString(pParent->GetFull( eStyle ), osl_getThreadTextEncoding());
+ aRet += ACCESSDELIM_C(eStyle);
+ aRet += ByteString(GetName( eStyle ), osl_getThreadTextEncoding());
+ }
+ }
+ else
+ {
+ aRet = ByteString(GetName( eStyle ), osl_getThreadTextEncoding());
+ }
+
+ if ( ( eStyle == FSYS_STYLE_MAC ) &&
+ ( ImpGetTopPtr()->eFlag != FSYS_FLAG_VOLUME ) &&
+ ( ImpGetTopPtr()->eFlag != FSYS_FLAG_ABSROOT ) &&
+ ( aRet.GetChar(0) != ':' ) )
+ aRet.Insert( ACCESSDELIM_C(eStyle), 0 );
+
+ //! Hack
+ if ( bWithDelimiter )
+ if ( aRet.GetChar( aRet.Len()-1 ) != ACCESSDELIM_C(eStyle) )
+ aRet += ACCESSDELIM_C(eStyle);
+
+ //! noch ein Hack
+ if ( nMaxChars < STRING_MAXLEN )
+ aRet = ImplCutPath( aRet, nMaxChars, ACCESSDELIM_C(eStyle) );
+
+ return String(aRet, osl_getThreadTextEncoding());
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetPath()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry DirEntry::GetPath() const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ if ( pParent )
+ return DirEntry( *pParent );
+
+ return DirEntry();
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetExtension()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+String DirEntry::GetExtension( char cSep ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ const char *p0 = ( aName.GetBuffer() );
+ const char *p1 = p0 + aName.Len() - 1;
+ while ( p1 >= p0 && *p1 != cSep )
+ p1--;
+
+ if ( p1 >= p0 )
+ // es wurde ein cSep an der Position p1 gefunden
+ return String(
+ aName.Copy( static_cast< xub_StrLen >(p1 - p0 + 1) ),
+ osl_getThreadTextEncoding());
+ return String();
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetBase()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+String DirEntry::GetBase( char cSep ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ const char *p0 = ( aName.GetBuffer() );
+ const char *p1 = p0 + aName.Len() - 1;
+ while ( p1 >= p0 && *p1 != cSep )
+ p1--;
+
+ if ( p1 >= p0 )
+ // es wurde ein cSep an der Position p1 gefunden
+ return String(
+ aName.Copy( 0, static_cast< xub_StrLen >(p1 - p0) ),
+ osl_getThreadTextEncoding());
+
+ else
+ // es wurde kein cSep gefunden
+ return String(aName, osl_getThreadTextEncoding());
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetName()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91 13:47
+|*
+*************************************************************************/
+
+String DirEntry::GetName( FSysPathStyle eStyle ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ ByteString aRet;
+ eStyle = GetStyle( eStyle );
+
+ switch( eFlag )
+ {
+ case FSYS_FLAG_PARENT:
+ aRet = ACTPARENT(eStyle);
+ break;
+
+ case FSYS_FLAG_ABSROOT:
+ {
+ if ( eStyle == FSYS_STYLE_URL )
+ {
+ aRet = "file:///";
+ aRet += aName;
+
+#ifndef UNX
+ if ( aName.Len())
+ {
+ if ( aName.GetChar(aName.Len()-1) == ':' )
+ {
+ aRet.SetChar(aRet.Len()-1, '|');
+ }
+ else
+ {
+ aRet.Insert( '/', 5 );
+ }
+ aRet += "/";
+ }
+#endif
+ }
+ else if ( eStyle != FSYS_STYLE_MAC &&
+ aName.Len() > 1 && aName.GetChar( 1 ) != ':' )
+ {
+ // UNC-Pathname
+ aRet = ACCESSDELIM_C(eStyle);
+ aRet += ACCESSDELIM_C(eStyle);
+ aRet += aName ;
+ aRet += ACCESSDELIM_C(eStyle);
+ }
+ else
+ {
+ aRet = aName;
+ aRet += ACCESSDELIM_C(eStyle);
+ }
+ break;
+ }
+
+ case FSYS_FLAG_INVALID:
+ case FSYS_FLAG_VOLUME:
+ {
+ if ( eStyle == FSYS_STYLE_URL )
+ {
+ aRet = "file:///";
+ aRet += aName;
+#ifndef UNX
+ if ( aName.Len() && aName.GetChar(aName.Len()-1) == ':' )
+ {
+ aRet.SetChar(aRet.Len()-1, '|');
+ }
+#endif
+ }
+ else
+ {
+ aRet = aName;
+ }
+
+ break;
+ }
+
+ case FSYS_FLAG_RELROOT:
+ if ( !aName.Len() )
+ {
+ aRet = ACTCURRENT(eStyle);
+ break;
+ }
+
+ default:
+ aRet = aName;
+ }
+
+ return String(aRet, osl_getThreadTextEncoding());
+}
+
+/*************************************************************************
+|*
+|* DirEntry::IsAbs()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+bool DirEntry::IsAbs() const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+#ifdef UNX
+ return ( pParent ? pParent->IsAbs() : eFlag == FSYS_FLAG_ABSROOT );
+#else
+ return ( pParent ? pParent->IsAbs() : eFlag == FSYS_FLAG_ABSROOT && aName.Len() > 0 );
+#endif
+}
+
+/*************************************************************************
+|*
+|* DirEntry::CutName()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+String DirEntry::CutName( FSysPathStyle eStyle )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ eStyle = GetStyle( eStyle );
+
+ String aOldName( GetName( eStyle ) );
+
+ if ( pParent )
+ {
+ DirEntry *pOldParent = pParent;
+ if ( pOldParent )
+ {
+ pParent = pOldParent->pParent;
+ eFlag = pOldParent->eFlag;
+ aName = pOldParent->aName;
+ pOldParent->pParent = NULL;
+ delete pOldParent;
+ }
+ else
+ {
+ eFlag = FSYS_FLAG_CURRENT;
+ aName.Erase();
+ }
+ }
+ else
+ {
+ eFlag = FSYS_FLAG_CURRENT;
+ aName.Erase();
+ delete pParent;
+ pParent = NULL;
+ }
+
+ return aOldName;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::NameCompare
+|*
+|* Beschreibung Vergleich nur die Namen (ohne Pfad, aber mit Gross/Klein)
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+StringCompare DirEntry::NameCompare( const DirEntry &rWith ) const
+{
+ ByteString aThisName;
+ ByteString aParameterName;
+
+#ifdef UNX
+ aThisName = aName;
+ aParameterName = rWith.aName;
+#else
+ aThisName = ByteString(aName).ToLowerAscii();
+ aParameterName = ByteString(rWith.aName).ToLowerAscii();
+#endif
+
+ return aThisName.CompareTo( aParameterName );
+}
+
+
+/*************************************************************************
+|*
+|* DirEntry::operator==()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+BOOL DirEntry::operator==( const DirEntry& rEntry ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ // test wheather the contents are textual the same
+
+ if ( nError && ( nError == rEntry.nError ) )
+ return TRUE;
+ if ( nError || rEntry.nError ||
+ ( eFlag == FSYS_FLAG_INVALID ) ||
+ ( rEntry.eFlag == FSYS_FLAG_INVALID ) )
+ return FALSE;
+
+#ifndef OS2
+ const
+#endif
+ DirEntry *pThis = (DirEntry *)this;
+#ifndef OS2
+ const
+#endif
+ DirEntry *pWith = (DirEntry *)&rEntry;
+ while( pThis && pWith && (pThis->eFlag == pWith->eFlag) )
+ {
+ if ( CMP_LOWER(pThis->aName) != CMP_LOWER(pWith->aName) )
+ break;
+ pThis = pThis->pParent;
+ pWith = pWith->pParent;
+ }
+
+ return ( !pThis && !pWith );
+}
+
+/*************************************************************************
+|*
+|* DirEntry::operator=()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry& DirEntry::operator=( const DirEntry& rEntry )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ if ( this == &rEntry )
+ return *this;
+ if ( rEntry.nError != FSYS_ERR_OK ) {
+ DBG_ERROR("Zuweisung mit invalidem DirEntry");
+ nError = rEntry.nError;
+ return *this;
+ }
+
+ // Name und Typ uebernehmen, Refs beibehalten
+ aName = rEntry.aName;
+ eFlag = rEntry.eFlag;
+ nError = FSYS_ERR_OK;
+
+ DirEntry *pOldParent = pParent;
+ if ( rEntry.pParent )
+ pParent = new DirEntry( *rEntry.pParent );
+ else
+ pParent = NULL;
+
+ if ( pOldParent )
+ delete pOldParent;
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::operator+()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry DirEntry::operator+( const DirEntry& rEntry ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+#ifdef DBG_UTIL
+ static BOOL bTested = FALSE;
+ if ( !bTested )
+ {
+ bTested = TRUE;
+ FSysTest();
+ }
+#endif
+
+ const DirEntry *pEntryTop = rEntry.ImpGetTopPtr();
+ const DirEntry *pThisTop = ImpGetTopPtr();
+
+ // "." + irgendwas oder irgendwas + "d:irgendwas"
+/* TPF:org
+ if ( ( eFlag == FSYS_FLAG_RELROOT && !aName ) ||
+ ( pEntryTop->aName.Len() &&
+ ( pEntryTop->eFlag == FSYS_FLAG_ABSROOT ||
+ pEntryTop->eFlag == FSYS_FLAG_RELROOT ||
+ pEntryTop->eFlag == FSYS_FLAG_VOLUME ) ) )
+ return rEntry;
+*/
+
+ if (
+ (eFlag == FSYS_FLAG_RELROOT && !aName.Len()) ||
+ (
+ (pEntryTop->aName.Len() ||
+ ((rEntry.Level()>1)?(rEntry[rEntry.Level()-2].aName.CompareIgnoreCaseToAscii(RFS_IDENTIFIER)==COMPARE_EQUAL):FALSE))
+ &&
+ (pEntryTop->eFlag == FSYS_FLAG_ABSROOT ||
+ pEntryTop->eFlag == FSYS_FLAG_RELROOT ||
+ pEntryTop->eFlag == FSYS_FLAG_VOLUME)
+ )
+ )
+ {
+ return rEntry;
+ }
+
+ // irgendwas + "." (=> pEntryTop == &rEntry)
+ if ( pEntryTop->eFlag == FSYS_FLAG_RELROOT && !pEntryTop->aName.Len() )
+ {
+ DBG_ASSERT( pEntryTop == &rEntry, "DirEntry::op+ buggy" );
+ return *this;
+ }
+
+ // root += ".." (=> unmoeglich)
+ if ( pEntryTop->eFlag == FSYS_FLAG_PARENT && pThisTop == this &&
+ ( eFlag == FSYS_FLAG_ABSROOT ) )
+ return DirEntry( FSYS_FLAG_INVALID );
+
+ // irgendwas += abs (=> nur Device uebernehmen falls vorhanden)
+ if ( pEntryTop->eFlag == FSYS_FLAG_ABSROOT )
+ {
+ ByteString aDevice;
+ if ( pThisTop->eFlag == FSYS_FLAG_ABSROOT )
+ aDevice = pThisTop->aName;
+ DirEntry aRet = rEntry;
+ if ( aDevice.Len() )
+ aRet.ImpGetTopPtr()->aName = aDevice;
+ return aRet;
+ }
+
+ // irgendwas += ".." (=> aufloesen)
+ if ( eFlag == FSYS_FLAG_NORMAL && pEntryTop->eFlag == FSYS_FLAG_PARENT )
+ {
+ String aConcated( GetFull() );
+ aConcated += ACCESSDELIM_C(FSYS_STYLE_HOST);
+ aConcated += rEntry.GetFull();
+ return DirEntry( aConcated );
+ }
+
+ // sonst einfach hintereinander haengen
+ DirEntry aRet( rEntry );
+ DirEntry *pTop = aRet.ImpGetTopPtr();
+ pTop->pParent = new DirEntry( *this );
+
+ return aRet;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::operator+=()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry &DirEntry::operator+=( const DirEntry& rEntry )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ return *this = *this + rEntry;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetAccessDelimiter()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 27.05.93
+|* Letzte Aenderung MI 10.06.93
+|*
+*************************************************************************/
+
+String DirEntry::GetAccessDelimiter( FSysPathStyle eFormatter )
+{
+ return String( ACCESSDELIM_C( GetStyle( eFormatter ) ) );
+}
+
+/*************************************************************************
+|*
+|* DirEntry::SetExtension()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 02.08.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+void DirEntry::SetExtension( const String& rExtension, char cSep )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ // do not set extensions for drives
+ if(eFlag == FSYS_FLAG_ABSROOT)
+ {
+ nError = FSYS_ERR_NOTSUPPORTED;
+ return;
+ }
+
+ // cSep im Namen suchen
+ const char *p0 = ( aName.GetBuffer() );
+ const char *p1 = p0 + aName.Len() - 1;
+ while ( p1 >= p0 && *p1 != cSep )
+ p1--;
+ if ( p1 >= p0 )
+ {
+ // es wurde ein cSep an der Position p1 gefunden
+ aName.Erase(
+ static_cast< xub_StrLen >(
+ p1 - p0 + 1 - ( rExtension.Len() ? 0 : 1 )) );
+ aName += ByteString(rExtension, osl_getThreadTextEncoding());
+ }
+ else if ( rExtension.Len() )
+ {
+ // es wurde kein cSep gefunden
+ aName += cSep;
+ aName += ByteString(rExtension, osl_getThreadTextEncoding());
+ }
+}
+
+/*************************************************************************
+|*
+|* DirEntry::CutExtension()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 23.07.93
+|* Letzte Aenderung MI 23.07.93
+|*
+*************************************************************************/
+
+String DirEntry::CutExtension( char cSep )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ const char *p0 = ( aName.GetBuffer() );
+ const char *p1 = p0 + aName.Len() - 1;
+ while ( p1 >= p0 && *p1 != cSep )
+ p1--;
+
+ if ( p1 >= p0 )
+ {
+ // es wurde ein cSep an der Position p1 gefunden
+ aName.Erase( static_cast< xub_StrLen >(p1-p0) );
+ return String(p1 + 1, osl_getThreadTextEncoding());
+ }
+
+ return String();
+}
+
+/*************************************************************************
+|*
+|* DirEntry::SetName()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 04.09.93
+|* Letzte Aenderung MI 04.09.93
+|*
+*************************************************************************/
+
+void DirEntry::SetName( const String& rName, FSysPathStyle eFormatter )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ if ( eFormatter == FSYS_STYLE_HOST || eFormatter == FSYS_STYLE_DETECT )
+ eFormatter = DEFSTYLE;
+ ByteString aAccDelim( ACCESSDELIM_C( eFormatter ) );
+
+ if ( (eFlag != FSYS_FLAG_NORMAL) ||
+ (aName.Search( ':' ) != STRING_NOTFOUND) ||
+ (aName.Search( aAccDelim ) != STRING_NOTFOUND) ||
+ (eFormatter == FSYS_STYLE_FAT && (aName.GetTokenCount( '.' ) > 2) ) )
+ {
+ eFlag = FSYS_FLAG_INVALID;
+ }
+ else
+ {
+ aName = ByteString(rName, osl_getThreadTextEncoding());
+ }
+}
+
+/*************************************************************************
+|*
+|* DirEntry::Find()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+BOOL DirEntry::Find( const String& rPfad, char cDelim )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ if ( ImpGetTopPtr()->eFlag == FSYS_FLAG_ABSROOT )
+ return TRUE;
+
+ BOOL bWild = aName.Search( '*' ) != STRING_NOTFOUND ||
+ aName.Search( '?' ) != STRING_NOTFOUND;
+ if ( !cDelim )
+ cDelim = SEARCHDELIM(DEFSTYLE)[0];
+
+ USHORT nTokenCount = rPfad.GetTokenCount( cDelim );
+ USHORT nIndex = 0;
+ ByteString aThis = ACCESSDELIM(DEFSTYLE);
+ aThis += ByteString(GetFull(), osl_getThreadTextEncoding());
+ for ( USHORT nToken = 0; nToken < nTokenCount; ++nToken )
+ {
+ ByteString aPath = ByteString(rPfad, osl_getThreadTextEncoding()).GetToken( 0, cDelim, nIndex );
+
+ if ( aPath.Len() )
+ {
+ if (aPath.GetChar(aPath.Len()-1)== ACCESSDELIM(DEFSTYLE)[0])
+ aPath.Erase(aPath.Len()-1);
+ aPath += aThis;
+ DirEntry aEntry( String(aPath, osl_getThreadTextEncoding()));
+ if ( aEntry.ToAbs() &&
+ ( ( !bWild && aEntry.Exists() ) || ( bWild && aEntry.First() ) ) )
+ {
+ (*this) = aEntry;
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpToRel()
+|*
+|* Beschreibung
+|* Ersterstellung MI 17.06.93
+|* Letzte Aenderung MI 17.06.93
+|*
+*************************************************************************/
+
+BOOL DirEntry::ImpToRel( String aCurStr )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntry aThis(*this);
+ aThis.ToAbs();
+ String aThisStr( aThis.GetFull( FSYS_STYLE_HPFS ) );
+
+ // #109512 preserve case of path even if caseinsensitive
+ String aThisCompareStr( aThisStr ), aCurCompareStr( aCurStr );
+ if ( ! IsCaseSensitive() )
+ {
+ aThisCompareStr.ToLowerAscii();
+ aCurCompareStr.ToLowerAscii();
+ }
+
+ // "Ubereinstimmung pr"ufen
+ USHORT nPos = aThisCompareStr.Match( aCurCompareStr );
+ if ( nPos == STRING_MATCH && aThisStr.Len() != aCurStr.Len() )
+ nPos = Min( aThisStr.Len(), aCurStr.Len() );
+
+ // Sonderfall, die DirEntries sind identisch
+ if ( nPos == STRING_MATCH )
+ {
+ // dann ist der relative Pfad das aktuelle Verzeichnis
+ *this = DirEntry();
+ return TRUE;
+ }
+
+ // Sonderfall, die DirEntries sind total verschieden
+ if ( nPos == 0 )
+ {
+ // dann ist der relativste Pfad absolut
+ *this = aThis;
+ return FALSE;
+ }
+
+ // sonst nehmen wir die identischen Einzelteile vorne weg
+ while ( nPos > 0 && aThisStr.GetChar(nPos) != '\\' )
+ --nPos;
+ aThisStr.Erase( 0, nPos + ( ( aThisStr.GetChar(nPos) == '\\' ) ? 1 : 0 ) );
+ aCurStr.Erase( 0, nPos + ( ( aCurStr.GetChar(nPos) == '\\' ) ? 1 : 0 ) );
+
+ // und fuellen mit dem Level der Directories auf
+ for ( nPos = 0; nPos < aCurStr.Len(); ++nPos )
+ if ( aCurStr.GetChar(nPos) == '\\' )
+ aThisStr.Insert( String( "..\\", osl_getThreadTextEncoding() ), 0 );
+
+ // das ist dann unser relativer Pfad
+ *this = DirEntry( aThisStr, FSYS_STYLE_HPFS );
+ return TRUE;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::CutRelParents()
+|*
+|* Beschreibung
+|* Ersterstellung MI 01.08.95
+|* Letzte Aenderung MI 01.08.95
+|*
+*************************************************************************/
+
+USHORT DirEntry::CutRelParents()
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ // erstes '..' finden
+ DirEntry *pDir = 0;
+ DirEntry *pPar;
+
+ for ( pPar = this;
+ pPar && pPar->eFlag != FSYS_FLAG_PARENT;
+ pPar = pPar->pParent )
+ pDir = pPar;
+
+ // '..' zaehlen
+ USHORT nParCount = 0;
+ while ( pPar && pPar->eFlag == FSYS_FLAG_PARENT )
+ {
+ ++nParCount;
+ pPar = pPar->pParent;
+ }
+
+ // cutten
+ if ( pDir )
+ DELETEZ(pDir->pParent);
+ else
+ eFlag = FSYS_FLAG_CURRENT;
+
+ return nParCount;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ToRel()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.06.93
+|* Letzte Aenderung MI 17.06.93
+|*
+*************************************************************************/
+
+BOOL DirEntry::ToRel()
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntry aCur;
+ aCur.ToAbs();
+ return ImpToRel( aCur.GetFull( FSYS_STYLE_HPFS ) );
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ToRel()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+BOOL DirEntry::ToRel( const DirEntry& rStart )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntry aStart( rStart );
+ aStart.ToAbs();
+ return ImpToRel( aStart.GetFull( FSYS_STYLE_HPFS ) );
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetDevice()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+#ifndef UNX
+
+DirEntry DirEntry::GetDevice() const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ const DirEntry *pTop = ImpGetTopPtr();
+
+ if ( ( pTop->eFlag == FSYS_FLAG_ABSROOT || pTop->eFlag == FSYS_FLAG_RELROOT ) &&
+ pTop->aName.Len() )
+ return DirEntry( pTop->aName, FSYS_FLAG_VOLUME, FSYS_STYLE_HOST );
+ else
+ return DirEntry( ByteString(), FSYS_FLAG_INVALID, FSYS_STYLE_HOST );
+}
+
+#endif
+
+/*************************************************************************
+|*
+|* DirEntry::SetBase()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 23.10.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+void DirEntry::SetBase( const String& rBase, char cSep )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ const char *p0 = ( aName.GetBuffer() );
+ const char *p1 = p0 + aName.Len() - 1;
+ while ( p1 >= p0 && *p1 != cSep )
+ p1--;
+
+ if ( p1 >= p0 )
+ {
+ // es wurde ein cSep an der Position p1 gefunden
+ aName.Erase( 0, static_cast< xub_StrLen >(p1 - p0) );
+ aName.Insert( ByteString(rBase, osl_getThreadTextEncoding()), 0 );
+ }
+ else
+ aName = ByteString(rBase, osl_getThreadTextEncoding());
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetSearchDelimiter()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 10.06.93
+|* Letzte Aenderung MI 10.06.93
+|*
+*************************************************************************/
+
+String DirEntry::GetSearchDelimiter( FSysPathStyle eFormatter )
+{
+ return String( ByteString(SEARCHDELIM( GetStyle( eFormatter ) ) ), osl_getThreadTextEncoding());
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetMaxNameLen()
+|*
+|* Beschreibung Liefert die maximale Anzahl von Zeichen in
+|* einzelnen Namensteile. Bei FileSystmen mit
+|* fester Extension (FAT) zaehlt diese nicht mit.
+|* Bei unbekannten FileSytemen und FSYS_STYLE_URL
+|* wird USHRT_MAX zurueckgegeben.
+|* Ersterstellung MI 17.06.97
+|* Letzte Aenderung MI 17.06.97
+|*
+*************************************************************************/
+
+USHORT DirEntry::GetMaxNameLen( FSysPathStyle eFormatter )
+{
+ eFormatter = GetStyle( eFormatter );
+ switch ( eFormatter )
+ {
+ case FSYS_STYLE_MAC: return 31;
+
+ case FSYS_STYLE_FAT: return 8;
+
+ case FSYS_STYLE_VFAT:
+ case FSYS_STYLE_NTFS:
+ case FSYS_STYLE_NWFS:
+ case FSYS_STYLE_HPFS: return 255;
+
+
+ case FSYS_STYLE_SYSV: return 14;
+
+ case FSYS_STYLE_BSD: return 250;
+
+ default:
+ return USHRT_MAX;
+ }
+}
+
+/*************************************************************************
+|*
+|* DirEntry::TempName()
+|*
+|* Beschreibung FSYS.SDW - Aha, wo?
+|* Ersterstellung VB 06.09.93 (im SWG)
+|* Letzte Aenderung MI 06.02.98
+|*
+*************************************************************************/
+namespace { struct TempNameBase_Impl : public rtl::Static< DirEntry, TempNameBase_Impl > {}; }
+
+const DirEntry& DirEntry::SetTempNameBase( const String &rBase )
+{
+ DirEntry aTempDir = DirEntry().TempName().GetPath();
+ aTempDir += DirEntry( rBase );
+#ifdef UNX
+ ByteString aName( aTempDir.GetFull(), osl_getThreadTextEncoding());
+ if ( access( aName.GetBuffer(), W_OK | X_OK | R_OK ) )
+ {
+ // Create the directory and only on success give all rights to
+ // everyone. Use mkdir instead of DirEntry::MakeDir because
+ // this returns TRUE even if directory already exists.
+
+ if ( !mkdir( aName.GetBuffer(), S_IRWXU | S_IRWXG | S_IRWXO ) )
+ chmod( aName.GetBuffer(), S_IRWXU | S_IRWXG | S_IRWXO );
+
+ // This will not create a directory but perhaps FileStat called
+ // there modifies the DirEntry
+
+ aTempDir.MakeDir();
+ }
+#else
+ aTempDir.MakeDir();
+#endif
+ DirEntry &rEntry = TempNameBase_Impl::get();
+ rEntry = aTempDir.TempName( FSYS_KIND_DIR );
+ return rEntry;
+}
+
+DirEntry DirEntry::TempName( DirEntryKind eKind ) const
+{
+ // ggf. Base-Temp-Dir verwenden (macht Remote keinen Sinn => vorher)
+ const DirEntry &rEntry = TempNameBase_Impl::get();
+ if ( !pParent && FSYS_FLAG_CURRENT != rEntry.eFlag && FSYS_FLAG_ABSROOT != eFlag )
+
+ {
+ DirEntry aFactory( rEntry );
+ aFactory += GetName();
+ return aFactory.TempName();
+ }
+
+ ByteString aDirName; // hiermit hatte MPW C++ Probleme - immmer noch??
+ char *ret_val;
+ size_t i;
+
+ // dertermine Directory, Prefix and Extension
+ char pfx[6];
+ char ext[5];
+ const char *dir;
+ const char *pWild = strchr( aName.GetBuffer(), '*' );
+ if ( !pWild )
+ pWild = strchr( aName.GetBuffer(), '?' );
+
+ if ( pWild )
+ {
+ if ( pParent )
+ aDirName = ByteString(pParent->GetFull(), osl_getThreadTextEncoding());
+ strncpy( pfx, aName.GetBuffer(), Min( (int)5, (int)(pWild-aName.GetBuffer()) ) );
+ pfx[ pWild-aName.GetBuffer() ] = 0;
+ const char *pExt = strchr( pWild, '.' );
+ if ( pExt )
+ {
+ strncpy( ext, pExt, 4 );
+ ext[4] = 0;
+ }
+ else
+ strcpy( ext, ".tmp" );
+ }
+ else
+ {
+ aDirName = ByteString(GetFull(), osl_getThreadTextEncoding());
+ strcpy( pfx, "sv" );
+ strcpy( ext, ".tmp" );
+ }
+ dir = aDirName.GetBuffer();
+
+ // wurde kein Dir angegeben, dann nehmen wir ein passendes TEMP-Verz.
+ char sBuf[_MAX_PATH];
+ if ( eFlag == FSYS_FLAG_CURRENT || ( !pParent && pWild ) )
+ dir = TempDirImpl(sBuf);
+
+ // ab hier leicht modifizierter Code von VB
+ DirEntry aRet(FSYS_FLAG_INVALID);
+ i = strlen(dir);
+ // need to add ?\\? + prefix + number + pid + .ext + '\0'
+# define TMPNAME_SIZE ( 1 + 5 + 5 + 10 + 4 + 1 )
+ ret_val = new char[i + TMPNAME_SIZE ];
+ if (ret_val)
+ {
+ strcpy(ret_val,dir);
+
+ /* Make sure directory ends with a separator */
+#if defined(WNT) || defined(OS2)
+ if ( i>0 && ret_val[i-1] != '\\' && ret_val[i-1] != '/' &&
+ ret_val[i-1] != ':')
+ ret_val[i++] = '\\';
+#elif defined UNX
+ if (i>0 && ret_val[i-1] != '/')
+ ret_val[i++] = '/';
+#else
+#error unknown operating system
+#endif
+
+ strncpy(ret_val + i, pfx, 5);
+ ret_val[i + 5] = '\0'; /* strncpy doesn't put a 0 if more */
+ i = strlen(ret_val); /* than 'n' chars. */
+
+ /* Prefix can have 5 chars, leaving 3 for numbers. 26 ** 3 == 17576
+ * Welcome to the 21st century, we can have longer filenames now ;)
+ * New format: pfx + "5 char milli/micro second res" + "current pid" + ".tmp"
+ */
+#if (defined MSC || defined __MINGW32__) && defined WNT
+ /* Milliseconds !! */
+ static unsigned long u = GetTickCount();
+ unsigned long mypid = static_cast<unsigned long>(_getpid());
+#else
+ /* Microseconds !! */
+ static unsigned long u = clock();
+ unsigned long mypid = static_cast<unsigned long>(getpid());
+#endif
+ for ( unsigned long nOld = u; ++u != nOld; ) /* Hae??? */
+ {
+ u %= 100000; /* on *NIX repeats every 100ms, maybe less if CLOCKS_PER_SEC > 10^6 */
+ snprintf(ret_val+i, TMPNAME_SIZE, "%05lu%lu", u, mypid);
+
+ strcat(ret_val,ext);
+
+ if ( FSYS_KIND_FILE == eKind )
+ {
+ SvFileStream aStream( String( ret_val, osl_getThreadTextEncoding()),
+ STREAM_WRITE|STREAM_SHARE_DENYALL );
+ if ( aStream.IsOpen() )
+ {
+ aStream.Seek( STREAM_SEEK_TO_END );
+ if ( 0 == aStream.Tell() )
+ {
+ aRet = DirEntry( String( ret_val, osl_getThreadTextEncoding()));
+ break;
+ }
+ aStream.Close();
+ }
+ }
+ else
+ {
+ // Redirect
+ String aRetVal(ret_val, osl_getThreadTextEncoding());
+ String aRedirected (aRetVal);
+#ifndef BOOTSTRAP
+ FSysRedirector::DoRedirect( aRedirected );
+#endif
+ if ( FSYS_KIND_DIR == eKind )
+ {
+ if ( 0 == _mkdir( ByteString(aRedirected.GetBuffer(), osl_getThreadTextEncoding()).GetBuffer() ) )
+ {
+ aRet = DirEntry( aRetVal );
+ break;
+ }
+ }
+ else
+ {
+#if defined(UNX) || defined(OS2)
+ if( access( ByteString(aRedirected, osl_getThreadTextEncoding()).GetBuffer(), F_OK ) )
+ {
+ aRet = DirEntry( aRetVal );
+ break;
+ }
+#else
+ struct stat aStat;
+ if ( stat( ByteString(aRedirected, osl_getThreadTextEncoding()).GetBuffer(), &aStat ) )
+ {
+ aRet = DirEntry( aRetVal );
+ break;
+ }
+#endif
+ }
+ }
+ }
+
+ delete[] ret_val;
+ ret_val = 0;
+ }
+
+ return aRet;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::operator[]()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 03.03.92
+|* Letzte Aenderung MI 03.03.92
+|*
+*************************************************************************/
+
+const DirEntry &DirEntry::operator[]( USHORT nParentLevel ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ //TPF: maybe to be implemented (FastFSys)
+
+ const DirEntry *pRes = this;
+ while ( pRes && nParentLevel-- )
+ pRes = pRes->pParent;
+
+ return *pRes;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpParseUnixName()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 26.05.93
+|*
+*************************************************************************/
+
+FSysError DirEntry::ImpParseUnixName( const ByteString& rPfad, FSysPathStyle eStyle )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ // die einzelnen Namen auf einen Stack packen
+ DirEntryStack aStack;
+ ByteString aPfad( rPfad );
+ do
+ {
+ // den Namen vor dem ersten "/" abspalten,
+ // falls '/' am Anfang, ist der Name '/',
+ // der Rest immer ohne die fuehrenden '/'.
+ // den ersten '/' suchen
+ USHORT nPos;
+ for ( nPos = 0;
+ nPos < aPfad.Len() && aPfad.GetChar(nPos) != '/';
+ nPos++ )
+ /* do nothing */;
+
+ // ist der Name die Root des aktuellen Drives?
+ if ( nPos == 0 && aPfad.Len() > 0 && ( aPfad.GetChar(0) == '/' ) )
+ {
+ // Root-Directory des aktuellen Drives
+ aStack.Push( new DirEntry( FSYS_FLAG_ABSROOT ) );
+ }
+ else
+ {
+ // den Namen ohne Trenner abspalten
+ aName = aPfad.Copy( 0, nPos );
+
+ // stellt der Name die aktuelle Directory dar?
+ if ( aName == "." )
+ /* do nothing */;
+
+#ifdef UNX
+ // stellt der Name das User-Dir dar?
+ else if ( aName == "~" )
+ {
+ DirEntry aHome( String( (const char *) getenv( "HOME" ), osl_getThreadTextEncoding()) );
+ for ( USHORT n = aHome.Level(); n; --n )
+ aStack.Push( new DirEntry( aHome[ (USHORT) n-1 ] ) );
+ }
+#endif
+
+ // stellt der Name die Parent-Directory dar?
+ else if ( aName == ".." )
+ {
+ // ist nichts, ein Parent oder eine relative Root
+ // auf dem Stack?
+ if ( ( aStack.Count() == 0 ) ||
+ ( aStack.Top()->eFlag == FSYS_FLAG_PARENT ) )
+ // fuehrende Parents kommen auf den Stack
+ aStack.Push( new DirEntry( ByteString(), FSYS_FLAG_PARENT, eStyle ) );
+
+ // ist es eine absolute Root
+ else if ( aStack.Top()->eFlag == FSYS_FLAG_ABSROOT ) {
+ // die hat keine Parent-Directory
+ return FSYS_ERR_NOTEXISTS;
+ }
+ else
+ // sonst hebt der Parent den TOS auf
+ delete aStack.Pop();
+ }
+ else
+ {
+ DirEntry *pNew = NULL;
+ // normalen Entries kommen auf den Stack
+ pNew = new DirEntry( aName, FSYS_FLAG_NORMAL, eStyle );
+ if ( !pNew->IsValid() )
+ {
+ aName = rPfad;
+ ErrCode eErr = pNew->GetError();
+ delete pNew;
+ return eErr;
+ }
+ aStack.Push( pNew );
+ }
+ }
+
+ // den Restpfad bestimmen
+ aPfad.Erase( 0, nPos + 1 );
+ while ( aPfad.Len() && ( aPfad.GetChar(0) == '/' ) )
+ aPfad.Erase( 0, 1 );
+ }
+ while ( aPfad.Len() );
+
+ // Haupt-Entry (selbst) zuweisen
+ if ( aStack.Count() == 0 )
+ {
+ eFlag = FSYS_FLAG_CURRENT;
+ aName.Erase();
+ }
+ else
+ {
+ eFlag = aStack.Top()->eFlag;
+ aName = aStack.Top()->aName;
+ delete aStack.Pop();
+ }
+
+ // die Parent-Entries vom Stack holen
+ DirEntry** pTemp = &pParent;
+ while ( aStack.Count() )
+ {
+ *pTemp = aStack.Pop();
+ pTemp = &( (*pTemp)->pParent );
+ }
+
+ return FSYS_ERR_OK;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::MakeShortName()
+|*
+|* Beschreibung
+|* Ersterstellung TLX
+|* Letzte Aenderung PB 21.08.97 (in CreateEntry_Impl())
+|*
+*************************************************************************/
+
+ErrCode CreateEntry_Impl( const DirEntry &rPath, DirEntryKind eKind )
+{
+ // versuchen, anzulegen (ausser bei FSYS_KIND_ALL)
+ ErrCode eErr = ERRCODE_NONE;
+ if ( FSYS_KIND_FILE == eKind )
+ {
+ SvFileStream aStream( rPath.GetFull(), STREAM_STD_WRITE );
+ aStream.WriteLine( "" );
+ eErr = aStream.GetError();
+ }
+ else if ( FSYS_KIND_ALL != eKind )
+ eErr = rPath.MakeDir() ? ERRCODE_NONE : ERRCODE_IO_UNKNOWN;
+
+ // erfolgreich?
+ if ( !rPath.Exists() )
+ eErr = ERRCODE_IO_UNKNOWN; // Doch was schiefgegangen ?
+
+ // ggf. wieder l"oschen
+ if ( FSYS_KIND_NONE == eKind )
+ rPath.Kill();
+
+ // Fehlercode zur?ckliefern
+ return eErr;
+}
+
+BOOL IsValidEntry_Impl( const DirEntry &rPath,
+ const String &rLongName,
+ DirEntryKind eKind,
+ BOOL bIsShortened,
+ BOOL bUseDelim )
+{
+ // Parameter-Pr"uefung
+ DBG_ASSERT( eKind == FSYS_KIND_NONE || eKind == FSYS_KIND_ALL ||
+ eKind == FSYS_KIND_FILE || eKind == FSYS_KIND_DIR,
+ "invalid entry-kind" );
+
+ // Alle von MSDOS erreichbaren FSYS_STYLES muessen den
+ // MSDOS Filenamenanforderungen genuegen. Sonst wird probiert,
+ // ob sich eine Datei des gewuenschten Names anlegen laesst.
+ FSysPathStyle eStyle = DirEntry::GetPathStyle( rPath.GetDevice().GetName() );
+ DirEntry aPath(rPath);
+ DirEntry aName(rLongName, eStyle);
+ if ( !aName.IsValid() || aName.Level() != 1 )
+ return FALSE;
+ aPath += aName;
+ if ( 1 == aPath.Level() )
+ return FALSE;
+ if ( eStyle == FSYS_STYLE_FAT || eStyle == FSYS_STYLE_NWFS ||
+ eStyle == FSYS_STYLE_UNKNOWN )
+ {
+ DirEntry aDosEntry( rLongName, FSYS_STYLE_FAT );
+ if ( !aDosEntry.IsValid() )
+ return FALSE;
+ }
+
+ // Pfad-Trenner sind nicht erlaubt (bei ungek"urzten auch nicht FSYS_SHORTNAME_DELIMITER)
+ char cDelim = bUseDelim == 2 ? FSYS_SHORTNAME_DELIMITER : char(0);
+ if (
+ rLongName.Search(DirEntry::GetAccessDelimiter()) != STRING_NOTFOUND ||
+ (!bIsShortened && rLongName.Search(cDelim) != STRING_NOTFOUND)
+ )
+ {
+ return FALSE;
+ }
+
+ // MI: Abfrage nach 'CON:' etc. wird jetzt in Exists() mitgemacht
+ if ( aPath.Exists() )
+ return FALSE;
+
+ return (ERRCODE_NONE == CreateEntry_Impl( aPath, eKind ));
+}
+
+//-------------------------------------------------------------------------
+
+#define MAX_EXT_FAT 3
+#define MAX_LEN_FAT 8
+#define INVALID_CHARS_FAT "\\/\"':|^<>[]?* "
+
+#define MAX_EXT_MAC 16 // nur wegen sinnvoller Namensk"rzung
+#define MAX_LEN_MAC 31
+#define INVALID_CHARS_MAC "\":"
+
+#define MAX_EXT_MAX 250
+#define MAX_LEN_MAX 255
+#define INVALID_CHARS_DEF "\\/\"':|^<>?*"
+
+BOOL DirEntry::MakeShortName( const String& rLongName, DirEntryKind eKind,
+ BOOL bUseDelim, FSysPathStyle eStyle )
+{
+ String aLongName(rLongName);
+
+ // Alle '#' aus den Dateinamen entfernen, weil das INetURLObject
+ // damit Probleme hat. Siehe auch #51246#
+ aLongName.EraseAllChars( '#' );
+ ByteString bLongName(aLongName, osl_getThreadTextEncoding());
+
+ // Auf Novell-Servern (wegen der rottigen Clients) nur 7bit ASCII
+
+ // HRO: #69627# Weg mit dem Scheiss. Wenn es Client gibt, die so einen
+ // BUG haben, dann muss halt der Client ersetzt werden, aber doch nicht das
+ // Office kastrieren !!!
+
+#if 0
+ if ( FSYS_STYLE_NWFS == GetPathStyle( ImpGetTopPtr()->GetName() ) )
+ {
+ for ( USHORT n = aLongName.Len(); n; --n )
+ {
+ short nChar = aLongName(n-1);
+ if ( nChar < 32 || nChar >= 127 )
+ aLongName.Erase( n-1, 1 );
+ }
+ }
+#endif
+
+ // bei FSYS_KIND_ALL den alten Namen merken und abh"angen (rename)
+ ByteString aOldName;
+ if ( FSYS_KIND_ALL == eKind )
+ {
+ aOldName = ByteString(CutName(), osl_getThreadTextEncoding());
+ aOldName = CMP_LOWER(aOldName);
+ }
+
+ // ist der Langname direkt verwendbar?
+ if ( IsValidEntry_Impl( *this, aLongName, eKind, FALSE, bUseDelim ) )
+ {
+ operator+=( DirEntry(aLongName) );
+ return TRUE;
+ }
+
+ // max L"angen feststellen
+ USHORT nMaxExt, nMaxLen;
+ if ( FSYS_STYLE_DETECT == eStyle )
+ eStyle = DirEntry::GetPathStyle( GetDevice().GetName() );
+ ByteString aInvalidChars;
+ switch ( eStyle )
+ {
+ case FSYS_STYLE_FAT:
+ nMaxExt = MAX_EXT_FAT;
+ nMaxLen = MAX_LEN_FAT;
+ aInvalidChars = INVALID_CHARS_FAT;
+ break;
+
+ case FSYS_STYLE_MAC:
+ nMaxExt = MAX_EXT_MAC;
+ nMaxLen = MAX_LEN_MAC;
+ aInvalidChars = INVALID_CHARS_MAC;
+ break;
+
+ default:
+ nMaxExt = MAX_EXT_MAX;
+ nMaxLen = MAX_LEN_MAX;
+ aInvalidChars = INVALID_CHARS_DEF;
+ }
+
+ // Extension abschneiden und kuerzen
+ ByteString aExt;
+ ByteString aFName = bLongName;
+ if ( FSYS_STYLE_MAC != eStyle )
+ {
+ DirEntry aUnparsed;
+ aUnparsed.aName = bLongName;
+ aExt = ByteString(aUnparsed.CutExtension(), osl_getThreadTextEncoding());
+ aFName = aUnparsed.aName;
+ if ( aExt.Len() > nMaxExt )
+ {
+ char c = aExt.GetChar( aExt.Len() - 1 );
+ aExt.Erase(nMaxExt-1);
+ aExt += c;
+ }
+ }
+
+ if ( FSYS_STYLE_FAT != eStyle )
+ {
+ // ausser auf einem FAT-System geh"ort die Extension zur
+ // Maxl"ange. Muss also vorher mit dem Punkt abgezogen werden.
+ nMaxLen -= ( aExt.Len() + 1 );
+ }
+
+ // Name k"urzen
+ ByteString aSName;
+ for ( const char *pc = aFName.GetBuffer(); aSName.Len() < nMaxLen && *pc; ++pc )
+ {
+ if ( STRING_NOTFOUND == aInvalidChars.Search( *pc ) &&
+ (unsigned char) *pc >= (unsigned char) 32 &&
+ ( !aSName.Len() || *pc != ' ' || aSName.GetChar(aSName.Len()-1) != ' ' ) )
+ aSName += *pc;
+ }
+ aSName.EraseTrailingChars();
+
+ // HRO: #74246# Also cut leading spaces
+ aSName.EraseLeadingChars();
+
+ if ( !aSName.Len() )
+ aSName = "noname";
+
+ // kommt dabei der alte Name raus?
+ ByteString aNewName = aSName;
+ if ( aExt.Len() )
+ ( aNewName += '.' ) += aExt;
+ operator+=( DirEntry(String(aNewName, osl_getThreadTextEncoding())) );
+ if ( FSYS_KIND_ALL == eKind && CMP_LOWER(aName) == aOldName )
+ if ( FSYS_KIND_ALL == eKind && CMP_LOWER(ByteString(GetName(), osl_getThreadTextEncoding())) == aOldName )
+ return TRUE;
+
+ // kann der gek"urzte Name direkt verwendet werden?
+ if ( !Exists() && (ERRCODE_NONE == CreateEntry_Impl( *this, eKind )) )
+ return TRUE;
+
+ // darf '?##' verwendet werden, um eindeutigen Name zu erzeugen?
+ if ( bUseDelim )
+ {
+ // eindeutigen Namen per '?##' erzeugen
+ aSName.Erase( nMaxLen-3 );
+ if ( bUseDelim != 2 )
+ aSName += FSYS_SHORTNAME_DELIMITER;
+ for ( int n = 1; n < 99; ++n )
+ {
+ // Name zusammensetzen
+ ByteString aTmpStr( aSName );
+ aTmpStr += ByteString::CreateFromInt32(n);
+ if ( aExt.Len() )
+ ( aTmpStr += '.' ) += aExt;
+
+ // noch nicht vorhanden?
+ SetName( String(aTmpStr, osl_getThreadTextEncoding()) );
+
+ if ( !Exists() )
+ {
+ // Fehler setzen !!!
+ nError = CreateEntry_Impl( *this, eKind );
+ return (ERRCODE_NONE == nError);
+ }
+ }
+ }
+
+ // keine ## mehr frei / ?## soll nicht verwendet werden
+ nError = ERRCODE_IO_ALREADYEXISTS;
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::CreatePath()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+BOOL DirEntry::MakeDir( BOOL bSloppy ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ // Schnellpruefung, ob vorhanden
+ if ( FileStat( *this ).IsKind( FSYS_KIND_DIR ) )
+ return TRUE;
+ if ( bSloppy && pParent )
+ if ( FileStat( *pParent ).IsKind( FSYS_KIND_DIR ) )
+ return TRUE;
+
+ const DirEntry *pNewDir = bSloppy ? pParent : this;
+ if ( pNewDir )
+ {
+ // den Path zum Dir erzeugen
+ if ( pNewDir->pParent && !pNewDir->pParent->MakeDir(FALSE) )
+ return FALSE;
+
+ // das Dir selbst erzeugen
+ if ( pNewDir->eFlag == FSYS_FLAG_ABSROOT ||
+ pNewDir->eFlag == FSYS_FLAG_ABSROOT ||
+ pNewDir->eFlag == FSYS_FLAG_VOLUME )
+ return TRUE;
+ else
+ {
+ //? nError = ???
+ if ( FileStat( *pNewDir ).IsKind( FSYS_KIND_DIR ) )
+ return TRUE;
+ else
+ {
+ FSysFailOnErrorImpl();
+ String aDirName(pNewDir->GetFull());
+#ifndef BOOTSTRAP
+ FSysRedirector::DoRedirect( aDirName );
+#endif
+ ByteString bDirName( aDirName, osl_getThreadTextEncoding() );
+ bDirName = GUI2FSYS( bDirName );
+
+#ifdef WIN32
+ SetLastError(0);
+#endif
+ BOOL bResult = (0 == _mkdir( (char*) bDirName.GetBuffer() ));
+ if ( !bResult )
+ {
+ // Wer hat diese Methode const gemacht ?
+#ifdef WIN32
+ ((DirEntry *)this)->SetError( Sys2SolarError_Impl( GetLastError() ) );
+#else
+ ((DirEntry *)this)->SetError( Sys2SolarError_Impl( errno ) );
+#endif
+ }
+
+ return bResult;
+ }
+ }
+ }
+ return TRUE;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::CopyTo()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 07.08.96
+|*
+*************************************************************************/
+
+FSysError DirEntry::CopyTo( const DirEntry& rDest, FSysAction nActions ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ if ( FSYS_ACTION_COPYFILE != (nActions & FSYS_ACTION_COPYFILE) )
+#ifdef UNX
+ {
+ // Hardlink anlegen
+ HACK(redirection missing)
+ ByteString aThis(GUI2FSYS(GetFull()), osl_getThreadTextEncoding());
+ ByteString aDest(GUI2FSYS(rDest.GetFull()), osl_getThreadTextEncoding());
+ if (link( aThis.GetBuffer(), aDest.GetBuffer() ) == -1)
+ return Sys2SolarError_Impl( errno );
+ else
+ return FSYS_ERR_OK;
+ }
+#else
+ return FSYS_ERR_NOTSUPPORTED;
+#endif
+
+ FileCopier fc(*this, rDest);
+ return fc.Execute(nActions);
+}
+
+/*************************************************************************
+|*
+|* DirEntry::MoveTo()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung HRO 24.03.99
+|*
+*************************************************************************/
+
+#if defined WNT || defined UNX || defined OS2
+
+FSysError DirEntry::MoveTo( const DirEntry& rNewName ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+/*
+ FileStat aSourceStat(*this);
+ if ( !aSourceStat.IsKind(FSYS_KIND_FILE) )
+ return FSYS_ERR_NOTAFILE;
+*/
+
+ DirEntry aDest(rNewName);
+ FileStat aDestStat(rNewName);
+ if ( aDestStat.IsKind(FSYS_KIND_DIR ) )
+ {
+ aDest += String(aName, osl_getThreadTextEncoding());
+ }
+ if ( aDest.Exists() )
+ {
+ return FSYS_ERR_ALREADYEXISTS;
+ }
+
+#if defined(OS2)
+ if ( FileStat(*this).IsKind(FSYS_KIND_DIR) && aDest.GetPath() != GetPath() )
+ {
+ return FSYS_ERR_NOTSUPPORTED;
+ }
+#endif
+
+ FSysFailOnErrorImpl();
+ String aFrom( GetFull() );
+
+#ifndef BOOTSTRAP
+ FSysRedirector::DoRedirect(aFrom);
+#endif
+
+ String aTo( aDest.GetFull() );
+
+#ifndef BOOTSTRAP
+ FSysRedirector::DoRedirect(aTo);
+#endif
+
+ ByteString bFrom(aFrom, osl_getThreadTextEncoding());
+ ByteString bTo(aTo, osl_getThreadTextEncoding());
+ bFrom = GUI2FSYS(bFrom);
+ bTo = GUI2FSYS(bTo);
+
+#ifdef WNT
+ // MoveTo nun atomar
+ SetLastError(0);
+
+ DirEntry aFromDevice(String(bFrom, osl_getThreadTextEncoding()));
+ DirEntry aToDevice(String(bTo,osl_getThreadTextEncoding()));
+ aFromDevice.ToAbs();
+ aToDevice.ToAbs();
+ aFromDevice=aFromDevice.GetDevice();
+ aToDevice=aToDevice.GetDevice();
+
+ //Quelle und Ziel auf gleichem device?
+ if (aFromDevice==aToDevice)
+ {
+ // ja, also intra-device-move mit MoveFile
+ MoveFile( bFrom.GetBuffer(), bTo.GetBuffer() );
+ // MoveFile ist buggy bei cross-device operationen.
+ // Der R?ckgabewert ist auch dann TRUE, wenn nur ein Teil der Operation geklappt hat.
+ // Zudem zeigt MoveFile unterschiedliches Verhalten bei unterschiedlichen NT-Versionen.
+ return Sys2SolarError_Impl( GetLastError() );
+ }
+ else
+ {
+ //nein, also inter-device-move mit copy/delete
+ FSysError nCopyError = CopyTo(rNewName, FSYS_ACTION_COPYFILE);
+
+ DirEntry aKill(String(bTo, osl_getThreadTextEncoding()));
+ FileStat aKillStat(String(bTo, osl_getThreadTextEncoding()));
+ if ( aKillStat.IsKind(FSYS_KIND_DIR ) )
+ {
+ aKill += String(aName, osl_getThreadTextEncoding());
+ }
+
+ if (nCopyError==FSYS_ERR_OK)
+ {
+ if (Kill()==FSYS_ERR_OK)
+ {
+ return FSYS_ERR_OK;
+ }
+ else
+ {
+ aKill.Kill();
+ return FSYS_ERR_ACCESSDENIED;
+ }
+ }
+ else
+ {
+ aKill.Kill();
+ return nCopyError;
+ }
+ }
+#else
+ // #68639#
+ // on some nfs connections rename with from == to
+ // leads to destruction of file
+ if ( ( aFrom != aTo ) && ( 0 != rename( bFrom.GetBuffer(), bTo.GetBuffer() ) ) )
+#if !defined(UNX) && !defined(OS2)
+ return Sys2SolarError_Impl( GetLastError() );
+#else
+ {
+ if( errno == EXDEV )
+// cross device geht latuernich nicht mit rename
+ {
+ FILE *fpIN = fopen( bFrom.GetBuffer(), "r" );
+ FILE *fpOUT = fopen( bTo.GetBuffer(), "w" );
+ if( fpIN && fpOUT )
+ {
+ char pBuf[ 16384 ];
+ int nBytes, nWritten, nErr = 0;
+ errno = 0;
+ while( ( nBytes = fread( pBuf, 1, sizeof(pBuf), fpIN ) ) && ! nErr )
+ {
+ nWritten = fwrite( pBuf, 1, nBytes, fpOUT );
+ // Fehler im fwrite ?
+ if( nWritten < nBytes )
+ {
+ nErr = errno;
+ break;
+ }
+ }
+ fclose( fpIN );
+ fclose( fpOUT );
+ if ( nErr )
+ {
+ unlink( bTo.GetBuffer() );
+ return Sys2SolarError_Impl( nErr );
+ }
+ else
+ {
+ unlink( bFrom.GetBuffer() );
+ }
+ }
+ else
+ {
+ return Sys2SolarError_Impl( EXDEV );
+ }
+ }
+ else
+ {
+ return Sys2SolarError_Impl( errno );
+ }
+ }
+#endif
+#endif
+ return ERRCODE_NONE;
+}
+
+#endif
+
+/*************************************************************************
+|*
+|* DirEntry::Kill()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 07.08.96
+|*
+*************************************************************************/
+
+FSysError DirEntry::Kill( FSysAction nActions ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ FSysError eError = FSYS_ERR_OK;
+ FSysFailOnErrorImpl();
+
+ // Name als doppelt 0-terminierter String
+ String aTmpName( GetFull() );
+#ifndef BOOTSTRAP
+ FSysRedirector::DoRedirect( aTmpName );
+#endif
+ ByteString bTmpName( aTmpName, osl_getThreadTextEncoding());
+ bTmpName = GUI2FSYS(bTmpName);
+
+ char *pName = new char[bTmpName.Len()+2];
+ strcpy( pName, bTmpName.GetBuffer() );
+ pName[bTmpName.Len()+1] = (char) 0;
+
+ //read-only files sollen auch geloescht werden koennen
+ BOOL isReadOnly = FileStat::GetReadOnlyFlag(*this);
+ if (isReadOnly)
+ {
+ FileStat::SetReadOnlyFlag(*this, FALSE);
+ }
+
+ // directory?
+ if ( FileStat( *this ).IsKind(FSYS_KIND_DIR) )
+ {
+ // Inhalte recursiv loeschen?
+ if ( FSYS_ACTION_RECURSIVE == (nActions & FSYS_ACTION_RECURSIVE) )
+ {
+ Dir aDir( *this, FSYS_KIND_DIR|FSYS_KIND_FILE );
+ for ( USHORT n = 0; eError == FSYS_ERR_OK && n < aDir.Count(); ++n )
+ {
+ const DirEntry &rSubDir = aDir[n];
+ DirEntryFlag flag = rSubDir.GetFlag();
+ if ( flag != FSYS_FLAG_CURRENT && flag != FSYS_FLAG_PARENT )
+ eError = rSubDir.Kill(nActions);
+ }
+ }
+
+ // das Dir selbst loeschen
+#ifdef WIN32
+ SetLastError(0);
+#endif
+ if ( eError == FSYS_ERR_OK && 0 != _rmdir( (char*) pName ) )
+ //
+ {
+ // falls L"oschen nicht ging, CWD umsetzen
+#ifdef WIN32
+ eError = Sys2SolarError_Impl( GetLastError() );
+#else
+ eError = Sys2SolarError_Impl( errno );
+#endif
+ if ( eError )
+ {
+ GetPath().SetCWD();
+#ifdef WIN32
+ SetLastError(0);
+#endif
+ if (_rmdir( (char*) pName) != 0)
+ {
+#ifdef WIN32
+ eError = Sys2SolarError_Impl( GetLastError() );
+#else
+ eError = Sys2SolarError_Impl( errno );
+#endif
+ }
+ else
+ {
+ eError = FSYS_ERR_OK;
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( FSYS_ACTION_USERECYCLEBIN == (nActions & FSYS_ACTION_USERECYCLEBIN) )
+ {
+#ifdef OS2
+ eError = ApiRet2ToSolarError_Impl( DosDelete( (PSZ) pName ) );
+#elif defined(WNT)
+ SHFILEOPSTRUCT aOp;
+ aOp.hwnd = 0;
+ aOp.wFunc = FO_DELETE;
+ aOp.pFrom = pName;
+ aOp.pTo = 0;
+ aOp.fFlags = FOF_ALLOWUNDO|FOF_SILENT|FOF_NOCONFIRMATION;
+ aOp.hNameMappings = 0;
+ aOp.lpszProgressTitle = 0;
+ eError = Sys2SolarError_Impl( SHFileOperation( &aOp ) );
+#else
+ eError = ERRCODE_IO_NOTSUPPORTED;
+#endif
+ }
+ else
+ {
+#ifdef WIN32
+ SetLastError(0);
+#endif
+ if ( 0 != _unlink( (char*) pName ) )
+ {
+#ifdef WIN32
+ eError = Sys2SolarError_Impl( GetLastError() );
+#else
+ eError = Sys2SolarError_Impl( errno );
+#endif
+ }
+ else
+ {
+ eError = ERRCODE_NONE;
+ }
+ }
+ }
+
+ //falls Fehler, originales read-only flag wieder herstellen
+ if ( isReadOnly && (eError!=ERRCODE_NONE) )
+ {
+ FileStat::SetReadOnlyFlag(*this, isReadOnly);
+ }
+
+ delete[] pName;
+ return eError;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::Contains()
+|*
+|* Beschreibung ob rSubEntry direkt oder indirect in *this liegt
+|* Ersterstellung MI 20.03.97
+|* Letzte Aenderung MI 20.03.97
+|*
+*************************************************************************/
+
+BOOL DirEntry::Contains( const DirEntry &rSubEntry ) const
+{
+ DBG_ASSERT( IsAbs() && rSubEntry.IsAbs(), "must be absolute entries" );
+
+ USHORT nThisLevel = Level();
+ USHORT nSubLevel = rSubEntry.Level();
+ if ( nThisLevel < nSubLevel )
+ {
+ for ( ; nThisLevel; --nThisLevel, --nSubLevel )
+ if ( (*this)[nThisLevel-1] != rSubEntry[nSubLevel-1] )
+ return FALSE;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::Level()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 03.03.92
+|* Letzte Aenderung MI 03.03.92
+|*
+*************************************************************************/
+
+USHORT DirEntry::Level() const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ USHORT nLevel = 0;
+ const DirEntry *pRes = this;
+ while ( pRes )
+ {
+ pRes = pRes->pParent;
+ nLevel++;
+ }
+
+ return nLevel;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ConvertNameToSystem()
+|*
+|* Beschreibung
+|* Ersterstellung DV 29.03.96
+|* Letzte Aenderung DV 29.03.96
+|*
+*************************************************************************/
+
+String DirEntry::ConvertNameToSystem( const String &rName )
+{
+ return rName;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ConvertSystemToName()
+|*
+|* Beschreibung
+|* Ersterstellung DV 29.03.96
+|* Letzte Aenderung DV 29.03.96
+|*
+*************************************************************************/
+
+String DirEntry::ConvertSystemToName( const String &rName )
+{
+ return rName;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::IsValid()
+|*
+|* Beschreibung
+|* Ersterstellung MI 18.09.93
+|* Letzte Aenderung TPF 18.09.98
+|*
+*************************************************************************/
+
+BOOL DirEntry::IsValid() const
+{
+ return (nError == FSYS_ERR_OK);
+}
+
+/*************************************************************************
+|*
+|* DirEntry::IsRFSAvailable()
+|*
+|* Beschreibung
+|* Ersterstellung TPF 21.10.98
+|* Letzte Aenderung TPF 21.10.98
+|*
+*************************************************************************/
+
+BOOL DirEntry::IsRFSAvailable()
+{
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* IsLongNameOnFAT()
+|*
+|* Beschreibung ?berpr?ft , ob das DirEntry einen langen
+|* Filenamen auf einer FAT-Partition enth?lt (EAs).
+|* (eigentlich nur f?r OS2 interessant)
+|* Ersterstellung TPF 02.10.98
+|* Letzte Aenderung TPF 01.03.1999
+|*
+*************************************************************************/
+
+BOOL DirEntry::IsLongNameOnFAT() const
+{
+ // FAT-System?
+ DirEntry aTempDirEntry(*this);
+ aTempDirEntry.ToAbs();
+ if (DirEntry::GetPathStyle(aTempDirEntry.GetDevice().GetName().GetChar(0)) != FSYS_STYLE_FAT)
+ {
+ return FALSE; // nein, also false
+ }
+
+ // DirEntry-Kette auf lange Dateinamen pr?fen
+ for( USHORT iLevel = this->Level(); iLevel > 0; iLevel-- )
+ {
+ const DirEntry& rEntry = (const DirEntry&) (*this)[iLevel-1];
+ String aBase( rEntry.GetBase() );
+ String aExtension( rEntry.GetExtension() );
+
+ if (aBase.Len()>8) // Name > 8?
+ {
+ return TRUE;
+ }
+
+ if (aExtension.Len()>3) // Extension > 3?
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+//========================================================================
+
+#if defined(DBG_UTIL)
+
+void FSysTest()
+{
+}
+
+#endif
+