system: vold2: Initial skeleton for vold2.

Let there be light.

Signed-off-by: San Mehat <san@android.com>
This commit is contained in:
San Mehat 2009-10-10 17:22:08 -07:00
parent 8f8ba4d0c0
commit f1b736bc56
20 changed files with 1332 additions and 0 deletions

43
Android.mk Normal file
View file

@ -0,0 +1,43 @@
BUILD_VOLD2 := false
ifeq ($(BUILD_VOLD2),true)
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
main.cpp \
VolumeManager.cpp \
CommandListener.cpp \
VoldCommand.cpp \
NetlinkManager.cpp \
NetlinkHandler.cpp \
BlockDevice.cpp \
Volume.cpp \
DeviceVolume.cpp
LOCAL_MODULE:= vold
LOCAL_C_INCLUDES := $(KERNEL_HEADERS) -I../../frameworks/base/include/
LOCAL_CFLAGS :=
LOCAL_SHARED_LIBRARIES := libsysutils
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
vdc.c \
LOCAL_MODULE:= vdc
LOCAL_C_INCLUDES := $(KERNEL_HEADERS)
LOCAL_CFLAGS :=
LOCAL_SHARED_LIBRARIES := libcutils
include $(BUILD_EXECUTABLE)
endif # ifeq ($(BUILD_VOLD,true)

36
BlockDevice.cpp Normal file
View file

