/* * Copyright (C) 2017 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 "ObbVolume.h" #include "Devmapper.h" #include "Loop.h" #include "Utils.h" #include "VoldUtil.h" #include "fs/Vfat.h" #include #include #include #include #include #include #include #include #include #include #include #include using android::base::StringPrintf; using android::base::unique_fd; namespace android { namespace vold { ObbVolume::ObbVolume(int id, const std::string& sourcePath, const std::string& sourceKey, gid_t ownerGid) : VolumeBase(Type::kObb) { setId(StringPrintf("obb:%d", id)); mSourcePath = sourcePath; mSourceKey = sourceKey; mOwnerGid = ownerGid; } ObbVolume::~ObbVolume() {} status_t ObbVolume::doCreate() { if (Loop::create(mSourcePath, mLoopPath)) { PLOG(ERROR) << getId() << " failed to create loop"; return -1; } if (!mSourceKey.empty()) { unsigned long nr_sec = 0; { unique_fd loop_fd(open(mLoopPath.c_str(), O_RDWR | O_CLOEXEC)); if (loop_fd.get() == -1) { PLOG(ERROR) << getId() << " failed to open loop"; return -1; } get_blkdev_size(loop_fd.get(), &nr_sec); if (nr_sec == 0) { PLOG(ERROR) << getId() << " failed to get loop size"; return -1; } } char tmp[PATH_MAX]; if (Devmapper::create(getId().c_str(), mLoopPath.c_str(), mSourceKey.c_str(), nr_sec, tmp, PATH_MAX)) { PLOG(ERROR) << getId() << " failed to create dm"; return -1; } mDmPath = tmp; mMountPath = mDmPath; } else { mMountPath = mLoopPath; } return OK; } status_t ObbVolume::doDestroy() { if (!mDmPath.empty() && Devmapper::destroy(getId().c_str())) { PLOG(WARNING) << getId() << " failed to destroy dm"; } if (!mLoopPath.empty() && Loop::destroyByDevice(mLoopPath.c_str())) { PLOG(WARNING) << getId() << " failed to destroy loop"; } mDmPath.clear(); mLoopPath.clear(); return OK; } status_t ObbVolume::doMount() { auto path = StringPrintf("/mnt/obb/%s", getId().c_str()); setPath(path); if (fs_prepare_dir(path.c_str(), 0700, AID_ROOT, AID_ROOT)) { PLOG(ERROR) << getId() << " failed to create mount point"; return -1; } // clang-format off if (android::vold::vfat::Mount(mMountPath, path, true, false, true, 0, mOwnerGid, 0227, false)) { // clang-format on PLOG(ERROR) << getId() << " failed to mount"; return -1; } return OK; } status_t ObbVolume::doUnmount() { auto path = getPath(); KillProcessesUsingPath(path); ForceUnmount(path); rmdir(path.c_str()); return OK; } } // namespace vold } // namespace android