Code drop from //branches/cupcake/...@124589
diff --git a/adb/Android.mk b/adb/Android.mk
index 8ac5eb4..c06485f 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -7,6 +7,7 @@
 
 # adb host tool
 # =========================================================
+ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean (also unused with the sim)
 include $(CLEAR_VARS)
 
 # Default to a virtual (sockets) usb interface
@@ -29,7 +30,7 @@
   USB_SRCS := usb_windows.c
   EXTRA_SRCS := get_my_path_windows.c
   EXTRA_STATIC_LIBS := AdbWinApi
-  LOCAL_C_INCLUDES += /usr/include/w32api/ddk $(LOCAL_PATH)/../windows/usb/api
+  LOCAL_C_INCLUDES += /usr/include/w32api/ddk development/host/windows/usb/api/
   ifneq ($(strip $(USE_CYGWIN)),)
     LOCAL_LDLIBS += -lpthread
   else
@@ -51,7 +52,8 @@
 	file_sync_client.c \
 	$(EXTRA_SRCS) \
 	$(USB_SRCS) \
-	shlist.c
+	shlist.c \
+	utils.c \
 
 
 ifneq ($(USE_SYSDEPS_WIN32),)
@@ -69,6 +71,8 @@
 
 include $(BUILD_HOST_EXECUTABLE)
 
+$(call dist-for-goals,droid,$(LOCAL_BUILT_MODULE))
+
 ifeq ($(HOST_OS),windows)
 $(LOCAL_INSTALLED_MODULE): $(HOST_OUT_EXECUTABLES)/AdbWinApi.dll
 endif
@@ -81,10 +85,25 @@
 include $(BUILD_HOST_EXECUTABLE)
 endif
 
+endif
 
 # adbd device daemon
 # =========================================================
-ifeq ($(TARGET_ARCH),arm)
+
+# build adbd in all non-simulator builds
+BUILD_ADBD := false
+ifneq ($(TARGET_SIMULATOR),true)
+    BUILD_ADBD := true
+endif
+
+# build adbd for the Linux simulator build
+# so we can use it to test the adb USB gadget driver on x86
+ifeq ($(HOST_OS),linux)
+    BUILD_ADBD := true
+endif
+
+
+ifeq ($(BUILD_ADBD),true)
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := \
@@ -99,18 +118,31 @@
 	framebuffer_service.c \
 	remount_service.c \
 	usb_linux_client.c \
-	log_service.c
+	log_service.c \
+	utils.c \
 
-
-LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -DANDROID_GADGET=1 -Wall -Wno-unused-parameter
+LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter
 LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE
+
+# TODO: This should probably be board specific, whether or not the kernel has
+# the gadget driver; rather than relying on the architecture type.
+ifeq ($(TARGET_ARCH),arm)
+LOCAL_CFLAGS += -DANDROID_GADGET=1
+endif
+
 LOCAL_MODULE := adbd
 
 LOCAL_FORCE_STATIC_EXECUTABLE := true
 LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)
 LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)
 
-LOCAL_STATIC_LIBRARIES := libcutils libc
+ifeq ($(TARGET_SIMULATOR),true)
+  LOCAL_STATIC_LIBRARIES := libcutils
+  LOCAL_LDLIBS += -lpthread
+  include $(BUILD_HOST_EXECUTABLE)
+else
+  LOCAL_STATIC_LIBRARIES := libcutils libc
+  include $(BUILD_EXECUTABLE)
+endif
 
-include $(BUILD_EXECUTABLE)
 endif