@ -0,0 +1,36 @@
/*
* Copyright (C) 2008 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 <stdio.h>
#include <errno.h>
#include <string.h>
#define LOG_TAG "Vold"
#include <cutils/log.h>
#include "BlockDevice.h"
BlockDevice::BlockDevice(const char *devpath, int major, int minor) {
mDevpath = strdup(devpath);
mMajor = major;
mMinor = minor;
}
BlockDevice::~BlockDevice() {
free(mDevpath);
}

39
BlockDevice.h Normal file
View file

@ -0,0 +1,39 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _BLKDEVICE_H
#define _BLKDEVICE_H
#include <utils/List.h>
class BlockDevice {
char *mDevpath;
int mMajor;
int mMinor;
public:
BlockDevice(const char *devpath, int major, int minor);
virtual ~BlockDevice();
const char *getDevpath() { return mDevpath; }
int getMajor() { return mMajor; }
int getMinor() { return mMinor; }
};
typedef android::List<BlockDevice *> BlockDeviceCollection;
#endif

96
CommandListener.cpp Normal file
View file

@ -0,0 +1,96 @@
/*
* Copyright (C) 2008 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 <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#define LOG_TAG "CommandListener"
#include <cutils/log.h>
#include <sysutils/SocketClient.h>
#include "CommandListener.h"
#include "VolumeManager.h"
#include "ErrorCode.h"
CommandListener::CommandListener() :
FrameworkListener("vold") {
registerCmd(new ListVolumesCmd());
registerCmd(new MountVolumeCmd());
registerCmd(new UnmountVolumeCmd());
registerCmd(new ShareVolumeCmd());
registerCmd(new UnshareVolumeCmd());
}
CommandListener::ListVolumesCmd::ListVolumesCmd() :
VoldCommand("list_volumes") {
}
int CommandListener::ListVolumesCmd::runCommand(SocketClient *cli,
int argc, char **argv) {
return VolumeManager::Instance()->listVolumes(cli);
}
CommandListener::MountVolumeCmd::MountVolumeCmd() :
VoldCommand("mount_volume") {
}
int CommandListener::MountVolumeCmd::runCommand(SocketClient *cli,
int argc, char **argv) {
VolumeManager *nm = VolumeManager::Instance();
errno = ENOSYS;
cli->sendMsg(ErrorCode::OperationFailed, "Failed to mount volume", true);
return 0;
}
CommandListener::UnmountVolumeCmd::UnmountVolumeCmd() :
VoldCommand("unmount_volume") {
}
int CommandListener::UnmountVolumeCmd::runCommand(SocketClient *cli,
int argc, char **argv) {
VolumeManager *nm = VolumeManager::Instance();
errno = ENOSYS;
cli->sendMsg(ErrorCode::OperationFailed, "Failed to unmount volume", true);
return 0;
}
CommandListener::ShareVolumeCmd::ShareVolumeCmd() :
VoldCommand("share_volume") {
}
int CommandListener::ShareVolumeCmd::runCommand(SocketClient *cli,
int argc, char **argv) {
VolumeManager *nm = VolumeManager::Instance();
errno = ENOSYS;
cli->sendMsg(ErrorCode::OperationFailed, "Failed to share volume", true);
return 0;
}
CommandListener::UnshareVolumeCmd::UnshareVolumeCmd() :
VoldCommand("unshare_volume") {
}
int CommandListener::UnshareVolumeCmd::runCommand(SocketClient *cli,
int argc, char **argv) {
VolumeManager *nm = VolumeManager::Instance();
errno = ENOSYS;
cli->sendMsg(ErrorCode::OperationFailed, "Failed to unshare volume", true);
return 0;
}

67
CommandListener.h Normal file
View file

@ -0,0 +1,67 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _COMMANDLISTENER_H__
#define _COMMANDLISTENER_H__
#include <sysutils/FrameworkListener.h>
#include "VoldCommand.h"
class CommandListener : public FrameworkListener {
public:
CommandListener();
virtual ~CommandListener() {}
private:
class ListVolumesCmd : public VoldCommand {
public:
ListVolumesCmd();
virtual ~ListVolumesCmd() {}
int runCommand(SocketClient *c, int argc, char ** argv);
};
class MountVolumeCmd : public VoldCommand {
public:
MountVolumeCmd();
virtual ~MountVolumeCmd() {}
int runCommand(SocketClient *c, int argc, char ** argv);
};
class UnmountVolumeCmd : public VoldCommand {
public:
UnmountVolumeCmd();
virtual ~UnmountVolumeCmd() {}
int runCommand(SocketClient *c, int argc, char ** argv);
};
class ShareVolumeCmd : public VoldCommand {
public:
ShareVolumeCmd();
virtual ~ShareVolumeCmd() {}
int runCommand(SocketClient *c, int argc, char ** argv);
};
class UnshareVolumeCmd : public VoldCommand {
public:
UnshareVolumeCmd();
virtual ~UnshareVolumeCmd() {}
int runCommand(SocketClient *c, int argc, char ** argv);
};
};
#endif

73
DeviceVolume.cpp Normal file
View file

@ -0,0 +1,73 @@
/*
* Copyright (C) 2008 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 <stdio.h>
#include <errno.h>
#include <string.h>
#define LOG_TAG "Vold"
#include <cutils/log.h>
#include "DeviceVolume.h"
DeviceVolume::DeviceVolume(const char *label, const char *mount_point, int partIdx) :
Volume(label, mount_point) {
mPartIdx = partIdx;
mPaths = new PathCollection();
}
DeviceVolume::~DeviceVolume() {
PathCollection::iterator it;
for (it = mPaths->begin(); it != mPaths->end(); ++it)
free(*it);
delete mPaths;
}
int DeviceVolume::addPath(const char *path) {
mPaths->push_back(strdup(path));
return 0;
}
int DeviceVolume::handleDiskInsertion(const char *dp, int maj, int min,
int nr_parts) {
PathCollection::iterator it;
LOGD("Dv::diskInsertion - %s %d %d %d", dp, maj, min, nr_parts);
for (it = mPaths->begin(); it != mPaths->end(); ++it) {
LOGD("Dv::chk %s", *it);
if (!strncmp(dp, *it, strlen(*it))) {
/*
* We can handle this disk. If there are no partitions then we're
* good to go son!
*/
mDiskMaj = maj;
mDiskNumParts = nr_parts;
if (nr_parts == 0) {
LOGD("Dv::diskIns - No partitions - good to go");
setState(Volume::State_Idle);
} else {
LOGD("Dv::diskIns - waiting for %d partitions", nr_parts);
setState(Volume::State_Pending);
}
return 0;
}
}
errno = ENODEV;
return -1;
}

44
DeviceVolume.h Normal file
View file

@ -0,0 +1,44 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _DEVICEVOLUME_H
#define _DEVICEVOLUME_H
#include <utils/List.h>
#include "Volume.h"
typedef android::List<char *> PathCollection;
class DeviceVolume : public Volume {
protected:
PathCollection *mPaths;
int mPartIdx;
int mDiskMaj;
int mDiskNumParts;
public:
DeviceVolume(const char *label, const char *mount_point, int partIdx);
virtual ~DeviceVolume();
int addPath(const char *path);
int handleDiskInsertion(const char *dp, int maj, int min, int nr_parts);
};
typedef android::List<DeviceVolume *> DeviceVolumeCollection;
#endif

43
ErrorCode.h Normal file
View file

