From 840b6019c035eb3abeadfb2dc8abac38692a829b Mon Sep 17 00:00:00 2001 From: Dimitry Ivanov Date: Fri, 9 Sep 2016 10:49:21 -0700 Subject: [PATCH] Add android::base::Realpath. Bug: http://b/31396973 Test: libbase_test on host and device Change-Id: I1e5f15c76227ec1c2128baa38eb454d347987703 --- base/file.cpp | 14 ++++++++++++++ base/file_test.cpp | 32 ++++++++++++++++++++++++++++++++ base/include/android-base/file.h | 1 + 3 files changed, 47 insertions(+) diff --git a/base/file.cpp b/base/file.cpp index 81b04d74e..378a405bc 100644 --- a/base/file.cpp +++ b/base/file.cpp @@ -212,6 +212,20 @@ bool Readlink(const std::string& path, std::string* result) { } #endif +#if !defined(_WIN32) +bool Realpath(const std::string& path, std::string* result) { + result->clear(); + + char* realpath_buf = realpath(path.c_str(), nullptr); + if (realpath_buf == nullptr) { + return false; + } + result->assign(realpath_buf); + free(realpath_buf); + return true; +} +#endif + std::string GetExecutablePath() { #if defined(__linux__) std::string path; diff --git a/base/file_test.cpp b/base/file_test.cpp index 102132626..266131ecf 100644 --- a/base/file_test.cpp +++ b/base/file_test.cpp @@ -159,6 +159,38 @@ TEST(file, Readlink) { #endif } +TEST(file, Realpath) { +#if !defined(_WIN32) + TemporaryDir td; + std::string basename = android::base::Basename(td.path); + std::string dir_name = android::base::Dirname(td.path); + std::string base_dir_name = android::base::Basename(dir_name); + + { + std::string path = dir_name + "/../" + base_dir_name + "/" + basename; + std::string result; + ASSERT_TRUE(android::base::Realpath(path, &result)); + ASSERT_EQ(td.path, result); + } + + { + std::string path = std::string(td.path) + "/.."; + std::string result; + ASSERT_TRUE(android::base::Realpath(path, &result)); + ASSERT_EQ(dir_name, result); + } + + { + errno = 0; + std::string path = std::string(td.path) + "/foo.noent"; + std::string result = "wrong"; + ASSERT_TRUE(!android::base::Realpath(path, &result)); + ASSERT_TRUE(result.empty()); + ASSERT_EQ(ENOENT, errno); + } +#endif +} + TEST(file, GetExecutableDirectory) { std::string path = android::base::GetExecutableDirectory(); ASSERT_NE("", path); diff --git a/base/include/android-base/file.h b/base/include/android-base/file.h index 33d1ab320..651f52962 100644 --- a/base/include/android-base/file.h +++ b/base/include/android-base/file.h @@ -47,6 +47,7 @@ bool WriteFully(int fd, const void* data, size_t byte_count); bool RemoveFileIfExists(const std::string& path, std::string* err = nullptr); #if !defined(_WIN32) +bool Realpath(const std::string& path, std::string* result); bool Readlink(const std::string& path, std::string* result); #endif