• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 vold {
35 
VolumeBase(Type type)36 VolumeBase::VolumeBase(Type type) :
37         mType(type), mMountFlags(0), mMountUserId(-1), mCreated(false), mState(
38                 State::kUnmounted), mSilent(false) {
39 }
40 
~VolumeBase()41 VolumeBase::~VolumeBase() {
42     CHECK(!mCreated);
43 }
44 
setState(State state)45 void VolumeBase::setState(State state) {
46     mState = state;
47     notifyEvent(ResponseCode::VolumeStateChanged, StringPrintf("%d", mState));
48 }
49 
setDiskId(const std::string & diskId)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 
setPartGuid(const std::string & partGuid)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 
setMountFlags(int mountFlags)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 
setMountUserId(userid_t mountUserId)80 status_t VolumeBase::setMountUserId(userid_t mountUserId) {
81     if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
82         LOG(WARNING) << getId() << " user change requires state unmounted or unmountable";
83         return -EBUSY;
84     }
85 
86     mMountUserId = mountUserId;
87     return OK;
88 }
89 
setSilent(bool silent)90 status_t VolumeBase::setSilent(bool silent) {
91     if (mCreated) {
92         LOG(WARNING) << getId() << " silence change requires destroyed";
93         return -EBUSY;
94     }
95 
96     mSilent = silent;
97     return OK;
98 }
99 
setId(const std::string & id)100 status_t VolumeBase::setId(const std::string& id) {
101     if (mCreated) {
102         LOG(WARNING) << getId() << " id change requires not created";
103         return -EBUSY;
104     }
105 
106     mId = id;
107     return OK;
108 }
109 
setPath(const std::string & path)110 status_t VolumeBase::setPath(const std::string& path) {
111     if (mState != State::kChecking) {
112         LOG(WARNING) << getId() << " path change requires state checking";
113         return -EBUSY;
114     }
115 
116     mPath = path;
117     notifyEvent(ResponseCode::VolumePathChanged, mPath);
118     return OK;
119 }
120 
setInternalPath(const std::string & internalPath)121 status_t VolumeBase::setInternalPath(const std::string& internalPath) {
122     if (mState != State::kChecking) {
123         LOG(WARNING) << getId() << " internal path change requires state checking";
124         return -EBUSY;
125     }
126 
127     mInternalPath = internalPath;
128     notifyEvent(ResponseCode::VolumeInternalPathChanged, mInternalPath);
129     return OK;
130 }
131 
notifyEvent(int event)132 void VolumeBase::notifyEvent(int event) {
133     if (mSilent) return;
134     VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event,
135             getId().c_str(), false);
136 }
137 
notifyEvent(int event,const std::string & value)138 void VolumeBase::notifyEvent(int event, const std::string& value) {
139     if (mSilent) return;
140     VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event,
141             StringPrintf("%s %s", getId().c_str(), value.c_str()).c_str(), false);
142 }
143 
addVolume(const std::shared_ptr<VolumeBase> & volume)144 void VolumeBase::addVolume(const std::shared_ptr<VolumeBase>& volume) {
145     mVolumes.push_back(volume);
146 }
147 
removeVolume(const std::shared_ptr<VolumeBase> & volume)148 void VolumeBase::removeVolume(const std::shared_ptr<VolumeBase>& volume) {
149     mVolumes.remove(volume);
150 }
151 
findVolume(const std::string & id)152 std::shared_ptr<VolumeBase> VolumeBase::findVolume(const std::string& id) {
153     for (auto vol : mVolumes) {
154         if (vol->getId() == id) {
155             return vol;
156         }
157     }
158     return nullptr;
159 }
160 
create()161 status_t VolumeBase::create() {
162     CHECK(!mCreated);
163 
164     mCreated = true;
165     status_t res = doCreate();
166     notifyEvent(ResponseCode::VolumeCreated,
167             StringPrintf("%d \"%s\" \"%s\"", mType, mDiskId.c_str(), mPartGuid.c_str()));
168     setState(State::kUnmounted);
169     return res;
170 }
171 
doCreate()172 status_t VolumeBase::doCreate() {
173     return OK;
174 }
175 
destroy()176 status_t VolumeBase::destroy() {
177     CHECK(mCreated);
178 
179     if (mState == State::kMounted) {
180         unmount();
181         setState(State::kBadRemoval);
182     } else {
183         setState(State::kRemoved);
184     }
185 
186     notifyEvent(ResponseCode::VolumeDestroyed);
187     status_t res = doDestroy();
188     mCreated = false;
189     return res;
190 }
191 
doDestroy()192 status_t VolumeBase::doDestroy() {
193     return OK;
194 }
195 
mount()196 status_t VolumeBase::mount() {
197     if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
198         LOG(WARNING) << getId() << " mount requires state unmounted or unmountable";
199         return -EBUSY;
200     }
201 
202     setState(State::kChecking);
203     status_t res = doMount();
204     if (res == OK) {
205         setState(State::kMounted);
206     } else {
207         setState(State::kUnmountable);
208     }
209 
210     return res;
211 }
212 
unmount()213 status_t VolumeBase::unmount() {
214     if (mState != State::kMounted) {
215         LOG(WARNING) << getId() << " unmount requires state mounted";
216         return -EBUSY;
217     }
218 
219     setState(State::kEjecting);
220     for (const auto& vol : mVolumes) {
221         if (vol->destroy()) {
222             LOG(WARNING) << getId() << " failed to destroy " << vol->getId()
223                     << " stacked above";
224         }
225     }
226     mVolumes.clear();
227 
228     status_t res = doUnmount();
229     setState(State::kUnmounted);
230     return res;
231 }
232 
format(const std::string & fsType)233 status_t VolumeBase::format(const std::string& fsType) {
234     if (mState == State::kMounted) {
235         unmount();
236     }
237 
238     if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
239         LOG(WARNING) << getId() << " format requires state unmounted or unmountable";
240         return -EBUSY;
241     }
242 
243     setState(State::kFormatting);
244     status_t res = doFormat(fsType);
245     setState(State::kUnmounted);
246     return res;
247 }
248 
doFormat(const std::string & fsType)249 status_t VolumeBase::doFormat(const std::string& fsType) {
250     return -ENOTSUP;
251 }
252 
253 }  // namespace vold
254 }  // namespace android
255