recovery: Implement a volume manager

This is a copy of the pre-binderized vold which has been converted to
use direct calls instead of sockets and stripped down to only what is
needed to support recovery.

Change-Id: Ic82d929e052b5ba70ecf7b475e0a223d77d9687e
diff --git a/volume_manager/EmulatedVolume.cpp b/volume_manager/EmulatedVolume.cpp
new file mode 100644
index 0000000..8260563
--- /dev/null
+++ b/volume_manager/EmulatedVolume.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2019 The LineageOS 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.
+ */
+
+#include "EmulatedVolume.h"
+#include <volume_manager/VolumeManager.h>
+#include "ResponseCode.h"
+#include "Utils.h"
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <cutils/fs.h>
+#include <private/android_filesystem_config.h>
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+using android::base::StringPrintf;
+
+namespace android {
+namespace volmgr {
+
+static const std::string kStagingPath = "/mnt/staging/emulated";
+
+EmulatedVolume::EmulatedVolume(FstabEntry* rec, const std::string& subdir)
+    : VolumeBase(Type::kEmulated),
+      mSubdir(subdir),
+      mDevPath(rec->blk_device),
+      mFsType(rec->fs_type),
+      mFlags(rec->flags),
+      mFsOptions(rec->fs_options) {
+    setId("emulated");
+    setPartLabel("internal storage");
+    setPath("/storage/emulated");
+}
+
+EmulatedVolume::~EmulatedVolume() {}
+
+status_t EmulatedVolume::doMount() {
+    if (fs_prepare_dir(kStagingPath.c_str(), 0700, AID_ROOT, AID_ROOT)) {
+        PLOG(ERROR) << getId() << " failed to create mount points";
+        return -errno;
+    }
+    if (fs_prepare_dir(getPath().c_str(), 0700, AID_ROOT, AID_ROOT)) {
+        PLOG(ERROR) << getId() << " failed to create mount points";
+        return -errno;
+    }
+
+    std::string bindPath = kStagingPath + "/" + mSubdir;
+
+    if (::mount(mDevPath.c_str(), kStagingPath.c_str(), mFsType.c_str(), mFlags,
+                mFsOptions.c_str()) != 0) {
+        PLOG(ERROR) << getId() << " failed to mount " << mDevPath << " on " << kStagingPath;
+        return -EIO;
+    }
+    if (BindMount(bindPath, getPath()) != OK) {
+        PLOG(ERROR) << getId() << " failed to bind mount " << bindPath << " on " << getPath();
+        ForceUnmount(kStagingPath);
+        return -EIO;
+    }
+
+    return OK;
+}
+
+status_t EmulatedVolume::doUnmount(bool detach /* = false */) {
+    ForceUnmount(getPath(), detach);
+    ForceUnmount(kStagingPath, detach);
+
+    rmdir(getPath().c_str());
+    rmdir(kStagingPath.c_str());
+
+    return OK;
+}
+
+}  // namespace volmgr
+}  // namespace android