mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Mac v2 signing - Bug 1064523 - Create staging directory outside of the Mac bundle. r=bbondy
This commit is contained in:
parent
19489bfb24
commit
cddf6a2d9d
@ -25,7 +25,7 @@
|
|||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
|
|
||||||
// Wait 15 minutes for an update operation to run at most.
|
// Wait 15 minutes for an update operation to run at most.
|
||||||
// Updates usually take less than a minute so this seems like a
|
// Updates usually take less than a minute so this seems like a
|
||||||
// significantly large and safe amount of time to wait.
|
// significantly large and safe amount of time to wait.
|
||||||
static const int TIME_TO_WAIT_ON_UPDATER = 15 * 60 * 1000;
|
static const int TIME_TO_WAIT_ON_UPDATER = 15 * 60 * 1000;
|
||||||
char16_t* MakeCommandLine(int argc, char16_t **argv);
|
char16_t* MakeCommandLine(int argc, char16_t **argv);
|
||||||
@ -33,9 +33,9 @@ BOOL WriteStatusFailure(LPCWSTR updateDirPath, int errorCode);
|
|||||||
BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer, LPCWSTR siblingFilePath,
|
BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer, LPCWSTR siblingFilePath,
|
||||||
LPCWSTR newFileName);
|
LPCWSTR newFileName);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the update.status file and sets isApplying to true if
|
* Read the update.status file and sets isApplying to true if
|
||||||
* the status is set to applying
|
* the status is set to applying.
|
||||||
*
|
*
|
||||||
* @param updateDirPath The directory where update.status is stored
|
* @param updateDirPath The directory where update.status is stored
|
||||||
* @param isApplying Out parameter for specifying if the status
|
* @param isApplying Out parameter for specifying if the status
|
||||||
@ -54,8 +54,8 @@ IsStatusApplying(LPCWSTR updateDirPath, BOOL &isApplying)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsAutoHandle statusFile(CreateFileW(updateStatusFilePath, GENERIC_READ,
|
nsAutoHandle statusFile(CreateFileW(updateStatusFilePath, GENERIC_READ,
|
||||||
FILE_SHARE_READ |
|
FILE_SHARE_READ |
|
||||||
FILE_SHARE_WRITE |
|
FILE_SHARE_WRITE |
|
||||||
FILE_SHARE_DELETE,
|
FILE_SHARE_DELETE,
|
||||||
nullptr, OPEN_EXISTING, 0, nullptr));
|
nullptr, OPEN_EXISTING, 0, nullptr));
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ IsStatusApplying(LPCWSTR updateDirPath, BOOL &isApplying)
|
|||||||
LOG(("updater.exe returned status: %s", buf));
|
LOG(("updater.exe returned status: %s", buf));
|
||||||
|
|
||||||
const char kApplying[] = "applying";
|
const char kApplying[] = "applying";
|
||||||
isApplying = strncmp(buf, kApplying,
|
isApplying = strncmp(buf, kApplying,
|
||||||
sizeof(kApplying) - 1) == 0;
|
sizeof(kApplying) - 1) == 0;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -82,15 +82,51 @@ IsStatusApplying(LPCWSTR updateDirPath, BOOL &isApplying)
|
|||||||
/**
|
/**
|
||||||
* Determines whether we're staging an update.
|
* Determines whether we're staging an update.
|
||||||
*
|
*
|
||||||
* @param argc The argc value normally sent to updater.exe
|
* @param argc The argc value normally sent to updater.exe
|
||||||
* @param argv The argv value normally sent to updater.exe
|
* @param argv The argv value normally sent to updater.exe
|
||||||
* @param boolean True if we're staging an update
|
* @return boolean True if we're staging an update
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
IsUpdateBeingStaged(int argc, LPWSTR *argv)
|
IsUpdateBeingStaged(int argc, LPWSTR *argv)
|
||||||
{
|
{
|
||||||
// PID will be set to -1 if we're supposed to stage an update.
|
// PID will be set to -1 if we're supposed to stage an update.
|
||||||
return argc == 4 && !wcscmp(argv[3], L"-1");
|
return argc == 4 && !wcscmp(argv[3], L"-1") ||
|
||||||
|
argc == 5 && !wcscmp(argv[4], L"-1");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether the param only contains digits.
|
||||||
|
*
|
||||||
|
* @param str The string to check
|
||||||
|
* @param boolean True if the param only contains digits
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
IsDigits(WCHAR *str)
|
||||||
|
{
|
||||||
|
while (*str) {
|
||||||
|
if (!iswdigit(*str++)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether the command line contains just the directory to apply the
|
||||||
|
* update to (old command line) or if it contains the installation directory and
|
||||||
|
* the directory to apply the update to.
|
||||||
|
*
|
||||||
|
* @param argc The argc value normally sent to updater.exe
|
||||||
|
* @param argv The argv value normally sent to updater.exe
|
||||||
|
* @param boolean True if the command line contains just the directory to apply
|
||||||
|
* the update to
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
IsOldCommandline(int argc, LPWSTR *argv)
|
||||||
|
{
|
||||||
|
return argc == 4 && !wcscmp(argv[3], L"-1") ||
|
||||||
|
!wcscmp(argv[3], L"0/replace") ||
|
||||||
|
IsDigits(argv[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -103,19 +139,29 @@ IsUpdateBeingStaged(int argc, LPWSTR *argv)
|
|||||||
static BOOL
|
static BOOL
|
||||||
GetInstallationDir(int argcTmp, LPWSTR *argvTmp, WCHAR aResultDir[MAX_PATH + 1])
|
GetInstallationDir(int argcTmp, LPWSTR *argvTmp, WCHAR aResultDir[MAX_PATH + 1])
|
||||||
{
|
{
|
||||||
if (argcTmp < 2) {
|
int index = 3;
|
||||||
|
if (IsOldCommandline(argcTmp, argvTmp)) {
|
||||||
|
index = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argcTmp < index) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
wcsncpy(aResultDir, argvTmp[2], MAX_PATH);
|
wcsncpy(aResultDir, argvTmp[2], MAX_PATH);
|
||||||
WCHAR* backSlash = wcsrchr(aResultDir, L'\\');
|
WCHAR* backSlash = wcsrchr(aResultDir, L'\\');
|
||||||
// Make sure that the path does not include trailing backslashes
|
// Make sure that the path does not include trailing backslashes
|
||||||
if (backSlash && (backSlash[1] == L'\0')) {
|
if (backSlash && (backSlash[1] == L'\0')) {
|
||||||
*backSlash = L'\0';
|
*backSlash = L'\0';
|
||||||
}
|
}
|
||||||
bool backgroundUpdate = IsUpdateBeingStaged(argcTmp, argvTmp);
|
|
||||||
bool replaceRequest = (argcTmp >= 4 && wcsstr(argvTmp[3], L"/replace"));
|
// The new command line's argv[2] is always the installation directory.
|
||||||
if (backgroundUpdate || replaceRequest) {
|
if (index == 2) {
|
||||||
return PathRemoveFileSpecW(aResultDir);
|
bool backgroundUpdate = IsUpdateBeingStaged(argcTmp, argvTmp);
|
||||||
|
bool replaceRequest = (argcTmp >= 4 && wcsstr(argvTmp[3], L"/replace"));
|
||||||
|
if (backgroundUpdate || replaceRequest) {
|
||||||
|
return PathRemoveFileSpecW(aResultDir);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -145,18 +191,23 @@ StartUpdateProcess(int argc,
|
|||||||
// updater.exe update-dir apply [wait-pid [callback-dir callback-path args]]
|
// updater.exe update-dir apply [wait-pid [callback-dir callback-path args]]
|
||||||
LPWSTR cmdLine = MakeCommandLine(argc, argv);
|
LPWSTR cmdLine = MakeCommandLine(argc, argv);
|
||||||
|
|
||||||
|
int index = 3;
|
||||||
|
if (IsOldCommandline(argc, argv)) {
|
||||||
|
index = 2;
|
||||||
|
}
|
||||||
|
|
||||||
// If we're about to start the update process from session 0,
|
// If we're about to start the update process from session 0,
|
||||||
// then we should not show a GUI. This only really needs to be done
|
// then we should not show a GUI. This only really needs to be done
|
||||||
// on Vista and higher, but it's better to keep everything consistent
|
// on Vista and higher, but it's better to keep everything consistent
|
||||||
// across all OS if it's of no harm.
|
// across all OS if it's of no harm.
|
||||||
if (argc >= 2 ) {
|
if (argc >= index) {
|
||||||
// Setting the desktop to blank will ensure no GUI is displayed
|
// Setting the desktop to blank will ensure no GUI is displayed
|
||||||
si.lpDesktop = L"";
|
si.lpDesktop = L"";
|
||||||
si.dwFlags |= STARTF_USESHOWWINDOW;
|
si.dwFlags |= STARTF_USESHOWWINDOW;
|
||||||
si.wShowWindow = SW_HIDE;
|
si.wShowWindow = SW_HIDE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We move the updater.ini file out of the way because we will handle
|
// We move the updater.ini file out of the way because we will handle
|
||||||
// executing PostUpdate through the service. We handle PostUpdate from
|
// executing PostUpdate through the service. We handle PostUpdate from
|
||||||
// the service because there are some per user things that happen that
|
// the service because there are some per user things that happen that
|
||||||
// can't run in session 0 which we run updater.exe in.
|
// can't run in session 0 which we run updater.exe in.
|
||||||
@ -169,7 +220,7 @@ StartUpdateProcess(int argc,
|
|||||||
// because of background updates.
|
// because of background updates.
|
||||||
if (PathGetSiblingFilePath(updaterINI, argv[0], L"updater.ini") &&
|
if (PathGetSiblingFilePath(updaterINI, argv[0], L"updater.ini") &&
|
||||||
PathGetSiblingFilePath(updaterINITemp, argv[0], L"updater.tmp")) {
|
PathGetSiblingFilePath(updaterINITemp, argv[0], L"updater.tmp")) {
|
||||||
selfHandlePostUpdate = MoveFileExW(updaterINI, updaterINITemp,
|
selfHandlePostUpdate = MoveFileExW(updaterINI, updaterINITemp,
|
||||||
MOVEFILE_REPLACE_EXISTING);
|
MOVEFILE_REPLACE_EXISTING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,14 +229,14 @@ StartUpdateProcess(int argc,
|
|||||||
// Search in updater.cpp for more info on MOZ_USING_SERVICE.
|
// Search in updater.cpp for more info on MOZ_USING_SERVICE.
|
||||||
putenv(const_cast<char*>("MOZ_USING_SERVICE=1"));
|
putenv(const_cast<char*>("MOZ_USING_SERVICE=1"));
|
||||||
LOG(("Starting service with cmdline: %ls", cmdLine));
|
LOG(("Starting service with cmdline: %ls", cmdLine));
|
||||||
processStarted = CreateProcessW(argv[0], cmdLine,
|
processStarted = CreateProcessW(argv[0], cmdLine,
|
||||||
nullptr, nullptr, FALSE,
|
nullptr, nullptr, FALSE,
|
||||||
CREATE_DEFAULT_ERROR_MODE,
|
CREATE_DEFAULT_ERROR_MODE,
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr, &si, &pi);
|
nullptr, &si, &pi);
|
||||||
// Empty value on putenv is how you remove an env variable in Windows
|
// Empty value on putenv is how you remove an env variable in Windows
|
||||||
putenv(const_cast<char*>("MOZ_USING_SERVICE="));
|
putenv(const_cast<char*>("MOZ_USING_SERVICE="));
|
||||||
|
|
||||||
BOOL updateWasSuccessful = FALSE;
|
BOOL updateWasSuccessful = FALSE;
|
||||||
if (processStarted) {
|
if (processStarted) {
|
||||||
// Wait for the updater process to finish
|
// Wait for the updater process to finish
|
||||||
@ -216,7 +267,7 @@ StartUpdateProcess(int argc,
|
|||||||
if (updateWasSuccessful) {
|
if (updateWasSuccessful) {
|
||||||
LOG(("update.status is still applying even know update "
|
LOG(("update.status is still applying even know update "
|
||||||
" was successful."));
|
" was successful."));
|
||||||
if (!WriteStatusFailure(argv[1],
|
if (!WriteStatusFailure(argv[1],
|
||||||
SERVICE_STILL_APPLYING_ON_SUCCESS)) {
|
SERVICE_STILL_APPLYING_ON_SUCCESS)) {
|
||||||
LOG_WARN(("Could not write update.status still applying on"
|
LOG_WARN(("Could not write update.status still applying on"
|
||||||
" success error."));
|
" success error."));
|
||||||
@ -226,7 +277,7 @@ StartUpdateProcess(int argc,
|
|||||||
updateWasSuccessful = FALSE;
|
updateWasSuccessful = FALSE;
|
||||||
} else {
|
} else {
|
||||||
LOG_WARN(("update.status is still applying and update was not successful."));
|
LOG_WARN(("update.status is still applying and update was not successful."));
|
||||||
if (!WriteStatusFailure(argv[1],
|
if (!WriteStatusFailure(argv[1],
|
||||||
SERVICE_STILL_APPLYING_ON_FAILURE)) {
|
SERVICE_STILL_APPLYING_ON_FAILURE)) {
|
||||||
LOG_WARN(("Could not write update.status still applying on"
|
LOG_WARN(("Could not write update.status still applying on"
|
||||||
" success error."));
|
" success error."));
|
||||||
@ -241,18 +292,18 @@ StartUpdateProcess(int argc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Now that we're done with the update, restore back the updater.ini file
|
// Now that we're done with the update, restore back the updater.ini file
|
||||||
// We use it ourselves, and also we want it back in case we had any type
|
// We use it ourselves, and also we want it back in case we had any type
|
||||||
// of error so that the normal update process can use it.
|
// of error so that the normal update process can use it.
|
||||||
if (selfHandlePostUpdate) {
|
if (selfHandlePostUpdate) {
|
||||||
MoveFileExW(updaterINITemp, updaterINI, MOVEFILE_REPLACE_EXISTING);
|
MoveFileExW(updaterINITemp, updaterINI, MOVEFILE_REPLACE_EXISTING);
|
||||||
|
|
||||||
// Only run the PostUpdate if the update was successful
|
// Only run the PostUpdate if the update was successful
|
||||||
if (updateWasSuccessful && argc > 2) {
|
if (updateWasSuccessful && argc > index) {
|
||||||
LPCWSTR updateInfoDir = argv[1];
|
LPCWSTR updateInfoDir = argv[1];
|
||||||
bool backgroundUpdate = IsUpdateBeingStaged(argc, argv);
|
bool stagingUpdate = IsUpdateBeingStaged(argc, argv);
|
||||||
|
|
||||||
// Launch the PostProcess with admin access in session 0. This is
|
// Launch the PostProcess with admin access in session 0. This is
|
||||||
// actually launching the post update process but it takes in the
|
// actually launching the post update process but it takes in the
|
||||||
// callback app path to figure out where to apply to.
|
// callback app path to figure out where to apply to.
|
||||||
// The PostUpdate process with user only access will be done inside
|
// The PostUpdate process with user only access will be done inside
|
||||||
// the unelevated updater.exe after the update process is complete
|
// the unelevated updater.exe after the update process is complete
|
||||||
@ -261,7 +312,7 @@ StartUpdateProcess(int argc,
|
|||||||
// Note that we don't need to do this if we're just staging the
|
// Note that we don't need to do this if we're just staging the
|
||||||
// update in the background, as the PostUpdate step runs when
|
// update in the background, as the PostUpdate step runs when
|
||||||
// performing the replacing in that case.
|
// performing the replacing in that case.
|
||||||
if (!backgroundUpdate) {
|
if (!stagingUpdate) {
|
||||||
LOG(("Launching post update process as the service in session 0."));
|
LOG(("Launching post update process as the service in session 0."));
|
||||||
if (!LaunchWinPostProcess(installDir, updateInfoDir, true, nullptr)) {
|
if (!LaunchWinPostProcess(installDir, updateInfoDir, true, nullptr)) {
|
||||||
LOG_WARN(("The post update process could not be launched."
|
LOG_WARN(("The post update process could not be launched."
|
||||||
@ -294,8 +345,8 @@ ProcessSoftwareUpdateCommand(DWORD argc, LPWSTR *argv)
|
|||||||
|
|
||||||
// We can only update update.status if argv[1] exists. argv[1] is
|
// We can only update update.status if argv[1] exists. argv[1] is
|
||||||
// the directory where the update.status file exists.
|
// the directory where the update.status file exists.
|
||||||
if (argc < 2 ||
|
if (argc < 2 ||
|
||||||
!WriteStatusFailure(argv[1],
|
!WriteStatusFailure(argv[1],
|
||||||
SERVICE_NOT_ENOUGH_COMMAND_LINE_ARGS)) {
|
SERVICE_NOT_ENOUGH_COMMAND_LINE_ARGS)) {
|
||||||
LOG_WARN(("Could not write update.status service update failure. (%d)",
|
LOG_WARN(("Could not write update.status service update failure. (%d)",
|
||||||
GetLastError()));
|
GetLastError()));
|
||||||
@ -320,7 +371,7 @@ ProcessSoftwareUpdateCommand(DWORD argc, LPWSTR *argv)
|
|||||||
if (!IsLocalFile(argv[0], isLocal) || !isLocal) {
|
if (!IsLocalFile(argv[0], isLocal) || !isLocal) {
|
||||||
LOG_WARN(("Filesystem in path %ls is not supported (%d)",
|
LOG_WARN(("Filesystem in path %ls is not supported (%d)",
|
||||||
argv[0], GetLastError()));
|
argv[0], GetLastError()));
|
||||||
if (!WriteStatusFailure(argv[1],
|
if (!WriteStatusFailure(argv[1],
|
||||||
SERVICE_UPDATER_NOT_FIXED_DRIVE)) {
|
SERVICE_UPDATER_NOT_FIXED_DRIVE)) {
|
||||||
LOG_WARN(("Could not write update.status service update failure. (%d)",
|
LOG_WARN(("Could not write update.status service update failure. (%d)",
|
||||||
GetLastError()));
|
GetLastError()));
|
||||||
@ -328,12 +379,12 @@ ProcessSoftwareUpdateCommand(DWORD argc, LPWSTR *argv)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsAutoHandle noWriteLock(CreateFileW(argv[0], GENERIC_READ, FILE_SHARE_READ,
|
nsAutoHandle noWriteLock(CreateFileW(argv[0], GENERIC_READ, FILE_SHARE_READ,
|
||||||
nullptr, OPEN_EXISTING, 0, nullptr));
|
nullptr, OPEN_EXISTING, 0, nullptr));
|
||||||
if (INVALID_HANDLE_VALUE == noWriteLock) {
|
if (INVALID_HANDLE_VALUE == noWriteLock) {
|
||||||
LOG_WARN(("Could not set no write sharing access on file. (%d)",
|
LOG_WARN(("Could not set no write sharing access on file. (%d)",
|
||||||
GetLastError()));
|
GetLastError()));
|
||||||
if (!WriteStatusFailure(argv[1],
|
if (!WriteStatusFailure(argv[1],
|
||||||
SERVICE_COULD_NOT_LOCK_UPDATER)) {
|
SERVICE_COULD_NOT_LOCK_UPDATER)) {
|
||||||
LOG_WARN(("Could not write update.status service update failure. (%d)",
|
LOG_WARN(("Could not write update.status service update failure. (%d)",
|
||||||
GetLastError()));
|
GetLastError()));
|
||||||
@ -352,7 +403,7 @@ ProcessSoftwareUpdateCommand(DWORD argc, LPWSTR *argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
BOOL updaterIsCorrect;
|
BOOL updaterIsCorrect;
|
||||||
if (result && !VerifySameFiles(argv[0], installDirUpdater,
|
if (result && !VerifySameFiles(argv[0], installDirUpdater,
|
||||||
updaterIsCorrect)) {
|
updaterIsCorrect)) {
|
||||||
LOG_WARN(("Error checking if the updaters are the same.\n"
|
LOG_WARN(("Error checking if the updaters are the same.\n"
|
||||||
"Path 1: %ls\nPath 2: %ls", argv[0], installDirUpdater));
|
"Path 1: %ls\nPath 2: %ls", argv[0], installDirUpdater));
|
||||||
@ -360,7 +411,7 @@ ProcessSoftwareUpdateCommand(DWORD argc, LPWSTR *argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (result && !updaterIsCorrect) {
|
if (result && !updaterIsCorrect) {
|
||||||
LOG_WARN(("The updaters do not match, updater will not run."));
|
LOG_WARN(("The updaters do not match, updater will not run."));
|
||||||
result = FALSE;
|
result = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,7 +419,7 @@ ProcessSoftwareUpdateCommand(DWORD argc, LPWSTR *argv)
|
|||||||
LOG(("updater.exe was compared successfully to the installation directory"
|
LOG(("updater.exe was compared successfully to the installation directory"
|
||||||
" updater.exe."));
|
" updater.exe."));
|
||||||
} else {
|
} else {
|
||||||
if (!WriteStatusFailure(argv[1],
|
if (!WriteStatusFailure(argv[1],
|
||||||
SERVICE_UPDATER_COMPARE_ERROR)) {
|
SERVICE_UPDATER_COMPARE_ERROR)) {
|
||||||
LOG_WARN(("Could not write update.status updater compare failure."));
|
LOG_WARN(("Could not write update.status updater compare failure."));
|
||||||
}
|
}
|
||||||
@ -378,14 +429,14 @@ ProcessSoftwareUpdateCommand(DWORD argc, LPWSTR *argv)
|
|||||||
// Check to make sure the updater.exe module has the unique updater identity.
|
// Check to make sure the updater.exe module has the unique updater identity.
|
||||||
// This is a security measure to make sure that the signed executable that
|
// This is a security measure to make sure that the signed executable that
|
||||||
// we will run is actually an updater.
|
// we will run is actually an updater.
|
||||||
HMODULE updaterModule = LoadLibraryEx(argv[0], nullptr,
|
HMODULE updaterModule = LoadLibraryEx(argv[0], nullptr,
|
||||||
LOAD_LIBRARY_AS_DATAFILE);
|
LOAD_LIBRARY_AS_DATAFILE);
|
||||||
if (!updaterModule) {
|
if (!updaterModule) {
|
||||||
LOG_WARN(("updater.exe module could not be loaded. (%d)", GetLastError()));
|
LOG_WARN(("updater.exe module could not be loaded. (%d)", GetLastError()));
|
||||||
result = FALSE;
|
result = FALSE;
|
||||||
} else {
|
} else {
|
||||||
char updaterIdentity[64];
|
char updaterIdentity[64];
|
||||||
if (!LoadStringA(updaterModule, IDS_UPDATER_IDENTITY,
|
if (!LoadStringA(updaterModule, IDS_UPDATER_IDENTITY,
|
||||||
updaterIdentity, sizeof(updaterIdentity))) {
|
updaterIdentity, sizeof(updaterIdentity))) {
|
||||||
LOG_WARN(("The updater.exe application does not contain the Mozilla"
|
LOG_WARN(("The updater.exe application does not contain the Mozilla"
|
||||||
" updater identity."));
|
" updater identity."));
|
||||||
@ -403,7 +454,7 @@ ProcessSoftwareUpdateCommand(DWORD argc, LPWSTR *argv)
|
|||||||
LOG(("The updater.exe application contains the Mozilla"
|
LOG(("The updater.exe application contains the Mozilla"
|
||||||
" updater identity."));
|
" updater identity."));
|
||||||
} else {
|
} else {
|
||||||
if (!WriteStatusFailure(argv[1],
|
if (!WriteStatusFailure(argv[1],
|
||||||
SERVICE_UPDATER_IDENTITY_ERROR)) {
|
SERVICE_UPDATER_IDENTITY_ERROR)) {
|
||||||
LOG_WARN(("Could not write update.status no updater identity."));
|
LOG_WARN(("Could not write update.status no updater identity."));
|
||||||
}
|
}
|
||||||
@ -438,12 +489,12 @@ ProcessSoftwareUpdateCommand(DWORD argc, LPWSTR *argv)
|
|||||||
LogFlush();
|
LogFlush();
|
||||||
|
|
||||||
// If the update process was started, then updater.exe is responsible for
|
// If the update process was started, then updater.exe is responsible for
|
||||||
// setting the failure code. If it could not be started then we do the
|
// setting the failure code. If it could not be started then we do the
|
||||||
// work. We set an error instead of directly setting status pending
|
// work. We set an error instead of directly setting status pending
|
||||||
// so that the app.update.service.errors pref can be updated when
|
// so that the app.update.service.errors pref can be updated when
|
||||||
// the callback app restarts.
|
// the callback app restarts.
|
||||||
if (!updateProcessWasStarted) {
|
if (!updateProcessWasStarted) {
|
||||||
if (!WriteStatusFailure(argv[1],
|
if (!WriteStatusFailure(argv[1],
|
||||||
SERVICE_UPDATER_COULD_NOT_BE_STARTED)) {
|
SERVICE_UPDATER_COULD_NOT_BE_STARTED)) {
|
||||||
LOG_WARN(("Could not write update.status service update failure. (%d)",
|
LOG_WARN(("Could not write update.status service update failure. (%d)",
|
||||||
GetLastError()));
|
GetLastError()));
|
||||||
@ -457,7 +508,7 @@ ProcessSoftwareUpdateCommand(DWORD argc, LPWSTR *argv)
|
|||||||
|
|
||||||
// When there is a certificate check error on the updater.exe application,
|
// When there is a certificate check error on the updater.exe application,
|
||||||
// we want to write out the error.
|
// we want to write out the error.
|
||||||
if (!WriteStatusFailure(argv[1],
|
if (!WriteStatusFailure(argv[1],
|
||||||
SERVICE_UPDATER_SIGN_ERROR)) {
|
SERVICE_UPDATER_SIGN_ERROR)) {
|
||||||
LOG_WARN(("Could not write pending state to update.status. (%d)",
|
LOG_WARN(("Could not write pending state to update.status. (%d)",
|
||||||
GetLastError()));
|
GetLastError()));
|
||||||
@ -547,7 +598,7 @@ DeleteSecureUpdater(WCHAR serviceUpdaterPath[MAX_PATH + 1])
|
|||||||
* @param argv The service command line arguments, argv[0] and argv[1]
|
* @param argv The service command line arguments, argv[0] and argv[1]
|
||||||
* and automatically included by Windows. argv[2] is the
|
* and automatically included by Windows. argv[2] is the
|
||||||
* service command.
|
* service command.
|
||||||
*
|
*
|
||||||
* @return FALSE if there was an error executing the service command.
|
* @return FALSE if there was an error executing the service command.
|
||||||
*/
|
*/
|
||||||
BOOL
|
BOOL
|
||||||
@ -558,7 +609,7 @@ ExecuteServiceCommand(int argc, LPWSTR *argv)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The tests work by making sure the log has changed, so we put a
|
// The tests work by making sure the log has changed, so we put a
|
||||||
// unique ID in the log.
|
// unique ID in the log.
|
||||||
RPC_WSTR guidString = RPC_WSTR(L"");
|
RPC_WSTR guidString = RPC_WSTR(L"");
|
||||||
GUID guid;
|
GUID guid;
|
||||||
|
@ -612,7 +612,17 @@ XPCOMUtils.defineLazyGetter(this, "gCanApplyUpdates", function aus_gCanApplyUpda
|
|||||||
var updateTestFile = getUpdateFile([FILE_PERMS_TEST]);
|
var updateTestFile = getUpdateFile([FILE_PERMS_TEST]);
|
||||||
LOG("gCanApplyUpdates - testing write access " + updateTestFile.path);
|
LOG("gCanApplyUpdates - testing write access " + updateTestFile.path);
|
||||||
testWriteAccess(updateTestFile, false);
|
testWriteAccess(updateTestFile, false);
|
||||||
#ifdef XP_WIN
|
#ifdef XP_MACOSX
|
||||||
|
// Check that the application bundle can be written to.
|
||||||
|
var appDirTestFile = getAppBaseDir();
|
||||||
|
appDirTestFile.append(FILE_PERMS_TEST);
|
||||||
|
LOG("gCanApplyUpdates - testing write access " + appDirTestFile.path);
|
||||||
|
if (appDirTestFile.exists()) {
|
||||||
|
appDirTestFile.remove(false)
|
||||||
|
}
|
||||||
|
appDirTestFile.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
|
||||||
|
appDirTestFile.remove(false);
|
||||||
|
#elifdef XP_WIN
|
||||||
var sysInfo = Cc["@mozilla.org/system-info;1"].
|
var sysInfo = Cc["@mozilla.org/system-info;1"].
|
||||||
getService(Ci.nsIPropertyBag2);
|
getService(Ci.nsIPropertyBag2);
|
||||||
|
|
||||||
@ -997,7 +1007,7 @@ function getUpdatesDir() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the Active Updates directory inside the directory where we apply the
|
* Get the Active Updates directory inside the directory where we apply the
|
||||||
* background updates.
|
* staged update.
|
||||||
* @return The active updates directory inside the updated directory, as a
|
* @return The active updates directory inside the updated directory, as a
|
||||||
* nsIFile object.
|
* nsIFile object.
|
||||||
*/
|
*/
|
||||||
|
@ -195,7 +195,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct MARChannelStringTable {
|
struct MARChannelStringTable {
|
||||||
MARChannelStringTable()
|
MARChannelStringTable()
|
||||||
{
|
{
|
||||||
MARChannelID[0] = '\0';
|
MARChannelID[0] = '\0';
|
||||||
}
|
}
|
||||||
@ -268,8 +268,9 @@ private:
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
static NS_tchar* gSourcePath;
|
static NS_tchar* gPatchDirPath;
|
||||||
static NS_tchar gDestinationPath[MAXPATHLEN];
|
static NS_tchar gInstallDirPath[MAXPATHLEN];
|
||||||
|
static NS_tchar gWorkingDirPath[MAXPATHLEN];
|
||||||
static ArchiveReader gArchiveReader;
|
static ArchiveReader gArchiveReader;
|
||||||
static bool gSucceeded = false;
|
static bool gSucceeded = false;
|
||||||
static bool sStagedUpdate = false;
|
static bool sStagedUpdate = false;
|
||||||
@ -1369,7 +1370,7 @@ PatchFile::Prepare()
|
|||||||
mPatchIndex = sPatchIndex++;
|
mPatchIndex = sPatchIndex++;
|
||||||
|
|
||||||
NS_tsnprintf(spath, sizeof(spath)/sizeof(spath[0]),
|
NS_tsnprintf(spath, sizeof(spath)/sizeof(spath[0]),
|
||||||
NS_T("%s/updating/%d.patch"), gDestinationPath, mPatchIndex);
|
NS_T("%s/updating/%d.patch"), gWorkingDirPath, mPatchIndex);
|
||||||
|
|
||||||
NS_tremove(spath);
|
NS_tremove(spath);
|
||||||
|
|
||||||
@ -1738,9 +1739,9 @@ IsUpdateFromMetro(int argc, NS_tchar **argv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
LaunchCallbackApp(const NS_tchar *workingDir,
|
LaunchCallbackApp(const NS_tchar *workingDir,
|
||||||
int argc,
|
int argc,
|
||||||
NS_tchar **argv,
|
NS_tchar **argv,
|
||||||
bool usingService)
|
bool usingService)
|
||||||
{
|
{
|
||||||
putenv(const_cast<char*>("NO_EM_RESTART="));
|
putenv(const_cast<char*>("NO_EM_RESTART="));
|
||||||
@ -1781,7 +1782,7 @@ WriteStatusFile(const char* aStatus)
|
|||||||
{
|
{
|
||||||
NS_tchar filename[MAXPATHLEN];
|
NS_tchar filename[MAXPATHLEN];
|
||||||
NS_tsnprintf(filename, sizeof(filename)/sizeof(filename[0]),
|
NS_tsnprintf(filename, sizeof(filename)/sizeof(filename[0]),
|
||||||
NS_T("%s/update.status"), gSourcePath);
|
NS_T("%s/update.status"), gPatchDirPath);
|
||||||
|
|
||||||
// Make sure that the directory for the update status file exists
|
// Make sure that the directory for the update status file exists
|
||||||
if (ensure_parent_dir(filename))
|
if (ensure_parent_dir(filename))
|
||||||
@ -1818,7 +1819,7 @@ WriteStatusFile(int status)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MOZ_MAINTENANCE_SERVICE
|
#ifdef MOZ_MAINTENANCE_SERVICE
|
||||||
/*
|
/*
|
||||||
* Read the update.status file and sets isPendingService to true if
|
* Read the update.status file and sets isPendingService to true if
|
||||||
* the status is set to pending-service.
|
* the status is set to pending-service.
|
||||||
*
|
*
|
||||||
@ -1832,7 +1833,7 @@ IsUpdateStatusPendingService()
|
|||||||
{
|
{
|
||||||
NS_tchar filename[MAXPATHLEN];
|
NS_tchar filename[MAXPATHLEN];
|
||||||
NS_tsnprintf(filename, sizeof(filename)/sizeof(filename[0]),
|
NS_tsnprintf(filename, sizeof(filename)/sizeof(filename[0]),
|
||||||
NS_T("%s/update.status"), gSourcePath);
|
NS_T("%s/update.status"), gPatchDirPath);
|
||||||
|
|
||||||
AutoFile file(NS_tfopen(filename, NS_T("rb")));
|
AutoFile file(NS_tfopen(filename, NS_T("rb")));
|
||||||
if (file == nullptr)
|
if (file == nullptr)
|
||||||
@ -1844,7 +1845,7 @@ IsUpdateStatusPendingService()
|
|||||||
const char kPendingService[] = "pending-service";
|
const char kPendingService[] = "pending-service";
|
||||||
const char kAppliedService[] = "applied-service";
|
const char kAppliedService[] = "applied-service";
|
||||||
|
|
||||||
return (strncmp(buf, kPendingService,
|
return (strncmp(buf, kPendingService,
|
||||||
sizeof(kPendingService) - 1) == 0) ||
|
sizeof(kPendingService) - 1) == 0) ||
|
||||||
(strncmp(buf, kAppliedService,
|
(strncmp(buf, kAppliedService,
|
||||||
sizeof(kAppliedService) - 1) == 0);
|
sizeof(kAppliedService) - 1) == 0);
|
||||||
@ -1852,7 +1853,7 @@ IsUpdateStatusPendingService()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
/*
|
/*
|
||||||
* Read the update.status file and sets isSuccess to true if
|
* Read the update.status file and sets isSuccess to true if
|
||||||
* the status is set to succeeded.
|
* the status is set to succeeded.
|
||||||
*
|
*
|
||||||
@ -1866,7 +1867,7 @@ IsUpdateStatusSucceeded(bool &isSucceeded)
|
|||||||
isSucceeded = false;
|
isSucceeded = false;
|
||||||
NS_tchar filename[MAXPATHLEN];
|
NS_tchar filename[MAXPATHLEN];
|
||||||
NS_tsnprintf(filename, sizeof(filename)/sizeof(filename[0]),
|
NS_tsnprintf(filename, sizeof(filename)/sizeof(filename[0]),
|
||||||
NS_T("%s/update.status"), gSourcePath);
|
NS_T("%s/update.status"), gPatchDirPath);
|
||||||
|
|
||||||
AutoFile file(NS_tfopen(filename, NS_T("rb")));
|
AutoFile file(NS_tfopen(filename, NS_T("rb")));
|
||||||
if (file == nullptr)
|
if (file == nullptr)
|
||||||
@ -1876,42 +1877,12 @@ IsUpdateStatusSucceeded(bool &isSucceeded)
|
|||||||
fread(buf, sizeof(buf), 1, file);
|
fread(buf, sizeof(buf), 1, file);
|
||||||
|
|
||||||
const char kSucceeded[] = "succeeded";
|
const char kSucceeded[] = "succeeded";
|
||||||
isSucceeded = strncmp(buf, kSucceeded,
|
isSucceeded = strncmp(buf, kSucceeded,
|
||||||
sizeof(kSucceeded) - 1) == 0;
|
sizeof(kSucceeded) - 1) == 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the application installation directory.
|
|
||||||
*
|
|
||||||
* @param installDir Out parameter for specifying the installation directory.
|
|
||||||
* @return true if successful, false otherwise.
|
|
||||||
*/
|
|
||||||
template <size_t N>
|
|
||||||
static bool
|
|
||||||
GetInstallationDir(NS_tchar (&installDir)[N])
|
|
||||||
{
|
|
||||||
NS_tsnprintf(installDir, N, NS_T("%s"), gDestinationPath);
|
|
||||||
if (!sStagedUpdate && !sReplaceRequest) {
|
|
||||||
// no need to do any further processing
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_tchar *slash = (NS_tchar *) NS_tstrrchr(installDir, NS_SLASH);
|
|
||||||
// Make sure we're not looking at a trailing slash
|
|
||||||
if (slash && slash[1] == NS_T('\0')) {
|
|
||||||
*slash = NS_T('\0');
|
|
||||||
slash = (NS_tchar *) NS_tstrrchr(installDir, NS_SLASH);
|
|
||||||
}
|
|
||||||
if (slash) {
|
|
||||||
*slash = NS_T('\0');
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy the entire contents of the application installation directory to the
|
* Copy the entire contents of the application installation directory to the
|
||||||
* destination directory for the update process.
|
* destination directory for the update process.
|
||||||
@ -1921,32 +1892,24 @@ GetInstallationDir(NS_tchar (&installDir)[N])
|
|||||||
static int
|
static int
|
||||||
CopyInstallDirToDestDir()
|
CopyInstallDirToDestDir()
|
||||||
{
|
{
|
||||||
// First extract the installation directory from gSourcePath by going two
|
|
||||||
// levels above it. This is effectively skipping over "updates/0".
|
|
||||||
NS_tchar installDir[MAXPATHLEN];
|
|
||||||
if (!GetInstallationDir(installDir)) {
|
|
||||||
return NO_INSTALLDIR_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// These files should not be copied over to the updated app
|
// These files should not be copied over to the updated app
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
#define SKIPLIST_COUNT 3
|
#define SKIPLIST_COUNT 3
|
||||||
|
#elif XP_MACOSX
|
||||||
|
#define SKIPLIST_COUNT 0
|
||||||
#else
|
#else
|
||||||
#define SKIPLIST_COUNT 2
|
#define SKIPLIST_COUNT 2
|
||||||
#endif
|
#endif
|
||||||
copy_recursive_skiplist<SKIPLIST_COUNT> skiplist;
|
copy_recursive_skiplist<SKIPLIST_COUNT> skiplist;
|
||||||
#ifdef XP_MACOSX
|
#ifndef XP_MACOSX
|
||||||
skiplist.append(0, installDir, NS_T("Updated.app"));
|
skiplist.append(0, gInstallDirPath, NS_T("updated"));
|
||||||
skiplist.append(1, installDir, NS_T("Contents/MacOS/updates/0"));
|
skiplist.append(1, gInstallDirPath, NS_T("updates/0"));
|
||||||
#else
|
|
||||||
skiplist.append(0, installDir, NS_T("updated"));
|
|
||||||
skiplist.append(1, installDir, NS_T("updates/0"));
|
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
skiplist.append(2, installDir, NS_T("updated.update_in_progress.lock"));
|
skiplist.append(2, gInstallDirPath, NS_T("updated.update_in_progress.lock"));
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return ensure_copy_recursive(installDir, gDestinationPath, skiplist);
|
return ensure_copy_recursive(gInstallDirPath, gWorkingDirPath, skiplist);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1959,54 +1922,50 @@ static int
|
|||||||
ProcessReplaceRequest()
|
ProcessReplaceRequest()
|
||||||
{
|
{
|
||||||
// The replacement algorithm is like this:
|
// The replacement algorithm is like this:
|
||||||
// 1. Move sourceDir to tmpDir. In case of failure, abort.
|
// 1. Move destDir to tmpDir. In case of failure, abort.
|
||||||
// 2. Move newDir to sourceDir. In case of failure, revert step 1 and abort.
|
// 2. Move newDir to destDir. In case of failure, revert step 1 and abort.
|
||||||
// 3. Delete tmpDir (or defer it to the next reboot).
|
// 3. Delete tmpDir (or defer it to the next reboot).
|
||||||
|
|
||||||
NS_tchar installDir[MAXPATHLEN];
|
|
||||||
if (!GetInstallationDir(installDir)) {
|
|
||||||
return NO_INSTALLDIR_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
NS_tchar sourceDir[MAXPATHLEN];
|
NS_tchar destDir[MAXPATHLEN];
|
||||||
NS_tsnprintf(sourceDir, sizeof(sourceDir)/sizeof(sourceDir[0]),
|
NS_tsnprintf(destDir, sizeof(destDir)/sizeof(destDir[0]),
|
||||||
NS_T("%s/Contents"), installDir);
|
NS_T("%s/Contents"), gInstallDirPath);
|
||||||
#elif XP_WIN
|
#elif XP_WIN
|
||||||
// Windows preserves the case of the file/directory names. We use the
|
// Windows preserves the case of the file/directory names. We use the
|
||||||
// GetLongPathName API in order to get the correct case for the directory
|
// GetLongPathName API in order to get the correct case for the directory
|
||||||
// name, so that if the user has used a different case when launching the
|
// name, so that if the user has used a different case when launching the
|
||||||
// application, the installation directory's name does not change.
|
// application, the installation directory's name does not change.
|
||||||
NS_tchar sourceDir[MAXPATHLEN];
|
NS_tchar destDir[MAXPATHLEN];
|
||||||
if (!GetLongPathNameW(installDir, sourceDir, sizeof(sourceDir)/sizeof(sourceDir[0]))) {
|
if (!GetLongPathNameW(gInstallDirPath, destDir, sizeof(destDir)/sizeof(destDir[0]))) {
|
||||||
return NO_INSTALLDIR_ERROR;
|
return NO_INSTALLDIR_ERROR;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
NS_tchar* sourceDir = installDir;
|
NS_tchar* destDir = gInstallDirPath;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NS_tchar tmpDir[MAXPATHLEN];
|
NS_tchar tmpDir[MAXPATHLEN];
|
||||||
NS_tsnprintf(tmpDir, sizeof(tmpDir)/sizeof(tmpDir[0]),
|
NS_tsnprintf(tmpDir, sizeof(tmpDir)/sizeof(tmpDir[0]),
|
||||||
NS_T("%s.bak"), sourceDir);
|
NS_T("%s.bak"), destDir);
|
||||||
|
|
||||||
NS_tchar newDir[MAXPATHLEN];
|
NS_tchar newDir[MAXPATHLEN];
|
||||||
NS_tsnprintf(newDir, sizeof(newDir)/sizeof(newDir[0]),
|
NS_tsnprintf(newDir, sizeof(newDir)/sizeof(newDir[0]),
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
NS_T("%s/Updated.app/Contents"),
|
NS_T("%s/Contents"),
|
||||||
|
gWorkingDirPath);
|
||||||
#else
|
#else
|
||||||
NS_T("%s.bak/updated"),
|
NS_T("%s.bak/updated"),
|
||||||
|
gInstallDirPath);
|
||||||
#endif
|
#endif
|
||||||
installDir);
|
|
||||||
|
|
||||||
// First try to remove the possibly existing temp directory, because if this
|
// First try to remove the possibly existing temp directory, because if this
|
||||||
// directory exists, we will fail to rename sourceDir.
|
// directory exists, we will fail to rename destDir.
|
||||||
// No need to error check here because if this fails, we will fail in the
|
// No need to error check here because if this fails, we will fail in the
|
||||||
// next step anyways.
|
// next step anyways.
|
||||||
ensure_remove_recursive(tmpDir);
|
ensure_remove_recursive(tmpDir);
|
||||||
|
|
||||||
LOG(("Begin moving sourceDir (" LOG_S ") to tmpDir (" LOG_S ")",
|
LOG(("Begin moving destDir (" LOG_S ") to tmpDir (" LOG_S ")",
|
||||||
sourceDir, tmpDir));
|
destDir, tmpDir));
|
||||||
int rv = rename_file(sourceDir, tmpDir, true);
|
int rv = rename_file(destDir, tmpDir, true);
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
// On Windows, if Firefox is launched using the shortcut, it will hold a handle
|
// On Windows, if Firefox is launched using the shortcut, it will hold a handle
|
||||||
// to its installation directory open, which might not get released in time.
|
// to its installation directory open, which might not get released in time.
|
||||||
@ -2015,30 +1974,30 @@ ProcessReplaceRequest()
|
|||||||
const int max_retries = 10;
|
const int max_retries = 10;
|
||||||
int retries = 0;
|
int retries = 0;
|
||||||
while (rv == WRITE_ERROR && (retries++ < max_retries)) {
|
while (rv == WRITE_ERROR && (retries++ < max_retries)) {
|
||||||
LOG(("PerformReplaceRequest: sourceDir rename attempt %d failed. " \
|
LOG(("PerformReplaceRequest: destDir rename attempt %d failed. " \
|
||||||
"File: " LOG_S ". Last error: %d, err: %d", retries,
|
"File: " LOG_S ". Last error: %d, err: %d", retries,
|
||||||
sourceDir, GetLastError(), rv));
|
destDir, GetLastError(), rv));
|
||||||
|
|
||||||
Sleep(100);
|
Sleep(100);
|
||||||
|
|
||||||
rv = rename_file(sourceDir, tmpDir, true);
|
rv = rename_file(destDir, tmpDir, true);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (rv) {
|
if (rv) {
|
||||||
LOG(("Moving sourceDir to tmpDir failed, err: %d", rv));
|
LOG(("Moving destDir to tmpDir failed, err: %d", rv));
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(("Begin moving newDir (" LOG_S ") to sourceDir (" LOG_S ")",
|
LOG(("Begin moving newDir (" LOG_S ") to destDir (" LOG_S ")",
|
||||||
newDir, sourceDir));
|
newDir, destDir));
|
||||||
rv = rename_file(newDir, sourceDir, true);
|
rv = rename_file(newDir, destDir, true);
|
||||||
if (rv) {
|
if (rv) {
|
||||||
LOG(("Moving newDir to sourceDir failed, err: %d", rv));
|
LOG(("Moving newDir to destDir failed, err: %d", rv));
|
||||||
LOG(("Now, try to move tmpDir back to sourceDir"));
|
LOG(("Now, try to move tmpDir back to destDir"));
|
||||||
ensure_remove_recursive(sourceDir);
|
ensure_remove_recursive(destDir);
|
||||||
int rv2 = rename_file(tmpDir, sourceDir, true);
|
int rv2 = rename_file(tmpDir, destDir, true);
|
||||||
if (rv2) {
|
if (rv2) {
|
||||||
LOG(("Moving tmpDir back to sourceDir failed, err: %d", rv2));
|
LOG(("Moving tmpDir back to destDir failed, err: %d", rv2));
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -2058,39 +2017,11 @@ ProcessReplaceRequest()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
// On OS X, we need to copy anything else left over inside the Updated.app
|
// On OS X, we we need to remove the staging directory after its Contents
|
||||||
// directory, and then we need to get rid of it as it's no longer going to
|
// directory has been moved.
|
||||||
// be useful.
|
|
||||||
NS_tchar updatedAppDir[MAXPATHLEN];
|
NS_tchar updatedAppDir[MAXPATHLEN];
|
||||||
NS_tsnprintf(updatedAppDir, sizeof(updatedAppDir)/sizeof(updatedAppDir[0]),
|
NS_tsnprintf(updatedAppDir, sizeof(updatedAppDir)/sizeof(updatedAppDir[0]),
|
||||||
NS_T("%s/Updated.app"), installDir);
|
NS_T("%s/Updated.app"), gPatchDirPath);
|
||||||
NS_tDIR *dir = NS_topendir(updatedAppDir);
|
|
||||||
if (dir) {
|
|
||||||
NS_tdirent *entry;
|
|
||||||
while ((entry = NS_treaddir(dir)) != 0) {
|
|
||||||
if (NS_tstrcmp(entry->d_name, NS_T(".")) &&
|
|
||||||
NS_tstrcmp(entry->d_name, NS_T(".."))) {
|
|
||||||
NS_tchar childSrcPath[MAXPATHLEN];
|
|
||||||
NS_tsnprintf(childSrcPath, sizeof(childSrcPath)/sizeof(childSrcPath[0]),
|
|
||||||
NS_T("%s/%s"), updatedAppDir, entry->d_name);
|
|
||||||
NS_tchar childDstPath[MAXPATHLEN];
|
|
||||||
NS_tsnprintf(childDstPath, sizeof(childDstPath)/sizeof(childDstPath[0]),
|
|
||||||
NS_T("%s/%s"), installDir, entry->d_name);
|
|
||||||
ensure_remove_recursive(childDstPath);
|
|
||||||
rv = rename_file(childSrcPath, childDstPath, true);
|
|
||||||
if (rv) {
|
|
||||||
LOG(("Moving " LOG_S " to " LOG_S " failed, err: %d",
|
|
||||||
childSrcPath, childDstPath, errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_tclosedir(dir);
|
|
||||||
} else {
|
|
||||||
LOG(("Updated.app dir can't be found: " LOG_S ", err: %d",
|
|
||||||
updatedAppDir, errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
ensure_remove_recursive(updatedAppDir);
|
ensure_remove_recursive(updatedAppDir);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -2100,7 +2031,7 @@ ProcessReplaceRequest()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
static void
|
static void
|
||||||
WaitForServiceFinishThread(void *param)
|
WaitForServiceFinishThread(void *param)
|
||||||
{
|
{
|
||||||
// We wait at most 10 minutes, we already waited 5 seconds previously
|
// We wait at most 10 minutes, we already waited 5 seconds previously
|
||||||
@ -2144,11 +2075,11 @@ GetUpdateFileName(NS_tchar *fileName, int maxChars)
|
|||||||
|
|
||||||
NS_tchar linkFileName[MAXPATHLEN];
|
NS_tchar linkFileName[MAXPATHLEN];
|
||||||
NS_tsnprintf(linkFileName, sizeof(linkFileName)/sizeof(linkFileName[0]),
|
NS_tsnprintf(linkFileName, sizeof(linkFileName)/sizeof(linkFileName[0]),
|
||||||
NS_T("%s/update.link"), gSourcePath);
|
NS_T("%s/update.link"), gPatchDirPath);
|
||||||
AutoFile linkFile(NS_tfopen(linkFileName, NS_T("rb")));
|
AutoFile linkFile(NS_tfopen(linkFileName, NS_T("rb")));
|
||||||
if (linkFile == nullptr) {
|
if (linkFile == nullptr) {
|
||||||
NS_tsnprintf(fileName, maxChars,
|
NS_tsnprintf(fileName, maxChars,
|
||||||
NS_T("%s/update.mar"), gSourcePath);
|
NS_T("%s/update.mar"), gPatchDirPath);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2174,7 +2105,7 @@ GetUpdateFileName(NS_tchar *fileName, int maxChars)
|
|||||||
#else
|
#else
|
||||||
// We currently only support update.link files under GONK
|
// We currently only support update.link files under GONK
|
||||||
NS_tsnprintf(fileName, maxChars,
|
NS_tsnprintf(fileName, maxChars,
|
||||||
NS_T("%s/update.mar"), gSourcePath);
|
NS_T("%s/update.mar"), gPatchDirPath);
|
||||||
#endif
|
#endif
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@ -2199,19 +2130,11 @@ UpdateThreadFunc(void *param)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rv == OK) {
|
if (rv == OK) {
|
||||||
NS_tchar installDir[MAXPATHLEN];
|
|
||||||
if (sStagedUpdate) {
|
|
||||||
if (!GetInstallationDir(installDir)) {
|
|
||||||
rv = NO_INSTALLDIR_ERROR;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
NS_tstrcpy(installDir, gDestinationPath);
|
|
||||||
}
|
|
||||||
if (rv == OK) {
|
if (rv == OK) {
|
||||||
NS_tchar updateSettingsPath[MAX_TEXT_LEN];
|
NS_tchar updateSettingsPath[MAX_TEXT_LEN];
|
||||||
NS_tsnprintf(updateSettingsPath,
|
NS_tsnprintf(updateSettingsPath,
|
||||||
sizeof(updateSettingsPath) / sizeof(updateSettingsPath[0]),
|
sizeof(updateSettingsPath) / sizeof(updateSettingsPath[0]),
|
||||||
NS_T("%s/update-settings.ini"), installDir);
|
NS_T("%s/update-settings.ini"), gWorkingDirPath);
|
||||||
MARChannelStringTable MARStrings;
|
MARChannelStringTable MARStrings;
|
||||||
if (ReadMARChannelIDs(updateSettingsPath, &MARStrings) != OK) {
|
if (ReadMARChannelIDs(updateSettingsPath, &MARStrings) != OK) {
|
||||||
// If we can't read from update-settings.ini then we shouldn't impose
|
// If we can't read from update-settings.ini then we shouldn't impose
|
||||||
@ -2234,7 +2157,7 @@ UpdateThreadFunc(void *param)
|
|||||||
gArchiveReader.Close();
|
gArchiveReader.Close();
|
||||||
NS_tchar updatingDir[MAXPATHLEN];
|
NS_tchar updatingDir[MAXPATHLEN];
|
||||||
NS_tsnprintf(updatingDir, sizeof(updatingDir)/sizeof(updatingDir[0]),
|
NS_tsnprintf(updatingDir, sizeof(updatingDir)/sizeof(updatingDir[0]),
|
||||||
NS_T("%s/updating"), gDestinationPath);
|
NS_T("%s/updating"), gWorkingDirPath);
|
||||||
ensure_remove_recursive(updatingDir);
|
ensure_remove_recursive(updatingDir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2252,23 +2175,11 @@ UpdateThreadFunc(void *param)
|
|||||||
// bypass this fallback, and is used in the updater tests.
|
// bypass this fallback, and is used in the updater tests.
|
||||||
// The only special thing which we should do here is to remove the
|
// The only special thing which we should do here is to remove the
|
||||||
// staged directory as it won't be useful any more.
|
// staged directory as it won't be useful any more.
|
||||||
NS_tchar installDir[MAXPATHLEN];
|
ensure_remove_recursive(gWorkingDirPath);
|
||||||
if (GetInstallationDir(installDir)) {
|
WriteStatusFile(sUsingService ? "pending-service" : "pending");
|
||||||
NS_tchar stageDir[MAXPATHLEN];
|
char processUpdates[] = "MOZ_PROCESS_UPDATES=";
|
||||||
NS_tsnprintf(stageDir, sizeof(stageDir)/sizeof(stageDir[0]),
|
putenv(processUpdates); // We need to use -process-updates again in the tests
|
||||||
#ifdef XP_MACOSX
|
reportRealResults = false; // pretend success
|
||||||
NS_T("%s/Updated.app"),
|
|
||||||
#else
|
|
||||||
NS_T("%s/updated"),
|
|
||||||
#endif
|
|
||||||
installDir);
|
|
||||||
|
|
||||||
ensure_remove_recursive(stageDir);
|
|
||||||
WriteStatusFile(sUsingService ? "pending-service" : "pending");
|
|
||||||
char processUpdates[] = "MOZ_PROCESS_UPDATES=";
|
|
||||||
putenv(processUpdates); // We need to use -process-updates again in the tests
|
|
||||||
reportRealResults = false; // pretend success
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reportRealResults) {
|
if (reportRealResults) {
|
||||||
@ -2342,14 +2253,14 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The directory containing the update information.
|
// The directory containing the update information.
|
||||||
gSourcePath = argv[1];
|
gPatchDirPath = argv[1];
|
||||||
// The directory we're going to update to.
|
// The directory we're going to update to.
|
||||||
// We copy this string because we need to remove trailing slashes. The C++
|
// We copy this string because we need to remove trailing slashes. The C++
|
||||||
// standard says that it's always safe to write to strings pointed to by argv
|
// standard says that it's always safe to write to strings pointed to by argv
|
||||||
// elements, but I don't necessarily believe it.
|
// elements, but I don't necessarily believe it.
|
||||||
NS_tstrncpy(gDestinationPath, argv[2], MAXPATHLEN);
|
NS_tstrncpy(gInstallDirPath, argv[2], MAXPATHLEN);
|
||||||
gDestinationPath[MAXPATHLEN - 1] = NS_T('\0');
|
gInstallDirPath[MAXPATHLEN - 1] = NS_T('\0');
|
||||||
NS_tchar *slash = NS_tstrrchr(gDestinationPath, NS_SLASH);
|
NS_tchar *slash = NS_tstrrchr(gInstallDirPath, NS_SLASH);
|
||||||
if (slash && !slash[1]) {
|
if (slash && !slash[1]) {
|
||||||
*slash = NS_T('\0');
|
*slash = NS_T('\0');
|
||||||
}
|
}
|
||||||
@ -2365,7 +2276,7 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
#ifdef MOZ_MAINTENANCE_SERVICE
|
#ifdef MOZ_MAINTENANCE_SERVICE
|
||||||
useService = IsUpdateStatusPendingService();
|
useService = IsUpdateStatusPendingService();
|
||||||
// Our tests run with a different apply directory for each test.
|
// Our tests run with a different apply directory for each test.
|
||||||
// We use this registry key on our test slaves to store the
|
// We use this registry key on our test slaves to store the
|
||||||
// allowed name/issuers.
|
// allowed name/issuers.
|
||||||
testOnlyFallbackKeyExists = DoesFallbackKeyExist();
|
testOnlyFallbackKeyExists = DoesFallbackKeyExist();
|
||||||
#endif
|
#endif
|
||||||
@ -2395,23 +2306,34 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
#else
|
#else
|
||||||
int pid = 0;
|
int pid = 0;
|
||||||
#endif
|
#endif
|
||||||
if (argc > 3) {
|
if (argc > 4) {
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
pid = _wtoi64(argv[3]);
|
pid = _wtoi64(argv[4]);
|
||||||
#else
|
#else
|
||||||
pid = atoi(argv[3]);
|
pid = atoi(argv[4]);
|
||||||
#endif
|
#endif
|
||||||
if (pid == -1) {
|
if (pid == -1) {
|
||||||
// This is a signal from the parent process that the updater should stage
|
// This is a signal from the parent process that the updater should stage
|
||||||
// the update.
|
// the update.
|
||||||
sStagedUpdate = true;
|
sStagedUpdate = true;
|
||||||
} else if (NS_tstrstr(argv[3], NS_T("/replace"))) {
|
} else if (NS_tstrstr(argv[4], NS_T("/replace"))) {
|
||||||
// We're processing a request to replace the application with a staged
|
// We're processing a request to replace the application with a staged
|
||||||
// update.
|
// update.
|
||||||
sReplaceRequest = true;
|
sReplaceRequest = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The directory we're going to update to.
|
||||||
|
// We copy this string because we need to remove trailing slashes. The C++
|
||||||
|
// standard says that it's always safe to write to strings pointed to by argv
|
||||||
|
// elements, but I don't necessarily believe it.
|
||||||
|
NS_tstrncpy(gWorkingDirPath, argv[3], MAXPATHLEN);
|
||||||
|
gWorkingDirPath[MAXPATHLEN - 1] = NS_T('\0');
|
||||||
|
slash = NS_tstrrchr(gWorkingDirPath, NS_SLASH);
|
||||||
|
if (slash && !slash[1]) {
|
||||||
|
*slash = NS_T('\0');
|
||||||
|
}
|
||||||
|
|
||||||
if (getenv("MOZ_OS_UPDATE")) {
|
if (getenv("MOZ_OS_UPDATE")) {
|
||||||
sIsOSUpdate = true;
|
sIsOSUpdate = true;
|
||||||
putenv(const_cast<char*>("MOZ_OS_UPDATE="));
|
putenv(const_cast<char*>("MOZ_OS_UPDATE="));
|
||||||
@ -2420,28 +2342,22 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
if (sReplaceRequest) {
|
if (sReplaceRequest) {
|
||||||
// If we're attempting to replace the application, try to append to the
|
// If we're attempting to replace the application, try to append to the
|
||||||
// log generated when staging the staged update.
|
// log generated when staging the staged update.
|
||||||
NS_tchar installDir[MAXPATHLEN];
|
|
||||||
if (!GetInstallationDir(installDir)) {
|
|
||||||
fprintf(stderr, "Could not get the installation directory\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
NS_tchar* logDir = gSourcePath;
|
NS_tchar* logDir = gPatchDirPath;
|
||||||
|
#else
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
NS_tchar* logDir = gPatchDirPath;
|
||||||
#else
|
#else
|
||||||
NS_tchar logDir[MAXPATHLEN];
|
NS_tchar logDir[MAXPATHLEN];
|
||||||
NS_tsnprintf(logDir, sizeof(logDir)/sizeof(logDir[0]),
|
NS_tsnprintf(logDir, sizeof(logDir)/sizeof(logDir[0]),
|
||||||
#ifdef XP_MACOSX
|
|
||||||
NS_T("%s/Updated.app/Contents/MacOS/updates"),
|
|
||||||
#else
|
|
||||||
NS_T("%s/updated/updates"),
|
NS_T("%s/updated/updates"),
|
||||||
|
gInstallDirPath);
|
||||||
#endif
|
#endif
|
||||||
installDir);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LogInitAppend(logDir, NS_T("last-update.log"), NS_T("update.log"));
|
LogInitAppend(logDir, NS_T("last-update.log"), NS_T("update.log"));
|
||||||
} else {
|
} else {
|
||||||
LogInit(gSourcePath, NS_T("update.log"));
|
LogInit(gPatchDirPath, NS_T("update.log"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!WriteStatusFile("applying")) {
|
if (!WriteStatusFile("applying")) {
|
||||||
@ -2455,6 +2371,10 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
LOG(("Performing a replace request"));
|
LOG(("Performing a replace request"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG(("PATCH DIRECTORY " LOG_S, gPatchDirPath));
|
||||||
|
LOG(("INSTALLATION DIRECTORY " LOG_S, gInstallDirPath));
|
||||||
|
LOG(("WORKING DIRECTORY " LOG_S, gWorkingDirPath));
|
||||||
|
|
||||||
#ifdef MOZ_WIDGET_GONK
|
#ifdef MOZ_WIDGET_GONK
|
||||||
const char *prioEnv = getenv("MOZ_UPDATER_PRIO");
|
const char *prioEnv = getenv("MOZ_UPDATER_PRIO");
|
||||||
if (prioEnv) {
|
if (prioEnv) {
|
||||||
@ -2522,14 +2442,14 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
// The callback is the remaining arguments starting at callbackIndex.
|
// The callback is the remaining arguments starting at callbackIndex.
|
||||||
// The argument specified by callbackIndex is the callback executable and the
|
// The argument specified by callbackIndex is the callback executable and the
|
||||||
// argument prior to callbackIndex is the working directory.
|
// argument prior to callbackIndex is the working directory.
|
||||||
const int callbackIndex = 5;
|
const int callbackIndex = 6;
|
||||||
|
|
||||||
#if defined(XP_WIN)
|
#if defined(XP_WIN)
|
||||||
sUsingService = getenv("MOZ_USING_SERVICE") != nullptr;
|
sUsingService = getenv("MOZ_USING_SERVICE") != nullptr;
|
||||||
putenv(const_cast<char*>("MOZ_USING_SERVICE="));
|
putenv(const_cast<char*>("MOZ_USING_SERVICE="));
|
||||||
// lastFallbackError keeps track of the last error for the service not being
|
// lastFallbackError keeps track of the last error for the service not being
|
||||||
// used, in case of an error when fallback is not enabled we write the
|
// used, in case of an error when fallback is not enabled we write the
|
||||||
// error to the update.status file.
|
// error to the update.status file.
|
||||||
// When fallback is disabled (MOZ_NO_SERVICE_FALLBACK does not exist) then
|
// When fallback is disabled (MOZ_NO_SERVICE_FALLBACK does not exist) then
|
||||||
// we will instead fallback to not using the service and display a UAC prompt.
|
// we will instead fallback to not using the service and display a UAC prompt.
|
||||||
int lastFallbackError = FALLBACKKEY_UNKNOWN_ERROR;
|
int lastFallbackError = FALLBACKKEY_UNKNOWN_ERROR;
|
||||||
@ -2543,17 +2463,15 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
NS_tchar updateLockFilePath[MAXPATHLEN];
|
NS_tchar updateLockFilePath[MAXPATHLEN];
|
||||||
if (sStagedUpdate) {
|
if (sStagedUpdate) {
|
||||||
// When staging an update, the lock file is:
|
// When staging an update, the lock file is:
|
||||||
// $INSTALLDIR\updated.update_in_progress.lock
|
// <install_dir>\updated.update_in_progress.lock
|
||||||
NS_tsnprintf(updateLockFilePath,
|
NS_tsnprintf(updateLockFilePath,
|
||||||
sizeof(updateLockFilePath)/sizeof(updateLockFilePath[0]),
|
sizeof(updateLockFilePath)/sizeof(updateLockFilePath[0]),
|
||||||
NS_T("%s.update_in_progress.lock"), gDestinationPath);
|
NS_T("%s/updated.update_in_progress.lock"), gInstallDirPath);
|
||||||
} else if (sReplaceRequest) {
|
} else if (sReplaceRequest) {
|
||||||
// When processing a replace request, the lock file is:
|
// When processing a replace request, the lock file is:
|
||||||
// $INSTALLDIR\..\moz_update_in_progress.lock
|
// <install_dir>\..\moz_update_in_progress.lock
|
||||||
NS_tchar installDir[MAXPATHLEN];
|
NS_tchar installDir[MAXPATHLEN];
|
||||||
if (!GetInstallationDir(installDir)) {
|
NS_tstrcpy(installDir, gInstallDirPath);
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
NS_tchar *slash = (NS_tchar *) NS_tstrrchr(installDir, NS_SLASH);
|
NS_tchar *slash = (NS_tchar *) NS_tstrrchr(installDir, NS_SLASH);
|
||||||
*slash = NS_T('\0');
|
*slash = NS_T('\0');
|
||||||
NS_tsnprintf(updateLockFilePath,
|
NS_tsnprintf(updateLockFilePath,
|
||||||
@ -2561,7 +2479,7 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
NS_T("%s\\moz_update_in_progress.lock"), installDir);
|
NS_T("%s\\moz_update_in_progress.lock"), installDir);
|
||||||
} else {
|
} else {
|
||||||
// In the non-staging update case, the lock file is:
|
// In the non-staging update case, the lock file is:
|
||||||
// $INSTALLDIR\$APPNAME.exe.update_in_progress.lock
|
// <install_dir>\<app_name>.exe.update_in_progress.lock
|
||||||
NS_tsnprintf(updateLockFilePath,
|
NS_tsnprintf(updateLockFilePath,
|
||||||
sizeof(updateLockFilePath)/sizeof(updateLockFilePath[0]),
|
sizeof(updateLockFilePath)/sizeof(updateLockFilePath[0]),
|
||||||
NS_T("%s.update_in_progress.lock"), argv[callbackIndex]);
|
NS_T("%s.update_in_progress.lock"), argv[callbackIndex]);
|
||||||
@ -2593,17 +2511,16 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
|
|
||||||
NS_tsnprintf(elevatedLockFilePath,
|
NS_tsnprintf(elevatedLockFilePath,
|
||||||
sizeof(elevatedLockFilePath)/sizeof(elevatedLockFilePath[0]),
|
sizeof(elevatedLockFilePath)/sizeof(elevatedLockFilePath[0]),
|
||||||
NS_T("%s/update_elevated.lock"), gSourcePath);
|
NS_T("%s/update_elevated.lock"), gPatchDirPath);
|
||||||
|
|
||||||
|
|
||||||
// Even if a file has no sharing access, you can still get its attributes
|
// Even if a file has no sharing access, you can still get its attributes
|
||||||
bool startedFromUnelevatedUpdater =
|
bool startedFromUnelevatedUpdater =
|
||||||
GetFileAttributesW(elevatedLockFilePath) != INVALID_FILE_ATTRIBUTES;
|
GetFileAttributesW(elevatedLockFilePath) != INVALID_FILE_ATTRIBUTES;
|
||||||
|
|
||||||
// If we're running from the service, then we were started with the same
|
// If we're running from the service, then we were started with the same
|
||||||
// token as the service so the permissions are already dropped. If we're
|
// token as the service so the permissions are already dropped. If we're
|
||||||
// running from an elevated updater that was started from an unelevated
|
// running from an elevated updater that was started from an unelevated
|
||||||
// updater, then we drop the permissions here. We do not drop the
|
// updater, then we drop the permissions here. We do not drop the
|
||||||
// permissions on the originally called updater because we use its token
|
// permissions on the originally called updater because we use its token
|
||||||
// to start the callback application.
|
// to start the callback application.
|
||||||
if(startedFromUnelevatedUpdater) {
|
if(startedFromUnelevatedUpdater) {
|
||||||
@ -2612,7 +2529,7 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
UACHelper::DisablePrivileges(nullptr);
|
UACHelper::DisablePrivileges(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updateLockFileHandle == INVALID_HANDLE_VALUE ||
|
if (updateLockFileHandle == INVALID_HANDLE_VALUE ||
|
||||||
(useService && testOnlyFallbackKeyExists && noServiceFallback)) {
|
(useService && testOnlyFallbackKeyExists && noServiceFallback)) {
|
||||||
if (!_waccess(elevatedLockFilePath, F_OK) &&
|
if (!_waccess(elevatedLockFilePath, F_OK) &&
|
||||||
NS_tremove(elevatedLockFilePath) != 0) {
|
NS_tremove(elevatedLockFilePath) != 0) {
|
||||||
@ -2640,11 +2557,6 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_tchar installDir[MAXPATHLEN];
|
|
||||||
if (!GetInstallationDir(installDir)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure the path to the updater to use for the update is on local.
|
// Make sure the path to the updater to use for the update is on local.
|
||||||
// We do this check to make sure that file locking is available for
|
// We do this check to make sure that file locking is available for
|
||||||
// race condition security checks.
|
// race condition security checks.
|
||||||
@ -2670,11 +2582,11 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
// are available. If not don't use the service.
|
// are available. If not don't use the service.
|
||||||
if (useService) {
|
if (useService) {
|
||||||
WCHAR maintenanceServiceKey[MAX_PATH + 1];
|
WCHAR maintenanceServiceKey[MAX_PATH + 1];
|
||||||
if (CalculateRegistryPathFromFilePath(installDir, maintenanceServiceKey)) {
|
if (CalculateRegistryPathFromFilePath(gInstallDirPath, maintenanceServiceKey)) {
|
||||||
HKEY baseKey;
|
HKEY baseKey;
|
||||||
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
||||||
maintenanceServiceKey, 0,
|
maintenanceServiceKey, 0,
|
||||||
KEY_READ | KEY_WOW64_64KEY,
|
KEY_READ | KEY_WOW64_64KEY,
|
||||||
&baseKey) == ERROR_SUCCESS) {
|
&baseKey) == ERROR_SUCCESS) {
|
||||||
RegCloseKey(baseKey);
|
RegCloseKey(baseKey);
|
||||||
} else {
|
} else {
|
||||||
@ -2695,7 +2607,7 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
// fails in between, we can fall back to using the normal update process
|
// fails in between, we can fall back to using the normal update process
|
||||||
// on our own.
|
// on our own.
|
||||||
|
|
||||||
// If we still want to use the service try to launch the service
|
// If we still want to use the service try to launch the service
|
||||||
// comamnd for the update.
|
// comamnd for the update.
|
||||||
if (useService) {
|
if (useService) {
|
||||||
// If the update couldn't be started, then set useService to false so
|
// If the update couldn't be started, then set useService to false so
|
||||||
@ -2718,7 +2630,7 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
DWORD lastState = WaitForServiceStop(SVC_NAME, 5);
|
DWORD lastState = WaitForServiceStop(SVC_NAME, 5);
|
||||||
if (lastState != SERVICE_STOPPED) {
|
if (lastState != SERVICE_STOPPED) {
|
||||||
Thread t1;
|
Thread t1;
|
||||||
if (t1.Run(WaitForServiceFinishThread, nullptr) == 0 &&
|
if (t1.Run(WaitForServiceFinishThread, nullptr) == 0 &&
|
||||||
showProgressUI) {
|
showProgressUI) {
|
||||||
ShowProgressUI(true, false);
|
ShowProgressUI(true, false);
|
||||||
}
|
}
|
||||||
@ -2744,7 +2656,7 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
if (updateLockFileHandle != INVALID_HANDLE_VALUE) {
|
if (updateLockFileHandle != INVALID_HANDLE_VALUE) {
|
||||||
CloseHandle(updateLockFileHandle);
|
CloseHandle(updateLockFileHandle);
|
||||||
}
|
}
|
||||||
WriteStatusPending(gSourcePath);
|
WriteStatusPending(gPatchDirPath);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2757,9 +2669,9 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
// as the PostUpdate step runs when performing the replacing in that case.
|
// as the PostUpdate step runs when performing the replacing in that case.
|
||||||
if (useService && !sStagedUpdate) {
|
if (useService && !sStagedUpdate) {
|
||||||
bool updateStatusSucceeded = false;
|
bool updateStatusSucceeded = false;
|
||||||
if (IsUpdateStatusSucceeded(updateStatusSucceeded) &&
|
if (IsUpdateStatusSucceeded(updateStatusSucceeded) &&
|
||||||
updateStatusSucceeded) {
|
updateStatusSucceeded) {
|
||||||
if (!LaunchWinPostProcess(installDir, gSourcePath, false, nullptr)) {
|
if (!LaunchWinPostProcess(gInstallDirPath, gPatchDirPath, false, nullptr)) {
|
||||||
fprintf(stderr, "The post update process which runs as the user"
|
fprintf(stderr, "The post update process which runs as the user"
|
||||||
" for service update could not be launched.");
|
" for service update could not be launched.");
|
||||||
}
|
}
|
||||||
@ -2772,7 +2684,7 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
// We don't launch the elevated updater in the case that we did have
|
// We don't launch the elevated updater in the case that we did have
|
||||||
// write access all along because in that case the only reason we're
|
// write access all along because in that case the only reason we're
|
||||||
// using the service is because we are testing.
|
// using the service is because we are testing.
|
||||||
if (!useService && !noServiceFallback &&
|
if (!useService && !noServiceFallback &&
|
||||||
updateLockFileHandle == INVALID_HANDLE_VALUE) {
|
updateLockFileHandle == INVALID_HANDLE_VALUE) {
|
||||||
SHELLEXECUTEINFO sinfo;
|
SHELLEXECUTEINFO sinfo;
|
||||||
memset(&sinfo, 0, sizeof(SHELLEXECUTEINFO));
|
memset(&sinfo, 0, sizeof(SHELLEXECUTEINFO));
|
||||||
@ -2798,7 +2710,7 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (argc > callbackIndex) {
|
if (argc > callbackIndex) {
|
||||||
LaunchCallbackApp(argv[4], argc - callbackIndex,
|
LaunchCallbackApp(argv[5], argc - callbackIndex,
|
||||||
argv + callbackIndex, sUsingService);
|
argv + callbackIndex, sUsingService);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2811,7 +2723,7 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
// update.status file.
|
// update.status file.
|
||||||
return 0;
|
return 0;
|
||||||
} else if(useService) {
|
} else if(useService) {
|
||||||
// The service command was launched. The service is responsible for
|
// The service command was launched. The service is responsible for
|
||||||
// writing out the update.status file.
|
// writing out the update.status file.
|
||||||
if (updateLockFileHandle != INVALID_HANDLE_VALUE) {
|
if (updateLockFileHandle != INVALID_HANDLE_VALUE) {
|
||||||
CloseHandle(updateLockFileHandle);
|
CloseHandle(updateLockFileHandle);
|
||||||
@ -2853,16 +2765,16 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
if (sStagedUpdate) {
|
if (sStagedUpdate) {
|
||||||
// When staging updates, blow away the old installation directory and create
|
// When staging updates, blow away the old installation directory and create
|
||||||
// it from scratch.
|
// it from scratch.
|
||||||
ensure_remove_recursive(gDestinationPath);
|
ensure_remove_recursive(gWorkingDirPath);
|
||||||
}
|
}
|
||||||
if (!sReplaceRequest) {
|
if (!sReplaceRequest) {
|
||||||
// Change current directory to the directory where we need to apply the update.
|
// Change current directory to the directory where we need to apply the update.
|
||||||
if (NS_tchdir(gDestinationPath) != 0) {
|
if (NS_tchdir(gWorkingDirPath) != 0) {
|
||||||
// Try to create the destination directory if it doesn't exist
|
// Try to create the destination directory if it doesn't exist
|
||||||
int rv = NS_tmkdir(gDestinationPath, 0755);
|
int rv = NS_tmkdir(gWorkingDirPath, 0755);
|
||||||
if (rv == OK && errno != EEXIST) {
|
if (rv == OK && errno != EEXIST) {
|
||||||
// Try changing the current directory again
|
// Try changing the current directory again
|
||||||
if (NS_tchdir(gDestinationPath) != 0) {
|
if (NS_tchdir(gWorkingDirPath) != 0) {
|
||||||
// OK, time to give up!
|
// OK, time to give up!
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -2873,24 +2785,21 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(("SOURCE DIRECTORY " LOG_S, gSourcePath));
|
|
||||||
LOG(("DESTINATION DIRECTORY " LOG_S, gDestinationPath));
|
|
||||||
|
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
// For replace requests, we don't need to do any real updates, so this is not
|
// For replace requests, we don't need to do any real updates, so this is not
|
||||||
// necessary.
|
// necessary.
|
||||||
if (!sReplaceRequest) {
|
if (!sReplaceRequest) {
|
||||||
// Allocate enough space for the length of the path an optional additional
|
// Allocate enough space for the length of the path an optional additional
|
||||||
// trailing slash and null termination.
|
// trailing slash and null termination.
|
||||||
NS_tchar *destpath = (NS_tchar *) malloc((NS_tstrlen(gDestinationPath) + 2) * sizeof(NS_tchar));
|
NS_tchar *destpath = (NS_tchar *) malloc((NS_tstrlen(gWorkingDirPath) + 2) * sizeof(NS_tchar));
|
||||||
if (!destpath)
|
if (!destpath)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
NS_tchar *c = destpath;
|
NS_tchar *c = destpath;
|
||||||
NS_tstrcpy(c, gDestinationPath);
|
NS_tstrcpy(c, gWorkingDirPath);
|
||||||
c += NS_tstrlen(gDestinationPath);
|
c += NS_tstrlen(gWorkingDirPath);
|
||||||
if (gDestinationPath[NS_tstrlen(gDestinationPath) - 1] != NS_T('/') &&
|
if (gWorkingDirPath[NS_tstrlen(gWorkingDirPath) - 1] != NS_T('/') &&
|
||||||
gDestinationPath[NS_tstrlen(gDestinationPath) - 1] != NS_T('\\')) {
|
gWorkingDirPath[NS_tstrlen(gWorkingDirPath) - 1] != NS_T('\\')) {
|
||||||
NS_tstrcat(c, NS_T("/"));
|
NS_tstrcat(c, NS_T("/"));
|
||||||
c += NS_tstrlen(NS_T("/"));
|
c += NS_tstrlen(NS_T("/"));
|
||||||
}
|
}
|
||||||
@ -2901,14 +2810,14 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
NS_tchar applyDirLongPath[MAXPATHLEN];
|
NS_tchar applyDirLongPath[MAXPATHLEN];
|
||||||
if (!GetLongPathNameW(gDestinationPath, applyDirLongPath,
|
if (!GetLongPathNameW(gWorkingDirPath, applyDirLongPath,
|
||||||
sizeof(applyDirLongPath)/sizeof(applyDirLongPath[0]))) {
|
sizeof(applyDirLongPath)/sizeof(applyDirLongPath[0]))) {
|
||||||
LOG(("NS_main: unable to find apply to dir: " LOG_S, gDestinationPath));
|
LOG(("NS_main: unable to find apply to dir: " LOG_S, gWorkingDirPath));
|
||||||
LogFinish();
|
LogFinish();
|
||||||
WriteStatusFile(WRITE_ERROR);
|
WriteStatusFile(WRITE_ERROR);
|
||||||
EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1);
|
EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1);
|
||||||
if (argc > callbackIndex) {
|
if (argc > callbackIndex) {
|
||||||
LaunchCallbackApp(argv[4], argc - callbackIndex,
|
LaunchCallbackApp(argv[5], argc - callbackIndex,
|
||||||
argv + callbackIndex, sUsingService);
|
argv + callbackIndex, sUsingService);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@ -2930,15 +2839,15 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
// In case of replace requests, we should look for the callback file in
|
// In case of replace requests, we should look for the callback file in
|
||||||
// the destination directory.
|
// the destination directory.
|
||||||
size_t commonPrefixLength = PathCommonPrefixW(argv[callbackIndex],
|
size_t commonPrefixLength = PathCommonPrefixW(argv[callbackIndex],
|
||||||
gDestinationPath,
|
gInstallDirPath,
|
||||||
nullptr);
|
nullptr);
|
||||||
NS_tchar *p = buffer;
|
NS_tchar *p = buffer;
|
||||||
NS_tstrncpy(p, argv[callbackIndex], commonPrefixLength);
|
NS_tstrncpy(p, argv[callbackIndex], commonPrefixLength);
|
||||||
p += commonPrefixLength;
|
p += commonPrefixLength;
|
||||||
bufferLeft -= commonPrefixLength;
|
bufferLeft -= commonPrefixLength;
|
||||||
NS_tstrncpy(p, gDestinationPath + commonPrefixLength, bufferLeft);
|
NS_tstrncpy(p, gInstallDirPath + commonPrefixLength, bufferLeft);
|
||||||
|
|
||||||
size_t len = NS_tstrlen(gDestinationPath + commonPrefixLength);
|
size_t len = NS_tstrlen(gInstallDirPath + commonPrefixLength);
|
||||||
p += len;
|
p += len;
|
||||||
bufferLeft -= len;
|
bufferLeft -= len;
|
||||||
*p = NS_T('\\');
|
*p = NS_T('\\');
|
||||||
@ -2946,8 +2855,7 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
bufferLeft--;
|
bufferLeft--;
|
||||||
*p = NS_T('\0');
|
*p = NS_T('\0');
|
||||||
NS_tchar installDir[MAXPATHLEN];
|
NS_tchar installDir[MAXPATHLEN];
|
||||||
if (!GetInstallationDir(installDir))
|
NS_tstrcpy(installDir, gInstallDirPath);
|
||||||
return 1;
|
|
||||||
size_t callbackPrefixLength = PathCommonPrefixW(argv[callbackIndex],
|
size_t callbackPrefixLength = PathCommonPrefixW(argv[callbackIndex],
|
||||||
installDir,
|
installDir,
|
||||||
nullptr);
|
nullptr);
|
||||||
@ -2961,9 +2869,9 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
WriteStatusFile(WRITE_ERROR);
|
WriteStatusFile(WRITE_ERROR);
|
||||||
EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1);
|
EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1);
|
||||||
if (argc > callbackIndex) {
|
if (argc > callbackIndex) {
|
||||||
LaunchCallbackApp(argv[4],
|
LaunchCallbackApp(argv[5],
|
||||||
argc - callbackIndex,
|
argc - callbackIndex,
|
||||||
argv + callbackIndex,
|
argv + callbackIndex,
|
||||||
sUsingService);
|
sUsingService);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@ -3042,7 +2950,7 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
|
|
||||||
NS_tremove(gCallbackBackupPath);
|
NS_tremove(gCallbackBackupPath);
|
||||||
EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1);
|
EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1);
|
||||||
LaunchCallbackApp(argv[4],
|
LaunchCallbackApp(argv[5],
|
||||||
argc - callbackIndex,
|
argc - callbackIndex,
|
||||||
argv + callbackIndex,
|
argv + callbackIndex,
|
||||||
sUsingService);
|
sUsingService);
|
||||||
@ -3119,37 +3027,31 @@ int NS_main(int argc, NS_tchar **argv)
|
|||||||
if (gSucceeded) {
|
if (gSucceeded) {
|
||||||
// The service update will only be executed if it is already installed.
|
// The service update will only be executed if it is already installed.
|
||||||
// For first time installs of the service, the install will happen from
|
// For first time installs of the service, the install will happen from
|
||||||
// the PostUpdate process. We do the service update process here
|
// the PostUpdate process. We do the service update process here
|
||||||
// because it's possible we are updating with updater.exe without the
|
// because it's possible we are updating with updater.exe without the
|
||||||
// service if the service failed to apply the update. We want to update
|
// service if the service failed to apply the update. We want to update
|
||||||
// the service to a newer version in that case. If we are not running
|
// the service to a newer version in that case. If we are not running
|
||||||
// through the service, then MOZ_USING_SERVICE will not exist.
|
// through the service, then MOZ_USING_SERVICE will not exist.
|
||||||
if (!sUsingService) {
|
if (!sUsingService) {
|
||||||
NS_tchar installDir[MAXPATHLEN];
|
if (!LaunchWinPostProcess(gInstallDirPath, gPatchDirPath, false, nullptr)) {
|
||||||
if (GetInstallationDir(installDir)) {
|
LOG(("NS_main: The post update process could not be launched."));
|
||||||
if (!LaunchWinPostProcess(installDir, gSourcePath, false, nullptr)) {
|
|
||||||
LOG(("NS_main: The post update process could not be launched."));
|
|
||||||
}
|
|
||||||
|
|
||||||
StartServiceUpdate(installDir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StartServiceUpdate(gInstallDirPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 0);
|
EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 0);
|
||||||
#endif /* XP_WIN */
|
#endif /* XP_WIN */
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
if (gSucceeded) {
|
if (gSucceeded) {
|
||||||
char installDir[MAXPATHLEN];
|
LaunchMacPostProcess(gInstallDirPath);
|
||||||
if (GetInstallationDir(installDir)) {
|
|
||||||
LaunchMacPostProcess(installDir);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* XP_MACOSX */
|
#endif /* XP_MACOSX */
|
||||||
|
|
||||||
if (getenv("MOZ_PROCESS_UPDATES") == nullptr) {
|
if (getenv("MOZ_PROCESS_UPDATES") == nullptr) {
|
||||||
LaunchCallbackApp(argv[4],
|
LaunchCallbackApp(argv[5],
|
||||||
argc - callbackIndex,
|
argc - callbackIndex,
|
||||||
argv + callbackIndex,
|
argv + callbackIndex,
|
||||||
sUsingService);
|
sUsingService);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3662,7 +3564,7 @@ int DoUpdate()
|
|||||||
{
|
{
|
||||||
NS_tchar manifest[MAXPATHLEN];
|
NS_tchar manifest[MAXPATHLEN];
|
||||||
NS_tsnprintf(manifest, sizeof(manifest)/sizeof(manifest[0]),
|
NS_tsnprintf(manifest, sizeof(manifest)/sizeof(manifest[0]),
|
||||||
NS_T("%s/updating/update.manifest"), gDestinationPath);
|
NS_T("%s/updating/update.manifest"), gWorkingDirPath);
|
||||||
ensure_parent_dir(manifest);
|
ensure_parent_dir(manifest);
|
||||||
|
|
||||||
// extract the manifest
|
// extract the manifest
|
||||||
|
@ -132,6 +132,44 @@ GetCurrentWorkingDir(char *buf, size_t size)
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the path to the installation directory. For Mac OS X this will be the
|
||||||
|
* bundle directory.
|
||||||
|
*
|
||||||
|
* @param appDir the application directory file object
|
||||||
|
* @param installDirPath the path to the installation directory
|
||||||
|
*/
|
||||||
|
static nsresult
|
||||||
|
GetInstallDirPath(nsIFile *appDir, nsACString& installDirPath)
|
||||||
|
{
|
||||||
|
nsresult rv;
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
nsCOMPtr<nsIFile> parentDir1, parentDir2;
|
||||||
|
rv = appDir->GetParent(getter_AddRefs(parentDir1));
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
rv = parentDir1->GetParent(getter_AddRefs(parentDir2));
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
rv = parentDir2->GetNativePath(installDirPath);
|
||||||
|
#elif XP_WIN
|
||||||
|
nsAutoString installDirPathW;
|
||||||
|
rv = appDir->GetPath(installDirPathW);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
installDirPath = NS_ConvertUTF16toUTF8(installDirPathW);
|
||||||
|
#else
|
||||||
|
rv = appDir->GetNativePath(installDirPath);
|
||||||
|
#endif
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(XP_MACOSX)
|
#if defined(XP_MACOSX)
|
||||||
// This is a copy of OS X's XRE_GetBinaryPath from nsAppRunner.cpp with the
|
// This is a copy of OS X's XRE_GetBinaryPath from nsAppRunner.cpp with the
|
||||||
// gBinaryPath check removed so that the updater can reload the stub executable
|
// gBinaryPath check removed so that the updater can reload the stub executable
|
||||||
@ -343,11 +381,12 @@ CopyUpdaterIntoUpdateDir(nsIFile *greDir, nsIFile *appDir, nsIFile *updateDir,
|
|||||||
#if defined(XP_MACOSX)
|
#if defined(XP_MACOSX)
|
||||||
if (!CopyFileIntoUpdateDir(appDir, kUpdaterApp, updateDir))
|
if (!CopyFileIntoUpdateDir(appDir, kUpdaterApp, updateDir))
|
||||||
return false;
|
return false;
|
||||||
|
CopyFileIntoUpdateDir(greDir, kUpdaterINI, updateDir);
|
||||||
#else
|
#else
|
||||||
if (!CopyFileIntoUpdateDir(greDir, kUpdaterBin, updateDir))
|
if (!CopyFileIntoUpdateDir(greDir, kUpdaterBin, updateDir))
|
||||||
return false;
|
return false;
|
||||||
#endif
|
|
||||||
CopyFileIntoUpdateDir(appDir, kUpdaterINI, updateDir);
|
CopyFileIntoUpdateDir(appDir, kUpdaterINI, updateDir);
|
||||||
|
#endif
|
||||||
#if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(ANDROID)
|
#if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(ANDROID)
|
||||||
nsCOMPtr<nsIFile> iconDir;
|
nsCOMPtr<nsIFile> iconDir;
|
||||||
appDir->Clone(getter_AddRefs(iconDir));
|
appDir->Clone(getter_AddRefs(iconDir));
|
||||||
@ -466,40 +505,35 @@ SwitchToUpdatedApp(nsIFile *greDir, nsIFile *updateDir, nsIFile *statusFile,
|
|||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Get the directory to which the update will be applied. On Mac OSX we need
|
nsAutoCString installDirPath;
|
||||||
// to apply the update to the Updated.app directory under the Foo.app
|
rv = GetInstallDirPath(appDir, installDirPath);
|
||||||
// directory which is the parent of the parent of the appDir. On other
|
if (NS_FAILED(rv)) {
|
||||||
// platforms we will just apply to the appDir/updated.
|
|
||||||
nsCOMPtr<nsIFile> updatedDir;
|
|
||||||
#if defined(XP_MACOSX)
|
|
||||||
nsAutoCString applyToDir;
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIFile> parentDir1, parentDir2;
|
|
||||||
rv = appDir->GetParent(getter_AddRefs(parentDir1));
|
|
||||||
if (NS_FAILED(rv))
|
|
||||||
return;
|
|
||||||
rv = parentDir1->GetParent(getter_AddRefs(parentDir2));
|
|
||||||
if (NS_FAILED(rv))
|
|
||||||
return;
|
|
||||||
if (!GetFile(parentDir2, NS_LITERAL_CSTRING("Updated.app"), updatedDir))
|
|
||||||
return;
|
|
||||||
rv = updatedDir->GetNativePath(applyToDir);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (!GetFile(appDir, NS_LITERAL_CSTRING("updated"), updatedDir))
|
|
||||||
return;
|
return;
|
||||||
#if defined(XP_WIN)
|
}
|
||||||
|
|
||||||
|
// Get the directory where the update will be staged.
|
||||||
|
nsAutoCString applyToDir;
|
||||||
|
nsCOMPtr<nsIFile> updatedDir;
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
if (!GetFile(updateDir, NS_LITERAL_CSTRING("Updated.app"), updatedDir)) {
|
||||||
|
#else
|
||||||
|
if (!GetFile(appDir, NS_LITERAL_CSTRING("updated"), updatedDir)) {
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#ifdef XP_WIN
|
||||||
nsAutoString applyToDirW;
|
nsAutoString applyToDirW;
|
||||||
rv = updatedDir->GetPath(applyToDirW);
|
rv = updatedDir->GetPath(applyToDirW);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
NS_ConvertUTF16toUTF8 applyToDir(applyToDirW);
|
return;
|
||||||
|
}
|
||||||
|
applyToDir = NS_ConvertUTF16toUTF8(applyToDirW);
|
||||||
#else
|
#else
|
||||||
nsAutoCString applyToDir;
|
|
||||||
rv = updatedDir->GetNativePath(applyToDir);
|
rv = updatedDir->GetNativePath(applyToDir);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
if (NS_FAILED(rv)) {
|
||||||
if (NS_FAILED(rv))
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure that the updated directory exists
|
// Make sure that the updated directory exists
|
||||||
bool updatedDirExists = false;
|
bool updatedDirExists = false;
|
||||||
@ -511,13 +545,11 @@ SwitchToUpdatedApp(nsIFile *greDir, nsIFile *updateDir, nsIFile *statusFile,
|
|||||||
#if defined(XP_WIN)
|
#if defined(XP_WIN)
|
||||||
nsAutoString updateDirPathW;
|
nsAutoString updateDirPathW;
|
||||||
rv = updateDir->GetPath(updateDirPathW);
|
rv = updateDir->GetPath(updateDirPathW);
|
||||||
|
|
||||||
NS_ConvertUTF16toUTF8 updateDirPath(updateDirPathW);
|
NS_ConvertUTF16toUTF8 updateDirPath(updateDirPathW);
|
||||||
#else
|
#else
|
||||||
nsAutoCString updateDirPath;
|
nsAutoCString updateDirPath;
|
||||||
rv = updateDir->GetNativePath(updateDirPath);
|
rv = updateDir->GetNativePath(updateDirPath);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -548,19 +580,20 @@ SwitchToUpdatedApp(nsIFile *greDir, nsIFile *updateDir, nsIFile *statusFile,
|
|||||||
immersiveArgc = 1;
|
immersiveArgc = 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
int argc = appArgc + 5 + immersiveArgc;
|
int argc = appArgc + 6 + immersiveArgc;
|
||||||
char **argv = new char*[argc + 1];
|
char **argv = new char*[argc + 1];
|
||||||
if (!argv)
|
if (!argv)
|
||||||
return;
|
return;
|
||||||
argv[0] = (char*) updaterPath.get();
|
argv[0] = (char*) updaterPath.get();
|
||||||
argv[1] = (char*) updateDirPath.get();
|
argv[1] = (char*) updateDirPath.get();
|
||||||
argv[2] = (char*) applyToDir.get();
|
argv[2] = (char*) installDirPath.get();
|
||||||
argv[3] = (char*) pid.get();
|
argv[3] = (char*) applyToDir.get();
|
||||||
|
argv[4] = (char*) pid.get();
|
||||||
if (appArgc) {
|
if (appArgc) {
|
||||||
argv[4] = workingDirPath;
|
argv[5] = workingDirPath;
|
||||||
argv[5] = (char*) appFilePath.get();
|
argv[6] = (char*) appFilePath.get();
|
||||||
for (int i = 1; i < appArgc; ++i)
|
for (int i = 1; i < appArgc; ++i)
|
||||||
argv[5 + i] = appArgv[i];
|
argv[6 + i] = appArgv[i];
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
if (immersiveArgc) {
|
if (immersiveArgc) {
|
||||||
argv[argc - 1] = "-ServerName:DefaultBrowserServer";
|
argv[argc - 1] = "-ServerName:DefaultBrowserServer";
|
||||||
@ -568,8 +601,8 @@ SwitchToUpdatedApp(nsIFile *greDir, nsIFile *updateDir, nsIFile *statusFile,
|
|||||||
#endif
|
#endif
|
||||||
argv[argc] = nullptr;
|
argv[argc] = nullptr;
|
||||||
} else {
|
} else {
|
||||||
argc = 4;
|
argc = 5;
|
||||||
argv[4] = nullptr;
|
argv[5] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gSafeMode) {
|
if (gSafeMode) {
|
||||||
@ -726,79 +759,64 @@ ApplyUpdate(nsIFile *greDir, nsIFile *updateDir, nsIFile *statusFile,
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Get the directory to which the update will be applied. On Mac OSX we need
|
nsAutoCString installDirPath;
|
||||||
// to apply the update to the Updated.app directory under the Foo.app
|
rv = GetInstallDirPath(appDir, installDirPath);
|
||||||
// directory which is the parent of the parent of the appDir. On other
|
if (NS_FAILED(rv))
|
||||||
// platforms we will just apply to the appDir/updated.
|
return;
|
||||||
nsCOMPtr<nsIFile> updatedDir;
|
|
||||||
#if defined(XP_MACOSX)
|
// Get the directory where the update was staged for replace and GONK OS
|
||||||
|
// Updates or where it will be applied.
|
||||||
|
#ifndef MOZ_WIDGET_GONK
|
||||||
|
// OS Updates are only supported on GONK so force it to false on everything
|
||||||
|
// but GONK to simplify the following logic.
|
||||||
|
isOSUpdate = false;
|
||||||
|
#endif
|
||||||
nsAutoCString applyToDir;
|
nsAutoCString applyToDir;
|
||||||
{
|
nsCOMPtr<nsIFile> updatedDir;
|
||||||
nsCOMPtr<nsIFile> parentDir1, parentDir2;
|
if (restart && !isOSUpdate) {
|
||||||
rv = appDir->GetParent(getter_AddRefs(parentDir1));
|
applyToDir.Assign(installDirPath);
|
||||||
if (NS_FAILED(rv))
|
} else {
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
if (!GetFile(updateDir, NS_LITERAL_CSTRING("Updated.app"), updatedDir)) {
|
||||||
|
#else
|
||||||
|
if (!GetFile(appDir, NS_LITERAL_CSTRING("updated"), updatedDir)) {
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
rv = parentDir1->GetParent(getter_AddRefs(parentDir2));
|
}
|
||||||
if (NS_FAILED(rv))
|
#ifdef XP_WIN
|
||||||
|
nsAutoString applyToDirW;
|
||||||
|
rv = updatedDir->GetPath(applyToDirW);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
return;
|
return;
|
||||||
if (restart) {
|
}
|
||||||
// Use the correct directory if we're not staging the update.
|
applyToDir = NS_ConvertUTF16toUTF8(applyToDirW);
|
||||||
rv = parentDir2->GetNativePath(applyToDir);
|
#elif MOZ_WIDGET_GONK
|
||||||
} else {
|
if (isOSUpdate) {
|
||||||
if (!GetFile(parentDir2, NS_LITERAL_CSTRING("Updated.app"), updatedDir))
|
if (!osApplyToDir) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
rv = osApplyToDir->GetNativePath(applyToDir);
|
||||||
|
} else {
|
||||||
rv = updatedDir->GetNativePath(applyToDir);
|
rv = updatedDir->GetNativePath(applyToDir);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
if (restart) {
|
|
||||||
// Use the correct directory if we're not staging the update.
|
|
||||||
updatedDir = do_QueryInterface(appDir);
|
|
||||||
} else if (!GetFile(appDir, NS_LITERAL_CSTRING("updated"), updatedDir)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#if defined(XP_WIN)
|
|
||||||
nsAutoString applyToDirW;
|
|
||||||
rv = updatedDir->GetPath(applyToDirW);
|
|
||||||
|
|
||||||
NS_ConvertUTF16toUTF8 applyToDir(applyToDirW);
|
|
||||||
#else
|
|
||||||
nsAutoCString applyToDir;
|
|
||||||
|
|
||||||
#if defined(MOZ_WIDGET_GONK)
|
|
||||||
if (isOSUpdate) {
|
|
||||||
if (!osApplyToDir) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = osApplyToDir->GetNativePath(applyToDir);
|
|
||||||
} else {
|
|
||||||
#endif // defined(MOZ_WIDGET_GONK)
|
|
||||||
|
|
||||||
rv = updatedDir->GetNativePath(applyToDir);
|
rv = updatedDir->GetNativePath(applyToDir);
|
||||||
|
|
||||||
#if defined(MOZ_WIDGET_GONK)
|
|
||||||
}
|
|
||||||
#endif // defined(MOZ_WIDGET_GONK)
|
|
||||||
|
|
||||||
#endif // defined(XP_WIN)
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if defined(XP_WIN)
|
#if defined(XP_WIN)
|
||||||
nsAutoString updateDirPathW;
|
nsAutoString updateDirPathW;
|
||||||
rv = updateDir->GetPath(updateDirPathW);
|
rv = updateDir->GetPath(updateDirPathW);
|
||||||
|
|
||||||
NS_ConvertUTF16toUTF8 updateDirPath(updateDirPathW);
|
NS_ConvertUTF16toUTF8 updateDirPath(updateDirPathW);
|
||||||
#else
|
#else
|
||||||
nsAutoCString updateDirPath;
|
nsAutoCString updateDirPath;
|
||||||
rv = updateDir->GetNativePath(updateDirPath);
|
rv = updateDir->GetNativePath(updateDirPath);
|
||||||
#endif
|
#endif
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
if (NS_FAILED(rv))
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the current working directory.
|
// Get the current working directory.
|
||||||
char workingDirPath[MAXPATHLEN];
|
char workingDirPath[MAXPATHLEN];
|
||||||
@ -834,19 +852,20 @@ ApplyUpdate(nsIFile *greDir, nsIFile *updateDir, nsIFile *statusFile,
|
|||||||
immersiveArgc = 1;
|
immersiveArgc = 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
int argc = appArgc + 5 + immersiveArgc;
|
int argc = appArgc + 6 + immersiveArgc;
|
||||||
char **argv = new char*[argc + 1 ];
|
char **argv = new char*[argc + 1 ];
|
||||||
if (!argv)
|
if (!argv)
|
||||||
return;
|
return;
|
||||||
argv[0] = (char*) updaterPath.get();
|
argv[0] = (char*) updaterPath.get();
|
||||||
argv[1] = (char*) updateDirPath.get();
|
argv[1] = (char*) updateDirPath.get();
|
||||||
argv[2] = (char*) applyToDir.get();
|
argv[2] = (char*) installDirPath.get();
|
||||||
argv[3] = (char*) pid.get();
|
argv[3] = (char*) applyToDir.get();
|
||||||
|
argv[4] = (char*) pid.get();
|
||||||
if (restart && appArgc) {
|
if (restart && appArgc) {
|
||||||
argv[4] = workingDirPath;
|
argv[5] = workingDirPath;
|
||||||
argv[5] = (char*) appFilePath.get();
|
argv[6] = (char*) appFilePath.get();
|
||||||
for (int i = 1; i < appArgc; ++i)
|
for (int i = 1; i < appArgc; ++i)
|
||||||
argv[5 + i] = appArgv[i];
|
argv[6 + i] = appArgv[i];
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
if (immersiveArgc) {
|
if (immersiveArgc) {
|
||||||
argv[argc - 1] = "-ServerName:DefaultBrowserServer";
|
argv[argc - 1] = "-ServerName:DefaultBrowserServer";
|
||||||
@ -854,8 +873,8 @@ ApplyUpdate(nsIFile *greDir, nsIFile *updateDir, nsIFile *statusFile,
|
|||||||
#endif
|
#endif
|
||||||
argv[argc] = nullptr;
|
argv[argc] = nullptr;
|
||||||
} else {
|
} else {
|
||||||
argc = 4;
|
argc = 5;
|
||||||
argv[4] = nullptr;
|
argv[5] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gSafeMode) {
|
if (gSafeMode) {
|
||||||
|
Loading…
Reference in New Issue
Block a user