metrics daemon: create /var/run/metrics/uma-events earlier

The uma-events file needs to be created earlier, for all users of the
metrics library.  This also avoids permission issues with writing
to /var/run/metrics.

BUG=chromium:376891
TEST=manual
CQ-DEPEND=CL:201416

Change-Id: I3a48a3779edb24f3bd08a91fbee4e8fe5a25ec49
Reviewed-on: https://chromium-review.googlesource.com/201347
Tested-by: Luigi Semenzato <semenzato@chromium.org>
Reviewed-by: Jorge Lucangeli Obes <jorgelo@chromium.org>
Commit-Queue: Luigi Semenzato <semenzato@chromium.org>
diff --git a/init/metrics_daemon.conf b/init/metrics_daemon.conf
index 885ab0f..52fe90d 100644
--- a/init/metrics_daemon.conf
+++ b/init/metrics_daemon.conf
@@ -12,11 +12,8 @@
 respawn
 
 pre-start script
-  # Make directories, but don't die on error.  Let someone else complain.
-  LIBDIR=/var/lib/metrics
-  RUNDIR=/var/run/metrics
-  mkdir -p $LIBDIR || logger "metrics_daemon: cannot create $LIBDIR"
-  mkdir -p $RUNDIR || logger "metrics_daemon: cannot create $RUNDIR"
+  # Make directory, but don't die on error.  Let someone else complain.
+  mkdir -p /var/lib/metrics
 end script
 
 expect fork
diff --git a/init/metrics_library.conf b/init/metrics_library.conf
new file mode 100644
index 0000000..6aa49ed
--- /dev/null
+++ b/init/metrics_library.conf
@@ -0,0 +1,19 @@
+# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+description     "Metrics Library upstart file"
+author          "chromium-os-dev@chromium.org"
+
+# The metrics library is used by several programs (daemons and others)
+# to send UMA stats.
+start on starting boot-services
+
+pre-start script
+  # Create the file used as communication endpoint for metrics.
+  RUNDIR=/var/run/metrics
+  EVENTS_FILE=${RUNDIR}/uma-events
+  mkdir -p ${RUNDIR}
+  touch ${EVENTS_FILE}
+  chmod 666 ${EVENTS_FILE}
+end script
diff --git a/metrics_library.cc b/metrics_library.cc
index b15fd49..4fbc1d8 100644
--- a/metrics_library.cc
+++ b/metrics_library.cc
@@ -19,8 +19,6 @@
 
 #include "policy/device_policy.h"
 
-#define READ_WRITE_ALL_FILE_FLAGS \
-  (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 
 static const char kAutotestPath[] = "/var/log/metrics/autotest-events";
@@ -178,21 +176,15 @@
     return false;
   }
   // Use libc here instead of chromium base classes because we need a UNIX fd
-  // for flock.
+  // for flock. |uma_events_file_| must exist already.
   int chrome_fd = HANDLE_EINTR(open(uma_events_file_.c_str(),
-                                    O_WRONLY | O_APPEND | O_CREAT,
-                                    READ_WRITE_ALL_FILE_FLAGS));
+                                    O_WRONLY | O_APPEND));
   // If we failed to open it, return.
   if (chrome_fd < 0) {
     PLOG(ERROR) << uma_events_file_ << ": open";
     return false;
   }
 
-  // Need to chmod because open flags are anded with umask. Ignore the
-  // exit code -- a chronos process may fail chmoding because the file
-  // has been created by a root process but that should be OK.
-  fchmod(chrome_fd, READ_WRITE_ALL_FILE_FLAGS);
-
   // Grab an exclusive lock to protect Chrome from truncating
   // underneath us.
   if (HANDLE_EINTR(flock(chrome_fd, LOCK_EX)) < 0) {
diff --git a/metrics_library_test.cc b/metrics_library_test.cc
index 377495f..82418ed 100644
--- a/metrics_library_test.cc
+++ b/metrics_library_test.cc
@@ -33,6 +33,7 @@
     lib_.Init();
     EXPECT_FALSE(lib_.uma_events_file_.empty());
     lib_.uma_events_file_ = kTestUMAEventsFile.value();
+    EXPECT_EQ(0, WriteFile(kTestUMAEventsFile, "", 0));
     device_policy_ = new policy::MockDevicePolicy();
     EXPECT_CALL(*device_policy_, LoadPolicy())
         .Times(AnyNumber())
@@ -256,6 +257,7 @@
     CMetricsLibraryInit(lib_);
     EXPECT_FALSE(ml.uma_events_file_.empty());
     ml.uma_events_file_ = kTestUMAEventsFile.value();
+    EXPECT_EQ(0, WriteFile(kTestUMAEventsFile, "", 0));
     device_policy_ = new policy::MockDevicePolicy();
     EXPECT_CALL(*device_policy_, LoadPolicy())
         .Times(AnyNumber())