Merge "init: Adding support to import directories"
diff --git a/init/init.cpp b/init/init.cpp
index c66c487..4be16ea 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -1057,7 +1057,7 @@
     property_load_boot_defaults();
     start_property_service();
 
-    init_parse_config_file("/init.rc");
+    init_parse_config("/init.rc");
 
     action_for_each_trigger("early-init", action_add_queue_tail);
 
diff --git a/init/init_parser.cpp b/init/init_parser.cpp
index 86e9ce6..460f5ac 100644
--- a/init/init_parser.cpp
+++ b/init/init_parser.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <ctype.h>
+#include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
@@ -32,6 +33,7 @@
 #include "property_service.h"
 #include "util.h"
 
+#include <base/stringprintf.h>
 #include <cutils/iosched_policy.h>
 #include <cutils/list.h>
 
@@ -385,15 +387,15 @@
 parser_done:
     list_for_each(node, &import_list) {
          struct import* import = node_to_item(node, struct import, list);
-         if (!init_parse_config_file(import->filename)) {
+         if (!init_parse_config(import->filename)) {
              ERROR("could not import file '%s' from '%s': %s\n",
                    import->filename, fn, strerror(errno));
          }
     }
 }
 
-bool init_parse_config_file(const char* path) {
-    INFO("Parsing %s...\n", path);
+static bool init_parse_config_file(const char* path) {
+    INFO("Parsing file %s...\n", path);
     Timer t;
     std::string data;
     if (!read_file(path, &data)) {
@@ -408,6 +410,34 @@
     return true;
 }
 
+static bool init_parse_config_dir(const char* path) {
+    INFO("Parsing directory %s...\n", path);
+    std::unique_ptr<DIR, int(*)(DIR*)> config_dir(opendir(path), closedir);
+    if (!config_dir) {
+        ERROR("Could not import directory '%s'\n", path);
+        return false;
+    }
+    dirent* current_file;
+    while ((current_file = readdir(config_dir.get()))) {
+        std::string current_path =
+            android::base::StringPrintf("%s/%s", path, current_file->d_name);
+        // Ignore directories and only process regular files.
+        if (current_file->d_type == DT_REG) {
+            if (!init_parse_config_file(current_path.c_str())) {
+                ERROR("could not import file '%s'\n", current_path.c_str());
+            }
+        }
+    }
+    return true;
+}
+
+bool init_parse_config(const char* path) {
+    if (is_dir(path)) {
+        return init_parse_config_dir(path);
+    }
+    return init_parse_config_file(path);
+}
+
 static int valid_name(const char *name)
 {
     if (strlen(name) > 16) {
diff --git a/init/init_parser.h b/init/init_parser.h
index fa7e67f..1ebb1ef 100644
--- a/init/init_parser.h
+++ b/init/init_parser.h
@@ -33,7 +33,7 @@
 void queue_all_property_triggers();
 void queue_builtin_action(int (*func)(int nargs, char **args), const char *name);
 
-bool init_parse_config_file(const char* path);
+bool init_parse_config(const char* path);
 int expand_props(const char *src, std::string *dst);
 
 service* make_exec_oneshot_service(int argc, char** argv);
diff --git a/init/readme.txt b/init/readme.txt
index 4dda340..5a758d7 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -197,8 +197,11 @@
 ifup <interface>
    Bring the network interface <interface> online.
 
-import <filename>
+import <path>
    Parse an init config file, extending the current configuration.
+   If <path> is a directory, each file in the directory is parsed as
+   a config file. It is not recursive, nested directories will
+   not be parsed.
 
 insmod <path>
    Install the module at <path>
diff --git a/init/util.cpp b/init/util.cpp
index 7f29e94..f6131e3 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -465,3 +465,14 @@
         android::base::StringAppendF(&hex, "%02x", bytes[i]);
     return hex;
 }
+
+/*
+ * Returns true is pathname is a directory
+ */
+bool is_dir(const char* pathname) {
+    struct stat info;
+    if (stat(pathname, &info) == -1) {
+        return false;
+    }
+    return S_ISDIR(info.st_mode);
+}
diff --git a/init/util.h b/init/util.h
index 3aba599..f08cb8d 100644
--- a/init/util.h
+++ b/init/util.h
@@ -64,4 +64,5 @@
 int restorecon(const char *pathname);
 int restorecon_recursive(const char *pathname);
 std::string bytes_to_hex(const uint8_t *bytes, size_t bytes_len);
+bool is_dir(const char* pathname);
 #endif