summaryrefslogtreecommitdiff
authorBaocheng Sun <baocheng.sun@amlogic.com>2018-01-12 01:59:41 (GMT)
committer Baocheng Sun <baocheng.sun@amlogic.com>2018-01-19 05:58:09 (GMT)
commit99b34704afebdf2c4ae0eee2aeeaa25dbd016d1a (patch)
tree393cc9657cac461c0467e7f85ba13aac70d01edf
parent3e08e2c68e393382cb647334d34997bfff56c8b1 (diff)
downloaddroidvold-99b34704afebdf2c4ae0eee2aeeaa25dbd016d1a.zip
droidvold-99b34704afebdf2c4ae0eee2aeeaa25dbd016d1a.tar.gz
droidvold-99b34704afebdf2c4ae0eee2aeeaa25dbd016d1a.tar.bz2
droidvold: add sdcardfs support [1/4]
PD# 153584 add sdcardfs support Change-Id: I6638694ea159126cf99e3934ddda4d5e18626371
Diffstat
-rw-r--r--Android.mk1
-rw-r--r--Disk.cpp9
-rw-r--r--Disk.h1
-rw-r--r--DroidVold.cpp9
-rw-r--r--DroidVold.h1
-rw-r--r--PublicVolume.cpp50
-rw-r--r--PublicVolume.h3
-rw-r--r--VolumeManager.cpp11
-rw-r--r--VolumeManager.h1
-rw-r--r--fs/Sdcardfs.cpp171
-rw-r--r--fs/Sdcardfs.h38
-rw-r--r--main.cpp2
12 files changed, 285 insertions, 12 deletions
diff --git a/Android.mk b/Android.mk
index bf85877..6356425 100644
--- a/Android.mk
+++ b/Android.mk
@@ -12,6 +12,7 @@ common_src_files := \
fs/Exfat.cpp \
fs/Hfsplus.cpp \
fs/Iso9660.cpp \
+ fs/Sdcardfs.cpp \
Disk.cpp \
VolumeBase.cpp \
PublicVolume.cpp \
diff --git a/Disk.cpp b/Disk.cpp
index 1489252..8bd3e41 100644
--- a/Disk.cpp
+++ b/Disk.cpp
@@ -135,6 +135,15 @@ std::shared_ptr<VolumeBase> Disk::findVolume(const std::string& id) {
return nullptr;
}
+std::shared_ptr<VolumeBase> Disk::findVolumeByPath(const std::string& path) {
+ for (auto vol : mVolumes) {
+ if (vol->getPath() == path) {
+ return vol;
+ }
+ }
+ return nullptr;
+}
+
void Disk::listVolumes(VolumeBase::Type type, std::list<std::string>& list) {
for (auto vol : mVolumes) {
if (vol->getType() == type) {
diff --git a/Disk.h b/Disk.h
index 6283417..a623a62 100644
--- a/Disk.h
+++ b/Disk.h
@@ -66,6 +66,7 @@ public:
int getFlags() { return mFlags; }
std::shared_ptr<VolumeBase> findVolume(const std::string& id);
+ std::shared_ptr<VolumeBase> findVolumeByPath(const std::string& path);
void listVolumes(VolumeBase::Type type, std::list<std::string>& list);
diff --git a/DroidVold.cpp b/DroidVold.cpp
index 3d6086a..a1db38f 100644
--- a/DroidVold.cpp
+++ b/DroidVold.cpp
@@ -181,6 +181,15 @@ void DroidVold::sendBroadcast(int event, const std::string& message) {
*/
}
+Return<int32_t> DroidVold::getDiskFlag(const hidl_string &path) {
+ int32_t flag = 0;
+ std::string mPath = path;
+
+ flag = VolumeManager::Instance()->getDiskFlag(mPath);
+
+ return flag;
+}
+
} // namespace implementation
} // namespace V1_0
} // namespace droidvold
diff --git a/DroidVold.h b/DroidVold.h
index 346742f..0c576cf 100644
--- a/DroidVold.h
+++ b/DroidVold.h
@@ -56,6 +56,7 @@ public:
Return<Result> mount(const hidl_string& id, uint32_t flag, uint32_t uid) override;
Return<Result> unmount(const hidl_string& id) override;
Return<Result> format(const hidl_string& id, const hidl_string& type) override;
+ Return<int32_t> getDiskFlag(const hidl_string &path) override;
static DroidVold *Instance();
void sendBroadcast(int event, const std::string& message);
diff --git a/PublicVolume.cpp b/PublicVolume.cpp
index 1a41ab0..1977f24 100644
--- a/PublicVolume.cpp
+++ b/PublicVolume.cpp
@@ -20,6 +20,7 @@
#include "fs/Hfsplus.h"
#include "fs/Iso9660.h"
#include "fs/Ext4.h"
+#include "fs/Sdcardfs.h"
#include "PublicVolume.h"
#include "Utils.h"
#include "VolumeManager.h"
@@ -46,7 +47,7 @@ namespace droidvold {
static const char* kChownPath = "/system/bin/chown";
PublicVolume::PublicVolume(const std::string& physicalDevName, const bool isPhysical) :
- VolumeBase(Type::kPublic), mFusePid(0), mJustPhysicalDev(isPhysical) {
+ VolumeBase(Type::kPublic), mJustPhysicalDev(isPhysical) {
setId(physicalDevName);
mDevPath = StringPrintf("/dev/block/%s", getId().c_str());
}
@@ -108,6 +109,11 @@ status_t PublicVolume::doMount() {
}
mRawPath = StringPrintf("/mnt/media_rw/%s", stableName.c_str());
+ mFuseDefault = StringPrintf("/mnt/runtime/default/%s", stableName.c_str());
+ mFuseRead = StringPrintf("/mnt/runtime/read/%s", stableName.c_str());
+ mFuseWrite = StringPrintf("/mnt/runtime/write/%s", stableName.c_str());
+
+
VolumeManager *vm = VolumeManager::Instance();
//if (!mJustPhysicalDev && mFsType == "vfat") {
if (mFsType == "vfat") {
@@ -124,13 +130,27 @@ status_t PublicVolume::doMount() {
}
setInternalPath(mRawPath);
- setPath(mRawPath);
+
+ if (getMountFlags() & MountFlags::kVisible) {
+ setPath(StringPrintf("/storage/%s", stableName.c_str()));
+ } else {
+ setPath(mRawPath);
+ }
if (prepareDir(mRawPath, 0700, AID_ROOT, AID_ROOT)) {
PLOG(ERROR) << getId() << " failed to create mount points";
return -errno;
}
+ if (prepareDir(mFuseDefault.c_str(), 0700, AID_ROOT, AID_ROOT) ||
+ prepareDir(mFuseRead.c_str(), 0700, AID_ROOT, AID_ROOT) ||
+ prepareDir(mFuseWrite.c_str(), 0700, AID_ROOT, AID_ROOT)) {
+ rmdir(mRawPath.c_str());
+ PLOG(ERROR) << getId() << " failed to create FUSE mount points";
+ return -errno;
+ }
+
+
// Mount device
status_t mountStatus = -1;
@@ -156,6 +176,7 @@ status_t PublicVolume::doMount() {
if (mountStatus) {
PLOG(ERROR) << " failed to mount " << mDevPath << " as " << mFsType;
+ rmdir(mRawPath.c_str());
return -EIO;
} else {
LOG(INFO) << "successfully mount " << mDevPath << " as " << mFsType;
@@ -180,6 +201,16 @@ status_t PublicVolume::doMount() {
LOG(VERBOSE) << "Finished restorecon of " << mRawPath;
}
+
+ // mount sdcardfs
+ if (getMountFlags() & MountFlags::kPrimary) {
+ sdcardfs::run_sdcardfs(mRawPath, stableName,
+ 1023, 1023, getMountUserId(), false, true);
+ } else {
+ sdcardfs::run_sdcardfs(mRawPath, stableName,
+ 1023, 1023, getMountUserId(), false, false);
+ }
+
return OK;
}
@@ -200,16 +231,19 @@ status_t PublicVolume::doUnmount() {
vm->unmountLoopIfNeed(stableName.c_str());
#endif
+ ForceUnmount(mFuseDefault);
+ ForceUnmount(mFuseRead);
+ ForceUnmount(mFuseWrite);
ForceUnmount(mRawPath);
- if (mFusePid > 0) {
- kill(mFusePid, SIGTERM);
- TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, 0));
- mFusePid = 0;
- }
-
+ rmdir(mFuseDefault.c_str());
+ rmdir(mFuseRead.c_str());
+ rmdir(mFuseWrite.c_str());
rmdir(mRawPath.c_str());
+ mFuseDefault.clear();
+ mFuseRead.clear();
+ mFuseWrite.clear();
mRawPath.clear();
return OK;
diff --git a/PublicVolume.h b/PublicVolume.h
index 787776c..b196a4d 100644
--- a/PublicVolume.h
+++ b/PublicVolume.h
@@ -66,9 +66,6 @@ private:
std::string mFuseRead;
std::string mFuseWrite;
- /* PID of FUSE wrapper */
- pid_t mFusePid;
-
/* Filesystem type */
std::string mFsType;
/* Filesystem UUID */
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index d6bdc0d..5b82180 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -424,3 +424,14 @@ void VolumeManager::coldboot(const char *path) {
closedir(d);
}
}
+int VolumeManager::getDiskFlag(const std::string &path) {
+ if (mDebug)
+ LOG(DEBUG) << "getdisk flag path=" << path;
+ for (auto disk : mDisks) {
+ auto vol = disk->findVolumeByPath(path);
+ if (vol != nullptr) {
+ return disk->getFlags();
+ }
+ }
+ return 0;
+}
diff --git a/VolumeManager.h b/VolumeManager.h
index 73b5b2b..59b8c69 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -112,6 +112,7 @@ public:
bool isMountpointMounted(const char *mp);
int mkdirs(char* path);
void coldboot(const char *path);
+ int getDiskFlag(const std::string &path);
private:
VolumeManager();
diff --git a/fs/Sdcardfs.cpp b/fs/Sdcardfs.cpp
new file mode 100644
index 0000000..faaa883
--- a/dev/null
+++ b/fs/Sdcardfs.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2008 The Android Open Source 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 <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/mount.h>
+#include <sys/wait.h>
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+
+#include <linux/kdev_t.h>
+
+#define LOG_TAG "droidVold"
+
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+#include <android-base/file.h>
+#include <android-base/macros.h>
+#include <android-base/stringprintf.h>
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#include <cutils/multiuser.h>
+
+#include <private/android_filesystem_config.h>
+
+#include "Utils.h"
+
+#define PROP_SDCARDFS_DEVICE "ro.sys.sdcardfs"
+#define PROP_SDCARDFS_USER "persist.sys.sdcardfs"
+
+using android::base::StringPrintf;
+
+namespace android {
+namespace droidvold {
+namespace sdcardfs {
+
+static bool supports_sdcardfs(void) {
+ std::string filesystems;
+ if (!android::base::ReadFileToString("/proc/filesystems", &filesystems)) {
+ PLOG(ERROR) << "Could not read /proc/filesystems";
+ return false;
+ }
+ for (const auto& fs : android::base::Split(filesystems, "\n")) {
+ if (fs.find("sdcardfs") != std::string::npos) return true;
+ }
+ return false;
+}
+
+static bool should_use_sdcardfs(void) {
+ char property[PROPERTY_VALUE_MAX];
+
+ // Allow user to have a strong opinion about state
+ property_get(PROP_SDCARDFS_USER, property, "");
+ if (!strcmp(property, "force_on")) {
+ LOG(WARNING) << "User explicitly enabled sdcardfs";
+ return supports_sdcardfs();
+ } else if (!strcmp(property, "force_off")) {
+ LOG(WARNING) << "User explicitly disabled sdcardfs";
+ return false;
+ }
+
+ // Fall back to device opinion about state
+ if (property_get_bool(PROP_SDCARDFS_DEVICE, true)) {
+ LOG(WARNING) << "Device explicitly enabled sdcardfs";
+ return supports_sdcardfs();
+ } else {
+ LOG(WARNING) << "Device explicitly disabled sdcardfs";
+ return false;
+ }
+}
+
+
+static bool sdcardfs_setup(const std::string& source_path, const std::string& dest_path, uid_t fsuid,
+ gid_t fsgid, bool multi_user, userid_t userid, gid_t gid, mode_t mask) {
+ std::string opts = android::base::StringPrintf("fsuid=%d,fsgid=%d,%smask=%d,userid=%d,gid=%d",
+ fsuid, fsgid, multi_user?"multiuser,":"", mask, userid, gid);
+
+ if (mount(source_path.c_str(), dest_path.c_str(), "sdcardfs",
+ MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opts.c_str()) == -1) {
+ PLOG(ERROR) << "failed to mount sdcardfs filesystem";
+ return false;
+ }
+
+ return true;
+}
+
+static bool sdcardfs_setup_bind_remount(const std::string& source_path, const std::string& dest_path,
+ gid_t gid, mode_t mask) {
+ std::string opts = android::base::StringPrintf("mask=%d,gid=%d", mask, gid);
+
+ if (mount(source_path.c_str(), dest_path.c_str(), nullptr,
+ MS_BIND, nullptr) != 0) {
+ PLOG(ERROR) << "failed to bind mount sdcardfs filesystem";
+ return false;
+ }
+
+ if (mount(source_path.c_str(), dest_path.c_str(), "none",
+ MS_REMOUNT | MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opts.c_str()) != 0) {
+ PLOG(ERROR) << "failed to mount sdcardfs filesystem";
+ if (umount2(dest_path.c_str(), MNT_DETACH))
+ PLOG(WARNING) << "Failed to unmount bind";
+ return false;
+ }
+
+ return true;
+}
+
+
+int run_sdcardfs(const std::string& source_path, const std::string& label, uid_t uid,
+ gid_t gid, userid_t userid, bool multi_user, bool full_write) {
+ std::string dest_path_default = "/mnt/runtime/default/" + label;
+ std::string dest_path_read = "/mnt/runtime/read/" + label;
+ std::string dest_path_write = "/mnt/runtime/write/" + label;
+
+ umask(0);
+ if (multi_user) {
+ // Multi-user storage is fully isolated per user, so "other"
+ // permissions are completely masked off.
+ if (!sdcardfs_setup(source_path, dest_path_default, uid, gid, multi_user, userid,
+ AID_SDCARD_RW, 0006)
+ || !sdcardfs_setup_bind_remount(dest_path_default, dest_path_read, AID_EVERYBODY, 0027)
+ || !sdcardfs_setup_bind_remount(dest_path_default, dest_path_write,
+ AID_EVERYBODY, full_write ? 0007 : 0027)) {
+ PLOG(ERROR) << "failed to sdcardfs_setup";
+ }
+ } else {
+ // Physical storage is readable by all users on device, but
+ // the Android directories are masked off to a single user
+ // deep inside attr_from_stat().
+ if (!sdcardfs_setup(source_path, dest_path_default, uid, gid, multi_user, userid,
+ AID_SDCARD_RW, 0006)
+ || !sdcardfs_setup_bind_remount(dest_path_default, dest_path_read,
+ AID_EVERYBODY, full_write ? 0027 : 0022)
+ || !sdcardfs_setup_bind_remount(dest_path_default, dest_path_write,
+ AID_EVERYBODY, full_write ? 0007 : 0022)) {
+ PLOG(ERROR) << "failed to sdcardfs_setup";
+ }
+ }
+
+ return 0;
+}
+
+
+} // namespace sdcardfs
+} // namespace droidvold
+} // namespace android
diff --git a/fs/Sdcardfs.h b/fs/Sdcardfs.h
new file mode 100644
index 0000000..c43dd0d
--- a/dev/null
+++ b/fs/Sdcardfs.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008 The Android Open Source 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.
+ */
+
+#ifndef ANDROID_VOLD_SDCARD_H
+#define ANDROID_VOLD_SDCARD_H
+
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string>
+#include <cutils/multiuser.h>
+
+namespace android {
+namespace droidvold {
+namespace sdcardfs {
+
+int run_sdcardfs(const std::string& source_path, const std::string& label, uid_t uid,
+ gid_t gid, userid_t userid, bool multi_user, bool full_write);
+
+} // namespace sdcardfs
+} // namespace droidvold
+} // namespace android
+
+#endif
diff --git a/main.cpp b/main.cpp
index aed5430..6d4abae 100644
--- a/main.cpp
+++ b/main.cpp
@@ -67,7 +67,7 @@ int main(int argc, char** argv) {
LOG(INFO) << "doildVold 1.0 firing up";
- android::ProcessState::initWithDriver("/dev/hwbinder");
+ //android::ProcessState::initWithDriver("/dev/hwbinder");
configureRpcThreadpool(4, true);
VolumeManager *vm;