@ -0,0 +1,43 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _ERRORCODE_H
#define _ERRORCODE_H
class ErrorCode {
public:
// 100 series - Requestion action was initiated; expect another reply
// before proceeding with a new command.
static const int ActionInitiated = 100;
static const int VolumeListResult = 110;
// 200 series - Requested action has been successfully completed
static const int CommandOkay = 200;
// 400 series - The command was accepted but the requested action
// did not take place.
static const int OperationFailed = 400;
// 500 series - The command was not accepted and the requested
// action did not take place.
static const int CommandSyntaxError = 500;
static const int CommandParameterError = 501;
// 600 series - Unsolicited broadcasts
static const int UnsolicitedInformational = 600;
};
#endif

91
NetlinkHandler.cpp Normal file
View file

@ -0,0 +1,91 @@
/*
* Copyright (C) 2008 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 <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define LOG_TAG "Vold"
#include <cutils/log.h>
#include <sysutils/NetlinkEvent.h>
#include "NetlinkHandler.h"
#include "VolumeManager.h"
NetlinkHandler::NetlinkHandler(int listenerSocket) :
NetlinkListener(listenerSocket) {
}
NetlinkHandler::~NetlinkHandler() {
}
int NetlinkHandler::start() {
return this->startListener();
}
int NetlinkHandler::stop() {
return this->stopListener();
}
void NetlinkHandler::onEvent(NetlinkEvent *evt) {
VolumeManager *vm = VolumeManager::Instance();
const char *subsys = evt->getSubsystem();
int action = evt->getAction();
if (!subsys) {
LOGW("No subsystem found in netlink event");
return;
}
if (!strcmp(subsys, "block")) {
const char *devpath = evt->findParam("DEVPATH");
const char *devtype = evt->findParam("DEVTYPE");
int major = atoi(evt->findParam("MAJOR"));
int minor = atoi(evt->findParam("MINOR"));
LOGI("Block event %d, type %s, %d:%d, path '%s'", action, devtype, major, minor, devpath);
if (!strcmp(devtype, "disk")) {
const char *tmp = evt->findParam("NPARTS");
if (!tmp) {
LOGE("Disk uevent missing 'NPARTS' parameter");
return;
}
if (action == NetlinkEvent::NlActionAdd)
vm->handleDiskInserted(devpath, major, minor, atoi(tmp));
else if (action == NetlinkEvent::NlActionRemove)
vm->handleDiskRemoved(major, minor);
} else {
const char *tmp = evt->findParam("PARTN");
if (!tmp) {
LOGE("Partition uevent missing 'PARTN' parameter");
return;
}
if (action == NetlinkEvent::NlActionAdd)
vm->handlePartCreated(devpath, major, minor, atoi(tmp));
else if (action == NetlinkEvent::NlActionRemove)
vm->handlePartRemoved(major, minor);
}
LOGD("Block event handled");
} else if (!strcmp(subsys, "battery")) {
} else if (!strcmp(subsys, "power_supply")) {
} else {
LOGE("Dropping %s netlink event", subsys);
}
}

34
NetlinkHandler.h Normal file
View file

@ -0,0 +1,34 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _NETLINKHANDLER_H
#define _NETLINKHANDLER_H
#include <sysutils/NetlinkListener.h>
class NetlinkHandler: public NetlinkListener {
public:
NetlinkHandler(int listenerSocket);
virtual ~NetlinkHandler();
int start(void);
int stop(void);
protected:
virtual void onEvent(NetlinkEvent *evt);
};
#endif

95
NetlinkManager.cpp Normal file
View file

@ -0,0 +1,95 @@
/*
* Copyright (C) 2008 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 <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/un.h>
#include <linux/netlink.h>
#define LOG_TAG "Vold"
#include <cutils/log.h>
#include "NetlinkManager.h"
#include "NetlinkHandler.h"
NetlinkManager *NetlinkManager::sInstance = NULL;
NetlinkManager *NetlinkManager::Instance() {
if (!sInstance)
sInstance = new NetlinkManager();
return sInstance;
}
NetlinkManager::NetlinkManager() {
mBroadcaster = NULL;
}
NetlinkManager::~NetlinkManager() {
}
int NetlinkManager::start() {
struct sockaddr_nl nladdr;
int sz = 64 * 1024;
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = getpid();
nladdr.nl_groups = 0xffffffff;
if ((mSock = socket(PF_NETLINK,
SOCK_DGRAM,NETLINK_KOBJECT_UEVENT)) < 0) {
LOGE("Unable to create uevent socket: %s", strerror(errno));
return -1;
}
if (setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) {
LOGE("Unable to set uevent socket options: %s", strerror(errno));
return -1;
}
if (bind(mSock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {
LOGE("Unable to bind uevent socket: %s", strerror(errno));
return -1;
}
mHandler = new NetlinkHandler(mSock);
if (mHandler->start()) {
LOGE("Unable to start NetlinkHandler: %s", strerror(errno));
return -1;
}
return 0;
}
int NetlinkManager::stop() {
if (mHandler->stop()) {
LOGE("Unable to stop NetlinkHandler: %s", strerror(errno));
return -1;
}
delete mHandler;
mHandler = NULL;
close(mSock);
mSock = -1;
return 0;
}

48
NetlinkManager.h Normal file
View file

@ -0,0 +1,48 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _NETLINKMANAGER_H
#define _NETLINKMANAGER_H
#include <sysutils/SocketListener.h>
#include <sysutils/NetlinkListener.h>
class NetlinkHandler;
class NetlinkManager {
private:
static NetlinkManager *sInstance;
private:
SocketListener *mBroadcaster;
NetlinkHandler *mHandler;
int mSock;
public:
virtual ~NetlinkManager();
int start();
int stop();
void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; }
SocketListener *getBroadcaster() { return mBroadcaster; }
static NetlinkManager *Instance();
private:
NetlinkManager();
};
#endif

21
VoldCommand.cpp Normal file
View file

@ -0,0 +1,21 @@
/*
* Copyright (C) 2008 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 "VoldCommand.h"
VoldCommand::VoldCommand(const char *cmd) :
FrameworkCommand(cmd) {
}

28
VoldCommand.h Normal file
View file

@ -0,0 +1,28 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _VOLD_COMMAND_H
#define _VOLD_COMMAND_H
#include <sysutils/FrameworkCommand.h>
class VoldCommand : public FrameworkCommand {
public:
VoldCommand(const char *cmd);
virtual ~VoldCommand() {}
};
#endif

46
Volume.cpp Normal file
View file

@ -0,0 +1,46 @@
/*
* Copyright (C) 2008 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 <stdio.h>
#include <errno.h>
#include <string.h>
#define LOG_TAG "Vold"
#include <cutils/log.h>
#include "Volume.h"
Volume::Volume(const char *label, const char *mount_point) {
mLabel = strdup(label);
mMountpoint = strdup(mount_point);
mState = Volume::State_Init;
}
Volume::~Volume() {
free(mLabel);
free(mMountpoint);
}
int Volume::handleDiskInsertion(const char *dp, int maj, int min, int nr_parts) {
errno = ENOSYS;
return -1;
}
void Volume::setState(int state) {
LOGD("Volume %s state changing %d -> %d", mLabel, mState, state);
mState = state;
}

54
Volume.h Normal file
View file

@ -0,0 +1,54 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _VOLUME_H
#define _VOLUME_H
#include <utils/List.h>
class Volume {
private:
int mState;
public:
static const int State_Init = -1;
static const int State_Idle = 1;
static const int State_Pending = 2;
static const int State_Mounted = 3;
static const int State_Checking = 4;
static const int State_Formatting = 5;
protected:
char *mLabel;
char *mMountpoint;
public:
Volume(const char *label, const char *mount_point);
virtual ~Volume();
const char *getLabel() { return mLabel; }
const char *getMountpoint() { return mMountpoint; }
int getState() { return mState; }
virtual int handleDiskInsertion(const char *dp, int maj, int min, int nr_parts);
protected:
void setState(int state);
};
typedef android::List<Volume *> VolumeCollection;
#endif

103
VolumeManager.cpp Normal file
View file

@ -0,0 +1,103 @@
/*
* Copyright (C) 2008 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 <stdio.h>
#include <errno.h>
#define LOG_TAG "Vold"
#include <cutils/log.h>
#include "VolumeManager.h"
#include "DeviceVolume.h"
#include "ErrorCode.h"
VolumeManager *VolumeManager::sInstance = NULL;
VolumeManager *VolumeManager::Instance() {
if (!sInstance)
sInstance = new VolumeManager();
return sInstance;
}
VolumeManager::VolumeManager() {
mBlockDevices = new BlockDeviceCollection();
mVolumes = new VolumeCollection();
mBroadcaster = NULL;
}
VolumeManager::~VolumeManager() {
delete mBlockDevices;
}
int VolumeManager::start() {
return 0;
}
int VolumeManager::stop() {
return 0;
}
int VolumeManager::addVolume(Volume *v) {
mVolumes->push_back(v);
return 0;
}
void VolumeManager::handleDiskInserted(const char *devpath, int maj, int min,
int nr_parts) {
/* Lookup possible candidate DeviceVolumes */
VolumeCollection::iterator it;
bool hit = false;
for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
if (!(*it)->handleDiskInsertion(devpath, maj, min, nr_parts)) {
hit = true;
LOGD("Volume '%s' has handled disk insertion for '%s'",
(*it)->getLabel(), devpath);
break;
}
}
if (!hit) {
LOGW("No volumes handled insertion of disk '%s'", devpath);
}
}
void VolumeManager::handleDiskRemoved(int maj, int min) {
}
void VolumeManager::handlePartCreated(const char *devpath, int maj, int min,
int part_no) {
}
void VolumeManager::handlePartRemoved(int maj, int min) {
}
int VolumeManager::listVolumes(SocketClient *cli) {
VolumeCollection::iterator i;
for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
char *buffer;
asprintf(&buffer, "%s %s %d",
(*i)->getLabel(), (*i)->getMountpoint(),
(*i)->getState());
cli->sendMsg(ErrorCode::VolumeListResult, buffer, false);
free(buffer);
}
cli->sendMsg(ErrorCode::CommandOkay, "Volumes Listed", false);
return 0;
}

