main.cc revision aea4c1cea20dda7ae7e85fc8924a2d784f70d806
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
1767363ee8c3c542e8799983cc4dd375b77e8252e9Alex Deymo#include <unistd.h>
1867363ee8c3c542e8799983cc4dd375b77e8252e9Alex Deymo
194fe15d017c145aca449c2248420c1b4ec8c23758Andrew de los Reyes#include <string>
209d65b7b9249124a433b9a018a1952435f7f75c4dDarin Petkov
211023a6029771fb8dea867e14193df8e58a59a662Darin Petkov#include <base/at_exit.h>
221023a6029771fb8dea867e14193df8e58a59a662Darin Petkov#include <base/command_line.h>
2306c76a49bfd29c8abdb8abd5b646a6583783191aBen Chan#include <base/files/file_util.h>
241023a6029771fb8dea867e14193df8e58a59a662Darin Petkov#include <base/logging.h>
2575039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko#include <base/strings/string_util.h>
2675039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko#include <base/strings/stringprintf.h>
27d570820920e030fefd9644fb5427b538160af1a1Steve Fung#include <chromeos/flag_helper.h>
28b7ca096f98a43ebbf412f1b2d3d15bb184f871f8Alex Deymo#include <chromeos/message_loops/base_message_loop.h>
291023a6029771fb8dea867e14193df8e58a59a662Darin Petkov#include <metrics/metrics_library.h>
304dc2ada660d3f7cd50d624b6bf102d806cf8997fChris Masone#include <sys/stat.h>
3144666f97392f1f0f8be292fe6a4edcf9237540dfAlex Deymo#include <sys/types.h>
329d65b7b9249124a433b9a018a1952435f7f75c4dDarin Petkov
33b7ca096f98a43ebbf412f1b2d3d15bb184f871f8Alex Deymo#include "update_engine/daemon.h"
349c0baf82049efd95230a8389769e1b3e5d001209Darin Petkov#include "update_engine/terminator.h"
3544cab30e0ee04b277e8463785ab069e9885a9f2dAlex Vakulenko#include "update_engine/utils.h"
364e9b9f4d57a0c95fb1b9281077f0eef5fdf5e345Andrew de los Reyes
374fe15d017c145aca449c2248420c1b4ec8c23758Andrew de los Reyesusing std::string;
3867363ee8c3c542e8799983cc4dd375b77e8252e9Alex Deymo
394fe15d017c145aca449c2248420c1b4ec8c23758Andrew de los Reyesnamespace chromeos_update_engine {
4073520670492f3358c496698767879adcf6c03aeaAndrew de los Reyesnamespace {
4173520670492f3358c496698767879adcf6c03aeaAndrew de los Reyes
4230291edee8e2f7646b540b00672c81b442386ed6Darin Petkovvoid SetupLogSymlink(const string& symlink_path, const string& log_path) {
4330291edee8e2f7646b540b00672c81b442386ed6Darin Petkov  // TODO(petkov): To ensure a smooth transition between non-timestamped and
4430291edee8e2f7646b540b00672c81b442386ed6Darin Petkov  // timestamped logs, move an existing log to start the first timestamped
4530291edee8e2f7646b540b00672c81b442386ed6Darin Petkov  // one. This code can go away once all clients are switched to this version or
4630291edee8e2f7646b540b00672c81b442386ed6Darin Petkov  // we stop caring about the old-style logs.
4730291edee8e2f7646b540b00672c81b442386ed6Darin Petkov  if (utils::FileExists(symlink_path.c_str()) &&
4830291edee8e2f7646b540b00672c81b442386ed6Darin Petkov      !utils::IsSymlink(symlink_path.c_str())) {
4975039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko    base::ReplaceFile(base::FilePath(symlink_path),
5075039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko                      base::FilePath(log_path),
5175039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko                      nullptr);
5230291edee8e2f7646b540b00672c81b442386ed6Darin Petkov  }
5375039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko  base::DeleteFile(base::FilePath(symlink_path), true);
5430291edee8e2f7646b540b00672c81b442386ed6Darin Petkov  if (symlink(log_path.c_str(), symlink_path.c_str()) == -1) {
5530291edee8e2f7646b540b00672c81b442386ed6Darin Petkov    PLOG(ERROR) << "Unable to create symlink " << symlink_path
5630291edee8e2f7646b540b00672c81b442386ed6Darin Petkov                << " pointing at " << log_path;
5730291edee8e2f7646b540b00672c81b442386ed6Darin Petkov  }
5830291edee8e2f7646b540b00672c81b442386ed6Darin Petkov}
5973520670492f3358c496698767879adcf6c03aeaAndrew de los Reyes
6030291edee8e2f7646b540b00672c81b442386ed6Darin Petkovstring GetTimeAsString(time_t utime) {
6130291edee8e2f7646b540b00672c81b442386ed6Darin Petkov  struct tm tm;
62d2779df63aaad8b65fc5d4badee7dbc9bed7f2b6Alex Vakulenko  CHECK_EQ(localtime_r(&utime, &tm), &tm);
6330291edee8e2f7646b540b00672c81b442386ed6Darin Petkov  char str[16];
64d2779df63aaad8b65fc5d4badee7dbc9bed7f2b6Alex Vakulenko  CHECK_EQ(strftime(str, sizeof(str), "%Y%m%d-%H%M%S", &tm), 15u);
6530291edee8e2f7646b540b00672c81b442386ed6Darin Petkov  return str;
6630291edee8e2f7646b540b00672c81b442386ed6Darin Petkov}
6749fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
6830291edee8e2f7646b540b00672c81b442386ed6Darin Petkovstring SetupLogFile(const string& kLogsRoot) {
6930291edee8e2f7646b540b00672c81b442386ed6Darin Petkov  const string kLogSymlink = kLogsRoot + "/update_engine.log";
7030291edee8e2f7646b540b00672c81b442386ed6Darin Petkov  const string kLogsDir = kLogsRoot + "/update_engine";
7130291edee8e2f7646b540b00672c81b442386ed6Darin Petkov  const string kLogPath =
7275039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko      base::StringPrintf("%s/update_engine.%s",
7375039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko                         kLogsDir.c_str(),
7475039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko                         GetTimeAsString(::time(nullptr)).c_str());
7530291edee8e2f7646b540b00672c81b442386ed6Darin Petkov  mkdir(kLogsDir.c_str(), 0755);
7630291edee8e2f7646b540b00672c81b442386ed6Darin Petkov  SetupLogSymlink(kLogSymlink, kLogPath);
7730291edee8e2f7646b540b00672c81b442386ed6Darin Petkov  return kLogSymlink;
7830291edee8e2f7646b540b00672c81b442386ed6Darin Petkov}
7930291edee8e2f7646b540b00672c81b442386ed6Darin Petkov
80d570820920e030fefd9644fb5427b538160af1a1Steve Fungvoid SetupLogging(bool log_to_std_err) {
81d603ba9ff52c72a68556495245e1069c991866d4Alex Deymo  string log_file;
8275039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko  logging::LoggingSettings log_settings;
8375039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko  log_settings.lock_log = logging::DONT_LOCK_LOG_FILE;
8475039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko  log_settings.delete_old = logging::APPEND_TO_OLD_LOG_FILE;
8575039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko
86d570820920e030fefd9644fb5427b538160af1a1Steve Fung  if (log_to_std_err) {
8775039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko    // Log to stderr initially.
8875039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko    log_settings.log_file = nullptr;
8975039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko    log_settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
9075039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko  } else {
91d603ba9ff52c72a68556495245e1069c991866d4Alex Deymo    log_file = SetupLogFile("/var/log");
9275039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko    log_settings.log_file = log_file.c_str();
9375039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko    log_settings.logging_dest = logging::LOG_TO_FILE;
9430291edee8e2f7646b540b00672c81b442386ed6Darin Petkov  }
9575039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko
9675039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko  logging::InitLogging(log_settings);
9730291edee8e2f7646b540b00672c81b442386ed6Darin Petkov}
98000d895da247697f4e4e0c67a3a847f71fca8eb9Andrew de los Reyes
99d2779df63aaad8b65fc5d4badee7dbc9bed7f2b6Alex Vakulenko}  // namespace
10030291edee8e2f7646b540b00672c81b442386ed6Darin Petkov}  // namespace chromeos_update_engine
10149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
10249fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.comint main(int argc, char** argv) {
103d570820920e030fefd9644fb5427b538160af1a1Steve Fung  DEFINE_bool(logtostderr, false,
104d570820920e030fefd9644fb5427b538160af1a1Steve Fung              "Write logs to stderr instead of to a file in log_dir.");
105d570820920e030fefd9644fb5427b538160af1a1Steve Fung  DEFINE_bool(foreground, false,
106d570820920e030fefd9644fb5427b538160af1a1Steve Fung              "Don't daemon()ize; run in foreground.");
107d570820920e030fefd9644fb5427b538160af1a1Steve Fung
1089c0baf82049efd95230a8389769e1b3e5d001209Darin Petkov  chromeos_update_engine::Terminator::Init();
109d570820920e030fefd9644fb5427b538160af1a1Steve Fung  chromeos::FlagHelper::Init(argc, argv, "Chromium OS Update Engine");
110d570820920e030fefd9644fb5427b538160af1a1Steve Fung  chromeos_update_engine::SetupLogging(FLAGS_logtostderr);
1116b78e29f80e98c4ad009c830012682220dc9de3bAndrew de los Reyes  if (!FLAGS_foreground)
1126b78e29f80e98c4ad009c830012682220dc9de3bAndrew de los Reyes    PLOG_IF(FATAL, daemon(0, 0) == 1) << "daemon() failed";
1136b78e29f80e98c4ad009c830012682220dc9de3bAndrew de los Reyes
1144fe15d017c145aca449c2248420c1b4ec8c23758Andrew de los Reyes  LOG(INFO) << "Chrome OS Update Engine starting";
115a4a8a8ccc2d9e0285728ed247b43f09433e63323Darin Petkov
1164dc2ada660d3f7cd50d624b6bf102d806cf8997fChris Masone  // Ensure that all written files have safe permissions.
1174dc2ada660d3f7cd50d624b6bf102d806cf8997fChris Masone  // This is a mask, so we _block_ execute for the owner, and ALL
1184dc2ada660d3f7cd50d624b6bf102d806cf8997fChris Masone  // permissions for other users.
1194dc2ada660d3f7cd50d624b6bf102d806cf8997fChris Masone  // Done _after_ log file creation.
1204dc2ada660d3f7cd50d624b6bf102d806cf8997fChris Masone  umask(S_IXUSR | S_IRWXG | S_IRWXO);
1214dc2ada660d3f7cd50d624b6bf102d806cf8997fChris Masone
122b7ca096f98a43ebbf412f1b2d3d15bb184f871f8Alex Deymo  chromeos_update_engine::UpdateEngineDaemon update_engine_daemon;
123b7ca096f98a43ebbf412f1b2d3d15bb184f871f8Alex Deymo  int exit_code = update_engine_daemon.Run();
1244fe15d017c145aca449c2248420c1b4ec8c23758Andrew de los Reyes
125b7ca096f98a43ebbf412f1b2d3d15bb184f871f8Alex Deymo  LOG(INFO) << "Chrome OS Update Engine terminating with exit code "
126b7ca096f98a43ebbf412f1b2d3d15bb184f871f8Alex Deymo            << exit_code;
127b7ca096f98a43ebbf412f1b2d3d15bb184f871f8Alex Deymo  return exit_code;
12849fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com}
129