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/file_util.h" 11 #include "base/files/file_path.h" 12 #include "base/logging.h" 13 #include "base/logging_win.h" 14 #include "base/path_service.h" 15 #include "base/platform_file.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 const int file_flags = base::PLATFORM_FILE_OPEN | 41 base::PLATFORM_FILE_READ | 42 base::PLATFORM_FILE_SHARE_DELETE | 43 base::PLATFORM_FILE_DELETE_ON_CLOSE; 44 base::win::ScopedHandle old_log_file( 45 base::CreatePlatformFile(log_file, file_flags, NULL, NULL)); 46 47 if (old_log_file.IsValid()) { 48 result = LOGFILE_DELETED; 49 base::FilePath tmp_log(log_file.value() + FILE_PATH_LITERAL(".tmp")); 50 // Note that base::Move will attempt to replace existing files. 51 if (base::Move(log_file, tmp_log)) { 52 int64 offset = log_size - kTruncatedInstallerLogFileSize; 53 std::string old_log_data(kTruncatedInstallerLogFileSize, 0); 54 int bytes_read = base::ReadPlatformFile(old_log_file, 55 offset, 56 &old_log_data[0], 57 kTruncatedInstallerLogFileSize); 58 if (bytes_read > 0 && 59 (bytes_read == file_util::WriteFile(log_file, 60 &old_log_data[0], 61 bytes_read) || 62 base::PathExists(log_file))) { 63 result = LOGFILE_TRUNCATED; 64 } 65 } 66 } else if (base::DeleteFile(log_file, false)) { 67 // Couldn't get sufficient access to the log file, optimistically try to 68 // delete it. 69 result = LOGFILE_DELETED; 70 } 71 } 72 73 return result; 74 } 75 76 77 void InitInstallerLogging(const installer::MasterPreferences& prefs) { 78 if (installer_logging_) 79 return; 80 81 installer_logging_ = true; 82 83 bool value = false; 84 if (prefs.GetBool(installer::master_preferences::kDisableLogging, 85 &value) && value) { 86 return; 87 } 88 89 base::FilePath log_file_path(GetLogFilePath(prefs)); 90 TruncateLogFileIfNeeded(log_file_path); 91 92 logging::LoggingSettings settings; 93 settings.logging_dest = logging::LOG_TO_FILE; 94 settings.log_file = log_file_path.value().c_str(); 95 logging::InitLogging(settings); 96 97 if (prefs.GetBool(installer::master_preferences::kVerboseLogging, 98 &value) && value) { 99 logging::SetMinLogLevel(logging::LOG_VERBOSE); 100 } else { 101 logging::SetMinLogLevel(logging::LOG_ERROR); 102 } 103 104 // Enable ETW logging. 105 logging::LogEventProvider::Initialize(kSetupTraceProvider); 106 } 107 108 void EndInstallerLogging() { 109 logging::CloseLogFile(); 110 111 installer_logging_ = false; 112 } 113 114 base::FilePath GetLogFilePath(const installer::MasterPreferences& prefs) { 115 std::string path; 116 prefs.GetString(installer::master_preferences::kLogFile, &path); 117 if (!path.empty()) 118 return base::FilePath(UTF8ToWide(path)); 119 120 static const base::FilePath::CharType kLogFilename[] = 121 FILE_PATH_LITERAL("chrome_installer.log"); 122 123 // Fallback to current directory if getting the temp directory fails. 124 base::FilePath tmp_path; 125 ignore_result(PathService::Get(base::DIR_TEMP, &tmp_path)); 126 return tmp_path.Append(kLogFilename); 127 } 128 129 } // namespace installer 130