| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <string> | 5 #include <string> |
| 6 | 6 |
| 7 #include <gflags/gflags.h> | 7 #include <gflags/gflags.h> |
| 8 #include <glib.h> | 8 #include <glib.h> |
| 9 | 9 |
| 10 #include "update_engine/marshal.glibmarshal.h" | 10 #include "update_engine/marshal.glibmarshal.h" |
| 11 #include "update_engine/dbus_constants.h" | 11 #include "update_engine/dbus_constants.h" |
| 12 #include "update_engine/subprocess.h" | 12 #include "update_engine/subprocess.h" |
| 13 #include "update_engine/utils.h" | 13 #include "update_engine/utils.h" |
| 14 | 14 |
| 15 extern "C" { | 15 extern "C" { |
| 16 #include "update_engine/update_engine.dbusclient.h" | 16 #include "update_engine/update_engine.dbusclient.h" |
| 17 } | 17 } |
| 18 | 18 |
| 19 using chromeos_update_engine::kUpdateEngineServiceName; | 19 using chromeos_update_engine::kUpdateEngineServiceName; |
| 20 using chromeos_update_engine::kUpdateEngineServicePath; | 20 using chromeos_update_engine::kUpdateEngineServicePath; |
| 21 using chromeos_update_engine::kUpdateEngineServiceInterface; | 21 using chromeos_update_engine::kUpdateEngineServiceInterface; |
| 22 using chromeos_update_engine::utils::GetGErrorMessage; | 22 using chromeos_update_engine::utils::GetGErrorMessage; |
| 23 using std::string; | 23 using std::string; |
| 24 | 24 |
| 25 DEFINE_string(app_version, "", "Force the current app version."); | 25 DEFINE_string(app_version, "", "Force the current app version."); |
| 26 DEFINE_bool(check_for_update, false, "Initiate check for updates."); | 26 DEFINE_bool(check_for_update, false, "Initiate check for updates."); |
| 27 DEFINE_bool(force_update, false, | |
| 28 "Force an update, even over an expensive network."); | |
| 29 DEFINE_string(omaha_url, "", "The URL of the Omaha update server."); | 27 DEFINE_string(omaha_url, "", "The URL of the Omaha update server."); |
| 30 DEFINE_bool(reboot, false, "Initiate a reboot if needed."); | 28 DEFINE_bool(reboot, false, "Initiate a reboot if needed."); |
| 31 DEFINE_bool(status, false, "Print the status to stdout."); | 29 DEFINE_bool(status, false, "Print the status to stdout."); |
| 30 DEFINE_bool(update, false, "Forces an update and waits for its completion. " |
| 31 "Exit status is 0 if the update succeeded, and 1 otherwise."); |
| 32 DEFINE_bool(watch_for_updates, false, | 32 DEFINE_bool(watch_for_updates, false, |
| 33 "Listen for status updates and print them to the screen."); | 33 "Listen for status updates and print them to the screen."); |
| 34 | 34 |
| 35 namespace { | 35 namespace { |
| 36 | 36 |
| 37 bool GetProxy(DBusGProxy** out_proxy) { | 37 bool GetProxy(DBusGProxy** out_proxy) { |
| 38 DBusGConnection* bus; | 38 DBusGConnection* bus; |
| 39 DBusGProxy* proxy; | 39 DBusGProxy* proxy; |
| 40 GError* error = NULL; | 40 GError* error = NULL; |
| 41 | 41 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 63 int64_t new_size, | 63 int64_t new_size, |
| 64 void* user_data) { | 64 void* user_data) { |
| 65 LOG(INFO) << "Got status update:"; | 65 LOG(INFO) << "Got status update:"; |
| 66 LOG(INFO) << " last_checked_time: " << last_checked_time; | 66 LOG(INFO) << " last_checked_time: " << last_checked_time; |
| 67 LOG(INFO) << " progress: " << progress; | 67 LOG(INFO) << " progress: " << progress; |
| 68 LOG(INFO) << " current_operation: " << current_operation; | 68 LOG(INFO) << " current_operation: " << current_operation; |
| 69 LOG(INFO) << " new_version: " << new_version; | 69 LOG(INFO) << " new_version: " << new_version; |
| 70 LOG(INFO) << " new_size: " << new_size; | 70 LOG(INFO) << " new_size: " << new_size; |
| 71 } | 71 } |
| 72 | 72 |
| 73 bool GetStatus() { | 73 // If |op| is non-NULL, sets it to the current operation string or an |
| 74 // empty string if unable to obtain the current status. |
| 75 bool GetStatus(string* op) { |
| 74 DBusGProxy* proxy; | 76 DBusGProxy* proxy; |
| 75 GError* error = NULL; | 77 GError* error = NULL; |
| 76 | 78 |
| 77 CHECK(GetProxy(&proxy)); | 79 CHECK(GetProxy(&proxy)); |
| 78 | 80 |
| 79 gint64 last_checked_time = 0; | 81 gint64 last_checked_time = 0; |
| 80 gdouble progress = 0.0; | 82 gdouble progress = 0.0; |
| 81 char* current_op = NULL; | 83 char* current_op = NULL; |
| 82 char* new_version = NULL; | 84 char* new_version = NULL; |
| 83 gint64 new_size = 0; | 85 gint64 new_size = 0; |
| 84 | 86 |
| 85 gboolean rc = org_chromium_UpdateEngineInterface_get_status( | 87 gboolean rc = org_chromium_UpdateEngineInterface_get_status( |
| 86 proxy, | 88 proxy, |
| 87 &last_checked_time, | 89 &last_checked_time, |
| 88 &progress, | 90 &progress, |
| 89 ¤t_op, | 91 ¤t_op, |
| 90 &new_version, | 92 &new_version, |
| 91 &new_size, | 93 &new_size, |
| 92 &error); | 94 &error); |
| 93 if (rc == FALSE) { | 95 if (rc == FALSE) { |
| 94 LOG(INFO) << "Error getting status: " << GetGErrorMessage(error); | 96 LOG(INFO) << "Error getting status: " << GetGErrorMessage(error); |
| 95 } | 97 } |
| 96 printf("LAST_CHECKED_TIME=%" PRIi64 "\nPROGRESS=%f\nCURRENT_OP=%s\n" | 98 printf("LAST_CHECKED_TIME=%" PRIi64 "\nPROGRESS=%f\nCURRENT_OP=%s\n" |
| 97 "NEW_VERSION=%s\nNEW_SIZE=%" PRIi64 "\n", | 99 "NEW_VERSION=%s\nNEW_SIZE=%" PRIi64 "\n", |
| 98 last_checked_time, | 100 last_checked_time, |
| 99 progress, | 101 progress, |
| 100 current_op, | 102 current_op, |
| 101 new_version, | 103 new_version, |
| 102 new_size); | 104 new_size); |
| 105 if (op) { |
| 106 *op = current_op ? current_op : ""; |
| 107 } |
| 103 return true; | 108 return true; |
| 104 } | 109 } |
| 105 | 110 |
| 106 // Should never return. | 111 // Should never return. |
| 107 void WatchForUpdates() { | 112 void WatchForUpdates() { |
| 108 DBusGProxy* proxy; | 113 DBusGProxy* proxy; |
| 109 | 114 |
| 110 CHECK(GetProxy(&proxy)); | 115 CHECK(GetProxy(&proxy)); |
| 111 | 116 |
| 112 // Register marshaller | 117 // Register marshaller |
| (...skipping 19 matching lines...) Expand all Loading... |
| 132 GMainLoop* loop = g_main_loop_new (NULL, TRUE); | 137 GMainLoop* loop = g_main_loop_new (NULL, TRUE); |
| 133 dbus_g_proxy_connect_signal(proxy, | 138 dbus_g_proxy_connect_signal(proxy, |
| 134 kStatusUpdate, | 139 kStatusUpdate, |
| 135 G_CALLBACK(StatusUpdateSignalHandler), | 140 G_CALLBACK(StatusUpdateSignalHandler), |
| 136 NULL, | 141 NULL, |
| 137 NULL); | 142 NULL); |
| 138 g_main_loop_run(loop); | 143 g_main_loop_run(loop); |
| 139 g_main_loop_unref(loop); | 144 g_main_loop_unref(loop); |
| 140 } | 145 } |
| 141 | 146 |
| 142 bool CheckForUpdates(bool force, const string& app_version, | 147 bool CheckForUpdates(const string& app_version, const string& omaha_url) { |
| 143 const string& omaha_url) { | |
| 144 DBusGProxy* proxy; | 148 DBusGProxy* proxy; |
| 145 GError* error = NULL; | 149 GError* error = NULL; |
| 146 | 150 |
| 147 CHECK(GetProxy(&proxy)); | 151 CHECK(GetProxy(&proxy)); |
| 148 | 152 |
| 149 gboolean rc = | 153 gboolean rc = |
| 150 org_chromium_UpdateEngineInterface_attempt_update(proxy, | 154 org_chromium_UpdateEngineInterface_attempt_update(proxy, |
| 151 app_version.c_str(), | 155 app_version.c_str(), |
| 152 omaha_url.c_str(), | 156 omaha_url.c_str(), |
| 153 &error); | 157 &error); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 164 | 168 |
| 165 gboolean rc = | 169 gboolean rc = |
| 166 org_chromium_UpdateEngineInterface_reboot_if_needed(proxy, &error); | 170 org_chromium_UpdateEngineInterface_reboot_if_needed(proxy, &error); |
| 167 // Reboot error code doesn't necessarily mean that a reboot | 171 // Reboot error code doesn't necessarily mean that a reboot |
| 168 // failed. For example, D-Bus may be shutdown before we receive the | 172 // failed. For example, D-Bus may be shutdown before we receive the |
| 169 // result. | 173 // result. |
| 170 LOG_IF(INFO, !rc) << "Reboot error message: " << GetGErrorMessage(error); | 174 LOG_IF(INFO, !rc) << "Reboot error message: " << GetGErrorMessage(error); |
| 171 return true; | 175 return true; |
| 172 } | 176 } |
| 173 | 177 |
| 178 static gboolean CompleteUpdateSource(gpointer data) { |
| 179 string current_op; |
| 180 if (!GetStatus(¤t_op) || current_op == "UPDATE_STATUS_IDLE") { |
| 181 LOG(ERROR) << "Update failed."; |
| 182 exit(1); |
| 183 } |
| 184 if (current_op == "UPDATE_STATUS_UPDATED_NEED_REBOOT") { |
| 185 LOG(INFO) << "Update succeeded -- reboot needed."; |
| 186 exit(0); |
| 187 } |
| 188 return TRUE; |
| 189 } |
| 190 |
| 191 // This is similar to watching for updates but rather than registering |
| 192 // a signal watch, activelly poll the daemon just in case it stops |
| 193 // sending notifications. |
| 194 void CompleteUpdate() { |
| 195 GMainLoop* loop = g_main_loop_new (NULL, TRUE); |
| 196 g_timeout_add_seconds(5, CompleteUpdateSource, NULL); |
| 197 g_main_loop_run(loop); |
| 198 g_main_loop_unref(loop); |
| 199 } |
| 200 |
| 174 } // namespace {} | 201 } // namespace {} |
| 175 | 202 |
| 176 int main(int argc, char** argv) { | 203 int main(int argc, char** argv) { |
| 177 // Boilerplate init commands. | 204 // Boilerplate init commands. |
| 178 g_type_init(); | 205 g_type_init(); |
| 179 g_thread_init(NULL); | 206 g_thread_init(NULL); |
| 180 dbus_g_thread_init(); | 207 dbus_g_thread_init(); |
| 181 chromeos_update_engine::Subprocess::Init(); | 208 chromeos_update_engine::Subprocess::Init(); |
| 182 google::ParseCommandLineFlags(&argc, &argv, true); | 209 google::ParseCommandLineFlags(&argc, &argv, true); |
| 183 | 210 |
| 184 if (FLAGS_status) { | 211 if (FLAGS_status) { |
| 185 LOG(INFO) << "Querying Update Engine status..."; | 212 LOG(INFO) << "Querying Update Engine status..."; |
| 186 if (!GetStatus()) { | 213 if (!GetStatus(NULL)) { |
| 187 LOG(FATAL) << "GetStatus() failed."; | 214 LOG(FATAL) << "GetStatus failed."; |
| 215 return 1; |
| 188 } | 216 } |
| 189 return 0; | 217 return 0; |
| 190 } | 218 } |
| 191 if (FLAGS_force_update || FLAGS_check_for_update || | 219 |
| 192 !FLAGS_app_version.empty() || !FLAGS_omaha_url.empty()) { | 220 // Initiate an update check, if necessary. |
| 221 if (FLAGS_check_for_update || |
| 222 FLAGS_update || |
| 223 !FLAGS_app_version.empty() || |
| 224 !FLAGS_omaha_url.empty()) { |
| 193 LOG_IF(WARNING, FLAGS_reboot) << "-reboot flag ignored."; | 225 LOG_IF(WARNING, FLAGS_reboot) << "-reboot flag ignored."; |
| 226 string app_version = FLAGS_app_version; |
| 227 if (FLAGS_update && app_version.empty()) { |
| 228 app_version = "ForcedUpdate"; |
| 229 LOG(INFO) << "Forcing an update by setting app_version to ForcedUpdate."; |
| 230 } |
| 194 LOG(INFO) << "Initiating update check and install."; | 231 LOG(INFO) << "Initiating update check and install."; |
| 195 if (FLAGS_force_update) { | 232 CHECK(CheckForUpdates(app_version, FLAGS_omaha_url)) |
| 196 LOG(INFO) << "Will not abort due to being on expensive network."; | 233 << "Update check/initiate update failed."; |
| 234 |
| 235 // Wait for an update to complete. |
| 236 if (FLAGS_update) { |
| 237 LOG(INFO) << "Waiting for update the complete."; |
| 238 CompleteUpdate(); // Should never return. |
| 239 return 1; |
| 197 } | 240 } |
| 198 CHECK(CheckForUpdates(FLAGS_force_update, FLAGS_app_version, | |
| 199 FLAGS_omaha_url)) | |
| 200 << "Update check/initiate update failed."; | |
| 201 return 0; | 241 return 0; |
| 202 } | 242 } |
| 243 |
| 244 // Start watching for updates. |
| 203 if (FLAGS_watch_for_updates) { | 245 if (FLAGS_watch_for_updates) { |
| 204 LOG_IF(WARNING, FLAGS_reboot) << "-reboot flag ignored."; | 246 LOG_IF(WARNING, FLAGS_reboot) << "-reboot flag ignored."; |
| 205 LOG(INFO) << "Watching for status updates."; | 247 LOG(INFO) << "Watching for status updates."; |
| 206 WatchForUpdates(); // Should never return. | 248 WatchForUpdates(); // Should never return. |
| 207 return 1; | 249 return 1; |
| 208 } | 250 } |
| 251 |
| 209 if (FLAGS_reboot) { | 252 if (FLAGS_reboot) { |
| 210 LOG(INFO) << "Requesting a reboot..."; | 253 LOG(INFO) << "Requesting a reboot..."; |
| 211 CHECK(RebootIfNeeded()); | 254 CHECK(RebootIfNeeded()); |
| 212 return 0; | 255 return 0; |
| 213 } | 256 } |
| 214 | 257 |
| 215 LOG(INFO) << "No flags specified. Exiting."; | 258 LOG(INFO) << "No flags specified. Exiting."; |
| 216 return 0; | 259 return 0; |
| 217 } | 260 } |
| OLD | NEW |