summaryrefslogtreecommitdiff
path: root/apexd/apexd_utils.h
diff options
context:
space:
mode:
Diffstat (limited to 'apexd/apexd_utils.h')
-rw-r--r--apexd/apexd_utils.h71
1 files changed, 71 insertions, 0 deletions
diff --git a/apexd/apexd_utils.h b/apexd/apexd_utils.h
index 2759f9a..6997efc 100644
--- a/apexd/apexd_utils.h
+++ b/apexd/apexd_utils.h
@@ -21,6 +21,7 @@
#include <filesystem>
#include <string>
#include <thread>
+#include <type_traits>
#include <vector>
#include <dirent.h>
@@ -245,6 +246,76 @@ inline Result<std::vector<std::string>> GetDeUserDirs() {
return GetSubdirs(kDeNDataDir);
}
+// Returns first path between |first_dir| and |second_dir| that correspond to a
+// existing directory. Returns error if neither |first_dir| nor |second_dir|
+// correspond to an existing directory.
+inline Result<std::string> FindFirstExistingDirectory(
+ const std::string& first_dir, const std::string& second_dir) {
+ struct stat stat_buf;
+ if (stat(first_dir.c_str(), &stat_buf) != 0) {
+ PLOG(WARNING) << "Failed to stat " << first_dir;
+ if (stat(second_dir.c_str(), &stat_buf) != 0) {
+ return ErrnoError() << "Failed to stat " << second_dir;
+ }
+ if (!S_ISDIR(stat_buf.st_mode)) {
+ return Error() << second_dir << " is not a directory";
+ }
+ return second_dir;
+ }
+
+ if (S_ISDIR(stat_buf.st_mode)) {
+ return first_dir;
+ }
+ LOG(WARNING) << first_dir << " is not a directory";
+
+ if (stat(second_dir.c_str(), &stat_buf) != 0) {
+ return ErrnoError() << "Failed to stat " << second_dir;
+ }
+ if (!S_ISDIR(stat_buf.st_mode)) {
+ return Error() << second_dir << " is not a directory";
+ }
+ return second_dir;
+}
+
+// Copies all entries under |from| directory to |to| directory, and then them.
+// Leaving |from| empty.
+inline Result<void> MoveDir(const std::string& from, const std::string& to) {
+ struct stat stat_buf;
+ if (stat(to.c_str(), &stat_buf) != 0) {
+ return ErrnoError() << "Failed to stat " << to;
+ }
+ if (!S_ISDIR(stat_buf.st_mode)) {
+ return Error() << to << " is not a directory";
+ }
+
+ namespace fs = std::filesystem;
+ std::error_code ec;
+ auto it = fs::directory_iterator(from, ec);
+ if (ec) {
+ return Error() << "Can't read " << from << " : " << ec.message();
+ }
+
+ for (const auto& end = fs::directory_iterator(); it != end;) {
+ auto from_path = it->path();
+ it.increment(ec);
+ if (ec) {
+ return Error() << "Can't read " << from << " : " << ec.message();
+ }
+ auto to_path = to / from_path.filename();
+ fs::copy(from_path, to_path, fs::copy_options::recursive, ec);
+ if (ec) {
+ return Error() << "Failed to copy " << from_path << " to " << to_path
+ << " : " << ec.message();
+ }
+ fs::remove_all(from_path, ec);
+ if (ec) {
+ return Error() << "Failed to delete " << from_path << " : "
+ << ec.message();
+ }
+ }
+ return {};
+}
+
} // namespace apex
} // namespace android