Support host build for libdm and libfstab

The host builds for both libs are needed for libfs_avb host unit test.
Also replaces strlcat()/strlcpy() with snprintf() because the former
doesn't have a glibc version. Or switch char* to std::string*.

Bug: 112103720
Bug: 117960205
Test: m libdm ARCH=x86_64
Test: m libfstab ARCH=x86_64
Test: atest libdm_test
Test: atest fs_mgr_unit_test
Test: boot a device

Change-Id: Id9b92b5286b8ed9ab0d80f18ab5802dcfeb83dfa
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index 824511e..1616a61 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -92,6 +92,7 @@
     name: "libfstab",
     vendor_available: true,
     recovery_available: true,
+    host_supported: true,
     defaults: ["fs_mgr_defaults"],
     srcs: [
         "fs_mgr_fstab.cpp",
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index e0891eb..53b47be 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -209,17 +209,12 @@
 }
 
 static uint64_t parse_flags(char* flags, struct flag_list* fl, struct fs_mgr_flag_values* flag_vals,
-                            char* fs_options, int fs_options_len) {
+                            std::string* fs_options) {
     uint64_t f = 0;
     int i;
     char *p;
     char *savep;
 
-    /* initialize fs_options to the null string */
-    if (fs_options && (fs_options_len > 0)) {
-        fs_options[0] = '\0';
-    }
-
     p = strtok_r(flags, ",", &savep);
     while (p) {
         /* Look for the flag "p" in the flag list "fl"
@@ -356,26 +351,20 @@
 
         if (!fl[i].name) {
             if (fs_options) {
-                /* It's not a known flag, so it must be a filesystem specific
-                 * option.  Add it to fs_options if it was passed in.
-                 */
-                strlcat(fs_options, p, fs_options_len);
-                strlcat(fs_options, ",", fs_options_len);
+                // It's not a known flag, so it must be a filesystem specific
+                // option.  Add it to fs_options if it was passed in.
+                if (!fs_options->empty()) {
+                    fs_options->append(",");  // appends a comma if not the first
+                }
+                fs_options->append(p);
             } else {
-                /* fs_options was not passed in, so if the flag is unknown
-                 * it's an error.
-                 */
+                // fs_options was not passed in, so if the flag is unknown it's an error.
                 LERROR << "Warning: unknown flag " << p;
             }
         }
         p = strtok_r(NULL, ",", &savep);
     }
 
-    if (fs_options && fs_options[0]) {
-        /* remove the last trailing comma from the list of options */
-        fs_options[strlen(fs_options) - 1] = '\0';
-    }
-
     return f;
 }
 
@@ -513,8 +502,6 @@
     char *save_ptr, *p;
     Fstab fstab;
     struct fs_mgr_flag_values flag_vals;
-#define FS_OPTIONS_LEN 1024
-    char tmp_fs_options[FS_OPTIONS_LEN];
 
     while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
         /* if the last character is a newline, shorten the string by 1 byte */
@@ -555,13 +542,7 @@
             LERROR << "Error parsing mount_flags";
             goto err;
         }
-        tmp_fs_options[0] = '\0';
-        entry.flags = parse_flags(p, mount_flags, NULL, tmp_fs_options, FS_OPTIONS_LEN);
-
-        /* fs_options are optional */
-        if (tmp_fs_options[0]) {
-            entry.fs_options = tmp_fs_options;
-        }
+        entry.flags = parse_flags(p, mount_flags, nullptr, &entry.fs_options);
 
         // For /proc/mounts, ignore everything after mnt_freq and mnt_passno
         if (proc_mounts) {
@@ -570,7 +551,7 @@
             LERROR << "Error parsing fs_mgr_options";
             goto err;
         }
-        entry.fs_mgr_flags.val = parse_flags(p, fs_mgr_flags, &flag_vals, NULL, 0);
+        entry.fs_mgr_flags.val = parse_flags(p, fs_mgr_flags, &flag_vals, nullptr);
 
         entry.key_loc = std::move(flag_vals.key_loc);
         entry.key_dir = std::move(flag_vals.key_dir);
diff --git a/fs_mgr/libdm/Android.bp b/fs_mgr/libdm/Android.bp
index 90bce51..fc1aafb 100644
--- a/fs_mgr/libdm/Android.bp
+++ b/fs_mgr/libdm/Android.bp
@@ -18,6 +18,7 @@
     name: "libdm",
     defaults: ["fs_mgr_defaults"],
     recovery_available: true,
+    host_supported: true,
 
     export_include_dirs: ["include"],
 
diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp
index d9786ad..c6a9e0b 100644
--- a/fs_mgr/libdm/dm.cpp
+++ b/fs_mgr/libdm/dm.cpp
@@ -349,7 +349,7 @@
     io->data_size = sizeof(*io);
     io->data_start = 0;
     if (!name.empty()) {
-        strlcpy(io->name, name.c_str(), sizeof(io->name));
+        snprintf(io->name, sizeof(io->name), "%s", name.c_str());
     }
 }
 