diff --git a/adb/OVERVIEW.TXT b/adb/OVERVIEW.TXT
new file mode 100644
index 0000000..6a5191a
--- /dev/null
+++ b/adb/OVERVIEW.TXT
@@ -0,0 +1,139 @@
+Implementation notes regarding ADB.
+
+I. General Overview:
+
+The Android Debug Bridge (ADB) is used to:
+
+- keep track of all Android devices and emulators instances
+  connected to or running on a given host developer machine
+
+- implement various control commands (e.g. "adb shell", "adb pull", etc..)
+  for the benefit of clients (command-line users, or helper programs like
+  DDMS). These commands are what is called a 'service' in ADB.
+
+As a whole, everything works through the following components:
+
+  1. The ADB server
+
+    This is a background process that runs on the host machine. Its purpose
+    if to sense the USB ports to know when devices are attached/removed,
+    as well as when emulator instances start/stop.
+
+    It thus maintains a list of "connected devices" and assigns a 'state'
+    to each one of them: OFFLINE, BOOTLOADER, RECOVERY or ONLINE (more on
+    this below).
+
+    The ADB server is really one giant multiplexing loop whose purpose is
+    to orchestrate the exchange of data (packets, really) between clients,
+    services and devices.
+
+
+  2. The ADB daemon (adbd)
+
+    The 'adbd' program runs as a background process within an Android device
+    or emulated system. Its purpose is to connect to the ADB server
+    (through USB for devices, through TCP for emulators) and provide a
+    few services for clients that run on the host.
+
+    The ADB server considers that a device is ONLINE when it has succesfully
+    connected to the adbd program within it. Otherwise, the device is OFFLINE,
+    meaning that the ADB server detected a new device/emulator, but could not
+    connect to the adbd daemon.
+
+    the BOOTLOADER and RECOVERY states correspond to alternate states of
+    devices when they are in the bootloader or recovery mode.
+
+  3. The ADB command-line client
+
+    The 'adb' command-line program is used to run adb commands from a shell
+    or a script. It first tries to locate the ADB server on the host machine,
+    and will start one automatically if none is found.
+
+    then, the client sends its service requests to the ADB server. It doesn't
+    need to know.
+
+    Currently, a single 'adb' binary is used for both the server and client.
+    this makes distribution and starting the server easier.
+
+
+  4. Services
+
+    There are essentially two kinds of services that a client can talk to.
+
+    Host Services:
+      these services run within the ADB Server and thus do not need to
+      communicate with a device at all. A typical example is "adb devices"
+      which is used to return the list of currently known devices and their
+      state. They are a few couple other services though.
+
+    Local Services:
+      these services either run within the adbd daemon, or are started by
+      it on the device. The ADB server is used to multiplex streams
+      between the client and the service running in adbd. In this case
+      its role is to initiate the connection, then of being a pass-through
+      for the data.
+
+
+II. Protocol details:
+
+  1. Client <-> Server protocol:
+
+    This details the protocol used between ADB clients and the ADB
+    server itself. The ADB server listens on TCP:localhost:5037.
+
+    A client sends a request using the following format:
+
+        1. A 4-byte hexadecimal string giving the length of the payload
+        2. Followed by the payload itself.
+
+    For example, to query the ADB server for its internal version number,
+    the client will do the following:
+
+        1. Connect to tcp:localhost:5037
+        2. Send the string "000Chost:version" to the corresponding socket
+
+    The 'host:' prefix is used to indicate that the request is addressed
+    to the server itself (we will talk about other kinds of requests later).
+    The content length is encoded in ASCII for easier debugging.
+
+    The server should answer a request with one of the following:
+
+        1. For success, the 4-byte "OKAY" string
+
+        2. For failure, the 4-byte "FAIL" string, followed by a
+           4-byte hex length, followed by a string giving the reason
+           for failure.
+
+        3. As a special exception, for 'host:version', a 4-byte
+           hex string corresponding to the server's internal version number
+
+    Note that the connection is still alive after an OKAY, which allows the
+    client to make other requests. But in certain cases, an OKAY will even
+    change the state of the connection. 
+
+    For example, the case of the 'host:transport:<serialnumber>' request,
+    where '<serialnumber>' is used to identify a given device/emulator; after
+    the "OKAY" answer, all further requests made by the client will go
+    directly to the corresponding adbd daemon.
+
+    The file SERVICES.TXT lists all services currently implemented by ADB.
+
+
+  2. Transports:
+
+    An ADB transport models a connection between the ADB server and one device
+    or emulator. There are currently two kinds of transports:
+
+       - USB transports, for physical devices through USB
+
+       - Local transports, for emulators running on the host, connected to
+         the server through TCP
+
+    In theory, it should be possible to write a local transport that proxies
+    a connection between an ADB server and a device/emulator connected to/
+    running on another machine. This hasn't been done yet though.
+
+    Each transport can carry one or more multiplexed streams between clients
+    and the device/emulator they point to. The ADB server must handle
+    unexpected transport disconnections (e.g. when a device is physically
+    unplugged) properly.
diff --git a/adb/SERVICES.TXT b/adb/SERVICES.TXT
new file mode 100644
index 0000000..d059e18
--- /dev/null
+++ b/adb/SERVICES.TXT
@@ -0,0 +1,245 @@
+This file tries to document all requests a client can make
+to the ADB server of an adbd daemon. See the OVERVIEW.TXT document
+to understand what's going on here.
+
+HOST SERVICES:
+
+host:version
+    Ask the ADB server for its internal version number.
+
+    As a special exception, the server will respond with a 4-byte
+    hex string corresponding to its internal version number, without
+    any OKAY or FAIL.
+
+host:kill
+    Ask the ADB server to quit immediately. This is used when the
+    ADB client detects that an obsolete server is running after an
+    upgrade.
+
+host:devices
+    Ask to return the list of available Android devices and their
+    state. After the OKAY, this is followed by a 4-byte hex len,
+    and a string that will be dumped as-is by the client, then
+    the connection is closed
+
+host:track-devices
+    This is a variant of host:devices which doesn't close the
+    connection. Instead, a new device list description is sent
+    each time a device is added/removed or the state of a given
+    device changes (hex4 + content). This allows tools like DDMS
+    to track the state of connected devices in real-time without
+    polling the server repeatedly.
+
+host:emulator:<port>
+    This is a special query that is sent to the ADB server when a
+    new emulator starts up. <port> is a decimal number corresponding
+    to the emulator's ADB control port, i.e. the TCP port that the
+    emulator will forward automatically to the adbd daemon running
+    in the emulator system.
+
+    This mechanism allows the ADB server to know when new emulator
+    instances start.
+
+host:transport:<serial-number>
+    Ask to switch the connection to the device/emulator identified by
+    <serial-number>. After the OKAY response, every client request will
+    be sent directly to the adbd daemon running on the device.
+    (Used to implement the -s option)
+
+host:transport-usb
+    Ask to switch the connection to one device connected through USB
+    to the host machine. This will fail if there are more than one such
+    devices. (Used to implement the -d convenience option)
+
+host:transport-local
+    Ask to switch the connection to one emulator connected through TCP.
+    This will fail if there is more than one such emulator instance
+    running. (Used to implement the -e convenience option)
+
+host:transport-any
+    Another host:transport variant. Ask to switch the connection to
+    either the device or emulator connect to/running on the host.
+    Will fail if there is more than one such device/emulator available.
+    (Used when neither -s, -d or -e are provided)
+
+host-serial:<serial-number>:<request>
+    This is a special form of query, where the 'host-serial:<serial-number>:'
+    prefix can be used to indicate that the client is asking the ADB server
+    for information related to a specific device. <request> can be in one
+    of the format described below.
+
+host-usb:<request>
+    A variant of host-serial used to target the single USB device connected
+    to the host. This will fail if there is none or more than one.
+
+host-local:<request>
+    A variant of host-serial used to target the single emulator instance
+    running on the host. This will fail if therre is none or more than one.
+
+host:<request>
+    When asking for information related to a device, 'host:' can also be
+    interpreted as 'any single device or emulator connected to/running on
+    the host'.
+
+<host-prefix>:get-product
+    XXX
+
+<host-prefix>:get-serialno
+    Returns the serial number of the corresponding device/emulator.
+    Note that emulator serial numbers are of the form "emulator-5554"
+
+<host-prefix>:get-state
+    Returns the state of a given device as a string.
+
+<host-prefix>:forward:<local>:<remote>
+    Asks the ADB server to forward local connections from <local>
+    to the <remote> address on a given device.
+
+    There, <host-prefix> can be one of the
+    host-serial/host-usb/host-local/host prefixes as described previously
+    and indicates which device/emulator to target.
+
+    the format of <local> is one of:
+
+        tcp:<port>      -> TCP connection on localhost:<port>
+        local:<path>    -> Unix local domain socket on <path>
+
+    the format of <remote> is one of:
+
+        tcp:<port>      -> TCP localhost:<port> on device
+        local:<path>    -> Unix local domain socket on device
+        jdwp:<pid>      -> JDWP thread on VM process <pid>
+
+    or even any one of the local services described below.
+
+
+
+LOCAL SERVICES:
+
+All the queries below assumed that you already switched the transport
+to a real device, or that you have used a query prefix as described
+above.
+
+shell:command arg1 arg2 ...
+    Run 'command arg1 arg2 ...' in a shell on the device, and return
+    its output and error streams. Note that arguments must be separated
+    by spaces. If an argument contains a space, it must be quoted with
+    double-quotes. Arguments cannot contain double quotes or things
+    will go very wrong.
+
+    Note that this is the non-interactive version of "adb shell"
+
+shell:
+    Start an interactive shell session on the device. Redirect
+    stdin/stdout/stderr as appropriate. Note that the ADB server uses
+    this to implement "adb shell", but will also cook the input before
+    sending it to the device (see interactive_shell() in commandline.c)
+
+bootdebug:
+    Ask debugging information to the bootloader. The adbd daemon will
+    respond with FAIL to this request.
+
+bootloader:<command>
+    Send a request to the bootloader. This can also work if the device
+    is currently in the bootloader state. The adbd daemon will respond
+    with FAIL to such requests.
+
+remount:
+    Ask adbd to remount the device's filesystem in read-write mode,
+    instead of read-only. This is usually necessary before performing
+    an "adb sync" or "adb push" request.
+
+    This request may not succeed on certain builds which do not allow
+    that.
+
+dev:<path>
+    Opens a device file and connects the client directly to it for
+    read/write purposes. Useful for debugging, but may require special
+    priviledges and thus may not run on all devices. <path> is a full
+    path from the root of the filesystem.
+
+tcp:<port>
+    Tries to connect to tcp port <port> on localhost.
+
+tcp:<port>:<server-name>
+    Tries to connect to tcp port <port> on machine <server-name> from
+    the device. This can be useful to debug some networking/proxy
+    issues that can only be revealed on the device itself.
+
+local:<path>
+    Tries to connect to a Unix domain socket <path> on the device
+
+localreserved:<path>
+localabstract:<path>
+localfilesystem:<path>
+    Variants of local:<path> that are used to access other Android
+    socket namespaces.
+
+log:<name>
+    Opens one of the system logs (/dev/log/<name>) and allows the client
+    to read them directly. Used to implement 'adb logcat'. The stream
+    will be read-only for the client.
+
+framebuffer:
+    This service is used to send snapshots of the framebuffer to a client.
+    It requires sufficient priviledges but works as follow:
+
+      After the OKAY, the service sends 16-byte binary structure
+      containing the following fields (little-endian format):
+
+            depth:   uint32_t:    framebuffer depth
+            size:    uint32_t:    framebuffer size in bytes
+            width:   uint32_t:    framebuffer width in pixels
+            height:  uint32_t:    framebuffer height in pixels
+
+      With the current implementation, depth is always 16, and
+      size is always width*height*2
+
+      Then, each time the client wants a snapshot, it should send
+      one byte through the channel, which will trigger the service
+      to send it 'size' bytes of framebuffer data.
+
+      If the adbd daemon doesn't have sufficient priviledges to open
+      the framebuffer device, the connection is simply closed immediately.
+
+dns:<server-name>
+    This service is an exception because it only runs within the ADB server.
+    It is used to implement USB networking, i.e. to provide a network connection
+    to the device through the host machine (note: this is the exact opposite of
+    network thetering).
+
+    It is used to perform a gethostbyname(<address>) on the host and return
+    the corresponding IP address as a 4-byte string.
+
+recover:<size>
+    This service is used to upload a recovery image to the device. <size>
+    must be a number corresponding to the size of the file. The service works
+    by:
+
+       - creating a file named /tmp/update
+       - reading 'size' bytes from the client and writing them to /tmp/update
+       - when everything is read succesfully, create a file named /tmp/update.start
+
+    This service can only work when the device is in recovery mode. Otherwise,
+    the /tmp directory doesn't exist and the connection will be closed immediately.
+
+jdwp:<pid>
+    Connects to the JDWP thread running in the VM of process <pid>.
+
+track-jdwp
+    This is used to send the list of JDWP pids periodically to the client.
+    The format of the returned data is the following:
+
+        <hex4>:    the length of all content as a 4-char hexadecimal string
+        <content>: a series of ASCII lines of the following format:
+                        <pid> "\n"
+
+    This service is used by DDMS to know which debuggable processes are running
+    on the device/emulator.
+
+    Note that there is no single-shot service to retrieve the list only once.
+
+sync:
+    This starts the file synchronisation service, used to implement "adb push"
+    and "adb pull". Since this service is pretty complex, it will be detailed
+    in a companion document named SYNC.TXT
diff --git a/adb/adb.c b/adb/adb.c
index a50ef33..27d0c81 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -67,59 +67,59 @@
  */
 void  adb_trace_init(void)
 {
-	const char*  p = getenv("ADB_TRACE");
-	const char*  q;
+    const char*  p = getenv("ADB_TRACE");
+    const char*  q;
 
-	static const struct {
-		const char*  tag;
-		int           flag;
-	} tags[] = {
-	    { "1", 0 },
-		{ "all", 0 },
-		{ "adb", TRACE_ADB },
-		{ "sockets", TRACE_SOCKETS },
-		{ "packets", TRACE_PACKETS },
-		{ "rwx", TRACE_RWX },
-		{ "usb", TRACE_USB },
-		{ "sync", TRACE_SYNC },
-		{ "sysdeps", TRACE_SYSDEPS },
+    static const struct {
+        const char*  tag;
+        int           flag;
+    } tags[] = {
+        { "1", 0 },
+        { "all", 0 },
+        { "adb", TRACE_ADB },
+        { "sockets", TRACE_SOCKETS },
+        { "packets", TRACE_PACKETS },
+        { "rwx", TRACE_RWX },
+        { "usb", TRACE_USB },
+        { "sync", TRACE_SYNC },
+        { "sysdeps", TRACE_SYSDEPS },
         { "transport", TRACE_TRANSPORT },
         { "jdwp", TRACE_JDWP },
-		{ NULL, 0 }
-	};
+        { NULL, 0 }
+    };
 
-	if (p == NULL)
-		return;
+    if (p == NULL)
+            return;
 
-	/* use a comma/column/semi-colum/space separated list */
-	while (*p) {
-		int  len, tagn;
+    /* use a comma/column/semi-colum/space separated list */
+    while (*p) {
+        int  len, tagn;
 
-		q = strpbrk(p, " ,:;");
-		if (q == NULL) {
-			q = p + strlen(p);
-		}
-		len = q - p;
+        q = strpbrk(p, " ,:;");
+        if (q == NULL) {
+            q = p + strlen(p);
+        }
+        len = q - p;
 
-		for (tagn = 0; tags[tagn].tag != NULL; tagn++)
-		{
-			int  taglen = strlen(tags[tagn].tag);
+        for (tagn = 0; tags[tagn].tag != NULL; tagn++)
+        {
+            int  taglen = strlen(tags[tagn].tag);
 
-			if (len == taglen && !memcmp(tags[tagn].tag, p, len) )
-			{
-				int  flag = tags[tagn].flag;
-				if (flag == 0) {
-					adb_trace_mask = ~0;
-					return;
-				}
-				adb_trace_mask |= (1 << flag);
-				break;
-			}
-		}
-		p = q;
-		if (*p)
-			p++;
-	}
+            if (len == taglen && !memcmp(tags[tagn].tag, p, len) )
+            {
+                int  flag = tags[tagn].flag;
+                if (flag == 0) {
+                    adb_trace_mask = ~0;
+                    return;
+                }
+                adb_trace_mask |= (1 << flag);
+                break;
+            }
+        }
+        p = q;
+        if (*p)
+            p++;
+    }
 }
 
 