64
VolumeManager.h Normal file
View file

@ -0,0 +1,64 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _VOLUMEMANAGER_H
#define _VOLUMEMANAGER_H
#include <pthread.h>
#include <utils/List.h>
#include <sysutils/SocketListener.h>
#include "BlockDevice.h"
#include "Volume.h"
class VolumeManager {
private:
static VolumeManager *sInstance;
private:
SocketListener *mBroadcaster;
BlockDeviceCollection *mBlockDevices;
VolumeCollection *mVolumes;
public:
virtual ~VolumeManager();
int start();
int stop();
void handleDiskInserted(const char *devpath, int maj, int min,
int nr_parts);
void handleDiskRemoved(int maj, int min);
void handlePartCreated(const char *devpath, int maj, int min,
int part_no);
void handlePartRemoved(int maj, int min);
int addVolume(Volume *v);
int listVolumes(SocketClient *cli);
void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; }
SocketListener *getBroadcaster() { return mBroadcaster; }
static VolumeManager *Instance();
private:
VolumeManager();
};
#endif

159
main.cpp Normal file
View file

@ -0,0 +1,159 @@
/*
* Copyright (C) 2008 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 <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#define LOG_TAG "Vold"
#include "cutils/log.h"
#include "VolumeManager.h"
#include "CommandListener.h"
#include "NetlinkManager.h"
#include "DeviceVolume.h"
static int process_config(VolumeManager *vm);
int main() {
VolumeManager *vm;
CommandListener *cl;
NetlinkManager *nm;
LOGI("Vold 2.0 firing up");
/* Create our singleton managers */
if (!(vm = VolumeManager::Instance())) {
LOGE("Unable to create VolumeManager");
exit(1);
};
if (!(nm = NetlinkManager::Instance())) {
LOGE("Unable to create NetlinkManager");
exit(1);
};
cl = new CommandListener();
vm->setBroadcaster((SocketListener *) cl);
nm->setBroadcaster((SocketListener *) cl);
if (vm->start()) {
LOGE("Unable to start VolumeManager (%s)", strerror(errno));
exit(1);
}
if (process_config(vm)) {
LOGE("Error reading configuration (%s)", strerror(errno));
exit(1);
}
if (nm->start()) {
LOGE("Unable to start NetlinkManager (%s)", strerror(errno));
exit(1);
}
/*
* Now that we're up, we can respond to commands
*/
if (cl->startListener()) {
LOGE("Unable to start CommandListener (%s)", strerror(errno));
exit(1);
}
// Eventually we'll become the monitoring thread
while(1) {
sleep(1000);
}
LOGI("Vold exiting");
exit(0);
}
static int process_config(VolumeManager *vm) {
FILE *fp;
int n = 0;
char line[255];
if (!(fp = fopen("/etc/vold.fstab", "r"))) {
return -1;
}
while(fgets(line, sizeof(line), fp)) {
char *next = line;
char *type, *label, *mount_point;
n++;
line[strlen(line)-1] = '\0';
if (line[0] == '#' || line[0] == '\0')
continue;
if (!(type = strsep(&next, " \t"))) {
LOGE("Error parsing type");
goto out_syntax;
}
if (!(label = strsep(&next, " \t"))) {
LOGE("Error parsing label");
goto out_syntax;
}
if (!(mount_point = strsep(&next, " \t"))) {
LOGE("Error parsing mount point");
goto out_syntax;
}
if (!strcmp(type, "dev_mount")) {
DeviceVolume *dv = NULL;
char *part, *sysfs_path;
if (!(part = strsep(&next, " \t"))) {
LOGE("Error parsing partition");
goto out_syntax;
}
if (strcmp(part, "auto") && atoi(part) == 0) {
LOGE("Partition must either be 'auto' or 1 based index instead of '%s'", part);
goto out_syntax;
}
dv = new DeviceVolume(label, mount_point, atoi(part));
while((sysfs_path = strsep(&next, " \t"))) {
if (dv->addPath(sysfs_path)) {
LOGE("Failed to add devpath %s to volume %s", sysfs_path,
label);
goto out_fail;
}
}
vm->addVolume(dv);
} else if (!strcmp(type, "map_mount")) {
} else {
LOGE("Unknown type '%s'", type);
goto out_syntax;
}
}
fclose(fp);
return 0;
out_syntax:
LOGE("Syntax error on config line %d", n);
errno = -EINVAL;
out_fail:
fclose(fp);
return -1;
}

