From 060b74baad7c366cb6c74042bf307f1548a8331f Mon Sep 17 00:00:00 2001 From: Tom Cherry Date: Wed, 12 Apr 2017 14:27:51 -0700 Subject: [PATCH] ueventd: convert mkdir_recursive() to std::string Bug: 36250207 Test: Boot bullhead Test: Boot sailfish, observe no boot time regression Test: init unit tests Change-Id: I5a2ac369d846e044230b709fd07eb21ad12d47bb --- init/Android.mk | 3 ++- init/util.cpp | 39 ++++++++++----------------------------- init/util.h | 2 +- init/util_test.cpp | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 31 deletions(-) diff --git a/init/Android.mk b/init/Android.mk index dbbf40a62..7e9b6136c 100644 --- a/init/Android.mk +++ b/init/Android.mk @@ -148,8 +148,9 @@ LOCAL_SRC_FILES := \ util_test.cpp \ LOCAL_SHARED_LIBRARIES += \ - libcutils \ libbase \ + libcutils \ + libselinux \ LOCAL_STATIC_LIBRARIES := libinit LOCAL_SANITIZE := integer diff --git a/init/util.cpp b/init/util.cpp index bbc59cb88..32ae93de0 100644 --- a/init/util.cpp +++ b/init/util.cpp @@ -194,37 +194,18 @@ bool write_file(const std::string& path, const std::string& content) { return success; } -int mkdir_recursive(const char *pathname, mode_t mode) -{ - char buf[128]; - const char *slash; - const char *p = pathname; - int width; - int ret; - struct stat info; - - while ((slash = strchr(p, '/')) != NULL) { - width = slash - pathname; - p = slash + 1; - if (width < 0) - break; - if (width == 0) - continue; - if ((unsigned int)width > sizeof(buf) - 1) { - LOG(ERROR) << "path too long for mkdir_recursive"; - return -1; - } - memcpy(buf, pathname, width); - buf[width] = 0; - if (stat(buf, &info) != 0) { - ret = make_dir(buf, mode); - if (ret && errno != EEXIST) - return ret; +int mkdir_recursive(const std::string& path, mode_t mode) { + std::string::size_type slash = 0; + while ((slash = path.find('/', slash + 1)) != std::string::npos) { + auto directory = path.substr(0, slash); + struct stat info; + if (stat(directory.c_str(), &info) != 0) { + auto ret = make_dir(directory.c_str(), mode); + if (ret && errno != EEXIST) return ret; } } - ret = make_dir(pathname, mode); - if (ret && errno != EEXIST) - return ret; + auto ret = make_dir(path.c_str(), mode); + if (ret && errno != EEXIST) return ret; return 0; } diff --git a/init/util.h b/init/util.h index 38a7bdb3a..0bb9cdfc4 100644 --- a/init/util.h +++ b/init/util.h @@ -60,7 +60,7 @@ std::ostream& operator<<(std::ostream& os, const Timer& t); unsigned int decode_uid(const char *s); -int mkdir_recursive(const char *pathname, mode_t mode); +int mkdir_recursive(const std::string& pathname, mode_t mode); int wait_for_file(const char *filename, std::chrono::nanoseconds timeout); void import_kernel_cmdline(bool in_qemu, const std::function&); diff --git a/init/util_test.cpp b/init/util_test.cpp index 0c0350a60..b8b409a1a 100644 --- a/init/util_test.cpp +++ b/init/util_test.cpp @@ -120,3 +120,39 @@ TEST(util, decode_uid) { EXPECT_EQ(UINT_MAX, decode_uid("toot")); EXPECT_EQ(123U, decode_uid("123")); } + +TEST(util, is_dir) { + TemporaryDir test_dir; + EXPECT_TRUE(is_dir(test_dir.path)); + TemporaryFile tf; + EXPECT_FALSE(is_dir(tf.path)); +} + +// sehandle is needed for make_dir() +// TODO: Remove once sehandle is encapsulated +#include +selabel_handle* sehandle; + +TEST(util, mkdir_recursive) { + TemporaryDir test_dir; + std::string path = android::base::StringPrintf("%s/three/directories/deep", test_dir.path); + EXPECT_EQ(0, mkdir_recursive(path, 0755)); + std::string path1 = android::base::StringPrintf("%s/three", test_dir.path); + EXPECT_TRUE(is_dir(path1.c_str())); + std::string path2 = android::base::StringPrintf("%s/three/directories", test_dir.path); + EXPECT_TRUE(is_dir(path1.c_str())); + std::string path3 = android::base::StringPrintf("%s/three/directories/deep", test_dir.path); + EXPECT_TRUE(is_dir(path1.c_str())); +} + +TEST(util, mkdir_recursive_extra_slashes) { + TemporaryDir test_dir; + std::string path = android::base::StringPrintf("%s/three////directories/deep//", test_dir.path); + EXPECT_EQ(0, mkdir_recursive(path, 0755)); + std::string path1 = android::base::StringPrintf("%s/three", test_dir.path); + EXPECT_TRUE(is_dir(path1.c_str())); + std::string path2 = android::base::StringPrintf("%s/three/directories", test_dir.path); + EXPECT_TRUE(is_dir(path1.c_str())); + std::string path3 = android::base::StringPrintf("%s/three/directories/deep", test_dir.path); + EXPECT_TRUE(is_dir(path1.c_str())); +}