summaryrefslogtreecommitdiffstats
path: root/base/file.cpp
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2017-02-23 21:23:05 -0800
committerColin Cross <ccross@android.com>2017-02-27 18:18:31 -0800
commit58021d15c94eb6a81d2673634956b5374af6a1e5 (patch)
tree8c0b0a97ac977600f45e75fc1d6664594e30b56c /base/file.cpp
parent0cde0eae09e1a3751bb0d921e289ba5cdc228965 (diff)
downloadsystem_core-58021d15c94eb6a81d2673634956b5374af6a1e5.tar.gz
system_core-58021d15c94eb6a81d2673634956b5374af6a1e5.tar.bz2
system_core-58021d15c94eb6a81d2673634956b5374af6a1e5.zip
Move adb_dirname and adb_basename to libbase
adb already provides an implementation of dirname and basename that take and produce std::strings, move it into libbase so it can be used in the implementation of GetExecutableDirectory. Test: out/host/linux-x86/nativetest64/adb_test/adb_test Test: out/host/linux-x86/nativetest64/libbase_test/libbase_test Test: adb shell /data/nativetest64/libbase_test/libbase_test64 Change-Id: Ideb1627607b14562121316d4ed27fa6fb0930684
Diffstat (limited to 'base/file.cpp')
-rw-r--r--base/file.cpp53
1 files changed, 53 insertions, 0 deletions
diff --git a/base/file.cpp b/base/file.cpp
index 6284b04c9..32c243957 100644
--- a/base/file.cpp
+++ b/base/file.cpp
@@ -18,11 +18,13 @@
#include <errno.h>
#include <fcntl.h>
+#include <libgen.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <memory>
+#include <mutex>
#include <string>
#include <vector>
@@ -236,5 +238,56 @@ std::string GetExecutablePath() {
#endif
}
+std::string Basename(const std::string& path) {
+
+ // Copy path because basename may modify the string passed in.
+ std::string result(path);
+
+#if !defined(__BIONIC__)
+ // Use lock because basename() may write to a process global and return a
+ // pointer to that. Note that this locking strategy only works if all other
+ // callers to basename in the process also grab this same lock, but its
+ // better than nothing. Bionic's basename returns a thread-local buffer.
+ static std::mutex& basename_lock = *new std::mutex();
+ std::lock_guard<std::mutex> lock(basename_lock);
+#endif
+
+ // Note that if std::string uses copy-on-write strings, &str[0] will cause
+ // the copy to be made, so there is no chance of us accidentally writing to
+ // the storage for 'path'.
+ char* name = basename(&result[0]);
+
+ // In case basename returned a pointer to a process global, copy that string
+ // before leaving the lock.
+ result.assign(name);
+
+ return result;
+}
+
+std::string Dirname(const std::string& path) {
+ // Copy path because dirname may modify the string passed in.
+ std::string result(path);
+
+#if !defined(__BIONIC__)
+ // Use lock because dirname() may write to a process global and return a
+ // pointer to that. Note that this locking strategy only works if all other
+ // callers to dirname in the process also grab this same lock, but its
+ // better than nothing. Bionic's dirname returns a thread-local buffer.
+ static std::mutex& dirname_lock = *new std::mutex();
+ std::lock_guard<std::mutex> lock(dirname_lock);
+#endif
+
+ // Note that if std::string uses copy-on-write strings, &str[0] will cause
+ // the copy to be made, so there is no chance of us accidentally writing to
+ // the storage for 'path'.
+ char* parent = dirname(&result[0]);
+
+ // In case dirname returned a pointer to a process global, copy that string
+ // before leaving the lock.
+ result.assign(parent);
+
+ return result;
+}
+
} // namespace base
} // namespace android