diff -r 000000000000 -r 7f656887cf89 libraries/iosrv/client/file_utils.cpp --- /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 +#include +#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& 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 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& 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)); + } +