Merge "libcutils: fs_config: target_out_path assumed /system breaking partitions" am: e800b97c46 am: 0c7f2287aa
am: d98968eeda

Change-Id: Ie2624cba34872dfaa60e2e44c26c82cc766af2b3
diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c
index a2f5816..b19a2fd 100644
--- a/libcutils/fs_config.c
+++ b/libcutils/fs_config.c
@@ -227,21 +227,24 @@
     /* clang-format on */
 };
 
+static size_t strip(const char* path, size_t len, const char suffix[]) {
+    if (len < strlen(suffix)) return len;
+    if (strncmp(path + len - strlen(suffix), suffix, strlen(suffix))) return len;
+    return len - strlen(suffix);
+}
+
 static int fs_config_open(int dir, int which, const char* target_out_path) {
     int fd = -1;
 
     if (target_out_path && *target_out_path) {
         /* target_out_path is the path to the directory holding content of
-         * system partition but as we cannot guaranty it ends with '/system'
-         * we need this below skip_len logic */
+         * system partition but as we cannot guarantee it ends with '/system'
+         * or with or without a trailing slash, need to strip them carefully. */
         char* name = NULL;
-        int target_out_path_len = strlen(target_out_path);
-        int skip_len = strlen("/system");
-
-        if (target_out_path[target_out_path_len] == '/') {
-            skip_len++;
-        }
-        if (asprintf(&name, "%s%s", target_out_path, conf[which][dir] + skip_len) != -1) {
+        size_t len = strlen(target_out_path);
+        len = strip(target_out_path, len, "/");
+        len = strip(target_out_path, len, "/system");
+        if (asprintf(&name, "%.*s%s", (int)len, target_out_path, conf[which][dir]) != -1) {
             fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY | O_BINARY));
             free(name);
         }