@@ -783,8 +783,8 @@
 
         // child process
         int result = execl(path, "adb", "fork-server", "server", NULL);
-	    // this should not return
-	    fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno);
+        // this should not return
+        fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno);
     } else  {
         // parent side of the fork
 
@@ -894,7 +894,7 @@
     if(access("/dev/android_adb", F_OK) == 0 ||
        access("/dev/android", F_OK) == 0) {
         usb_init();
-	} else {
+    } else {
         local_init();
     }
     init_jdwp();
diff --git a/adb/adb.h b/adb/adb.h
index 5a74b7b..a17c8dd 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -79,6 +79,11 @@
         */
     unsigned id;
 
+        /* flag: set when the socket's peer has closed
+        ** but packets are still queued for delivery
+        */
+    int    closing;
+
         /* the asocket we are connected to
         */
 
@@ -309,15 +314,15 @@
  * the adb_trace_init() function implemented in adb.c
  */
 typedef enum {
-	TRACE_ADB = 0,
-	TRACE_SOCKETS,
-	TRACE_PACKETS,
-	TRACE_TRANSPORT,
-	TRACE_RWX,
-	TRACE_USB,
-	TRACE_SYNC,
-	TRACE_SYSDEPS,
-        TRACE_JDWP,
+    TRACE_ADB = 0,
+    TRACE_SOCKETS,
+    TRACE_PACKETS,
+    TRACE_TRANSPORT,
+    TRACE_RWX,
+    TRACE_USB,
+    TRACE_SYNC,
+    TRACE_SYSDEPS,
+    TRACE_JDWP,
 } AdbTrace;
 
 #if ADB_TRACE
diff --git a/adb/adb_client.c b/adb/adb_client.c
index c1b87ee..5868744 100644
--- a/adb/adb_client.c
+++ b/adb/adb_client.c
@@ -211,7 +211,7 @@
             return -1;
         } else {
             fprintf(stdout,"* daemon started successfully *\n");
-		}
+        }
         /* give the server some time to start properly and detect devices */
         adb_sleep_ms(2000);
         // fall through to _adb_connect
@@ -223,13 +223,13 @@
 
         // if we have a file descriptor, then parse version result
         if(fd >= 0) {
-	        if(readx(fd, buf, 4)) goto error;
+            if(readx(fd, buf, 4)) goto error;
 
-		    buf[4] = 0;
-		    n = strtoul(buf, 0, 16);
-		    if(n > (int)sizeof(buf)) goto error;
-		    if(readx(fd, buf, n)) goto error;
-		    adb_close(fd);
+            buf[4] = 0;
+            n = strtoul(buf, 0, 16);
+            if(n > (int)sizeof(buf)) goto error;
+            if(readx(fd, buf, n)) goto error;
+            adb_close(fd);
 
             if (sscanf(buf, "%04x", &version) != 1) goto error;
         } else {
@@ -240,14 +240,14 @@
         }
 
         if(version != ADB_SERVER_VERSION) {
-	        printf("adb server is out of date.  killing...\n");
-	        fd = _adb_connect("host:kill");
-	        adb_close(fd);
+            printf("adb server is out of date.  killing...\n");
+            fd = _adb_connect("host:kill");
+            adb_close(fd);
 
-                /* XXX can we better detect its death? */
-	        adb_sleep_ms(2000);
+            /* XXX can we better detect its death? */
+            adb_sleep_ms(2000);
             goto start_server;
-	    }
+        }
     }
 
     // if the command is start-server, we are done.
diff --git a/adb/commandline.c b/adb/commandline.c
index c1ef8b0..cbf079c 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -296,8 +296,8 @@
                             buf_ptr[cmdlen] = '\0';
                             if( (item = shListFindItem( &history, (void *)buf_ptr, shItemCmp )) == NULL ) {
                                 shListInsFirstItem( &history, (void *)buf_ptr );
-				item = &history;
-			    }
+                                item = &history;
+                            }
                         }
                     }
                     cmdlen = 0;
