Merge "libsysutils: reimplement NetlinkEvent::findParam in the proper way"
diff --git a/adb/adb.c b/adb/adb.c
index 95dc001..ee78688 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -302,8 +302,10 @@
 {
     asocket *s;
 
-    D("handle_packet() %d\n", p->msg.command);
-
+    D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
+            ((char*) (&(p->msg.command)))[1],
+            ((char*) (&(p->msg.command)))[2],
+            ((char*) (&(p->msg.command)))[3]);
     print_packet("recv", p);
 
     switch(p->msg.command){
diff --git a/adb/jdwp_service.c b/adb/jdwp_service.c
index 0c26f7b..296f718 100644
--- a/adb/jdwp_service.c
+++ b/adb/jdwp_service.c
@@ -5,6 +5,7 @@
 #include <errno.h>
 #include <stdio.h>
 #include <string.h>
+#include <unistd.h>
 
 /* here's how these things work.
 
@@ -320,6 +321,7 @@
             struct iovec     iov;
             char             dummy = '!';
             char             buffer[sizeof(struct cmsghdr) + sizeof(int)];
+            int flags;
 
             iov.iov_base       = &dummy;
             iov.iov_len        = 1;
@@ -337,10 +339,27 @@
             cmsg->cmsg_type  = SCM_RIGHTS;
             ((int*)CMSG_DATA(cmsg))[0] = fd;
 
+            flags = fcntl(proc->socket,F_GETFL,0);
+
+            if (flags == -1) {
+                D("failed to get cntl flags for socket %d: %s\n",
+                  proc->pid, strerror(errno));
+                goto CloseProcess;
+
+            }
+
+            if (fcntl(proc->socket, F_SETFL, flags & ~O_NONBLOCK) == -1) {
+                D("failed to remove O_NONBLOCK flag for socket %d: %s\n",
+                  proc->pid, strerror(errno));
+                goto CloseProcess;
+            }
+
             for (;;) {
                 ret = sendmsg(proc->socket, &msg, 0);
-                if (ret >= 0)
+                if (ret >= 0) {
+                    adb_close(fd);
                     break;
+                }
                 if (errno == EINTR)
                     continue;
                 D("sending new file descriptor to JDWP %d failed: %s\n",
@@ -354,6 +373,12 @@
             for (n = 1; n < proc->out_count; n++)
                 proc->out_fds[n-1] = proc->out_fds[n];
 
+            if (fcntl(proc->socket, F_SETFL, flags) == -1) {
+                D("failed to set O_NONBLOCK flag for socket %d: %s\n",
+                  proc->pid, strerror(errno));
+                goto CloseProcess;
+            }
+
             if (--proc->out_count == 0)
                 fdevent_del( proc->fde, FDE_WRITE );
         }
diff --git a/adb/usb_vendors.c b/adb/usb_vendors.c
index db8b018..efeb2a0 100644
--- a/adb/usb_vendors.c
+++ b/adb/usb_vendors.c
@@ -71,6 +71,12 @@
 #define VENDOR_ID_QUALCOMM      0x05c6
 // On-The-Go-Video's USB Vendor ID
 #define VENDOR_ID_OTGV          0x2257
+// NEC's USB Vendor ID
+#define VENDOR_ID_NEC           0x0409
+// Panasonic Mobile Communication's USB Vendor ID
+#define VENDOR_ID_PMC           0x04DA
+// Toshiba's USB Vendor ID
+#define VENDOR_ID_TOSHIBA       0x0930
 
 
 /** built-in vendor list */
@@ -93,6 +99,9 @@
     VENDOR_ID_PANTECH,
     VENDOR_ID_QUALCOMM,
     VENDOR_ID_OTGV,
+    VENDOR_ID_NEC,
+    VENDOR_ID_PMC,
+    VENDOR_ID_TOSHIBA,
 };
 
 #define BUILT_IN_VENDOR_COUNT    (sizeof(builtInVendorIds)/sizeof(builtInVendorIds[0]))
