1aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 2aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Copyright (C) 2012 The Android Open Source Project 3aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 4aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License"); 5aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// you may not use this file except in compliance with the License. 6aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// You may obtain a copy of the License at 7aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 8aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// http://www.apache.org/licenses/LICENSE-2.0 9aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 10aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Unless required by applicable law or agreed to in writing, software 11aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS, 12aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// See the License for the specific language governing permissions and 14aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// limitations under the License. 15aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 1649fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com 172e71f90d6af955a5359853132085931f1e0479e0Alex Deymo#include <sys/stat.h> 182e71f90d6af955a5359853132085931f1e0479e0Alex Deymo#include <sys/types.h> 1967363ee8c3c542e8799983cc4dd375b77e8252e9Alex Deymo#include <unistd.h> 202e71f90d6af955a5359853132085931f1e0479e0Alex Deymo#include <xz.h> 2167363ee8c3c542e8799983cc4dd375b77e8252e9Alex Deymo 224fe15d017c145aca449c2248420c1b4ec8c23758Andrew de los Reyes#include <string> 239d65b7b9249124a433b9a018a1952435f7f75c4dDarin Petkov 241023a6029771fb8dea867e14193df8e58a59a662Darin Petkov#include <base/at_exit.h> 251023a6029771fb8dea867e14193df8e58a59a662Darin Petkov#include <base/command_line.h> 2606c76a49bfd29c8abdb8abd5b646a6583783191aBen Chan#include <base/files/file_util.h> 271023a6029771fb8dea867e14193df8e58a59a662Darin Petkov#include <base/logging.h> 2875039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko#include <base/strings/string_util.h> 2975039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko#include <base/strings/stringprintf.h> 303f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko#include <brillo/flag_helper.h> 319d65b7b9249124a433b9a018a1952435f7f75c4dDarin Petkov 3239910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/terminator.h" 3339910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/utils.h" 34b7ca096f98a43ebbf412f1b2d3d15bb184f871f8Alex Deymo#include "update_engine/daemon.h" 354e9b9f4d57a0c95fb1b9281077f0eef5fdf5e345Andrew de los Reyes 364fe15d017c145aca449c2248420c1b4ec8c23758Andrew de los Reyesusing std::string; 3767363ee8c3c542e8799983cc4dd375b77e8252e9Alex Deymo 384fe15d017c145aca449c2248420c1b4ec8c23758Andrew de los Reyesnamespace chromeos_update_engine { 3973520670492f3358c496698767879adcf6c03aeaAndrew de los Reyesnamespace { 4073520670492f3358c496698767879adcf6c03aeaAndrew de los Reyes 4130291edee8e2f7646b540b00672c81b442386ed6Darin Petkovvoid SetupLogSymlink(const string& symlink_path, const string& log_path) { 4230291edee8e2f7646b540b00672c81b442386ed6Darin Petkov // TODO(petkov): To ensure a smooth transition between non-timestamped and 4330291edee8e2f7646b540b00672c81b442386ed6Darin Petkov // timestamped logs, move an existing log to start the first timestamped 4430291edee8e2f7646b540b00672c81b442386ed6Darin Petkov // one. This code can go away once all clients are switched to this version or 4530291edee8e2f7646b540b00672c81b442386ed6Darin Petkov // we stop caring about the old-style logs. 4630291edee8e2f7646b540b00672c81b442386ed6Darin Petkov if (utils::FileExists(symlink_path.c_str()) && 4730291edee8e2f7646b540b00672c81b442386ed6Darin Petkov !utils::IsSymlink(symlink_path.c_str())) { 4875039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko base::ReplaceFile(base::FilePath(symlink_path), 4975039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko base::FilePath(log_path), 5075039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko nullptr); 5130291edee8e2f7646b540b00672c81b442386ed6Darin Petkov } 5275039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko base::DeleteFile(base::FilePath(symlink_path), true); 5330291edee8e2f7646b540b00672c81b442386ed6Darin Petkov if (symlink(log_path.c_str(), symlink_path.c_str()) == -1) { 5430291edee8e2f7646b540b00672c81b442386ed6Darin Petkov PLOG(ERROR) << "Unable to create symlink " << symlink_path 5530291edee8e2f7646b540b00672c81b442386ed6Darin Petkov << " pointing at " << log_path; 5630291edee8e2f7646b540b00672c81b442386ed6Darin Petkov } 5730291edee8e2f7646b540b00672c81b442386ed6Darin Petkov} 5873520670492f3358c496698767879adcf6c03aeaAndrew de los Reyes 5930291edee8e2f7646b540b00672c81b442386ed6Darin Petkovstring GetTimeAsString(time_t utime) { 6030291edee8e2f7646b540b00672c81b442386ed6Darin Petkov struct tm tm; 61d2779df63aaad8b65fc5d4badee7dbc9bed7f2b6Alex Vakulenko CHECK_EQ(localtime_r(&utime, &tm), &tm); 6230291edee8e2f7646b540b00672c81b442386ed6Darin Petkov char str[16]; 63d2779df63aaad8b65fc5d4badee7dbc9bed7f2b6Alex Vakulenko CHECK_EQ(strftime(str, sizeof(str), "%Y%m%d-%H%M%S", &tm), 15u); 6430291edee8e2f7646b540b00672c81b442386ed6Darin Petkov return str; 6530291edee8e2f7646b540b00672c81b442386ed6Darin Petkov} 6649fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com 6730291edee8e2f7646b540b00672c81b442386ed6Darin Petkovstring SetupLogFile(const string& kLogsRoot) { 6830291edee8e2f7646b540b00672c81b442386ed6Darin Petkov const string kLogSymlink = kLogsRoot + "/update_engine.log"; 6930291edee8e2f7646b540b00672c81b442386ed6Darin Petkov const string kLogsDir = kLogsRoot + "/update_engine"; 7030291edee8e2f7646b540b00672c81b442386ed6Darin Petkov const string kLogPath = 7175039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko base::StringPrintf("%s/update_engine.%s", 7275039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko kLogsDir.c_str(), 7375039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko GetTimeAsString(::time(nullptr)).c_str()); 7430291edee8e2f7646b540b00672c81b442386ed6Darin Petkov mkdir(kLogsDir.c_str(), 0755); 7530291edee8e2f7646b540b00672c81b442386ed6Darin Petkov SetupLogSymlink(kLogSymlink, kLogPath); 7630291edee8e2f7646b540b00672c81b442386ed6Darin Petkov return kLogSymlink; 7730291edee8e2f7646b540b00672c81b442386ed6Darin Petkov} 7830291edee8e2f7646b540b00672c81b442386ed6Darin Petkov 79d570820920e030fefd9644fb5427b538160af1a1Steve Fungvoid SetupLogging(bool log_to_std_err) { 80d603ba9ff52c72a68556495245e1069c991866d4Alex Deymo string log_file; 8175039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko logging::LoggingSettings log_settings; 8275039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko log_settings.lock_log = logging::DONT_LOCK_LOG_FILE; 8375039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko log_settings.delete_old = logging::APPEND_TO_OLD_LOG_FILE; 8475039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko 85d570820920e030fefd9644fb5427b538160af1a1Steve Fung if (log_to_std_err) { 8675039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko // Log to stderr initially. 8775039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko log_settings.log_file = nullptr; 8875039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko log_settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; 8975039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko } else { 90d603ba9ff52c72a68556495245e1069c991866d4Alex Deymo log_file = SetupLogFile("/var/log"); 9175039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko log_settings.log_file = log_file.c_str(); 9275039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko log_settings.logging_dest = logging::LOG_TO_FILE; 9330291edee8e2f7646b540b00672c81b442386ed6Darin Petkov } 9475039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko 9575039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko logging::InitLogging(log_settings); 9630291edee8e2f7646b540b00672c81b442386ed6Darin Petkov} 97000d895da247697f4e4e0c67a3a847f71fca8eb9Andrew de los Reyes 98d2779df63aaad8b65fc5d4badee7dbc9bed7f2b6Alex Vakulenko} // namespace 9930291edee8e2f7646b540b00672c81b442386ed6Darin Petkov} // namespace chromeos_update_engine 10049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com 10149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.comint main(int argc, char** argv) { 102d570820920e030fefd9644fb5427b538160af1a1Steve Fung DEFINE_bool(logtostderr, false, 103d570820920e030fefd9644fb5427b538160af1a1Steve Fung "Write logs to stderr instead of to a file in log_dir."); 104d570820920e030fefd9644fb5427b538160af1a1Steve Fung DEFINE_bool(foreground, false, 105d570820920e030fefd9644fb5427b538160af1a1Steve Fung "Don't daemon()ize; run in foreground."); 106d570820920e030fefd9644fb5427b538160af1a1Steve Fung 1079c0baf82049efd95230a8389769e1b3e5d001209Darin Petkov chromeos_update_engine::Terminator::Init(); 1083f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko brillo::FlagHelper::Init(argc, argv, "Chromium OS Update Engine"); 109d570820920e030fefd9644fb5427b538160af1a1Steve Fung chromeos_update_engine::SetupLogging(FLAGS_logtostderr); 1106b78e29f80e98c4ad009c830012682220dc9de3bAndrew de los Reyes if (!FLAGS_foreground) 1116b78e29f80e98c4ad009c830012682220dc9de3bAndrew de los Reyes PLOG_IF(FATAL, daemon(0, 0) == 1) << "daemon() failed"; 1126b78e29f80e98c4ad009c830012682220dc9de3bAndrew de los Reyes 1134fe15d017c145aca449c2248420c1b4ec8c23758Andrew de los Reyes LOG(INFO) << "Chrome OS Update Engine starting"; 114a4a8a8ccc2d9e0285728ed247b43f09433e63323Darin Petkov 1152e71f90d6af955a5359853132085931f1e0479e0Alex Deymo // xz-embedded requires to initialize its CRC-32 table once on startup. 1162e71f90d6af955a5359853132085931f1e0479e0Alex Deymo xz_crc32_init(); 1172e71f90d6af955a5359853132085931f1e0479e0Alex Deymo 1184dc2ada660d3f7cd50d624b6bf102d806cf8997fChris Masone // Ensure that all written files have safe permissions. 119a9fea846fce755062537320ad5126a40078409fbAlex Deymo // This is a mask, so we _block_ all permissions for the group owner and other 120a9fea846fce755062537320ad5126a40078409fbAlex Deymo // users but allow all permissions for the user owner. We allow execution 121a9fea846fce755062537320ad5126a40078409fbAlex Deymo // for the owner so we can create directories. 1224dc2ada660d3f7cd50d624b6bf102d806cf8997fChris Masone // Done _after_ log file creation. 123a9fea846fce755062537320ad5126a40078409fbAlex Deymo umask(S_IRWXG | S_IRWXO); 1244dc2ada660d3f7cd50d624b6bf102d806cf8997fChris Masone 125b7ca096f98a43ebbf412f1b2d3d15bb184f871f8Alex Deymo chromeos_update_engine::UpdateEngineDaemon update_engine_daemon; 126b7ca096f98a43ebbf412f1b2d3d15bb184f871f8Alex Deymo int exit_code = update_engine_daemon.Run(); 1274fe15d017c145aca449c2248420c1b4ec8c23758Andrew de los Reyes 128b7ca096f98a43ebbf412f1b2d3d15bb184f871f8Alex Deymo LOG(INFO) << "Chrome OS Update Engine terminating with exit code " 129b7ca096f98a43ebbf412f1b2d3d15bb184f871f8Alex Deymo << exit_code; 130b7ca096f98a43ebbf412f1b2d3d15bb184f871f8Alex Deymo return exit_code; 13149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com} 132