| Mike Frysinger | 8155d08 | 2012-04-06 15:23:18 -0400 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium OS Authors. All rights reserved. | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be | 
|  | 3 | // found in the LICENSE file. | 
|  | 4 |  | 
| Andrew de los Reyes | 4fe15d0 | 2009-12-10 19:01:36 -0800 | [diff] [blame] | 5 | #include <string> | 
| Andrew de los Reyes | 4fe15d0 | 2009-12-10 19:01:36 -0800 | [diff] [blame] | 6 | #include <vector> | 
| Darin Petkov | 9d65b7b | 2010-07-20 09:13:01 -0700 | [diff] [blame] | 7 |  | 
| Darin Petkov | 1023a60 | 2010-08-30 13:47:51 -0700 | [diff] [blame] | 8 | #include <base/at_exit.h> | 
|  | 9 | #include <base/command_line.h> | 
| Darin Petkov | 30291ed | 2010-11-12 10:23:06 -0800 | [diff] [blame] | 10 | #include <base/file_util.h> | 
| Darin Petkov | 1023a60 | 2010-08-30 13:47:51 -0700 | [diff] [blame] | 11 | #include <base/logging.h> | 
|  | 12 | #include <base/string_util.h> | 
| Mike Frysinger | 8155d08 | 2012-04-06 15:23:18 -0400 | [diff] [blame] | 13 | #include <base/stringprintf.h> | 
| Andrew de los Reyes | 4fe15d0 | 2009-12-10 19:01:36 -0800 | [diff] [blame] | 14 | #include <gflags/gflags.h> | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 15 | #include <glib.h> | 
| Darin Petkov | 1023a60 | 2010-08-30 13:47:51 -0700 | [diff] [blame] | 16 | #include <metrics/metrics_library.h> | 
| Chris Masone | 4dc2ada | 2010-09-23 12:43:03 -0700 | [diff] [blame] | 17 | #include <sys/types.h> | 
|  | 18 | #include <sys/stat.h> | 
| Darin Petkov | 9d65b7b | 2010-07-20 09:13:01 -0700 | [diff] [blame] | 19 |  | 
| Bruno Rocha | 7f9aea2 | 2011-09-12 14:31:24 -0700 | [diff] [blame] | 20 | #include "update_engine/certificate_checker.h" | 
| Andrew de los Reyes | 4e9b9f4 | 2010-04-26 15:06:43 -0700 | [diff] [blame] | 21 | #include "update_engine/dbus_constants.h" | 
| Andrew de los Reyes | 4516810 | 2010-11-22 11:13:50 -0800 | [diff] [blame] | 22 | #include "update_engine/dbus_interface.h" | 
| Andrew de los Reyes | 4e9b9f4 | 2010-04-26 15:06:43 -0700 | [diff] [blame] | 23 | #include "update_engine/dbus_service.h" | 
| Jay Srinivasan | 55f50c2 | 2013-01-10 19:24:35 -0800 | [diff] [blame] | 24 | #include "update_engine/real_system_state.h" | 
| Andrew de los Reyes | 3d6a209 | 2010-08-23 18:23:26 -0700 | [diff] [blame] | 25 | #include "update_engine/subprocess.h" | 
| Darin Petkov | 9c0baf8 | 2010-10-07 13:44:48 -0700 | [diff] [blame] | 26 | #include "update_engine/terminator.h" | 
| Andrew de los Reyes | 4e9b9f4 | 2010-04-26 15:06:43 -0700 | [diff] [blame] | 27 | #include "update_engine/update_attempter.h" | 
| Darin Petkov | 1023a60 | 2010-08-30 13:47:51 -0700 | [diff] [blame] | 28 | #include "update_engine/update_check_scheduler.h" | 
| Jay Srinivasan | 08fce04 | 2012-06-07 16:31:01 -0700 | [diff] [blame] | 29 | #include "update_engine/utils.h" | 
| Andrew de los Reyes | 4e9b9f4 | 2010-04-26 15:06:43 -0700 | [diff] [blame] | 30 |  | 
|  | 31 | extern "C" { | 
|  | 32 | #include "update_engine/update_engine.dbusserver.h" | 
|  | 33 | } | 
|  | 34 |  | 
|  | 35 | DEFINE_bool(logtostderr, false, | 
|  | 36 | "Write logs to stderr instead of to a file in log_dir."); | 
| Andrew de los Reyes | 6b78e29 | 2010-05-10 15:54:39 -0700 | [diff] [blame] | 37 | DEFINE_bool(foreground, false, | 
|  | 38 | "Don't daemon()ize; run in foreground."); | 
| Andrew de los Reyes | 4fe15d0 | 2009-12-10 19:01:36 -0800 | [diff] [blame] | 39 |  | 
|  | 40 | using std::string; | 
| Andrew de los Reyes | 4fe15d0 | 2009-12-10 19:01:36 -0800 | [diff] [blame] | 41 | using std::vector; | 
|  | 42 |  | 
|  | 43 | namespace chromeos_update_engine { | 
|  | 44 |  | 
| Andrew de los Reyes | 3d6a209 | 2010-08-23 18:23:26 -0700 | [diff] [blame] | 45 | gboolean UpdateBootFlags(void* arg) { | 
| Darin Petkov | 61635a9 | 2011-05-18 16:20:36 -0700 | [diff] [blame] | 46 | reinterpret_cast<UpdateAttempter*>(arg)->UpdateBootFlags(); | 
|  | 47 | return FALSE;  // Don't call this callback again | 
|  | 48 | } | 
|  | 49 |  | 
|  | 50 | gboolean BroadcastStatus(void* arg) { | 
|  | 51 | reinterpret_cast<UpdateAttempter*>(arg)->BroadcastStatus(); | 
| Andrew de los Reyes | 3d6a209 | 2010-08-23 18:23:26 -0700 | [diff] [blame] | 52 | return FALSE;  // Don't call this callback again | 
|  | 53 | } | 
|  | 54 |  | 
| David Zeuthen | e4c58bf | 2013-06-18 17:26:50 -0700 | [diff] [blame] | 55 | gboolean UpdateEngineStarted(gpointer user_data) { | 
|  | 56 | reinterpret_cast<UpdateAttempter*>(user_data)->UpdateEngineStarted(); | 
|  | 57 | return FALSE; // Remove idle source (e.g. don't do the callback again) | 
|  | 58 | } | 
|  | 59 |  | 
| Andrew de los Reyes | 7352067 | 2010-05-10 13:44:58 -0700 | [diff] [blame] | 60 | namespace { | 
|  | 61 |  | 
| Andrew de los Reyes | 4e9b9f4 | 2010-04-26 15:06:43 -0700 | [diff] [blame] | 62 | void SetupDbusService(UpdateEngineService* service) { | 
|  | 63 | DBusGConnection *bus; | 
|  | 64 | DBusGProxy *proxy; | 
|  | 65 | GError *error = NULL; | 
|  | 66 |  | 
|  | 67 | bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error); | 
| Darin Petkov | a0b9e77 | 2011-10-06 05:05:56 -0700 | [diff] [blame] | 68 | LOG_IF(FATAL, !bus) << "Failed to get bus: " | 
|  | 69 | << utils::GetAndFreeGError(&error); | 
| Andrew de los Reyes | 4e9b9f4 | 2010-04-26 15:06:43 -0700 | [diff] [blame] | 70 | proxy = dbus_g_proxy_new_for_name(bus, | 
|  | 71 | DBUS_SERVICE_DBUS, | 
|  | 72 | DBUS_PATH_DBUS, | 
|  | 73 | DBUS_INTERFACE_DBUS); | 
| Andrew de los Reyes | 4e9b9f4 | 2010-04-26 15:06:43 -0700 | [diff] [blame] | 74 | guint32 request_name_ret; | 
|  | 75 | if (!org_freedesktop_DBus_request_name(proxy, | 
|  | 76 | kUpdateEngineServiceName, | 
|  | 77 | 0, | 
|  | 78 | &request_name_ret, | 
|  | 79 | &error)) { | 
| Darin Petkov | a0b9e77 | 2011-10-06 05:05:56 -0700 | [diff] [blame] | 80 | LOG(FATAL) << "Failed to get name: " << utils::GetAndFreeGError(&error); | 
| Andrew de los Reyes | 4e9b9f4 | 2010-04-26 15:06:43 -0700 | [diff] [blame] | 81 | } | 
|  | 82 | if (request_name_ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { | 
|  | 83 | g_warning("Got result code %u from requesting name", request_name_ret); | 
| Andrew de los Reyes | 4e9b9f4 | 2010-04-26 15:06:43 -0700 | [diff] [blame] | 84 | LOG(FATAL) << "Got result code " << request_name_ret | 
|  | 85 | << " from requesting name, but expected " | 
|  | 86 | << DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER; | 
|  | 87 | } | 
|  | 88 | dbus_g_connection_register_g_object(bus, | 
|  | 89 | "/org/chromium/UpdateEngine", | 
|  | 90 | G_OBJECT(service)); | 
|  | 91 | } | 
|  | 92 |  | 
| Darin Petkov | 30291ed | 2010-11-12 10:23:06 -0800 | [diff] [blame] | 93 | void SetupLogSymlink(const string& symlink_path, const string& log_path) { | 
|  | 94 | // TODO(petkov): To ensure a smooth transition between non-timestamped and | 
|  | 95 | // timestamped logs, move an existing log to start the first timestamped | 
|  | 96 | // one. This code can go away once all clients are switched to this version or | 
|  | 97 | // we stop caring about the old-style logs. | 
|  | 98 | if (utils::FileExists(symlink_path.c_str()) && | 
|  | 99 | !utils::IsSymlink(symlink_path.c_str())) { | 
|  | 100 | file_util::ReplaceFile(FilePath(symlink_path), FilePath(log_path)); | 
|  | 101 | } | 
|  | 102 | file_util::Delete(FilePath(symlink_path), true); | 
|  | 103 | if (symlink(log_path.c_str(), symlink_path.c_str()) == -1) { | 
|  | 104 | PLOG(ERROR) << "Unable to create symlink " << symlink_path | 
|  | 105 | << " pointing at " << log_path; | 
|  | 106 | } | 
|  | 107 | } | 
|  | 108 |  | 
|  | 109 | string GetTimeAsString(time_t utime) { | 
|  | 110 | struct tm tm; | 
|  | 111 | CHECK(localtime_r(&utime, &tm) == &tm); | 
|  | 112 | char str[16]; | 
|  | 113 | CHECK(strftime(str, sizeof(str), "%Y%m%d-%H%M%S", &tm) == 15); | 
|  | 114 | return str; | 
|  | 115 | } | 
|  | 116 |  | 
|  | 117 | string SetupLogFile(const string& kLogsRoot) { | 
|  | 118 | const string kLogSymlink = kLogsRoot + "/update_engine.log"; | 
|  | 119 | const string kLogsDir = kLogsRoot + "/update_engine"; | 
|  | 120 | const string kLogPath = | 
|  | 121 | StringPrintf("%s/update_engine.%s", | 
|  | 122 | kLogsDir.c_str(), | 
|  | 123 | GetTimeAsString(::time(NULL)).c_str()); | 
|  | 124 | mkdir(kLogsDir.c_str(), 0755); | 
|  | 125 | SetupLogSymlink(kLogSymlink, kLogPath); | 
|  | 126 | return kLogSymlink; | 
|  | 127 | } | 
|  | 128 |  | 
|  | 129 | void SetupLogging() { | 
|  | 130 | // Log to stderr initially. | 
|  | 131 | logging::InitLogging(NULL, | 
|  | 132 | logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG, | 
|  | 133 | logging::DONT_LOCK_LOG_FILE, | 
| Chris Masone | d903c3b | 2011-05-12 15:35:46 -0700 | [diff] [blame] | 134 | logging::APPEND_TO_OLD_LOG_FILE, | 
|  | 135 | logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS); | 
| Darin Petkov | 30291ed | 2010-11-12 10:23:06 -0800 | [diff] [blame] | 136 | if (FLAGS_logtostderr) { | 
|  | 137 | return; | 
|  | 138 | } | 
|  | 139 | const string log_file = SetupLogFile("/var/log"); | 
|  | 140 | logging::InitLogging(log_file.c_str(), | 
|  | 141 | logging::LOG_ONLY_TO_FILE, | 
|  | 142 | logging::DONT_LOCK_LOG_FILE, | 
| Chris Masone | d903c3b | 2011-05-12 15:35:46 -0700 | [diff] [blame] | 143 | logging::APPEND_TO_OLD_LOG_FILE, | 
|  | 144 | logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS); | 
| Darin Petkov | 30291ed | 2010-11-12 10:23:06 -0800 | [diff] [blame] | 145 | } | 
| Andrew de los Reyes | 000d895 | 2011-03-02 15:21:14 -0800 | [diff] [blame] | 146 |  | 
| Andrew de los Reyes | 7352067 | 2010-05-10 13:44:58 -0700 | [diff] [blame] | 147 | }  // namespace {} | 
| Andrew de los Reyes | 4fe15d0 | 2009-12-10 19:01:36 -0800 | [diff] [blame] | 148 | }  // namespace chromeos_update_engine | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 149 |  | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 150 | int main(int argc, char** argv) { | 
| Andrew de los Reyes | 4e9b9f4 | 2010-04-26 15:06:43 -0700 | [diff] [blame] | 151 | ::g_type_init(); | 
| Ben Chan | 46bf5c8 | 2013-06-24 11:17:41 -0700 | [diff] [blame] | 152 | dbus_threads_init_default(); | 
| Darin Petkov | 5c0a8af | 2010-08-24 13:39:13 -0700 | [diff] [blame] | 153 | base::AtExitManager exit_manager;  // Required for base/rand_util.h. | 
| Darin Petkov | 9c0baf8 | 2010-10-07 13:44:48 -0700 | [diff] [blame] | 154 | chromeos_update_engine::Terminator::Init(); | 
| adlr@google.com | c98a7ed | 2009-12-04 18:54:03 +0000 | [diff] [blame] | 155 | chromeos_update_engine::Subprocess::Init(); | 
| Andrew de los Reyes | 4fe15d0 | 2009-12-10 19:01:36 -0800 | [diff] [blame] | 156 | google::ParseCommandLineFlags(&argc, &argv, true); | 
| Andrew de los Reyes | 4e9b9f4 | 2010-04-26 15:06:43 -0700 | [diff] [blame] | 157 | CommandLine::Init(argc, argv); | 
| Darin Petkov | 30291ed | 2010-11-12 10:23:06 -0800 | [diff] [blame] | 158 | chromeos_update_engine::SetupLogging(); | 
| Andrew de los Reyes | 6b78e29 | 2010-05-10 15:54:39 -0700 | [diff] [blame] | 159 | if (!FLAGS_foreground) | 
|  | 160 | PLOG_IF(FATAL, daemon(0, 0) == 1) << "daemon() failed"; | 
|  | 161 |  | 
| Andrew de los Reyes | 4fe15d0 | 2009-12-10 19:01:36 -0800 | [diff] [blame] | 162 | LOG(INFO) << "Chrome OS Update Engine starting"; | 
| Darin Petkov | a4a8a8c | 2010-07-15 22:21:12 -0700 | [diff] [blame] | 163 |  | 
| Chris Masone | 4dc2ada | 2010-09-23 12:43:03 -0700 | [diff] [blame] | 164 | // Ensure that all written files have safe permissions. | 
|  | 165 | // This is a mask, so we _block_ execute for the owner, and ALL | 
|  | 166 | // permissions for other users. | 
|  | 167 | // Done _after_ log file creation. | 
|  | 168 | umask(S_IXUSR | S_IRWXG | S_IRWXO); | 
|  | 169 |  | 
| Andrew de los Reyes | 4fe15d0 | 2009-12-10 19:01:36 -0800 | [diff] [blame] | 170 | // Create the single GMainLoop | 
| Andrew de los Reyes | 63b96d7 | 2010-05-10 13:08:54 -0700 | [diff] [blame] | 171 | GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE); | 
| Andrew de los Reyes | 4fe15d0 | 2009-12-10 19:01:36 -0800 | [diff] [blame] | 172 |  | 
| Jay Srinivasan | f057205 | 2012-10-23 18:12:56 -0700 | [diff] [blame] | 173 | chromeos_update_engine::RealSystemState real_system_state; | 
| Gilad Arnold | bf7919b | 2013-01-08 13:07:37 -0800 | [diff] [blame] | 174 | // TODO(garnold) s/false/true/ once we decide to activate actual GPIO-based | 
|  | 175 | // protocol for testing of MP-signed images (chromium-os:25400). | 
|  | 176 | LOG_IF(ERROR, !real_system_state.Initialize(false)) | 
| Jay Srinivasan | 6f6ea00 | 2012-12-14 11:26:28 -0800 | [diff] [blame] | 177 | << "Failed to initialize system state."; | 
| Jay Srinivasan | 55f50c2 | 2013-01-10 19:24:35 -0800 | [diff] [blame] | 178 | chromeos_update_engine::UpdateAttempter *update_attempter = | 
|  | 179 | real_system_state.update_attempter(); | 
|  | 180 | CHECK(update_attempter); | 
| Darin Petkov | 9d65b7b | 2010-07-20 09:13:01 -0700 | [diff] [blame] | 181 |  | 
| Bruno Rocha | 7f9aea2 | 2011-09-12 14:31:24 -0700 | [diff] [blame] | 182 | // Sets static members for the certificate checker. | 
| Jay Srinivasan | 6f6ea00 | 2012-12-14 11:26:28 -0800 | [diff] [blame] | 183 | chromeos_update_engine::CertificateChecker::set_system_state( | 
|  | 184 | &real_system_state); | 
| Bruno Rocha | 7f9aea2 | 2011-09-12 14:31:24 -0700 | [diff] [blame] | 185 | chromeos_update_engine::OpenSSLWrapper openssl_wrapper; | 
|  | 186 | chromeos_update_engine::CertificateChecker::set_openssl_wrapper( | 
|  | 187 | &openssl_wrapper); | 
|  | 188 |  | 
| Andrew de los Reyes | 4e9b9f4 | 2010-04-26 15:06:43 -0700 | [diff] [blame] | 189 | // Create the dbus service object: | 
|  | 190 | dbus_g_object_type_install_info(UPDATE_ENGINE_TYPE_SERVICE, | 
|  | 191 | &dbus_glib_update_engine_service_object_info); | 
|  | 192 | UpdateEngineService* service = | 
|  | 193 | UPDATE_ENGINE_SERVICE(g_object_new(UPDATE_ENGINE_TYPE_SERVICE, NULL)); | 
| Jay Srinivasan | ae4697c | 2013-03-18 17:08:08 -0700 | [diff] [blame] | 194 | service->system_state_ = &real_system_state; | 
| Jay Srinivasan | 55f50c2 | 2013-01-10 19:24:35 -0800 | [diff] [blame] | 195 | update_attempter->set_dbus_service(service); | 
| Andrew de los Reyes | 4e9b9f4 | 2010-04-26 15:06:43 -0700 | [diff] [blame] | 196 | chromeos_update_engine::SetupDbusService(service); | 
| Andrew de los Reyes | 4fe15d0 | 2009-12-10 19:01:36 -0800 | [diff] [blame] | 197 |  | 
| Darin Petkov | 1023a60 | 2010-08-30 13:47:51 -0700 | [diff] [blame] | 198 | // Schedule periodic update checks. | 
| Jay Srinivasan | 55f50c2 | 2013-01-10 19:24:35 -0800 | [diff] [blame] | 199 | chromeos_update_engine::UpdateCheckScheduler scheduler(update_attempter, | 
| Jay Srinivasan | 08fce04 | 2012-06-07 16:31:01 -0700 | [diff] [blame] | 200 | &real_system_state); | 
| Darin Petkov | 1023a60 | 2010-08-30 13:47:51 -0700 | [diff] [blame] | 201 | scheduler.Run(); | 
| Andrew de los Reyes | 7352067 | 2010-05-10 13:44:58 -0700 | [diff] [blame] | 202 |  | 
| Darin Petkov | eee26ee | 2010-10-22 11:05:46 -0700 | [diff] [blame] | 203 | // Update boot flags after 45 seconds. | 
|  | 204 | g_timeout_add_seconds(45, | 
|  | 205 | &chromeos_update_engine::UpdateBootFlags, | 
| Jay Srinivasan | 55f50c2 | 2013-01-10 19:24:35 -0800 | [diff] [blame] | 206 | update_attempter); | 
| Andrew de los Reyes | 3d6a209 | 2010-08-23 18:23:26 -0700 | [diff] [blame] | 207 |  | 
| Darin Petkov | 61635a9 | 2011-05-18 16:20:36 -0700 | [diff] [blame] | 208 | // Broadcast the update engine status on startup to ensure consistent system | 
|  | 209 | // state on crashes. | 
| Jay Srinivasan | 55f50c2 | 2013-01-10 19:24:35 -0800 | [diff] [blame] | 210 | g_idle_add(&chromeos_update_engine::BroadcastStatus, update_attempter); | 
| Darin Petkov | 61635a9 | 2011-05-18 16:20:36 -0700 | [diff] [blame] | 211 |  | 
| David Zeuthen | e4c58bf | 2013-06-18 17:26:50 -0700 | [diff] [blame] | 212 | // Run the UpdateEngineStarted() method on |update_attempter|. | 
|  | 213 | g_idle_add(&chromeos_update_engine::UpdateEngineStarted, update_attempter); | 
|  | 214 |  | 
| Andrew de los Reyes | 4e9b9f4 | 2010-04-26 15:06:43 -0700 | [diff] [blame] | 215 | // Run the main loop until exit time: | 
| Andrew de los Reyes | 4fe15d0 | 2009-12-10 19:01:36 -0800 | [diff] [blame] | 216 | g_main_loop_run(loop); | 
| Andrew de los Reyes | 4e9b9f4 | 2010-04-26 15:06:43 -0700 | [diff] [blame] | 217 |  | 
|  | 218 | // Cleanup: | 
| Andrew de los Reyes | 4fe15d0 | 2009-12-10 19:01:36 -0800 | [diff] [blame] | 219 | g_main_loop_unref(loop); | 
| Jay Srinivasan | 55f50c2 | 2013-01-10 19:24:35 -0800 | [diff] [blame] | 220 | update_attempter->set_dbus_service(NULL); | 
| Andrew de los Reyes | 4e9b9f4 | 2010-04-26 15:06:43 -0700 | [diff] [blame] | 221 | g_object_unref(G_OBJECT(service)); | 
| Andrew de los Reyes | 4fe15d0 | 2009-12-10 19:01:36 -0800 | [diff] [blame] | 222 |  | 
|  | 223 | LOG(INFO) << "Chrome OS Update Engine terminating"; | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 224 | return 0; | 
|  | 225 | } |