diff --git a/include/cutils/log.h b/include/cutils/log.h
index dd47c35..f602017 100644
--- a/include/cutils/log.h
+++ b/include/cutils/log.h
@@ -291,11 +291,11 @@
  */
 #define LOG_ALWAYS_FATAL_IF(cond, ...) \
     ( (CONDITION(cond)) \
-    ? ((void)android_printAssert(#cond, LOG_TAG, __VA_ARGS__)) \
+    ? ((void)android_printAssert(#cond, LOG_TAG, ## __VA_ARGS__)) \
     : (void)0 )
 
 #define LOG_ALWAYS_FATAL(...) \
-    ( ((void)android_printAssert(NULL, LOG_TAG, __VA_ARGS__)) )
+    ( ((void)android_printAssert(NULL, LOG_TAG, ## __VA_ARGS__)) )
 
 /*
  * Versions of LOG_ALWAYS_FATAL_IF and LOG_ALWAYS_FATAL that
@@ -308,7 +308,7 @@
 
 #else
 
-#define LOG_FATAL_IF(cond, ...) LOG_ALWAYS_FATAL_IF(cond, __VA_ARGS__)
+#define LOG_FATAL_IF(cond, ...) LOG_ALWAYS_FATAL_IF(cond, ## __VA_ARGS__)
 #define LOG_FATAL(...) LOG_ALWAYS_FATAL(__VA_ARGS__)
 
 #endif
@@ -317,7 +317,7 @@
  * Assertion that generates a log message when the assertion fails.
  * Stripped out of release builds.  Uses the current LOG_TAG.
  */
-#define LOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), __VA_ARGS__)
+#define LOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), ## __VA_ARGS__)
 //#define LOG_ASSERT(cond) LOG_FATAL_IF(!(cond), "Assertion failed: " #cond)
 
 // ---------------------------------------------------------------------
@@ -403,8 +403,24 @@
 #define android_vprintLog(prio, cond, tag, fmt...) \
     __android_log_vprint(prio, tag, fmt)
 
+/* XXX Macros to work around syntax errors in places where format string
+ * arg is not passed to LOG_ASSERT, LOG_ALWAYS_FATAL or LOG_ALWAYS_FATAL_IF
+ * (happens only in debug builds).
+ */
+
+/* Returns 2nd arg.  Used to substitute default value if caller's vararg list
+ * is empty.
+ */
+#define __android_second(dummy, second, ...)     second
+
+/* If passed multiple args, returns ',' followed by all but 1st arg, otherwise
+ * returns nothing.
+ */
+#define __android_rest(first, ...)               , ## __VA_ARGS__
+
 #define android_printAssert(cond, tag, fmt...) \
-    __android_log_assert(cond, tag, fmt)
+    __android_log_assert(cond, tag, \
+        __android_second(0, ## fmt, NULL) __android_rest(fmt))
 
 #define android_writeLog(prio, tag, text) \
     __android_log_write(prio, tag, text)
@@ -413,7 +429,7 @@
     __android_log_bwrite(tag, payload, len)
 #define android_btWriteLog(tag, type, payload, len) \
     __android_log_btwrite(tag, type, payload, len)
-	
+
 // TODO: remove these prototypes and their users
 #define android_testLog(prio, tag) (1)
 #define android_writevLog(vec,num) do{}while(0)
diff --git a/init/init.c b/init/init.c
index 4d98cc2..0667593 100755
--- a/init/init.c
+++ b/init/init.c
@@ -657,8 +657,9 @@
         if (x) {
             x += 2;
             n = 0;
-            while (*x && !isspace(*x)) {
-                hardware[n++] = tolower(*x);
+            while (*x && *x != '\n') {
+                if (!isspace(*x))
+                    hardware[n++] = tolower(*x);
                 x++;
                 if (n == 31) break;
             }
diff --git a/libdiskconfig/Android.mk b/libdiskconfig/Android.mk
index ef08bec..c887955 100644
--- a/libdiskconfig/Android.mk
+++ b/libdiskconfig/Android.mk
@@ -3,7 +3,6 @@
 
 ifneq ($(TARGET_SIMULATOR),true)
 
-
 commonSources := \
 	diskconfig.c \
 	diskutils.c \
@@ -16,13 +15,13 @@
 LOCAL_SYSTEM_SHARED_LIBRARIES := libcutils liblog libc
 include $(BUILD_SHARED_LIBRARY)
 
+ifeq ($(HOST_OS),linux)
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := $(commonSources)
 LOCAL_MODULE := libdiskconfig_host
 LOCAL_SYSTEM_SHARED_LIBRARIES := libcutils
 LOCAL_CFLAGS := -O2 -g -W -Wall -Werror -D_LARGEFILE64_SOURCE
 include $(BUILD_HOST_STATIC_LIBRARY)
-
-
+endif # HOST_OS == linux
 
 endif  # ! TARGET_SIMULATOR
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index 9923bba..a0a753b 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -56,7 +56,7 @@
  * the simulator rather than a desktop tool and want to use the device.
  */
 static enum {
-    kLogUninitialized, kLogNotAvailable, kLogAvailable 
+    kLogUninitialized, kLogNotAvailable, kLogAvailable
 } g_log_status = kLogUninitialized;
 int __android_log_dev_available(void)
 {
@@ -189,7 +189,7 @@
 
 int __android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap)
 {
-    char buf[LOG_BUF_SIZE];    
+    char buf[LOG_BUF_SIZE];
 
     vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
 
@@ -223,12 +223,23 @@
 void __android_log_assert(const char *cond, const char *tag,
 			  const char *fmt, ...)
 {
-    va_list ap;
-    char buf[LOG_BUF_SIZE];    
+    char buf[LOG_BUF_SIZE];
 
-    va_start(ap, fmt);
-    vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
-    va_end(ap);
+    if (fmt) {
+        va_list ap;
+        va_start(ap, fmt);
+        vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
+        va_end(ap);
+    } else {
+        /* Msg not provided, log condition.  N.B. Do not use cond directly as
+         * format string as it could contain spurious '%' syntax (e.g.
+         * "%d" in "blocks%devs == 0").
+         */
+        if (cond)
+            snprintf(buf, LOG_BUF_SIZE, "Assertion failed: %s", cond);
+        else
+            strcpy(buf, "Unspecified assertion failed");
+    }
 
     __android_log_write(ANDROID_LOG_FATAL, tag, buf);
 
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 7ac991c..9a56bfd 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -7,7 +7,7 @@
 	etc/dbus.conf \
 	etc/hosts
 
-ifeq ($(TARGET_PRODUCT),generic)
+ifeq ($(TARGET_PRODUCT),full)
 copy_from += etc/vold.fstab
 endif
 
diff --git a/toolbox/chmod.c b/toolbox/chmod.c
index 31a53bf..2a524e9 100644
--- a/toolbox/chmod.c
+++ b/toolbox/chmod.c
@@ -4,17 +4,74 @@
 #include <sys/types.h>
 #include <dirent.h>
 #include <errno.h>
+#include <sys/limits.h>
+#include <sys/stat.h>
 
 #include <unistd.h>
 #include <time.h>
 
+void recurse_chmod(char* path, int mode)
+{
+    struct dirent *dp;
+    DIR *dir = opendir(path);
+    if (dir == NULL) {
+        // not a directory, carry on
+        return;
+    }
+    char *subpath = malloc(sizeof(char)*PATH_MAX);
+    int pathlen = strlen(path);
+
+    while ((dp = readdir(dir)) != NULL) {
+        if (strcmp(dp->d_name, ".") == 0 ||
+            strcmp(dp->d_name, "..") == 0) continue;
+
+        if (strlen(dp->d_name) + pathlen + 2/*NUL and slash*/ > PATH_MAX) {
+            fprintf(stderr, "Invalid path specified: too long\n");
+            exit(1);
+        }
+
+        strcpy(subpath, path);
+        strcat(subpath, "/");
+        strcat(subpath, dp->d_name);
+
+        if (chmod(subpath, mode) < 0) {
+            fprintf(stderr, "Unable to chmod %s: %s\n", subpath, strerror(errno));
+            exit(1);
+        }
+
+        recurse_chmod(subpath, mode);
+    }
+    free(subpath);
+    closedir(dir);
+}
+
+static int usage()
+{
+    fprintf(stderr, "Usage: chmod [OPTION] <MODE> <FILE>\n");
+    fprintf(stderr, "  -R, --recursive         change files and directories recursively\n");
+    fprintf(stderr, "  --help                  display this help and exit\n");
+
+    return 10;
+}
+
 int chmod_main(int argc, char **argv)
 {
     int i;
 
-    if (argc < 3) {
-        fprintf(stderr, "Usage: chmod <MODE> <FILE>\n");
-        return 10;
+    if (argc < 3 || strcmp(argv[1], "--help") == 0) {
+        return usage();
+    }
+
+    int recursive = (strcmp(argv[1], "-R") == 0 ||
+                     strcmp(argv[1], "--recursive") == 0) ? 1 : 0;
+
+    if (recursive && argc < 4) {
+        return usage();
+    }
+
+    if (recursive) {
+        argc--;
+        argv++;
     }
 
     int mode = 0;
@@ -29,11 +86,15 @@
         }
         s++;
     }
+
     for (i = 2; i < argc; i++) {
         if (chmod(argv[i], mode) < 0) {
             fprintf(stderr, "Unable to chmod %s: %s\n", argv[i], strerror(errno));
             return 10;
         }
+        if (recursive) {
+            recurse_chmod(argv[i], mode);
+        }
     }
     return 0;
 }
diff --git a/toolbox/insmod.c b/toolbox/insmod.c
index 44b9847..756a64b 100644
--- a/toolbox/insmod.c
+++ b/toolbox/insmod.c
@@ -77,7 +77,6 @@
 			memcpy(ptr, argv[i], len);
 			ptr += len;
 			*ptr++ = ' ';
-			*ptr++ = '\0';
 		}
 		*(ptr - 1) = '\0';
 	}
diff --git a/toolbox/mkdir.c b/toolbox/mkdir.c
index 121adab..656970a 100644
--- a/toolbox/mkdir.c
+++ b/toolbox/mkdir.c
@@ -2,10 +2,14 @@
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
+#include <sys/limits.h>
+#include <sys/stat.h>
 
 static int usage()
 {
-    fprintf(stderr,"mkdir <target>\n");
+    fprintf(stderr,"mkdir [OPTION] <target>\n");
+    fprintf(stderr,"    --help           display usage and exit\n");
+    fprintf(stderr,"    -p, --parents    create parent directories as needed\n");
     return -1;
 }
 
@@ -13,15 +17,60 @@
 {
     int symbolic = 0;
     int ret;
-    if(argc < 2) return usage();
+    if(argc < 2 || strcmp(argv[1], "--help") == 0) {
+        return usage();
+    }
+
+    int recursive = (strcmp(argv[1], "-p") == 0 ||
+                     strcmp(argv[1], "--parents") == 0) ? 1 : 0;
+
+    if(recursive && argc < 3) {
+        // -p specified without a path
+        return usage();
+    }
+
+    if(recursive) {
+        argc--;
+        argv++;
+    }
+
+    char currpath[PATH_MAX], *pathpiece;
+    struct stat st;
 
     while(argc > 1) {
         argc--;
         argv++;
-        ret = mkdir(argv[0], 0777);
-        if(ret < 0) {
-            fprintf(stderr, "mkdir failed for %s, %s\n", argv[0], strerror(errno));
-            return ret;
+        if(recursive) {
+            // reset path
+            strcpy(currpath, "");
+            // create the pieces of the path along the way
+            pathpiece = strtok(argv[0], "/");
+            if(argv[0][0] == '/') {
+                // prepend / if needed
+                strcat(currpath, "/");
+            }
+            while(pathpiece != NULL) {
+                if(strlen(currpath) + strlen(pathpiece) + 2/*NUL and slash*/ > PATH_MAX) {
+                    fprintf(stderr, "Invalid path specified: too long\n");
+                    return 1;
+                }
+                strcat(currpath, pathpiece);
+                strcat(currpath, "/");
+                if(stat(currpath, &st) != 0) {
+                    ret = mkdir(currpath, 0777);
+                    if(ret < 0) {
+                        fprintf(stderr, "mkdir failed for %s, %s\n", currpath, strerror(errno));
+                        return ret;
+                    }
+                }
+                pathpiece = strtok(NULL, "/");
+            }
+        } else {
+            ret = mkdir(argv[0], 0777);
+            if(ret < 0) {
+                fprintf(stderr, "mkdir failed for %s, %s\n", argv[0], strerror(errno));
+                return ret;
+            }
         }
     }