Home | History | Annotate | Download | only in util
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <windows.h>
      6 
      7 #include "chrome/installer/util/logging_installer.h"
      8 
      9 #include "base/command_line.h"
     10 #include "base/files/file.h"
     11 #include "base/files/file_path.h"
     12 #include "base/files/file_util.h"
     13 #include "base/logging.h"
     14 #include "base/logging_win.h"
     15 #include "base/path_service.h"
     16 #include "base/strings/string_util.h"
     17 #include "base/strings/utf_string_conversions.h"
     18 #include "base/win/scoped_handle.h"
     19 #include "chrome/installer/util/master_preferences.h"
     20 #include "chrome/installer/util/master_preferences_constants.h"
     21 #include "chrome/installer/util/util_constants.h"
     22 
     23 // {93BCE0BF-3FAF-43b1-9E28-BEB6FAB5ECE7}
     24 static const GUID kSetupTraceProvider = { 0x93bce0bf, 0x3faf, 0x43b1,
     25     { 0x9e, 0x28, 0xbe, 0xb6, 0xfa, 0xb5, 0xec, 0xe7 } };
     26 
     27 namespace installer {
     28 
     29 // This should be true for the period between the end of
     30 // InitInstallerLogging() and the beginning of EndInstallerLogging().
     31 bool installer_logging_ = false;
     32 
     33 TruncateResult TruncateLogFileIfNeeded(const base::FilePath& log_file) {
     34   TruncateResult result = LOGFILE_UNTOUCHED;
     35 
     36   int64 log_size = 0;
     37   if (base::GetFileSize(log_file, &log_size) &&
     38       log_size > kMaxInstallerLogFileSize) {
     39     // Cause the old log file to be deleted when we are done with it.
     40     uint32 file_flags = base::File::FLAG_OPEN |
     41                         base::File::FLAG_READ |
     42                         base::File::FLAG_SHARE_DELETE |
     43                         base::File::FLAG_DELETE_ON_CLOSE;
     44     base::File old_log_file(log_file, file_flags);
     45 
     46     if (old_log_file.IsValid()) {
     47       result = LOGFILE_DELETED;
     48       base::FilePath tmp_log(log_file.value() + FILE_PATH_LITERAL(".tmp"));
     49       // Note that base::Move will attempt to replace existing files.
     50       if (base::Move(log_file, tmp_log)) {
     51         int64 offset = log_size - kTruncatedInstallerLogFileSize;
     52         std::string old_log_data(kTruncatedInstallerLogFileSize, 0);
     53         int bytes_read = old_log_file.Read(offset,
     54                                            &old_log_data[0],
     55                                            kTruncatedInstallerLogFileSize);
     56         if (bytes_read > 0 &&
     57             (bytes_read == base::WriteFile(log_file, &old_log_data[0],
     58                                            bytes_read) ||
     59              base::PathExists(log_file))) {
     60           result = LOGFILE_TRUNCATED;
     61         }
     62       }
     63     } else if (base::DeleteFile(log_file, false)) {
     64       // Couldn't get sufficient access to the log file, optimistically try to
     65       // delete it.
     66       result = LOGFILE_DELETED;
     67     }
     68   }
     69 
     70   return result;
     71 }
     72 
     73 
     74 void InitInstallerLogging(const installer::MasterPreferences& prefs) {
     75   if (installer_logging_)
     76     return;
     77 
     78   installer_logging_ = true;
     79 
     80   bool value = false;
     81   if (prefs.GetBool(installer::master_preferences::kDisableLogging,
     82                     &value) && value) {
     83     return;
     84   }
     85 
     86   base::FilePath log_file_path(GetLogFilePath(prefs));
     87   TruncateLogFileIfNeeded(log_file_path);
     88 
     89   logging::LoggingSettings settings;
     90   settings.logging_dest = logging::LOG_TO_FILE;
     91   settings.log_file = log_file_path.value().c_str();
     92   logging::InitLogging(settings);
     93 
     94   if (prefs.GetBool(installer::master_preferences::kVerboseLogging,
     95                     &value) && value) {
     96     logging::SetMinLogLevel(logging::LOG_VERBOSE);
     97   } else {
     98     logging::SetMinLogLevel(logging::LOG_ERROR);
     99   }
    100 
    101   // Enable ETW logging.
    102   logging::LogEventProvider::Initialize(kSetupTraceProvider);
    103 }
    104 
    105 void EndInstallerLogging() {
    106   logging::CloseLogFile();
    107 
    108   installer_logging_ = false;
    109 }
    110 
    111 base::FilePath GetLogFilePath(const installer::MasterPreferences& prefs) {
    112   std::string path;
    113   prefs.GetString(installer::master_preferences::kLogFile, &path);
    114   if (!path.empty())
    115     return base::FilePath(base::UTF8ToWide(path));
    116 
    117   static const base::FilePath::CharType kLogFilename[] =
    118       FILE_PATH_LITERAL("chrome_installer.log");
    119 
    120   // Fallback to current directory if getting the temp directory fails.
    121   base::FilePath tmp_path;
    122   ignore_result(PathService::Get(base::DIR_TEMP, &tmp_path));
    123   return tmp_path.Append(kLogFilename);
    124 }
    125 
    126 }  // namespace installer
    127