/* * 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 #include "ResponseCode.h" #include "Utils.h" #include #include #include #include #include #include #include #include #include #include #include #include #include using android::base::StringPrintf; namespace android { namespace volmgr { static const std::string kStagingPath = "/mnt/staging/emulated"; static const std::string kFbeKeyVersion = kStagingPath + "/unencrypted/key/version"; 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) { // It's ok to fail mounting if we're encrytped, so avoid printing to recovery's UiLogger std::cout << getId() << " failed to mount " << mDevPath << " on " << kStagingPath << ": " << std::strerror(errno); 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; } bool EmulatedVolume::detectMountable() { bool mountable = false; if (doMount() == OK) { // Check if FBE encrypted mountable = access(kFbeKeyVersion.c_str(), F_OK) != 0; doUnmount(); } return mountable; } } // namespace volmgr } // namespace android