Backout of 71fcbc6087f3 due to test failures
authorRobert Strong <robert.bugzilla@gmail.com>
Thu, 09 Jul 2015 23:40:58 -0700
changeset 491450 ef3942acc585b996044d8b185c36901eb3e92e8a
parent 491449 d325765dd694ff530fafa4aa03cc74f9fe49c586
child 491451 37b26b8494407ca7ab55f8417c5750cefee52d6a
push id47343
push userbmo:dothayer@mozilla.com
push dateWed, 01 Mar 2017 22:58:58 +0000
milestone42.0a1
backs out71fcbc6087f3ed89eec4ea44b38611977e2223f0
Backout of 71fcbc6087f3 due to test failures
toolkit/mozapps/update/common/updatelogging.cpp
toolkit/mozapps/update/common/updatelogging.h
toolkit/mozapps/update/nsUpdateService.js
toolkit/mozapps/update/tests/data/xpcshellUtilsAUS.js
toolkit/mozapps/update/updater/updater.cpp
--- a/toolkit/mozapps/update/common/updatelogging.cpp
+++ b/toolkit/mozapps/update/common/updatelogging.cpp
@@ -13,111 +13,95 @@
 #include <stdarg.h>
 
 #include "updatelogging.h"
 
 UpdateLog::UpdateLog() : logFP(nullptr)
 {
 }
 
