} else if (cmd == "shutdown") {
return sendGenericOkFail(cli, vm->shutdown());
+ } else if (cmd == "debug") {
+ return sendGenericOkFail(cli, vm->setDebug(true));
+
} else if (cmd == "partition" && argc > 3) {
// partition [diskId] [public|private|mixed] [ratio]
std::string id(argv[2]);
return cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown volume", false);
}
- int flags = (argc > 3) ? atoi(argv[3]) : 0;
- userid_t user = (argc > 4) ? atoi(argv[4]) : -1;
+ int mountFlags = (argc > 3) ? atoi(argv[3]) : 0;
+ userid_t mountUserId = (argc > 4) ? atoi(argv[4]) : -1;
- if (flags & android::vold::VolumeBase::Flags::kPrimary) {
+ if (mountFlags & android::vold::VolumeBase::MountFlags::kPrimary) {
vm->setPrimary(vol);
}
- vol->setFlags(flags);
- vol->setUser(user);
+ vol->setMountFlags(mountFlags);
+ vol->setMountUserId(mountUserId);
return sendGenericOkFail(cli, vol->mount());
#include <sys/stat.h>
#include <sys/mount.h>
+#define ENTIRE_DEVICE_FALLBACK 0
+
using android::base::ReadFileToString;
using android::base::WriteStringToFile;
using android::base::StringPrintf;
}
mVolumes.push_back(vol);
+ vol->setDiskId(getId());
vol->create();
- notifyEvent(ResponseCode::DiskVolumeCreated, vol->getId());
}
void Disk::createPrivateVolume(dev_t device, const std::string& partGuid) {
}
mVolumes.push_back(vol);
+ vol->setDiskId(getId());
vol->create();
- notifyEvent(ResponseCode::DiskVolumeCreated, vol->getId());
}
void Disk::destroyAllVolumes() {
for (auto vol : mVolumes) {
vol->destroy();
- notifyEvent(ResponseCode::DiskVolumeDestroyed, vol->getId());
}
mVolumes.clear();
}
}
}
+#if ENTIRE_DEVICE_FALLBACK
// Ugly last ditch effort, treat entire disk as partition
if (table == Table::kUnknown || !foundParts) {
+ // TODO: use blkid to confirm filesystem before doing this
LOG(WARNING) << mId << " has unknown partition table; trying entire device";
createPublicVolume(mDevice);
}
+#endif
+
+ // Well this is embarrassing, we can't handle the disk
+ if (mVolumes.size() == 0) {
+ notifyEvent(ResponseCode::DiskUnsupported);
+ }
mJustPartitioned = false;
return OK;
return -EIO;
}
- if (getFlags() & Flags::kPrimary) {
+ if (getMountFlags() & MountFlags::kPrimary) {
initAsecStage();
}
- // Only need to spin up FUSE when visible
- if (!(getFlags() & Flags::kVisible)) {
- return OK;
- }
-
// TODO: teach FUSE daemon to protect itself with user-specific GID
if (!(mFusePid = fork())) {
- if (getFlags() & Flags::kPrimary) {
+ if (!(getMountFlags() & MountFlags::kVisible)) {
+ // TODO: mount so that only system apps can access
+ if (execl(kFusePath, kFusePath,
+ "-u", "1023", // AID_MEDIA_RW
+ "-g", "1023", // AID_MEDIA_RW
+ mRawPath.c_str(),
+ mFusePath.c_str(),
+ NULL)) {
+ PLOG(ERROR) << "Failed to exec";
+ }
+ } else if (getMountFlags() & MountFlags::kPrimary) {
if (execl(kFusePath, kFusePath,
"-u", "1023", // AID_MEDIA_RW
"-g", "1023", // AID_MEDIA_RW
static const int DiskCreated = 640;
static const int DiskSizeChanged = 641;
static const int DiskLabelChanged = 642;
- static const int DiskVolumeCreated = 643;
- static const int DiskVolumeDestroyed = 644;
+ static const int DiskUnsupported = 643;
static const int DiskDestroyed = 649;
static const int VolumeCreated = 650;
namespace vold {
VolumeBase::VolumeBase(Type type) :
- mType(type), mFlags(0), mUser(-1), mCreated(false), mState(
+ mType(type), mMountFlags(0), mMountUserId(-1), mCreated(false), mState(
State::kUnmounted), mSilent(false) {
}
notifyEvent(ResponseCode::VolumeStateChanged, StringPrintf("%d", mState));
}
-status_t VolumeBase::setFlags(int flags) {
- if (mState != State::kUnmounted) {
- LOG(WARNING) << getId() << " flags change requires state unmounted";
+status_t VolumeBase::setDiskId(const std::string& diskId) {
+ if (mCreated) {
+ LOG(WARNING) << getId() << " diskId change requires destroyed";
+ return -EBUSY;
+ }
+
+ mDiskId = diskId;
+ return OK;
+}
+
+status_t VolumeBase::setMountFlags(int mountFlags) {
+ if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
+ LOG(WARNING) << getId() << " flags change requires state unmounted or unmountable";
return -EBUSY;
}
- mFlags = flags;
+ mMountFlags = mountFlags;
return OK;
}
-status_t VolumeBase::setUser(userid_t user) {
- if (mState != State::kUnmounted) {
- LOG(WARNING) << getId() << " user change requires state unmounted";
+status_t VolumeBase::setMountUserId(userid_t mountUserId) {
+ if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
+ LOG(WARNING) << getId() << " user change requires state unmounted or unmountable";
return -EBUSY;
}
- mUser = user;
+ mMountUserId = mountUserId;
return OK;
}
}
status_t VolumeBase::setPath(const std::string& path) {
- if (mState != State::kMounting) {
- LOG(WARNING) << getId() << " path change requires state mounting";
+ if (mState != State::kChecking) {
+ LOG(WARNING) << getId() << " path change requires state checking";
return -EBUSY;
}
mCreated = true;
status_t res = doCreate();
- notifyEvent(ResponseCode::VolumeCreated, StringPrintf("%d", mType));
+ notifyEvent(ResponseCode::VolumeCreated, StringPrintf("%d %s", mType, mDiskId.c_str()));
setState(State::kUnmounted);
return res;
}
if (mState == State::kMounted) {
unmount();
+ setState(State::kBadRemoval);
+ } else {
+ setState(State::kRemoved);
}
- setState(State::kRemoved);
notifyEvent(ResponseCode::VolumeDestroyed);
status_t res = doDestroy();
mCreated = false;
return -EBUSY;
}
- setState(State::kMounting);
+ setState(State::kChecking);
status_t res = doMount();
if (res == OK) {
setState(State::kMounted);
return -EBUSY;
}
- setState(State::kUnmounting);
+ setState(State::kEjecting);
for (auto vol : mVolumes) {
if (vol->destroy()) {
kObb,
};
- enum Flags {
+ enum MountFlags {
/* Flag that volume is primary external storage */
kPrimary = 1 << 0,
/* Flag that volume is visible to normal apps */
};
enum class State {
- /* Next states: mounting, formatting */
kUnmounted = 0,
- /* Next states: mounted, unmountable */
- kMounting,
- /* Next states: unmounting */
+ kChecking,
kMounted,
- /* Next states: unmounted */
+ kMountedReadOnly,
kFormatting,
- /* Next states: unmounted */
- kUnmounting,
- /* Next states: mounting, formatting */
+ kEjecting,
kUnmountable,
- /* Next states: none */
kRemoved,
+ kBadRemoval,
};
const std::string& getId() { return mId; }
+ const std::string& getDiskId() { return mDiskId; }
Type getType() { return mType; }
- int getFlags() { return mFlags; }
- userid_t getUser() { return mUser; }
+ int getMountFlags() { return mMountFlags; }
+ userid_t getMountUserId() { return mMountUserId; }
State getState() { return mState; }
const std::string& getPath() { return mPath; }
- status_t setFlags(int flags);
- status_t setUser(userid_t user);
+ status_t setDiskId(const std::string& diskId);
+ status_t setMountFlags(int mountFlags);
+ status_t setMountUserId(userid_t mountUserId);
status_t setSilent(bool silent);
void addVolume(const std::shared_ptr<VolumeBase>& volume);
private:
/* ID that uniquely references volume while alive */
std::string mId;
+ /* ID that uniquely references parent disk while alive */
+ std::string mDiskId;
/* Volume type */
Type mType;
- /* Flags applicable to volume */
- int mFlags;
+ /* Flags used when mounting this volume */
+ int mMountFlags;
/* User that owns this volume, otherwise -1 */
- userid_t mUser;
+ userid_t mMountUserId;
/* Flag indicating object is created */
bool mCreated;
/* Current state of volume */
#include "VoldUtil.h"
#include "cryptfs.h"
-#define DEBUG_NETLINK 0
-
#define MASS_STORAGE_FILE_PATH "/sys/class/android_usb/android0/f_mass_storage/lun/file"
#define ROUND_UP_POWER_OF_2(number, po2) (((!!(number & ((1U << po2) - 1))) << po2)\
return buffer;
}
-void VolumeManager::setDebug(bool enable) {
+int VolumeManager::setDebug(bool enable) {
mDebug = enable;
+ return 0;
}
int VolumeManager::start() {
}
void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
-#if DEBUG_NETLINK
- LOG(VERBOSE) << "handleBlockEvent with action " << (int) evt->getAction();
- evt->dump();
-#endif
+ if (mDebug) {
+ LOG(VERBOSE) << "----------------";
+ LOG(VERBOSE) << "handleBlockEvent with action " << (int) evt->getAction();
+ evt->dump();
+ }
std::string eventPath(evt->findParam("DEVPATH"));
std::string devType(evt->findParam("DEVTYPE"));
int unmountLoopImage(const char *containerId, const char *loopId,
const char *fileName, const char *mountPoint, bool force);
- void setDebug(bool enable);
+ int setDebug(bool enable);
void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; }
SocketListener *getBroadcaster() { return mBroadcaster; }