1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "ObbVolume.h"
18 #include "Devmapper.h"
19 #include "Loop.h"
20 #include "Utils.h"
21 #include "VoldUtil.h"
22 #include "fs/Vfat.h"
23
24 #include <android-base/logging.h>
25 #include <android-base/stringprintf.h>
26 #include <cutils/fs.h>
27 #include <private/android_filesystem_config.h>
28
29 #include <fcntl.h>
30 #include <stdlib.h>
31 #include <sys/mount.h>
32 #include <sys/stat.h>
33 #include <sys/sysmacros.h>
34 #include <sys/types.h>
35 #include <sys/wait.h>
36
37 using android::base::StringPrintf;
38
39 namespace android {
40 namespace vold {
41
ObbVolume(int id,const std::string & sourcePath,const std::string & sourceKey,gid_t ownerGid)42 ObbVolume::ObbVolume(int id, const std::string& sourcePath, const std::string& sourceKey,
43 gid_t ownerGid)
44 : VolumeBase(Type::kObb) {
45 setId(StringPrintf("obb:%d", id));
46 mSourcePath = sourcePath;
47 mSourceKey = sourceKey;
48 mOwnerGid = ownerGid;
49 }
50
~ObbVolume()51 ObbVolume::~ObbVolume() {}
52
doCreate()53 status_t ObbVolume::doCreate() {
54 if (Loop::create(mSourcePath, mLoopPath)) {
55 PLOG(ERROR) << getId() << " failed to create loop";
56 return -1;
57 }
58
59 if (!mSourceKey.empty()) {
60 uint64_t nr_sec = 0;
61 if (GetBlockDev512Sectors(mLoopPath, &nr_sec) != OK) {
62 PLOG(ERROR) << getId() << " failed to get loop size";
63 return -1;
64 }
65
66 char tmp[PATH_MAX];
67 if (Devmapper::create(getId().c_str(), mLoopPath.c_str(), mSourceKey.c_str(), nr_sec, tmp,
68 PATH_MAX)) {
69 PLOG(ERROR) << getId() << " failed to create dm";
70 return -1;
71 }
72 mDmPath = tmp;
73 mMountPath = mDmPath;
74 } else {
75 mMountPath = mLoopPath;
76 }
77 return OK;
78 }
79
doDestroy()80 status_t ObbVolume::doDestroy() {
81 if (!mDmPath.empty() && Devmapper::destroy(getId().c_str())) {
82 PLOG(WARNING) << getId() << " failed to destroy dm";
83 }
84 if (!mLoopPath.empty() && Loop::destroyByDevice(mLoopPath.c_str())) {
85 PLOG(WARNING) << getId() << " failed to destroy loop";
86 }
87 mDmPath.clear();
88 mLoopPath.clear();
89 return OK;
90 }
91
doMount()92 status_t ObbVolume::doMount() {
93 auto path = StringPrintf("/mnt/obb/%s", getId().c_str());
94 setPath(path);
95
96 if (fs_prepare_dir(path.c_str(), 0700, AID_ROOT, AID_ROOT)) {
97 PLOG(ERROR) << getId() << " failed to create mount point";
98 return -1;
99 }
100 // clang-format off
101 if (android::vold::vfat::Mount(mMountPath, path, true, false, true,
102 0, mOwnerGid, 0227, false)) {
103 // clang-format on
104 PLOG(ERROR) << getId() << " failed to mount";
105 return -1;
106 }
107 return OK;
108 }
109
doUnmount()110 status_t ObbVolume::doUnmount() {
111 auto path = getPath();
112
113 KillProcessesUsingPath(path);
114 ForceUnmount(path);
115 rmdir(path.c_str());
116
117 return OK;
118 }
119
120 } // namespace vold
121 } // namespace android
122