blob: f91c201d3b1a87c0c5e040c8b304266e9391951a [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
Andrew de los Reyes63b96d72010-05-10 13:08:54 -070011#include "update_engine/marshal.glibmarshal.h"
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070012#include "update_engine/dbus_constants.h"
13#include "update_engine/subprocess.h"
14#include "update_engine/utils.h"
15
16extern "C" {
17#include "update_engine/update_engine.dbusclient.h"
18}
19
20using chromeos_update_engine::kUpdateEngineServiceName;
21using chromeos_update_engine::kUpdateEngineServicePath;
22using chromeos_update_engine::kUpdateEngineServiceInterface;
David Zeuthen75a4c3e2013-09-06 11:36:59 -070023using chromeos_update_engine::AttemptUpdateFlags;
24using chromeos_update_engine::kAttemptUpdateFlagNonInteractive;
Darin Petkova0b9e772011-10-06 05:05:56 -070025using chromeos_update_engine::utils::GetAndFreeGError;
Darin Petkov5a7f5652010-07-22 21:40:09 -070026using std::string;
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070027
Darin Petkov296889c2010-07-23 16:20:54 -070028DEFINE_string(app_version, "", "Force the current app version.");
Jay Srinivasanae4697c2013-03-18 17:08:08 -070029DEFINE_string(channel, "",
Chris Sosa192449e2013-10-28 14:16:19 -070030 "Set the target channel. The device will be powerwashed if the "
31 "target channel is more stable than the current channel unless "
32 "--nopowerwash is specified.");
Chris Sosad317e402013-06-12 13:47:09 -070033DEFINE_bool(check_for_update, false, "Initiate check for updates.");
Chris Sosa192449e2013-10-28 14:16:19 -070034DEFINE_bool(follow, false, "Wait for any update operations to complete."
35 "Exit status is 0 if the update succeeded, and 1 otherwise.");
36DEFINE_bool(interactive, true, "Mark the update request as interactive.");
Chris Sosad317e402013-06-12 13:47:09 -070037DEFINE_string(omaha_url, "", "The URL of the Omaha update server.");
Chris Sosa192449e2013-10-28 14:16:19 -070038DEFINE_string(p2p_update, "",
39 "Enables (\"yes\") or disables (\"no\") the peer-to-peer update "
40 "sharing.");
41DEFINE_bool(powerwash, true, "When performing rollback or channel change, "
42 "do a powerwash or allow it respectively.");
Chris Sosad317e402013-06-12 13:47:09 -070043DEFINE_bool(reboot, false, "Initiate a reboot if needed.");
44DEFINE_bool(reset_status, false, "Sets the status in update_engine to idle.");
45DEFINE_bool(rollback, false, "Perform a rollback to the previous partition.");
46DEFINE_bool(show_channel, false, "Show the current and target channels.");
Chris Sosa192449e2013-10-28 14:16:19 -070047DEFINE_bool(show_p2p_update, false,
48 "Show the current setting for peer-to-peer update sharing.");
Alex Deymof4867c42013-06-28 14:41:39 -070049DEFINE_bool(show_update_over_cellular, false,
50 "Show the current setting for updates over cellular networks.");
Chris Sosa192449e2013-10-28 14:16:19 -070051DEFINE_bool(status, false, "Print the status to stdout.");
52DEFINE_bool(update, false, "Forces an update and waits for it to complete. "
53 "Implies --follow.");
Alex Deymof4867c42013-06-28 14:41:39 -070054DEFINE_string(update_over_cellular, "",
55 "Enables (\"yes\") or disables (\"no\") the updates over "
56 "cellular networks.");
Chris Sosa192449e2013-10-28 14:16:19 -070057DEFINE_bool(watch_for_updates, false,
58 "Listen for status updates and print them to the screen.");
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070059
60namespace {
61
Andrew de los Reyes63b96d72010-05-10 13:08:54 -070062bool GetProxy(DBusGProxy** out_proxy) {
63 DBusGConnection* bus;
Andrew de los Reyes68ab6ed2011-08-09 14:46:39 -070064 DBusGProxy* proxy = NULL;
Andrew de los Reyes63b96d72010-05-10 13:08:54 -070065 GError* error = NULL;
Andrew de los Reyes68ab6ed2011-08-09 14:46:39 -070066 const int kTries = 4;
Darin Petkova0b9e772011-10-06 05:05:56 -070067 const int kRetrySeconds = 10;
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070068
69 bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
Richard Barnetted7936062013-01-18 13:38:51 -080070 if (bus == NULL) {
71 LOG(ERROR) << "Failed to get bus: " << GetAndFreeGError(&error);
72 exit(1);
73 }
Andrew de los Reyes68ab6ed2011-08-09 14:46:39 -070074 for (int i = 0; !proxy && i < kTries; ++i) {
Darin Petkova0b9e772011-10-06 05:05:56 -070075 if (i > 0) {
76 LOG(INFO) << "Retrying to get dbus proxy. Try "
77 << (i + 1) << "/" << kTries;
Gilad Arnold8e3f1262013-01-08 14:59:54 -080078 g_usleep(kRetrySeconds * G_USEC_PER_SEC);
Darin Petkova0b9e772011-10-06 05:05:56 -070079 }
Andrew de los Reyes68ab6ed2011-08-09 14:46:39 -070080 proxy = dbus_g_proxy_new_for_name_owner(bus,
81 kUpdateEngineServiceName,
82 kUpdateEngineServicePath,
83 kUpdateEngineServiceInterface,
84 &error);
Darin Petkova0b9e772011-10-06 05:05:56 -070085 LOG_IF(WARNING, !proxy) << "Error getting dbus proxy for "
86 << kUpdateEngineServiceName << ": "
87 << GetAndFreeGError(&error);
Andrew de los Reyes68ab6ed2011-08-09 14:46:39 -070088 }
Richard Barnetted7936062013-01-18 13:38:51 -080089 if (proxy == NULL) {
90 LOG(ERROR) << "Giving up -- unable to get dbus proxy for "
91 << kUpdateEngineServiceName;
92 exit(1);
93 }
Andrew de los Reyes63b96d72010-05-10 13:08:54 -070094 *out_proxy = proxy;
95 return true;
96}
97
98static void StatusUpdateSignalHandler(DBusGProxy* proxy,
99 int64_t last_checked_time,
100 double progress,
101 gchar* current_operation,
102 gchar* new_version,
103 int64_t new_size,
104 void* user_data) {
105 LOG(INFO) << "Got status update:";
106 LOG(INFO) << " last_checked_time: " << last_checked_time;
107 LOG(INFO) << " progress: " << progress;
108 LOG(INFO) << " current_operation: " << current_operation;
109 LOG(INFO) << " new_version: " << new_version;
110 LOG(INFO) << " new_size: " << new_size;
111}
112
Jay Srinivasanc1ba09a2012-08-14 14:15:57 -0700113bool ResetStatus() {
114 DBusGProxy* proxy;
115 GError* error = NULL;
116
117 CHECK(GetProxy(&proxy));
118
Alex Deymo36dc2f32013-08-29 15:45:06 -0700119 gboolean rc = update_engine_client_reset_status(proxy, &error);
Jay Srinivasanc1ba09a2012-08-14 14:15:57 -0700120 return rc;
121}
122
123
Darin Petkov58529db2010-08-13 09:19:47 -0700124// If |op| is non-NULL, sets it to the current operation string or an
125// empty string if unable to obtain the current status.
126bool GetStatus(string* op) {
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700127 DBusGProxy* proxy;
128 GError* error = NULL;
Andrew de los Reyesada42202010-07-15 22:23:20 -0700129
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700130 CHECK(GetProxy(&proxy));
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700131
132 gint64 last_checked_time = 0;
133 gdouble progress = 0.0;
134 char* current_op = NULL;
135 char* new_version = NULL;
136 gint64 new_size = 0;
137
Alex Deymo36dc2f32013-08-29 15:45:06 -0700138 gboolean rc = update_engine_client_get_status(proxy,
139 &last_checked_time,
140 &progress,
141 &current_op,
142 &new_version,
143 &new_size,
144 &error);
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700145 if (rc == FALSE) {
Darin Petkova0b9e772011-10-06 05:05:56 -0700146 LOG(INFO) << "Error getting status: " << GetAndFreeGError(&error);
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700147 }
148 printf("LAST_CHECKED_TIME=%" PRIi64 "\nPROGRESS=%f\nCURRENT_OP=%s\n"
149 "NEW_VERSION=%s\nNEW_SIZE=%" PRIi64 "\n",
150 last_checked_time,
151 progress,
152 current_op,
153 new_version,
154 new_size);
Darin Petkov58529db2010-08-13 09:19:47 -0700155 if (op) {
156 *op = current_op ? current_op : "";
157 }
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700158 return true;
159}
160
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700161// Should never return.
162void WatchForUpdates() {
163 DBusGProxy* proxy;
Andrew de los Reyesada42202010-07-15 22:23:20 -0700164
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700165 CHECK(GetProxy(&proxy));
Andrew de los Reyesada42202010-07-15 22:23:20 -0700166
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700167 // Register marshaller
168 dbus_g_object_register_marshaller(
169 update_engine_VOID__INT64_DOUBLE_STRING_STRING_INT64,
170 G_TYPE_NONE,
171 G_TYPE_INT64,
172 G_TYPE_DOUBLE,
173 G_TYPE_STRING,
174 G_TYPE_STRING,
175 G_TYPE_INT64,
176 G_TYPE_INVALID);
Andrew de los Reyesada42202010-07-15 22:23:20 -0700177
178 static const char kStatusUpdate[] = "StatusUpdate";
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700179 dbus_g_proxy_add_signal(proxy,
Andrew de los Reyesada42202010-07-15 22:23:20 -0700180 kStatusUpdate,
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700181 G_TYPE_INT64,
182 G_TYPE_DOUBLE,
183 G_TYPE_STRING,
184 G_TYPE_STRING,
185 G_TYPE_INT64,
186 G_TYPE_INVALID);
187 GMainLoop* loop = g_main_loop_new (NULL, TRUE);
188 dbus_g_proxy_connect_signal(proxy,
Andrew de los Reyesada42202010-07-15 22:23:20 -0700189 kStatusUpdate,
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700190 G_CALLBACK(StatusUpdateSignalHandler),
191 NULL,
192 NULL);
193 g_main_loop_run(loop);
194 g_main_loop_unref(loop);
195}
196
Chris Sosad317e402013-06-12 13:47:09 -0700197bool Rollback(bool rollback) {
198 DBusGProxy* proxy;
199 GError* error = NULL;
200
201 CHECK(GetProxy(&proxy));
202
Alex Deymo36dc2f32013-08-29 15:45:06 -0700203 gboolean rc = update_engine_client_attempt_rollback(proxy,
204 rollback,
205 &error);
Chris Sosad317e402013-06-12 13:47:09 -0700206 CHECK_EQ(rc, TRUE) << "Error with rollback request: "
207 << GetAndFreeGError(&error);
208 return true;
209}
210
Darin Petkov58529db2010-08-13 09:19:47 -0700211bool CheckForUpdates(const string& app_version, const string& omaha_url) {
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700212 DBusGProxy* proxy;
213 GError* error = NULL;
Andrew de los Reyesada42202010-07-15 22:23:20 -0700214
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700215 CHECK(GetProxy(&proxy));
216
David Zeuthen75a4c3e2013-09-06 11:36:59 -0700217 AttemptUpdateFlags flags = static_cast<AttemptUpdateFlags>(
218 FLAGS_interactive ? 0 : kAttemptUpdateFlagNonInteractive);
219 gboolean rc =
220 update_engine_client_attempt_update_with_flags(proxy,
221 app_version.c_str(),
222 omaha_url.c_str(),
223 static_cast<gint>(flags),
224 &error);
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700225 CHECK_EQ(rc, TRUE) << "Error checking for update: "
Darin Petkova0b9e772011-10-06 05:05:56 -0700226 << GetAndFreeGError(&error);
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700227 return true;
228}
229
Darin Petkov296889c2010-07-23 16:20:54 -0700230bool RebootIfNeeded() {
231 DBusGProxy* proxy;
232 GError* error = NULL;
233
234 CHECK(GetProxy(&proxy));
235
236 gboolean rc =
Alex Deymo36dc2f32013-08-29 15:45:06 -0700237 update_engine_client_reboot_if_needed(proxy, &error);
Darin Petkov296889c2010-07-23 16:20:54 -0700238 // Reboot error code doesn't necessarily mean that a reboot
239 // failed. For example, D-Bus may be shutdown before we receive the
240 // result.
Darin Petkova0b9e772011-10-06 05:05:56 -0700241 LOG_IF(INFO, !rc) << "Reboot error message: " << GetAndFreeGError(&error);
Darin Petkov296889c2010-07-23 16:20:54 -0700242 return true;
243}
244
Chris Sosacb7fa882013-07-25 17:02:59 -0700245void SetTargetChannel(const string& target_channel, bool allow_powerwash) {
Darin Petkov8daa3242010-10-25 13:28:47 -0700246 DBusGProxy* proxy;
247 GError* error = NULL;
248
249 CHECK(GetProxy(&proxy));
250
Alex Deymo36dc2f32013-08-29 15:45:06 -0700251 gboolean rc = update_engine_client_set_channel(proxy,
252 target_channel.c_str(),
253 allow_powerwash,
254 &error);
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700255 CHECK_EQ(rc, true) << "Error setting the channel: "
Darin Petkova0b9e772011-10-06 05:05:56 -0700256 << GetAndFreeGError(&error);
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700257 LOG(INFO) << "Channel permanently set to: " << target_channel;
Darin Petkov8daa3242010-10-25 13:28:47 -0700258}
259
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700260string GetChannel(bool get_current_channel) {
Satoru Takabayashi583667b2010-10-27 13:09:57 +0900261 DBusGProxy* proxy;
262 GError* error = NULL;
263
264 CHECK(GetProxy(&proxy));
265
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700266 char* channel = NULL;
Alex Deymo36dc2f32013-08-29 15:45:06 -0700267 gboolean rc = update_engine_client_get_channel(proxy,
268 get_current_channel,
269 &channel,
270 &error);
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700271 CHECK_EQ(rc, true) << "Error getting the channel: "
272 << GetAndFreeGError(&error);
273 string output = channel;
274 g_free(channel);
Satoru Takabayashi583667b2010-10-27 13:09:57 +0900275 return output;
276}
277
Alex Deymo5fdf7762013-07-17 20:01:40 -0700278void SetUpdateOverCellularPermission(gboolean allowed) {
Alex Deymof4867c42013-06-28 14:41:39 -0700279 DBusGProxy* proxy;
280 GError* error = NULL;
281
282 CHECK(GetProxy(&proxy));
283
Alex Deymo36dc2f32013-08-29 15:45:06 -0700284 gboolean rc = update_engine_client_set_update_over_cellular_permission(
285 proxy,
286 allowed,
287 &error);
Alex Deymof4867c42013-06-28 14:41:39 -0700288 CHECK_EQ(rc, true) << "Error setting the update over cellular setting: "
289 << GetAndFreeGError(&error);
Alex Deymof4867c42013-06-28 14:41:39 -0700290}
291
292bool GetUpdateOverCellularPermission() {
293 DBusGProxy* proxy;
294 GError* error = NULL;
295
296 CHECK(GetProxy(&proxy));
297
298 gboolean allowed;
Alex Deymo36dc2f32013-08-29 15:45:06 -0700299 gboolean rc = update_engine_client_get_update_over_cellular_permission(
300 proxy,
301 &allowed,
302 &error);
Alex Deymof4867c42013-06-28 14:41:39 -0700303 CHECK_EQ(rc, true) << "Error getting the update over cellular setting: "
304 << GetAndFreeGError(&error);
305 return allowed;
306}
307
Alex Deymo5fdf7762013-07-17 20:01:40 -0700308void SetP2PUpdatePermission(gboolean enabled) {
309 DBusGProxy* proxy;
310 GError* error = NULL;
311
312 CHECK(GetProxy(&proxy));
313
Alex Deymo36dc2f32013-08-29 15:45:06 -0700314 gboolean rc = update_engine_client_set_p2p_update_permission(
315 proxy,
316 enabled,
317 &error);
Alex Deymo5fdf7762013-07-17 20:01:40 -0700318 CHECK_EQ(rc, true) << "Error setting the peer-to-peer update setting: "
319 << GetAndFreeGError(&error);
320}
321
322bool GetP2PUpdatePermission() {
323 DBusGProxy* proxy;
324 GError* error = NULL;
325
326 CHECK(GetProxy(&proxy));
327
328 gboolean enabled;
Alex Deymo36dc2f32013-08-29 15:45:06 -0700329 gboolean rc = update_engine_client_get_p2p_update_permission(
330 proxy,
331 &enabled,
332 &error);
Alex Deymo5fdf7762013-07-17 20:01:40 -0700333 CHECK_EQ(rc, true) << "Error getting the peer-to-peer update setting: "
334 << GetAndFreeGError(&error);
335 return enabled;
336}
337
Darin Petkov58529db2010-08-13 09:19:47 -0700338static gboolean CompleteUpdateSource(gpointer data) {
339 string current_op;
340 if (!GetStatus(&current_op) || current_op == "UPDATE_STATUS_IDLE") {
341 LOG(ERROR) << "Update failed.";
342 exit(1);
343 }
344 if (current_op == "UPDATE_STATUS_UPDATED_NEED_REBOOT") {
345 LOG(INFO) << "Update succeeded -- reboot needed.";
346 exit(0);
347 }
348 return TRUE;
349}
350
351// This is similar to watching for updates but rather than registering
352// a signal watch, activelly poll the daemon just in case it stops
353// sending notifications.
354void CompleteUpdate() {
355 GMainLoop* loop = g_main_loop_new (NULL, TRUE);
356 g_timeout_add_seconds(5, CompleteUpdateSource, NULL);
357 g_main_loop_run(loop);
358 g_main_loop_unref(loop);
359}
360
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700361} // namespace {}
362
363int main(int argc, char** argv) {
364 // Boilerplate init commands.
365 g_type_init();
Ben Chan46bf5c82013-06-24 11:17:41 -0700366 dbus_threads_init_default();
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700367 chromeos_update_engine::Subprocess::Init();
368 google::ParseCommandLineFlags(&argc, &argv, true);
Andrew de los Reyesada42202010-07-15 22:23:20 -0700369
Jay Srinivasanc1ba09a2012-08-14 14:15:57 -0700370 // Update the status if requested.
371 if (FLAGS_reset_status) {
372 LOG(INFO) << "Setting Update Engine status to idle ...";
373 if (!ResetStatus()) {
374 LOG(ERROR) << "ResetStatus failed.";
375 return 1;
376 }
Gilad Arnold50c60632013-01-25 10:27:19 -0800377 LOG(INFO) << "ResetStatus succeeded; to undo partition table changes run:\n"
378 "(D=$(rootdev -d) P=$(rootdev -s); cgpt p -i$(($(echo ${P#$D} "
379 "| sed 's/^[^0-9]*//')-1)) $D;)";
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700380 }
Darin Petkov58529db2010-08-13 09:19:47 -0700381
Alex Deymof4867c42013-06-28 14:41:39 -0700382 // Changes the current update over cellular network setting.
383 if (!FLAGS_update_over_cellular.empty()) {
384 gboolean allowed = FLAGS_update_over_cellular == "yes";
385 if (!allowed && FLAGS_update_over_cellular != "no") {
386 LOG(ERROR) << "Unknown option: \"" << FLAGS_update_over_cellular
387 << "\". Please specify \"yes\" or \"no\".";
388 } else {
389 SetUpdateOverCellularPermission(allowed);
390 }
391 }
392
393 // Show the current update over cellular network setting.
394 if (FLAGS_show_update_over_cellular) {
395 bool allowed = GetUpdateOverCellularPermission();
396 LOG(INFO) << "Current update over cellular network setting: "
397 << (allowed ? "ENABLED" : "DISABLED");
398 }
399
Chris Sosacb7fa882013-07-25 17:02:59 -0700400 if (!FLAGS_powerwash && !FLAGS_rollback && FLAGS_channel.empty()) {
Chris Sosa192449e2013-10-28 14:16:19 -0700401 LOG(ERROR) << "powerwash flag only makes sense rollback or channel change";
Chris Sosacb7fa882013-07-25 17:02:59 -0700402 return 1;
403 }
404
Alex Deymo5fdf7762013-07-17 20:01:40 -0700405 // Change the P2P enabled setting.
406 if (!FLAGS_p2p_update.empty()) {
407 gboolean enabled = FLAGS_p2p_update == "yes";
408 if (!enabled && FLAGS_p2p_update != "no") {
409 LOG(ERROR) << "Unknown option: \"" << FLAGS_p2p_update
410 << "\". Please specify \"yes\" or \"no\".";
411 } else {
412 SetP2PUpdatePermission(enabled);
413 }
414 }
415
416 // Show the current P2P enabled setting.
417 if (FLAGS_show_p2p_update) {
418 bool enabled = GetP2PUpdatePermission();
419 LOG(INFO) << "Current update using P2P setting: "
420 << (enabled ? "ENABLED" : "DISABLED");
421 }
422
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700423 // First, update the target channel if requested.
424 if (!FLAGS_channel.empty())
Chris Sosacb7fa882013-07-25 17:02:59 -0700425 SetTargetChannel(FLAGS_channel, FLAGS_powerwash);
Darin Petkov8daa3242010-10-25 13:28:47 -0700426
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700427 // Show the current and target channels if requested.
428 if (FLAGS_show_channel) {
429 string current_channel = GetChannel(true);
430 LOG(INFO) << "Current Channel: " << current_channel;
431
432 string target_channel = GetChannel(false);
433 if (!target_channel.empty())
434 LOG(INFO) << "Target Channel (pending update): " << target_channel;
Satoru Takabayashi583667b2010-10-27 13:09:57 +0900435 }
436
Chris Sosad317e402013-06-12 13:47:09 -0700437 bool do_update_request = FLAGS_check_for_update | FLAGS_update |
438 !FLAGS_app_version.empty() | !FLAGS_omaha_url.empty();
Chris Sosa192449e2013-10-28 14:16:19 -0700439 if (FLAGS_update)
440 FLAGS_follow = true;
Chris Sosad317e402013-06-12 13:47:09 -0700441
Chris Sosad317e402013-06-12 13:47:09 -0700442 if (do_update_request && FLAGS_rollback) {
Chris Sosa192449e2013-10-28 14:16:19 -0700443 LOG(ERROR) << "Incompatible flags specified with rollback."
444 << "Rollback should not include update-related flags.";
Chris Sosad317e402013-06-12 13:47:09 -0700445 return 1;
446 }
447
448 if(FLAGS_rollback) {
449 LOG(INFO) << "Requesting rollback.";
450 CHECK(Rollback(FLAGS_powerwash)) << "Request for rollback failed.";
Chris Sosad317e402013-06-12 13:47:09 -0700451 }
452
Darin Petkov58529db2010-08-13 09:19:47 -0700453 // Initiate an update check, if necessary.
Chris Sosad317e402013-06-12 13:47:09 -0700454 if (do_update_request) {
Darin Petkov296889c2010-07-23 16:20:54 -0700455 LOG_IF(WARNING, FLAGS_reboot) << "-reboot flag ignored.";
Darin Petkov58529db2010-08-13 09:19:47 -0700456 string app_version = FLAGS_app_version;
457 if (FLAGS_update && app_version.empty()) {
458 app_version = "ForcedUpdate";
459 LOG(INFO) << "Forcing an update by setting app_version to ForcedUpdate.";
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700460 }
Darin Petkov58529db2010-08-13 09:19:47 -0700461 LOG(INFO) << "Initiating update check and install.";
462 CHECK(CheckForUpdates(app_version, FLAGS_omaha_url))
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700463 << "Update check/initiate update failed.";
Chris Sosa192449e2013-10-28 14:16:19 -0700464 }
Darin Petkov58529db2010-08-13 09:19:47 -0700465
Chris Sosa192449e2013-10-28 14:16:19 -0700466 // These final options are all mutually exclusive with one another.
467 if (FLAGS_follow + FLAGS_watch_for_updates + FLAGS_reboot + FLAGS_status > 1)
468 {
469 LOG(ERROR) << "Multiple exclusive options selected. "
470 << "Select only one of --follow, --watch_for_updates, --reboot, "
471 << "or --status.";
472 return 1;
473 }
474
475 if (FLAGS_status) {
476 LOG(INFO) << "Querying Update Engine status...";
477 if (!GetStatus(NULL)) {
478 LOG(ERROR) << "GetStatus failed.";
Darin Petkov58529db2010-08-13 09:19:47 -0700479 return 1;
480 }
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700481 return 0;
482 }
Darin Petkov58529db2010-08-13 09:19:47 -0700483
Chris Sosa192449e2013-10-28 14:16:19 -0700484 if (FLAGS_follow) {
485 LOG(INFO) << "Waiting for update to complete.";
486 CompleteUpdate(); // Should never return.
487 return 1;
488 }
489
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700490 if (FLAGS_watch_for_updates) {
491 LOG(INFO) << "Watching for status updates.";
492 WatchForUpdates(); // Should never return.
493 return 1;
494 }
Darin Petkov58529db2010-08-13 09:19:47 -0700495
Darin Petkov296889c2010-07-23 16:20:54 -0700496 if (FLAGS_reboot) {
497 LOG(INFO) << "Requesting a reboot...";
498 CHECK(RebootIfNeeded());
499 return 0;
500 }
Andrew de los Reyesada42202010-07-15 22:23:20 -0700501
Darin Petkov8daa3242010-10-25 13:28:47 -0700502 LOG(INFO) << "Done.";
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700503 return 0;
504}