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 |