system: vold2: Initial skeleton for vold2.

  Let there be light.

Signed-off-by: San Mehat <san@android.com>
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);
+}
+