diff --git a/fs_mgr/libdm/dm_target.cpp b/fs_mgr/libdm/dm_target.cpp
index 7c18267..cb33eea 100644
--- a/fs_mgr/libdm/dm_target.cpp
+++ b/fs_mgr/libdm/dm_target.cpp
@@ -42,7 +42,7 @@
     struct dm_target_spec* spec = reinterpret_cast<struct dm_target_spec*>(&data[0]);
     spec->sector_start = start();
     spec->length = size();
-    strlcpy(spec->target_type, name().c_str(), sizeof(spec->target_type));
+    snprintf(spec->target_type, sizeof(spec->target_type), "%s", name().c_str());
     spec->next = (uint32_t)data.size();
     return data;
 }
diff --git a/fs_mgr/tests/Android.bp b/fs_mgr/tests/Android.bp
index 5497223..ea12e96 100644
--- a/fs_mgr/tests/Android.bp
+++ b/fs_mgr/tests/Android.bp
@@ -23,7 +23,9 @@
         "libfs_mgr",
         "libfstab",
     ],
-
+    data: [
+        "data/*",
+    ],
     srcs: [
         "fs_mgr_test.cpp",
     ],
diff --git a/fs_mgr/tests/data/fstab.example b/fs_mgr/tests/data/fstab.example
new file mode 100644
index 0000000..1a3dfa1
--- /dev/null
+++ b/fs_mgr/tests/data/fstab.example
@@ -0,0 +1,11 @@
+# Android fstab file.
+
+#<src>                                              <mnt_point>        <type>      <mnt_flags and options>                               <fs_mgr_flags>
+
+/dev/block/bootdevice/by-name/system                /                  ext4        ro,barrier=1                                          wait,slotselect,avb
+/dev/block/bootdevice/by-name/metadata              /metadata          ext4        noatime,nosuid,nodev,discard                          wait,formattable
+/dev/block/bootdevice/by-name/userdata              /data              f2fs        noatime,nosuid,nodev,discard,reserve_root=32768,resgid=1065,fsync_mode=nobarrier       latemount,wait,check,fileencryption=ice,keydirectory=/metadata/vold/metadata_encryption,quota,formattable,sysfs_path=/sys/devices/platform/soc/1d84000.ufshc,reservedsize=128M
+/dev/block/bootdevice/by-name/misc                  /misc              emmc        defaults                                              defaults
+/dev/block/bootdevice/by-name/modem                 /vendor/firmware_mnt          vfat        ro,shortname=lower,uid=1000,gid=1000,dmask=227,fmask=337,context=u:object_r:firmware_file:s0   wait,slotselect
+/devices/platform/soc/a600000.ssusb/a600000.dwc3*   auto               vfat        defaults                                              voldmanaged=usb:auto
+/dev/block/zram0                                    none               swap        defaults                                              zramsize=1073741824,max_comp_streams=8
diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp
index db01c1e..1922a69 100644
--- a/fs_mgr/tests/fs_mgr_test.cpp
+++ b/fs_mgr/tests/fs_mgr_test.cpp
@@ -24,6 +24,8 @@
 #include <utility>
 #include <vector>
 
+#include <android-base/file.h>
+#include <android-base/properties.h>
 #include <android-base/strings.h>
 #include <fstab/fstab.h>
 #include <gtest/gtest.h>
@@ -201,3 +203,33 @@
         ++i;
     }
 }
+
+TEST(fs_mgr, ReadFstabFromFile_FsOptions) {
+    Fstab fstab;
+    std::string fstab_file = android::base::GetExecutableDirectory() + "/data/fstab.example";
+    EXPECT_TRUE(ReadFstabFromFile(fstab_file, &fstab));
+
+    EXPECT_EQ("/", fstab[0].mount_point);
+    EXPECT_EQ("barrier=1", fstab[0].fs_options);
+
+    EXPECT_EQ("/metadata", fstab[1].mount_point);
+    EXPECT_EQ("discard", fstab[1].fs_options);
+
+    EXPECT_EQ("/data", fstab[2].mount_point);
+    EXPECT_EQ("discard,reserve_root=32768,resgid=1065,fsync_mode=nobarrier", fstab[2].fs_options);
+
+    EXPECT_EQ("/misc", fstab[3].mount_point);
+    EXPECT_EQ("", fstab[3].fs_options);
+
+    EXPECT_EQ("/vendor/firmware_mnt", fstab[4].mount_point);
+    EXPECT_EQ(
+            "shortname=lower,uid=1000,gid=1000,dmask=227,fmask=337,"
+            "context=u:object_r:firmware_file:s0",
+            fstab[4].fs_options);
+
+    EXPECT_EQ("auto", fstab[5].mount_point);
+    EXPECT_EQ("", fstab[5].fs_options);
+
+    EXPECT_EQ("none", fstab[6].mount_point);
+    EXPECT_EQ("", fstab[6].fs_options);
+}