summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk43
-rw-r--r--BlockDevice.cpp36
-rw-r--r--BlockDevice.h39
-rw-r--r--CommandListener.cpp96
-rw-r--r--CommandListener.h67
-rw-r--r--DeviceVolume.cpp73
-rw-r--r--DeviceVolume.h44
-rw-r--r--ErrorCode.h43
-rw-r--r--NetlinkHandler.cpp91
-rw-r--r--NetlinkHandler.h34
-rw-r--r--NetlinkManager.cpp95
-rw-r--r--NetlinkManager.h48
-rw-r--r--VoldCommand.cpp21
-rw-r--r--VoldCommand.h28
-rw-r--r--Volume.cpp46
-rw-r--r--Volume.h54
-rw-r--r--VolumeManager.cpp103
-rw-r--r--VolumeManager.h64
-rw-r--r--main.cpp159
-rw-r--r--vdc.c148
20 files changed, 1332 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..3af7544
--- /dev/null
+++ b/Android.mk
@@ -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)
diff --git a/BlockDevice.cpp b/BlockDevice.cpp
new file mode 100644
index 0000000..97c980d
--- /dev/null
+++ b/BlockDevice.cpp
@@ -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);
+}
+
diff --git a/BlockDevice.h b/BlockDevice.h
new file mode 100644
index 0000000..0239824
--- /dev/null
+++ b/BlockDevice.h
@@ -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
diff --git a/CommandListener.cpp b/CommandListener.cpp
new file mode 100644
index 0000000..f395818
--- /dev/null
+++ b/CommandListener.cpp
@@ -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;
+}
diff --git a/CommandListener.h b/CommandListener.h
new file mode 100644
index 0000000..9c770a2
--- /dev/null
+++ b/CommandListener.h
@@ -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
diff --git a/DeviceVolume.cpp b/DeviceVolume.cpp
new file mode 100644
index 0000000..187e97f
--- /dev/null
+++ b/DeviceVolume.cpp
@@ -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;
+}
diff --git a/DeviceVolume.h b/DeviceVolume.h
new file mode 100644
index 0000000..edf4c98
--- /dev/null
+++ b/DeviceVolume.h
@@ -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
diff --git a/ErrorCode.h b/ErrorCode.h
new file mode 100644
index 0000000..328b2b1
--- /dev/null
+++ b/ErrorCode.h
@@ -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
diff --git a/NetlinkHandler.cpp b/NetlinkHandler.cpp
new file mode 100644
index 0000000..156079f
--- /dev/null
+++ b/NetlinkHandler.cpp
@@ -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);
+ }
+}
diff --git a/NetlinkHandler.h b/NetlinkHandler.h
new file mode 100644
index 0000000..00a31c8
--- /dev/null
+++ b/NetlinkHandler.h
@@ -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
diff --git a/NetlinkManager.cpp b/NetlinkManager.cpp
new file mode 100644
index 0000000..271a75f
--- /dev/null
+++ b/NetlinkManager.cpp
@@ -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;
+}
diff --git a/NetlinkManager.h b/NetlinkManager.h
new file mode 100644
index 0000000..9c7ba11
--- /dev/null
+++ b/NetlinkManager.h
@@ -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
diff --git a/VoldCommand.cpp b/VoldCommand.cpp
new file mode 100644
index 0000000..3c0d58d
--- /dev/null
+++ b/VoldCommand.cpp
@@ -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) {
+}
diff --git a/VoldCommand.h b/VoldCommand.h
new file mode 100644
index 0000000..5ddc666
--- /dev/null
+++ b/VoldCommand.h
@@ -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
diff --git a/Volume.cpp b/Volume.cpp
new file mode 100644
index 0000000..aaccb2b
--- /dev/null
+++ b/Volume.cpp
@@ -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;
+}
diff --git a/Volume.h b/Volume.h
new file mode 100644
index 0000000..bf2a799
--- /dev/null
+++ b/Volume.h
@@ -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
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
new file mode 100644
index 0000000..ffe4e22
--- /dev/null
+++ b/VolumeManager.cpp
@@ -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;
+}
diff --git a/VolumeManager.h b/VolumeManager.h
new file mode 100644
index 0000000..8263805
--- /dev/null
+++ b/VolumeManager.h
@@ -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
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..1ccd147
--- /dev/null
+++ b/main.cpp
@@ -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;
+}
diff --git a/vdc.c b/vdc.c
new file mode 100644
index 0000000..4f94ad3
--- /dev/null
+++ b/vdc.c
@@ -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);
+}
+