AU: Use Omaha ID rather than MAC address in delta updater

Review URL: http://codereview.chromium.org/467051
diff --git a/omaha_request_prep_action.cc b/omaha_request_prep_action.cc
index 21d5799..8c015d8 100644
--- a/omaha_request_prep_action.cc
+++ b/omaha_request_prep_action.cc
@@ -4,7 +4,9 @@
 
 #include "update_engine/omaha_request_prep_action.h"
 #include <sys/utsname.h>
+#include <errno.h>
 #include <string>
+#include "base/string_util.h"
 #include "update_engine/utils.h"
 
 using std::string;
@@ -12,11 +14,19 @@
 // This gathers local system information and prepares info used by the
 // update check action.
 
+namespace {
+const string OmahaIdPath() {
+  return chromeos_update_engine::utils::kStatefulPartition + "/etc/omaha_id";
+}
+}  // namespace {}
+
 namespace chromeos_update_engine {
 
 void OmahaRequestPrepAction::PerformAction() {
   // TODO(adlr): honor force_full_update_
-  const string machine_id(GetMachineId());
+  ScopedActionCompleter completer(processor_, this);
+  string machine_id;
+  TEST_AND_RETURN(GetMachineId(&machine_id));
   const string version(GetLsbValue("GOOGLE_RELEASE"));
   const string sp(version + "_" + GetMachineType());
   const string track(GetLsbValue("GOOGLE_TRACK"));
@@ -33,28 +43,49 @@
 
   CHECK(HasOutputPipe());
   SetOutputObject(out);
-  processor_->ActionComplete(this, true);
+  completer.set_success(true);
 }
 
-std::string OmahaRequestPrepAction::GetMachineId() const {
-  FILE* fp = popen("/sbin/ifconfig", "r");
-  if (!fp)
-    return "";
-  string data;
-  for (;;) {
-    char buffer[1000];
-    size_t r = fread(buffer, 1, sizeof(buffer), fp);
-    if (r <= 0)
-      break;
-    data.insert(data.end(), buffer, buffer + r);
+namespace {
+const size_t kGuidDataByteLength = 128 / 8;
+const string::size_type kGuidStringLength = 38;
+// Formats 16 bytes (128 bits) of data as a GUID:
+// "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}" where X is a hex digit
+string GuidFromData(const unsigned char data[kGuidDataByteLength]) {
+  return StringPrintf(
+      "{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+      data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
+      data[8], data[9], data[10], data[11], data[12], data[13], data[14],
+      data[15]);
+}
+}
+
+// Returns true on success.
+bool OmahaRequestPrepAction::GetMachineId(std::string* out_id) const {
+  // See if we have an existing Machine ID
+  const string omaha_id_path = root_ + OmahaIdPath();
+  
+  if (utils::ReadFileToString(omaha_id_path, out_id) &&
+      out_id->size() == kGuidStringLength) {
+    return true;
   }
-  fclose(fp);
-  // scan data for MAC address
-  string::size_type pos = data.find(" HWaddr ");
-  if (pos == string::npos)
-    return "";
-  // 3 * 6 - 1 is the number of bytes of the hwaddr.
-  return data.substr(pos + strlen(" HWaddr "), 3 * 6 - 1);
+  
+  // Create a new ID
+  int rand_fd = open("/dev/urandom", O_RDONLY, 0);
+  TEST_AND_RETURN_FALSE_ERRNO(rand_fd >= 0);
+  ScopedFdCloser rand_fd_closer(&rand_fd);
+  unsigned char buf[kGuidDataByteLength];
+  size_t bytes_read = 0;
+  while (bytes_read < sizeof(buf)) {
+    ssize_t rc = read(rand_fd, buf + bytes_read, sizeof(buf) - bytes_read);
+    TEST_AND_RETURN_FALSE_ERRNO(rc > 0);
+    bytes_read += rc;
+  }
+  string guid = GuidFromData(buf);
+  TEST_AND_RETURN_FALSE(
+      utils::WriteFile(omaha_id_path.c_str(), guid.data(), guid.size()));
+  *out_id = guid;
+  return true;
 }
 
 std::string OmahaRequestPrepAction::GetLsbValue(const std::string& key) const {