Use unique_fd

Also allow the state just before doMount() as a valid state for setting
fuse fd.
Test: manual
BUG:140173712

Change-Id: I012f8a83fef00e68f33010954fbc2ebc53cf8f1d
diff --git a/Utils.cpp b/Utils.cpp
index bd3d452..5e284b2 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -985,7 +985,8 @@
     return true;
 }
 
-int MountUserFuse(userid_t user_id, const std::string& relative_path, int* device_fd) {
+int MountUserFuse(userid_t user_id, const std::string& relative_path,
+                  android::base::unique_fd* fuse_fd) {
     std::string path(StringPrintf("/mnt/user/%d/%s", user_id, relative_path.c_str()));
 
     // Force remove the existing mount before we attempt to prepare the
@@ -1004,9 +1005,9 @@
         return -1;
     }
 
-    // Open device fd.
-    *device_fd = open("/dev/fuse", O_RDWR | O_CLOEXEC);
-    if (*device_fd == -1) {
+    // Open fuse fd.
+    fuse_fd->reset(open("/dev/fuse", O_RDWR | O_CLOEXEC));
+    if (fuse_fd->get() == -1) {
         PLOG(ERROR) << "Failed to open /dev/fuse";
         return -1;
     }
@@ -1018,7 +1019,7 @@
         "rootmode=40000,"
         "allow_other,"
         "user_id=0,group_id=0,",
-        *device_fd);
+        fuse_fd->get());
 
     const int result_int =
         TEMP_FAILURE_RETRY(mount("/dev/fuse", path.c_str(), "fuse",
diff --git a/Utils.h b/Utils.h
index cd55b09..e0102a7 100644
--- a/Utils.h
+++ b/Utils.h
@@ -20,6 +20,7 @@
 #include "KeyBuffer.h"
 
 #include <android-base/macros.h>
+#include <android-base/unique_fd.h>
 #include <cutils/multiuser.h>
 #include <selinux/selinux.h>
 #include <utils/Errors.h>
@@ -150,7 +151,8 @@
 
 bool writeStringToFile(const std::string& payload, const std::string& filename);
 
-int MountUserFuse(userid_t user_id, const std::string& relative_path, int* device_fd);
+int MountUserFuse(userid_t user_id, const std::string& relative_path,
+                  android::base::unique_fd* fuse_fd);
 
 }  // namespace vold
 }  // namespace android
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index 9004b40..9b223c7 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -345,7 +345,7 @@
         return translate(res);
     }
 
-    _aidl_return->reset(vol->getDeviceFd());
+    _aidl_return->reset(dup(vol->getFuseFd().get()));
     if (_aidl_return->get() == -1) {
         // Let's not return invalid fd since binder will not allow null fds. Instead give it a
         // default value.
diff --git a/model/EmulatedVolume.cpp b/model/EmulatedVolume.cpp
index ca314ef..022ff42 100644
--- a/model/EmulatedVolume.cpp
+++ b/model/EmulatedVolume.cpp
@@ -88,13 +88,13 @@
 
     if (isFuse) {
         LOG(INFO) << "Mounting emulated fuse volume";
-        int fd = -1;
+        android::base::unique_fd fd;
         int result = MountUserFuse(getMountUserId(), label, &fd);
         if (result != 0) {
             PLOG(ERROR) << "Failed to mount emulated fuse volume";
             return -result;
         }
-        setDeviceFd(fd);
+        setFuseFd(std::move(fd));
         return OK;
     }
 
@@ -170,7 +170,7 @@
         }
 
         rmdir(path.c_str());
-        setDeviceFd(-1);
+        setFuseFd(android::base::unique_fd());
         return OK;
     }
 
diff --git a/model/PublicVolume.cpp b/model/PublicVolume.cpp
index 2c0b4cc..ebcb91a 100644
--- a/model/PublicVolume.cpp
+++ b/model/PublicVolume.cpp
@@ -173,13 +173,13 @@
 
     if (isFuse) {
         LOG(INFO) << "Mounting public fuse volume";
-        int fd = -1;
+        android::base::unique_fd fd;
         int result = MountUserFuse(getMountUserId(), stableName, &fd);
         if (result != 0) {
             LOG(ERROR) << "Failed to mount public fuse volume";
             return -result;
         }
-        setDeviceFd(fd);
+        setFuseFd(std::move(fd));
         return OK;
     }
 
@@ -265,7 +265,7 @@
         }
 
         rmdir(path.c_str());
-        setDeviceFd(-1);
+        setFuseFd(android::base::unique_fd());
         return OK;
     }
 
diff --git a/model/VolumeBase.cpp b/model/VolumeBase.cpp
index fa007ad..d6e4288 100644
--- a/model/VolumeBase.cpp
+++ b/model/VolumeBase.cpp
@@ -143,13 +143,13 @@
     return OK;
 }
 
-status_t VolumeBase::setDeviceFd(int deviceFd) {
-    if ((mState != State::kChecking)) {
-        LOG(WARNING) << getId() << " device fd change requires state checking";
+status_t VolumeBase::setFuseFd(android::base::unique_fd fuseFd) {
+    if ((mState != State::kChecking) && (mState != State::kEjecting)) {
+        LOG(WARNING) << getId() << " fuse fd change requires state checking or ejecting";
         return -EBUSY;
     }
 
-    mDeviceFd.reset(deviceFd);
+    mFuseFd.reset(std::move(fuseFd.get()));
     return OK;
 }
 
diff --git a/model/VolumeBase.h b/model/VolumeBase.h
index fa9eee4..6afb88e 100644
--- a/model/VolumeBase.h
+++ b/model/VolumeBase.h
@@ -87,7 +87,7 @@
     State getState() const { return mState; }
     const std::string& getPath() const { return mPath; }
     const std::string& getInternalPath() const { return mInternalPath; }
-    int getDeviceFd() const { return dup(mDeviceFd.get()); }
+    const android::base::unique_fd& getFuseFd() const { return mFuseFd; }
 
     status_t setDiskId(const std::string& diskId);
     status_t setPartGuid(const std::string& partGuid);
@@ -122,7 +122,7 @@
     status_t setId(const std::string& id);
     status_t setPath(const std::string& path);
     status_t setInternalPath(const std::string& internalPath);
-    status_t setDeviceFd(int deviceFd);
+    status_t setFuseFd(android::base::unique_fd fuseFd);
 
     android::sp<android::os::IVoldListener> getListener() const;
 
@@ -150,7 +150,7 @@
     /* Flag indicating that volume should emit no events */
     bool mSilent;
     /* The filedescriptor for the fuse device, if the volume uses fuse, or -1 otherwise */
-    android::base::unique_fd mDeviceFd;
+    android::base::unique_fd mFuseFd;
 
     /* Volumes stacked on top of this volume */
     std::list<std::shared_ptr<VolumeBase>> mVolumes;