1 /*
2 * Copyright (C) 2015 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 "VolumeBase.h"
18 #include "Utils.h"
19 #include "VolumeManager.h"
20
21 #include <android-base/logging.h>
22 #include <android-base/stringprintf.h>
23
24 #include <fcntl.h>
25 #include <stdlib.h>
26 #include <sys/mount.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29
30 using android::base::StringPrintf;
31
32 namespace android {
33 namespace vold {
34
VolumeBase(Type type)35 VolumeBase::VolumeBase(Type type)
36 : mType(type),
37 mMountFlags(0),
38 mMountUserId(USER_UNKNOWN),
39 mCreated(false),
40 mState(State::kUnmounted),
41 mSilent(false) {}
42
~VolumeBase()43 VolumeBase::~VolumeBase() {
44 CHECK(!mCreated);
45 }
46
setState(State state)47 void VolumeBase::setState(State state) {
48 mState = state;
49
50 auto listener = getListener();
51 if (listener) {
52 listener->onVolumeStateChanged(getId(), static_cast<int32_t>(mState),
53 static_cast<int32_t>(mMountUserId));
54 }
55 }
56
setDiskId(const std::string & diskId)57 status_t VolumeBase::setDiskId(const std::string& diskId) {
58 if (mCreated) {
59 LOG(WARNING) << getId() << " diskId change requires destroyed";
60 return -EBUSY;
61 }
62
63 mDiskId = diskId;
64 return OK;
65 }
66
setPartGuid(const std::string & partGuid)67 status_t VolumeBase::setPartGuid(const std::string& partGuid) {
68 if (mCreated) {
69 LOG(WARNING) << getId() << " partGuid change requires destroyed";
70 return -EBUSY;
71 }
72
73 mPartGuid = partGuid;
74 return OK;
75 }
76
setMountFlags(int mountFlags)77 status_t VolumeBase::setMountFlags(int mountFlags) {
78 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
79 LOG(WARNING) << getId() << " flags change requires state unmounted or unmountable";
80 return -EBUSY;
81 }
82
83 mMountFlags = mountFlags;
84 return OK;
85 }
86
setMountUserId(userid_t mountUserId)87 status_t VolumeBase::setMountUserId(userid_t mountUserId) {
88 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
89 LOG(WARNING) << getId() << " user change requires state unmounted or unmountable";
90 return -EBUSY;
91 }
92
93 mMountUserId = mountUserId;
94 return OK;
95 }
96
setSilent(bool silent)97 status_t VolumeBase::setSilent(bool silent) {
98 if (mCreated) {
99 LOG(WARNING) << getId() << " silence change requires destroyed";
100 return -EBUSY;
101 }
102
103 mSilent = silent;
104 return OK;
105 }
106
setId(const std::string & id)107 status_t VolumeBase::setId(const std::string& id) {
108 if (mCreated) {
109 LOG(WARNING) << getId() << " id change requires not created";
110 return -EBUSY;
111 }
112
113 mId = id;
114 return OK;
115 }
116
setPath(const std::string & path)117 status_t VolumeBase::setPath(const std::string& path) {
118 if (mState != State::kChecking) {
119 LOG(WARNING) << getId() << " path change requires state checking";
120 return -EBUSY;
121 }
122
123 mPath = path;
124
125 auto listener = getListener();
126 if (listener) listener->onVolumePathChanged(getId(), mPath);
127
128 return OK;
129 }
130
setInternalPath(const std::string & internalPath)131 status_t VolumeBase::setInternalPath(const std::string& internalPath) {
132 if (mState != State::kChecking) {
133 LOG(WARNING) << getId() << " internal path change requires state checking";
134 return -EBUSY;
135 }
136
137 mInternalPath = internalPath;
138
139 auto listener = getListener();
140 if (listener) {
141 listener->onVolumeInternalPathChanged(getId(), mInternalPath);
142 }
143
144 return OK;
145 }
146
setMountCallback(const android::sp<android::os::IVoldMountCallback> & callback)147 status_t VolumeBase::setMountCallback(
148 const android::sp<android::os::IVoldMountCallback>& callback) {
149 mMountCallback = callback;
150 return OK;
151 }
152
getMountCallback() const153 sp<android::os::IVoldMountCallback> VolumeBase::getMountCallback() const {
154 return mMountCallback;
155 }
156
getListener() const157 android::sp<android::os::IVoldListener> VolumeBase::getListener() const {
158 if (mSilent) {
159 return nullptr;
160 } else {
161 return VolumeManager::Instance()->getListener();
162 }
163 }
164
addVolume(const std::shared_ptr<VolumeBase> & volume)165 void VolumeBase::addVolume(const std::shared_ptr<VolumeBase>& volume) {
166 mVolumes.push_back(volume);
167 }
168
removeVolume(const std::shared_ptr<VolumeBase> & volume)169 void VolumeBase::removeVolume(const std::shared_ptr<VolumeBase>& volume) {
170 mVolumes.remove(volume);
171 }
172
findVolume(const std::string & id)173 std::shared_ptr<VolumeBase> VolumeBase::findVolume(const std::string& id) {
174 for (auto vol : mVolumes) {
175 if (vol->getId() == id) {
176 return vol;
177 }
178 }
179 return nullptr;
180 }
181
create()182 status_t VolumeBase::create() {
183 CHECK(!mCreated);
184
185 mCreated = true;
186 status_t res = doCreate();
187
188 auto listener = getListener();
189 if (listener) {
190 listener->onVolumeCreated(getId(), static_cast<int32_t>(mType), mDiskId, mPartGuid,
191 mMountUserId);
192 }
193
194 setState(State::kUnmounted);
195 return res;
196 }
197
doCreate()198 status_t VolumeBase::doCreate() {
199 return OK;
200 }
201
destroy()202 status_t VolumeBase::destroy() {
203 CHECK(mCreated);
204
205 if (mState == State::kMounted) {
206 unmount();
207 setState(State::kBadRemoval);
208 } else {
209 setState(State::kRemoved);
210 }
211
212 auto listener = getListener();
213 if (listener) {
214 listener->onVolumeDestroyed(getId());
215 }
216
217 status_t res = doDestroy();
218 mCreated = false;
219 return res;
220 }
221
doDestroy()222 status_t VolumeBase::doDestroy() {
223 return OK;
224 }
225
mount()226 status_t VolumeBase::mount() {
227 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
228 LOG(WARNING) << getId() << " mount requires state unmounted or unmountable";
229 return -EBUSY;
230 }
231
232 setState(State::kChecking);
233 status_t res = doMount();
234 setState(res == OK ? State::kMounted : State::kUnmountable);
235
236 if (res == OK) {
237 doPostMount();
238 }
239 return res;
240 }
241
doPostMount()242 void VolumeBase::doPostMount() {}
243
unmount()244 status_t VolumeBase::unmount() {
245 if (mState != State::kMounted) {
246 LOG(WARNING) << getId() << " unmount requires state mounted";
247 return -EBUSY;
248 }
249
250 setState(State::kEjecting);
251 for (const auto& vol : mVolumes) {
252 if (vol->destroy()) {
253 LOG(WARNING) << getId() << " failed to destroy " << vol->getId() << " stacked above";
254 }
255 }
256 mVolumes.clear();
257
258 status_t res = doUnmount();
259 setState(State::kUnmounted);
260 return res;
261 }
262
format(const std::string & fsType)263 status_t VolumeBase::format(const std::string& fsType) {
264 if (mState == State::kMounted) {
265 unmount();
266 }
267
268 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
269 LOG(WARNING) << getId() << " format requires state unmounted or unmountable";
270 return -EBUSY;
271 }
272
273 setState(State::kFormatting);
274 status_t res = doFormat(fsType);
275 setState(State::kUnmounted);
276 return res;
277 }
278
doFormat(const std::string & fsType)279 status_t VolumeBase::doFormat(const std::string& fsType) {
280 return -ENOTSUP;
281 }
282
getRootPath() const283 std::string VolumeBase::getRootPath() const {
284 // Usually the same as the internal path, except for emulated volumes.
285 return getInternalPath();
286 }
287
operator <<(std::ostream & stream) const288 std::ostream& VolumeBase::operator<<(std::ostream& stream) const {
289 return stream << " VolumeBase{id=" << mId << ",mountFlags=" << mMountFlags
290 << ",mountUserId=" << mMountUserId << "}";
291 }
292
293 } // namespace vold
294 } // namespace android
295