Setup Android/, Android/data and Android/obb dirs correctly.
Normally sdcardfs takes care of setting up these directories on-demand,
for example when an app requests its private data directory to be
created. On devices without sdcardfs however, we ourselves need to make
sure to setup the UID/GID of these directories correctly.
Introduce a new PrepareAndroidDirs() function which sets the dirs up
correctly. On devices without sdcardfs, that means:
Path UID GID mode
/Android media_rw media_rw 771
/Android/data media_rw ext_data_rw 771
/Android/obb media_rw ext_obb_rw 771
Bug: 146419093
Test: wipe Android/, reboot, with and without sdcardfs, verify
contents
Change-Id: I3a879089422c7fc449b6a3e6f1c4b386b86687a4
diff --git a/model/EmulatedVolume.cpp b/model/EmulatedVolume.cpp
index 082dea5..8f8c87a 100644
--- a/model/EmulatedVolume.cpp
+++ b/model/EmulatedVolume.cpp
@@ -73,17 +73,8 @@
}
}
-// Creates a bind mount from source to target, creating the source (!) directory
-// if not yet present.
+// Creates a bind mount from source to target
static status_t doFuseBindMount(const std::string& source, const std::string& target) {
- if (access(source.c_str(), F_OK) != 0) {
- // Android path may not exist yet if users has just been created; create it on
- // the lower fs.
- if (fs_prepare_dir(source.c_str(), 0771, AID_MEDIA_RW, AID_MEDIA_RW) != 0) {
- PLOG(ERROR) << "Failed to create " << source;
- return -errno;
- }
- }
LOG(INFO) << "Bind mounting " << source << " on " << target;
auto status = BindMount(source, target);
if (status != OK) {
@@ -232,11 +223,19 @@
LOG(INFO) << "Mounting emulated fuse volume";
android::base::unique_fd fd;
int user_id = getMountUserId();
- int result = MountUserFuse(user_id, getInternalPath(), label, &fd);
+ auto volumeRoot = getRootPath();
- if (result != 0) {
+ // Make sure Android/ dirs exist for bind mounting
+ status_t res = PrepareAndroidDirs(volumeRoot);
+ if (res != OK) {
+ LOG(ERROR) << "Failed to prepare Android/ directories";
+ return res;
+ }
+
+ res = MountUserFuse(user_id, getInternalPath(), label, &fd);
+ if (res != 0) {
PLOG(ERROR) << "Failed to mount emulated fuse volume";
- return -result;
+ return res;
}
mFuseMounted = true;
@@ -252,7 +251,7 @@
}
// Only do the bind-mounts when we know for sure the FUSE daemon can resolve the path.
- status_t res = mountFuseBindMounts();
+ res = mountFuseBindMounts();
if (res != OK) {
fd.reset();
doUnmount();
@@ -317,5 +316,12 @@
return OK;
}
+std::string EmulatedVolume::getRootPath() const {
+ int user_id = getMountUserId();
+ std::string volumeRoot = StringPrintf("%s/%d", getInternalPath().c_str(), user_id);
+
+ return volumeRoot;
+}
+
} // namespace vold
} // namespace android
diff --git a/model/EmulatedVolume.h b/model/EmulatedVolume.h
index 4f76a60..3f1b2e3 100644
--- a/model/EmulatedVolume.h
+++ b/model/EmulatedVolume.h
@@ -40,6 +40,7 @@
explicit EmulatedVolume(const std::string& rawPath, int userId);
EmulatedVolume(const std::string& rawPath, dev_t device, const std::string& fsUuid, int userId);
virtual ~EmulatedVolume();
+ std::string getRootPath() const override;
protected:
status_t doMount() override;
diff --git a/model/VolumeBase.cpp b/model/VolumeBase.cpp
index 636c065..687d4f7 100644
--- a/model/VolumeBase.cpp
+++ b/model/VolumeBase.cpp
@@ -274,6 +274,11 @@
return -ENOTSUP;
}
+std::string VolumeBase::getRootPath() const {
+ // Usually the same as the internal path, except for emulated volumes.
+ return getInternalPath();
+}
+
std::ostream& VolumeBase::operator<<(std::ostream& stream) const {
return stream << " VolumeBase{id=" << mId << ",mountFlags=" << mMountFlags
<< ",mountUserId=" << mMountUserId << "}";
diff --git a/model/VolumeBase.h b/model/VolumeBase.h
index 1d88d1b..078bb0c 100644
--- a/model/VolumeBase.h
+++ b/model/VolumeBase.h
@@ -110,6 +110,8 @@
status_t unmount();
status_t format(const std::string& fsType);
+ virtual std::string getRootPath() const;
+
std::ostream& operator<<(std::ostream& stream) const;
protected: