blob: fc06da29570407c178b402f702206fd560a680d5 [file] [log] [blame]
Jay Srinivasanc1ba09a2012-08-14 14:15:57 -07001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Darin Petkov5a7f5652010-07-22 21:40:09 -07005#include <string>
6
Ben Chan46bf5c82013-06-24 11:17:41 -07007#include <dbus/dbus.h>
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -07008#include <gflags/gflags.h>
9#include <glib.h>
10
11#include "update_engine/dbus_constants.h"
12#include "update_engine/subprocess.h"
13#include "update_engine/utils.h"
14
15extern "C" {
16#include "update_engine/update_engine.dbusclient.h"
17}
18
19using chromeos_update_engine::kUpdateEngineServiceName;
20using chromeos_update_engine::kUpdateEngineServicePath;
21using chromeos_update_engine::kUpdateEngineServiceInterface;
David Zeuthen75a4c3e2013-09-06 11:36:59 -070022using chromeos_update_engine::AttemptUpdateFlags;
23using chromeos_update_engine::kAttemptUpdateFlagNonInteractive;
Darin Petkova0b9e772011-10-06 05:05:56 -070024using chromeos_update_engine::utils::GetAndFreeGError;
Darin Petkov5a7f5652010-07-22 21:40:09 -070025using std::string;
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070026
Darin Petkov296889c2010-07-23 16:20:54 -070027DEFINE_string(app_version, "", "Force the current app version.");
Jay Srinivasanae4697c2013-03-18 17:08:08 -070028DEFINE_string(channel, "",
Chris Sosa192449e2013-10-28 14:16:19 -070029 "Set the target channel. The device will be powerwashed if the "
30 "target channel is more stable than the current channel unless "
31 "--nopowerwash is specified.");
Chris Sosad317e402013-06-12 13:47:09 -070032DEFINE_bool(check_for_update, false, "Initiate check for updates.");
Chris Sosa192449e2013-10-28 14:16:19 -070033DEFINE_bool(follow, false, "Wait for any update operations to complete."
34 "Exit status is 0 if the update succeeded, and 1 otherwise.");
35DEFINE_bool(interactive, true, "Mark the update request as interactive.");
Chris Sosad317e402013-06-12 13:47:09 -070036DEFINE_string(omaha_url, "", "The URL of the Omaha update server.");
Chris Sosa192449e2013-10-28 14:16:19 -070037DEFINE_string(p2p_update, "",
38 "Enables (\"yes\") or disables (\"no\") the peer-to-peer update "
39 "sharing.");
40DEFINE_bool(powerwash, true, "When performing rollback or channel change, "
41 "do a powerwash or allow it respectively.");
Chris Sosad317e402013-06-12 13:47:09 -070042DEFINE_bool(reboot, false, "Initiate a reboot if needed.");
43DEFINE_bool(reset_status, false, "Sets the status in update_engine to idle.");
44DEFINE_bool(rollback, false, "Perform a rollback to the previous partition.");
45DEFINE_bool(show_channel, false, "Show the current and target channels.");
Chris Sosa192449e2013-10-28 14:16:19 -070046DEFINE_bool(show_p2p_update, false,
47 "Show the current setting for peer-to-peer update sharing.");
Alex Deymof4867c42013-06-28 14:41:39 -070048DEFINE_bool(show_update_over_cellular, false,
49 "Show the current setting for updates over cellular networks.");
Chris Sosa192449e2013-10-28 14:16:19 -070050DEFINE_bool(status, false, "Print the status to stdout.");
51DEFINE_bool(update, false, "Forces an update and waits for it to complete. "
52 "Implies --follow.");
Alex Deymof4867c42013-06-28 14:41:39 -070053DEFINE_string(update_over_cellular, "",
54 "Enables (\"yes\") or disables (\"no\") the updates over "
55 "cellular networks.");
Chris Sosa192449e2013-10-28 14:16:19 -070056DEFINE_bool(watch_for_updates, false,
57 "Listen for status updates and print them to the screen.");
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070058
59namespace {
60
Andrew de los Reyes63b96d72010-05-10 13:08:54 -070061bool GetProxy(DBusGProxy** out_proxy) {
62 DBusGConnection* bus;
Andrew de los Reyes68ab6ed2011-08-09 14:46:39 -070063 DBusGProxy* proxy = NULL;
Andrew de los Reyes63b96d72010-05-10 13:08:54 -070064 GError* error = NULL;
Andrew de los Reyes68ab6ed2011-08-09 14:46:39 -070065 const int kTries = 4;
Darin Petkova0b9e772011-10-06 05:05:56 -070066 const int kRetrySeconds = 10;
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070067
68 bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
Richard Barnetted7936062013-01-18 13:38:51 -080069 if (bus == NULL) {
70 LOG(ERROR) << "Failed to get bus: " << GetAndFreeGError(&error);
71 exit(1);
72 }
Andrew de los Reyes68ab6ed2011-08-09 14:46:39 -070073 for (int i = 0; !proxy && i < kTries; ++i) {
Darin Petkova0b9e772011-10-06 05:05:56 -070074 if (i > 0) {
75 LOG(INFO) << "Retrying to get dbus proxy. Try "
76 << (i + 1) << "/" << kTries;
Gilad Arnold8e3f1262013-01-08 14:59:54 -080077 g_usleep(kRetrySeconds * G_USEC_PER_SEC);
Darin Petkova0b9e772011-10-06 05:05:56 -070078 }
Andrew de los Reyes68ab6ed2011-08-09 14:46:39 -070079 proxy = dbus_g_proxy_new_for_name_owner(bus,
80 kUpdateEngineServiceName,
81 kUpdateEngineServicePath,
82 kUpdateEngineServiceInterface,
83 &error);
Darin Petkova0b9e772011-10-06 05:05:56 -070084 LOG_IF(WARNING, !proxy) << "Error getting dbus proxy for "
85 << kUpdateEngineServiceName << ": "
86 << GetAndFreeGError(&error);
Andrew de los Reyes68ab6ed2011-08-09 14:46:39 -070087 }
Richard Barnetted7936062013-01-18 13:38:51 -080088 if (proxy == NULL) {
89 LOG(ERROR) << "Giving up -- unable to get dbus proxy for "
90 << kUpdateEngineServiceName;
91 exit(1);
92 }
Andrew de los Reyes63b96d72010-05-10 13:08:54 -070093 *out_proxy = proxy;
94 return true;
95}
96
97static void StatusUpdateSignalHandler(DBusGProxy* proxy,
98 int64_t last_checked_time,
99 double progress,
100 gchar* current_operation,
101 gchar* new_version,
102 int64_t new_size,
103 void* user_data) {
104 LOG(INFO) << "Got status update:";
105 LOG(INFO) << " last_checked_time: " << last_checked_time;
106 LOG(INFO) << " progress: " << progress;
107 LOG(INFO) << " current_operation: " << current_operation;
108 LOG(INFO) << " new_version: " << new_version;
109 LOG(INFO) << " new_size: " << new_size;
110}
111
Jay Srinivasanc1ba09a2012-08-14 14:15:57 -0700112bool ResetStatus() {
113 DBusGProxy* proxy;
114 GError* error = NULL;
115
116 CHECK(GetProxy(&proxy));
117
Alex Deymo36dc2f32013-08-29 15:45:06 -0700118 gboolean rc = update_engine_client_reset_status(proxy, &error);
Jay Srinivasanc1ba09a2012-08-14 14:15:57 -0700119 return rc;
120}
121
122
Darin Petkov58529db2010-08-13 09:19:47 -0700123// If |op| is non-NULL, sets it to the current operation string or an
124// empty string if unable to obtain the current status.
125bool GetStatus(string* op) {
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700126 DBusGProxy* proxy;
127 GError* error = NULL;
Andrew de los Reyesada42202010-07-15 22:23:20 -0700128
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700129 CHECK(GetProxy(&proxy));
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700130
131 gint64 last_checked_time = 0;
132 gdouble progress = 0.0;
133 char* current_op = NULL;
134 char* new_version = NULL;
135 gint64 new_size = 0;
136
Alex Deymo36dc2f32013-08-29 15:45:06 -0700137 gboolean rc = update_engine_client_get_status(proxy,
138 &last_checked_time,
139 &progress,
140 &current_op,
141 &new_version,
142 &new_size,
143 &error);
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700144 if (rc == FALSE) {
Darin Petkova0b9e772011-10-06 05:05:56 -0700145 LOG(INFO) << "Error getting status: " << GetAndFreeGError(&error);
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700146 }
147 printf("LAST_CHECKED_TIME=%" PRIi64 "\nPROGRESS=%f\nCURRENT_OP=%s\n"
148 "NEW_VERSION=%s\nNEW_SIZE=%" PRIi64 "\n",
149 last_checked_time,
150 progress,
151 current_op,
152 new_version,
153 new_size);
Darin Petkov58529db2010-08-13 09:19:47 -0700154 if (op) {
155 *op = current_op ? current_op : "";
156 }
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700157 return true;
158}
159
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700160// Should never return.
161void WatchForUpdates() {
162 DBusGProxy* proxy;
Andrew de los Reyesada42202010-07-15 22:23:20 -0700163
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700164 CHECK(GetProxy(&proxy));
Andrew de los Reyesada42202010-07-15 22:23:20 -0700165
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700166 // Register marshaller
167 dbus_g_object_register_marshaller(
Alex Deymo3d41c4d2014-02-13 23:26:33 -0800168 NULL,
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700169 G_TYPE_NONE,
170 G_TYPE_INT64,
171 G_TYPE_DOUBLE,
172 G_TYPE_STRING,
173 G_TYPE_STRING,
174 G_TYPE_INT64,
175 G_TYPE_INVALID);
Andrew de los Reyesada42202010-07-15 22:23:20 -0700176
177 static const char kStatusUpdate[] = "StatusUpdate";
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700178 dbus_g_proxy_add_signal(proxy,
Andrew de los Reyesada42202010-07-15 22:23:20 -0700179 kStatusUpdate,
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700180 G_TYPE_INT64,
181 G_TYPE_DOUBLE,
182 G_TYPE_STRING,
183 G_TYPE_STRING,
184 G_TYPE_INT64,
185 G_TYPE_INVALID);
186 GMainLoop* loop = g_main_loop_new (NULL, TRUE);
187 dbus_g_proxy_connect_signal(proxy,
Andrew de los Reyesada42202010-07-15 22:23:20 -0700188 kStatusUpdate,
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700189 G_CALLBACK(StatusUpdateSignalHandler),
190 NULL,
191 NULL);
192 g_main_loop_run(loop);
193 g_main_loop_unref(loop);
194}
195
Chris Sosad317e402013-06-12 13:47:09 -0700196bool Rollback(bool rollback) {
197 DBusGProxy* proxy;
198 GError* error = NULL;
199
200 CHECK(GetProxy(&proxy));
201
Alex Deymo36dc2f32013-08-29 15:45:06 -0700202 gboolean rc = update_engine_client_attempt_rollback(proxy,
203 rollback,
204 &error);
Chris Sosad317e402013-06-12 13:47:09 -0700205 CHECK_EQ(rc, TRUE) << "Error with rollback request: "
206 << GetAndFreeGError(&error);
207 return true;
208}
209
Darin Petkov58529db2010-08-13 09:19:47 -0700210bool CheckForUpdates(const string& app_version, const string& omaha_url) {
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700211 DBusGProxy* proxy;
212 GError* error = NULL;
Andrew de los Reyesada42202010-07-15 22:23:20 -0700213
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700214 CHECK(GetProxy(&proxy));
215
David Zeuthen75a4c3e2013-09-06 11:36:59 -0700216 AttemptUpdateFlags flags = static_cast<AttemptUpdateFlags>(
217 FLAGS_interactive ? 0 : kAttemptUpdateFlagNonInteractive);
218 gboolean rc =
219 update_engine_client_attempt_update_with_flags(proxy,
220 app_version.c_str(),
221 omaha_url.c_str(),
222 static_cast<gint>(flags),
223 &error);
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700224 CHECK_EQ(rc, TRUE) << "Error checking for update: "
Darin Petkova0b9e772011-10-06 05:05:56 -0700225 << GetAndFreeGError(&error);
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700226 return true;
227}
228
Darin Petkov296889c2010-07-23 16:20:54 -0700229bool RebootIfNeeded() {
230 DBusGProxy* proxy;
231 GError* error = NULL;
232
233 CHECK(GetProxy(&proxy));
234
235 gboolean rc =
Alex Deymo36dc2f32013-08-29 15:45:06 -0700236 update_engine_client_reboot_if_needed(proxy, &error);
Darin Petkov296889c2010-07-23 16:20:54 -0700237 // Reboot error code doesn't necessarily mean that a reboot
238 // failed. For example, D-Bus may be shutdown before we receive the
239 // result.
Darin Petkova0b9e772011-10-06 05:05:56 -0700240 LOG_IF(INFO, !rc) << "Reboot error message: " << GetAndFreeGError(&error);
Darin Petkov296889c2010-07-23 16:20:54 -0700241 return true;
242}
243
Chris Sosacb7fa882013-07-25 17:02:59 -0700244void SetTargetChannel(const string& target_channel, bool allow_powerwash) {
Darin Petkov8daa3242010-10-25 13:28:47 -0700245 DBusGProxy* proxy;
246 GError* error = NULL;
247
248 CHECK(GetProxy(&proxy));
249
Alex Deymo36dc2f32013-08-29 15:45:06 -0700250 gboolean rc = update_engine_client_set_channel(proxy,
251 target_channel.c_str(),
252 allow_powerwash,
253 &error);
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700254 CHECK_EQ(rc, true) << "Error setting the channel: "
Darin Petkova0b9e772011-10-06 05:05:56 -0700255 << GetAndFreeGError(&error);
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700256 LOG(INFO) << "Channel permanently set to: " << target_channel;
Darin Petkov8daa3242010-10-25 13:28:47 -0700257}
258
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700259string GetChannel(bool get_current_channel) {
Satoru Takabayashi583667b2010-10-27 13:09:57 +0900260 DBusGProxy* proxy;
261 GError* error = NULL;
262
263 CHECK(GetProxy(&proxy));
264
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700265 char* channel = NULL;
Alex Deymo36dc2f32013-08-29 15:45:06 -0700266 gboolean rc = update_engine_client_get_channel(proxy,
267 get_current_channel,
268 &channel,
269 &error);
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700270 CHECK_EQ(rc, true) << "Error getting the channel: "
271 << GetAndFreeGError(&error);
272 string output = channel;
273 g_free(channel);
Satoru Takabayashi583667b2010-10-27 13:09:57 +0900274 return output;
275}
276
Alex Deymo5fdf7762013-07-17 20:01:40 -0700277void SetUpdateOverCellularPermission(gboolean allowed) {
Alex Deymof4867c42013-06-28 14:41:39 -0700278 DBusGProxy* proxy;
279 GError* error = NULL;
280
281 CHECK(GetProxy(&proxy));
282
Alex Deymo36dc2f32013-08-29 15:45:06 -0700283 gboolean rc = update_engine_client_set_update_over_cellular_permission(
284 proxy,
285 allowed,
286 &error);
Alex Deymof4867c42013-06-28 14:41:39 -0700287 CHECK_EQ(rc, true) << "Error setting the update over cellular setting: "
288 << GetAndFreeGError(&error);
Alex Deymof4867c42013-06-28 14:41:39 -0700289}
290
291bool GetUpdateOverCellularPermission() {
292 DBusGProxy* proxy;
293 GError* error = NULL;
294
295 CHECK(GetProxy(&proxy));
296
297 gboolean allowed;
Alex Deymo36dc2f32013-08-29 15:45:06 -0700298 gboolean rc = update_engine_client_get_update_over_cellular_permission(
299 proxy,
300 &allowed,
301 &error);
Alex Deymof4867c42013-06-28 14:41:39 -0700302 CHECK_EQ(rc, true) << "Error getting the update over cellular setting: "
303 << GetAndFreeGError(&error);
304 return allowed;
305}
306
Alex Deymo5fdf7762013-07-17 20:01:40 -0700307void SetP2PUpdatePermission(gboolean enabled) {
308 DBusGProxy* proxy;
309 GError* error = NULL;
310
311 CHECK(GetProxy(&proxy));
312
Alex Deymo36dc2f32013-08-29 15:45:06 -0700313 gboolean rc = update_engine_client_set_p2p_update_permission(
314 proxy,
315 enabled,
316 &error);
Alex Deymo5fdf7762013-07-17 20:01:40 -0700317 CHECK_EQ(rc, true) << "Error setting the peer-to-peer update setting: "
318 << GetAndFreeGError(&error);
319}
320
321bool GetP2PUpdatePermission() {
322 DBusGProxy* proxy;
323 GError* error = NULL;
324
325 CHECK(GetProxy(&proxy));
326
327 gboolean enabled;
Alex Deymo36dc2f32013-08-29 15:45:06 -0700328 gboolean rc = update_engine_client_get_p2p_update_permission(
329 proxy,
330 &enabled,
331 &error);
Alex Deymo5fdf7762013-07-17 20:01:40 -0700332 CHECK_EQ(rc, true) << "Error getting the peer-to-peer update setting: "
333 << GetAndFreeGError(&error);
334 return enabled;
335}
336
Darin Petkov58529db2010-08-13 09:19:47 -0700337static gboolean CompleteUpdateSource(gpointer data) {
338 string current_op;
339 if (!GetStatus(&current_op) || current_op == "UPDATE_STATUS_IDLE") {
340 LOG(ERROR) << "Update failed.";
341 exit(1);
342 }
343 if (current_op == "UPDATE_STATUS_UPDATED_NEED_REBOOT") {
344 LOG(INFO) << "Update succeeded -- reboot needed.";
345 exit(0);
346 }
347 return TRUE;
348}
349
350// This is similar to watching for updates but rather than registering
351// a signal watch, activelly poll the daemon just in case it stops
352// sending notifications.
353void CompleteUpdate() {
354 GMainLoop* loop = g_main_loop_new (NULL, TRUE);
355 g_timeout_add_seconds(5, CompleteUpdateSource, NULL);
356 g_main_loop_run(loop);
357 g_main_loop_unref(loop);
358}
359
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700360} // namespace {}
361
362int main(int argc, char** argv) {
363 // Boilerplate init commands.
364 g_type_init();
Ben Chan46bf5c82013-06-24 11:17:41 -0700365 dbus_threads_init_default();
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700366 chromeos_update_engine::Subprocess::Init();
367 google::ParseCommandLineFlags(&argc, &argv, true);
Andrew de los Reyesada42202010-07-15 22:23:20 -0700368
Jay Srinivasanc1ba09a2012-08-14 14:15:57 -0700369 // Update the status if requested.
370 if (FLAGS_reset_status) {
371 LOG(INFO) << "Setting Update Engine status to idle ...";
372 if (!ResetStatus()) {
373 LOG(ERROR) << "ResetStatus failed.";
374 return 1;
375 }
Gilad Arnold50c60632013-01-25 10:27:19 -0800376 LOG(INFO) << "ResetStatus succeeded; to undo partition table changes run:\n"
377 "(D=$(rootdev -d) P=$(rootdev -s); cgpt p -i$(($(echo ${P#$D} "
378 "| sed 's/^[^0-9]*//')-1)) $D;)";
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700379 }
Darin Petkov58529db2010-08-13 09:19:47 -0700380
Alex Deymof4867c42013-06-28 14:41:39 -0700381 // Changes the current update over cellular network setting.
382 if (!FLAGS_update_over_cellular.empty()) {
383 gboolean allowed = FLAGS_update_over_cellular == "yes";
384 if (!allowed && FLAGS_update_over_cellular != "no") {
385 LOG(ERROR) << "Unknown option: \"" << FLAGS_update_over_cellular
386 << "\". Please specify \"yes\" or \"no\".";
387 } else {
388 SetUpdateOverCellularPermission(allowed);
389 }
390 }
391
392 // Show the current update over cellular network setting.
393 if (FLAGS_show_update_over_cellular) {
394 bool allowed = GetUpdateOverCellularPermission();
395 LOG(INFO) << "Current update over cellular network setting: "
396 << (allowed ? "ENABLED" : "DISABLED");
397 }
398
Chris Sosacb7fa882013-07-25 17:02:59 -0700399 if (!FLAGS_powerwash && !FLAGS_rollback && FLAGS_channel.empty()) {
Chris Sosa192449e2013-10-28 14:16:19 -0700400 LOG(ERROR) << "powerwash flag only makes sense rollback or channel change";
Chris Sosacb7fa882013-07-25 17:02:59 -0700401 return 1;
402 }
403
Alex Deymo5fdf7762013-07-17 20:01:40 -0700404 // Change the P2P enabled setting.
405 if (!FLAGS_p2p_update.empty()) {
406 gboolean enabled = FLAGS_p2p_update == "yes";
407 if (!enabled && FLAGS_p2p_update != "no") {
408 LOG(ERROR) << "Unknown option: \"" << FLAGS_p2p_update
409 << "\". Please specify \"yes\" or \"no\".";
410 } else {
411 SetP2PUpdatePermission(enabled);
412 }
413 }
414
415 // Show the current P2P enabled setting.
416 if (FLAGS_show_p2p_update) {
417 bool enabled = GetP2PUpdatePermission();
418 LOG(INFO) << "Current update using P2P setting: "
419 << (enabled ? "ENABLED" : "DISABLED");
420 }
421
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700422 // First, update the target channel if requested.
423 if (!FLAGS_channel.empty())
Chris Sosacb7fa882013-07-25 17:02:59 -0700424 SetTargetChannel(FLAGS_channel, FLAGS_powerwash);
Darin Petkov8daa3242010-10-25 13:28:47 -0700425
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700426 // Show the current and target channels if requested.
427 if (FLAGS_show_channel) {
428 string current_channel = GetChannel(true);
429 LOG(INFO) << "Current Channel: " << current_channel;
430
431 string target_channel = GetChannel(false);
432 if (!target_channel.empty())
433 LOG(INFO) << "Target Channel (pending update): " << target_channel;
Satoru Takabayashi583667b2010-10-27 13:09:57 +0900434 }
435
Chris Sosad317e402013-06-12 13:47:09 -0700436 bool do_update_request = FLAGS_check_for_update | FLAGS_update |
437 !FLAGS_app_version.empty() | !FLAGS_omaha_url.empty();
Chris Sosa192449e2013-10-28 14:16:19 -0700438 if (FLAGS_update)
439 FLAGS_follow = true;
Chris Sosad317e402013-06-12 13:47:09 -0700440
Chris Sosad317e402013-06-12 13:47:09 -0700441 if (do_update_request && FLAGS_rollback) {
Chris Sosa192449e2013-10-28 14:16:19 -0700442 LOG(ERROR) << "Incompatible flags specified with rollback."
443 << "Rollback should not include update-related flags.";
Chris Sosad317e402013-06-12 13:47:09 -0700444 return 1;
445 }
446
447 if(FLAGS_rollback) {
448 LOG(INFO) << "Requesting rollback.";
449 CHECK(Rollback(FLAGS_powerwash)) << "Request for rollback failed.";
Chris Sosad317e402013-06-12 13:47:09 -0700450 }
451
Darin Petkov58529db2010-08-13 09:19:47 -0700452 // Initiate an update check, if necessary.
Chris Sosad317e402013-06-12 13:47:09 -0700453 if (do_update_request) {
Darin Petkov296889c2010-07-23 16:20:54 -0700454 LOG_IF(WARNING, FLAGS_reboot) << "-reboot flag ignored.";
Darin Petkov58529db2010-08-13 09:19:47 -0700455 string app_version = FLAGS_app_version;
456 if (FLAGS_update && app_version.empty()) {
457 app_version = "ForcedUpdate";
458 LOG(INFO) << "Forcing an update by setting app_version to ForcedUpdate.";
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700459 }
Darin Petkov58529db2010-08-13 09:19:47 -0700460 LOG(INFO) << "Initiating update check and install.";
461 CHECK(CheckForUpdates(app_version, FLAGS_omaha_url))
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700462 << "Update check/initiate update failed.";
Chris Sosa192449e2013-10-28 14:16:19 -0700463 }
Darin Petkov58529db2010-08-13 09:19:47 -0700464
Chris Sosa192449e2013-10-28 14:16:19 -0700465 // These final options are all mutually exclusive with one another.
466 if (FLAGS_follow + FLAGS_watch_for_updates + FLAGS_reboot + FLAGS_status > 1)
467 {
468 LOG(ERROR) << "Multiple exclusive options selected. "
469 << "Select only one of --follow, --watch_for_updates, --reboot, "
470 << "or --status.";
471 return 1;
472 }
473
474 if (FLAGS_status) {
475 LOG(INFO) << "Querying Update Engine status...";
476 if (!GetStatus(NULL)) {
477 LOG(ERROR) << "GetStatus failed.";
Darin Petkov58529db2010-08-13 09:19:47 -0700478 return 1;
479 }
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700480 return 0;
481 }
Darin Petkov58529db2010-08-13 09:19:47 -0700482
Chris Sosa192449e2013-10-28 14:16:19 -0700483 if (FLAGS_follow) {
484 LOG(INFO) << "Waiting for update to complete.";
485 CompleteUpdate(); // Should never return.
486 return 1;
487 }
488
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700489 if (FLAGS_watch_for_updates) {
490 LOG(INFO) << "Watching for status updates.";
491 WatchForUpdates(); // Should never return.
492 return 1;
493 }
Darin Petkov58529db2010-08-13 09:19:47 -0700494
Darin Petkov296889c2010-07-23 16:20:54 -0700495 if (FLAGS_reboot) {
496 LOG(INFO) << "Requesting a reboot...";
497 CHECK(RebootIfNeeded());
498 return 0;
499 }
Andrew de los Reyesada42202010-07-15 22:23:20 -0700500
Darin Petkov8daa3242010-10-25 13:28:47 -0700501 LOG(INFO) << "Done.";
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700502 return 0;
503}