Merge "bionic tests: migrate gethostname test to unistd_test.cpp from system/extras"
diff --git a/libc/include/dirent.h b/libc/include/dirent.h
index a849a61..4ca3a7d 100644
--- a/libc/include/dirent.h
+++ b/libc/include/dirent.h
@@ -58,6 +58,12 @@
 
 #undef __DIRENT64_BODY
 
+/* glibc compatibility. */
+#undef _DIRENT_HAVE_D_NAMLEN /* Linux doesn't have a d_namlen field. */
+#define _DIRENT_HAVE_D_RECLEN
+#define _DIRENT_HAVE_D_OFF
+#define _DIRENT_HAVE_D_TYPE
+
 #define d_fileno d_ino
 
 typedef struct DIR DIR;
diff --git a/libc/include/sys/_system_properties.h b/libc/include/sys/_system_properties.h
index 5a681df..0349e4c 100644
--- a/libc/include/sys/_system_properties.h
+++ b/libc/include/sys/_system_properties.h
@@ -81,6 +81,7 @@
 #define PROP_PATH_RAMDISK_DEFAULT  "/default.prop"
 #define PROP_PATH_SYSTEM_BUILD     "/system/build.prop"
 #define PROP_PATH_SYSTEM_DEFAULT   "/system/default.prop"
+#define PROP_PATH_VENDOR_BUILD     "/vendor/build.prop"
 #define PROP_PATH_LOCAL_OVERRIDE   "/data/local.prop"
 #define PROP_PATH_FACTORY          "/factory/factory.prop"
 
diff --git a/libc/include/sys/stat.h b/libc/include/sys/stat.h
index 7085ed9..7d85dd1 100644
--- a/libc/include/sys/stat.h
+++ b/libc/include/sys/stat.h
@@ -129,10 +129,6 @@
 #define st_atimensec st_atim.tv_nsec
 #define st_mtimensec st_mtim.tv_nsec
 #define st_ctimensec st_ctim.tv_nsec
-/* Compatibility with the kernel and older versions of bionic. */
-#define st_atime_nsec st_atim.tv_nsec
-#define st_mtime_nsec st_mtim.tv_nsec
-#define st_ctime_nsec st_ctim.tv_nsec
 
 #ifdef __USE_BSD
 /* Permission macros provided by glibc for compatibility with BSDs. */
diff --git a/libc/private/bionic_macros.h b/libc/private/bionic_macros.h
index 491b3ac..4f3cf89 100644
--- a/libc/private/bionic_macros.h
+++ b/libc/private/bionic_macros.h
@@ -17,11 +17,16 @@
 #ifndef _BIONIC_MACROS_H_
 #define _BIONIC_MACROS_H_
 
+// Frameworks OpenGL code currently leaks this header and allows
+// collisions with other declarations, e.g., from libnativehelper.
+// TODO: Remove once cleaned up. b/18334516
+#if !defined(DISALLOW_COPY_AND_ASSIGN)
 // DISALLOW_COPY_AND_ASSIGN disallows the copy and operator= functions.
 // It goes in the private: declarations in a class.
 #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
   TypeName(const TypeName&) = delete;      \
   void operator=(const TypeName&) = delete
+#endif  // !defined(DISALLOW_COPY_AND_ASSIGN)
 
 // A macro to disallow all the implicit constructors, namely the
 // default constructor, copy constructor and operator= functions.
diff --git a/libc/tools/zoneinfo/ZoneCompactor.java b/libc/tools/zoneinfo/ZoneCompactor.java
index bf3153e..2d598fe 100644
--- a/libc/tools/zoneinfo/ZoneCompactor.java
+++ b/libc/tools/zoneinfo/ZoneCompactor.java
@@ -132,9 +132,15 @@
         throw new RuntimeException("zone filename too long: " + zoneName.length());
       }
 
+      // Follow the chain of links to work out where the real data for this zone lives.
+      String actualZoneName = zoneName;
+      while (links.get(actualZoneName) != null) {
+        actualZoneName = links.get(actualZoneName);
+      }
+
       f.write(toAscii(new byte[MAXNAME], zoneName));
