Compare commits

...

10 Commits

Author SHA1 Message Date
lambdadroid 981e9b47b1 vold: Accept Linux GPT partitions on external SD cards
2 years ago
Jani Lusikka 943774c8e5 Fix the group permissions of the sdcard root.
2 years ago
Sam Mortimer feca80c63d vold ext4/f2fs: do not use dirsync if we're mounting adopted storage
2 years ago
Jani Lusikka f4028eedc5 vold: Mount ext4/f2fs portable storage with sdcard_posix
2 years ago
Tom Marshall 76c235ffe3 vold: Honor mount options for ext4/f2fs partitions
2 years ago
Tom Marshall af516f8875 vold: Support internal storage partitions
2 years ago
Michael Bestas c803d524ea vold: Fix fsck on public volumes
2 years ago
Dan Pasanen 584c493f5e vold: add support for more filesystems for public storage
2 years ago
Luca Stefani 6220c269ed Revert "Switch to exfatprogs compatible fsck parameter"
3 years ago
Eric Biggers ca79199a58
cryptfs: try harder to unmount subdirectory mounts
3 years ago

@ -140,8 +140,10 @@ cc_library_static {
"fs/Exfat.cpp",
"fs/Ext4.cpp",
"fs/F2fs.cpp",
"fs/Ntfs.cpp",
"fs/Vfat.cpp",
"model/Disk.cpp",
"model/DiskPartition.cpp",
"model/EmulatedVolume.cpp",
"model/ObbVolume.cpp",
"model/PrivateVolume.cpp",

@ -1000,6 +1000,10 @@ bool IsFilesystemSupported(const std::string& fsType) {
PLOG(ERROR) << "Failed to read supported filesystems";
return false;
}
/* fuse filesystems */
supported.append("fuse\tntfs\n");
return supported.find(fsType + "\n") != std::string::npos;
}

@ -240,8 +240,13 @@ void VolumeManager::handleBlockEvent(NetlinkEvent* evt) {
flags |= android::vold::Disk::Flags::kUsb;
}
auto disk =
new android::vold::Disk(eventPath, device, source->getNickname(), flags);
android::vold::Disk* disk = (source->getPartNum() == -1) ?
new android::vold::Disk(eventPath, device,
source->getNickname(), flags) :
new android::vold::DiskPartition(eventPath, device,
source->getNickname(), flags,
source->getPartNum(),
source->getFsType(), source->getMntOpts());
handleDiskAdded(std::shared_ptr<android::vold::Disk>(disk));
break;
}

