Merge changes I0a00b3d4,I19cb0694

* changes:
  adb: let `adb push` follow symlinks.
  base: add parameter that controls O_NOFOLLOW in file functions.
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index 56ff68c..f1e4179 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -606,7 +606,7 @@
     }
     if (st.st_size < SYNC_DATA_MAX) {
         std::string data;
-        if (!android::base::ReadFileToString(lpath, &data)) {
+        if (!android::base::ReadFileToString(lpath, &data, true)) {
             sc.Error("failed to read all of '%s': %s", lpath, strerror(errno));
             return false;
         }
diff --git a/adb/test_device.py b/adb/test_device.py
index 2efac9d..b12bf88 100644
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -787,6 +787,36 @@
             if host_dir is not None:
                 shutil.rmtree(host_dir)
 
+    @unittest.skipIf(sys.platform == "win32", "symlinks require elevated privileges on windows")
+    def test_push_symlink(self):
+        """Push a symlink.
+
+        Bug: http://b/31491920
+        """
+        try:
+            host_dir = tempfile.mkdtemp()
+
+            # Make sure the temp directory isn't setuid, or else adb will
+            # complain.
+            os.chmod(host_dir, 0o700)
+
+            with open(os.path.join(host_dir, 'foo'), 'w') as f:
+                f.write('foo')
+
+            symlink_path = os.path.join(host_dir, 'symlink')
+            os.symlink('foo', symlink_path)
+
+            self.device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
+            self.device.shell(['mkdir', self.DEVICE_TEMP_DIR])
+            self.device.push(symlink_path, self.DEVICE_TEMP_DIR)
+            rc, out, _ = self.device.shell_nocheck(
+                ['cat', posixpath.join(self.DEVICE_TEMP_DIR, 'symlink')])
+            self.assertEqual(0, rc)
+            self.assertEqual(out.strip(), 'foo')
+        finally:
+            if host_dir is not None:
+                shutil.rmtree(host_dir)
+
     def test_multiple_push(self):
         """Push multiple files to the device in one adb push command.
 
diff --git a/base/file.cpp b/base/file.cpp
index 721ab2f..6284b04 100644
--- a/base/file.cpp
+++ b/base/file.cpp
@@ -55,10 +55,11 @@
   return (n == 0) ? true : false;
 }
 
-bool ReadFileToString(const std::string& path, std::string* content) {
+bool ReadFileToString(const std::string& path, std::string* content, bool follow_symlinks) {
   content->clear();
 
-  int fd = TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_BINARY));
+  int flags = O_RDONLY | O_CLOEXEC | O_BINARY | (follow_symlinks ? 0 : O_NOFOLLOW);
+  int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags));
   if (fd == -1) {
     return false;
   }
@@ -91,8 +92,10 @@
 
 #if !defined(_WIN32)
 bool WriteStringToFile(const std::string& content, const std::string& path,
-                       mode_t mode, uid_t owner, gid_t group) {
-  int flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW | O_BINARY;
+                       mode_t mode, uid_t owner, gid_t group,
+                       bool follow_symlinks) {
+  int flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_BINARY |
+              (follow_symlinks ? 0 : O_NOFOLLOW);
   int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
   if (fd == -1) {
     PLOG(ERROR) << "android::WriteStringToFile open failed";
@@ -118,8 +121,10 @@
 }
 #endif
 
-bool WriteStringToFile(const std::string& content, const std::string& path) {
-  int flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW | O_BINARY;
+bool WriteStringToFile(const std::string& content, const std::string& path,
+                       bool follow_symlinks) {
+  int flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_BINARY |
+              (follow_symlinks ? 0 : O_NOFOLLOW);
   int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, DEFFILEMODE));
   if (fd == -1) {
     return false;
diff --git a/base/file_test.cpp b/base/file_test.cpp
index f5d6062..f741d89 100644
--- a/base/file_test.cpp
+++ b/base/file_test.cpp
@@ -45,6 +45,24 @@
   EXPECT_EQ("abc", s);
 }
 
+// symlinks require elevated privileges on Windows.
+#if !defined(_WIN32)
+TEST(file, ReadFileToString_WriteStringToFile_symlink) {
+  TemporaryFile target, link;
+  ASSERT_EQ(0, unlink(link.path));
+  ASSERT_EQ(0, symlink(target.path, link.path));
+  ASSERT_FALSE(android::base::WriteStringToFile("foo", link.path, false));
+  ASSERT_EQ(ELOOP, errno);
+  ASSERT_TRUE(android::base::WriteStringToFile("foo", link.path, true));
+
+  std::string s;
+  ASSERT_FALSE(android::base::ReadFileToString(link.path, &s));
+  ASSERT_EQ(ELOOP, errno);
+  ASSERT_TRUE(android::base::ReadFileToString(link.path, &s, true));
+  ASSERT_EQ("foo", s);
+}
+#endif
+
 // WriteStringToFile2 is explicitly for setting Unix permissions, which make no
 // sense on Windows.
 #if !defined(_WIN32)
diff --git a/base/include/android-base/file.h b/base/include/android-base/file.h
index 5b22a65..cd64262 100644
--- a/base/include/android-base/file.h
+++ b/base/include/android-base/file.h
@@ -28,14 +28,17 @@
 namespace base {
 
 bool ReadFdToString(int fd, std::string* content);
-bool ReadFileToString(const std::string& path, std::string* content);
+bool ReadFileToString(const std::string& path, std::string* content,
+                      bool follow_symlinks = false);
 
-bool WriteStringToFile(const std::string& content, const std::string& path);
+bool WriteStringToFile(const std::string& content, const std::string& path,
+                       bool follow_symlinks = false);
 bool WriteStringToFd(const std::string& content, int fd);
 
 #if !defined(_WIN32)
 bool WriteStringToFile(const std::string& content, const std::string& path,
-                       mode_t mode, uid_t owner, gid_t group);
+                       mode_t mode, uid_t owner, gid_t group,
+                       bool follow_symlinks = false);
 #endif
 
 bool ReadFully(int fd, void* data, size_t byte_count);