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