@@ -322,8 +322,8 @@
                 default:
 #ifdef SH_HISTORY
                     if( buf[n] == SH_DEL_CHAR ) {
-			if( cmdlen > 0 )
-                    	    cmdlen--;
+                        if( cmdlen > 0 )
+                            cmdlen--;
                     }
                     else {
                         realbuf[cmdlen] = buf[n];
@@ -478,7 +478,7 @@
 #ifdef _WIN32
     /* XXX: TODO */
 #else
-	int  fd;
+    int  fd;
     fd = unix_open("/dev/null", O_WRONLY);
     dup2(fd, 2);
     adb_close(fd);
@@ -512,7 +512,7 @@
     }
 }
 
-/** duplicate string and quote all \ " ( ) chars */
+/** duplicate string and quote all \ " ( ) chars + space character. */
 static char *
 dupAndQuote(const char *s)
 {
@@ -527,7 +527,7 @@
 
     for( ;*ts != '\0'; ts++) {
         alloc_len++;
-        if (*ts == '"' || *ts == '\\') {
+        if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
             alloc_len++;
         }
     }
@@ -538,7 +538,7 @@
     dest = ret;
 
     for ( ;*ts != '\0'; ts++) {
-        if (*ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
+        if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
             *dest++ = '\\';
         }
 
@@ -561,7 +561,7 @@
 {
 #ifdef HAVE_WIN32_PROC
     fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
-	return -1;
+    return -1;
 #else
     char *adb_service_name;
     pid_t pid;
@@ -657,8 +657,8 @@
     quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
 
     snprintf(buf, sizeof(buf),
-            "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
-	    quoted_log_tags);
+        "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
+        quoted_log_tags);
 
     free(quoted_log_tags);
 
@@ -847,7 +847,7 @@
     if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
         gProductOutPath = NULL;
     }
-    // TODO: also try TARGET_PRODUCT as a hint
+    // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
 
         /* modifiers and flags */
     while(argc > 0) {
@@ -1077,15 +1077,15 @@
             return 1;
         }
 
-		/* Allow a command to be run after wait-for-device,
-		 * e.g. 'adb wait-for-device shell'.
-		 */
-		if(argc > 1) {
-			argc--;
-			argv++;
-			goto top;
-		}
-		return 0;
+        /* Allow a command to be run after wait-for-device,
+            * e.g. 'adb wait-for-device shell'.
+            */
+        if(argc > 1) {
+            argc--;
+            argv++;
+            goto top;
+        }
+        return 0;
     }
 
     if(!strcmp(argv[0], "forward")) {
@@ -1299,7 +1299,7 @@
     while(argc-- > 0) {
         char *quoted;
 
-        quoted = dupAndQuote (*argv++);
+        quoted = dupAndQuote(*argv++);
 
         strncat(buf, " ", sizeof(buf)-1);
         strncat(buf, quoted, sizeof(buf)-1);
@@ -1312,6 +1312,18 @@
 
 int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
 {
+    /* if the user choose the -k option, we refuse to do it until devices are
+       out with the option to uninstall the remaining data somehow (adb/ui) */
+    if (argc == 3 && strcmp(argv[1], "-k") == 0)
+    {
+        printf(
+            "The -k option uninstalls the application while retaining the data/cache.\n"
+            "At the moment, there is no way to remove the remaining data.\n"
+            "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
+            "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
+        return -1;
+    }
+
     /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
     return pm_command(transport, serial, argc, argv);
 }
diff --git a/adb/file_sync_client.c b/adb/file_sync_client.c
index f9e80ed..4e6d385 100644
--- a/adb/file_sync_client.c
+++ b/adb/file_sync_client.c
@@ -55,7 +55,7 @@
     if(total_bytes == 0) return;
 
     if (t == 0)  /* prevent division by 0 :-) */
-		t = 1000000;
+        t = 1000000;
 
     fprintf(stderr,"%lld KB/s (%d bytes in %lld.%03llds)\n",
             ((((long long) total_bytes) * 1000000LL) / t) / 1024LL,
@@ -227,14 +227,14 @@
 
         if(ret < 0) {
             if(errno == EINTR)
-	        continue;
+                continue;
             fprintf(stderr,"cannot read '%s': %s\n", path, strerror(errno));
             break;
         }
 
         sbuf->size = htoll(ret);
         if(writex(fd, sbuf, sizeof(unsigned) * 2 + ret)){
-	        err = -1;
+            err = -1;
             break;
         }
         total_bytes += ret;
@@ -259,7 +259,7 @@
         memcpy(sbuf->data, &file_buffer[total], count);
         sbuf->size = htoll(count);
         if(writex(fd, sbuf, sizeof(unsigned) * 2 + count)){
-	        err = -1;
+            err = -1;
             break;
         }
         total += count;
@@ -277,7 +277,7 @@
     len = readlink(path, sbuf->data, SYNC_DATA_MAX-1);
     if(len < 0) {
         fprintf(stderr, "error reading link '%s': %s\n", path, strerror(errno));
-	return -1;
+        return -1;
     }
     sbuf->data[len] = '\0';
 
@@ -377,10 +377,10 @@
     }
 
     if (file_buffer) {
-	    write_data_buffer(fd, file_buffer, size, sbuf);
-	    free(file_buffer);
+        write_data_buffer(fd, file_buffer, size, sbuf);
+        free(file_buffer);
     } else if (S_ISREG(mode))
-    	write_data_file(fd, lpath, sbuf);
+        write_data_file(fd, lpath, sbuf);
 #ifdef HAVE_SYMLINKS
     else if (S_ISLNK(mode))
         write_data_link(fd, lpath, sbuf);
@@ -641,7 +641,7 @@
         } else {
             ci = mkcopyinfo(lpath, rpath, name, 0);
             if(lstat(ci->src, &st)) {
-            	closedir(d);
+                closedir(d);
                 fprintf(stderr,"cannot stat '%s': %s\n", ci->src, strerror(errno));
                 return -1;
             }
@@ -651,7 +651,7 @@
             } else {
                 ci->time = st.st_mtime;
                 ci->mode = st.st_mode;
-		ci->size = st.st_size;
+                ci->size = st.st_size;
                 ci->next = *filelist;
                 *filelist = ci;
             }
@@ -707,12 +707,12 @@
             unsigned int timestamp, mode, size;
             if(sync_finish_readtime(fd, &timestamp, &mode, &size))
                 return 1;
-	    if(size == ci->size) {
+            if(size == ci->size) {
                 /* for links, we cannot update the atime/mtime */
                 if((S_ISREG(ci->mode & mode) && timestamp == ci->time) ||
-		   (S_ISLNK(ci->mode & mode) && timestamp >= ci->time))
+                    (S_ISLNK(ci->mode & mode) && timestamp >= ci->time))
                     ci->flag = 1;
-	    }
+            }
         }
     }
     for(ci = filelist; ci != 0; ci = next) {
diff --git a/adb/file_sync_service.c b/adb/file_sync_service.c
index 21f8af7..a231e93 100644
--- a/adb/file_sync_service.c
+++ b/adb/file_sync_service.c
@@ -164,12 +164,12 @@
     }
     if(fd < 0) {
         if(fail_errno(s))
-	    return -1;
+            return -1;
         fd = -1;
     }
 
     for(;;) {
-	unsigned int len;
+        unsigned int len;
 
         if(readx(s, &msg.data, sizeof(msg.data)))
             goto fail;
@@ -264,7 +264,7 @@
             return -1;
     } else {
         fail_message(s, "invalid data message: expected ID_DONE");
-	return -1;
+        return -1;
     }
 
     return 0;
diff --git a/adb/framebuffer_service.c b/adb/framebuffer_service.c
index 1d2c4b5..0de0dd5 100644
--- a/adb/framebuffer_service.c
+++ b/adb/framebuffer_service.c
@@ -24,6 +24,7 @@
 #include "adb.h"
 
 #include <linux/fb.h>