-void UpdateLog::Init(NS_tchar* sourcePath, const NS_tchar* fileName)
+void UpdateLog::Init(NS_tchar* sourcePath,
+                     const NS_tchar* fileName,
+                     const NS_tchar* alternateFileName,
+                     bool append)
 {
-  if (logFP) {
+  if (logFP)
     return;
+
+#ifdef XP_WIN
+  GetTempFileNameW(sourcePath, L"log", 0, mTmpFilePath);
+  if (append) {
+    NS_tsnprintf(mDstFilePath, sizeof(mDstFilePath)/sizeof(mDstFilePath[0]),
+      NS_T("%s/%s"), sourcePath, alternateFileName);
+    MoveFileExW(mDstFilePath, mTmpFilePath, MOVEFILE_REPLACE_EXISTING);
+  } else {
+    NS_tsnprintf(mDstFilePath, sizeof(mDstFilePath)/sizeof(mDstFilePath[0]),
+                 NS_T("%s/%s"), sourcePath, fileName);
   }
 
+  logFP = NS_tfopen(mTmpFilePath, append ? NS_T("a") : NS_T("w"));
+  // Delete this file now so it is possible to tell from the unelevated
+  // updater process if the elevated updater process has written the log.
+  DeleteFileW(mDstFilePath);
+#else
   NS_tsnprintf(mDstFilePath, sizeof(mDstFilePath)/sizeof(mDstFilePath[0]),
                NS_T("%s/%s"), sourcePath, fileName);
-  // If there is a pre-existing file it is renamed by adding .bak to the file
-  // name instead of overwriting it. If there is already a file with that name
-  // that file is removed first.
-  if (!NS_taccess(mDstFilePath, F_OK)) {
-    NS_tchar bakFilePath[MAXPATHLEN];
-    NS_tsnprintf(bakFilePath, sizeof(bakFilePath)/sizeof(bakFilePath[0]),
-                 NS_T("%s/%s.bak"), sourcePath, fileName);
-    NS_tremove(bakFilePath);
-    NS_trename(mDstFilePath, bakFilePath);
+
+  if (alternateFileName && NS_taccess(mDstFilePath, F_OK)) {
+    NS_tsnprintf(mDstFilePath, sizeof(mDstFilePath)/sizeof(mDstFilePath[0]),
+      NS_T("%s/%s"), sourcePath, alternateFileName);
   }
-#if defined(XP_WIN)
-  GetTempFileNameW(sourcePath, L"log", 0, mTmpFilePath);
-  logFP = NS_tfopen(mTmpFilePath, NS_T("w"));
-  // Delete this file now so it is possible to tell from the unelevated
-  // updater process if the elevated updater process has written the log.
-  NS_tremove(mDstFilePath);
-#elif defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(MOZ_WIDGET_GONK)
-  // On Linux an in memory file is used and written to the destination file when
-  // the logging is finished since the update.log file is located in the
-  // application directory and the application directory is renamed when a
-  // staged update renames the application directory. After Linux uses an
-  // updates directory outside of the application directory this can use fopen
-  // just as Mac and Gonk uses.
-  size_t len;
-  logFP = open_memstream(&logBuf, &len);
-#else
-  logFP = NS_tfopen(mDstFilePath, NS_T("w"));
+
+  logFP = NS_tfopen(mDstFilePath, append ? NS_T("a") : NS_T("w"));
 #endif
 }
 
 void UpdateLog::Finish()
 {
-  if (!logFP) {
+  if (!logFP)
     return;
-  }
 
   fclose(logFP);
   logFP = nullptr;
 
-#if defined(XP_WIN)
+#ifdef XP_WIN
   // When the log file already exists then the elevated updater has already
   // written the log file and the temp file for the log should be discarded.
   if (!NS_taccess(mDstFilePath, F_OK)) {
     DeleteFileW(mTmpFilePath);
   } else {
-    MoveFileExW(mTmpFilePath, mDstFilePath, MOVEFILE_REPLACE_EXISTING);
-  }
-#endif
-
-#if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(MOZ_WIDGET_GONK)
-  if (logBuf) {
-    logFP = NS_tfopen(mDstFilePath, NS_T("w"));
-    fprintf(logFP, logBuf);
-    free(logBuf);
-    fclose(logFP);
-    logFP = nullptr;
+    MoveFileW(mTmpFilePath, mDstFilePath);
   }
 #endif
 }
 
 void UpdateLog::Flush()
 {
-  if (!logFP) {
+  if (!logFP)
     return;
-  }
 
   fflush(logFP);
 }
 
 void UpdateLog::Printf(const char *fmt, ... )
 {
-  if (!logFP) {
+  if (!logFP)
     return;
-  }
 
   va_list ap;
   va_start(ap, fmt);
   vfprintf(logFP, fmt, ap);
   fprintf(logFP, "\n");
   va_end(ap);
 }
 
 void UpdateLog::WarnPrintf(const char *fmt, ... )
 {
-  if (!logFP) {
+  if (!logFP)
     return;
-  }
 
   va_list ap;
   va_start(ap, fmt);
   fprintf(logFP, "*** Warning: ");
   vfprintf(logFP, fmt, ap);
   fprintf(logFP, "***\n");
   va_end(ap);
 }
--- a/toolkit/mozapps/update/common/updatelogging.h
+++ b/toolkit/mozapps/update/common/updatelogging.h
@@ -12,39 +12,37 @@ class UpdateLog
 {
 public:
   static UpdateLog & GetPrimaryLog() 
   {
     static UpdateLog primaryLog;
     return primaryLog;
   }
 
-  void Init(NS_tchar* sourcePath, const NS_tchar* fileName);
+  void Init(NS_tchar* sourcePath, const NS_tchar* fileName,
+            const NS_tchar* alternateFileName, bool append);
   void Finish();
   void Flush();
   void Printf(const char *fmt, ... );
   void WarnPrintf(const char *fmt, ... );
 
   ~UpdateLog()
   {
     Finish();
   }
 
 protected:
   UpdateLog();
   FILE *logFP;
+  NS_tchar mTmpFilePath[MAXPATHLEN];
   NS_tchar mDstFilePath[MAXPATHLEN];
-#if defined(XP_WIN)
-  NS_tchar mTmpFilePath[MAXPATHLEN];
-#endif
-#if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(MOZ_WIDGET_GONK)
-  NS_tchar *logBuf;
-#endif
 };
 
 #define LOG_WARN(args) UpdateLog::GetPrimaryLog().WarnPrintf args
 #define LOG(args) UpdateLog::GetPrimaryLog().Printf args
 #define LogInit(PATHNAME_, FILENAME_) \
-  UpdateLog::GetPrimaryLog().Init(PATHNAME_, FILENAME_)
+  UpdateLog::GetPrimaryLog().Init(PATHNAME_, FILENAME_, 0, false)
+#define LogInitAppend(PATHNAME_, FILENAME_, ALTERNATE_) \
+  UpdateLog::GetPrimaryLog().Init(PATHNAME_, FILENAME_, ALTERNATE_, true)
 #define LogFinish() UpdateLog::GetPrimaryLog().Finish()
 #define LogFlush() UpdateLog::GetPrimaryLog().Flush()
 
 #endif
--- a/toolkit/mozapps/update/nsUpdateService.js
+++ b/toolkit/mozapps/update/nsUpdateService.js
@@ -76,17 +76,16 @@ const DIR_UPDATED         = "updated";
 const DIR_UPDATED_APP     = "Updated.app";
 const DIR_UPDATES         = "updates";
 
 const FILE_UPDATE_STATUS  = "update.status";
 const FILE_UPDATE_VERSION = "update.version";
 const FILE_UPDATE_ARCHIVE = "update.mar";
 const FILE_UPDATE_LINK    = "update.link";
 const FILE_UPDATE_LOG     = "update.log";
-const FILE_UPDATE_LOG_BAK = "update.log.bak";
 const FILE_UPDATES_DB     = "updates.xml";
 const FILE_UPDATE_ACTIVE  = "active-update.xml";
 const FILE_PERMS_TEST     = "update.test";
 const FILE_LAST_LOG       = "last-update.log";
 const FILE_BACKUP_LOG     = "backup-update.log";
 const FILE_UPDATE_LOCALE  = "update.locale";
 
 const STATE_NONE            = "null";
@@ -1111,44 +1110,42 @@ function cleanUpMozUpdaterDirs() {
   } catch (e) {
     LOG("cleanUpMozUpdaterDirs - Exception: " + e);
   }
 }
 
 /**
  * Removes the contents of the Updates Directory
  *
- * @param aRemoveFiles
- *        When this is true the files in the updates patch directory are removed
- *        and the log files are renamed. When it is false only the log files are
- *        renamed.
+ * @param aBackgroundUpdate Whether the update has been performed in the
+ *        background.  If this is true, we move the update log file to the
+ *        updated directory, so that it survives replacing the directories
+ *        later on.
  */
-function cleanUpUpdatesDir(aRemoveFiles) {
+function cleanUpUpdatesDir(aBackgroundUpdate) {
   // Bail out if we don't have appropriate permissions
   let updateDir;
   try {
     updateDir = getUpdatesDir();
   } catch (e) {
     return;
   }
 
   // Preserve the last update log file for debugging purposes.
   let file = updateDir.clone();
   file.append(FILE_UPDATE_LOG);
   if (file.exists()) {
-    let dir = updateDir.parent;
+    let dir;
+    if (aBackgroundUpdate && getUpdateDirNoCreate([]).equals(getAppBaseDir())) {
+      dir = getUpdatesDirInApplyToDir();
+    } else {
+      dir = updateDir.parent;
+    }
     let logFile = dir.clone();
-    let updateLogBak = updateDir.clone();
-    updateLogBak.append(FILE_UPDATE_LOG_BAK);
-    if (updateLogBak.exists()) {
-      logFile = updateLogBak;
-    } else {
-      logFile.append(FILE_LAST_LOG);
-    }
-
+    logFile.append(FILE_LAST_LOG);
     if (logFile.exists()) {
       try {
         logFile.moveTo(dir, FILE_BACKUP_LOG);
       } catch (e) {
         LOG("cleanUpUpdatesDir - failed to rename file " + logFile.path +
             " to " + FILE_BACKUP_LOG);
       }
     }
@@ -1156,17 +1153,17 @@ function cleanUpUpdatesDir(aRemoveFiles)
     try {
       file.moveTo(dir, FILE_LAST_LOG);
     } catch (e) {
       LOG("cleanUpUpdatesDir - failed to rename file " + file.path +
           " to " + FILE_LAST_LOG);
     }
   }
 
-  if (aRemoveFiles) {
+  if (!aBackgroundUpdate) {
     let e = updateDir.directoryEntries;
     while (e.hasMoreElements()) {
       let f = e.getNext().QueryInterface(Ci.nsIFile);
       if (AppConstants.platform == "gonk") {
         if (f.leafName == FILE_UPDATE_LINK) {
           let linkedFile = getFileFromUpdateLink(updateDir);
           if (linkedFile && linkedFile.exists()) {
             linkedFile.remove(false);
@@ -1195,17 +1192,17 @@ function cleanUpUpdatesDir(aRemoveFiles)
 function cleanupActiveUpdate() {
   // Move the update from the Active Update list into the Past Updates list.
   var um = Cc["@mozilla.org/updates/update-manager;1"].
            getService(Ci.nsIUpdateManager);
   um.activeUpdate = null;
   um.saveUpdates();
 
   // Now trash the updates directory, since we're done with it
-  cleanUpUpdatesDir(true);
+  cleanUpUpdatesDir();
 }
 
 /**
  * Gets the locale from the update.locale file for replacing %LOCALE% in the
  * update url. The update.locale file can be located in the application
  * directory or the GRE directory with preference given to it being located in
  * the application directory.
  */
@@ -1341,17 +1338,16 @@ function handleUpdateFailure(update, err
   }
 
   // Replace with Array.prototype.includes when it has stabilized.
   if (WRITE_ERRORS.indexOf(update.errorCode) != -1 ||
       update.errorCode == FILESYSTEM_MOUNT_READWRITE_ERROR) {
     Cc["@mozilla.org/updates/update-prompt;1"].
       createInstance(Ci.nsIUpdatePrompt).
       showUpdateError(update);
-    cleanUpUpdatesDir(false);
     writeStatusFile(getUpdatesDir(), update.state = STATE_PENDING);
     return true;
   }
 
   if (update.errorCode == ELEVATION_CANCELED) {
     writeStatusFile(getUpdatesDir(), update.state = STATE_PENDING);
     let cancelations = getPref("getIntPref", PREF_APP_UPDATE_CANCELATIONS, 0);
     cancelations++;
@@ -2223,20 +2219,16 @@ UpdateService.prototype = {
       }
 
       // Something went wrong with the patch application process.
       handleFallbackToCompleteUpdate(update, false);
 
       prompter.showUpdateError(update);
     }
 
-    if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_CANCELATIONS)) {
-      Services.prefs.clearUserPref(PREF_APP_UPDATE_CANCELATIONS);
-    }
-
     // Now trash the MozUpdater directory created when replacing an install with
     // a staged update.
     cleanUpMozUpdaterDirs();
   },
 
   /**
    * Register an observer when the network comes online, so we can short-circuit
    * the app.update.interval when there isn't connectivity
@@ -3107,17 +3099,17 @@ function UpdateManager() {
   var updates = this._loadXMLFileIntoArray(getUpdateFile(
                   [FILE_UPDATE_ACTIVE]));
   if (updates.length > 0) {
     // Under some edgecases such as Windows system restore the active-update.xml
     // will contain a pending update without the status file which will return
     // STATE_NONE. To recover from this situation clean the updates dir and
     // rewrite the active-update.xml file without the broken update.
     if (readStatusFile(getUpdatesDir()) == STATE_NONE) {
-      cleanUpUpdatesDir(true);
+      cleanUpUpdatesDir();
       this._writeUpdatesToXMLFile([], getUpdateFile([FILE_UPDATE_ACTIVE]));
     }
     else
       this._activeUpdate = updates[0];
   }
 }
 UpdateManager.prototype = {
   /**
@@ -3246,17 +3238,17 @@ UpdateManager.prototype = {
       prefSvc.observe(null, "reload-default-prefs", null);
       if (this._activeUpdate.channel != UpdateChannel.get()) {
         // User switched channels, clear out any old active updates and remove
         // partial downloads
         this._activeUpdate = null;
         this.saveUpdates();
 
         // Destroy the updates directory, since we're done with it.
-        cleanUpUpdatesDir(true);
+        cleanUpUpdatesDir();
       }
     }
     return this._activeUpdate;
   },
   set activeUpdate(activeUpdate) {
     this._addUpdate(activeUpdate);
     this._activeUpdate = activeUpdate;
     if (!activeUpdate) {
@@ -3367,42 +3359,40 @@ UpdateManager.prototype = {
   /**
    * See nsIUpdateService.idl
    */
   refreshUpdateStatus: function UM_refreshUpdateStatus() {
     var update = this._activeUpdate;
     if (!update) {
       return;
     }
-    let stageSucceeded = true;
+    var updateSucceeded = true;
     var status = readStatusFile(getUpdatesDir());
     pingStateAndStatusCodes(update, false, status);
     var parts = status.split(":");
     update.state = parts[0];
 
     if (update.state == STATE_FAILED && parts[1]) {
-      stageSucceeded = false;
+      updateSucceeded = false;
       if (!handleUpdateFailure(update, parts[1])) {
         handleFallbackToCompleteUpdate(update, true);
       }
     }
     if (update.state == STATE_APPLIED && shouldUseService()) {
       writeStatusFile(getUpdatesDir(), update.state = STATE_APPLIED_SVC);
     }
     var um = Cc["@mozilla.org/updates/update-manager;1"].
              getService(Ci.nsIUpdateManager);
     um.saveUpdates();
 
     if (update.state != STATE_PENDING && update.state != STATE_PENDING_SVC) {
       // Destroy the updates directory, since we're done with it.
       // Make sure to not do this when the updater has fallen back to
       // non-staged updates.
-      cleanUpUpdatesDir(!stageSucceeded);
-    } else {
-      cleanUpUpdatesDir(false);
+      cleanUpUpdatesDir(updateSucceeded);
     }
 
     // Send an observer notification which the update wizard uses in
     // order to update its UI.
     LOG("UpdateManager:refreshUpdateStatus - Notifying observers that " +
         "the update was staged. state: " + update.state + ", status: " + status);
     Services.obs.notifyObservers(null, "update-staged", update.state);
 
@@ -3416,17 +3406,16 @@ UpdateManager.prototype = {
         let prompter = Cc["@mozilla.org/updates/update-prompt;1"].
                        createInstance(Ci.nsIUpdatePrompt);
         prompter.showUpdateDownloaded(update, true);
       } else {
         releaseSDCardMountLock();
       }
       return;
     }
-
     // Only prompt when the UI isn't already open.
     let windowType = getPref("getCharPref", PREF_APP_UPDATE_ALTWINDOWTYPE, null);
     if (Services.wm.getMostRecentWindow(UPDATE_WINDOW_NAME) ||
         windowType && Services.wm.getMostRecentWindow(windowType)) {
       return;
     }
 
     if (update.state == STATE_APPLIED || update.state == STATE_APPLIED_SVC ||
@@ -4323,17 +4312,17 @@ Downloader.prototype = {
         const vfCode = "verification_failed";
         var message = getStatusTextFromCode(vfCode, vfCode);
         this._update.statusText = message;
 
         if (this._update.isCompleteUpdate || this._update.patchCount != 2)
           deleteActiveUpdate = true;
 
         // Destroy the updates directory, since we're done with it.
-        cleanUpUpdatesDir(true);
+        cleanUpUpdatesDir();
       }
     } else {
       if (status == Cr.NS_ERROR_OFFLINE) {
         // Register an online observer to try again.
         // The online observer will continue the incremental download by
         // calling downloadUpdate on the active update which continues
         // downloading the file from where it was.
         LOG("Downloader:onStopRequest - offline, register online observer: true");
@@ -4383,17 +4372,17 @@ Downloader.prototype = {
         if (AppConstants.platform == "gonk") {
           // bug891009: On FirefoxOS, manaully retry OTA download will reuse
           // the Update object. We need to remove selected patch so that download
           // can be triggered again successfully.
           this._update.selectedPatch.selected = false;
         }
 
         // Destroy the updates directory, since we're done with it.
-        cleanUpUpdatesDir(true);
+        cleanUpUpdatesDir();
 
         deleteActiveUpdate = true;
       }
     }
     LOG("Downloader:onStopRequest - setting state to: " + state);
     this._patch.state = state;
     var um = Cc["@mozilla.org/updates/update-manager;1"].
              getService(Ci.nsIUpdateManager);
--- a/toolkit/mozapps/update/tests/data/xpcshellUtilsAUS.js
+++ b/toolkit/mozapps/update/tests/data/xpcshellUtilsAUS.js
@@ -2461,54 +2461,16 @@ function createUpdaterINI(aIsExeAsync) {
                            "ExeRelPath=" + gPostUpdateBinFile + "\n" +
                            exeArg +
                            exeAsync;
   let updaterIni = getApplyDirFile(DIR_RESOURCES + FILE_UPDATER_INI, true);
   writeFile(updaterIni, updaterIniContents);
 }
 
 /**
- * Gets the specified update log.
- *
- * @param   aLogLeafName
- *          The leaf name of the log to get.
- * @return  nsIFile for the update log.
- */
-function getUpdateLog(aLogLeafName) {
-  let updateLog = getUpdatesDir();
-  if (aLogLeafName == FILE_UPDATE_LOG) {
-    updateLog.append(DIR_PATCH);
-  }
-  updateLog.append(aLogLeafName);
-  return updateLog;
-}
-
-/**
- * Logs the contents of an update log.
- *
- * @param   aLogLeafName
- *          The leaf name of the log.
- */
-function logUpdateLog(aLogLeafName) {
-  let updateLog = getUpdateLog(aLogLeafName);
-  if (updateLog.exists()) {
-    // xpcshell tests won't display the entire contents so log each line.
-    let updateLogContents = readFileBytes(updateLog).replace(/\r\n/g, "\n");
-    updateLogContents = replaceLogPaths(updateLogContents);
-    let aryLogContents = updateLogContents.split("\n");
-    logTestInfo("contents of " + updateLog.path + ":");
-    aryLogContents.forEach(function RU_LC_FE(aLine) {
-      logTestInfo(aLine);
-    });
-  } else {
-    logTestInfo("update log doesn't exist, path: " + updateLog.path);
-  }
-}
-
-/**
  * Helper function that replaces the common part of paths in the update log's
  * contents with <test_dir_path> for paths to the the test directory and
  * <update_dir_path> for paths to the update directory. This is needed since
  * Assert.equal will truncate what it prints to the xpcshell log file.
  *
  * @param   aLogContents
  *          The update log file's contents.
  * @return  the log contents with the paths replaced.
@@ -2611,17 +2573,17 @@ function checkUpdateLogContents(aCompare
   updateLogContents = updateLogContents.replace(/^\n|\n$/g, "");
   updateLogContents = replaceLogPaths(updateLogContents);
 
   let compareLogContents = "";
   if (aCompareLogFile) {
     compareLogContents = readFileBytes(getTestDirFile(aCompareLogFile));
   }
   if (gSwitchApp) {
-    compareLogContents = LOG_SWITCH_SUCCESS;
+    compareLogContents += LOG_SWITCH_SUCCESS;
   }
   // The channel-prefs.js is defined in gTestFilesCommon which will always be
   // located to the end of gTestFiles.
   if (gTestFiles.length > 1 &&
       gTestFiles[gTestFiles.length - 1].fileName == "channel-prefs.js" &&
       !gTestFiles[gTestFiles.length - 1].originalContents) {
     compareLogContents = compareLogContents.replace(/.*defaults\/.*/g, "");
   }
@@ -2639,17 +2601,16 @@ function checkUpdateLogContents(aCompare
   compareLogContents = compareLogContents.replace(/^\n|\n$/g, "");
 
   // Don't write the contents of the file to the log to reduce log spam
   // unless there is a failure.
   if (compareLogContents == updateLogContents) {
     Assert.ok(true, "the update log contents" + MSG_SHOULD_EQUAL);
   } else {
     logTestInfo("the update log contents are not correct");
-    logUpdateLog(FILE_UPDATE_LOG);
     let aryLog = updateLogContents.split("\n");
     let aryCompare = compareLogContents.split("\n");
     // Pushing an empty string to both arrays makes it so either array's length
     // can be used in the for loop below without going out of bounds.
     aryLog.push("");
     aryCompare.push("");
     // xpcshell tests won't display the entire contents so log the incorrect
     // line.
--- a/toolkit/mozapps/update/updater/updater.cpp
+++ b/toolkit/mozapps/update/updater/updater.cpp
@@ -2624,17 +2624,32 @@ int NS_main(int argc, NS_tchar **argv)
     *slash = NS_T('\0');
   }
 
   if (EnvHasValue("MOZ_OS_UPDATE")) {
     sIsOSUpdate = true;
     putenv(const_cast<char*>("MOZ_OS_UPDATE="));
   }
 
-  LogInit(gPatchDirPath, NS_T("update.log"));
+  if (sReplaceRequest) {
+    // If we're attempting to replace the application, try to append to the
+    // log generated when staging the staged update.
+#if defined(XP_WIN) || defined(XP_MACOSX)
+    NS_tchar* logDir = gPatchDirPath;
+#else
+    NS_tchar logDir[MAXPATHLEN];
+    NS_tsnprintf(logDir, sizeof(logDir)/sizeof(logDir[0]),
+                 NS_T("%s/updated/updates"),
+                 gInstallDirPath);
+#endif
+
+    LogInitAppend(logDir, NS_T("last-update.log"), NS_T("update.log"));
+  } else {
+    LogInit(gPatchDirPath, NS_T("update.log"));
+  }
 
   if (!WriteStatusFile("applying")) {
     LOG(("failed setting status to 'applying'"));
     return 1;
   }
 
   if (sStagedUpdate) {
     LOG(("Performing a staged update"));