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 | |
31 | using android::base::StringPrintf; |
32 | |
33 | namespace android { |
34 | namespace droidvold { |
35 | |
36 | VolumeBase::VolumeBase(Type type) : |
37 | mType(type), mMountFlags(0), mMountUserId(-1), mCreated(false), mState( |
38 | State::kUnmounted), mSilent(false), mDiskFlags(0), mPartNo(0) { |
39 | } |
40 | |
41 | VolumeBase::~VolumeBase() { |
42 | CHECK(!mCreated); |
43 | } |
44 | |
45 | void VolumeBase::setState(State state) { |
46 | mState = state; |
47 | notifyEvent(ResponseCode::VolumeStateChanged, StringPrintf("%d", mState)); |
48 | } |
49 | |
50 | status_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 | |
60 | status_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 | |
70 | status_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 | |
80 | status_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 | |
90 | status_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 | |
100 | status_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 | |
110 | status_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 | |
120 | status_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 | |
130 | status_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 | |
141 | status_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 | |
152 | void VolumeBase::notifyEvent(int event) { |
153 | if (mSilent) return; |
154 | VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event, |
155 | getId()); |
156 | } |
157 | |
158 | void 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 | |
165 | void VolumeBase::addVolume(const std::shared_ptr<VolumeBase>& volume) { |
166 | mVolumes.push_back(volume); |
167 | } |
168 | |
169 | void VolumeBase::removeVolume(const std::shared_ptr<VolumeBase>& volume) { |
170 | mVolumes.remove(volume); |
171 | } |
172 | |
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 | |
182 | status_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 | |
193 | status_t VolumeBase::doCreate() { |
194 | return OK; |
195 | } |
196 | |
197 | status_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 | |
213 | status_t VolumeBase::doDestroy() { |
214 | return OK; |
215 | } |
216 | |
217 | status_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 | |
234 | status_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 | |
254 | status_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 | |
270 | status_t VolumeBase::doFormat(const std::string& fsType) { |
271 | return -ENOTSUP; |
272 | } |
273 | |
274 | } // namespace vold |
275 | } // namespace android |
276 |