+#include <sys/ioctl.h>
 #include <sys/mman.h>
 
 /* TODO:
@@ -37,9 +38,9 @@
     int fb;
     void *ptr = MAP_FAILED;
     char x;
-    
+
     unsigned fbinfo[4];
-    
+
     fb = open("/dev/graphics/fb0", O_RDONLY);
     if(fb < 0) goto done;
 
@@ -53,14 +54,14 @@
 
     ptr = mmap(0, fbinfo[1], PROT_READ, MAP_SHARED, fb, 0);
     if(ptr == MAP_FAILED) goto done;
-    
+
     if(writex(fd, fbinfo, sizeof(unsigned) * 4)) goto done;
 
     for(;;) {
         if(readx(fd, &x, 1)) goto done;
         if(writex(fd, ptr, fbinfo[1])) goto done;
     }
-    
+
 done:
     if(ptr != MAP_FAILED) munmap(ptr, fbinfo[1]);
     if(fb >= 0) close(fb);
diff --git a/adb/get_my_path_windows.c b/adb/get_my_path_windows.c
index 64a597d..fc7143c 100644
--- a/adb/get_my_path_windows.c
+++ b/adb/get_my_path_windows.c
@@ -20,12 +20,12 @@
 
 void get_my_path(char exe[PATH_MAX])
 {
-	char*  r;
+    char*  r;
 
-	GetModuleFileName( NULL, exe, PATH_MAX-1 );
-	exe[PATH_MAX-1] = 0;
-	r = strrchr( exe, '\\' );
-	if (r)
-		*r = 0;
+    GetModuleFileName( NULL, exe, PATH_MAX-1 );
+    exe[PATH_MAX-1] = 0;
+    r = strrchr( exe, '\\' );
+    if (r)
+        *r = 0;
 }
 
diff --git a/adb/jdwp_service.c b/adb/jdwp_service.c
index 43dc69e..ae7f12d 100644
--- a/adb/jdwp_service.c
+++ b/adb/jdwp_service.c
@@ -287,7 +287,7 @@
                 if (len <= 0) {
                     if (len < 0 && errno == EINTR)
                         continue;
-		    if (len < 0 && errno == EAGAIN)
+                    if (len < 0 && errno == EAGAIN)
                         return;
                     else {
                         D("terminating JDWP %d connection: %s\n", proc->pid,
@@ -295,7 +295,7 @@
                         break;
                     }
                 }
-		else {
+                else {
                     D( "ignoring unexpected JDWP %d control socket activity (%d bytes)\n",
                        proc->pid, len );
                 }
diff --git a/adb/sockets.c b/adb/sockets.c
index b9c9ae1..9f1b598 100644
--- a/adb/sockets.c
+++ b/adb/sockets.c
@@ -50,6 +50,15 @@
     .prev = &local_socket_list,
 };
 
+/* the the list of currently closing local sockets.
+** these have no peer anymore, but still packets to
+** write to their fd.
+*/
+static asocket local_socket_closing_list = {
+    .next = &local_socket_closing_list,
+    .prev = &local_socket_closing_list,
+};
+
 asocket *find_local_socket(unsigned id)
 {
     asocket *s;
@@ -64,16 +73,22 @@
     return result;
 }
 
+static void
+insert_local_socket(asocket*  s, asocket*  list)
+{
+    s->next       = list;
+    s->prev       = s->next->prev;
+    s->prev->next = s;
+    s->next->prev = s;
+}
+
+
 void install_local_socket(asocket *s)
 {
     adb_mutex_lock(&socket_list_lock);
 
     s->id = local_socket_next_id++;
-
-    s->next = &local_socket_list;
-    s->prev = local_socket_list.prev;
-    s->prev->next = s;
-    s->next->prev = s;
+    insert_local_socket(s, &local_socket_list);
 
     adb_mutex_unlock(&socket_list_lock);
 }
@@ -177,19 +192,11 @@
     adb_mutex_unlock(&socket_list_lock);
 }
 
-static void local_socket_close_locked(asocket *s)
+// be sure to hold the socket list lock when calling this
+static void local_socket_destroy(asocket  *s)
 {
     apacket *p, *n;
 
-    if(s->peer) {
-        s->peer->peer = 0;
-        // tweak to avoid deadlock
-        if (s->peer->close == local_socket_close)
-            local_socket_close_locked(s->peer);
-        else
-            s->peer->close(s->peer);
-    }
-
         /* IMPORTANT: the remove closes the fd
         ** that belongs to this socket
         */
@@ -201,16 +208,94 @@
         n = p->next;
         put_apacket(p);
     }
-
-    D("LS(%d): closed\n", s->id);
     remove_socket(s);
     free(s);
 }
 
+
+static void local_socket_close_locked(asocket *s)
+{
+    if(s->peer) {
+        s->peer->peer = 0;
+        // tweak to avoid deadlock
+        if (s->peer->close == local_socket_close)
+            local_socket_close_locked(s->peer);
+        else
+            s->peer->close(s->peer);
+    }
+
+        /* If we are already closing, or if there are no
+        ** pending packets, destroy immediately
+        */
+    if (s->closing || s->pkt_first == NULL) {
+        int   id = s->id;
+        local_socket_destroy(s);
+        D("LS(%d): closed\n", id);
+        return;
+    }
+
+        /* otherwise, put on the closing list
+        */
+    D("LS(%d): closing\n", s->id);
+    s->closing = 1;
+    fdevent_del(&s->fde, FDE_READ);
+    remove_socket(s);
+    insert_local_socket(s, &local_socket_closing_list);
+}
+
 static void local_socket_event_func(int fd, unsigned ev, void *_s)
 {
     asocket *s = _s;
 
+    /* put the FDE_WRITE processing before the FDE_READ
+    ** in order to simplify the code.
+    */
+    if(ev & FDE_WRITE){
+        apacket *p;
+
+        while((p = s->pkt_first) != 0) {
+            while(p->len > 0) {
+                int r = adb_write(fd, p->ptr, p->len);
+                if(r > 0) {
+                    p->ptr += r;
+                    p->len -= r;
+                    continue;
+                }
+                if(r < 0) {
+                    /* returning here is ok because FDE_READ will
+                    ** be processed in the next iteration loop
+                    */
+                    if(errno == EAGAIN) return;
+                    if(errno == EINTR) continue;
+                }
+                s->close(s);
+                return;
+            }
+
+            if(p->len == 0) {
+                s->pkt_first = p->next;
+                if(s->pkt_first == 0) s->pkt_last = 0;
+                put_apacket(p);
+            }
+        }
+
+            /* if we sent the last packet of a closing socket,
+            ** we can now destroy it.
+            */
+        if (s->closing) {
+            s->close(s);
+            return;
+        }
+
+            /* no more packets queued, so we can ignore
+            ** writable events again and tell our peer
+            ** to resume writing
+            */
+        fdevent_del(&s->fde, FDE_WRITE);
+        s->peer->ready(s->peer);
+    }
+
+
     if(ev & FDE_READ){
         apacket *p = get_apacket();
         unsigned char *x = p->data;
@@ -244,7 +329,12 @@
 
             if(r < 0) {
                     /* error return means they closed us as a side-effect
-                    ** and we must retutn immediately
+                    ** and we must return immediately.
+                    **
+                    ** note that if we still have buffered packets, the
+                    ** socket will be placed on the closing socket list.
+                    ** this handler function will be called again
+                    ** to process FDE_WRITE events.
                     */
                 return;
             }
@@ -261,42 +351,6 @@
         if(is_eof) {
             s->close(s);
         }
-        return;
-    }
-
-    if(ev & FDE_WRITE){
-        apacket *p;
-
-        while((p = s->pkt_first) != 0) {
-            while(p->len > 0) {
-                int r = adb_write(fd, p->ptr, p->len);
-                if(r > 0) {
-                    p->ptr += r;
-                    p->len -= r;
-                    continue;
-                }
-                if(r < 0) {
-                    if(errno == EAGAIN) return;
-                    if(errno == EINTR) continue;
-                }
-                s->close(s);
-                return;
-            }
-
-            if(p->len == 0) {
-                s->pkt_first = p->next;
-                if(s->pkt_first == 0) s->pkt_last = 0;
-                put_apacket(p);
-            }
-        }
-
-            /* no more packets queued, so we can ignore
-            ** writable events again and tell our peer
-            ** to resume writing
-            */
-        fdevent_del(&s->fde, FDE_WRITE);
-        s->peer->ready(s->peer);
-        return;
     }
 
     if(ev & FDE_ERROR){
diff --git a/adb/sysdeps_win32.c b/adb/sysdeps_win32.c
index 9d6a596..c2a9a98 100644
--- a/adb/sysdeps_win32.c
+++ b/adb/sysdeps_win32.c
@@ -940,12 +940,12 @@
         /* we can append to region A */
         if (avail > len)
             avail = len;
-         
+
         memcpy( bip->buff + bip->a_end, src, avail );
         src   += avail;
         count += avail;
         len   -= avail;
-     
+
         bip->a_end += avail;
         if (bip->a_end == BIP_BUFFER_SIZE && bip->a_start == 0) {
             bip->can_write = 0;
@@ -953,25 +953,25 @@
             goto Exit;
         }
     }
-    
+
     if (len == 0)
         goto Exit;
 
     avail = bip->a_start - bip->b_end;
     assert( avail > 0 );  /* since can_write is TRUE */
-    
+
     if (avail > len)
         avail = len;
-        
+
     memcpy( bip->buff + bip->b_end, src, avail );
     count += avail;
     bip->b_end += avail;
-    
+
     if (bip->b_end == bip->a_start) {
         bip->can_write = 0;
         ResetEvent( bip->evt_write );
     }
-    
+
 Exit:
     assert( count > 0 );
 
@@ -979,7 +979,7 @@
         bip->can_read = 1;
         SetEvent( bip->evt_read );
     }