-      f.writeInt(offsets.get(zoneName));
-      f.writeInt(lengths.get(zoneName));
+      f.writeInt(offsets.get(actualZoneName));
+      f.writeInt(lengths.get(actualZoneName));
       f.writeInt(0); // Used to be raw GMT offset. No longer used.
     }
 
diff --git a/libc/tools/zoneinfo/update-tzdata.py b/libc/tools/zoneinfo/update-tzdata.py
index f5681be..330f166 100755
--- a/libc/tools/zoneinfo/update-tzdata.py
+++ b/libc/tools/zoneinfo/update-tzdata.py
@@ -13,8 +13,11 @@
 import tarfile
 import tempfile
 
-regions = ['africa', 'antarctica', 'asia', 'australasia', 'backward',
-           'etcetera', 'europe', 'northamerica', 'southamerica']
+regions = ['africa', 'antarctica', 'asia', 'australasia',
+           'etcetera', 'europe', 'northamerica', 'southamerica',
+           # These two deliberately come last so they override what came
+           # before (and each other).
+           'backward', 'backzone' ]
 
 def CheckDirExists(dir, dirname):
   if not os.path.isdir(dir):
@@ -49,16 +52,16 @@
       fields = line.split()
       if fields:
         if fields[0] == 'Link':
-          links.append('%s %s %s\n' % (fields[0], fields[1], fields[2]))
+          links.append('%s %s %s' % (fields[0], fields[1], fields[2]))
           zones.append(fields[2])
         elif fields[0] == 'Zone':
           zones.append(fields[1])
   zones.sort()
 
   setup = open('setup', 'w')
-  for link in links:
-    setup.write(link)
-  for zone in zones:
+  for link in sorted(set(links)):
+    setup.write('%s\n' % link)
+  for zone in sorted(set(zones)):
     setup.write('%s\n' % zone)
   setup.close()
 
@@ -165,9 +168,10 @@
 
   print 'Calling zic(1)...'
   os.mkdir('data')
-  for region in regions:
-    if region != 'backward':
-      subprocess.check_call(['zic', '-d', 'data', 'extracted/%s' % region])
+  zic_inputs = [ 'extracted/%s' % x for x in regions ]
+  zic_cmd = ['zic', '-d', 'data' ]
+  zic_cmd.extend(zic_inputs)
+  subprocess.check_call(zic_cmd)
 
   WriteSetupFile()
 
diff --git a/libc/zoneinfo/tzdata b/libc/zoneinfo/tzdata
index e9cf164..fc6c5ba 100644
--- a/libc/zoneinfo/tzdata
+++ b/libc/zoneinfo/tzdata
Binary files differ
diff --git a/tests/string_test.cpp b/tests/string_test.cpp
index 6ecbb64..137565e 100644
--- a/tests/string_test.cpp
+++ b/tests/string_test.cpp
@@ -25,6 +25,11 @@
 
 #include "buffer_tests.h"
 
+#if defined(__BIONIC__)
+#define STRLCPY_SUPPORTED
+#define STRLCAT_SUPPORTED
+#endif
+
 #define KB 1024
 #define SMALL 1*KB
 #define MEDIUM 4*KB
@@ -70,7 +75,7 @@
 
   ASSERT_STREQ("Unknown error 1001", strerror1001);
 #else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
+  GTEST_LOG_(INFO) << "Skipping test, requires a thread safe strerror.";
 #endif // __BIONIC__
 }
 
@@ -532,7 +537,7 @@
 }
 
 TEST(string, strlcat) {
-#if defined(__BIONIC__)
+#if defined(STRLCAT_SUPPORTED)
   StringTestState<char> state(SMALL);
   for (size_t i = 0; i < state.n; i++) {
     for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
@@ -555,13 +560,13 @@
       ASSERT_TRUE(memcmp(state.ptr, state.ptr2, state.MAX_LEN + state.len[i]) == 0);
     }
   }
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
+#else
+  GTEST_LOG_(INFO) << "Skipping test, strlcat not supported on this platform.";
+#endif
 }
 
 TEST(string, strlcpy) {
-#if defined(__BIONIC__)
+#if defined(STRLCPY_SUPPORTED)
   StringTestState<char> state(SMALL);
   for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
     int rand = 'O';
@@ -587,9 +592,9 @@
     ASSERT_FALSE((memcmp(state.ptr1, state.ptr, state.MAX_LEN) != 0) ||
                  (memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN) != 0));
   }
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
+#else
+  GTEST_LOG_(INFO) << "Skipping test, strlcpy not supported on this platform.";
+#endif
 }
 
 TEST(string, strncat) {
@@ -1100,6 +1105,36 @@
   RunSrcDstBufferOverreadTest(DoStrcpyTest);
 }
 
