diff --git a/mozilla/xpcom/io/nsILocalFileWin.idl b/mozilla/xpcom/io/nsILocalFileWin.idl index 36d7e036aa7..b51ac82ce0e 100644 --- a/mozilla/xpcom/io/nsILocalFileWin.idl +++ b/mozilla/xpcom/io/nsILocalFileWin.idl @@ -39,7 +39,7 @@ #include "nsILocalFile.idl" -[scriptable, uuid(dc42f467-4094-437d-9e3e-8912a072aede)] +[scriptable, uuid(def38371-73b0-4dfd-85cd-0a7c91afbec6)] interface nsILocalFileWin : nsILocalFile { /** @@ -52,5 +52,17 @@ interface nsILocalFileWin : nsILocalFile * */ AString getVersionInfoField(in string aField); + + /** + * The canonical path of the file, which avoids short/long + * pathname inconsistencies. The nsILocalFile persistent + * descriptor is not guaranteed to be canonicalized (it may + * persist either the long or the short path name). The format of + * the canonical path will vary with the underlying file system: + * it will typically be the short pathname on filesystems that + * support both short and long path forms. + */ + readonly attribute AString canonicalPath; + [noscript] readonly attribute ACString nativeCanonicalPath; }; diff --git a/mozilla/xpcom/io/nsLocalFile.h b/mozilla/xpcom/io/nsLocalFile.h index 58c85f82bb4..09e63643985 100644 --- a/mozilla/xpcom/io/nsLocalFile.h +++ b/mozilla/xpcom/io/nsLocalFile.h @@ -47,6 +47,8 @@ #ifndef _NS_LOCAL_FILE_H_ #define _NS_LOCAL_FILE_H_ +#include "nscore.h" + #define NS_LOCAL_FILE_CID {0x2e23e220, 0x60be, 0x11d3, {0x8c, 0x4a, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74}} #define NS_DECL_NSLOCALFILE_UNICODE_METHODS \ diff --git a/mozilla/xpcom/io/nsLocalFileWin.cpp b/mozilla/xpcom/io/nsLocalFileWin.cpp index 65e3794b4a8..a51062c86c0 100644 --- a/mozilla/xpcom/io/nsLocalFileWin.cpp +++ b/mozilla/xpcom/io/nsLocalFileWin.cpp @@ -52,6 +52,7 @@ #include "prtypes.h" #include "prio.h" #include "prprf.h" +#include "nsHashKeys.h" #include "nsXPIDLString.h" #include "nsReadableUtils.h" @@ -452,7 +453,6 @@ NS_IMPL_ISUPPORTS2(nsDirEnumerator, nsISimpleEnumerator, nsIDirectoryEnumerator) nsLocalFile::nsLocalFile() : mDirty(PR_TRUE) , mFollowSymlinks(PR_FALSE) - , mHashCode(0) { } @@ -495,7 +495,6 @@ nsLocalFile::nsLocalFile(const nsLocalFile& other) : mDirty(PR_TRUE) , mFollowSymlinks(other.mFollowSymlinks) , mWorkingPath(other.mWorkingPath) - , mHashCode(0) { } @@ -2160,26 +2159,20 @@ nsLocalFile::Equals(nsIFile *inFile, PRBool *_retval) NS_ENSURE_ARG(inFile); NS_ENSURE_ARG(_retval); + EnsureShortPath(); + + nsCOMPtr lf(do_QueryInterface(inFile)); + if (!lf) { + *_retval = PR_FALSE; + return NS_OK; + } + nsCAutoString inFilePath; - inFile->GetNativePath(inFilePath); + lf->GetNativeCanonicalPath(inFilePath); - // Normalize both paths to the short form, failing back to a string - // comparison of the long form. + *_retval = _mbsicmp((unsigned char*) mShortWorkingPath.get(), + (unsigned char*) inFilePath.get()) == 0; - char thisshort[MAX_PATH]; - char thatshort[MAX_PATH]; - - DWORD thisr = GetShortPathName(mWorkingPath.get(), thisshort, sizeof(thisshort)); - DWORD thatr = GetShortPathName(inFilePath.get(), thatshort, sizeof(thatshort)); - - if (thisr && thatr && thisr < sizeof(thisshort) && thatr < sizeof(thatshort)) { - *_retval = (_mbsicmp((unsigned char*) thisshort, - (unsigned char*) thatshort) == 0); - } - else { - *_retval = (_mbsicmp((unsigned char*) inFilePath.get(), - (unsigned char*) mWorkingPath.get()) == 0); - } return NS_OK; } @@ -2544,23 +2537,45 @@ nsLocalFile::Equals(nsIHashable* aOther, PRBool *aResult) return Equals(otherfile, aResult); } +void +nsLocalFile::EnsureShortPath() +{ + if (!mShortWorkingPath.IsEmpty()) + return; + + char thisshort[MAX_PATH]; + DWORD thisr = GetShortPathName(mWorkingPath.get(), + thisshort, sizeof(thisshort)); + if (thisr < sizeof(thisshort)) + mShortWorkingPath.Assign(thisshort); + else + mShortWorkingPath.Assign(mWorkingPath); +} + +NS_IMETHODIMP +nsLocalFile::GetNativeCanonicalPath(nsACString &aResult) +{ + EnsureShortPath(); + aResult.Assign(mShortWorkingPath); + return NS_OK; +} + +NS_IMETHODIMP +nsLocalFile::GetCanonicalPath(nsAString &aResult) +{ + EnsureShortPath(); + NS_CopyNativeToUnicode(mShortWorkingPath, aResult); + return NS_OK; +} + NS_IMETHODIMP nsLocalFile::GetHashCode(PRUint32 *aResult) { - if (!mHashCode) { - // In order for short and long path names to hash to the same value we - // always hash on the short pathname. + // In order for short and long path names to hash to the same value we + // always hash on the short pathname. + EnsureShortPath(); - char thisshort[MAX_PATH]; - DWORD thisr = GetShortPathName(mWorkingPath.get(), - thisshort, sizeof(thisshort)); - if (thisr < sizeof(thisshort)) - mHashCode = nsCRT::HashCode(thisshort); - else - mHashCode = nsCRT::HashCode(mWorkingPath.get()); - } - - *aResult = mHashCode; + *aResult = HashString(mShortWorkingPath); return NS_OK; } diff --git a/mozilla/xpcom/io/nsLocalFileWin.h b/mozilla/xpcom/io/nsLocalFileWin.h index 44bed6105e1..f51d411f262 100644 --- a/mozilla/xpcom/io/nsLocalFileWin.h +++ b/mozilla/xpcom/io/nsLocalFileWin.h @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -104,13 +104,18 @@ private: // this will be the resolved path of shortcuts, it will *NEVER* be returned to the user nsCString mResolvedPath; - PRFileInfo64 mFileInfo64; - PRUint32 mHashCode; + // this string, if not empty, is the *short* pathname that represents + // mWorkingPath + nsCString mShortWorkingPath; - void MakeDirty() { mDirty = PR_TRUE; mHashCode = 0; } + PRFileInfo64 mFileInfo64; + + void MakeDirty() { mDirty = PR_TRUE; mShortWorkingPath.Truncate(); } nsresult ResolveAndStat(); nsresult ResolveShortcut(); + + void EnsureShortPath(); nsresult CopyMove(nsIFile *newParentDir, const nsACString &newName, PRBool followSymlinks, PRBool move); nsresult CopySingleFile(nsIFile *source, nsIFile* dest, const nsACString &newName, PRBool followSymlinks, PRBool move);