{
PRBool flagExists, flagRenamedDoomedFileExists, flagIsEqual;
nsCOMPtr<nsIFile> replacementFile;
nsresultrv;
// make a clone of aReplacement file so we touch affect callers
aReplacementFile->Clone(getter_AddRefs(replacementFile));
// replacement file must exist, doomed file doesn't have to
replacementFile->Exists(&flagExists);
if ( !flagExists )
returnnsInstall::DOES_NOT_EXIST;
// don't have to do anything if the files are the same
replacementFile->Equals(aDoomedFile, &flagIsEqual);
if ( flagIsEqual )
returnnsInstall::SUCCESS;
PRInt32result = nsInstall::ACCESS_DENIED;
// first try to rename the doomed file out of the way (if it exists)nsCOMPtr<nsIFile> renamedDoomedFile;
nsCOMPtr<nsILocalFile> tmpLocalFile;
aDoomedFile->Clone(getter_AddRefs(renamedDoomedFile));
renamedDoomedFile->Exists(&flagRenamedDoomedFileExists);
if ( flagRenamedDoomedFileExists )
{
#ifdef XP_MACOSX// If we clone an nsIFile, and move the clone, the FSRef of the *original*// file is not what you would expect - it points to the moved file. This// is despite the fact that the two FSRefs are independent objects. Until// the OS X file impl is changed to not use FSRefs, need to do this (see// bug 200024).nsCOMPtr<nsILocalFile> doomedFileLocal = do_QueryInterface(aDoomedFile);
nsCAutoString doomedFilePath;
rv = doomedFileLocal->GetNativePath(doomedFilePath);
if (NS_FAILED(rv))
returnnsInstall::UNEXPECTED_ERROR;
#endif
tmpLocalFile = do_QueryInterface(renamedDoomedFile, &rv); // Convert to an nsILocalFile//get the doomedLeafname so we can convert its extension to .oldnsAutoString doomedLeafname;
nsCAutoString uniqueLeafName;
tmpLocalFile->GetLeafName(doomedLeafname);
// do not RFind on the native charset! UTF8 or Unicode are OKPRInt32 extpos = doomedLeafname.RFindChar('.');
if (extpos != -1)
{
// We found the extension;
doomedLeafname.Truncate(extpos + 1); //strip off the old extension
}
doomedLeafname.AppendLiteral("old");
//Now reset the doomedLeafname
tmpLocalFile->SetLeafName(doomedLeafname);
tmpLocalFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0644);
tmpLocalFile->GetNativeLeafName(uniqueLeafName);//this is the new "unique" doomedLeafname
rv = aDoomedFile->Clone(getter_AddRefs(renamedDoomedFile));// Reset renamedDoomed file so aDoomedfile// isn't changed during the MoveTo callif (NS_FAILED(rv))
result = nsInstall::UNEXPECTED_ERROR;
else
{
rv = renamedDoomedFile->MoveToNative(nsnull, uniqueLeafName);
if (NS_FAILED(rv))
{
// MoveToNative() failing is OK. It simply means that the file// was locked in memory and needs to be replaced on browser// shutdown or system reboot.//// Since renamedDoomedFile->MoveToNative() failed, it created a// 0 byte '-old' file that needs to be cleaned up.
tmpLocalFile->Remove(PR_FALSE);
}
else
{
// The implementation of MoveToNative() on some platforms (osx and win32) resets// the object to the 'moved to' filename. This is incorrect behavior. This// implementation will be fixed in the future. We need to take into account that// fix by setting renamedDoomedFile to the filename that it was moved to above.// See bug 200024.//// renamedDoomedFile needs to be reset because it's used later on in this// function.
rv = renamedDoomedFile->SetNativeLeafName(uniqueLeafName);
if (NS_FAILED(rv))
result = nsInstall::UNEXPECTED_ERROR;
}
}
#ifdef XP_MACOSX rv = doomedFileLocal->InitWithNativePath(doomedFilePath);
if (NS_FAILED(rv))
result = nsInstall::UNEXPECTED_ERROR;
#endifif (result == nsInstall::UNEXPECTED_ERROR)
returnresult;
}
// if aDoomedFile is still in the way, give up and return result.
aDoomedFile->Exists(&flagExists);
if ( flagExists )
returnresult;
nsCOMPtr<nsIFile> parentofDoomedFile;
nsCAutoString doomedLeafname;
rv = aDoomedFile->GetParent(getter_AddRefs(parentofDoomedFile));
if ( NS_SUCCEEDED(rv) )
rv = aDoomedFile->GetNativeLeafName(doomedLeafname);
if ( NS_SUCCEEDED(rv) )
{
rv = replacementFile->MoveToNative(parentofDoomedFile, doomedLeafname);
// The implementation of MoveToNative() on some platforms (osx and win32) resets// the object to the 'moved to' filename. This is incorrect behavior. This// implementation will be fixed in the future. We need to take into account that// fix by setting replacementFile to the filename that it was moved to above.// See bug 200024.//// However, since replacementFile is a clone of aReplacementFile and is also// not used beyond here, there's no need to set the path+leafname to what// it was MoveToNative()'ed to.
}
if (NS_SUCCEEDED(rv))
{
if (flagRenamedDoomedFileExists)
{
// we replaced the old file OK, now we have to// get rid of it if it was renamed out of the way
result = DeleteFileNowOrSchedule( renamedDoomedFile );
}
}
else
{
// couldn't rename file, try to put old file back
renamedDoomedFile->MoveToNative(nsnull, doomedLeafname);
// No need to reset remanedDoomedFile after a MoveToNative() call// because renamedDoomedFile is not used beyond here.
}
returnresult;
}