--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libraries/iosrv/client/file_utils.cpp Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,513 @@
+// file_utils.cpp
+//
+// Copyright (c) 2006 - 2010 Accenture. All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Accenture - Initial contribution
+//
+
+#include <e32base.h>
+#include <f32file.h>
+#include "ioutils.h"
+
+using namespace IoUtils;
+
+
+//
+// Constants.
+//
+
+_LIT(KSlash, "\\");
+_LIT(KDoubleSlash, "\\\\");
+_LIT(KDot, ".");
+_LIT(KDoubleDot, "..");
+
+__ASSERT_COMPILE(sizeof(TFileName2) == sizeof(TFileName) + 4);
+
+//
+// TFileName2.
+//
+
+EXPORT_C TFileName2::TFileName2()
+ {
+ new(this) TFileName2(EFile);
+ }
+
+EXPORT_C TFileName2::TFileName2(TType aType)
+ {
+ new(this) TFileName2(KNullDesC, aType);
+ }
+
+EXPORT_C TFileName2::TFileName2(const TDesC& aName)
+ : TBuf<256>(aName), iType(EFile)
+ {
+ new(this) TFileName2(aName, EFile);
+ }
+
+EXPORT_C TFileName2::TFileName2(const TDesC& aName, TType aType)
+ : TBuf<256>(aName), iType(aType)
+ {
+ // Remove any double slashes that may be present.
+ TInt pos;
+ while ((pos = Find(KDoubleSlash)) >= 0)
+ {
+ Delete(pos, 1);
+ }
+ }
+
+EXPORT_C TBool TFileName2::IsAbsolute() const
+ {
+ return ((Length() >= 3) && TChar((*this)[0]).IsAlpha() && ((*this)[1] == ':') && ((*this)[2] == '\\'));
+ }
+
+EXPORT_C TBool TFileName2::IsDriveLetter() const
+ {
+ return (Length() == 2) && TChar((*this)[0]).IsAlpha() && ((*this)[1] == ':');
+ }
+
+EXPORT_C TBool TFileName2::IsDriveRoot() const
+ {
+ return ((Length() == 3) && TChar((*this)[0]).IsAlpha() && ((*this)[1] == ':') && ((*this)[2] == '\\'));
+ }
+
+EXPORT_C TBool TFileName2::IsWild() const
+ {
+ return TParsePtrC(*this).IsWild();
+ }
+
+EXPORT_C TBool TFileName2::IsFile() const
+ {
+ TBool ret = (iType == EFile);
+ ASSERT((ret && !HasTrailingSlash()) || (!ret && HasTrailingSlash()));
+ return ret;
+ }
+
+EXPORT_C TBool TFileName2::IsDir() const
+ {
+ TBool ret = (iType == EDirectory);
+ ASSERT((ret && HasTrailingSlash()) || (!ret && !HasTrailingSlash()));
+ return ret;
+ }
+
+EXPORT_C TBool TFileName2::HasDriveLetter() const
+ {
+ return ((Length() >= 2) && TChar((*this)[0]).IsAlpha() && ((*this)[1] == ':'));
+ }
+
+EXPORT_C TBool TFileName2::HasLeadingSlash() const
+ {
+ return ((Length() >= 1) && ((*this)[0] == '\\'));
+ }
+
+EXPORT_C TBool TFileName2::HasTrailingSlash() const
+ {
+ return ((Length() >= 1) && ((*this)[Length() - 1] == '\\'));
+ }
+
+EXPORT_C TPtrC TFileName2::Drive() const
+ {
+ return TParsePtrC(*this).Drive();
+ }
+
+EXPORT_C TPtrC TFileName2::Path() const
+ {
+ return TParsePtrC(*this).Path();
+ }
+
+EXPORT_C TPtrC TFileName2::DriveAndPath() const
+ {
+ return TParsePtrC(*this).DriveAndPath();
+ }
+
+EXPORT_C TPtrC TFileName2::Name() const
+ {
+ return TParsePtrC(*this).Name();
+ }
+
+EXPORT_C TPtrC TFileName2::Ext() const
+ {
+ return TParsePtrC(*this).Ext();
+ }
+
+EXPORT_C TPtrC TFileName2::NameAndExt() const
+ {
+ return TParsePtrC(*this).NameAndExt();
+ }
+
+EXPORT_C void TFileName2::SetL(const TFileName2& aName)
+ {
+ Zero();
+ AppendComponentL(aName);
+ }
+
+EXPORT_C void TFileName2::SetTypeL(TType aType)
+ {
+ switch (aType)
+ {
+ case EFile:
+ {
+ if (HasTrailingSlash() && ((HasDriveLetter() && (Length() > 3)) || (!HasDriveLetter() && (Length() > 1))))
+ {
+ Delete(Length() - 1, 1);
+ }
+ iType = EFile;
+ break;
+ }
+ case EDirectory:
+ {
+ if (!HasTrailingSlash())
+ {
+ AppendComponentL(KNullDesC());
+ }
+ iType = EDirectory;
+ break;
+ }
+ default:
+ {
+ ASSERT(EFalse);
+ }
+ }
+ }
+
+EXPORT_C void TFileName2::SetTypeL(RFs& aFs)
+ {
+ if (IsDirL(aFs))
+ {
+ SetTypeL(EDirectory);
+ }
+ else
+ {
+ SetTypeL(EFile);
+ }
+ }
+
+EXPORT_C void TFileName2::SetDriveL(const TDesC& aDrive)
+ {
+ if (Drive().Length() > 0)
+ {
+ (*this)[0] = aDrive[0];
+ }
+ else
+ {
+ PrependL(aDrive);
+ }
+ }
+
+EXPORT_C void TFileName2::SetPathL(const TDesC& aPath)
+ {
+ TFileName2 temp;
+ temp.SetDriveL(Drive());
+ temp.AppendComponentL(aPath);
+ temp.SetNameAndExtL(NameAndExt());
+ Copy(temp);
+ }
+
+EXPORT_C void TFileName2::SetNameL(const TDesC& aName)
+ {
+ TPtrC namePtrC(Name());
+ if (namePtrC.Length() > 0)
+ {
+ CheckSpaceL(aName.Length() - namePtrC.Length());
+ TInt namePos = namePtrC.Ptr() - Ptr();
+ Delete(namePos, namePtrC.Length());
+ Insert(namePos, aName);
+ }
+ else
+ {
+ AppendComponentL(aName);
+ }
+ }
+
+EXPORT_C void TFileName2::SetExtL(const TDesC& aExt)
+ {
+ TPtrC extPtrC(Ext());
+ if (extPtrC.Length() > 0)
+ {
+ CheckSpaceL(aExt.Length() + ((aExt[0] == '.') ? 0 : 1) - extPtrC.Length());
+ Delete(extPtrC.Ptr() - Ptr(), extPtrC.Length());
+ }
+ else
+ {
+ CheckSpaceL(aExt.Length() + ((aExt[0] == '.') ? 0 : 1));
+ }
+
+ if (aExt[0] != '.')
+ {
+ Append('.');
+ }
+ Append(aExt);
+ }
+
+EXPORT_C void TFileName2::SetNameAndExtL(const TDesC& aNameAndExt)
+ {
+ TPtrC nameAndExtPtrC(NameAndExt());
+ if (nameAndExtPtrC.Length() > 0)
+ {
+ CheckSpaceL(aNameAndExt.Length() - nameAndExtPtrC.Length());
+ TInt nameAndExtPos = nameAndExtPtrC.Ptr() - Ptr();
+ Delete(nameAndExtPos, nameAndExtPtrC.Length());
+ Insert(nameAndExtPos, aNameAndExt);
+ }
+ else
+ {
+ AppendComponentL(aNameAndExt);
+ }
+ }
+
+EXPORT_C void TFileName2::PrependL(const TFileName2& aName)
+ {
+ if (Length() == 0)
+ {
+ CheckSpaceL(aName.Length() + (((iType == EDirectory) && !HasTrailingSlash()) ? 1 : 0));
+ Append(aName);
+ }
+ else if (aName.HasTrailingSlash() && HasLeadingSlash())
+ {
+ CheckSpaceL(aName.Length() - 1 + (((iType == EDirectory) && !HasTrailingSlash()) ? 1 : 0));
+ Insert(0, aName.Mid(1));
+ }
+ else if (!aName.HasTrailingSlash() && !HasLeadingSlash())
+ {
+ CheckSpaceL(aName.Length() + 1 + (((iType == EDirectory) && !HasTrailingSlash()) ? 1 : 0));
+ Insert(0, KSlash);
+ Insert(0, aName);
+ }
+ else
+ {
+ CheckSpaceL(aName.Length() + (((iType == EDirectory) && !HasTrailingSlash()) ? 1 : 0));
+ Insert(0, aName);
+ }
+
+ if ((iType == EDirectory) && (!HasTrailingSlash()))
+ {
+ Append(KSlash);
+ }
+ }
+
+EXPORT_C void TFileName2::AppendComponentL(const TFileName2& aName)
+ {
+ AppendComponentL(aName, iType);
+ }
+
+EXPORT_C void TFileName2::AppendComponentL(const TDesC& aPathComponent, TFileName2::TType aType)
+ {
+ // This function doesn't use iType, therefore you can call it and get the same results regardless of whether the type has been set - you will only get a trailing slash if (a) aPathComponent ends in a slash, or (b) aType is EDirectory.
+ TPtrC pathWithoutLeadingSlash(aPathComponent);
+ if (aPathComponent.Length() && aPathComponent[0] == '\\') pathWithoutLeadingSlash.Set(aPathComponent.Mid(1));
+ TInt pathLen = pathWithoutLeadingSlash.Length();
+ const TDesC* middle = &KNullDesC;
+ if (Length() && !HasTrailingSlash()) middle = &KSlash;
+ const TDesC* end = &KNullDesC;
+ if (aType == EDirectory && pathLen && pathWithoutLeadingSlash[pathLen-1] != '\\') end = &KSlash;
+ CheckSpaceL(pathLen + middle->Length() + end->Length());
+
+ Append(*middle);
+ Append(pathWithoutLeadingSlash);
+ Append(*end);
+ }
+
+EXPORT_C void TFileName2::AppendComponentL(const TEntry& aEntry)
+ {
+ AppendComponentL(aEntry.iName, aEntry.IsDir() ? EDirectory : EFile);
+ }
+
+EXPORT_C void TFileName2::SetIsDirectoryL()
+ {
+ // This is the more complicated way to do it, the other would be: if (!HasTrailingSlash()) AppendL(KSlash);
+ // Or indeed, AppendComponentL(KNullDesC, EDirectory) since the type is irrelevant if the component is empty
+ AppendComponentL(KNullDesC, EFile);
+ }
+
+void TFileName2::CheckSpaceL(TInt aLengthToAdd) const
+ {
+ if ((MaxLength() - Length()) < aLengthToAdd)
+ {
+ User::Leave(KErrTooBig);
+ }
+ }
+
+EXPORT_C void TFileName2::SplitL(RArray<TFileName2>& aOutput)
+ {
+ TLex lex(*this);
+ while (!lex.Eos())
+ {
+ lex.Mark();
+ while (!lex.Eos() && (lex.Peek() != '\\'))
+ {
+ lex.Get();
+ }
+ User::LeaveIfError(aOutput.Append(TFileName2(lex.MarkedToken())));
+ if (!lex.Eos())
+ {
+ // Skip over the slash
+ lex.Get();
+ if (lex.Eos())
+ {
+ // ended with slash - insert empty path component
+ User::LeaveIfError(aOutput.Append(TFileName2()));
+ }
+ }
+ }
+ }
+
+EXPORT_C void TFileName2::MakeAbsoluteL(const TFileName2& aAbsoluteTo)
+ {
+ ASSERT(aAbsoluteTo.IsAbsolute());
+
+ if (IsAbsolute())
+ {
+ return;
+ }
+
+ if (HasLeadingSlash())
+ {
+ // Just prepend drive letter.
+ PrependL(aAbsoluteTo.Left(2));
+ return;
+ }
+
+ PrependL(aAbsoluteTo);
+ RArray<TFileName2> splitName;
+ CleanupClosePushL(splitName);
+ SplitL(splitName);
+ TInt i = 0;
+ while (i < splitName.Count())
+ {
+ const TFileName2& piece = splitName[i];
+ if (piece == KDot)
+ {
+ splitName.Remove(i);
+ }
+ else if (piece == KDoubleDot)
+ {
+ if ((i == 0) || ((i == 1) && splitName[0].IsDriveLetter()))
+ {
+ User::Leave(KErrBadName);
+ }
+ splitName.Remove(i);
+ splitName.Remove(i - 1);
+ --i;
+ }
+ else if ((piece == KNullDesC) && (i != 0) && (i != splitName.Count()-1))
+ {
+ // Allow empty piece in first or last slot to support leading/trailing slashes.
+ splitName.Remove(i);
+ }
+ else
+ {
+ ++i;
+ }
+ }
+
+ UnsplitL(splitName);
+ CleanupStack::PopAndDestroy(&splitName);
+ }
+
+EXPORT_C void TFileName2::MakeAbsoluteL(RFs& aFs)
+ {
+ TFileName2 sessionPath;
+ User::LeaveIfError(aFs.SessionPath(sessionPath));
+ MakeAbsoluteL(sessionPath);
+ }
+
+EXPORT_C void TFileName2::UnsplitL(const RArray<TFileName2>& aInput)
+ {
+ Zero();
+ const TInt count = aInput.Count();
+ for (TInt i = 0; i < count; ++i)
+ {
+ AppendComponentL(aInput[i]);
+ }
+ if ((count == 1) && (aInput[0].Match(_L("?:")) == 0))
+ {
+ Append(KSlash);
+ }
+ }
+
+EXPORT_C TBool TFileName2::Exists(RFs& aFs) const
+ {
+ TInt err;
+ if (IsDriveRoot())
+ {
+ TInt driveNumber;
+ err = RFs::CharToDrive(Drive()[0], driveNumber);
+ if (err == KErrNone)
+ {
+ TDriveInfo driveInfo;
+ err = aFs.Drive(driveInfo, driveNumber);
+ }
+ }
+ else
+ {
+ TUint att;
+ err = aFs.Att(*this, att);
+ }
+ return (err == KErrNone);
+ }
+
+EXPORT_C TBool TFileName2::IsReadOnlyL(RFs& aFs) const
+ {
+ TEntry entry;
+ User::LeaveIfError(aFs.Entry(*this, entry));
+ return entry.IsReadOnly();
+ }
+
+EXPORT_C TBool TFileName2::IsHiddenL(RFs& aFs) const
+ {
+ TEntry entry;
+ User::LeaveIfError(aFs.Entry(*this, entry));
+ return entry.IsHidden();
+ }
+
+EXPORT_C TBool TFileName2::IsSystemL(RFs& aFs) const
+ {
+ TEntry entry;
+ User::LeaveIfError(aFs.Entry(*this, entry));
+ return entry.IsSystem();
+ }
+
+EXPORT_C TBool TFileName2::IsDirL(RFs& aFs) const
+ {
+ if (IsDriveRoot())
+ {
+ if (!Exists(aFs))
+ {
+ User::Leave(KErrNotFound);
+ }
+ return ETrue;
+ }
+ else
+ {
+ TEntry entry;
+ User::LeaveIfError(aFs.Entry(*this, entry));
+ return entry.IsDir();
+ }
+ }
+
+EXPORT_C TBool TFileName2::IsArchiveL(RFs& aFs) const
+ {
+ TEntry entry;
+ User::LeaveIfError(aFs.Entry(*this, entry));
+ return entry.IsArchive();
+ }
+
+EXPORT_C TInt TFileName2::FindFile(RFs& aFs)
+ {
+ TFindFile ff(aFs);
+ TInt err = ff.FindByDir(*this, KNullDesC);
+ if (err==KErrNone)
+ {
+ *this = ff.File();
+ }
+ return err;
+ }
+
+EXPORT_C void TFileName2::FindFileL(RFs& aFs)
+ {
+ User::LeaveIfError(FindFile(aFs));
+ }
+