Refactor ForkExecvp to improve locking behaviour

Do our own fork/exec rather than using a library. This leads to
many improvements:

- unite the output recording path with the other path
- never concatenate arguments with spaces
- never use the shell
- move setexeccon after fork, so we don't need to take the lock
- general code refactor while we're there

My tests:
- Ensure Marlin device boots and vold_prepare_subdirs is called
successfully
- Try adb shell sm set-virtual-disk true, see that eg sgdisk output is
logged.

weilongping@huawei.com's tests:
- unlock a user's de and ce directory;
- connect to a OTG storage device or a sdcard and ensure the mount logic be successful

Bug: 26735063
Bug: 113796163
Test: details in commit
Change-Id: I0976413529d7cbeebf5b8649660a385f9b036f04
diff --git a/fs/Exfat.cpp b/fs/Exfat.cpp
index 5c15075..c624eb9 100644
--- a/fs/Exfat.cpp
+++ b/fs/Exfat.cpp
@@ -43,7 +43,7 @@
     cmd.push_back(kFsckPath);
     cmd.push_back(source);
 
-    int rc = ForkExecvp(cmd, sFsckUntrustedContext);
+    int rc = ForkExecvp(cmd, nullptr, sFsckUntrustedContext);
     if (rc == 0) {
         LOG(INFO) << "Check OK";
         return 0;
diff --git a/fs/Ext4.cpp b/fs/Ext4.cpp
index 806cfd1..0059233 100644
--- a/fs/Ext4.cpp
+++ b/fs/Ext4.cpp
@@ -117,7 +117,7 @@
         cmd.push_back(c_source);
 
         // ext4 devices are currently always trusted
-        return ForkExecvp(cmd, sFsckContext);
+        return ForkExecvp(cmd, nullptr, sFsckContext);
     }
 
     return 0;
diff --git a/fs/F2fs.cpp b/fs/F2fs.cpp
index c6e0f52..9517dc9 100644
--- a/fs/F2fs.cpp
+++ b/fs/F2fs.cpp
@@ -48,7 +48,7 @@
     cmd.push_back(source);
 
     // f2fs devices are currently always trusted
-    return ForkExecvp(cmd, sFsckContext);
+    return ForkExecvp(cmd, nullptr, sFsckContext);
 }
 
 status_t Mount(const std::string& source, const std::string& target) {
diff --git a/fs/Vfat.cpp b/fs/Vfat.cpp
index 7b833d1..14c42d6 100644
--- a/fs/Vfat.cpp
+++ b/fs/Vfat.cpp
@@ -67,7 +67,7 @@
         cmd.push_back(source);
 
         // Fat devices are currently always untrusted
-        rc = ForkExecvp(cmd, sFsckUntrustedContext);
+        rc = ForkExecvp(cmd, nullptr, sFsckUntrustedContext);
 
         if (rc < 0) {
             LOG(ERROR) << "Filesystem check failed due to logwrap error";