Add futimes, futimesat, and lutimes.

Spotted these while cleaning up <sys/cdefs.h> --- if we remove __USE_XOPEN2K8,
libchrome decides you "must" have futimes. Adding the missing functions (all
just alternative interfaces to utimensat(2) system call) lets us clean up
without breaking anything.

Change-Id: If44fab08ee3de0e31066d650d128a3c96323529b
diff --git a/tests/sys_time_test.cpp b/tests/sys_time_test.cpp
index 18fbe10..e041ba0 100644
--- a/tests/sys_time_test.cpp
+++ b/tests/sys_time_test.cpp
@@ -22,30 +22,113 @@
 
 #include "TemporaryFile.h"
 
-TEST(sys_time, utimes) {
-  timeval tv[2];
-  memset(&tv, 0, sizeof(tv));
+// http://b/11383777
+TEST(sys_time, utimes_nullptr) {
+  TemporaryFile tf;
+  ASSERT_EQ(0, utimes(tf.filename, nullptr));
+}
+
+TEST(sys_time, utimes_EINVAL) {
+  TemporaryFile tf;
+
+  timeval tv[2] = {};
 
   tv[0].tv_usec = -123;
-  ASSERT_EQ(-1, utimes("/", tv));
+  ASSERT_EQ(-1, utimes(tf.filename, tv));
   ASSERT_EQ(EINVAL, errno);
   tv[0].tv_usec = 1234567;
-  ASSERT_EQ(-1, utimes("/", tv));
+  ASSERT_EQ(-1, utimes(tf.filename, tv));
   ASSERT_EQ(EINVAL, errno);
+
   tv[0].tv_usec = 0;
 
   tv[1].tv_usec = -123;
-  ASSERT_EQ(-1, utimes("/", tv));
+  ASSERT_EQ(-1, utimes(tf.filename, tv));
   ASSERT_EQ(EINVAL, errno);
   tv[1].tv_usec = 1234567;
-  ASSERT_EQ(-1, utimes("/", tv));
+  ASSERT_EQ(-1, utimes(tf.filename, tv));
   ASSERT_EQ(EINVAL, errno);
 }
 
-// http://b/11383777
-TEST(sys_time, utimes_NULL) {
+TEST(sys_time, futimes_nullptr) {
   TemporaryFile tf;
-  ASSERT_EQ(0, utimes(tf.filename, NULL));
+  ASSERT_EQ(0, futimes(tf.fd, nullptr));
+}
+
+TEST(sys_time, futimes_EINVAL) {
+  TemporaryFile tf;
+
+  timeval tv[2] = {};
+
+  tv[0].tv_usec = -123;
+  ASSERT_EQ(-1, futimes(tf.fd, tv));
+  ASSERT_EQ(EINVAL, errno);
+  tv[0].tv_usec = 1234567;
+  ASSERT_EQ(-1, futimes(tf.fd, tv));
+  ASSERT_EQ(EINVAL, errno);
+
+  tv[0].tv_usec = 0;
+
+  tv[1].tv_usec = -123;
+  ASSERT_EQ(-1, futimes(tf.fd, tv));
+  ASSERT_EQ(EINVAL, errno);
+  tv[1].tv_usec = 1234567;
+  ASSERT_EQ(-1, futimes(tf.fd, tv));
+  ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(sys_time, futimesat_nullptr) {
+  TemporaryFile tf;
+  ASSERT_EQ(0, futimesat(AT_FDCWD, tf.filename, nullptr));
+}
+
+TEST(sys_time, futimesat_EINVAL) {
+  TemporaryFile tf;
+
+  timeval tv[2] = {};
+
+  tv[0].tv_usec = -123;
+  ASSERT_EQ(-1, futimesat(AT_FDCWD, tf.filename, tv));
+  ASSERT_EQ(EINVAL, errno);
+  tv[0].tv_usec = 1234567;
+  ASSERT_EQ(-1, futimesat(AT_FDCWD, tf.filename, tv));
+  ASSERT_EQ(EINVAL, errno);
+
+  tv[0].tv_usec = 0;
+
+  tv[1].tv_usec = -123;
+  ASSERT_EQ(-1, futimesat(AT_FDCWD, tf.filename, tv));
+  ASSERT_EQ(EINVAL, errno);
+  tv[1].tv_usec = 1234567;
+  ASSERT_EQ(-1, futimesat(AT_FDCWD, tf.filename, tv));
+  ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(sys_time, lutimes_nullptr) {
+  TemporaryFile tf;
+  ASSERT_EQ(0, lutimes(tf.filename, nullptr));
+}
+
+TEST(sys_time, lutimes_EINVAL) {
+  TemporaryFile tf;
+
+  timeval tv[2] = {};
+
+  tv[0].tv_usec = -123;
+  ASSERT_EQ(-1, lutimes(tf.filename, tv));
+  ASSERT_EQ(EINVAL, errno);
+  tv[0].tv_usec = 1234567;
+  ASSERT_EQ(-1, lutimes(tf.filename, tv));
+  ASSERT_EQ(EINVAL, errno);
+
+  tv[0].tv_usec = 0;
+
+  tv[1].tv_usec = -123;
+  ASSERT_EQ(-1, lutimes(tf.filename, tv));
+  ASSERT_EQ(EINVAL, errno);
+  tv[1].tv_usec = 1234567;
+  ASSERT_EQ(-1, lutimes(tf.filename, tv));
+  ASSERT_EQ(EINVAL, errno);
 }
 
 TEST(sys_time, gettimeofday) {