-  
+
     BIPD(( "bip_buffer_write: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n", 
             bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read ));
     LeaveCriticalSection( &bip->lock );
@@ -991,12 +991,12 @@
 bip_buffer_read( BipBuffer  bip, void*  dst, int  len )
 {
     int  avail, count = 0;
-    
+
     if (len <= 0)
         return 0;
-    
+
     BIPD(( "bip_buffer_read: enter %d->%d len %d\n", bip->fdin, bip->fdout, len ));
-    
+
     EnterCriticalSection( &bip->lock );
     while ( !bip->can_read )
     {
@@ -1007,7 +1007,7 @@
 #else    
         int  ret;
         LeaveCriticalSection( &bip->lock );
-        
+
         if (bip->closed) {
             errno = EPIPE;
             return -1;
@@ -1023,30 +1023,30 @@
             return -1;
         }
         EnterCriticalSection( &bip->lock );
-#endif        
+#endif
     }
 
     BIPD(( "bip_buffer_read: exec %d->%d len %d\n", bip->fdin, bip->fdout, len ));
-   
+
     avail = bip->a_end - bip->a_start;
     assert( avail > 0 );  /* since can_read is TRUE */
-    
+
     if (avail > len)
         avail = len;
-    
+
     memcpy( dst, bip->buff + bip->a_start, avail );
     dst   += avail;
     count += avail;
     len   -= avail;
-    
+
     bip->a_start += avail;
     if (bip->a_start < bip->a_end)
         goto Exit;
-    
+
     bip->a_start = 0;
     bip->a_end   = bip->b_end;
     bip->b_end   = 0;
-    
+
     avail = bip->a_end;
     if (avail > 0) {
         if (avail > len)
@@ -1054,13 +1054,13 @@
         memcpy( dst, bip->buff, avail );
         count += avail;
         bip->a_start += avail;
-        
+
         if ( bip->a_start < bip->a_end )
             goto Exit;
-            
+
         bip->a_start = bip->a_end = 0;
     }
-    
+
     bip->can_read = 0;
     ResetEvent( bip->evt_read );
 
@@ -1071,22 +1071,22 @@
         bip->can_write = 1;
         SetEvent( bip->evt_write );
     }
-    
+
     BIPDUMP( (const unsigned char*)dst - count, count );
     BIPD(( "bip_buffer_read: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n", 
             bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read ));
     LeaveCriticalSection( &bip->lock );
-    
+
     return count;
 }
- 
+
 typedef struct SocketPairRec_ 
 {
     BipBufferRec  a2b_bip;
     BipBufferRec  b2a_bip;
     FH            a_fd;
     int           used;
-    
+
 } SocketPairRec;
 
 void _fh_socketpair_init( FH  f )
@@ -1103,7 +1103,7 @@
         if ( f == pair->a_fd ) {
             pair->a_fd = NULL;
         }
-        
+
         bip_buffer_close( &pair->b2a_bip );
         bip_buffer_close( &pair->a2b_bip );
 
@@ -1199,7 +1199,7 @@
 
     sv[0] = _fh_to_int(fa);
     sv[1] = _fh_to_int(fb);
-    
+
     pair->a2b_bip.fdin  = sv[0];
     pair->a2b_bip.fdout = sv[1];
     pair->b2a_bip.fdin  = sv[1];
@@ -1303,7 +1303,7 @@
     hook->stop    = NULL;
     hook->check   = NULL;
     hook->peek    = NULL;
-    
+
     return hook;
 }
 
@@ -1324,7 +1324,7 @@
     FH        f   = hook->fh;
     int       fd  = _fh_to_int(f);
     fdevent*  fde = fd_table[ fd - WIN32_FH_BASE ];