148
vdc.c Normal file
View file

@ -0,0 +1,148 @@
/*
* Copyright (C) 2008 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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/un.h>
#include <cutils/sockets.h>
#include <private/android_filesystem_config.h>
static void usage(char *progname);
static int do_monitor(int sock, int stop_after_cmd);
static int do_cmd(int sock, int argc, char **argv);
int main(int argc, char **argv) {
int sock;
if (argc < 2)
usage(argv[0]);
if ((sock = socket_local_client("vold",
ANDROID_SOCKET_NAMESPACE_RESERVED,
SOCK_STREAM)) < 0) {
fprintf(stderr, "Error connecting (%s)\n", strerror(errno));
exit(4);
}
if (!strcmp(argv[1], "monitor"))
exit(do_monitor(sock, 0));
exit(do_cmd(sock, argc, argv));
}
static int do_cmd(int sock, int argc, char **argv) {
char final_cmd[255] = { '\0' };
int i;
for (i = 1; i < argc; i++) {
char *cmp;
if (!index(argv[i], ' '))
asprintf(&cmp, "%s%s", argv[i], (i == (argc -1)) ? "" : " ");
else
asprintf(&cmp, "\"%s\"%s", argv[i], (i == (argc -1)) ? "" : " ");
strcat(final_cmd, cmp);
free(cmp);
}
if (write(sock, final_cmd, strlen(final_cmd) + 1) < 0) {
perror("write");
return errno;
}
return do_monitor(sock, 1);
}
static int do_monitor(int sock, int stop_after_cmd) {
char *buffer = malloc(4096);
if (!stop_after_cmd)
printf("[Connected to Vold]\n");
while(1) {
fd_set read_fds;
struct timeval to;
int rc = 0;
to.tv_sec = 10;
to.tv_usec = 0;
FD_ZERO(&read_fds);
FD_SET(sock, &read_fds);
if ((rc = select(sock +1, &read_fds, NULL, NULL, &to)) < 0) {
fprintf(stderr, "Error in select (%s)\n", strerror(errno));
free(buffer);
return errno;
} else if (!rc) {
continue;
fprintf(stderr, "[TIMEOUT]\n");
return ETIMEDOUT;
} else if (FD_ISSET(sock, &read_fds)) {
memset(buffer, 0, 4096);
if ((rc = read(sock, buffer, 4096)) <= 0) {
if (rc == 0)
fprintf(stderr, "Lost connection to Vold - did it crash?\n");
else
fprintf(stderr, "Error reading data (%s)\n", strerror(errno));
free(buffer);
if (rc == 0)
return ECONNRESET;
return errno;
}
int offset = 0;
int i = 0;
for (i = 0; i < rc; i++) {
if (buffer[i] == '\0') {
int code;
char tmp[4];
strncpy(tmp, buffer + offset, 3);
tmp[3] = '\0';
code = atoi(tmp);
printf("%s\n", buffer + offset);
if (stop_after_cmd) {
if (code >= 200 && code < 600)
return 0;
}
offset = i + 1;
}
}
}
}
free(buffer);
return 0;
}
static void usage(char *progname) {
fprintf(stderr, "Usage: %s <monitor>|<cmd> [arg1] [arg2...]\n", progname);
exit(1);
}