+#if defined(STRLCPY_SUPPORTED)
+static void DoStrlcpyTest(uint8_t* src, uint8_t* dst, size_t len) {
+  if (len >= 1) {
+    memset(src, (32 + (len % 96)), len - 1);
+    src[len-1] = '\0';
+    memset(dst, 0, len);
+    ASSERT_EQ(len-1, strlcpy(reinterpret_cast<char*>(dst),
+                             reinterpret_cast<char*>(src), len));
+    ASSERT_TRUE(memcmp(src, dst, len) == 0);
+  }
+}
+#endif
+
+TEST(string, strlcpy_align) {
+#if defined(STRLCPY_SUPPORTED)
+  RunSrcDstBufferAlignTest(LARGE, DoStrlcpyTest);
+#else
+  GTEST_LOG_(INFO) << "Skipping test, strlcpy not supported on this platform.";
+#endif
+}
+
+TEST(string, strlcpy_overread) {
+#if defined(STRLCPY_SUPPORTED)
+  RunSrcDstBufferOverreadTest(DoStrlcpyTest);
+#else
+  GTEST_LOG_(INFO) << "Skipping test, strlcpy not supported on this platform.";
+#endif
+}
+
+
 static void DoStpcpyTest(uint8_t* src, uint8_t* dst, size_t len) {
   if (len >= 1) {
     memset(src, (32 + (len % 96)), len - 1);
@@ -1172,6 +1207,55 @@
   RunSrcDstBufferOverreadTest(DoStrcatTest);
 }
 
+#if defined(STRLCAT_SUPPORTED)
+static void DoStrlcatTest(uint8_t* src, uint8_t* dst, size_t len) {
+  if (len >= 1) {
+    int value = 32 + (len % 96);
+    memset(src, value, len - 1);
+    src[len-1] = '\0';
+
+    if (len >= STRCAT_DST_LEN) {
+      // Create a small buffer for doing quick compares in each loop.
+      uint8_t cmp_buf[STRCAT_DST_LEN];
+      // Make sure dst string contains a different value then the src string.
+      int value2 = 32 + (value + 2) % 96;
+      memset(cmp_buf, value2, sizeof(cmp_buf));
+
+      for (size_t i = 1; i <= STRCAT_DST_LEN; i++) {
+        memset(dst, value2, i-1);
+        memset(dst+i-1, 0, len-i);
+        src[len-i] = '\0';
+        ASSERT_EQ(len-1, strlcat(reinterpret_cast<char*>(dst),
+                                 reinterpret_cast<char*>(src), len));
+        ASSERT_TRUE(memcmp(dst, cmp_buf, i-1) == 0);
+        ASSERT_TRUE(memcmp(src, dst+i-1, len-i+1) == 0);
+      }
+    } else {
+      dst[0] = '\0';
+      ASSERT_EQ(len-1, strlcat(reinterpret_cast<char*>(dst),
+                               reinterpret_cast<char*>(src), len));
+      ASSERT_TRUE(memcmp(src, dst, len) == 0);
+    }
+  }
+}
+#endif
+
+TEST(string, strlcat_align) {
+#if defined(STRLCAT_SUPPORTED)
+  RunSrcDstBufferAlignTest(MEDIUM, DoStrlcatTest, LargeSetIncrement);
+#else
+  GTEST_LOG_(INFO) << "Skipping test, strlcat not supported on this platform.";
+#endif
+}
+
+TEST(string, strlcat_overread) {
+#if defined(STRLCAT_SUPPORTED)
+  RunSrcDstBufferOverreadTest(DoStrlcatTest);
+#else
+  GTEST_LOG_(INFO) << "Skipping test, strlcat not supported on this platform.";
+#endif
+}
+
 static void DoStrcmpTest(uint8_t* buf1, uint8_t* buf2, size_t len) {
   if (len >= 1) {
     memset(buf1, (32 + (len % 96)), len - 1);