blob: 3ee2a2a670ef2b5bb48b3e3c38231e13f394820a [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.");
Alex Vakulenko59e253e2014-02-24 10:40:21 -080045DEFINE_bool(can_rollback, false, "Shows whether rollback partition "
46 "is available.");
Chris Sosad317e402013-06-12 13:47:09 -070047DEFINE_bool(show_channel, false, "Show the current and target channels.");
Chris Sosa192449e2013-10-28 14:16:19 -070048DEFINE_bool(show_p2p_update, false,
49 "Show the current setting for peer-to-peer update sharing.");
Alex Deymof4867c42013-06-28 14:41:39 -070050DEFINE_bool(show_update_over_cellular, false,
51 "Show the current setting for updates over cellular networks.");
Chris Sosa192449e2013-10-28 14:16:19 -070052DEFINE_bool(status, false, "Print the status to stdout.");
53DEFINE_bool(update, false, "Forces an update and waits for it to complete. "
54 "Implies --follow.");
Alex Deymof4867c42013-06-28 14:41:39 -070055DEFINE_string(update_over_cellular, "",
56 "Enables (\"yes\") or disables (\"no\") the updates over "
57 "cellular networks.");
Chris Sosa192449e2013-10-28 14:16:19 -070058DEFINE_bool(watch_for_updates, false,
59 "Listen for status updates and print them to the screen.");
Alex Vakulenkodea2eac2014-03-14 15:56:59 -070060DEFINE_bool(prev_version, false,
61 "Show the previous OS version used before the update reboot.");
Alex Vakulenko2bddadd2014-03-27 13:23:46 -070062DEFINE_bool(show_kernels, false, "Show the list of kernel patritions and "
63 "whether each of them is bootable or not");
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070064
65namespace {
66
Andrew de los Reyes63b96d72010-05-10 13:08:54 -070067bool GetProxy(DBusGProxy** out_proxy) {
68 DBusGConnection* bus;
Andrew de los Reyes68ab6ed2011-08-09 14:46:39 -070069 DBusGProxy* proxy = NULL;
Andrew de los Reyes63b96d72010-05-10 13:08:54 -070070 GError* error = NULL;
Andrew de los Reyes68ab6ed2011-08-09 14:46:39 -070071 const int kTries = 4;
Darin Petkova0b9e772011-10-06 05:05:56 -070072 const int kRetrySeconds = 10;
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070073
74 bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
Richard Barnetted7936062013-01-18 13:38:51 -080075 if (bus == NULL) {
76 LOG(ERROR) << "Failed to get bus: " << GetAndFreeGError(&error);
77 exit(1);
78 }
Andrew de los Reyes68ab6ed2011-08-09 14:46:39 -070079 for (int i = 0; !proxy && i < kTries; ++i) {
Darin Petkova0b9e772011-10-06 05:05:56 -070080 if (i > 0) {
81 LOG(INFO) << "Retrying to get dbus proxy. Try "
82 << (i + 1) << "/" << kTries;
Gilad Arnold8e3f1262013-01-08 14:59:54 -080083 g_usleep(kRetrySeconds * G_USEC_PER_SEC);
Darin Petkova0b9e772011-10-06 05:05:56 -070084 }
Andrew de los Reyes68ab6ed2011-08-09 14:46:39 -070085 proxy = dbus_g_proxy_new_for_name_owner(bus,
86 kUpdateEngineServiceName,
87 kUpdateEngineServicePath,
88 kUpdateEngineServiceInterface,
89 &error);
Darin Petkova0b9e772011-10-06 05:05:56 -070090 LOG_IF(WARNING, !proxy) << "Error getting dbus proxy for "
91 << kUpdateEngineServiceName << ": "
92 << GetAndFreeGError(&error);
Andrew de los Reyes68ab6ed2011-08-09 14:46:39 -070093 }
Richard Barnetted7936062013-01-18 13:38:51 -080094 if (proxy == NULL) {
95 LOG(ERROR) << "Giving up -- unable to get dbus proxy for "
96 << kUpdateEngineServiceName;
97 exit(1);
98 }
Andrew de los Reyes63b96d72010-05-10 13:08:54 -070099 *out_proxy = proxy;
100 return true;
101}
102
103static void StatusUpdateSignalHandler(DBusGProxy* proxy,
104 int64_t last_checked_time,
105 double progress,
106 gchar* current_operation,
107 gchar* new_version,
108 int64_t new_size,
109 void* user_data) {
110 LOG(INFO) << "Got status update:";
111 LOG(INFO) << " last_checked_time: " << last_checked_time;
112 LOG(INFO) << " progress: " << progress;
113 LOG(INFO) << " current_operation: " << current_operation;
114 LOG(INFO) << " new_version: " << new_version;
115 LOG(INFO) << " new_size: " << new_size;
116}
117
Jay Srinivasanc1ba09a2012-08-14 14:15:57 -0700118bool ResetStatus() {
119 DBusGProxy* proxy;
120 GError* error = NULL;
121
122 CHECK(GetProxy(&proxy));
123
Alex Deymo36dc2f32013-08-29 15:45:06 -0700124 gboolean rc = update_engine_client_reset_status(proxy, &error);
Jay Srinivasanc1ba09a2012-08-14 14:15:57 -0700125 return rc;
126}
127
128
Darin Petkov58529db2010-08-13 09:19:47 -0700129// If |op| is non-NULL, sets it to the current operation string or an
130// empty string if unable to obtain the current status.
131bool GetStatus(string* op) {
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700132 DBusGProxy* proxy;
133 GError* error = NULL;
Andrew de los Reyesada42202010-07-15 22:23:20 -0700134
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700135 CHECK(GetProxy(&proxy));
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700136
137 gint64 last_checked_time = 0;
138 gdouble progress = 0.0;
139 char* current_op = NULL;
140 char* new_version = NULL;
141 gint64 new_size = 0;
142
Alex Deymo36dc2f32013-08-29 15:45:06 -0700143 gboolean rc = update_engine_client_get_status(proxy,
144 &last_checked_time,
145 &progress,
146 &current_op,
147 &new_version,
148 &new_size,
149 &error);
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700150 if (rc == FALSE) {
Darin Petkova0b9e772011-10-06 05:05:56 -0700151 LOG(INFO) << "Error getting status: " << GetAndFreeGError(&error);
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700152 }
153 printf("LAST_CHECKED_TIME=%" PRIi64 "\nPROGRESS=%f\nCURRENT_OP=%s\n"
154 "NEW_VERSION=%s\nNEW_SIZE=%" PRIi64 "\n",
155 last_checked_time,
156 progress,
157 current_op,
158 new_version,
159 new_size);
Darin Petkov58529db2010-08-13 09:19:47 -0700160 if (op) {
161 *op = current_op ? current_op : "";
162 }
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700163 return true;
164}
165
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700166// Should never return.
167void WatchForUpdates() {
168 DBusGProxy* proxy;
Andrew de los Reyesada42202010-07-15 22:23:20 -0700169
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700170 CHECK(GetProxy(&proxy));
Andrew de los Reyesada42202010-07-15 22:23:20 -0700171
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700172 // Register marshaller
173 dbus_g_object_register_marshaller(
Alex Deymo3d41c4d2014-02-13 23:26:33 -0800174 NULL,
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700175 G_TYPE_NONE,
176 G_TYPE_INT64,
177 G_TYPE_DOUBLE,
178 G_TYPE_STRING,
179 G_TYPE_STRING,
180 G_TYPE_INT64,
181 G_TYPE_INVALID);
Andrew de los Reyesada42202010-07-15 22:23:20 -0700182
183 static const char kStatusUpdate[] = "StatusUpdate";
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700184 dbus_g_proxy_add_signal(proxy,
Andrew de los Reyesada42202010-07-15 22:23:20 -0700185 kStatusUpdate,
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700186 G_TYPE_INT64,
187 G_TYPE_DOUBLE,
188 G_TYPE_STRING,
189 G_TYPE_STRING,
190 G_TYPE_INT64,
191 G_TYPE_INVALID);
192 GMainLoop* loop = g_main_loop_new (NULL, TRUE);
193 dbus_g_proxy_connect_signal(proxy,
Andrew de los Reyesada42202010-07-15 22:23:20 -0700194 kStatusUpdate,
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700195 G_CALLBACK(StatusUpdateSignalHandler),
196 NULL,
197 NULL);
198 g_main_loop_run(loop);
199 g_main_loop_unref(loop);
200}
201
Chris Sosad317e402013-06-12 13:47:09 -0700202bool Rollback(bool rollback) {
203 DBusGProxy* proxy;
204 GError* error = NULL;
205
206 CHECK(GetProxy(&proxy));
207
Alex Deymo36dc2f32013-08-29 15:45:06 -0700208 gboolean rc = update_engine_client_attempt_rollback(proxy,
209 rollback,
210 &error);
Chris Sosad317e402013-06-12 13:47:09 -0700211 CHECK_EQ(rc, TRUE) << "Error with rollback request: "
212 << GetAndFreeGError(&error);
213 return true;
214}
215
Alex Vakulenko2bddadd2014-03-27 13:23:46 -0700216std::string GetRollbackPartition() {
Alex Vakulenko59e253e2014-02-24 10:40:21 -0800217 DBusGProxy* proxy;
218 GError* error = NULL;
219
220 CHECK(GetProxy(&proxy));
221
Alex Vakulenko2bddadd2014-03-27 13:23:46 -0700222 char* rollback_partition = nullptr;
223 gboolean rc = update_engine_client_get_rollback_partition(proxy,
224 &rollback_partition,
225 &error);
Alex Vakulenko59e253e2014-02-24 10:40:21 -0800226 CHECK_EQ(rc, TRUE) << "Error while querying rollback partition availabilty: "
227 << GetAndFreeGError(&error);
Alex Vakulenko2bddadd2014-03-27 13:23:46 -0700228 std::string partition = rollback_partition;
229 g_free(rollback_partition);
230 return partition;
Alex Vakulenko59e253e2014-02-24 10:40:21 -0800231}
Alex Vakulenko2bddadd2014-03-27 13:23:46 -0700232
233std::string GetKernelDevices() {
234 DBusGProxy* proxy;
235 GError* error = nullptr;
236
237 CHECK(GetProxy(&proxy));
238
239 char* kernel_devices = nullptr;
240 gboolean rc = update_engine_client_get_kernel_devices(proxy,
241 &kernel_devices,
242 &error);
243 CHECK_EQ(rc, TRUE) << "Error while getting a list of kernel devices: "
244 << GetAndFreeGError(&error);
245 std::string devices = kernel_devices;
246 g_free(kernel_devices);
247 return devices;
248}
249
Darin Petkov58529db2010-08-13 09:19:47 -0700250bool CheckForUpdates(const string& app_version, const string& omaha_url) {
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700251 DBusGProxy* proxy;
252 GError* error = NULL;
Andrew de los Reyesada42202010-07-15 22:23:20 -0700253
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700254 CHECK(GetProxy(&proxy));
255
David Zeuthen75a4c3e2013-09-06 11:36:59 -0700256 AttemptUpdateFlags flags = static_cast<AttemptUpdateFlags>(
257 FLAGS_interactive ? 0 : kAttemptUpdateFlagNonInteractive);
258 gboolean rc =
259 update_engine_client_attempt_update_with_flags(proxy,
260 app_version.c_str(),
261 omaha_url.c_str(),
262 static_cast<gint>(flags),
263 &error);
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700264 CHECK_EQ(rc, TRUE) << "Error checking for update: "
Darin Petkova0b9e772011-10-06 05:05:56 -0700265 << GetAndFreeGError(&error);
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700266 return true;
267}
268
Darin Petkov296889c2010-07-23 16:20:54 -0700269bool RebootIfNeeded() {
270 DBusGProxy* proxy;
271 GError* error = NULL;
272
273 CHECK(GetProxy(&proxy));
274
275 gboolean rc =
Alex Deymo36dc2f32013-08-29 15:45:06 -0700276 update_engine_client_reboot_if_needed(proxy, &error);
Darin Petkov296889c2010-07-23 16:20:54 -0700277 // Reboot error code doesn't necessarily mean that a reboot
278 // failed. For example, D-Bus may be shutdown before we receive the
279 // result.
Darin Petkova0b9e772011-10-06 05:05:56 -0700280 LOG_IF(INFO, !rc) << "Reboot error message: " << GetAndFreeGError(&error);
Darin Petkov296889c2010-07-23 16:20:54 -0700281 return true;
282}
283
Chris Sosacb7fa882013-07-25 17:02:59 -0700284void SetTargetChannel(const string& target_channel, bool allow_powerwash) {
Darin Petkov8daa3242010-10-25 13:28:47 -0700285 DBusGProxy* proxy;
286 GError* error = NULL;
287
288 CHECK(GetProxy(&proxy));
289
Alex Deymo36dc2f32013-08-29 15:45:06 -0700290 gboolean rc = update_engine_client_set_channel(proxy,
291 target_channel.c_str(),
292 allow_powerwash,
293 &error);
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700294 CHECK_EQ(rc, true) << "Error setting the channel: "
Darin Petkova0b9e772011-10-06 05:05:56 -0700295 << GetAndFreeGError(&error);
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700296 LOG(INFO) << "Channel permanently set to: " << target_channel;
Darin Petkov8daa3242010-10-25 13:28:47 -0700297}
298
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700299string GetChannel(bool get_current_channel) {
Satoru Takabayashi583667b2010-10-27 13:09:57 +0900300 DBusGProxy* proxy;
301 GError* error = NULL;
302
303 CHECK(GetProxy(&proxy));
304
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700305 char* channel = NULL;
Alex Deymo36dc2f32013-08-29 15:45:06 -0700306 gboolean rc = update_engine_client_get_channel(proxy,
307 get_current_channel,
308 &channel,
309 &error);
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700310 CHECK_EQ(rc, true) << "Error getting the channel: "
311 << GetAndFreeGError(&error);
312 string output = channel;
313 g_free(channel);
Satoru Takabayashi583667b2010-10-27 13:09:57 +0900314 return output;
315}
316
Alex Deymo5fdf7762013-07-17 20:01:40 -0700317void SetUpdateOverCellularPermission(gboolean allowed) {
Alex Deymof4867c42013-06-28 14:41:39 -0700318 DBusGProxy* proxy;
319 GError* error = NULL;
320
321 CHECK(GetProxy(&proxy));
322
Alex Deymo36dc2f32013-08-29 15:45:06 -0700323 gboolean rc = update_engine_client_set_update_over_cellular_permission(
324 proxy,
325 allowed,
326 &error);
Alex Deymof4867c42013-06-28 14:41:39 -0700327 CHECK_EQ(rc, true) << "Error setting the update over cellular setting: "
328 << GetAndFreeGError(&error);
Alex Deymof4867c42013-06-28 14:41:39 -0700329}
330
331bool GetUpdateOverCellularPermission() {
332 DBusGProxy* proxy;
333 GError* error = NULL;
334
335 CHECK(GetProxy(&proxy));
336
337 gboolean allowed;
Alex Deymo36dc2f32013-08-29 15:45:06 -0700338 gboolean rc = update_engine_client_get_update_over_cellular_permission(
339 proxy,
340 &allowed,
341 &error);
Alex Deymof4867c42013-06-28 14:41:39 -0700342 CHECK_EQ(rc, true) << "Error getting the update over cellular setting: "
343 << GetAndFreeGError(&error);
344 return allowed;
345}
346
Alex Deymo5fdf7762013-07-17 20:01:40 -0700347void SetP2PUpdatePermission(gboolean enabled) {
348 DBusGProxy* proxy;
349 GError* error = NULL;
350
351 CHECK(GetProxy(&proxy));
352
Alex Deymo36dc2f32013-08-29 15:45:06 -0700353 gboolean rc = update_engine_client_set_p2p_update_permission(
354 proxy,
355 enabled,
356 &error);
Alex Deymo5fdf7762013-07-17 20:01:40 -0700357 CHECK_EQ(rc, true) << "Error setting the peer-to-peer update setting: "
358 << GetAndFreeGError(&error);
359}
360
361bool GetP2PUpdatePermission() {
362 DBusGProxy* proxy;
363 GError* error = NULL;
364
365 CHECK(GetProxy(&proxy));
366
367 gboolean enabled;
Alex Deymo36dc2f32013-08-29 15:45:06 -0700368 gboolean rc = update_engine_client_get_p2p_update_permission(
369 proxy,
370 &enabled,
371 &error);
Alex Deymo5fdf7762013-07-17 20:01:40 -0700372 CHECK_EQ(rc, true) << "Error getting the peer-to-peer update setting: "
373 << GetAndFreeGError(&error);
374 return enabled;
375}
376
Darin Petkov58529db2010-08-13 09:19:47 -0700377static gboolean CompleteUpdateSource(gpointer data) {
378 string current_op;
379 if (!GetStatus(&current_op) || current_op == "UPDATE_STATUS_IDLE") {
380 LOG(ERROR) << "Update failed.";
381 exit(1);
382 }
383 if (current_op == "UPDATE_STATUS_UPDATED_NEED_REBOOT") {
384 LOG(INFO) << "Update succeeded -- reboot needed.";
385 exit(0);
386 }
387 return TRUE;
388}
389
390// This is similar to watching for updates but rather than registering
391// a signal watch, activelly poll the daemon just in case it stops
392// sending notifications.
393void CompleteUpdate() {
394 GMainLoop* loop = g_main_loop_new (NULL, TRUE);
395 g_timeout_add_seconds(5, CompleteUpdateSource, NULL);
396 g_main_loop_run(loop);
397 g_main_loop_unref(loop);
398}
399
Alex Vakulenkodea2eac2014-03-14 15:56:59 -0700400void ShowPrevVersion() {
401 DBusGProxy* proxy;
402 GError* error = nullptr;
403
404 CHECK(GetProxy(&proxy));
405
406 char* prev_version = nullptr;
407
408 gboolean rc = update_engine_client_get_prev_version(proxy,
409 &prev_version,
410 &error);
411 if (!rc) {
412 LOG(ERROR) << "Error getting previous version: "
413 << GetAndFreeGError(&error);
414 } else {
415 LOG(INFO) << "Previous version = " << prev_version;
416 g_free(prev_version);
417 }
418}
419
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700420} // namespace {}
421
422int main(int argc, char** argv) {
423 // Boilerplate init commands.
424 g_type_init();
Ben Chan46bf5c82013-06-24 11:17:41 -0700425 dbus_threads_init_default();
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700426 chromeos_update_engine::Subprocess::Init();
427 google::ParseCommandLineFlags(&argc, &argv, true);
Andrew de los Reyesada42202010-07-15 22:23:20 -0700428
Jay Srinivasanc1ba09a2012-08-14 14:15:57 -0700429 // Update the status if requested.
430 if (FLAGS_reset_status) {
431 LOG(INFO) << "Setting Update Engine status to idle ...";
432 if (!ResetStatus()) {
433 LOG(ERROR) << "ResetStatus failed.";
434 return 1;
435 }
Gilad Arnold50c60632013-01-25 10:27:19 -0800436 LOG(INFO) << "ResetStatus succeeded; to undo partition table changes run:\n"
437 "(D=$(rootdev -d) P=$(rootdev -s); cgpt p -i$(($(echo ${P#$D} "
438 "| sed 's/^[^0-9]*//')-1)) $D;)";
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700439 }
Darin Petkov58529db2010-08-13 09:19:47 -0700440
Alex Deymof4867c42013-06-28 14:41:39 -0700441 // Changes the current update over cellular network setting.
442 if (!FLAGS_update_over_cellular.empty()) {
443 gboolean allowed = FLAGS_update_over_cellular == "yes";
444 if (!allowed && FLAGS_update_over_cellular != "no") {
445 LOG(ERROR) << "Unknown option: \"" << FLAGS_update_over_cellular
446 << "\". Please specify \"yes\" or \"no\".";
447 } else {
448 SetUpdateOverCellularPermission(allowed);
449 }
450 }
451
452 // Show the current update over cellular network setting.
453 if (FLAGS_show_update_over_cellular) {
454 bool allowed = GetUpdateOverCellularPermission();
455 LOG(INFO) << "Current update over cellular network setting: "
456 << (allowed ? "ENABLED" : "DISABLED");
457 }
458
Chris Sosacb7fa882013-07-25 17:02:59 -0700459 if (!FLAGS_powerwash && !FLAGS_rollback && FLAGS_channel.empty()) {
Chris Sosa192449e2013-10-28 14:16:19 -0700460 LOG(ERROR) << "powerwash flag only makes sense rollback or channel change";
Chris Sosacb7fa882013-07-25 17:02:59 -0700461 return 1;
462 }
463
Alex Deymo5fdf7762013-07-17 20:01:40 -0700464 // Change the P2P enabled setting.
465 if (!FLAGS_p2p_update.empty()) {
466 gboolean enabled = FLAGS_p2p_update == "yes";
467 if (!enabled && FLAGS_p2p_update != "no") {
468 LOG(ERROR) << "Unknown option: \"" << FLAGS_p2p_update
469 << "\". Please specify \"yes\" or \"no\".";
470 } else {
471 SetP2PUpdatePermission(enabled);
472 }
473 }
474
Alex Vakulenko59e253e2014-02-24 10:40:21 -0800475 // Show the rollback availability.
476 if (FLAGS_can_rollback) {
Alex Vakulenko2bddadd2014-03-27 13:23:46 -0700477 std::string rollback_partition = GetRollbackPartition();
478 if (rollback_partition.empty())
479 rollback_partition = "UNAVAILABLE";
480 else
481 rollback_partition = "AVAILABLE: " + rollback_partition;
482
483 LOG(INFO) << "Rollback partition: " << rollback_partition;
Alex Vakulenko59e253e2014-02-24 10:40:21 -0800484 }
485
Alex Deymo5fdf7762013-07-17 20:01:40 -0700486 // Show the current P2P enabled setting.
487 if (FLAGS_show_p2p_update) {
488 bool enabled = GetP2PUpdatePermission();
489 LOG(INFO) << "Current update using P2P setting: "
490 << (enabled ? "ENABLED" : "DISABLED");
491 }
492
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700493 // First, update the target channel if requested.
494 if (!FLAGS_channel.empty())
Chris Sosacb7fa882013-07-25 17:02:59 -0700495 SetTargetChannel(FLAGS_channel, FLAGS_powerwash);
Darin Petkov8daa3242010-10-25 13:28:47 -0700496
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700497 // Show the current and target channels if requested.
498 if (FLAGS_show_channel) {
499 string current_channel = GetChannel(true);
500 LOG(INFO) << "Current Channel: " << current_channel;
501
502 string target_channel = GetChannel(false);
503 if (!target_channel.empty())
504 LOG(INFO) << "Target Channel (pending update): " << target_channel;
Satoru Takabayashi583667b2010-10-27 13:09:57 +0900505 }
506
Chris Sosad317e402013-06-12 13:47:09 -0700507 bool do_update_request = FLAGS_check_for_update | FLAGS_update |
508 !FLAGS_app_version.empty() | !FLAGS_omaha_url.empty();
Chris Sosa192449e2013-10-28 14:16:19 -0700509 if (FLAGS_update)
510 FLAGS_follow = true;
Chris Sosad317e402013-06-12 13:47:09 -0700511
Chris Sosad317e402013-06-12 13:47:09 -0700512 if (do_update_request && FLAGS_rollback) {
Chris Sosa192449e2013-10-28 14:16:19 -0700513 LOG(ERROR) << "Incompatible flags specified with rollback."
514 << "Rollback should not include update-related flags.";
Chris Sosad317e402013-06-12 13:47:09 -0700515 return 1;
516 }
517
518 if(FLAGS_rollback) {
519 LOG(INFO) << "Requesting rollback.";
520 CHECK(Rollback(FLAGS_powerwash)) << "Request for rollback failed.";
Chris Sosad317e402013-06-12 13:47:09 -0700521 }
522
Darin Petkov58529db2010-08-13 09:19:47 -0700523 // Initiate an update check, if necessary.
Chris Sosad317e402013-06-12 13:47:09 -0700524 if (do_update_request) {
Darin Petkov296889c2010-07-23 16:20:54 -0700525 LOG_IF(WARNING, FLAGS_reboot) << "-reboot flag ignored.";
Darin Petkov58529db2010-08-13 09:19:47 -0700526 string app_version = FLAGS_app_version;
527 if (FLAGS_update && app_version.empty()) {
528 app_version = "ForcedUpdate";
529 LOG(INFO) << "Forcing an update by setting app_version to ForcedUpdate.";
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700530 }
Darin Petkov58529db2010-08-13 09:19:47 -0700531 LOG(INFO) << "Initiating update check and install.";
532 CHECK(CheckForUpdates(app_version, FLAGS_omaha_url))
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700533 << "Update check/initiate update failed.";
Chris Sosa192449e2013-10-28 14:16:19 -0700534 }
Darin Petkov58529db2010-08-13 09:19:47 -0700535
Chris Sosa192449e2013-10-28 14:16:19 -0700536 // These final options are all mutually exclusive with one another.
537 if (FLAGS_follow + FLAGS_watch_for_updates + FLAGS_reboot + FLAGS_status > 1)
538 {
539 LOG(ERROR) << "Multiple exclusive options selected. "
540 << "Select only one of --follow, --watch_for_updates, --reboot, "
541 << "or --status.";
542 return 1;
543 }
544
545 if (FLAGS_status) {
546 LOG(INFO) << "Querying Update Engine status...";
547 if (!GetStatus(NULL)) {
548 LOG(ERROR) << "GetStatus failed.";
Darin Petkov58529db2010-08-13 09:19:47 -0700549 return 1;
550 }
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700551 return 0;
552 }
Darin Petkov58529db2010-08-13 09:19:47 -0700553
Chris Sosa192449e2013-10-28 14:16:19 -0700554 if (FLAGS_follow) {
555 LOG(INFO) << "Waiting for update to complete.";
556 CompleteUpdate(); // Should never return.
557 return 1;
558 }
559
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700560 if (FLAGS_watch_for_updates) {
561 LOG(INFO) << "Watching for status updates.";
562 WatchForUpdates(); // Should never return.
563 return 1;
564 }
Darin Petkov58529db2010-08-13 09:19:47 -0700565
Darin Petkov296889c2010-07-23 16:20:54 -0700566 if (FLAGS_reboot) {
567 LOG(INFO) << "Requesting a reboot...";
568 CHECK(RebootIfNeeded());
569 return 0;
570 }
Andrew de los Reyesada42202010-07-15 22:23:20 -0700571
Alex Vakulenkodea2eac2014-03-14 15:56:59 -0700572 if (FLAGS_prev_version) {
573 ShowPrevVersion();
574 }
575
Alex Vakulenko2bddadd2014-03-27 13:23:46 -0700576 if (FLAGS_show_kernels) {
577 LOG(INFO) << "Kernel partitions:\n"
578 << GetKernelDevices();
579 }
580
Darin Petkov8daa3242010-10-25 13:28:47 -0700581 LOG(INFO) << "Done.";
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700582 return 0;
583}