@ -37,6 +37,7 @@
#include "android/os/IVoldListener.h"
#include "model/Disk.h"
#include "model/DiskPartition.h"
#include "model/VolumeBase.h"
class VolumeManager {
@ -62,20 +63,30 @@ class VolumeManager {
class DiskSource {
public:
DiskSource(const std::string& sysPattern, const std::string& nickname, int flags)
: mSysPattern(sysPattern), mNickname(nickname), mFlags(flags) {}
DiskSource(const std::string& sysPattern, const std::string& nickname,
int partnum, int flags,
const std::string& fstype, const std::string mntopts)
: mSysPattern(sysPattern), mNickname(nickname),
mPartNum(partnum), mFlags(flags),
mFsType(fstype), mMntOpts(mntopts) {}
bool matches(const std::string& sysPath) {
return !fnmatch(mSysPattern.c_str(), sysPath.c_str(), 0);
}
const std::string& getNickname() const { return mNickname; }
int getPartNum() const { return mPartNum; }
int getFlags() const { return mFlags; }
const std::string& getFsType() { return mFsType; }
const std::string& getMntOpts() { return mMntOpts; }
private:
std::string mSysPattern;
std::string mNickname;
int mPartNum;
int mFlags;
std::string mFsType;
std::string mMntOpts;
};
void addDiskSource(const std::shared_ptr<DiskSource>& diskSource);

@ -1744,20 +1744,23 @@ static void ensure_subdirectory_unmounted(const char *prefix) {
[](const std::string& s1, const std::string& s2) {return s1.length() > s2.length(); });
for (std::string& mount_point : umount_points) {
umount(mount_point.c_str());
SLOGW("umount sub-directory mount %s\n", mount_point.c_str());
SLOGW("unmounting sub-directory mount %s\n", mount_point.c_str());
if (umount(mount_point.c_str()) != 0) {
SLOGE("unmounting %s failed: %s\n", mount_point.c_str(), strerror(errno));
}
}
}
static int wait_and_unmount(const char* mountpoint) {
int i, err, rc;
// Subdirectory mount will cause a failure of umount.
ensure_subdirectory_unmounted(mountpoint);
#define WAIT_UNMOUNT_COUNT 200
/* Now umount the tmpfs filesystem */
for (i = 0; i < WAIT_UNMOUNT_COUNT; i++) {
// Subdirectory mount will cause a failure of umount.
ensure_subdirectory_unmounted(mountpoint);
if (umount(mountpoint) == 0) {
break;
}

@ -41,7 +41,7 @@ bool IsSupported() {
status_t Check(const std::string& source) {
std::vector<std::string> cmd;
cmd.push_back(kFsckPath);
cmd.push_back("-y");
cmd.push_back("-a");
cmd.push_back(source);
int rc = ForkExecvp(cmd, nullptr, sFsckUntrustedContext);

@ -38,6 +38,7 @@
#include <cutils/properties.h>
#include <fscrypt/fscrypt.h>
#include <logwrap/logwrap.h>
#include <private/android_filesystem_config.h>
#include <selinux/selinux.h>
#include "Ext4.h"
@ -60,7 +61,7 @@ bool IsSupported() {
IsFilesystemSupported("ext4");
}
status_t Check(const std::string& source, const std::string& target) {
status_t Check(const std::string& source, const std::string& target, bool trusted) {
// The following is shamelessly borrowed from fs_mgr.c, so it should be
// kept in sync with any changes over there.
@ -116,33 +117,50 @@ status_t Check(const std::string& source, const std::string& target) {
cmd.push_back("-y");
cmd.push_back(c_source);
// ext4 devices are currently always trusted
return ForkExecvp(cmd, nullptr, sFsckContext);
return ForkExecvp(cmd, nullptr, trusted ? sFsckContext : sFsckUntrustedContext);
}
return 0;
}
status_t Mount(const std::string& source, const std::string& target, bool ro, bool remount,
bool executable) {
bool executable, const std::string& opts /* = "" */, bool trusted, bool portable) {
int rc;
unsigned long flags;
std::string data(opts);
if (portable) {
if (!data.empty()) {
data += ",";
}
data += "context=u:object_r:sdcard_posix:s0";
}
const char* c_source = source.c_str();
const char* c_target = target.c_str();
const char* c_data = data.c_str();
flags = MS_NOATIME | MS_NODEV | MS_NOSUID | MS_DIRSYNC;
flags = MS_NOATIME | MS_NODEV | MS_NOSUID;
// Only use MS_DIRSYNC if we're not mounting adopted storage
if (!trusted) {
flags |= MS_DIRSYNC;
}
flags |= (executable ? 0 : MS_NOEXEC);
flags |= (ro ? MS_RDONLY : 0);
flags |= (remount ? MS_REMOUNT : 0);
rc = mount(c_source, c_target, "ext4", flags, NULL);
rc = mount(c_source, c_target, "ext4", flags, c_data);
if (portable && rc == 0) {
chown(c_target, AID_MEDIA_RW, AID_MEDIA_RW);
chmod(c_target, 0775);
}
if (rc && errno == EROFS) {
LOG(ERROR) << source << " appears to be a read only filesystem - retrying mount RO";
flags |= MS_RDONLY;
rc = mount(c_source, c_target, "ext4", flags, NULL);
rc = mount(c_source, c_target, "ext4", flags, c_data);
}
return rc;

@ -27,9 +27,10 @@ namespace ext4 {
bool IsSupported();
status_t Check(const std::string& source, const std::string& target);
status_t Check(const std::string& source, const std::string& target, bool trusted);
status_t Mount(const std::string& source, const std::string& target, bool ro, bool remount,
bool executable);
bool executable, const std::string& opts = "", bool trusted = false,
bool portable = false);
status_t Format(const std::string& source, unsigned long numSectors, const std::string& target);
status_t Resize(const std::string& source, unsigned long numSectors);

@ -21,10 +21,12 @@
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <fscrypt/fscrypt.h>
#include <private/android_filesystem_config.h>
#include <string>
#include <vector>
#include <sys/stat.h>
#include <sys/mount.h>
using android::base::StringPrintf;
@ -41,26 +43,47 @@ bool IsSupported() {
IsFilesystemSupported("f2fs");
}
status_t Check(const std::string& source) {
status_t Check(const std::string& source, bool trusted) {
std::vector<std::string> cmd;
cmd.push_back(kFsckPath);
cmd.push_back("-a");
cmd.push_back(source);
// f2fs devices are currently always trusted
return ForkExecvp(cmd, nullptr, sFsckContext);
return ForkExecvp(cmd, nullptr, trusted ? sFsckContext : sFsckUntrustedContext);
}
status_t Mount(const std::string& source, const std::string& target) {
status_t Mount(const std::string& source, const std::string& target,
const std::string& opts /* = "" */, bool trusted, bool portable) {
std::string data(opts);
if (portable) {
if (!data.empty()) {
data += ",";
}
data += "context=u:object_r:sdcard_posix:s0";
}
const char* c_source = source.c_str();
const char* c_target = target.c_str();
unsigned long flags = MS_NOATIME | MS_NODEV | MS_NOSUID | MS_DIRSYNC;
const char* c_data = data.c_str();
unsigned long flags = MS_NOATIME | MS_NODEV | MS_NOSUID;
// Only use MS_DIRSYNC if we're not mounting adopted storage
if (!trusted) {
flags |= MS_DIRSYNC;
}
int res = mount(c_source, c_target, "f2fs", flags, c_data);
if (portable && res == 0) {
chown(c_target, AID_MEDIA_RW, AID_MEDIA_RW);
chmod(c_target, 0775);
}
int res = mount(c_source, c_target, "f2fs", flags, NULL);
if (res != 0) {
PLOG(ERROR) << "Failed to mount " << source;
if (errno == EROFS) {
res = mount(c_source, c_target, "f2fs", flags | MS_RDONLY, NULL);
res = mount(c_source, c_target, "f2fs", flags | MS_RDONLY, c_data);
if (res != 0) {
PLOG(ERROR) << "Failed to mount read-only " << source;
}

@ -27,8 +27,10 @@ namespace f2fs {
bool IsSupported();
status_t Check(const std::string& source);
status_t Mount(const std::string& source, const std::string& target);
status_t Check(const std::string& source, bool trusted);
status_t Mount(const std::string& source, const std::string& target,
const std::string& opts = "", bool trusted = false,
bool portable = false);
status_t Format(const std::string& source);
} // namespace f2fs

@ -0,0 +1,104 @@
/*
* Copyright (C) 2015 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 <sys/mount.h>
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <logwrap/logwrap.h>
#include "Ntfs.h"
#include "Utils.h"
using android::base::StringPrintf;
namespace android {
namespace vold {
namespace ntfs {
static const char* kMkfsPath = "/system/bin/mkfs.ntfs";
static const char* kFsckPath = "/system/bin/fsck.ntfs";
static const char* kMountPath = "/system/bin/mount.ntfs";
bool IsSupported() {
return access(kMkfsPath, X_OK) == 0
&& access(kFsckPath, X_OK) == 0
&& access(kMountPath, X_OK) == 0
&& IsFilesystemSupported("ntfs");
}
status_t Check(const std::string& source) {
std::vector<std::string> cmd;
cmd.push_back(kFsckPath);
cmd.push_back("-n");
cmd.push_back(source);
int rc = ForkExecvp(cmd, nullptr, sFsckUntrustedContext);
if (rc == 0) {
LOG(INFO) << "Check OK";
return 0;
} else {
LOG(ERROR) << "Check failed (code " << rc << ")";
errno = EIO;
return -1;
}
}
status_t Mount(const std::string& source, const std::string& target, int ownerUid, int ownerGid,
int permMask) {
auto mountData = android::base::StringPrintf("utf8,uid=%d,gid=%d,fmask=%o,dmask=%o,"
"shortname=mixed,nodev,nosuid,dirsync,noatime,"
"noexec", ownerUid, ownerGid, permMask, permMask);
std::vector<std::string> cmd;
cmd.push_back(kMountPath);
cmd.push_back("-o");
cmd.push_back(mountData.c_str());
cmd.push_back(source.c_str());
cmd.push_back(target.c_str());
int rc = ForkExecvp(cmd);
if (rc == 0) {
LOG(INFO) << "Mount OK";
return 0;
} else {
LOG(ERROR) << "Mount failed (code " << rc << ")";
errno = EIO;
return -1;
}
}
status_t Format(const std::string& source) {
std::vector<std::string> cmd;
cmd.push_back(kMkfsPath);
cmd.push_back(source);
int rc = ForkExecvp(cmd);
if (rc == 0) {
LOG(INFO) << "Format OK";
return 0;
} else {
LOG(ERROR) << "Format failed (code " << rc << ")";
errno = EIO;
return -1;
}
return 0;
}
} // namespace ntfs
} // namespace vold
} // namespace android

@ -0,0 +1,39 @@
/*
* Copyright (C) 2015 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_NTFS_H
#define ANDROID_VOLD_NTFS_H
#include <utils/Errors.h>
#include <string>
namespace android {
namespace vold {
namespace ntfs {
bool IsSupported();
status_t Check(const std::string& source);
status_t Mount(const std::string& source, const std::string& target, int ownerUid, int ownerGid,
int permMask);
status_t Format(const std::string& source);
} // namespace ntfs
} // namespace vold
} // namespace android
#endif

@ -61,8 +61,10 @@ int main(int argc, char** argv) {
ATRACE_BEGIN("main");
LOG(DEBUG) << "Detected support for:"
<< (android::vold::IsFilesystemSupported("exfat") ? " exfat" : "")
<< (android::vold::IsFilesystemSupported("ext4") ? " ext4" : "")
<< (android::vold::IsFilesystemSupported("f2fs") ? " f2fs" : "")
<< (android::vold::IsFilesystemSupported("ntfs") ? " ntfs" : "")
<< (android::vold::IsFilesystemSupported("vfat") ? " vfat" : "");
VolumeManager* vm;
@ -240,13 +242,17 @@ static int process_config(VolumeManager* vm, bool* has_adoptable, bool* has_quot
}
if (entry.fs_mgr_flags.vold_managed) {
if (entry.fs_mgr_flags.nonremovable) {
LOG(WARNING) << "nonremovable no longer supported; ignoring volume";
continue;
}
std::string sysPattern(entry.blk_device);
std::string fstype;
if (!entry.fs_type.empty()) {
fstype = entry.fs_type;
}
std::string mntopts;
if (!entry.fs_options.empty()) {
mntopts = entry.fs_options;
}
std::string nickname(entry.label);
int partnum = entry.partnum;
int flags = 0;
if (entry.is_encryptable()) {
@ -257,9 +263,13 @@ static int process_config(VolumeManager* vm, bool* has_adoptable, bool* has_quot
android::base::GetBoolProperty("vold.debug.default_primary", false)) {
flags |= android::vold::Disk::Flags::kDefaultPrimary;
}
if (entry.fs_mgr_flags.nonremovable) {
flags |= android::vold::Disk::Flags::kNonRemovable;
}
vm->addDiskSource(std::shared_ptr<VolumeManager::DiskSource>(
new VolumeManager::DiskSource(sysPattern, nickname, flags)));
new VolumeManager::DiskSource(sysPattern, nickname, partnum, flags,
fstype, mntopts)));
}
}
return 0;

@ -77,6 +77,7 @@ static const unsigned int kMajorBlockDynamicMin = 234;
static const unsigned int kMajorBlockDynamicMax = 512;
static const char* kGptBasicData = "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7";
static const char* kGptLinuxFilesystem = "0FC63DAF-8483-4772-8E79-3D69D8477DE4";
static const char* kGptAndroidMeta = "19A710A2-B3CA-11E4-B026-10604B889DCF";
static const char* kGptAndroidExpand = "193D1EA4-B3CA-11E4-B075-10604B889DCF";
@ -171,8 +172,10 @@ status_t Disk::destroy() {
return OK;
}
void Disk::createPublicVolume(dev_t device) {
auto vol = std::shared_ptr<VolumeBase>(new PublicVolume(device));
void Disk::createPublicVolume(dev_t device,
const std::string& fstype /* = "" */,
const std::string& mntopts /* = "" */) {
auto vol = std::shared_ptr<VolumeBase>(new PublicVolume(device, fstype, mntopts));
if (mJustPartitioned) {
LOG(DEBUG) << "Device just partitioned; silently formatting";
vol->setSilent(true);
@ -401,6 +404,7 @@ status_t Disk::readPartitions() {
case 0x0b: // W95 FAT32 (LBA)
case 0x0c: // W95 FAT32 (LBA)
case 0x0e: // W95 FAT16 (LBA)
case 0x83: // Linux EXT4/F2FS/...
createPublicVolume(partDevice);
break;
}
@ -410,7 +414,8 @@ status_t Disk::readPartitions() {
if (++it == split.end()) continue;
auto partGuid = *it;
if (android::base::EqualsIgnoreCase(typeGuid, kGptBasicData)) {
if (android::base::EqualsIgnoreCase(typeGuid, kGptBasicData)
|| android::base::EqualsIgnoreCase(typeGuid, kGptLinuxFilesystem)) {
createPublicVolume(partDevice);
} else if (android::base::EqualsIgnoreCase(typeGuid, kGptAndroidExpand)) {
createPrivateVolume(partDevice, partGuid);

@ -56,6 +56,8 @@ class Disk {
/* Flag that disk is Stub disk, i.e., disk that is managed from outside
* Android (e.g., ARC++). */
kStub = 1 << 5,
/* Flag that disk is non-removable */
kNonRemovable = 1 << 6,
};
const std::string& getId() const { return mId; }
@ -73,20 +75,20 @@ class Disk {
std::vector<std::shared_ptr<VolumeBase>> getVolumes() const;
status_t create();
status_t destroy();
virtual status_t create();
virtual status_t destroy();
status_t readMetadata();
status_t readPartitions();
virtual status_t readMetadata();
virtual status_t readPartitions();
void initializePartition(std::shared_ptr<StubVolume> vol);
status_t unmountAll();
status_t partitionPublic();
status_t partitionPrivate();
status_t partitionMixed(int8_t ratio);
virtual status_t partitionPublic();
virtual status_t partitionPrivate();
virtual status_t partitionMixed(int8_t ratio);
private:
protected:
/* ID that uniquely references this disk */
std::string mId;
/* Original event path */
@ -114,7 +116,9 @@ class Disk {
/* Flag that we need to skip first disk change events after partitioning*/
bool mSkipChange;
void createPublicVolume(dev_t device);
void createPublicVolume(dev_t device,
const std::string& fstype = "",
const std::string& mntopts = "");
void createPrivateVolume(dev_t device, const std::string& partGuid);
void createStubVolume();

@ -0,0 +1,93 @@
/*
* Copyright (C) 2015 Cyanogen, Inc.
*
* 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 "DiskPartition.h"
#include "PublicVolume.h"
#include "PrivateVolume.h"
#include "Utils.h"
#include "VolumeBase.h"
#include "VolumeManager.h"
#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <android-base/logging.h>
#include <diskconfig/diskconfig.h>
#include <vector>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/sysmacros.h>
#include <sys/stat.h>
#include <sys/mount.h>
using android::base::ReadFileToString;
using android::base::WriteStringToFile;
using android::base::StringPrintf;
namespace android {
namespace vold {
DiskPartition::DiskPartition(const std::string& eventPath, dev_t device,
const std::string& nickname, int flags, int partnum,
const std::string& fstype /* = "" */, const std::string& mntopts /* = "" */) :
Disk(eventPath, device, nickname, flags),
mPartNum(partnum),
mFsType(fstype),
mMntOpts(mntopts) {
// Empty
}
DiskPartition::~DiskPartition() {
// Empty
}
status_t DiskPartition::create() {
CHECK(!mCreated);
mCreated = true;
auto listener = VolumeManager::Instance()->getListener();
if (listener) listener->onDiskCreated(getId(), mFlags);
dev_t partDevice = makedev(major(mDevice), minor(mDevice) + mPartNum);
createPublicVolume(partDevice, mFsType, mMntOpts);
return OK;
}
status_t DiskPartition::destroy() {
CHECK(mCreated);
destroyAllVolumes();
mCreated = false;
auto listener = VolumeManager::Instance()->getListener();
if (listener) listener->onDiskDestroyed(getId());
return OK;
}
status_t DiskPartition::partitionPublic() {
return -1;
}
status_t DiskPartition::partitionPrivate() {
return -1;
}
status_t DiskPartition::partitionMixed(int8_t ratio) {
return -1;
}
} // namespace vold
} // namespace android

@ -0,0 +1,58 @@
/*
* Copyright (C) 2015 Cyanogen, Inc.
*
* 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_DISKPARTITION_H
#define ANDROID_VOLD_DISKPARTITION_H
#include "Disk.h"
namespace android {
namespace vold {
/*
* Representation of a single partition on physical media. Useful for
* single media partitions such as "internal" sdcard partitions.
*/
class DiskPartition : public Disk {
public:
DiskPartition(const std::string& eventPath, dev_t device,
const std::string& nickname,
int flags, int partnum,
const std::string& fstype = "", const std::string& mntopts = "");
virtual ~DiskPartition();
virtual status_t create();
virtual status_t destroy();
virtual status_t partitionPublic();
virtual status_t partitionPrivate();
virtual status_t partitionMixed(int8_t ratio);
private:
/* Partition number */
int mPartNum;
/* Filesystem type */
std::string mFsType;
/* Mount options */
std::string mMntOpts;
};
} // namespace vold
} // namespace android
#endif

@ -155,7 +155,7 @@ status_t PrivateVolume::doMount() {
}
if (mFsType == "ext4") {
int res = ext4::Check(mDmDevPath, mPath);
int res = ext4::Check(mDmDevPath, mPath, true);
if (res == 0 || res == 1) {
LOG(DEBUG) << getId() << " passed filesystem check";
} else {
@ -163,13 +163,13 @@ status_t PrivateVolume::doMount() {
return -EIO;
}
if (ext4::Mount(mDmDevPath, mPath, false, false, true)) {
if (ext4::Mount(mDmDevPath, mPath, false, false, true, "", true)) {
PLOG(ERROR) << getId() << " failed to mount";
return -EIO;
}
} else if (mFsType == "f2fs") {
int res = f2fs::Check(mDmDevPath);
int res = f2fs::Check(mDmDevPath, true);
if (res == 0) {
LOG(DEBUG) << getId() << " passed filesystem check";
} else {
@ -177,7 +177,7 @@ status_t PrivateVolume::doMount() {
return -EIO;
}
if (f2fs::Mount(mDmDevPath, mPath)) {
if (f2fs::Mount(mDmDevPath, mPath, "", true)) {
PLOG(ERROR) << getId() << " failed to mount";
return -EIO;
}

@ -20,6 +20,9 @@
#include "Utils.h"
#include "VolumeManager.h"
#include "fs/Exfat.h"
#include "fs/Ext4.h"
#include "fs/F2fs.h"
#include "fs/Ntfs.h"
#include "fs/Vfat.h"
#include <android-base/logging.h>
@ -47,7 +50,10 @@ static const char* kSdcardFsPath = "/system/bin/sdcard";
static const char* kAsecPath = "/mnt/secure/asec";
PublicVolume::PublicVolume(dev_t device) : VolumeBase(Type::kPublic), mDevice(device) {
PublicVolume::PublicVolume(dev_t device, const std::string& fstype /* = "" */,
const std::string& mntopts /* = "" */)
: VolumeBase(Type::kPublic), mDevice(device),
mFsType(fstype), mMntOpts(mntopts) {
setId(StringPrintf("public:%u,%u", major(device), minor(device)));
mDevPath = StringPrintf("/dev/block/vold/%s", getId().c_str());
mFuseMounted = false;
@ -100,17 +106,7 @@ status_t PublicVolume::doMount() {
bool isVisible = getMountFlags() & MountFlags::kVisible;
readMetadata();
if (mFsType == "vfat" && vfat::IsSupported()) {
if (vfat::Check(mDevPath)) {
LOG(ERROR) << getId() << " failed filesystem check";
return -EIO;
}
} else if (mFsType == "exfat" && exfat::IsSupported()) {
if (exfat::Check(mDevPath)) {
LOG(ERROR) << getId() << " failed filesystem check";
return -EIO;
}
} else {
if (!IsFilesystemSupported(mFsType)) {
LOG(ERROR) << getId() << " unsupported filesystem " << mFsType;
return -EIO;
}
@ -140,18 +136,45 @@ status_t PublicVolume::doMount() {
return -errno;
}
if (mFsType == "vfat") {
if (vfat::Mount(mDevPath, mRawPath, false, false, false, AID_ROOT,
(isVisible ? AID_MEDIA_RW : AID_EXTERNAL_STORAGE), 0007, true)) {
PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
return -EIO;
}
} else if (mFsType == "exfat") {
if (exfat::Mount(mDevPath, mRawPath, AID_ROOT,
(isVisible ? AID_MEDIA_RW : AID_EXTERNAL_STORAGE), 0007)) {
PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
return -EIO;
}
int ret = 0;
if (mFsType == "exfat") {
ret = exfat::Check(mDevPath);
} else if (mFsType == "ext4") {
ret = ext4::Check(mDevPath, mRawPath, false);
} else if (mFsType == "f2fs") {
ret = f2fs::Check(mDevPath, false);
} else if (mFsType == "ntfs") {
ret = ntfs::Check(mDevPath);
} else if (mFsType == "vfat") {
ret = vfat::Check(mDevPath);
} else {
LOG(WARNING) << getId() << " unsupported filesystem check, skipping";
}
if (ret) {
LOG(ERROR) << getId() << " failed filesystem check";
return -EIO;
}
if (mFsType == "exfat") {
ret = exfat::Mount(mDevPath, mRawPath, AID_ROOT,
(isVisible ? AID_MEDIA_RW : AID_EXTERNAL_STORAGE), 0007);
} else if (mFsType == "ext4") {
ret = ext4::Mount(mDevPath, mRawPath, false, false, true, mMntOpts,
false, true);
} else if (mFsType == "f2fs") {
ret = f2fs::Mount(mDevPath, mRawPath, mMntOpts, false, true);
} else if (mFsType == "ntfs") {
ret = ntfs::Mount(mDevPath, mRawPath, AID_ROOT,
(isVisible ? AID_MEDIA_RW : AID_EXTERNAL_STORAGE), 0007);
} else if (mFsType == "vfat") {
ret = vfat::Mount(mDevPath, mRawPath, false, false, false, AID_ROOT,
(isVisible ? AID_MEDIA_RW : AID_EXTERNAL_STORAGE), 0007, true);
} else {
ret = ::mount(mDevPath.c_str(), mRawPath.c_str(), mFsType.c_str(), 0, NULL);
}
if (ret) {
PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
return -EIO;
}
if (getMountFlags() & MountFlags::kPrimary) {
@ -337,7 +360,7 @@ status_t PublicVolume::doFormat(const std::string& fsType) {
useVfat = false;
}
if (!useVfat && !useExfat) {
if (!IsFilesystemSupported(fsType) && !useVfat && !useExfat) {
LOG(ERROR) << "Unsupported filesystem " << fsType;
return -EINVAL;
}
@ -350,6 +373,16 @@ status_t PublicVolume::doFormat(const std::string& fsType) {
res = vfat::Format(mDevPath, 0);
} else if (useExfat) {
res = exfat::Format(mDevPath);
} else if (fsType == "ext4") {
res = ext4::Format(mDevPath, 0, mRawPath);
} else if (fsType == "f2fs") {
res = f2fs::Format(mDevPath);
} else if (fsType == "ntfs") {
res = ntfs::Format(mDevPath);
} else {
LOG(ERROR) << getId() << " unrecognized filesystem " << fsType;
res = -1;
errno = EIO;
}
if (res != OK) {

@ -39,7 +39,8 @@ namespace vold {
*/
class PublicVolume : public VolumeBase {
public:
explicit PublicVolume(dev_t device);
explicit PublicVolume(dev_t device, const std::string& mntopts = "",
const std::string& fstype = "");
virtual ~PublicVolume();
protected:
@ -77,6 +78,8 @@ class PublicVolume : public VolumeBase {
std::string mFsUuid;
/* User-visible filesystem label */
std::string mFsLabel;
/* Mount options */
std::string mMntOpts;
DISALLOW_COPY_AND_ASSIGN(PublicVolume);
};

Loading…
Cancel
Save