2015-03-03 06:01:40 +01:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2015 The Android Open Source Project
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "Utils.h"
|
|
|
|
#include "VolumeBase.h"
|
2015-03-14 00:09:20 +01:00
|
|
|
#include "VolumeManager.h"
|
|
|
|
#include "ResponseCode.h"
|
2015-03-03 06:01:40 +01:00
|
|
|
|
2015-03-14 00:09:20 +01:00
|
|
|
#include <base/stringprintf.h>
|
|
|
|
#include <base/logging.h>
|
2015-03-03 06:01:40 +01:00
|
|
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <sys/mount.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
2015-03-14 00:09:20 +01:00
|
|
|
using android::base::StringPrintf;
|
|
|
|
|
|
|
|
#define DEBUG 1
|
|
|
|
|
2015-03-03 06:01:40 +01:00
|
|
|
namespace android {
|
|
|
|
namespace vold {
|
|
|
|
|
2015-03-14 00:09:20 +01:00
|
|
|
VolumeBase::VolumeBase(Type type) :
|
|
|
|
mType(type), mFlags(0), mUser(-1), mCreated(false), mState(State::kUnmounted) {
|
2015-03-03 06:01:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
VolumeBase::~VolumeBase() {
|
2015-03-14 00:09:20 +01:00
|
|
|
CHECK(!mCreated);
|
2015-03-03 06:01:40 +01:00
|
|
|
}
|
|
|
|
|
2015-03-14 00:09:20 +01:00
|
|
|
void VolumeBase::setState(State state) {
|
2015-03-03 06:01:40 +01:00
|
|
|
mState = state;
|
|
|
|
|
2015-03-14 00:09:20 +01:00
|
|
|
VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
|
|
|
|
ResponseCode::VolumeStateChanged,
|
|
|
|
StringPrintf("%s %d", getId().c_str(), mState).c_str(), false);
|
2015-03-03 06:01:40 +01:00
|
|
|
}
|
|
|
|
|
2015-03-14 00:09:20 +01:00
|
|
|
status_t VolumeBase::setFlags(int flags) {
|
|
|
|
if (mState != State::kUnmounted) {
|
|
|
|
LOG(WARNING) << getId() << " flags change requires state unmounted";
|
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
|
|
|
|
mFlags = flags;
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t VolumeBase::setUser(userid_t user) {
|
|
|
|
if (mState != State::kUnmounted) {
|
|
|
|
LOG(WARNING) << getId() << " user change requires state unmounted";
|
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
|
|
|
|
mUser = user;
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t VolumeBase::setId(const std::string& id) {
|
|
|
|
if (mCreated) {
|
|
|
|
LOG(WARNING) << getId() << " id change requires not created";
|
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
|
|
|
|
mId = id;
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t VolumeBase::setPath(const std::string& path) {
|
|
|
|
if (mState != State::kMounting) {
|
|
|
|
LOG(WARNING) << getId() << " path change requires state mounting";
|
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
|
|
|
|
mPath = path;
|
|
|
|
VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
|
|
|
|
ResponseCode::VolumePathChanged,
|
|
|
|
StringPrintf("%s %s", getId().c_str(), mPath.c_str()).c_str(), false);
|
|
|
|
return OK;
|
2015-03-03 06:01:40 +01:00
|
|
|
}
|
|
|
|
|
2015-03-14 00:09:20 +01:00
|
|
|
void VolumeBase::addVolume(const std::shared_ptr<VolumeBase>& volume) {
|
|
|
|
mVolumes.push_back(volume);
|
|
|
|
}
|
|
|
|
|
|
|
|
void VolumeBase::removeVolume(const std::shared_ptr<VolumeBase>& volume) {
|
|
|
|
mVolumes.remove(volume);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::shared_ptr<VolumeBase> VolumeBase::findVolume(const std::string& id) {
|
|
|
|
for (auto vol : mVolumes) {
|
|
|
|
if (vol->getId() == id) {
|
|
|
|
return vol;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t VolumeBase::create() {
|
|
|
|
CHECK(!mCreated);
|
2015-03-31 19:35:33 +02:00
|
|
|
|
2015-03-14 00:09:20 +01:00
|
|
|
mCreated = true;
|
2015-03-31 19:35:33 +02:00
|
|
|
status_t res = doCreate();
|
2015-03-14 00:09:20 +01:00
|
|
|
VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
|
|
|
|
ResponseCode::VolumeCreated,
|
|
|
|
StringPrintf("%s %d", getId().c_str(), mType).c_str(), false);
|
2015-03-31 19:35:33 +02:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t VolumeBase::doCreate() {
|
2015-03-14 00:09:20 +01:00
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t VolumeBase::destroy() {
|
|
|
|
CHECK(mCreated);
|
|
|
|
|
|
|
|
if (mState == State::kMounted) {
|
|
|
|
unmount();
|
|
|
|
}
|
|
|
|
|
|
|
|
VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
|
|
|
|
ResponseCode::VolumeDestroyed, getId().c_str(), false);
|
2015-03-31 19:35:33 +02:00
|
|
|
status_t res = doDestroy();
|
|
|
|
mCreated = false;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t VolumeBase::doDestroy() {
|
2015-03-14 00:09:20 +01:00
|
|
|
return OK;
|
2015-03-03 06:01:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
status_t VolumeBase::mount() {
|
2015-03-14 00:09:20 +01:00
|
|
|
if (mState != State::kUnmounted) {
|
|
|
|
LOG(WARNING) << getId() << " mount requires state unmounted";
|
2015-03-03 06:01:40 +01:00
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
|
2015-03-14 00:09:20 +01:00
|
|
|
setState(State::kMounting);
|
2015-03-03 06:01:40 +01:00
|
|
|
status_t res = doMount();
|
2015-03-14 00:09:20 +01:00
|
|
|
if (res == OK) {
|
|
|
|
setState(State::kMounted);
|
2015-03-03 06:01:40 +01:00
|
|
|
} else {
|
2015-03-14 00:09:20 +01:00
|
|
|
setState(State::kUnmounted);
|
2015-03-03 06:01:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t VolumeBase::unmount() {
|
2015-03-14 00:09:20 +01:00
|
|
|
if (mState != State::kMounted) {
|
|
|
|
LOG(WARNING) << getId() << " unmount requires state mounted";
|
2015-03-03 06:01:40 +01:00
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
|
2015-03-14 00:09:20 +01:00
|
|
|
setState(State::kUnmounting);
|
2015-03-03 06:01:40 +01:00
|
|
|
|
2015-03-14 00:09:20 +01:00
|
|
|
for (auto vol : mVolumes) {
|
|
|
|
if (vol->unmount()) {
|
|
|
|
LOG(WARNING) << getId() << " failed to unmount " << vol->getId()
|
|
|
|
<< " stacked above";
|
2015-03-03 06:01:40 +01:00
|
|
|
}
|
|
|
|
}
|
2015-03-14 00:09:20 +01:00
|
|
|
mVolumes.clear();
|
2015-03-03 06:01:40 +01:00
|
|
|
|
|
|
|
status_t res = doUnmount();
|
2015-03-14 00:09:20 +01:00
|
|
|
setState(State::kUnmounted);
|
2015-03-03 06:01:40 +01:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t VolumeBase::format() {
|
2015-03-14 00:09:20 +01:00
|
|
|
if (mState != State::kUnmounted) {
|
|
|
|
LOG(WARNING) << getId() << " format requires state unmounted";
|
2015-03-03 06:01:40 +01:00
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
|
2015-03-14 00:09:20 +01:00
|
|
|
setState(State::kFormatting);
|
2015-03-03 06:01:40 +01:00
|
|
|
status_t res = doFormat();
|
2015-03-14 00:09:20 +01:00
|
|
|
setState(State::kUnmounted);
|
2015-03-03 06:01:40 +01:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t VolumeBase::doFormat() {
|
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace vold
|
|
|
|
} // namespace android
|