summaryrefslogtreecommitdiff
path: root/VolumeBase.cpp (plain)
blob: e2e53b9032646fa4f3e5f592b127bbe5cc5592c2
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 "Utils.h"
18#include "VolumeBase.h"
19#include "VolumeManager.h"
20#include "ResponseCode.h"
21
22#include <android-base/stringprintf.h>
23#include <android-base/logging.h>
24
25#include <fcntl.h>
26#include <stdlib.h>
27#include <sys/mount.h>
28#include <sys/stat.h>
29#include <sys/types.h>
30
31using android::base::StringPrintf;
32
33namespace android {
34namespace droidvold {
35
36VolumeBase::VolumeBase(Type type) :
37 mType(type), mMountFlags(0), mMountUserId(-1), mCreated(false), mState(
38 State::kUnmounted), mSilent(false), mDiskFlags(0), mPartNo(0) {
39}
40
41VolumeBase::~VolumeBase() {
42 CHECK(!mCreated);
43}
44
45void VolumeBase::setState(State state) {
46 mState = state;
47 notifyEvent(ResponseCode::VolumeStateChanged, StringPrintf("%d", mState));
48}
49
50status_t VolumeBase::setDiskId(const std::string& diskId) {
51 if (mCreated) {
52 LOG(WARNING) << getId() << " diskId change requires destroyed";
53 return -EBUSY;
54 }
55
56 mDiskId = diskId;
57 return OK;
58}
59
60status_t VolumeBase::setPartGuid(const std::string& partGuid) {
61 if (mCreated) {
62 LOG(WARNING) << getId() << " partGuid change requires destroyed";
63 return -EBUSY;
64 }
65
66 mPartGuid = partGuid;
67 return OK;
68}
69
70status_t VolumeBase::setMountFlags(int mountFlags) {
71 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
72 LOG(WARNING) << getId() << " flags change requires state unmounted or unmountable";
73 return -EBUSY;
74 }
75
76 mMountFlags = mountFlags;
77 return OK;
78}
79
80status_t VolumeBase::setDiskFlags(int diskFlags) {
81 if (mCreated) {
82 LOG(WARNING) << getId() << " Diskflags change requires destroyed";
83 return -EBUSY;
84 }
85
86 mDiskFlags = diskFlags;
87 return OK;
88}
89
90status_t VolumeBase::setPartNo(int part) {
91 if (mCreated) {
92 LOG(WARNING) << getId() << " partNo change requires destroyed";
93 return -EBUSY;
94 }
95
96 mPartNo = part;
97 return OK;
98}
99
100status_t VolumeBase::setMountUserId(userid_t mountUserId) {
101 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
102 LOG(WARNING) << getId() << " user change requires state unmounted or unmountable";
103 return -EBUSY;
104 }
105
106 mMountUserId = mountUserId;
107 return OK;
108}
109
110status_t VolumeBase::setSilent(bool silent) {
111 if (mCreated) {
112 LOG(WARNING) << getId() << " silence change requires destroyed";
113 return -EBUSY;
114 }
115
116 mSilent = silent;
117 return OK;
118}
119
120status_t VolumeBase::setId(const std::string& id) {
121 if (mCreated) {
122 LOG(WARNING) << getId() << " id change requires not created";
123 return -EBUSY;
124 }
125
126 mId = id;
127 return OK;
128}
129
130status_t VolumeBase::setPath(const std::string& path) {
131 if (mState != State::kChecking) {
132 LOG(WARNING) << getId() << " path change requires state checking";
133 return -EBUSY;
134 }
135
136 mPath = path;
137 notifyEvent(ResponseCode::VolumePathChanged, mPath);
138 return OK;
139}
140
141status_t VolumeBase::setInternalPath(const std::string& internalPath) {
142 if (mState != State::kChecking) {
143 LOG(WARNING) << getId() << " internal path change requires state checking";
144 return -EBUSY;
145 }
146
147 mInternalPath = internalPath;
148 notifyEvent(ResponseCode::VolumeInternalPathChanged, mInternalPath);
149 return OK;
150}
151
152void VolumeBase::notifyEvent(int event) {
153 if (mSilent) return;
154 VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event,
155 getId());
156}
157
158void VolumeBase::notifyEvent(int event, const std::string& value) {
159 if (mSilent) return;
160 VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event,
161 StringPrintf("%s %s", getId().c_str(), value.c_str()));
162}
163
164
165void VolumeBase::addVolume(const std::shared_ptr<VolumeBase>& volume) {
166 mVolumes.push_back(volume);
167}
168
169void VolumeBase::removeVolume(const std::shared_ptr<VolumeBase>& volume) {
170 mVolumes.remove(volume);
171}
172
173std::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
182status_t VolumeBase::create() {
183 CHECK(!mCreated);
184
185 mCreated = true;
186 status_t res = doCreate();
187 notifyEvent(ResponseCode::VolumeCreated,
188 StringPrintf("%d \"%s\" \"%s\"", mType, mDiskId.c_str(), mPartGuid.c_str()));
189 setState(State::kUnmounted);
190 return res;
191}
192
193status_t VolumeBase::doCreate() {
194 return OK;
195}
196
197status_t VolumeBase::destroy() {
198 CHECK(mCreated);
199
200 if (mState == State::kMounted) {
201 unmount();
202 setState(State::kBadRemoval);
203 } else {
204 setState(State::kRemoved);
205 }
206
207 notifyEvent(ResponseCode::VolumeDestroyed);
208 status_t res = doDestroy();
209 mCreated = false;
210 return res;
211}
212
213status_t VolumeBase::doDestroy() {
214 return OK;
215}
216
217status_t VolumeBase::mount() {
218 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
219 LOG(WARNING) << getId() << " mount requires state unmounted or unmountable";
220 return -EBUSY;
221 }
222
223 setState(State::kChecking);
224 status_t res = doMount();
225 if (res == OK) {
226 setState(State::kMounted);
227 } else {
228 setState(State::kUnmountable);
229 }
230
231 return res;
232}
233
234status_t VolumeBase::unmount() {
235 if (mState != State::kMounted) {
236 LOG(WARNING) << getId() << " unmount requires state mounted";
237 return -EBUSY;
238 }
239
240 setState(State::kEjecting);
241 for (auto vol : mVolumes) {
242 if (vol->destroy()) {
243 LOG(WARNING) << getId() << " failed to destroy " << vol->getId()
244 << " stacked above";
245 }
246 }
247 mVolumes.clear();
248
249 status_t res = doUnmount();
250 setState(State::kUnmounted);
251 return res;
252}
253
254status_t VolumeBase::format(const std::string& fsType) {
255 if (mState == State::kMounted) {
256 unmount();
257 }
258
259 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
260 LOG(WARNING) << getId() << " format requires state unmounted or unmountable";
261 return -EBUSY;
262 }
263
264 setState(State::kFormatting);
265 status_t res = doFormat(fsType);
266 setState(State::kUnmounted);
267 return res;
268}
269
270status_t VolumeBase::doFormat(const std::string& fsType) {
271 return -ENOTSUP;
272}
273
274} // namespace vold
275} // namespace android
276