Get rid of flawed Windows stat cache.
b=456603 r=smichaud sr=dougt
--- a/xpcom/io/nsLocalFileWin.cpp
+++ b/xpcom/io/nsLocalFileWin.cpp
@@ -714,18 +714,17 @@ class nsDirEnumerator : public nsISimple
NS_IMPL_ISUPPORTS2(nsDirEnumerator, nsISimpleEnumerator, nsIDirectoryEnumerator)
//-----------------------------------------------------------------------------
// nsLocalFile <public>
//-----------------------------------------------------------------------------
nsLocalFile::nsLocalFile()
- : mDirty(PR_TRUE)
- , mFollowSymlinks(PR_FALSE)
+ : mFollowSymlinks(PR_FALSE)
{
}
NS_METHOD
nsLocalFile::nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
{
NS_ENSURE_ARG_POINTER(aInstancePtr);
NS_ENSURE_NO_AGGREGATION(outer);
@@ -755,18 +754,17 @@ NS_IMPL_THREADSAFE_ISUPPORTS4(nsLocalFil
nsIHashable)
//-----------------------------------------------------------------------------
// nsLocalFile <private>
//-----------------------------------------------------------------------------
nsLocalFile::nsLocalFile(const nsLocalFile& other)
- : mDirty(PR_TRUE)
- , mFollowSymlinks(other.mFollowSymlinks)
+ : mFollowSymlinks(other.mFollowSymlinks)
, mWorkingPath(other.mWorkingPath)
{
}
// Resolve the shortcut file from mWorkingPath and write the path
// it points to into mResolvedPath.
nsresult
nsLocalFile::ResolveShortcut()
@@ -794,20 +792,16 @@ nsLocalFile::ResolveShortcut()
#endif
}
// Resolve any shortcuts and stat the resolved path. After a successful return
// the path is guaranteed valid and the members of mFileInfo64 can be used.
nsresult
nsLocalFile::ResolveAndStat()
{
- // if we aren't dirty then we are already done
- if (!mDirty)
- return NS_OK;
-
// we can't resolve/stat anything that isn't a valid NSPR addressable path
if (mWorkingPath.IsEmpty())
return NS_ERROR_FILE_INVALID_PATH;
// this is usually correct
mResolvedPath.Assign(mWorkingPath);
// slutty hack designed to work around bug 134796 until it is fixed
@@ -820,17 +814,16 @@ nsLocalFile::ResolveAndStat()
if (NS_FAILED(GetFileInfo(nsprPath, &mFileInfo64)))
return NS_ERROR_FILE_NOT_FOUND;
// if this isn't a shortcut file or we aren't following symlinks then we're done
if (!mFollowSymlinks
|| mFileInfo64.type != PR_FILE_FILE
|| !IsShortcutPath(mWorkingPath))
{
- mDirty = PR_FALSE;
return NS_OK;
}
// we need to resolve this shortcut to what it points to, this will
// set mResolvedPath. Even if it fails we need to have the resolved
// path equal to working path for those functions that always use
// the resolved path.
nsresult rv = ResolveShortcut();
@@ -839,17 +832,16 @@ nsLocalFile::ResolveAndStat()
mResolvedPath.Assign(mWorkingPath);
return rv;
}
// get the details of the resolved path
if (NS_FAILED(GetFileInfo(mResolvedPath, &mFileInfo64)))
return NS_ERROR_FILE_NOT_FOUND;
- mDirty = PR_FALSE;
return NS_OK;
}
//-----------------------------------------------------------------------------
// nsLocalFile::nsIFile,nsILocalFile
//-----------------------------------------------------------------------------
@@ -876,18 +868,16 @@ nsLocalFile::InitWithFile(nsILocalFile *
if (path.IsEmpty())
return NS_ERROR_INVALID_ARG;
return InitWithPath(path);
}
NS_IMETHODIMP
nsLocalFile::InitWithPath(const nsAString &filePath)
{
- MakeDirty();
-
nsAString::const_iterator begin, end;
filePath.BeginReading(begin);
filePath.EndReading(end);
// input string must not be empty
if (begin == end)
return NS_ERROR_FAILURE;
@@ -1096,18 +1086,16 @@ nsLocalFile::AppendInternal(const nsAFla
// catches the remaining cases of prefixes
if (StringBeginsWith(node, NS_LITERAL_STRING("..\\")))
return NS_ERROR_FILE_UNRECOGNIZED_PATH;
}
// single components can't contain '\'
else if (node.FindChar(L'\\') != kNotFound)
return NS_ERROR_FILE_UNRECOGNIZED_PATH;
#endif
-
- MakeDirty();
mWorkingPath.Append(NS_LITERAL_STRING("\\") + node);
return NS_OK;
}
#define TOUPPER(u) (((u) >= L'a' && (u) <= L'z') ? \
(u) - (L'a' - L'A') : (u))
@@ -1261,17 +1249,16 @@ nsLocalFile::Normalize()
// kill trailing dots and spaces.
PRInt32 filePathLen = mWorkingPath.Length() - 1;
while(filePathLen > 0 && (mWorkingPath[filePathLen] == L' ' ||
mWorkingPath[filePathLen] == L'.'))
{
mWorkingPath.Truncate(filePathLen--);
}
- MakeDirty();
#else // WINCE
// WINCE FIX
#endif
return NS_OK;
}
NS_IMETHODIMP
nsLocalFile::GetLeafName(nsAString &aLeafName)
@@ -1290,18 +1277,16 @@ nsLocalFile::GetLeafName(nsAString &aLea
aLeafName = Substring(mWorkingPath, offset + 1);
return NS_OK;
}
NS_IMETHODIMP
nsLocalFile::SetLeafName(const nsAString &aLeafName)
{
- MakeDirty();
-
if(mWorkingPath.IsEmpty())
return NS_ERROR_FILE_UNRECOGNIZED_PATH;
// cannot use nsCString::RFindChar() due to 0x5c problem
PRInt32 offset = mWorkingPath.RFindChar(L'\\');
if (offset)
{
mWorkingPath.Truncate(offset+1);
@@ -1676,18 +1661,16 @@ nsLocalFile::CopyMove(nsIFile *aParentDi
NS_ENSURE_SUCCESS(rv,rv);
}
}
// If we moved, we want to adjust this.
if (move)
{
- MakeDirty();
-
nsAutoString newParentPath;
newParentDir->GetPath(newParentPath);
if (newParentPath.IsEmpty())
return NS_ERROR_FAILURE;
if (newName.IsEmpty())
{
@@ -1831,17 +1814,16 @@ nsLocalFile::Remove(PRBool recursive)
{
rv = _wremove(mWorkingPath.get());
}
// fixup error code if necessary...
if (rv == (nsresult)-1)
rv = NSRESULT_FOR_ERRNO();
- MakeDirty();
return rv;
}
NS_IMETHODIMP
nsLocalFile::GetLastModifiedTime(PRInt64 *aLastModifiedTime)
{
// Check we are correctly initialized.
CHECK_mWorkingPath();
@@ -1900,34 +1882,27 @@ nsLocalFile::SetLastModifiedTime(PRInt64
return rv;
// set the modified time of the target as determined by mFollowSymlinks
// If PR_TRUE, then this will be for the target of the shortcut file,
// otherwise it will be for the shortcut file itself (i.e. the same
// results as SetLastModifiedTimeOfLink)
rv = SetModDate(aLastModifiedTime, mResolvedPath.get());
- if (NS_SUCCEEDED(rv))
- MakeDirty();
return rv;
}
NS_IMETHODIMP
nsLocalFile::SetLastModifiedTimeOfLink(PRInt64 aLastModifiedTime)
{
// The caller is assumed to have already called IsSymlink
// and to have found that this file is a link.
-
- nsresult rv = SetModDate(aLastModifiedTime, mWorkingPath.get());
- if (NS_SUCCEEDED(rv))
- MakeDirty();
-
- return rv;
+ return SetModDate(aLastModifiedTime, mWorkingPath.get());
}
nsresult
nsLocalFile::SetModDate(PRInt64 aLastModifiedTime, const PRUnichar *filePath)
{
HANDLE file = ::CreateFileW(filePath, // pointer to name of the file
GENERIC_WRITE, // access (write) mode
0, // share mode
@@ -2113,29 +2088,24 @@ nsLocalFile::SetFileSize(PRInt64 aFileSi
HANDLE hFile = ::CreateFileW(mResolvedPath.get(),// pointer to name of the file
GENERIC_WRITE, // access (write) mode
FILE_SHARE_READ, // share mode
NULL, // pointer to security attributes
OPEN_EXISTING, // how to create
FILE_ATTRIBUTE_NORMAL, // file attributes
NULL);
if (hFile == INVALID_HANDLE_VALUE)
- {
return ConvertWinError(GetLastError());
- }
// seek the file pointer to the new, desired end of file
// and then truncate the file at that position
rv = NS_ERROR_FAILURE;
aFileSize = MyFileSeek64(hFile, aFileSize, FILE_BEGIN);
if (aFileSize != -1 && SetEndOfFile(hFile))
- {
- MakeDirty();
rv = NS_OK;
- }
CloseHandle(hFile);
return rv;
}
NS_IMETHODIMP
nsLocalFile::GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable)
{
@@ -2209,17 +2179,16 @@ NS_IMETHODIMP
nsLocalFile::Exists(PRBool *_retval)
{
// Check we are correctly initialized.
CHECK_mWorkingPath();
NS_ENSURE_ARG(_retval);
*_retval = PR_FALSE;
- MakeDirty();
nsresult rv = ResolveAndStat();
*_retval = NS_SUCCEEDED(rv);
return NS_OK;
}
NS_IMETHODIMP
nsLocalFile::IsWritable(PRBool *aIsWritable)
@@ -2563,17 +2532,16 @@ NS_IMETHODIMP
nsLocalFile::GetFollowLinks(PRBool *aFollowLinks)
{
*aFollowLinks = mFollowSymlinks;
return NS_OK;
}
NS_IMETHODIMP
nsLocalFile::SetFollowLinks(PRBool aFollowLinks)
{
- MakeDirty();
mFollowSymlinks = aFollowLinks;
return NS_OK;
}
NS_IMETHODIMP
nsLocalFile::GetDirectoryEntries(nsISimpleEnumerator * *entries)
{
--- a/xpcom/io/nsLocalFileWin.h
+++ b/xpcom/io/nsLocalFileWin.h
@@ -47,23 +47,16 @@
#include "nsCRT.h"
#include "nsIFile.h"
#include "nsIFactory.h"
#include "nsILocalFileWin.h"
#include "nsIHashable.h"
#include "nsIClassInfoImpl.h"
#include "windows.h"
-
-// For older version (<6.0) of the VC Compiler
-#if (_MSC_VER == 1100)
-#include <objbase.h>
-DEFINE_OLEGUID(IID_IPersistFile, 0x0000010BL, 0, 0);
-#endif
-
#include "shlobj.h"
#include <sys/stat.h>
class nsLocalFile : public nsILocalFileWin,
public nsIHashable
{
public:
@@ -91,34 +84,32 @@ public:
public:
static void GlobalInit();
static void GlobalShutdown();
private:
nsLocalFile(const nsLocalFile& other);
~nsLocalFile() {}
- PRPackedBool mDirty; // cached information can only be used when this is PR_FALSE
PRPackedBool mFollowSymlinks; // should we follow symlinks when working on this file
// this string will always be in native format!
nsString mWorkingPath;
// this will be the resolved path of shortcuts, it will *NEVER*
// be returned to the user
nsString mResolvedPath;
// this string, if not empty, is the *short* pathname that represents
// mWorkingPath
nsString mShortWorkingPath;
+ // call ResolveAndStat() whenever this needs to be up-to-date
PRFileInfo64 mFileInfo64;
- void MakeDirty() { mDirty = PR_TRUE; mShortWorkingPath.Truncate(); }
-
nsresult ResolveAndStat();
nsresult ResolveShortcut();
void EnsureShortPath();
nsresult CopyMove(nsIFile *newParentDir, const nsAString &newName,
PRBool followSymlinks, PRBool move);
nsresult CopySingleFile(nsIFile *source, nsIFile* dest,