-    
+
     if (fde != NULL && fde->fd == fd) {
         if ((fde->state & FDE_PENDING) == 0) {
             fde->state |= FDE_PENDING;
@@ -1365,7 +1365,7 @@
     FH          f = _fh_from_int(fd);
     EventHook  *pnode;
     EventHook   node;
-    
+
     if (f == NULL)  /* invalid arg */ {
         D("event_looper_hook: invalid fd=%d\n", fd);
         return;
@@ -1397,7 +1397,7 @@
     FH          fh    = _fh_from_int(fd);
     EventHook  *pnode = event_looper_find_p( looper, fh );
     EventHook   node  = *pnode;
-    
+
     if (node != NULL) {
         int  events2 = events & node->wanted;
         if ( events2 == 0 ) {
@@ -1424,7 +1424,7 @@
 {
     EventLooper  looper = &win32_looper;
     int          events = fde->state & FDE_EVENTMASK;
-    
+
     if (events != 0)
         event_looper_hook( looper, fde->fd, events );
 }
@@ -1433,7 +1433,7 @@
 {
     EventLooper  looper = &win32_looper;
     int          events = fde->state & FDE_EVENTMASK;
-    
+
     if (events != 0)
         event_looper_unhook( looper, fde->fd, events );
 }
@@ -1462,7 +1462,7 @@
     EventLooper  looper = &win32_looper;
     EventHook    hook;
     int          gotone = 0;
-    
+
     /* if we have at least one ready hook, execute it/them */
     for (hook = looper->hooks; hook; hook = hook->next) {
         hook->ready = 0;
@@ -1479,7 +1479,7 @@
     if (!gotone)
     {
         looper->htab_count = 0;
-            
+
         for (hook = looper->hooks; hook; hook = hook->next) 
         {
             if (hook->start && !hook->start(hook)) {
@@ -1519,7 +1519,7 @@
                 D( "adb_win32: wait failed, error %ld\n", GetLastError() );
             } else {
                 D( "adb_win32: got one (index %d)\n", wait_ret );
-            
+
                 /* according to Cygwin, some objects like consoles wake up on "inappropriate" events
                  * like mouse movements. we need to filter these with the "check" function
                  */
@@ -1561,7 +1561,7 @@
     if(fd < 0) {
         FATAL("bogus negative fd (%d)\n", fde->fd);
     }
-    
+
     if(fd >= fd_table_max) {
         int oldmax = fd_table_max;
         if(fde->fd > 32000) {
@@ -1587,7 +1587,7 @@
 static void fdevent_unregister(fdevent *fde)
 {
     int  fd = fde->fd - WIN32_FH_BASE;
-    
+
     if((fd < 0) || (fd >= fd_table_max)) {
         FATAL("fd out of range (%d)\n", fde->fd);
     }
@@ -1626,9 +1626,9 @@
 {
     fdevent *list = &list_pending;
     fdevent *node = list->next;
-    
+
     if(node == list) return 0;
-    
+
     list->next = node->next;
     list->next->prev = list;
     node->next = 0;
@@ -1689,9 +1689,9 @@
 void fdevent_set(fdevent *fde, unsigned events)
 {
     events &= FDE_EVENTMASK;
-    
+
     if((fde->state & FDE_EVENTMASK) == (int)events) return;
-    
+
     if(fde->state & FDE_ACTIVE) {
         fdevent_update(fde, events);
         dump_fde(fde, "update");
@@ -1727,13 +1727,13 @@
 void fdevent_loop()
 {
     fdevent *fde;
-    
+
     for(;;) {
 #if DEBUG
         fprintf(stderr,"--- ---- waiting for events\n");
 #endif
         fdevent_process();
-        
+
         while((fde = fdevent_plist_dequeue())) {
             unsigned events = fde->events;
             fde->events = 0;
@@ -1793,7 +1793,7 @@
 static void  _event_socket_prepare( EventHook  hook )
 {
     WSANETWORKEVENTS  evts;
-    
+
     /* look if some of the events we want already happened ? */
     if (!WSAEnumNetworkEvents( hook->fh->fh_socket, NULL, &evts ))
         _event_socket_verify( hook, &evts );
@@ -1819,13 +1819,13 @@
     /* create an event which we're going to wait for */
     FH    fh    = hook->fh;
     long  flags = _socket_wanted_to_flags( hook->wanted );
-    
+
     hook->h = fh->event;
     if (hook->h == INVALID_HANDLE_VALUE) {
         D( "_event_socket_start: no event for %s\n", fh->name );
         return 0;
     }
-    
+
     if ( flags != fh->mask ) {
         D( "_event_socket_start: hooking %s for %x (flags %ld)\n", hook->fh->name, hook->wanted, flags );
         if ( WSAEventSelect( fh->fh_socket, hook->h, flags ) ) {
@@ -1850,7 +1850,7 @@
     int               result = 0;
     FH                fh = hook->fh;
     WSANETWORKEVENTS  evts;
-    
+
     if (!WSAEnumNetworkEvents( fh->fh_socket, hook->h, &evts ) ) {
         _event_socket_verify( hook, &evts );
         result = (hook->ready != 0);
@@ -1866,7 +1866,7 @@
 {
     WSANETWORKEVENTS  evts;
     FH                fh = hook->fh;
-    
+
     /* look if some of the events we want already happened ? */
     if (!WSAEnumNetworkEvents( fh->fh_socket, NULL, &evts )) {
         _event_socket_verify( hook, &evts );
@@ -1886,40 +1886,40 @@
     hook->stop    = _event_socket_stop;
     hook->check   = _event_socket_check;
     hook->peek    = _event_socket_peek;
-    
+
     _event_socket_start( hook );
 }
 
 /** SOCKETPAIR EVENT HOOKS
  **/
- 
+
 static void  _event_socketpair_prepare( EventHook  hook )
 {
     FH          fh   = hook->fh;
     SocketPair  pair = fh->fh_pair;
     BipBuffer   rbip = (pair->a_fd == fh) ? &pair->b2a_bip : &pair->a2b_bip;
     BipBuffer   wbip = (pair->a_fd == fh) ? &pair->a2b_bip : &pair->b2a_bip;
-   
+
     if (hook->wanted & FDE_READ && rbip->can_read)
         hook->ready |= FDE_READ;
-    
+
     if (hook->wanted & FDE_WRITE && wbip->can_write) 
         hook->ready |= FDE_WRITE;
  }
- 
+
  static int  _event_socketpair_start( EventHook  hook )
  {
     FH          fh   = hook->fh;
     SocketPair  pair = fh->fh_pair;
     BipBuffer   rbip = (pair->a_fd == fh) ? &pair->b2a_bip : &pair->a2b_bip;
     BipBuffer   wbip = (pair->a_fd == fh) ? &pair->a2b_bip : &pair->b2a_bip;
-    
+
     if (hook->wanted == FDE_READ)
         hook->h = rbip->evt_read;
-        
+
     else if (hook->wanted == FDE_WRITE)
         hook->h = wbip->evt_write;
-    
+
     else {
         D("_event_socketpair_start: can't handle FDE_READ+FDE_WRITE\n" );
         return 0;
diff --git a/adb/transport_local.c b/adb/transport_local.c
index 0e8b732..be01f29 100644
--- a/adb/transport_local.c
+++ b/adb/transport_local.c
@@ -76,7 +76,7 @@
     }
 
     if(check_data(p)) {
-	D("bad data: terminated (data)\n");
+        D("bad data: terminated (data)\n");
         return -1;
     }
 
@@ -107,15 +107,16 @@
     char buf[64];
     int  fd = -1;
 
-    fd = socket_loopback_client(port, SOCK_STREAM);
 #if ADB_HOST
-    if(fd < 0) {
-        const char *host = getenv("ADBHOST");
-        if(host) {
-            fd = socket_network_client(host, port, SOCK_STREAM);
-        }
+    const char *host = getenv("ADBHOST");
+    if (host) {
+        fd = socket_network_client(host, port, SOCK_STREAM);
     }
 #endif
+    if (fd < 0) {
+        fd = socket_loopback_client(port, SOCK_STREAM);
+    }
+
     if (fd >= 0) {
         D("client: connected on remote on fd %d\n", fd);
         close_on_exec(fd);
diff --git a/adb/transport_usb.c b/adb/transport_usb.c
index 4da7e8b..01c4a7e 100644
--- a/adb/transport_usb.c
+++ b/adb/transport_usb.c
@@ -55,7 +55,7 @@
     }
 
     fix_endians(p);
-    
+
     if(check_header(p)) {
         D("remote usb: check_header failed\n");
         return -1;
@@ -79,9 +79,9 @@
 static int remote_write(apacket *p, atransport *t)
 {
     unsigned size = p->msg.data_length;
-    
+
     fix_endians(p);
-    
+
     if(usb_write(t->usb, &p->msg, sizeof(amessage))) {
         D("remote usb: 1 - write terminated\n");
         return -1;
@@ -91,7 +91,7 @@
         D("remote usb: 2 - write terminated\n");
         return -1;
     }
-        
+
     return 0;
 }
 
@@ -117,7 +117,7 @@
     t->connection_state = CS_OFFLINE;
     t->type = kTransportUsb;
     t->usb = h;
-    
+
 #if ADB_HOST
     HOST = 1;
 #else
@@ -135,7 +135,7 @@
             /* not supported */
         return 0;
     }
-    
+
         /* class:vendor (0xff) subclass:android (0x42) proto:adb (0x01) */
     if(usb_class == 0xff) {
         if((usb_subclass == 0x42) && (usb_protocol == 0x01)) {
diff --git a/adb/usb_linux_client.c b/adb/usb_linux_client.c
index e265a1c..530bd04 100644
--- a/adb/usb_linux_client.c
+++ b/adb/usb_linux_client.c
@@ -118,7 +118,7 @@
     h->fd = -1;
     adb_cond_init(&h->notify, 0);
     adb_mutex_init(&h->lock, 0);
-    
+
     // Open the file /dev/android_adb_enable to trigger 
     // the enabling of the adb USB function in the kernel.
     // We never touch this file again - just leave it open
diff --git a/adb/usb_osx.c b/adb/usb_osx.c
index 8ea84f9..49e1eef 100644
--- a/adb/usb_osx.c
+++ b/adb/usb_osx.c
@@ -72,13 +72,13 @@
     CFRunLoopSourceRef      runLoopSource;
     SInt32					vendor, product;
     int                     i;
-    
+
     //* To set up asynchronous notifications, create a notification port and
     //* add its run loop event source to the program's run loop
     notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
     runLoopSource = IONotificationPortGetRunLoopSource(notificationPort);
     CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode);
-    
+
     memset(notificationIterators, 0, sizeof(notificationIterators));
 
     //* loop through all supported vendor/product pairs
@@ -86,19 +86,19 @@
         //* Create our matching dictionary to find the Android device
         //* IOServiceAddMatchingNotification consumes the reference, so we do not need to release this
         matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
-    
+
         if (!matchingDict) {
             DBG("ERR: Couldn't create USB matching dictionary.\n");
             return -1;
         }
-    
+
         //* Set up two matching dictionaries, one for each product ID we support.
         //* This will cause the kernel to notify us only if the vendor and product IDs match.
         vendor = kSupportedDevices[i].vid;
         product = kSupportedDevices[i].pid;
-      	CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vendor));
-      	CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &product));
-    
+        CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vendor));
+        CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &product));
+
         //* Now set up two notifications: one to be called when a raw device
         //* is first matched by the I/O Kit and another to be called when the
         //* device is terminated.
@@ -110,7 +110,7 @@
                 AndroidDeviceAdded,
                 NULL,
                 &notificationIterators[i]);
-    
+
         //* Iterate over set of matching devices to access already-present devices
         //* and to arm the notification
         AndroidDeviceAdded(NULL, notificationIterators[i]);
@@ -173,7 +173,7 @@
 
             if (kr == kIOReturnSuccess && req.wLenDone > 0) {
                 int i, count;
-                
+
                 // skip first word, and copy the rest to the serial string, changing shorts to bytes.
                 count = (req.wLenDone - 1) / 2;
                 for (i = 0; i < count; i++)
@@ -401,8 +401,8 @@
     currentRunLoop = 0;
 
     for (i = 0; i < kSupportedDeviceCount; i++) {
-	    IOObjectRelease(notificationIterators[i]);
-	}
+        IOObjectRelease(notificationIterators[i]);
+    }
     IONotificationPortDestroy(notificationPort);
 
     DBG("RunLoopThread done\n");
diff --git a/adb/usb_windows.c b/adb/usb_windows.c
index 5b0f11f..7ddaa0c 100644
--- a/adb/usb_windows.c
+++ b/adb/usb_windows.c
@@ -308,11 +308,11 @@
     while (len > 0) {
       int xfer = (len > 4096) ? 4096 : len;
 
-	    ret = AdbReadEndpointSync(handle->adb_read_pipe,
-	                              (void*)data,
-	                              (unsigned long)xfer,
-	                              &read,
-	                              time_out);
+      ret = AdbReadEndpointSync(handle->adb_read_pipe,
+                                  (void*)data,
+                                  (unsigned long)xfer,
+                                  &read,
+                                  time_out);
       errno = GetLastError();
       D("usb_write got: %ld, expected: %d, errno: %d\n", read, xfer, errno);
       if (ret) {
@@ -475,11 +475,11 @@
     // Lets see if we already have this device in the list
     if (!known_device(interf_name)) {
       // This seems to be a new device. Open it!
-	    handle = do_usb_open(next_interface->device_name);
-	    if (NULL != handle) {
+        handle = do_usb_open(next_interface->device_name);
+        if (NULL != handle) {
         // Lets see if this interface (device) belongs to us
         if (recognized_device(handle)) {
-	        D("adding a new device %s\n", interf_name);
+          D("adding a new device %s\n", interf_name);
           char serial_number[512];
           unsigned long serial_number_len = sizeof(serial_number);
           if (AdbGetSerialNumber(handle->adb_interface,
@@ -488,7 +488,7 @@
                                 true)) {
             // Lets make sure that we don't duplicate this device
             if (register_new_device(handle)) {
-	            register_usb_transport(handle, serial_number);
+              register_usb_transport(handle, serial_number);
             } else {
               D("register_new_device failed for %s\n", interf_name);
               usb_cleanup_handle(handle);
diff --git a/adb/utils.c b/adb/utils.c
new file mode 100644
index 0000000..91518ba
--- /dev/null
+++ b/adb/utils.c
@@ -0,0 +1,106 @@
+/*
+ * 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 "utils.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+char*
+buff_addc (char*  buff, char*  buffEnd, int  c)
+{
+    int  avail = buffEnd - buff;
+
+    if (avail <= 0)  /* already in overflow mode */
+        return buff;
+
+    if (avail == 1) {  /* overflowing, the last byte is reserved for zero */
+        buff[0] = 0;
+        return buff + 1;
+    }
+
+    buff[0] = (char) c;  /* add char and terminating zero */
+    buff[1] = 0;
+    return buff + 1;
+}
+
+char*
+buff_adds (char*  buff, char*  buffEnd, const char*  s)
+{
+    int  slen = strlen(s);
+
+    return buff_addb(buff, buffEnd, s, slen);
+}
+
+char*
+buff_addb (char*  buff, char*  buffEnd, const void*  data, int  len)
+{
+    int  avail = (buffEnd - buff);
+
+    if (avail <= 0 || len <= 0)  /* already overflowing */
+        return buff;
+
+    if (len > avail)
+        len = avail;
+
+    memcpy(buff, data, len);
+
+    buff += len;
+
+    /* ensure there is a terminating zero */
+    if (buff >= buffEnd) {  /* overflow */
+        buff[-1] = 0;
+    } else
+        buff[0] = 0;
+
+    return buff;
+}
+
+char*
+buff_add  (char*  buff, char*  buffEnd, const char*  format, ... )
+{
+    int      avail;
+
+    avail = (buffEnd - buff);
+
+    if (avail > 0) {
+        va_list  args;
+        int      nn;
+
+        va_start(args, format);
+        nn = vsnprintf( buff, avail, format, args);
+        va_end(args);
+
+        if (nn < 0) {
+            /* some C libraries return -1 in case of overflow,
+             * but they will also do that if the format spec is
+             * invalid. We assume ADB is not buggy enough to
+             * trigger that last case. */
+            nn = avail;
+        }
+        else if (nn > avail) {
+            nn = avail;
+        }
+
+        buff += nn;
+
+        /* ensure that there is a terminating zero */
+        if (buff >= buffEnd)
+            buff[-1] = 0;
+        else
+            buff[0] = 0;
+    }
+    return buff;
+}
diff --git a/adb/utils.h b/adb/utils.h
new file mode 100644
index 0000000..f70ecd2
--- /dev/null
+++ b/adb/utils.h
@@ -0,0 +1,68 @@
+/*
+ * 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 _ADB_UTILS_H
+#define _ADB_UTILS_H
+
+/* bounded buffer functions */
+
+/* all these functions are used to append data to a bounded buffer.
+ *
+ * after each operation, the buffer is guaranteed to be zero-terminated,
+ * even in the case of an overflow. they all return the new buffer position
+ * which allows one to use them in succession, only checking for overflows
+ * at the end. For example:
+ *
+ *    BUFF_DECL(temp,p,end,1024);
+ *    char*    p;
+ *
+ *    p = buff_addc(temp, end, '"');
+ *    p = buff_adds(temp, end, string);
+ *    p = buff_addc(temp, end, '"');
+ *
+ *    if (p >= end) {
+ *        overflow detected. note that 'temp' is
+ *        zero-terminated for safety. 
+ *    }
+ *    return strdup(temp);
+ */
+
+/* tries to add a character to the buffer, in case of overflow
+ * this will only write a terminating zero and return buffEnd.
+ */
+char*   buff_addc (char*  buff, char*  buffEnd, int  c);
+
+/* tries to add a string to the buffer */
+char*   buff_adds (char*  buff, char*  buffEnd, const char*  s);
+
+/* tries to add a bytes to the buffer. the input can contain zero bytes,
+ * but a terminating zero will always be appended at the end anyway
+ */
+char*   buff_addb (char*  buff, char*  buffEnd, const void*  data, int  len);
+
+/* tries to add a formatted string to a bounded buffer */
+char*   buff_add  (char*  buff, char*  buffEnd, const char*  format, ... );
+
+/* convenience macro used to define a bounded buffer, as well as
+ * a 'cursor' and 'end' variables all in one go.
+ *
+ * note: this doesn't place an initial terminating zero in the buffer,
+ * you need to use one of the buff_ functions for this. or simply
+ * do _cursor[0] = 0 manually.
+ */
+#define  BUFF_DECL(_buff,_cursor,_end,_size)   \
+    char   _buff[_size], *_cursor=_buff, *_end = _cursor + (_size)
+
+#endif /* _ADB_UTILS_H */