Export fts as a static library for use with musl

musl libc doesn't provide fts, but elfutils and libabigail need it.
Export bionic's fts as a staic library that can be linked into elfutils
and libabigail when compiling against musl.

fts uses recallocarray, which musl doesn't provide, so also include
recallocarray.c in libfts.a.

Requires minor tweaks to fts.c and a wrapper around fts.h to make them
compatible with musl, primarily by providing local definitions of macros
provided in bionic's sys/cdefs.h.

Bug: 190084016
Test: m libfts
Change-Id: Ifac9a59e7504c0c1f5f8a3a5bd3c19a13980b83c
diff --git a/libc/Android.bp b/libc/Android.bp
index 4f5089e..1472371 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -2534,6 +2534,29 @@
     },
 }
 
+cc_library_host_static {
+    name: "libfts",
+    srcs: [
+        "bionic/fts.c",
+        "upstream-openbsd/lib/libc/stdlib/recallocarray.c",
+    ],
+    export_include_dirs: ["fts/include"],
+    local_include_dirs: [
+        "private",
+        "upstream-openbsd/android/include",
+    ],
+    cflags: [
+        "-include openbsd-compat.h",
+        "-Wno-unused-parameter",
+    ],
+    enabled: false,
+    target: {
+        musl: {
+            enabled: true,
+        },
+    },
+}
+
 subdirs = [
     "bionic/scudo",
 ]
diff --git a/libc/bionic/fts.c b/libc/bionic/fts.c
index dc5ed6b..1287267 100644
--- a/libc/bionic/fts.c
+++ b/libc/bionic/fts.c
@@ -447,7 +447,7 @@
  * reasons.
  */
 int
-fts_set(FTS *sp __unused, FTSENT *p, int instr)
+fts_set(FTS *sp, FTSENT *p, int instr)
 {
 	if (instr && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
 	    instr != FTS_NOINSTR && instr != FTS_SKIP) {
diff --git a/libc/fts/include/bionic/fts.h b/libc/fts/include/bionic/fts.h
new file mode 120000
index 0000000..92e44cf
--- /dev/null
+++ b/libc/fts/include/bionic/fts.h
@@ -0,0 +1 @@
+../../../include/fts.h
\ No newline at end of file
diff --git a/libc/fts/include/fts.h b/libc/fts/include/fts.h
new file mode 100644
index 0000000..26b3e94
--- /dev/null
+++ b/libc/fts/include/fts.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+/*
+ * This file is exported as part of libfts for use with musl, which doesn't
+ * define __INTRODUCED_IN.  Stub it out.
+ */
+#define __INTRODUCED_IN(x)
+#include <bionic/fts.h>
+#undef __INTRODUCED_IN
diff --git a/libc/private/bsd_sys_param.h b/libc/private/bsd_sys_param.h
index 8c936c4..be5f692 100644
--- a/libc/private/bsd_sys_param.h
+++ b/libc/private/bsd_sys_param.h
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include <inttypes.h>
+
 /* OpenBSD has these in <sys/param.h>, but "ALIGN" isn't something we want to reserve. */
 #define ALIGNBYTES (sizeof(uintptr_t) - 1)
 #define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) & ~ALIGNBYTES)
diff --git a/libc/upstream-openbsd/android/include/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h
index 6c21c5b..8e6f87d 100644
--- a/libc/upstream-openbsd/android/include/openbsd-compat.h
+++ b/libc/upstream-openbsd/android/include/openbsd-compat.h
@@ -57,7 +57,13 @@
 /* OpenBSD has this, but we can't really implement it correctly on Linux. */
 #define issetugid() 0
 
+#if !defined(ANDROID_HOST_MUSL)
 #define explicit_bzero(p, s) memset(p, 0, s)
+#endif
+
+#if defined(ANDROID_HOST_MUSL)
+#define __LIBC_HIDDEN__ __attribute__((visibility("hidden")))
+#endif
 
 /* OpenBSD has this in paths.h. But this directory doesn't normally exist.
  * Even when it does exist, only the 'shell' user has permissions.