Bug 1127481 - Run the updater from the install directory instead of copying it. r=spohl

This commit is contained in:
Robert Strong 2015-04-28 22:41:03 -07:00
Родитель 84c09b9f81
Коммит e120b3ebb9
5 изменённых файлов: 145 добавлений и 37 удалений

Просмотреть файл

@ -1537,15 +1537,20 @@ function runUpdate(aExpectedExitValue, aExpectedStatus, aCallback) {
Assert.ok(updater.exists(), MSG_SHOULD_EXIST);
let updatesDir = getUpdatesPatchDir();
updater.copyToFollowingLinks(updatesDir, updater.leafName);
let updateBin = updatesDir.clone();
updateBin.append(updater.leafName);
if (updateBin.leafName == "updater.app") {
updateBin.append("Contents");
updateBin.append("MacOS");
updateBin.append("updater");
Assert.ok(updateBin.exists(), MSG_SHOULD_EXIST);
let updateBin;
if (IS_WIN) {
updateBin = updater.clone();
} else {
updater.copyToFollowingLinks(updatesDir, updater.leafName);
updateBin = updatesDir.clone();
updateBin.append(updater.leafName);
if (updateBin.leafName == "updater.app") {
updateBin.append("Contents");
updateBin.append("MacOS");
updateBin.append("updater");
}
}
Assert.ok(updateBin.exists(), MSG_SHOULD_EXIST);
let applyToDir = getApplyDirFile(null, true);
let applyToDirPath = applyToDir.path;
@ -2137,7 +2142,6 @@ function runUpdateUsingService(aInitialStatus, aExpectedStatus, aCheckSvcLog) {
}
let testBinDir = getGREBinDir();
updater.copyToFollowingLinks(testBinDir, updater.leafName);
updater.copyToFollowingLinks(updatesDir, updater.leafName);
// The service will execute maintenanceservice_installer.exe and
// will copy maintenanceservice.exe out of the same directory from
@ -2546,6 +2550,10 @@ function checkUpdateLogContents(aCompareLogFile, aExcludeDistributionDir) {
if (gSwitchApp) {
// Remove the lines which contain absolute paths
updateLogContents = updateLogContents.replace(/^Begin moving.*$/mg, "");
updateLogContents = updateLogContents.replace(/^ensure_remove: failed to remove file: .*$/mg, "");
updateLogContents = updateLogContents.replace(/^ensure_remove_recursive: unable to remove directory: .*$/mg, "");
updateLogContents = updateLogContents.replace(/^Removing tmpDir failed, err: -1$/mg, "");
updateLogContents = updateLogContents.replace(/^remove_recursive_on_reboot: .*$/mg, "");
}
updateLogContents = updateLogContents.replace(/\r/g, "");
// Replace error codes since they are different on each platform.

Просмотреть файл

@ -198,7 +198,7 @@ function finishCheckUpdateApplied() {
checkPostUpdateRunningFile(true);
checkAppBundleModTime();
checkFilesAfterUpdateSuccess(getApplyDirFile, false, false);
checkFilesAfterUpdateSuccess(getApplyDirFile, false, true);
gSwitchApp = true;
checkUpdateLogContents();
gSwitchApp = false;

Просмотреть файл

@ -202,7 +202,7 @@ function finishCheckUpdateApplied() {
checkPostUpdateRunningFile(true);
checkAppBundleModTime();
checkFilesAfterUpdateSuccess(getApplyDirFile, false, false);
checkFilesAfterUpdateSuccess(getApplyDirFile, false, true);
gSwitchApp = true;
checkUpdateLogContents();
gSwitchApp = false;

Просмотреть файл

@ -473,7 +473,8 @@ static int ensure_remove(const NS_tchar *path)
}
// Remove the directory pointed to by path and all of its files and sub-directories.
static int ensure_remove_recursive(const NS_tchar *path)
static int ensure_remove_recursive(const NS_tchar *path,
bool continueEnumOnFailure = false)
{
// We use lstat rather than stat here so that we can successfully remove
// symlinks.
@ -492,8 +493,8 @@ static int ensure_remove_recursive(const NS_tchar *path)
dir = NS_topendir(path);
if (!dir) {
LOG(("ensure_remove_recursive: path is not a directory: " LOG_S ", rv: %d, err: %d",
path, rv, errno));
LOG(("ensure_remove_recursive: unable to open directory: " LOG_S
", rv: %d, err: %d", path, rv, errno));
return rv;
}
@ -504,7 +505,7 @@ static int ensure_remove_recursive(const NS_tchar *path)
NS_tsnprintf(childPath, sizeof(childPath)/sizeof(childPath[0]),
NS_T("%s/%s"), path, entry->d_name);
rv = ensure_remove_recursive(childPath);
if (rv) {
if (rv && !continueEnumOnFailure) {
break;
}
}
@ -516,8 +517,8 @@ static int ensure_remove_recursive(const NS_tchar *path)
ensure_write_permissions(path);
rv = NS_trmdir(path);
if (rv) {
LOG(("ensure_remove_recursive: path is not a directory: " LOG_S ", rv: %d, err: %d",
path, rv, errno));
LOG(("ensure_remove_recursive: unable to remove directory: " LOG_S
", rv: %d, err: %d", path, rv, errno));
}
}
return rv;
@ -849,6 +850,73 @@ static int rename_file(const NS_tchar *spath, const NS_tchar *dpath,
return OK;
}
#ifdef XP_WIN
// Remove the directory pointed to by path and all of its files and
// sub-directories. If a file is in use move it to the tobedeleted directory
// and attempt to schedule removal of the file on reboot
static int remove_recursive_on_reboot(const NS_tchar *path, const NS_tchar *deleteDir)
{
struct NS_tstat_t sInfo;
int rv = NS_tlstat(path, &sInfo);
if (rv) {
// This error is benign
return rv;
}
if (!S_ISDIR(sInfo.st_mode)) {
NS_tchar tmpDeleteFile[MAXPATHLEN];
GetTempFileNameW(deleteDir, L"rep", 0, tmpDeleteFile);
NS_tremove(tmpDeleteFile);
rv = rename_file(path, tmpDeleteFile, false);
if (MoveFileEx(rv ? path : tmpDeleteFile, nullptr, MOVEFILE_DELAY_UNTIL_REBOOT)) {
LOG(("remove_recursive_on_reboot: file will be removed on OS reboot: "
LOG_S, rv ? path : tmpDeleteFile));
} else {
LOG(("remove_recursive_on_reboot: failed to schedule OS reboot removal of "
"file: " LOG_S, rv ? path : tmpDeleteFile));
}
return rv;
}
NS_tDIR *dir;
NS_tdirent *entry;
dir = NS_topendir(path);
if (!dir) {
LOG(("remove_recursive_on_reboot: unable to open directory: " LOG_S
", rv: %d, err: %d",
path, rv, errno));
return rv;
}
while ((entry = NS_treaddir(dir)) != 0) {
if (NS_tstrcmp(entry->d_name, NS_T(".")) &&
NS_tstrcmp(entry->d_name, NS_T(".."))) {
NS_tchar childPath[MAXPATHLEN];
NS_tsnprintf(childPath, sizeof(childPath)/sizeof(childPath[0]),
NS_T("%s/%s"), path, entry->d_name);
// There is no need to check the return value of this call since this
// function is only called after an update is successful and there is not
// much that can be done to recover if it isn't successful. There is also
// no need to log the value since it will have already been logged.
remove_recursive_on_reboot(childPath, deleteDir);
}
}
NS_tclosedir(dir);
if (rv == OK) {
ensure_write_permissions(path);
rv = NS_trmdir(path);
if (rv) {
LOG(("remove_recursive_on_reboot: unable to remove directory: " LOG_S
", rv: %d, err: %d", path, rv, errno));
}
}
return rv;
}
#endif
//-----------------------------------------------------------------------------
// Create a backup of the specified file by renaming it.
@ -2002,16 +2070,20 @@ ProcessReplaceRequest()
}
LOG(("Now, remove the tmpDir"));
rv = ensure_remove_recursive(tmpDir);
rv = ensure_remove_recursive(tmpDir, true);
if (rv) {
LOG(("Removing tmpDir failed, err: %d", rv));
#ifdef XP_WIN
if (MoveFileExW(tmpDir, nullptr, MOVEFILE_DELAY_UNTIL_REBOOT)) {
LOG(("tmpDir will be removed on OS reboot: " LOG_S, tmpDir));
} else {
LOG(("Failed to schedule OS reboot removal of directory: " LOG_S,
tmpDir));
NS_tchar deleteDir[MAXPATHLEN];
NS_tsnprintf(deleteDir, sizeof(deleteDir)/sizeof(deleteDir[0]),
NS_T("%s\\%s"), destDir, DELETE_DIR);
// Attempt to remove the tobedeleted directory and then recreate it if it
// was successfully removed.
_wrmdir(deleteDir);
if (NS_taccess(deleteDir, F_OK)) {
NS_tmkdir(deleteDir, 0755);
}
remove_recursive_on_reboot(tmpDir, deleteDir);
#endif
}
@ -2474,9 +2546,9 @@ int NS_main(int argc, NS_tchar **argv)
#ifdef XP_WIN
// On Windows, the current working directory of the process should be changed
// so that it's not locked.
NS_tchar tmpDir[MAXPATHLEN];
if (GetTempPathW(MAXPATHLEN, tmpDir)) {
NS_tchdir(tmpDir);
NS_tchar sysDir[MAX_PATH + 1] = { L'\0' };
if (GetSystemDirectoryW(sysDir, MAX_PATH + 1)) {
NS_tchdir(sysDir);
}
#endif
}

Просмотреть файл

@ -446,9 +446,10 @@ SwitchToUpdatedApp(nsIFile *greDir, nsIFile *updateDir,
nsresult rv;
// Steps:
// - copy updater into updates/0/MozUpdater/bgupdate/ dir
// - copy updater into updates/0/MozUpdater/bgupdate/ dir on all platforms
// except Windows
// - run updater with the correct arguments
#ifndef XP_WIN
nsCOMPtr<nsIFile> mozUpdaterDir;
rv = updateDir->Clone(getter_AddRefs(mozUpdaterDir));
if (NS_FAILED(rv)) {
@ -471,6 +472,7 @@ SwitchToUpdatedApp(nsIFile *greDir, nsIFile *updateDir,
LOG(("failed copying updater\n"));
return;
}
#endif
// We need to use the value returned from XRE_GetBinaryPath when attempting
// to restart the running application.
@ -490,15 +492,28 @@ SwitchToUpdatedApp(nsIFile *greDir, nsIFile *updateDir,
#ifdef XP_WIN
nsAutoString appFilePathW;
rv = appFile->GetPath(appFilePathW);
if (NS_FAILED(rv))
if (NS_FAILED(rv)) {
return;
}
NS_ConvertUTF16toUTF8 appFilePath(appFilePathW);
nsCOMPtr<nsIFile> updater;
rv = greDir->Clone(getter_AddRefs(updater));
if (NS_FAILED(rv)) {
return;
}
nsDependentCString leaf(kUpdaterBin);
rv = updater->AppendNative(leaf);
if (NS_FAILED(rv)) {
return;
}
nsAutoString updaterPathW;
rv = updater->GetPath(updaterPathW);
if (NS_FAILED(rv))
if (NS_FAILED(rv)) {
return;
}
NS_ConvertUTF16toUTF8 updaterPath(updaterPathW);
#else
@ -718,14 +733,15 @@ ApplyUpdate(nsIFile *greDir, nsIFile *updateDir, nsIFile *statusFile,
// Steps:
// - mark update as 'applying'
// - copy updater into update dir
// - copy updater into update dir on all platforms except Windows
// - run updater w/ appDir as the current working dir
#ifndef XP_WIN
nsCOMPtr<nsIFile> updater;
if (!CopyUpdaterIntoUpdateDir(greDir, appDir, updateDir, updater)) {
LOG(("failed copying updater\n"));
return;
}
#endif
// We need to use the value returned from XRE_GetBinaryPath when attempting
// to restart the running application.
@ -745,17 +761,29 @@ ApplyUpdate(nsIFile *greDir, nsIFile *updateDir, nsIFile *statusFile,
#ifdef XP_WIN
nsAutoString appFilePathW;
rv = appFile->GetPath(appFilePathW);
if (NS_FAILED(rv))
if (NS_FAILED(rv)) {
return;
}
NS_ConvertUTF16toUTF8 appFilePath(appFilePathW);
nsCOMPtr<nsIFile> updater;
rv = greDir->Clone(getter_AddRefs(updater));
if (NS_FAILED(rv)) {
return;
}
nsDependentCString leaf(kUpdaterBin);
rv = updater->AppendNative(leaf);
if (NS_FAILED(rv)) {
return;
}
nsAutoString updaterPathW;
rv = updater->GetPath(updaterPathW);
if (NS_FAILED(rv))
if (NS_FAILED(rv)) {
return;
}
NS_ConvertUTF16toUTF8 updaterPath(updaterPathW);
#else
nsAutoCString appFilePath;
rv = appFile->GetNativePath(appFilePath);