diff --git a/adb/Android.mk b/adb/Android.mk
index 32dd95a..bc8315e 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -16,7 +16,7 @@
 ifeq ($(HOST_OS),linux)
   USB_SRCS := usb_linux.c
   EXTRA_SRCS := get_my_path_linux.c
-  LOCAL_LDLIBS += -lrt -ldl -lpthread
+  LOCAL_LDLIBS += -lrt -lncurses -lpthread
 endif
 
 ifeq ($(HOST_OS),darwin)
@@ -139,7 +139,7 @@
 ifneq ($(SDK_ONLY),true)
 include $(CLEAR_VARS)
 
-LOCAL_LDLIBS := -lrt -ldl -lpthread
+LOCAL_LDLIBS := -lrt -lncurses -lpthread
 
 LOCAL_SRC_FILES := \
 	adb.c \
diff --git a/adb/SERVICES.TXT b/adb/SERVICES.TXT
index b53bc44..d9aa09c 100644
--- a/adb/SERVICES.TXT
+++ b/adb/SERVICES.TXT
@@ -117,34 +117,7 @@
 
     or even any one of the local services described below.
 
-<host-prefix>:forward:norebind:<local>;<remote>
-    Same as <host-prefix>:forward:<local>;<remote> except that it will
-    fail it there is already a forward connection from <local>.
 
-    Used to implement 'adb forward --no-rebind <local> <remote>'
-
-<host-prefix>:killforward:<local>
-    Remove any existing forward local connection from <local>.
-    This is used to implement 'adb forward --remove <local>'
-
-<host-prefix>:killforward-all
-    Remove all forward network connections.
-    This is used to implement 'adb forward --remove-all'.
-
-<host-prefix>:list-forward
-    List all existing forward connections from this server.
-    This returns something that looks like the following:
-
-       <hex4>: The length of the payload, as 4 hexadecimal chars.
-       <payload>: A series of lines of the following format:
-
-         <serial> " " <local> " " <remote> "\n"
-
-    Where <serial> is a device serial number.
-          <local>  is the host-specific endpoint (e.g. tcp:9000).
-          <remote> is the device-specific endpoint.
-
-    Used to implement 'adb forward --list'.
 
 LOCAL SERVICES:
 
diff --git a/adb/adb.c b/adb/adb.c
index b5d93f8..07bfbe5 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -46,7 +46,6 @@
 #endif
 
 int HOST = 0;
-int gListenAll = 0;
 
 static int auth_enabled = 0;
 
@@ -702,13 +701,7 @@
     if(!strncmp("tcp:", name, 4)){
         int  ret;
         port = atoi(name + 4);
-
-        if (gListenAll > 0) {
-            ret = socket_inaddr_any_server(port, SOCK_STREAM);
-        } else {
-            ret = socket_loopback_server(port, SOCK_STREAM);
-        }
-
+        ret = socket_loopback_server(port, SOCK_STREAM);
         return ret;
     }
 #ifndef HAVE_WIN32_IPC  /* no Unix-domain sockets on Win32 */
@@ -729,90 +722,24 @@
     return -1;
 }
 
-// Write a single line describing a listener to a user-provided buffer.
-// Appends a trailing zero, even in case of truncation, but the function
-// returns the full line length.
-// If |buffer| is NULL, does not write but returns required size.
-static int format_listener(alistener* l, char* buffer, size_t buffer_len) {
-    // Format is simply:
-    //
-    //  <device-serial> " " <local-name> " " <remote-name> "\n"
-    //
-    int local_len = strlen(l->local_name);
-    int connect_len = strlen(l->connect_to);
-    int serial_len = strlen(l->transport->serial);
-
-    if (buffer != NULL) {
-        snprintf(buffer, buffer_len, "%s %s %s\n",
-                l->transport->serial, l->local_name, l->connect_to);
-    }
-    // NOTE: snprintf() on Windows returns -1 in case of truncation, so
-    // return the computed line length instead.
-    return local_len + connect_len + serial_len + 3;
-}
-
-// Write the list of current listeners (network redirections) into a
-// user-provided buffer. Appends a trailing zero, even in case of
-// trunctaion, but return the full size in bytes.
-// If |buffer| is NULL, does not write but returns required size.
-static int format_listeners(char* buf, size_t buflen)
-{
-    alistener* l;
-    int result = 0;
-    for (l = listener_list.next; l != &listener_list; l = l->next) {
-        // Ignore special listeners like those for *smartsocket*
-        if (l->connect_to[0] == '*')
-          continue;
-        int len = format_listener(l, buf, buflen);
-        // Ensure there is space for the trailing zero.
-        result += len;
-        if (buf != NULL) {
-          buf += len;
-          buflen -= len;
-          if (buflen <= 0)
-              break;
-        }
-    }
-    return result;
-}
-
-static int remove_listener(const char *local_name, atransport* transport)
+static int remove_listener(const char *local_name, const char *connect_to, atransport* transport)
 {
     alistener *l;
 
     for (l = listener_list.next; l != &listener_list; l = l->next) {
-        if (!strcmp(local_name, l->local_name)) {
-            listener_disconnect(l, l->transport);
+        if (!strcmp(local_name, l->local_name) &&
+            !strcmp(connect_to, l->connect_to) &&
+            l->transport && l->transport == transport) {
+
+            listener_disconnect(l, transport);
             return 0;
         }
     }
+
     return -1;
 }
 
-static void remove_all_listeners(void)
-{
-    alistener *l, *l_next;
-    for (l = listener_list.next; l != &listener_list; l = l_next) {
-        l_next = l->next;
-        // Never remove smart sockets.
-        if (l->connect_to[0] == '*')
-            continue;
-        listener_disconnect(l, l->transport);
-    }
-}
-
-// error/status codes for install_listener.
-typedef enum {
-  INSTALL_STATUS_OK = 0,
-  INSTALL_STATUS_INTERNAL_ERROR = -1,
-  INSTALL_STATUS_CANNOT_BIND = -2,
-  INSTALL_STATUS_CANNOT_REBIND = -3,
-} install_status_t;
-
-static install_status_t install_listener(const char *local_name,
-                                         const char *connect_to,
-                                         atransport* transport,
-                                         int no_rebind)
+static int install_listener(const char *local_name, const char *connect_to, atransport* transport)
 {
     alistener *l;
 
@@ -824,17 +751,12 @@
 
                 /* can't repurpose a smartsocket */
             if(l->connect_to[0] == '*') {
-                return INSTALL_STATUS_INTERNAL_ERROR;
-            }
-
-                /* can't repurpose a listener if 'no_rebind' is true */
-            if (no_rebind) {
-                return INSTALL_STATUS_CANNOT_REBIND;
+                return -1;
             }
 
             cto = strdup(connect_to);
             if(cto == 0) {
-                return INSTALL_STATUS_INTERNAL_ERROR;
+                return -1;
             }
 
             //printf("rebinding '%s' to '%s'\n", local_name, connect_to);
@@ -845,7 +767,7 @@
                 l->transport = transport;
                 add_transport_disconnect(l->transport, &l->disconnect);
             }
-            return INSTALL_STATUS_OK;
+            return 0;
         }
     }
 
@@ -882,11 +804,11 @@
         l->disconnect.func   = listener_disconnect;
         add_transport_disconnect(transport, &l->disconnect);
     }
-    return INSTALL_STATUS_OK;
+    return 0;
 
 nomem:
     fatal("cannot allocate listener");
-    return INSTALL_STATUS_INTERNAL_ERROR;
+    return 0;
 }
 
 #ifdef HAVE_WIN32_PROC
@@ -991,7 +913,6 @@
     /* message since the pipe handles must be inheritable, we use a     */
     /* security attribute                                               */
     HANDLE                pipe_read, pipe_write;
-    HANDLE                stdout_handle, stderr_handle;
     SECURITY_ATTRIBUTES   sa;
     STARTUPINFO           startup;
     PROCESS_INFORMATION   pinfo;
@@ -1011,26 +932,6 @@
 
     SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 );
 
-    /* Some programs want to launch an adb command and collect its output by
-     * calling CreateProcess with inheritable stdout/stderr handles, then
-     * using read() to get its output. When this happens, the stdout/stderr
-     * handles passed to the adb client process will also be inheritable.
-     * When starting the adb server here, care must be taken to reset them
-     * to non-inheritable.
-     * Otherwise, something bad happens: even if the adb command completes,
-     * the calling process is stuck while read()-ing from the stdout/stderr
-     * descriptors, because they're connected to corresponding handles in the
-     * adb server process (even if the latter never uses/writes to them).
-     */
-    stdout_handle = GetStdHandle( STD_OUTPUT_HANDLE );
-    stderr_handle = GetStdHandle( STD_ERROR_HANDLE );
-    if (stdout_handle != INVALID_HANDLE_VALUE) {
-        SetHandleInformation( stdout_handle, HANDLE_FLAG_INHERIT, 0 );
-    }
-    if (stderr_handle != INVALID_HANDLE_VALUE) {
-        SetHandleInformation( stderr_handle, HANDLE_FLAG_INHERIT, 0 );
-    }
-
     ZeroMemory( &startup, sizeof(startup) );
     startup.cb = sizeof(startup);
     startup.hStdInput  = GetStdHandle( STD_INPUT_HANDLE );
@@ -1107,10 +1008,8 @@
         dup2(fd[1], STDERR_FILENO);
         adb_close(fd[1]);
 
-        char str_port[30];
-        snprintf(str_port, sizeof(str_port), "%d",  server_port);
         // child process
-        int result = execl(path, "adb", "-P", str_port, "fork-server", "server", NULL);
+        int result = execl(path, "adb", "fork-server", "server", NULL);
         // this should not return
         fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno);
     } else  {
@@ -1214,7 +1113,7 @@
 
     char local_name[30];
     build_local_name(local_name, sizeof(local_name), server_port);
-    if(install_listener(local_name, "*smartsocket*", NULL, 0)) {
+    if(install_listener(local_name, "*smartsocket*", NULL)) {
         exit(1);
     }
 #else
@@ -1281,7 +1180,7 @@
     } else {
         char local_name[30];
         build_local_name(local_name, sizeof(local_name), server_port);
-        if(install_listener(local_name, "*smartsocket*", NULL, 0)) {
+        if(install_listener(local_name, "*smartsocket*", NULL)) {
             exit(1);
         }
     }
@@ -1575,63 +1474,24 @@
     }
 #endif // ADB_HOST
 
-    if(!strcmp(service,"list-forward")) {
-        // Create the list of forward redirections.
-        char header[9];
-        int buffer_size = format_listeners(NULL, 0);
-        // Add one byte for the trailing zero.
-        char* buffer = malloc(buffer_size+1);
-        (void) format_listeners(buffer, buffer_size+1);
-        snprintf(header, sizeof header, "OKAY%04x", buffer_size);
-        writex(reply_fd, header, 8);
-        writex(reply_fd, buffer, buffer_size);
-        free(buffer);
-        return 0;
-    }
-
-    if (!strcmp(service,"killforward-all")) {
-        remove_all_listeners();
-        adb_write(reply_fd, "OKAYOKAY", 8);
-        return 0;
-    }
-
-    if(!strncmp(service,"forward:",8) ||
-       !strncmp(service,"killforward:",12)) {
+    if(!strncmp(service,"forward:",8) || !strncmp(service,"killforward:",12)) {
         char *local, *remote, *err;
         int r;
         atransport *transport;
 
         int createForward = strncmp(service,"kill",4);
-        int no_rebind = 0;
 
-        local = strchr(service, ':') + 1;
-
-        // Handle forward:norebind:<local>... here
-        if (createForward && !strncmp(local, "norebind:", 9)) {
-            no_rebind = 1;
-            local = strchr(local, ':') + 1;
+        local = service + (createForward ? 8 : 12);
+        remote = strchr(local,';');
+        if(remote == 0) {
+            sendfailmsg(reply_fd, "malformed forward spec");
+            return 0;
         }
 
-        remote = strchr(local,';');
-
-        if (createForward) {
-            // Check forward: parameter format: '<local>;<remote>'
-            if(remote == 0) {
-                sendfailmsg(reply_fd, "malformed forward spec");
-                return 0;
-            }
-
-            *remote++ = 0;
-            if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')){
-                sendfailmsg(reply_fd, "malformed forward spec");
-                return 0;
-            }
-        } else {
-            // Check killforward: parameter format: '<local>'
-            if (local[0] == 0) {
-                sendfailmsg(reply_fd, "malformed forward spec");
-                return 0;
-            }
+        *remote++ = 0;
+        if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')){
+            sendfailmsg(reply_fd, "malformed forward spec");
+            return 0;
         }
 
         transport = acquire_one_transport(CS_ANY, ttype, serial, &err);
@@ -1641,9 +1501,9 @@
         }
 
         if (createForward) {
-            r = install_listener(local, remote, transport, no_rebind);
+            r = install_listener(local, remote, transport);
         } else {
-            r = remove_listener(local, transport);
+            r = remove_listener(local, remote, transport);
         }
         if(r == 0) {
                 /* 1st OKAY is connect, 2nd OKAY is status */
@@ -1652,18 +1512,7 @@
         }
 
         if (createForward) {
-            const char* message;
-            switch (r) {
-              case INSTALL_STATUS_CANNOT_BIND:
-                message = "cannot bind to socket";
-                break;
-              case INSTALL_STATUS_CANNOT_REBIND:
-                message = "cannot rebind existing socket";
-                break;
-              default:
-                message = "internal error";
-            }
-            sendfailmsg(reply_fd, message);
+            sendfailmsg(reply_fd, (r == -1) ? "cannot rebind smartsocket" : "cannot bind socket");
         } else {
             sendfailmsg(reply_fd, "cannot remove listener");
         }
diff --git a/adb/adb_client.c b/adb/adb_client.c
index 8340738..9a812f0 100644
--- a/adb/adb_client.c
+++ b/adb/adb_client.c
@@ -17,7 +17,6 @@
 static const char* __adb_serial = NULL;
 
 static int __adb_server_port = DEFAULT_ADB_PORT;
-static const char* __adb_server_name = NULL;
 
 void adb_set_transport(transport_type type, const char* serial)
 {
@@ -30,11 +29,6 @@
     __adb_server_port = server_port;
 }
 
-void adb_set_tcp_name(const char* hostname)
-{
-    __adb_server_name = hostname;
-}
-
 int  adb_get_emulator_console_port(void)
 {
     const char*   serial = __adb_serial;
@@ -187,11 +181,7 @@
     }
     snprintf(tmp, sizeof tmp, "%04x", len);
 
-    if (__adb_server_name)
-        fd = socket_network_client(__adb_server_name, __adb_server_port, SOCK_STREAM);
-    else
-        fd = socket_loopback_client(__adb_server_port, SOCK_STREAM);
-
+    fd = socket_loopback_client(__adb_server_port, SOCK_STREAM);
     if(fd < 0) {
         strcpy(__adb_error, "cannot connect to daemon");
         return -2;
@@ -222,10 +212,7 @@
     int fd = _adb_connect("host:version");
 
     D("adb_connect: service %s\n", service);
-    if(fd == -2 && __adb_server_name) {
-        fprintf(stderr,"** Cannot start server on remote host\n");
-        return fd;
-    } else if(fd == -2) {
+    if(fd == -2) {
         fprintf(stdout,"* daemon not running. starting it now on port %d *\n",
                 __adb_server_port);
     start_server:
@@ -279,7 +266,7 @@
 
     fd = _adb_connect(service);
     if(fd == -2) {
-        fprintf(stderr,"** daemon still not running\n");
+        fprintf(stderr,"** daemon still not running");
     }
     D("adb_connect: return fd %d\n", fd);
 
diff --git a/adb/adb_client.h b/adb/adb_client.h
index 0ec47ca..40ab189 100644
--- a/adb/adb_client.h
+++ b/adb/adb_client.h
@@ -29,10 +29,6 @@
 */
 void adb_set_tcp_specifics(int server_port);
 
-/* Set TCP Hostname of the transport to use
-*/
-void adb_set_tcp_name(const char* hostname);
-
 /* Return the console port of the currently connected emulator (if any)
  * of -1 if there is no emulator, and -2 if there is more than one.
  * assumes adb_set_transport() was alled previously...
diff --git a/adb/commandline.c b/adb/commandline.c
index cbe4616..24cbb5a 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -46,7 +46,6 @@
 int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
 
 static const char *gProductOutPath = NULL;
-extern int gListenAll;
 
 static char *product_file(const char *extra)
 {
@@ -81,7 +80,6 @@
 
     fprintf(stderr,
         "\n"
-        " -a                            - directs adb to listen on all interfaces for a connection\n"
         " -d                            - directs command to the only connected USB device\n"
         "                                 returns an error if more than one USB device is present.\n"
         " -e                            - directs command to the only running emulator.\n"
@@ -95,8 +93,6 @@
         "                                 If -p is not specified, the ANDROID_PRODUCT_OUT\n"
         "                                 environment variable is used, which must\n"
         "                                 be an absolute path.\n"
-        " -H                            - Name of adb server host (default: localhost)\n"
-        " -P                            - Port of adb server (default: 5037)\n"
         " devices [-l]                  - list all connected devices\n"
         "                                 ('-l' will also list device qualifiers)\n"
         " connect <host>[:<port>]       - connect to a device via TCP/IP\n"
@@ -116,9 +112,6 @@
         "  adb shell <command>          - run remote shell command\n"
         "  adb emu <command>            - run emulator console command\n"
         "  adb logcat [ <filter-spec> ] - View device log\n"
-        "  adb forward --list           - list all forward socket connections.\n"
-        "                                 the format is a list of lines with the following format:\n"
-        "                                    <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
         "  adb forward <local> <remote> - forward socket connections\n"
         "                                 forward specs are one of: \n"
         "                                   tcp:<port>\n"
@@ -127,11 +120,6 @@
         "                                   localfilesystem:<unix domain socket name>\n"
         "                                   dev:<character device name>\n"
         "                                   jdwp:<process pid> (remote only)\n"
-        "  adb forward --no-rebind <local> <remote>\n"
-        "                               - same as 'adb forward <local> <remote>' but fails\n"
-        "                                 if <local> is already forwarded\n"
-        "  adb forward --remove <local> - remove a specific forward socket connection\n"
-        "  adb forward --remove-all     - remove all forward socket connections\n"
         "  adb jdwp                     - list PIDs of processes hosting a JDWP transport\n"
         "  adb install [-l] [-r] [-s] [--algo <algorithm name> --key <hex-encoded key> --iv <hex-encoded iv>] <file>\n"
         "                               - push this package file to the device and install it\n"
@@ -950,9 +938,9 @@
     int server_port = DEFAULT_ADB_PORT;
     if (server_port_str && strlen(server_port_str) > 0) {
         server_port = (int) strtol(server_port_str, NULL, 0);
-        if (server_port <= 0 || server_port > 65535) {
+        if (server_port <= 0) {
             fprintf(stderr,
-                    "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number less than 65535. Got \"%s\"\n",
+                    "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number. Got \"%s\"\n",
                     server_port_str);
             return usage();
         }
@@ -998,42 +986,6 @@
             ttype = kTransportUsb;
         } else if (!strcmp(argv[0],"-e")) {
             ttype = kTransportLocal;
-        } else if (!strcmp(argv[0],"-a")) {
-            gListenAll = 1;
-        } else if(!strncmp(argv[0], "-H", 2)) {
-            const char *hostname = NULL;
-            if (argv[0][2] == '\0') {
-                if (argc < 2) return usage();
-                hostname = argv[1];
-                argc--;
-                argv++;
-            } else {
-                hostname = argv[0] + 2;
-            }
-            adb_set_tcp_name(hostname);
-
-        } else if(!strncmp(argv[0], "-P", 2)) {
-            if (argv[0][2] == '\0') {
-                if (argc < 2) return usage();
-                server_port_str = argv[1];
-                argc--;
-                argv++;
-            } else {
-                server_port_str = argv[0] + 2;
-            }
-            if (strlen(server_port_str) > 0) {
-                server_port = (int) strtol(server_port_str, NULL, 0);
-                if (server_port <= 0 || server_port > 65535) {
-                    fprintf(stderr,
-                            "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
-                            server_port_str);
-                    return usage();
-                }
-            } else {
-                fprintf(stderr,
-                "adb: port number must be a positive number less than 65536. Got empty string.\n");
-                return usage();
-            }
         } else {
                 /* out of recognized modifiers and flags */
             break;
@@ -1271,85 +1223,16 @@
     }
 
     if(!strcmp(argv[0], "forward")) {
-        char host_prefix[64];
-        char remove = 0;
-        char remove_all = 0;
-        char list = 0;
-        char no_rebind = 0;
-
-        // Parse options here.
-        while (argc > 1 && argv[1][0] == '-') {
-            if (!strcmp(argv[1], "--list"))
-                list = 1;
-            else if (!strcmp(argv[1], "--remove"))
-                remove = 1;
-            else if (!strcmp(argv[1], "--remove-all"))
-                remove_all = 1;
-            else if (!strcmp(argv[1], "--no-rebind"))
-                no_rebind = 1;
-            else {
-                return usage();
-            }
-            argc--;
-            argv++;
-        }
-
-        // Ensure we can only use one option at a time.
-        if (list + remove + remove_all + no_rebind > 1) {
-            return usage();
-        }
-
-        // Determine the <host-prefix> for this command.
+        if(argc != 3) return usage();
         if (serial) {
-            snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
-                    serial);
+            snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]);
         } else if (ttype == kTransportUsb) {
-            snprintf(host_prefix, sizeof host_prefix, "host-usb");
+            snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]);
         } else if (ttype == kTransportLocal) {
-            snprintf(host_prefix, sizeof host_prefix, "host-local");
+            snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]);
         } else {
-            snprintf(host_prefix, sizeof host_prefix, "host");
+            snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]);
         }
-
-        // Implement forward --list
-        if (list) {
-            if (argc != 1)
-                return usage();
-            snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
-            char* forwards = adb_query(buf);
-            if (forwards == NULL) {
-                fprintf(stderr, "error: %s\n", adb_error());
-                return 1;
-            }
-            printf("%s", forwards);
-            free(forwards);
-            return 0;
-        }
-
-        // Implement forward --remove-all
-        else if (remove_all) {
-            if (argc != 1)
-                return usage();
-            snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
-        }
-
-        // Implement forward --remove <local>
-        else if (remove) {
-            if (argc != 2)
-                return usage();
-            snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
-        }
-        // Or implement one of:
-        //    forward <local> <remote>
-        //    forward --no-rebind <local> <remote>
-        else
-        {
-          if (argc != 3)
-            return usage();
-          const char* command = no_rebind ? "forward:norebind:" : "forward";
-          snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
-        }
-
         if(adb_command(buf)) {
             fprintf(stderr,"error: %s\n", adb_error());
             return 1;
diff --git a/adb/services.c b/adb/services.c
index 54d21a8..495a083 100644
--- a/adb/services.c
+++ b/adb/services.c
@@ -202,7 +202,7 @@
     int c;
 
     for(;;) {
-        r = adb_read(fd, buf, 4096);
+        r = read(fd, buf, 4096);
         if(r == 0) goto done;
         if(r < 0) {
             if(errno == EINTR) continue;
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 0252ef3..66b60cc 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -275,22 +275,6 @@
 #include <netinet/in.h>
 #include <netinet/tcp.h>
 #include <string.h>
-#include <unistd.h>
-
-/*
- * TEMP_FAILURE_RETRY is defined by some, but not all, versions of
- * <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's
- * not already defined, then define it here.
- */
-#ifndef TEMP_FAILURE_RETRY
-/* Used to retry syscalls that can return EINTR. */
-#define TEMP_FAILURE_RETRY(exp) ({         \
-    typeof (exp) _rc;                      \
-    do {                                   \
-        _rc = (exp);                       \
-    } while (_rc == -1 && errno == EINTR); \
-    _rc; })
-#endif
 
 #define OS_PATH_SEPARATOR '/'
 #define OS_PATH_SEPARATOR_STR "/"
@@ -326,7 +310,7 @@
 {
     if ((options & O_CREAT) == 0)
     {
-        return  TEMP_FAILURE_RETRY( open(path, options) );
+        return  open(path, options);
     }
     else
     {
@@ -335,19 +319,19 @@
         va_start( args, options );
         mode = va_arg( args, int );
         va_end( args );
-        return TEMP_FAILURE_RETRY( open( path, options, mode ) );
+        return open(path, options, mode);
     }
 }
 
 static __inline__ int  adb_open_mode( const char*  pathname, int  options, int  mode )
 {
-    return TEMP_FAILURE_RETRY( open( pathname, options, mode ) );
+    return open( pathname, options, mode );
 }
 
 
 static __inline__ int  adb_open( const char*  pathname, int  options )
 {
-    int  fd = TEMP_FAILURE_RETRY( open( pathname, options ) );
+    int  fd = open( pathname, options );
     if (fd < 0)
         return -1;
     close_on_exec( fd );
@@ -373,7 +357,7 @@
 
 static __inline__  int  adb_read(int  fd, void*  buf, size_t  len)
 {
-    return TEMP_FAILURE_RETRY( read( fd, buf, len ) );
+    return read(fd, buf, len);
 }
 
 #undef   read
@@ -381,7 +365,7 @@
 
 static __inline__  int  adb_write(int  fd, const void*  buf, size_t  len)
 {
-    return TEMP_FAILURE_RETRY( write( fd, buf, len ) );
+    return write(fd, buf, len);
 }
 #undef   write
 #define  write  ___xxx_write
@@ -402,7 +386,7 @@
 
 static __inline__  int  adb_creat(const char*  path, int  mode)
 {
-    int  fd = TEMP_FAILURE_RETRY( creat( path, mode ) );
+    int  fd = creat(path, mode);
 
     if ( fd < 0 )
         return -1;
@@ -417,7 +401,7 @@
 {
     int fd;
 
-    fd = TEMP_FAILURE_RETRY( accept( serverfd, addr, addrlen ) );
+    fd = accept(serverfd, addr, addrlen);
     if (fd >= 0)
         close_on_exec(fd);
 
diff --git a/charger/Android.mk b/charger/Android.mk
index fe0c91d..0258604 100644
--- a/charger/Android.mk
+++ b/charger/Android.mk
@@ -12,6 +12,10 @@
 LOCAL_CFLAGS := -DCHARGER_DISABLE_INIT_BLANK
 endif
 
+ifeq ($(strip $(BOARD_CHARGER_ENABLE_SUSPEND)),true)
+LOCAL_CFLAGS += -DCHARGER_ENABLE_SUSPEND
+endif
+
 LOCAL_MODULE := charger
 LOCAL_MODULE_TAGS := optional
 LOCAL_FORCE_STATIC_EXECUTABLE := true
@@ -21,6 +25,9 @@
 LOCAL_C_INCLUDES := bootable/recovery
 
 LOCAL_STATIC_LIBRARIES := libminui libpixelflinger_static libpng
+ifeq ($(strip $(BOARD_CHARGER_ENABLE_SUSPEND)),true)
+LOCAL_STATIC_LIBRARIES += libsuspend
+endif
 LOCAL_STATIC_LIBRARIES += libz libstdc++ libcutils libm libc
 
 include $(BUILD_EXECUTABLE)
diff --git a/charger/charger.c b/charger/charger.c
index c5e4ec2..353bdf0 100644
--- a/charger/charger.c
+++ b/charger/charger.c
@@ -41,6 +41,10 @@
 #include <cutils/misc.h>
 #include <cutils/uevent.h>
 
+#ifdef CHARGER_ENABLE_SUSPEND
+#include <suspend/autosuspend.h>
+#endif
+
 #include "minui/minui.h"
 
 #ifndef max
@@ -352,6 +356,21 @@
     free(supply);
 }
 
+#ifdef CHARGER_ENABLE_SUSPEND
+static int request_suspend(bool enable)
+{
+    if (enable)
+        return autosuspend_enable();
+    else
+        return autosuspend_disable();
+}
+#else
+static int request_suspend(bool enable)
+{
+    return 0;
+}
+#endif
+
 static void parse_uevent(const char *msg, struct uevent *uevent)
 {
     uevent->action = "";
@@ -685,6 +704,8 @@
         charger->next_screen_transition = -1;
         gr_fb_blank(true);
         LOGV("[%lld] animation done\n", now);
+        if (charger->num_supplies_online > 0)
+            request_suspend(true);
         return;
     }
 
@@ -824,8 +845,10 @@
             }
         } else {
             /* if the power key got released, force screen state cycle */
-            if (key->pending)
+            if (key->pending) {
+                request_suspend(false);
                 kick_animation(charger->batt_anim);
+            }
         }
     }
 
@@ -843,6 +866,7 @@
 static void handle_power_supply_state(struct charger *charger, int64_t now)
 {
     if (charger->num_supplies_online == 0) {
+        request_suspend(false);
         if (charger->next_pwr_check == -1) {
             charger->next_pwr_check = now + UNPLUGGED_SHUTDOWN_TIME;
             LOGI("[%lld] device unplugged: shutting down in %lld (@ %lld)\n",
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index e48b9af..15083f4 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -23,11 +23,13 @@
 LOCAL_CFLAGS += -DWITH_VFP_D32
 endif # ARCH_ARM_HAVE_VFP_D32
 
-LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-	libc \
-	libcorkscrew \
-	libselinux
+LOCAL_SHARED_LIBRARIES := libcutils libc libcorkscrew
+
+ifeq ($(HAVE_SELINUX),true)
+LOCAL_SHARED_LIBRARIES += libselinux
+LOCAL_C_INCLUDES += external/libselinux/include
+LOCAL_CFLAGS += -DHAVE_SELINUX
+endif
 
 include $(BUILD_EXECUTABLE)
 
diff --git a/debuggerd/backtrace.c b/debuggerd/backtrace.c
index ba76e7d..62f7f32 100644
--- a/debuggerd/backtrace.c
+++ b/debuggerd/backtrace.c
@@ -125,9 +125,10 @@
     char task_path[64];
     snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid);
     DIR* d = opendir(task_path);
-    if (d != NULL) {
-        struct dirent* de = NULL;
-        while ((de = readdir(d)) != NULL) {
+    if (d) {
+        struct dirent debuf;
+        struct dirent *de;
+        while (!readdir_r(d, &debuf, &de) && de) {
             if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
                 continue;
             }
diff --git a/debuggerd/crasher.c b/debuggerd/crasher.c
index 74eaa49..00652e9 100644
--- a/debuggerd/crasher.c
+++ b/debuggerd/crasher.c
@@ -20,7 +20,6 @@
 void crash1(void);
 void crashnostack(void);
 void maybeabort(void);
-int do_action(const char* arg);
 
 static void debuggerd_connect()
 {
@@ -75,46 +74,24 @@
     return 0;
 }
 
-static void* thread_callback(void* raw_arg)
-{
-    return (void*) do_action((const char*) raw_arg);
-}
-
-int do_action_on_thread(const char* arg)
-{
-    pthread_t t;
-    pthread_create(&t, NULL, thread_callback, (void*) arg);
-    void* result = NULL;
-    pthread_join(t, &result);
-    return (int) result;
-}
-
-int do_action(const char* arg)
-{
-    if(!strncmp(arg, "thread-", strlen("thread-"))) {
-        return do_action_on_thread(arg + strlen("thread-"));
-    }
-
-    if(!strcmp(arg,"nostack")) crashnostack();
-    if(!strcmp(arg,"ctest")) return ctest();
-    if(!strcmp(arg,"exit")) exit(1);
-    if(!strcmp(arg,"abort")) maybeabort();
-
-    pthread_t thr;
-    pthread_attr_t attr;
-    pthread_attr_init(&attr);
-    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-    pthread_create(&thr, &attr, test_thread, 0);
-    while(1) sleep(1);
-}
-
 int main(int argc, char **argv)
 {
-    fprintf(stderr,"crasher: built at " __TIME__ "!@\n");
+    pthread_t thr;
+    pthread_attr_t attr;
+
+    fprintf(stderr,"crasher: " __TIME__ "!@\n");
     fprintf(stderr,"crasher: init pid=%d tid=%d\n", getpid(), gettid());
 
     if(argc > 1) {
-        return do_action(argv[1]);
+        if(!strcmp(argv[1],"nostack")) crashnostack();
+        if(!strcmp(argv[1],"ctest")) return ctest();
+        if(!strcmp(argv[1],"exit")) exit(1);
+        if(!strcmp(argv[1],"abort")) maybeabort();
+        
+        pthread_attr_init(&attr);
+        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+        pthread_create(&thr, &attr, test_thread, 0);
+        while(1) sleep(1);
     } else {
         crash1();
 //        *((int*) 0) = 42;
diff --git a/debuggerd/tombstone.c b/debuggerd/tombstone.c
index e8b3e24..592f4f2 100644
--- a/debuggerd/tombstone.c
+++ b/debuggerd/tombstone.c
@@ -35,7 +35,9 @@
 #include <corkscrew/demangle.h>
 #include <corkscrew/backtrace.h>
 
+#ifdef HAVE_SELINUX
 #include <selinux/android.h>
+#endif
 
 #include "machine.h"
 #include "tombstone.h"
@@ -84,7 +86,6 @@
 
 static const char *get_sigcode(int signo, int code)
 {
-    // Try the signal-specific codes...
     switch (signo) {
     case SIGILL:
         switch (code) {
@@ -123,31 +124,7 @@
         case SEGV_ACCERR: return "SEGV_ACCERR";
         }
         break;
-    case SIGTRAP:
-        switch (code) {
-        case TRAP_BRKPT: return "TRAP_BRKPT";
-        case TRAP_TRACE: return "TRAP_TRACE";
-        }
-        break;
     }
-    // Then the other codes...
-    switch (code) {
-    case SI_USER:    return "SI_USER";
-#if defined(SI_KERNEL)
-    case SI_KERNEL:  return "SI_KERNEL";
-#endif
-    case SI_QUEUE:   return "SI_QUEUE";
-    case SI_TIMER:   return "SI_TIMER";
-    case SI_MESGQ:   return "SI_MESGQ";
-    case SI_ASYNCIO: return "SI_ASYNCIO";
-#if defined(SI_SIGIO)
-    case SI_SIGIO:   return "SI_SIGIO";
-#endif
-#if defined(SI_TKILL)
-    case SI_TKILL:   return "SI_TKILL";
-#endif
-    }
-    // Then give up...
     return "?";
 }
 
@@ -350,18 +327,6 @@
     }
 }
 
-static void dump_map(log_t* log, map_info_t* m, const char* what) {
-    if (m != NULL) {
-        _LOG(log, false, "    %08x-%08x %c%c%c %s\n", m->start, m->end,
-             m->is_readable ? 'r' : '-',
-             m->is_writable ? 'w' : '-',
-             m->is_executable ? 'x' : '-',
-             m->name);
-    } else {
-        _LOG(log, false, "    (no %s)\n", what);
-    }
-}
-
 static void dump_nearby_maps(const ptrace_context_t* context, log_t* log, pid_t tid) {
     siginfo_t si;
     memset(&si, 0, sizeof(si));
@@ -408,9 +373,21 @@
      * Show "next" then "match" then "prev" so that the addresses appear in
      * ascending order (like /proc/pid/maps).
      */
-    dump_map(log, next, "map below");
-    dump_map(log, map, "map for address");
-    dump_map(log, prev, "map above");
+    if (next != NULL) {
+        _LOG(log, false, "    %08x-%08x %s\n", next->start, next->end, next->name);
+    } else {
+        _LOG(log, false, "    (no map below)\n");
+    }
+    if (map != NULL) {
+        _LOG(log, false, "    %08x-%08x %s\n", map->start, map->end, map->name);
+    } else {
+        _LOG(log, false, "    (no map for address)\n");
+    }
+    if (prev != NULL) {
+        _LOG(log, false, "    %08x-%08x %s\n", prev->start, prev->end, prev->name);
+    } else {
+        _LOG(log, false, "    (no map above)\n");
+    }
 }
 
 static void dump_thread(const ptrace_context_t* context, log_t* log, pid_t tid, bool at_fault,
@@ -439,8 +416,9 @@
     }
 
     bool detach_failed = false;
-    struct dirent* de;
-    while ((de = readdir(d)) != NULL) {
+    struct dirent debuf;
+    struct dirent *de;
+    while (!readdir_r(d, &debuf, &de) && de) {
         /* Ignore "." and ".." */
         if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
             continue;
@@ -718,10 +696,12 @@
     mkdir(TOMBSTONE_DIR, 0755);
     chown(TOMBSTONE_DIR, AID_SYSTEM, AID_SYSTEM);
 
+#ifdef HAVE_SELINUX
     if (selinux_android_restorecon(TOMBSTONE_DIR) == -1) {
         *detach_failed = false;
         return NULL;
     }
+#endif
 
     int fd;
     char* path = find_and_open_tombstone(&fd);
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index 5025dae..92e9219 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -57,7 +57,9 @@
     libz
 
 ifneq ($(HOST_OS),windows)
+ifeq ($(HAVE_SELINUX), true)
 LOCAL_STATIC_LIBRARIES += libselinux
+endif # HAVE_SELINUX
 endif # HOST_OS != windows
 
 include $(BUILD_HOST_EXECUTABLE)
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index 2bcc9c4..538b5be 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -173,7 +173,7 @@
  * then return an empty buffer.  This effectively ignores lines that are too long.
  * On EOF, return null.
  */
-static char *fs_getline(char *buf, int size, FILE *file)
+static char *getline(char *buf, int size, FILE *file)
 {
     int cnt = 0;
     int eof = 0;
@@ -247,7 +247,7 @@
     }
 
     entries = 0;
-    while (fs_getline(line, sizeof(line), fstab_file)) {
+    while (getline(line, sizeof(line), fstab_file)) {
         /* if the last character is a newline, shorten the string by 1 byte */
         len = strlen(line);
         if (line[len - 1] == '\n') {
@@ -274,7 +274,7 @@
     fseek(fstab_file, 0, SEEK_SET);
 
     cnt = 0;
-    while (fs_getline(line, sizeof(line), fstab_file)) {
+    while (getline(line, sizeof(line), fstab_file)) {
         /* if the last character is a newline, shorten the string by 1 byte */
         len = strlen(line);
         if (line[len - 1] == '\n') {
diff --git a/include/corkscrew/map_info.h b/include/corkscrew/map_info.h
index c9b241d..ea1d35f 100644
--- a/include/corkscrew/map_info.h
+++ b/include/corkscrew/map_info.h
@@ -32,7 +32,6 @@
     uintptr_t start;
     uintptr_t end;
     bool is_readable;
-    bool is_writable;
     bool is_executable;
     void* data; // arbitrary data associated with the map by the user, initially NULL
     char name[];
@@ -47,10 +46,9 @@
 /* Finds the memory map that contains the specified address. */
 const map_info_t* find_map_info(const map_info_t* milist, uintptr_t addr);
 
-/* Returns true if the addr is in a readable map. */
+/* Returns true if the addr is in an readable map. */
 bool is_readable_map(const map_info_t* milist, uintptr_t addr);
-/* Returns true if the addr is in a writable map. */
-bool is_writable_map(const map_info_t* milist, uintptr_t addr);
+
 /* Returns true if the addr is in an executable map. */
 bool is_executable_map(const map_info_t* milist, uintptr_t addr);
 
diff --git a/include/cutils/atomic-arm.h b/include/cutils/atomic-arm.h
index 795afd3..16fe512 100644
--- a/include/cutils/atomic-arm.h
+++ b/include/cutils/atomic-arm.h
@@ -20,78 +20,72 @@
 #include <stdint.h>
 #include <machine/cpu-features.h>
 
-#ifndef ANDROID_ATOMIC_INLINE
-#define ANDROID_ATOMIC_INLINE inline __attribute__((always_inline))
-#endif
-
-extern ANDROID_ATOMIC_INLINE void android_compiler_barrier(void)
+extern inline void android_compiler_barrier(void)
 {
     __asm__ __volatile__ ("" : : : "memory");
 }
 
 #if ANDROID_SMP == 0
-extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void)
+extern inline void android_memory_barrier(void)
 {
     android_compiler_barrier();
 }
-extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void)
+extern inline void android_memory_store_barrier(void)
 {
     android_compiler_barrier();
 }
 #elif defined(__ARM_HAVE_DMB)
-extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void)
+extern inline void android_memory_barrier(void)
 {
     __asm__ __volatile__ ("dmb" : : : "memory");
 }
-extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void)
+extern inline void android_memory_store_barrier(void)
 {
     __asm__ __volatile__ ("dmb st" : : : "memory");
 }
 #elif defined(__ARM_HAVE_LDREX_STREX)
-extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void)
+extern inline void android_memory_barrier(void)
 {
     __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r" (0) : "memory");
 }
-extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void)
+extern inline void android_memory_store_barrier(void)
 {
     android_memory_barrier();
 }
 #else
-extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void)
+extern inline void android_memory_barrier(void)
 {
     typedef void (kuser_memory_barrier)(void);
     (*(kuser_memory_barrier *)0xffff0fa0)();
 }
-extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void)
+extern inline void android_memory_store_barrier(void)
 {
     android_memory_barrier();
 }
 #endif
 
-extern ANDROID_ATOMIC_INLINE
-int32_t android_atomic_acquire_load(volatile const int32_t *ptr)
+extern inline int32_t android_atomic_acquire_load(volatile const int32_t *ptr)
 {
     int32_t value = *ptr;
     android_memory_barrier();
     return value;
 }
 
-extern ANDROID_ATOMIC_INLINE
-int32_t android_atomic_release_load(volatile const int32_t *ptr)
+extern inline int32_t android_atomic_release_load(volatile const int32_t *ptr)
 {
     android_memory_barrier();
     return *ptr;
 }
 
-extern ANDROID_ATOMIC_INLINE void
-android_atomic_acquire_store(int32_t value, volatile int32_t *ptr)
+extern inline void android_atomic_acquire_store(int32_t value,
+                                                volatile int32_t *ptr)
 {
     *ptr = value;
     android_memory_barrier();
 }
 
-extern ANDROID_ATOMIC_INLINE void
-android_atomic_release_store(int32_t value, volatile int32_t *ptr)
+extern inline void android_atomic_release_store(int32_t value,
+                                                volatile int32_t *ptr)
 {
     android_memory_barrier();
     *ptr = value;
@@ -101,8 +95,8 @@
 extern int android_atomic_cas(int32_t old_value, int32_t new_value,
                               volatile int32_t *ptr);
 #elif defined(__ARM_HAVE_LDREX_STREX)
-extern ANDROID_ATOMIC_INLINE int
-android_atomic_cas(int32_t old_value, int32_t new_value, volatile int32_t *ptr)
+extern inline int android_atomic_cas(int32_t old_value, int32_t new_value,
+                                     volatile int32_t *ptr)
 {
     int32_t prev, status;
     do {
@@ -117,8 +111,8 @@
     return prev != old_value;
 }
 #else
-extern ANDROID_ATOMIC_INLINE int
-android_atomic_cas(int32_t old_value, int32_t new_value, volatile int32_t *ptr)
+extern inline int android_atomic_cas(int32_t old_value, int32_t new_value,
+                                     volatile int32_t *ptr)
 {
     typedef int (kuser_cmpxchg)(int32_t, int32_t, volatile int32_t *);
     int32_t prev, status;
@@ -133,20 +127,18 @@
 }
 #endif
 
-extern ANDROID_ATOMIC_INLINE int
-android_atomic_acquire_cas(int32_t old_value,
-                           int32_t new_value,
-                           volatile int32_t *ptr)
+extern inline int android_atomic_acquire_cas(int32_t old_value,
+                                             int32_t new_value,
+                                             volatile int32_t *ptr)
 {
     int status = android_atomic_cas(old_value, new_value, ptr);
     android_memory_barrier();
     return status;
 }
 
-extern ANDROID_ATOMIC_INLINE int
-android_atomic_release_cas(int32_t old_value,
-                           int32_t new_value,
-                           volatile int32_t *ptr)
+extern inline int android_atomic_release_cas(int32_t old_value,
+                                             int32_t new_value,
+                                             volatile int32_t *ptr)
 {
     android_memory_barrier();
     return android_atomic_cas(old_value, new_value, ptr);
@@ -157,8 +149,8 @@
 extern int32_t android_atomic_add(int32_t increment,
                                   volatile int32_t *ptr);
 #elif defined(__ARM_HAVE_LDREX_STREX)
-extern ANDROID_ATOMIC_INLINE int32_t
-android_atomic_add(int32_t increment, volatile int32_t *ptr)
+extern inline int32_t android_atomic_add(int32_t increment,
+                                         volatile int32_t *ptr)
 {
     int32_t prev, tmp, status;
     android_memory_barrier();
@@ -174,8 +166,8 @@
     return prev;
 }
 #else
-extern ANDROID_ATOMIC_INLINE int32_t
-android_atomic_add(int32_t increment, volatile int32_t *ptr)
+extern inline int32_t android_atomic_add(int32_t increment,
+                                         volatile int32_t *ptr)
 {
     int32_t prev, status;
     android_memory_barrier();
@@ -187,12 +179,12 @@
 }
 #endif
 
-extern ANDROID_ATOMIC_INLINE int32_t android_atomic_inc(volatile int32_t *addr)
+extern inline int32_t android_atomic_inc(volatile int32_t *addr)
 {
     return android_atomic_add(1, addr);
 }
 
-extern ANDROID_ATOMIC_INLINE int32_t android_atomic_dec(volatile int32_t *addr)
+extern inline int32_t android_atomic_dec(volatile int32_t *addr)
 {
     return android_atomic_add(-1, addr);
 }
@@ -200,8 +192,7 @@
 #if defined(__thumb__)
 extern int32_t android_atomic_and(int32_t value, volatile int32_t *ptr);
 #elif defined(__ARM_HAVE_LDREX_STREX)
-extern ANDROID_ATOMIC_INLINE int32_t
-android_atomic_and(int32_t value, volatile int32_t *ptr)
+extern inline int32_t android_atomic_and(int32_t value, volatile int32_t *ptr)
 {
     int32_t prev, tmp, status;
     android_memory_barrier();
@@ -217,8 +208,7 @@
     return prev;
 }
 #else
-extern ANDROID_ATOMIC_INLINE int32_t
-android_atomic_and(int32_t value, volatile int32_t *ptr)
+extern inline int32_t android_atomic_and(int32_t value, volatile int32_t *ptr)
 {
     int32_t prev, status;
     android_memory_barrier();
@@ -233,8 +223,7 @@
 #if defined(__thumb__)
 extern int32_t android_atomic_or(int32_t value, volatile int32_t *ptr);
 #elif defined(__ARM_HAVE_LDREX_STREX)
-extern ANDROID_ATOMIC_INLINE int32_t
-android_atomic_or(int32_t value, volatile int32_t *ptr)
+extern inline int32_t android_atomic_or(int32_t value, volatile int32_t *ptr)
 {
     int32_t prev, tmp, status;
     android_memory_barrier();
@@ -250,8 +239,7 @@
     return prev;
 }
 #else
-extern ANDROID_ATOMIC_INLINE int32_t
-android_atomic_or(int32_t value, volatile int32_t *ptr)
+extern inline int32_t android_atomic_or(int32_t value, volatile int32_t *ptr)
 {
     int32_t prev, status;
     android_memory_barrier();
diff --git a/include/cutils/atomic-mips.h b/include/cutils/atomic-mips.h
index f9d3e25..49144a3 100644
--- a/include/cutils/atomic-mips.h
+++ b/include/cutils/atomic-mips.h
@@ -19,66 +19,60 @@
 
 #include <stdint.h>
 
-#ifndef ANDROID_ATOMIC_INLINE
-#define ANDROID_ATOMIC_INLINE inline __attribute__((always_inline))
-#endif
-
-extern ANDROID_ATOMIC_INLINE void android_compiler_barrier(void)
+extern inline void android_compiler_barrier(void)
 {
     __asm__ __volatile__ ("" : : : "memory");
 }
 
 #if ANDROID_SMP == 0
-extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void)
+extern inline void android_memory_barrier(void)
 {
     android_compiler_barrier();
 }
-extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void)
+extern inline void android_memory_store_barrier(void)
 {
     android_compiler_barrier();
 }
 #else
-extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void)
+extern inline void android_memory_barrier(void)
 {
     __asm__ __volatile__ ("sync" : : : "memory");
 }
-extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void)
+extern inline void android_memory_store_barrier(void)
 {
     __asm__ __volatile__ ("sync" : : : "memory");
 }
 #endif
 
-extern ANDROID_ATOMIC_INLINE int32_t
-android_atomic_acquire_load(volatile const int32_t *ptr)
+extern inline int32_t android_atomic_acquire_load(volatile const int32_t *ptr)
 {
     int32_t value = *ptr;
     android_memory_barrier();
     return value;
 }
 
-extern ANDROID_ATOMIC_INLINE int32_t
-android_atomic_release_load(volatile const int32_t *ptr)
+extern inline int32_t android_atomic_release_load(volatile const int32_t *ptr)
 {
     android_memory_barrier();
     return *ptr;
 }
 
-extern ANDROID_ATOMIC_INLINE void
-android_atomic_acquire_store(int32_t value, volatile int32_t *ptr)
+extern inline void android_atomic_acquire_store(int32_t value,
+                                                volatile int32_t *ptr)
 {
     *ptr = value;
     android_memory_barrier();
 }
 
-extern ANDROID_ATOMIC_INLINE void
-android_atomic_release_store(int32_t value, volatile int32_t *ptr)
+extern inline void android_atomic_release_store(int32_t value,
+                                                volatile int32_t *ptr)
 {
     android_memory_barrier();
     *ptr = value;
 }
 
-extern ANDROID_ATOMIC_INLINE int
-android_atomic_cas(int32_t old_value, int32_t new_value, volatile int32_t *ptr)
+extern inline int android_atomic_cas(int32_t old_value, int32_t new_value,
+                                     volatile int32_t *ptr)
 {
     int32_t prev, status;
     do {
@@ -96,28 +90,26 @@
     return prev != old_value;
 }
 
-extern ANDROID_ATOMIC_INLINE int
-android_atomic_acquire_cas(int32_t old_value,
-                           int32_t new_value,
-                           volatile int32_t *ptr)
+extern inline int android_atomic_acquire_cas(int32_t old_value,
+                                             int32_t new_value,
+                                             volatile int32_t *ptr)
 {
     int status = android_atomic_cas(old_value, new_value, ptr);
     android_memory_barrier();
     return status;
 }
 
-extern ANDROID_ATOMIC_INLINE int
-android_atomic_release_cas(int32_t old_value,
-                           int32_t new_value,
-                           volatile int32_t *ptr)
+extern inline int android_atomic_release_cas(int32_t old_value,
+                                             int32_t new_value,
+                                             volatile int32_t *ptr)
 {
     android_memory_barrier();
     return android_atomic_cas(old_value, new_value, ptr);
 }
 
 
-extern ANDROID_ATOMIC_INLINE int32_t
-android_atomic_swap(int32_t new_value, volatile int32_t *ptr)
+extern inline int32_t android_atomic_swap(int32_t new_value,
+                                          volatile int32_t *ptr)
 {
     int32_t prev, status;
     do {
@@ -133,8 +125,8 @@
     return prev;
 }
 
-extern ANDROID_ATOMIC_INLINE int32_t
-android_atomic_add(int32_t increment, volatile int32_t *ptr)
+extern inline int32_t android_atomic_add(int32_t increment,
+                                         volatile int32_t *ptr)
 {
     int32_t prev, status;
     android_memory_barrier();
@@ -150,20 +142,17 @@
     return prev;
 }
 
-extern ANDROID_ATOMIC_INLINE int32_t
-android_atomic_inc(volatile int32_t *addr)
+extern inline int32_t android_atomic_inc(volatile int32_t *addr)
 {
     return android_atomic_add(1, addr);
 }
 
-extern ANDROID_ATOMIC_INLINE int32_t
-android_atomic_dec(volatile int32_t *addr)
+extern inline int32_t android_atomic_dec(volatile int32_t *addr)
 {
     return android_atomic_add(-1, addr);
 }
 
-extern ANDROID_ATOMIC_INLINE int32_t
-android_atomic_and(int32_t value, volatile int32_t *ptr)
+extern inline int32_t android_atomic_and(int32_t value, volatile int32_t *ptr)
 {
     int32_t prev, status;
     android_memory_barrier();
@@ -179,8 +168,7 @@
     return prev;
 }
 
-extern ANDROID_ATOMIC_INLINE int32_t
-android_atomic_or(int32_t value, volatile int32_t *ptr)
+extern inline int32_t android_atomic_or(int32_t value, volatile int32_t *ptr)
 {
     int32_t prev, status;
     android_memory_barrier();
diff --git a/include/cutils/atomic-x86.h b/include/cutils/atomic-x86.h
index 9480f57..438012e 100644
--- a/include/cutils/atomic-x86.h
+++ b/include/cutils/atomic-x86.h
@@ -19,66 +19,60 @@
 
 #include <stdint.h>
 
-#ifndef ANDROID_ATOMIC_INLINE
-#define ANDROID_ATOMIC_INLINE inline __attribute__((always_inline))
-#endif
-
-extern ANDROID_ATOMIC_INLINE void android_compiler_barrier(void)
+extern inline void android_compiler_barrier(void)
 {
     __asm__ __volatile__ ("" : : : "memory");
 }
 
 #if ANDROID_SMP == 0
-extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void)
+extern inline void android_memory_barrier(void)
 {
     android_compiler_barrier();
 }
-extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void)
+extern inline void android_memory_store_barrier(void)
 {
     android_compiler_barrier();
 }
 #else
-extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void)
+extern inline void android_memory_barrier(void)
 {
     __asm__ __volatile__ ("mfence" : : : "memory");
 }
-extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void)
+extern inline void android_memory_store_barrier(void)
 {
     android_compiler_barrier();
 }
 #endif
 
-extern ANDROID_ATOMIC_INLINE int32_t
-android_atomic_acquire_load(volatile const int32_t *ptr)
+extern inline int32_t android_atomic_acquire_load(volatile const int32_t *ptr)
 {
     int32_t value = *ptr;
     android_compiler_barrier();
     return value;
 }
 
-extern ANDROID_ATOMIC_INLINE int32_t
-android_atomic_release_load(volatile const int32_t *ptr)
+extern inline int32_t android_atomic_release_load(volatile const int32_t *ptr)
 {
     android_memory_barrier();
     return *ptr;
 }
 
-extern ANDROID_ATOMIC_INLINE void
-android_atomic_acquire_store(int32_t value, volatile int32_t *ptr)
+extern inline void android_atomic_acquire_store(int32_t value,
+                                                volatile int32_t *ptr)
 {
     *ptr = value;
     android_memory_barrier();
 }
 
-extern ANDROID_ATOMIC_INLINE void
-android_atomic_release_store(int32_t value, volatile int32_t *ptr)
+extern inline void android_atomic_release_store(int32_t value,
+                                                volatile int32_t *ptr)
 {
     android_compiler_barrier();
     *ptr = value;
 }
 
-extern ANDROID_ATOMIC_INLINE int
-android_atomic_cas(int32_t old_value, int32_t new_value, volatile int32_t *ptr)
+extern inline int android_atomic_cas(int32_t old_value, int32_t new_value,
+                                     volatile int32_t *ptr)
 {
     int32_t prev;
     __asm__ __volatile__ ("lock; cmpxchgl %1, %2"
@@ -88,26 +82,24 @@
     return prev != old_value;
 }
 
-extern ANDROID_ATOMIC_INLINE int
-android_atomic_acquire_cas(int32_t old_value,
-                           int32_t new_value,
-                           volatile int32_t *ptr)
+extern inline int android_atomic_acquire_cas(int32_t old_value,
+                                             int32_t new_value,
+                                             volatile int32_t *ptr)
 {
     /* Loads are not reordered with other loads. */
     return android_atomic_cas(old_value, new_value, ptr);
 }
 
-extern ANDROID_ATOMIC_INLINE int
-android_atomic_release_cas(int32_t old_value,
-                           int32_t new_value,
-                           volatile int32_t *ptr)
+extern inline int android_atomic_release_cas(int32_t old_value,
+                                             int32_t new_value,
+                                             volatile int32_t *ptr)
 {
     /* Stores are not reordered with other stores. */
     return android_atomic_cas(old_value, new_value, ptr);
 }
 
-extern ANDROID_ATOMIC_INLINE int32_t
-android_atomic_add(int32_t increment, volatile int32_t *ptr)
+extern inline int32_t android_atomic_add(int32_t increment,
+                                         volatile int32_t *ptr)
 {
     __asm__ __volatile__ ("lock; xaddl %0, %1"
                           : "+r" (increment), "+m" (*ptr)
@@ -116,20 +108,18 @@
     return increment;
 }
 
-extern ANDROID_ATOMIC_INLINE int32_t
-android_atomic_inc(volatile int32_t *addr)
+extern inline int32_t android_atomic_inc(volatile int32_t *addr)
 {
     return android_atomic_add(1, addr);
 }
 
-extern ANDROID_ATOMIC_INLINE int32_t
-android_atomic_dec(volatile int32_t *addr)
+extern inline int32_t android_atomic_dec(volatile int32_t *addr)
 {
     return android_atomic_add(-1, addr);
 }
 
-extern ANDROID_ATOMIC_INLINE int32_t
-android_atomic_and(int32_t value, volatile int32_t *ptr)
+extern inline int32_t android_atomic_and(int32_t value,
+                                         volatile int32_t *ptr)
 {
     int32_t prev, status;
     do {
@@ -139,8 +129,7 @@
     return prev;
 }
 
-extern ANDROID_ATOMIC_INLINE int32_t
-android_atomic_or(int32_t value, volatile int32_t *ptr)
+extern inline int32_t android_atomic_or(int32_t value, volatile int32_t *ptr)
 {
     int32_t prev, status;
     do {
diff --git a/include/cutils/log.h b/include/cutils/log.h
index 8b045c7..878952e 100644
--- a/include/cutils/log.h
+++ b/include/cutils/log.h
@@ -279,88 +279,7 @@
     : (void)0 )
 #endif
 
-// ---------------------------------------------------------------------
-
-/*
- * Simplified macro to send a verbose radio log message using the current LOG_TAG.
- */
-#ifndef RLOGV
-#if LOG_NDEBUG
-#define RLOGV(...)   ((void)0)
-#else
-#define RLOGV(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
-#endif
-#endif
-
-#define CONDITION(cond)     (__builtin_expect((cond)!=0, 0))
-
-#ifndef RLOGV_IF
-#if LOG_NDEBUG
-#define RLOGV_IF(cond, ...)   ((void)0)
-#else
-#define RLOGV_IF(cond, ...) \
-    ( (CONDITION(cond)) \
-    ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \
-    : (void)0 )
-#endif
-#endif
-
-/*
- * Simplified macro to send a debug radio log message using the current LOG_TAG.
- */
-#ifndef RLOGD
-#define RLOGD(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef RLOGD_IF
-#define RLOGD_IF(cond, ...) \
-    ( (CONDITION(cond)) \
-    ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
-    : (void)0 )
-#endif
-
-/*
- * Simplified macro to send an info radio log message using the current LOG_TAG.
- */
-#ifndef RLOGI
-#define RLOGI(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef RLOGI_IF
-#define RLOGI_IF(cond, ...) \
-    ( (CONDITION(cond)) \
-    ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \
-    : (void)0 )
-#endif
-
-/*
- * Simplified macro to send a warning radio log message using the current LOG_TAG.
- */
-#ifndef RLOGW
-#define RLOGW(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef RLOGW_IF
-#define RLOGW_IF(cond, ...) \
-    ( (CONDITION(cond)) \
-    ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \
-    : (void)0 )
-#endif
-
-/*
- * Simplified macro to send an error radio log message using the current LOG_TAG.
- */
-#ifndef RLOGE
-#define RLOGE(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef RLOGE_IF
-#define RLOGE_IF(cond, ...) \
-    ( (CONDITION(cond)) \
-    ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \
-    : (void)0 )
-#endif
-
+    
 
 // ---------------------------------------------------------------------
 
diff --git a/include/cutils/tztime.h b/include/cutils/tztime.h
index dbdbd60..36ac25d 100644
--- a/include/cutils/tztime.h
+++ b/include/cutils/tztime.h
@@ -17,8 +17,45 @@
 #ifndef _CUTILS_TZTIME_H
 #define _CUTILS_TZTIME_H
 
-// TODO: fix both callers to just include <bionic_time.h> themselves.
+#include <time.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+time_t mktime_tz(struct tm * const tmp, char const * tz);
+void localtime_tz(const time_t * const timep, struct tm * tmp, const char* tz);
+
+#ifdef HAVE_ANDROID_OS
+
+/* the following is defined in the Bionic C library on Android, but the
+ * declarations are only available through a platform-private header
+ */
 #include <bionic_time.h>
 
+#else /* !HAVE_ANDROID_OS */
+
+struct strftime_locale {
+    const char *mon[12];    /* short names */
+    const char *month[12];  /* long names */
+    const char *standalone_month[12];  /* long standalone names */
+    const char *wday[7];    /* short names */
+    const char *weekday[7]; /* long names */
+    const char *X_fmt;
+    const char *x_fmt;
+    const char *c_fmt;
+    const char *am;
+    const char *pm;
+    const char *date_fmt;
+};
+
+size_t strftime_tz(char *s, size_t max, const char *format, const struct tm *tm, const struct strftime_locale *locale);
+
+#endif /* !HAVE_ANDROID_OS */
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* __CUTILS_TZTIME_H */ 
 
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index f90af81..7e34da8 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -62,7 +62,6 @@
 #define AID_DRMRPC        1026  /* group for drm rpc */
 #define AID_NFC           1027  /* nfc subsystem */
 #define AID_SDCARD_R      1028  /* external storage read access */
-#define AID_CLAT          1029  /* clat part of nat464 */
 
 #define AID_SHELL         2000  /* adb and debug shell user */
 #define AID_CACHE         2001  /* cache access */
@@ -140,7 +139,6 @@
     { "net_bw_acct", AID_NET_BW_ACCT, },
     { "misc",      AID_MISC, },
     { "nobody",    AID_NOBODY, },
-    { "clat",      AID_CLAT, },
 };
 
 #define android_id_count \
@@ -236,10 +234,6 @@
     struct fs_path_config *pc;
     int plen;
 
-    if (path[0] == '/') {
-        path++;
-    }
-
     pc = dir ? android_dirs : android_files;
     plen = strlen(path);
     for(; pc->prefix; pc++){
diff --git a/include/sysutils/FrameworkListener.h b/include/sysutils/FrameworkListener.h
index f1a4b43..756bacf 100644
--- a/include/sysutils/FrameworkListener.h
+++ b/include/sysutils/FrameworkListener.h
@@ -23,11 +23,10 @@
 
 class FrameworkListener : public SocketListener {
 public:
-    static const int CMD_ARGS_MAX = 26;
+    static const int CMD_ARGS_MAX = 16;
 
     /* 1 out of errorRate will be dropped */
     int errorRate;
-
 private:
     int mCommandCount;
     bool mWithSeq;
diff --git a/include/usbhost/usbhost.h b/include/usbhost/usbhost.h
index 1d67c12..9a6b59c 100644
--- a/include/usbhost/usbhost.h
+++ b/include/usbhost/usbhost.h
@@ -72,19 +72,6 @@
 /* Call this to cleanup the USB host library. */
 void usb_host_cleanup(struct usb_host_context *context);
 
-/* Call this to get the inotify file descriptor. */
-int usb_host_get_fd(struct usb_host_context *context);
-
-/* Call this to initialize the usb host context. */
-int usb_host_load(struct usb_host_context *context,
-                  usb_device_added_cb added_cb,
-                  usb_device_removed_cb removed_cb,
-                  usb_discovery_done_cb discovery_done_cb,
-                  void *client_data);
-
-/* Call this to read and handle occuring usb event. */
-int usb_host_read_event(struct usb_host_context *context);
-
 /* Call this to monitor the USB bus for new and removed devices.
  * This is intended to be called from a dedicated thread,
  * as it will not return until one of the callbacks returns true.
diff --git a/init/Android.mk b/init/Android.mk
index 00d2144..a1c1e7a 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -33,11 +33,13 @@
 LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
 LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
 
-LOCAL_STATIC_LIBRARIES := \
-	libfs_mgr \
-	libcutils \
-	libc \
-	libselinux
+LOCAL_STATIC_LIBRARIES := libfs_mgr libcutils libc
+
+ifeq ($(HAVE_SELINUX),true)
+LOCAL_STATIC_LIBRARIES += libselinux
+LOCAL_C_INCLUDES += external/libselinux/include
+LOCAL_CFLAGS += -DHAVE_SELINUX
+endif
 
 include $(BUILD_EXECUTABLE)
 
diff --git a/init/builtins.c b/init/builtins.c
index dc7900e..aaf85d9 100644
--- a/init/builtins.c
+++ b/init/builtins.c
@@ -35,8 +35,10 @@
 #include <sys/system_properties.h>
 #include <fs_mgr.h>
 
+#ifdef HAVE_SELINUX
 #include <selinux/selinux.h>
 #include <selinux/label.h>
+#endif
 
 #include "init.h"
 #include "keywords.h"
@@ -513,20 +515,24 @@
 }
 
 int do_setcon(int nargs, char **args) {
+#ifdef HAVE_SELINUX
     if (is_selinux_enabled() <= 0)
         return 0;
     if (setcon(args[1]) < 0) {
         return -errno;
     }
+#endif
     return 0;
 }
 
 int do_setenforce(int nargs, char **args) {
+#ifdef HAVE_SELINUX
     if (is_selinux_enabled() <= 0)
         return 0;
     if (security_setenforce(atoi(args[1])) < 0) {
         return -errno;
     }
+#endif
     return 0;
 }
 
@@ -754,30 +760,36 @@
 }
 
 int do_setsebool(int nargs, char **args) {
-    const char *name = args[1];
-    const char *value = args[2];
-    SELboolean b;
-    int ret;
+#ifdef HAVE_SELINUX
+    SELboolean *b = alloca(nargs * sizeof(SELboolean));
+    char *v;
+    int i;
 
     if (is_selinux_enabled() <= 0)
         return 0;
 
-    b.name = name;
-    if (!strcmp(value, "1") || !strcasecmp(value, "true") || !strcasecmp(value, "on"))
-        b.value = 1;
-    else if (!strcmp(value, "0") || !strcasecmp(value, "false") || !strcasecmp(value, "off"))
-        b.value = 0;
-    else {
-        ERROR("setsebool: invalid value %s\n", value);
-        return -EINVAL;
+    for (i = 1; i < nargs; i++) {
+        char *name = args[i];
+        v = strchr(name, '=');
+        if (!v) {
+            ERROR("setsebool: argument %s had no =\n", name);
+            return -EINVAL;
+        }
+        *v++ = 0;
+        b[i-1].name = name;
+        if (!strcmp(v, "1") || !strcasecmp(v, "true") || !strcasecmp(v, "on"))
+            b[i-1].value = 1;
+        else if (!strcmp(v, "0") || !strcasecmp(v, "false") || !strcasecmp(v, "off"))
+            b[i-1].value = 0;
+        else {
+            ERROR("setsebool: invalid value %s\n", v);
+            return -EINVAL;
+        }
     }
 
-    if (security_set_boolean_list(1, &b, 0) < 0) {
-        ret = -errno;
-        ERROR("setsebool: could not set %s to %s\n", name, value);
-        return ret;
-    }
-
+    if (security_set_boolean_list(nargs - 1, b, 0) < 0)
+        return -errno;
+#endif
     return 0;
 }
 
diff --git a/init/devices.c b/init/devices.c
index b07a1a6..c30303f 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -30,9 +30,11 @@
 #include <sys/un.h>
 #include <linux/netlink.h>
 
+#ifdef HAVE_SELINUX
 #include <selinux/selinux.h>
 #include <selinux/label.h>
 #include <selinux/android.h>
+#endif
 
 #include <private/android_filesystem_config.h>
 #include <sys/time.h>
@@ -51,7 +53,9 @@
 #define FIRMWARE_DIR2   "/vendor/firmware"
 #define FIRMWARE_DIR3   "/firmware/image"
 
+#ifdef HAVE_SELINUX
 extern struct selabel_handle *sehandle;
+#endif
 
 static int device_fd = -1;
 
@@ -189,15 +193,17 @@
     unsigned gid;
     mode_t mode;
     dev_t dev;
+#ifdef HAVE_SELINUX
     char *secontext = NULL;
+#endif
 
     mode = get_device_perm(path, &uid, &gid) | (block ? S_IFBLK : S_IFCHR);
-
+#ifdef HAVE_SELINUX
     if (sehandle) {
         selabel_lookup(sehandle, &secontext, path, mode);
         setfscreatecon(secontext);
     }
-
+#endif
     dev = makedev(major, minor);
     /* Temporarily change egid to avoid race condition setting the gid of the
      * device node. Unforunately changing the euid would prevent creation of
@@ -208,11 +214,12 @@
     mknod(path, mode, dev);
     chown(path, uid, -1);
     setegid(AID_ROOT);
-
+#ifdef HAVE_SELINUX
     if (secontext) {
         freecon(secontext);
         setfscreatecon(NULL);
     }
+#endif
 }
 
 static void add_platform_device(const char *name)
@@ -875,14 +882,14 @@
     suseconds_t t0, t1;
     struct stat info;
     int fd;
-
+#ifdef HAVE_SELINUX
     sehandle = NULL;
     if (is_selinux_enabled() > 0) {
         sehandle = selinux_android_file_context_handle();
     }
-
-    /* is 256K enough? udev uses 16MB! */
-    device_fd = uevent_open_socket(256*1024, true);
+#endif
+    /* is 64K enough? udev uses 16MB! */
+    device_fd = uevent_open_socket(64*1024, true);
     if(device_fd < 0)
         return;
 
diff --git a/init/init.c b/init/init.c
index b20b434..1c80d9c 100755
--- a/init/init.c
+++ b/init/init.c
@@ -33,9 +33,11 @@
 #include <sys/un.h>
 #include <sys/personality.h>
 
+#ifdef HAVE_SELINUX
 #include <selinux/selinux.h>
 #include <selinux/label.h>
 #include <selinux/android.h>
+#endif
 
 #include <libgen.h>
 
@@ -59,8 +61,10 @@
 #include "ueventd.h"
 #include "watchdogd.h"
 
+#ifdef HAVE_SELINUX
 struct selabel_handle *sehandle;
 struct selabel_handle *sehandle_prop;
+#endif
 
 static int property_triggers_enabled = 0;
 
@@ -74,7 +78,9 @@
 static unsigned revision = 0;
 static char qemu[32];
 
+#ifdef HAVE_SELINUX
 static int selinux_enabled = 1;
+#endif
 
 static struct action *cur_action = NULL;
 static struct command *cur_command = NULL;
@@ -158,9 +164,10 @@
     pid_t pid;
     int needs_console;
     int n;
+#ifdef HAVE_SELINUX
     char *scon = NULL;
     int rc;
-
+#endif
         /* starting a service removes it from the disabled or reset
          * state and immediately takes it out of the restarting
          * state if it was in there
@@ -197,6 +204,7 @@
         return;
     }
 
+#ifdef HAVE_SELINUX
     if (is_selinux_enabled() > 0) {
         char *mycon = NULL, *fcon = NULL;
 
@@ -222,6 +230,7 @@
             return;
         }
     }
+#endif
 
     NOTICE("starting '%s'\n", svc->name);
 
@@ -258,7 +267,9 @@
         for (ei = svc->envvars; ei; ei = ei->next)
             add_environment(ei->name, ei->value);
 
+#ifdef HAVE_SELINUX
         setsockcreatecon(scon);
+#endif
 
         for (si = svc->sockets; si; si = si->next) {
             int socket_type = (
@@ -271,9 +282,11 @@
             }
         }
 
+#ifdef HAVE_SELINUX
         freecon(scon);
         scon = NULL;
         setsockcreatecon(NULL);
+#endif
 
         if (svc->ioprio_class != IoSchedClass_NONE) {
             if (android_set_ioprio(getpid(), svc->ioprio_class, svc->ioprio_pri)) {
@@ -319,12 +332,15 @@
                 _exit(127);
             }
         }
+
+#ifdef HAVE_SELINUX
         if (svc->seclabel) {
             if (is_selinux_enabled() > 0 && setexeccon(svc->seclabel) < 0) {
                 ERROR("cannot setexeccon('%s'): %s\n", svc->seclabel, strerror(errno));
                 _exit(127);
             }
         }
+#endif
 
         if (!dynamic_args) {
             if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) {
@@ -351,7 +367,9 @@
         _exit(127);
     }
 
+#ifdef HAVE_SELINUX
     freecon(scon);
+#endif
 
     if (pid < 0) {
         ERROR("failed to start '%s'\n", svc->name);
@@ -602,9 +620,11 @@
     *value++ = 0;
     if (name_len == 0) return;
 
+#ifdef HAVE_SELINUX
     if (!strcmp(name,"selinux")) {
         selinux_enabled = atoi(value);
     }
+#endif
 
     if (for_emulator) {
         /* in the emulator, export any kernel option with the
@@ -752,6 +772,7 @@
 }
 #endif
 
+#ifdef HAVE_SELINUX
 static const struct selinux_opt seopts_prop[] = {
         { SELABEL_OPT_PATH, "/data/system/property_contexts" },
         { SELABEL_OPT_PATH, "/property_contexts" },
@@ -810,6 +831,8 @@
     return 0;
 }
 
+#endif
+
 int main(int argc, char **argv)
 {
     int fd_count = 0;
@@ -863,6 +886,7 @@
 
     process_kernel_cmdline();
 
+#ifdef HAVE_SELINUX
     union selinux_callback cb;
     cb.func_log = klog_write;
     selinux_set_callback(SELINUX_CB_LOG, cb);
@@ -887,6 +911,7 @@
      */
     restorecon("/dev");
     restorecon("/dev/socket");
+#endif
 
     is_charger = !strcmp(bootmode, "charger");
 
diff --git a/init/init.h b/init/init.h
index 955e1f0..b7e06c9 100644
--- a/init/init.h
+++ b/init/init.h
@@ -95,7 +95,9 @@
     gid_t supp_gids[NR_SVC_SUPP_GIDS];
     size_t nr_supp_gids;
 
+#ifdef HAVE_SELINUX
     char *seclabel;
+#endif
 
     struct socketinfo *sockets;
     struct svcenvinfo *envvars;
@@ -134,8 +136,10 @@
 
 int load_565rle_image( char *file_name );
 
+#ifdef HAVE_SELINUX
 extern struct selabel_handle *sehandle;
 extern struct selabel_handle *sehandle_prop;
 extern int selinux_reload_policy(void);
+#endif
 
 #endif	/* _INIT_INIT_H */
diff --git a/init/init_parser.c b/init/init_parser.c
index beb9188..5393e52 100644
--- a/init/init_parser.c
+++ b/init/init_parser.c
@@ -799,11 +799,13 @@
         }
         break;
     case K_seclabel:
+#ifdef HAVE_SELINUX
         if (nargs != 2) {
             parse_error(state, "seclabel option requires a label string\n");
         } else {
             svc->seclabel = args[1];
         }
+#endif
         break;
 
     default:
diff --git a/init/keywords.h b/init/keywords.h
index f188db5..97d4950 100644
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -78,7 +78,7 @@
     KEYWORD(setkey,      COMMAND, 0, do_setkey)
     KEYWORD(setprop,     COMMAND, 2, do_setprop)
     KEYWORD(setrlimit,   COMMAND, 3, do_setrlimit)
-    KEYWORD(setsebool,   COMMAND, 2, do_setsebool)
+    KEYWORD(setsebool,   COMMAND, 1, do_setsebool)
     KEYWORD(socket,      OPTION,  0, 0)
     KEYWORD(start,       COMMAND, 1, do_start)
     KEYWORD(stop,        COMMAND, 1, do_stop)
diff --git a/init/property_service.c b/init/property_service.c
index 61dd86f..f58e07d 100755
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -40,8 +40,10 @@
 #include <sys/atomics.h>
 #include <private/android_filesystem_config.h>
 
+#ifdef HAVE_SELINUX
 #include <selinux/selinux.h>
 #include <selinux/label.h>
+#endif
 
 #include "property_service.h"
 #include "init.h"
@@ -123,7 +125,7 @@
         /* dev is a tmpfs that we can use to carve a shared workspace
          * out of, so let's do that...
          */
-    fd = open("/dev/__properties__", O_RDWR | O_CREAT | O_NOFOLLOW, 0600);
+    fd = open("/dev/__properties__", O_RDWR | O_CREAT, 0600);
     if (fd < 0)
         return -1;
 
@@ -136,7 +138,7 @@
 
     close(fd);
 
-    fd = open("/dev/__properties__", O_RDONLY | O_NOFOLLOW);
+    fd = open("/dev/__properties__", O_RDONLY);
     if (fd < 0)
         return -1;
 
@@ -199,6 +201,7 @@
 
 static int check_mac_perms(const char *name, char *sctx)
 {
+#ifdef HAVE_SELINUX
     if (is_selinux_enabled() <= 0)
         return 1;
 
@@ -222,10 +225,15 @@
     freecon(tctx);
  err:
     return result;
+
+#endif
+    return 1;
 }
 
 static int check_control_mac_perms(const char *name, char *sctx)
 {
+#ifdef HAVE_SELINUX
+
     /*
      *  Create a name prefix out of ctl.<service name>
      *  The new prefix allows the use of the existing
@@ -239,6 +247,9 @@
         return 0;
 
     return check_mac_perms(ctl_name, sctx);
+
+#endif
+    return 1;
 }
 
 /*
@@ -309,12 +320,13 @@
 
 static void write_persistent_property(const char *name, const char *value)
 {
-    char tempPath[PATH_MAX];
+    const char *tempPath = PERSISTENT_PROPERTY_DIR "/.temp";
     char path[PATH_MAX];
-    int fd;
+    int fd, length;
 
-    snprintf(tempPath, sizeof(tempPath), "%s/.temp.XXXXXX", PERSISTENT_PROPERTY_DIR);
-    fd = mkstemp(tempPath);
+    snprintf(path, sizeof(path), "%s/%s", PERSISTENT_PROPERTY_DIR, name);
+
+    fd = open(tempPath, O_WRONLY|O_CREAT|O_TRUNC, 0600);
     if (fd < 0) {
         ERROR("Unable to write persistent property to temp file %s errno: %d\n", tempPath, errno);
         return;
@@ -322,7 +334,6 @@
     write(fd, value, strlen(value));
     close(fd);
 
-    snprintf(path, sizeof(path), "%s/%s", PERSISTENT_PROPERTY_DIR, name);
     if (rename(tempPath, path)) {
         unlink(tempPath);
         ERROR("Unable to rename persistent property file %s to %s\n", tempPath, path);
@@ -334,8 +345,8 @@
     prop_area *pa;
     prop_info *pi;
 
-    size_t namelen = strlen(name);
-    size_t valuelen = strlen(value);
+    int namelen = strlen(name);
+    int valuelen = strlen(value);
 
     if(namelen >= PROP_NAME_MAX) return -1;
     if(valuelen >= PROP_VALUE_MAX) return -1;
@@ -385,9 +396,11 @@
          * to prevent them from being overwritten by default values.
          */
         write_persistent_property(name, value);
+#ifdef HAVE_SELINUX
     } else if (strcmp("selinux.reload_policy", name) == 0 &&
                strcmp("1", value) == 0) {
         selinux_reload_policy();
+#endif
     }
     property_changed(name, value);
     return 0;
@@ -412,13 +425,13 @@
     /* Check socket options here */
     if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) {
         close(s);
-        ERROR("Unable to receive socket options\n");
+        ERROR("Unable to recieve socket options\n");
         return;
     }
 
     r = TEMP_FAILURE_RETRY(recv(s, &msg, sizeof(msg), 0));
     if(r != sizeof(prop_msg)) {
-        ERROR("sys_prop: mis-match msg size received: %d expected: %d errno: %d\n",
+        ERROR("sys_prop: mis-match msg size recieved: %d expected: %d errno: %d\n",
               r, sizeof(prop_msg), errno);
         close(s);
         return;
@@ -429,7 +442,9 @@
         msg.name[PROP_NAME_MAX-1] = 0;
         msg.value[PROP_VALUE_MAX-1] = 0;
 
+#ifdef HAVE_SELINUX
         getpeercon(s, &source_ctx);
+#endif
 
         if(memcmp(msg.name,"ctl.",4) == 0) {
             // Keep the old close-socket-early behavior when handling
@@ -454,7 +469,10 @@
             // the property is written to memory.
             close(s);
         }
+#ifdef HAVE_SELINUX
         freecon(source_ctx);
+#endif
+
         break;
 
     default:
@@ -512,14 +530,12 @@
 static void load_persistent_properties()
 {
     DIR* dir = opendir(PERSISTENT_PROPERTY_DIR);
-    int dir_fd;
     struct dirent*  entry;
+    char path[PATH_MAX];
     char value[PROP_VALUE_MAX];
     int fd, length;
-    struct stat sb;
 
     if (dir) {
-        dir_fd = dirfd(dir);
         while ((entry = readdir(dir)) != NULL) {
             if (strncmp("persist.", entry->d_name, strlen("persist.")))
                 continue;
@@ -528,39 +544,20 @@
                 continue;
 #endif
             /* open the file and read the property value */
-            fd = openat(dir_fd, entry->d_name, O_RDONLY | O_NOFOLLOW);
-            if (fd < 0) {
-                ERROR("Unable to open persistent property file \"%s\" errno: %d\n",
-                      entry->d_name, errno);
-                continue;
-            }
-            if (fstat(fd, &sb) < 0) {
-                ERROR("fstat on property file \"%s\" failed errno: %d\n", entry->d_name, errno);
+            snprintf(path, sizeof(path), "%s/%s", PERSISTENT_PROPERTY_DIR, entry->d_name);
+            fd = open(path, O_RDONLY);
+            if (fd >= 0) {
+                length = read(fd, value, sizeof(value) - 1);
+                if (length >= 0) {
+                    value[length] = 0;
+                    property_set(entry->d_name, value);
+                } else {
+                    ERROR("Unable to read persistent property file %s errno: %d\n", path, errno);
+                }
                 close(fd);
-                continue;
-            }
-
-            // File must not be accessible to others, be owned by root/root, and
-            // not be a hard link to any other file.
-            if (((sb.st_mode & (S_IRWXG | S_IRWXO)) != 0)
-                    || (sb.st_uid != 0)
-                    || (sb.st_gid != 0)
-                    || (sb.st_nlink != 1)) {
-                ERROR("skipping insecure property file %s (uid=%lu gid=%lu nlink=%d mode=%o)\n",
-                      entry->d_name, sb.st_uid, sb.st_gid, sb.st_nlink, sb.st_mode);
-                close(fd);
-                continue;
-            }
-
-            length = read(fd, value, sizeof(value) - 1);
-            if (length >= 0) {
-                value[length] = 0;
-                property_set(entry->d_name, value);
             } else {
-                ERROR("Unable to read persistent property file %s errno: %d\n",
-                      entry->d_name, errno);
+                ERROR("Unable to open persistent property file %s errno: %d\n", path, errno);
             }
-            close(fd);
         }
         closedir(dir);
     } else {
diff --git a/init/readme.txt b/init/readme.txt
index 7a5997d..fe0d15d 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -88,13 +88,6 @@
    supplemental groups of the process (via setgroups()).
    Currently defaults to root.  (??? probably should default to nobody)
 
-seclabel <securitycontext>
-  Change to securitycontext before exec'ing this service.
-  Primarily for use by services run from the rootfs, e.g. ueventd, adbd.
-  Services on the system partition can instead use policy-defined transitions
-  based on their file security context.
-  If not specified and no transition is defined in policy, defaults to the init context.
-
 oneshot
    Do not restart the service when it exits.
 
@@ -189,21 +182,6 @@
    device by name.
    <mountoption>s include "ro", "rw", "remount", "noatime", ...
 
-restorecon <path>
-   Restore the file named by <path> to the security context specified
-   in the file_contexts configuration.
-   Not required for directories created by the init.rc as these are
-   automatically labeled correctly by init.
-
-setcon <securitycontext>
-   Set the current process security context to the specified string.
-   This is typically only used from early-init to set the init context
-   before any other process is started.
-
-setenforce 0|1
-   Set the SELinux system-wide enforcing status.
-   0 is permissive (i.e. log but do not deny), 1 is enforcing.
-
 setkey
    TBD
 
@@ -213,10 +191,6 @@
 setrlimit <resource> <cur> <max>
    Set the rlimit for a resource.
 
-setsebool <name> <value>
-   Set SELinux boolean <name> to <value>.
-   <value> may be 1|true|on or 0|false|off
-
 start <service>
    Start a service running if it is not already running.
 
diff --git a/init/util.c b/init/util.c
index 918bc05..743748b 100755
--- a/init/util.c
+++ b/init/util.c
@@ -23,7 +23,9 @@
 #include <errno.h>
 #include <time.h>
 
+#ifdef HAVE_SELINUX
 #include <selinux/label.h>
+#endif
 
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -87,7 +89,9 @@
 {
     struct sockaddr_un addr;
     int fd, ret;
+#ifdef HAVE_SELINUX
     char *secon;
+#endif
 
     fd = socket(PF_UNIX, type, 0);
     if (fd < 0) {
@@ -106,12 +110,14 @@
         goto out_close;
     }
 
+#ifdef HAVE_SELINUX
     secon = NULL;
     if (sehandle) {
         ret = selabel_lookup(sehandle, &secon, addr.sun_path, S_IFSOCK);
         if (ret == 0)
             setfscreatecon(secon);
     }
+#endif
 
     ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr));
     if (ret) {
@@ -119,8 +125,10 @@
         goto out_unlink;
     }
 
+#ifdef HAVE_SELINUX
     setfscreatecon(NULL);
     freecon(secon);
+#endif
 
     chown(addr.sun_path, uid, gid);
     chmod(addr.sun_path, perm);
@@ -460,27 +468,31 @@
 {
     int rc;
 
+#ifdef HAVE_SELINUX
     char *secontext = NULL;
 
     if (sehandle) {
         selabel_lookup(sehandle, &secontext, path, mode);
         setfscreatecon(secontext);
     }
+#endif
 
     rc = mkdir(path, mode);
 
+#ifdef HAVE_SELINUX
     if (secontext) {
         int save_errno = errno;
         freecon(secontext);
         setfscreatecon(NULL);
         errno = save_errno;
     }
-
+#endif
     return rc;
 }
 
 int restorecon(const char *pathname)
 {
+#ifdef HAVE_SELINUX
     char *secontext = NULL;
     struct stat sb;
     int i;
@@ -497,5 +509,6 @@
         return -errno;
     }
     freecon(secontext);
+#endif
     return 0;
 }
diff --git a/libcorkscrew/arch-arm/ptrace-arm.c b/libcorkscrew/arch-arm/ptrace-arm.c
index 78a9ea9..868230c 100644
--- a/libcorkscrew/arch-arm/ptrace-arm.c
+++ b/libcorkscrew/arch-arm/ptrace-arm.c
@@ -29,15 +29,12 @@
 static void load_exidx_header(pid_t pid, map_info_t* mi,
         uintptr_t* out_exidx_start, size_t* out_exidx_size) {
     uint32_t elf_phoff;
-    uint32_t elf_phentsize_ehsize;
-    uint32_t elf_shentsize_phnum;
+    uint32_t elf_phentsize_phnum;
     if (try_get_word_ptrace(pid, mi->start + offsetof(Elf32_Ehdr, e_phoff), &elf_phoff)
-            && try_get_word_ptrace(pid, mi->start + offsetof(Elf32_Ehdr, e_ehsize),
-                    &elf_phentsize_ehsize)
             && try_get_word_ptrace(pid, mi->start + offsetof(Elf32_Ehdr, e_phnum),
-                    &elf_shentsize_phnum)) {
-        uint32_t elf_phentsize = elf_phentsize_ehsize >> 16;
-        uint32_t elf_phnum = elf_shentsize_phnum & 0xffff;
+                    &elf_phentsize_phnum)) {
+        uint32_t elf_phentsize = elf_phentsize_phnum >> 16;
+        uint32_t elf_phnum = elf_phentsize_phnum & 0xffff;
         for (uint32_t i = 0; i < elf_phnum; i++) {
             uintptr_t elf_phdr = mi->start + elf_phoff + i * elf_phentsize;
             uint32_t elf_phdr_type;
diff --git a/libcorkscrew/map_info.c b/libcorkscrew/map_info.c
index 6a27664..3c52854 100644
--- a/libcorkscrew/map_info.c
+++ b/libcorkscrew/map_info.c
@@ -57,15 +57,13 @@
         mi->start = start;
         mi->end = end;
         mi->is_readable = strlen(permissions) == 4 && permissions[0] == 'r';
-        mi->is_writable = strlen(permissions) == 4 && permissions[1] == 'w';
         mi->is_executable = strlen(permissions) == 4 && permissions[2] == 'x';
         mi->data = NULL;
         memcpy(mi->name, name, name_len);
         mi->name[name_len] = '\0';
         ALOGV("Parsed map: start=0x%08x, end=0x%08x, "
-                "is_readable=%d, is_writable=%d, is_executable=%d, name=%s",
-                mi->start, mi->end,
-                mi->is_readable, mi->is_writable, mi->is_executable, mi->name);
+                "is_readable=%d, is_executable=%d, name=%s",
+                mi->start, mi->end, mi->is_readable, mi->is_executable, mi->name);
     }
     return mi;
 }
@@ -112,11 +110,6 @@
     return mi && mi->is_readable;
 }
 
-bool is_writable_map(const map_info_t* milist, uintptr_t addr) {
-    const map_info_t* mi = find_map_info(milist, addr);
-    return mi && mi->is_writable;
-}
-
 bool is_executable_map(const map_info_t* milist, uintptr_t addr) {
     const map_info_t* mi = find_map_info(milist, addr);
     return mi && mi->is_executable;
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index fc6d08d..d9bd8d8 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -77,8 +77,12 @@
         abort_socket.c \
         fs.c \
         selector.c \
+        tztime.c \
         multiuser.c \
         zygote.c
+
+    commonHostSources += \
+        tzstrftime.c
 endif
 
 
diff --git a/libcutils/atomic.c b/libcutils/atomic.c
index 1484ef8..f6cd8b0 100644
--- a/libcutils/atomic.c
+++ b/libcutils/atomic.c
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-#define ANDROID_ATOMIC_INLINE
+#define inline
 
 #include <cutils/atomic-inline.h>
diff --git a/libcutils/private.h b/libcutils/private.h
new file mode 100644
index 0000000..2837b70
--- /dev/null
+++ b/libcutils/private.h
@@ -0,0 +1,368 @@
+#ifndef PRIVATE_H
+
+#define PRIVATE_H
+
+/*
+** This file is in the public domain, so clarified as of
+** 1996-06-05 by Arthur David Olson.
+*/
+
+/*
+** This header is for use ONLY with the time conversion code.
+** There is no guarantee that it will remain unchanged,
+** or that it will remain at all.
+** Do NOT copy it to any system include directory.
+** Thank you!
+*/
+
+/*
+** ID
+*/
+
+#ifndef lint
+#ifndef NOID
+static char	privatehid[] = "@(#)private.h	8.2";
+#endif /* !defined NOID */
+#endif /* !defined lint */
+
+#define GRANDPARENTED	"Local time zone must be set--see zic manual page"
+
+/*
+** Defaults for preprocessor symbols.
+** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'.
+*/
+
+#ifndef HAVE_ADJTIME
+#define HAVE_ADJTIME		1
+#endif /* !defined HAVE_ADJTIME */
+
+#ifndef HAVE_GETTEXT
+#define HAVE_GETTEXT		0
+#endif /* !defined HAVE_GETTEXT */
+
+#ifndef HAVE_INCOMPATIBLE_CTIME_R
+#define HAVE_INCOMPATIBLE_CTIME_R	0
+#endif /* !defined INCOMPATIBLE_CTIME_R */
+
+#ifndef HAVE_SETTIMEOFDAY
+#define HAVE_SETTIMEOFDAY	3
+#endif /* !defined HAVE_SETTIMEOFDAY */
+
+#ifndef HAVE_STRERROR
+#define HAVE_STRERROR		1
+#endif /* !defined HAVE_STRERROR */
+
+#ifndef HAVE_SYMLINK
+#define HAVE_SYMLINK		1
+#endif /* !defined HAVE_SYMLINK */
+
+#ifndef HAVE_SYS_STAT_H
+#define HAVE_SYS_STAT_H		1
+#endif /* !defined HAVE_SYS_STAT_H */
+
+#ifndef HAVE_SYS_WAIT_H
+#define HAVE_SYS_WAIT_H		1
+#endif /* !defined HAVE_SYS_WAIT_H */
+
+#ifndef HAVE_UNISTD_H
+#define HAVE_UNISTD_H		1
+#endif /* !defined HAVE_UNISTD_H */
+
+#ifndef HAVE_UTMPX_H
+#define HAVE_UTMPX_H		0
+#endif /* !defined HAVE_UTMPX_H */
+
+#ifndef LOCALE_HOME
+#define LOCALE_HOME		"/usr/lib/locale"
+#endif /* !defined LOCALE_HOME */
+
+#if HAVE_INCOMPATIBLE_CTIME_R
+#define asctime_r _incompatible_asctime_r
+#define ctime_r _incompatible_ctime_r
+#endif /* HAVE_INCOMPATIBLE_CTIME_R */
+
+/*
+** Nested includes
+*/
+
+#include "sys/types.h"	/* for time_t */
+#include "stdio.h"
+#include "errno.h"
+#include "string.h"
+#include "limits.h"	/* for CHAR_BIT et al. */
+#include "time.h"
+#include "stdlib.h"
+
+#if HAVE_GETTEXT
+#include "libintl.h"
+#endif /* HAVE_GETTEXT */
+
+#if HAVE_SYS_WAIT_H
+#include <sys/wait.h>	/* for WIFEXITED and WEXITSTATUS */
+#endif /* HAVE_SYS_WAIT_H */
+
+#ifndef WIFEXITED
+#define WIFEXITED(status)	(((status) & 0xff) == 0)
+#endif /* !defined WIFEXITED */
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(status)	(((status) >> 8) & 0xff)
+#endif /* !defined WEXITSTATUS */
+
+#if HAVE_UNISTD_H
+#include "unistd.h"	/* for F_OK and R_OK */
+#endif /* HAVE_UNISTD_H */
+
+#if !HAVE_UNISTD_H
+#ifndef F_OK
+#define F_OK	0
+#endif /* !defined F_OK */
+#ifndef R_OK
+#define R_OK	4
+#endif /* !defined R_OK */
+#endif /* !HAVE_UNISTD_H */
+
+/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
+#define is_digit(c) ((unsigned)(c) - '0' <= 9)
+
+/*
+** Define HAVE_STDINT_H's default value here, rather than at the
+** start, since __GLIBC__'s value depends on previously-included
+** files.
+** (glibc 2.1 and later have stdint.h, even with pre-C99 compilers.)
+*/
+#ifndef HAVE_STDINT_H
+#define HAVE_STDINT_H \
+	(199901 <= __STDC_VERSION__ || \
+	2 < (__GLIBC__ + (0 < __GLIBC_MINOR__)))
+#endif /* !defined HAVE_STDINT_H */
+
+#if HAVE_STDINT_H
+#include "stdint.h"
+#endif /* !HAVE_STDINT_H */
+
+#ifndef INT_FAST64_MAX
+/* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX.  */
+#if defined LLONG_MAX || defined __LONG_LONG_MAX__
+typedef long long	int_fast64_t;
+#else /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
+#if (LONG_MAX >> 31) < 0xffffffff
+Please use a compiler that supports a 64-bit integer type (or wider);
+you may need to compile with "-DHAVE_STDINT_H".
+#endif /* (LONG_MAX >> 31) < 0xffffffff */
+typedef long		int_fast64_t;
+#endif /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
+#endif /* !defined INT_FAST64_MAX */
+
+#ifndef INT32_MAX
+#define INT32_MAX 0x7fffffff
+#endif /* !defined INT32_MAX */
+#ifndef INT32_MIN
+#define INT32_MIN (-1 - INT32_MAX)
+#endif /* !defined INT32_MIN */
+
+/*
+** Workarounds for compilers/systems.
+*/
+
+/*
+** If your compiler lacks prototypes, "#define P(x) ()".
+*/
+
+#ifndef P
+#define P(x)	x
+#endif /* !defined P */
+
+/*
+** SunOS 4.1.1 headers lack EXIT_SUCCESS.
+*/
+
+#ifndef EXIT_SUCCESS
+#define EXIT_SUCCESS	0
+#endif /* !defined EXIT_SUCCESS */
+
+/*
+** SunOS 4.1.1 headers lack EXIT_FAILURE.
+*/
+
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE	1
+#endif /* !defined EXIT_FAILURE */
+
+/*
+** SunOS 4.1.1 headers lack FILENAME_MAX.
+*/
+
+#ifndef FILENAME_MAX
+
+#ifndef MAXPATHLEN
+#ifdef unix
+#include "sys/param.h"
+#endif /* defined unix */
+#endif /* !defined MAXPATHLEN */
+
+#ifdef MAXPATHLEN
+#define FILENAME_MAX	MAXPATHLEN
+#endif /* defined MAXPATHLEN */
+#ifndef MAXPATHLEN
+#define FILENAME_MAX	1024		/* Pure guesswork */
+#endif /* !defined MAXPATHLEN */
+
+#endif /* !defined FILENAME_MAX */
+
+/*
+** SunOS 4.1.1 libraries lack remove.
+*/
+
+#ifndef remove
+extern int	unlink P((const char * filename));
+#define remove	unlink
+#endif /* !defined remove */
+
+/*
+** Some ancient errno.h implementations don't declare errno.
+** But some newer errno.h implementations define it as a macro.
+** Fix the former without affecting the latter.
+*/
+
+#ifndef errno
+extern int errno;
+#endif /* !defined errno */
+
+/*
+** Some time.h implementations don't declare asctime_r.
+** Others might define it as a macro.
+** Fix the former without affecting the latter.
+*/
+
+#ifndef asctime_r
+extern char *	asctime_r();
+#endif
+
+/*
+** Private function declarations.
+*/
+
+char *		icalloc P((int nelem, int elsize));
+char *		icatalloc P((char * old, const char * new));
+char *		icpyalloc P((const char * string));
+char *		imalloc P((int n));
+void *		irealloc P((void * pointer, int size));
+void		icfree P((char * pointer));
+void		ifree P((char * pointer));
+const char *	scheck P((const char * string, const char * format));
+
+/*
+** Finally, some convenience items.
+*/
+
+#ifndef TRUE
+#define TRUE	1
+#endif /* !defined TRUE */
+
+#ifndef FALSE
+#define FALSE	0
+#endif /* !defined FALSE */
+
+#ifndef TYPE_BIT
+#define TYPE_BIT(type)	(sizeof (type) * CHAR_BIT)
+#endif /* !defined TYPE_BIT */
+
+#ifndef TYPE_SIGNED
+#define TYPE_SIGNED(type) (((type) -1) < 0)
+#endif /* !defined TYPE_SIGNED */
+
+/*
+** Since the definition of TYPE_INTEGRAL contains floating point numbers,
+** it cannot be used in preprocessor directives.
+*/
+
+#ifndef TYPE_INTEGRAL
+#define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5)
+#endif /* !defined TYPE_INTEGRAL */
+
+#ifndef INT_STRLEN_MAXIMUM
+/*
+** 302 / 1000 is log10(2.0) rounded up.
+** Subtract one for the sign bit if the type is signed;
+** add one for integer division truncation;
+** add one more for a minus sign if the type is signed.
+*/
+#define INT_STRLEN_MAXIMUM(type) \
+	((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \
+	1 + TYPE_SIGNED(type))
+#endif /* !defined INT_STRLEN_MAXIMUM */
+
+/*
+** INITIALIZE(x)
+*/
+
+#ifndef GNUC_or_lint
+#ifdef lint
+#define GNUC_or_lint
+#endif /* defined lint */
+#ifndef lint
+#ifdef __GNUC__
+#define GNUC_or_lint
+#endif /* defined __GNUC__ */
+#endif /* !defined lint */
+#endif /* !defined GNUC_or_lint */
+
+#ifndef INITIALIZE
+#ifdef GNUC_or_lint
+#define INITIALIZE(x)	((x) = 0)
+#endif /* defined GNUC_or_lint */
+#ifndef GNUC_or_lint
+#define INITIALIZE(x)
+#endif /* !defined GNUC_or_lint */
+#endif /* !defined INITIALIZE */
+
+/*
+** For the benefit of GNU folk...
+** `_(MSGID)' uses the current locale's message library string for MSGID.
+** The default is to use gettext if available, and use MSGID otherwise.
+*/
+
+#ifndef _
+#if HAVE_GETTEXT
+#define _(msgid) gettext(msgid)
+#else /* !HAVE_GETTEXT */
+#define _(msgid) msgid
+#endif /* !HAVE_GETTEXT */
+#endif /* !defined _ */
+
+#ifndef TZ_DOMAIN
+#define TZ_DOMAIN "tz"
+#endif /* !defined TZ_DOMAIN */
+
+#if HAVE_INCOMPATIBLE_CTIME_R
+#undef asctime_r
+#undef ctime_r
+char *asctime_r P((struct tm const *, char *));
+char *ctime_r P((time_t const *, char *));
+#endif /* HAVE_INCOMPATIBLE_CTIME_R */
+
+#ifndef YEARSPERREPEAT
+#define YEARSPERREPEAT		400	/* years before a Gregorian repeat */
+#endif /* !defined YEARSPERREPEAT */
+
+/*
+** The Gregorian year averages 365.2425 days, which is 31556952 seconds.
+*/
+
+#ifndef AVGSECSPERYEAR
+#define AVGSECSPERYEAR		31556952L
+#endif /* !defined AVGSECSPERYEAR */
+
+#ifndef SECSPERREPEAT
+#define SECSPERREPEAT		((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR)
+#endif /* !defined SECSPERREPEAT */
+ 
+#ifndef SECSPERREPEAT_BITS
+#define SECSPERREPEAT_BITS	34	/* ceil(log2(SECSPERREPEAT)) */
+#endif /* !defined SECSPERREPEAT_BITS */
+
+/*
+** UNIX was a registered trademark of The Open Group in 2003.
+*/
+
+#endif /* !defined PRIVATE_H */
diff --git a/libcutils/tzfile.h b/libcutils/tzfile.h
new file mode 100644
index 0000000..8c70375
--- /dev/null
+++ b/libcutils/tzfile.h
@@ -0,0 +1,180 @@
+#ifndef TZFILE_H
+
+#define TZFILE_H
+
+/*
+** This file is in the public domain, so clarified as of
+** 1996-06-05 by Arthur David Olson.
+*/
+
+/*
+** This header is for use ONLY with the time conversion code.
+** There is no guarantee that it will remain unchanged,
+** or that it will remain at all.
+** Do NOT copy it to any system include directory.
+** Thank you!
+*/
+
+/*
+** ID
+*/
+
+#ifndef lint
+#ifndef NOID
+static char	tzfilehid[] = "@(#)tzfile.h	8.1";
+#endif /* !defined NOID */
+#endif /* !defined lint */
+
+/*
+** Information about time zone files.
+*/
+
+#ifndef TZDIR
+#define TZDIR "/usr/share/zoneinfo" /* "/android/usr/share/zoneinfo" */ /* Time zone object file directory */
+#endif /* !defined TZDIR */
+
+#ifndef TZDEFAULT
+#define TZDEFAULT	"localtime"
+#endif /* !defined TZDEFAULT */
+
+#ifndef TZDEFRULES
+#define TZDEFRULES	"posixrules"
+#endif /* !defined TZDEFRULES */
+
+/*
+** Each file begins with. . .
+*/
+
+#define	TZ_MAGIC	"TZif"
+
+struct tzhead {
+	char	tzh_magic[4];		/* TZ_MAGIC */
+	char	tzh_version[1];		/* '\0' or '2' as of 2005 */
+	char	tzh_reserved[15];	/* reserved--must be zero */
+	char	tzh_ttisgmtcnt[4];	/* coded number of trans. time flags */
+	char	tzh_ttisstdcnt[4];	/* coded number of trans. time flags */
+	char	tzh_leapcnt[4];		/* coded number of leap seconds */
+	char	tzh_timecnt[4];		/* coded number of transition times */
+	char	tzh_typecnt[4];		/* coded number of local time types */
+	char	tzh_charcnt[4];		/* coded number of abbr. chars */
+};
+
+/*
+** . . .followed by. . .
+**
+**	tzh_timecnt (char [4])s		coded transition times a la time(2)
+**	tzh_timecnt (unsigned char)s	types of local time starting at above
+**	tzh_typecnt repetitions of
+**		one (char [4])		coded UTC offset in seconds
+**		one (unsigned char)	used to set tm_isdst
+**		one (unsigned char)	that's an abbreviation list index
+**	tzh_charcnt (char)s		'\0'-terminated zone abbreviations
+**	tzh_leapcnt repetitions of
+**		one (char [4])		coded leap second transition times
+**		one (char [4])		total correction after above
+**	tzh_ttisstdcnt (char)s		indexed by type; if TRUE, transition
+**					time is standard time, if FALSE,
+**					transition time is wall clock time
+**					if absent, transition times are
+**					assumed to be wall clock time
+**	tzh_ttisgmtcnt (char)s		indexed by type; if TRUE, transition
+**					time is UTC, if FALSE,
+**					transition time is local time
+**					if absent, transition times are
+**					assumed to be local time
+*/
+
+/*
+** If tzh_version is '2' or greater, the above is followed by a second instance
+** of tzhead and a second instance of the data in which each coded transition
+** time uses 8 rather than 4 chars,
+** then a POSIX-TZ-environment-variable-style string for use in handling
+** instants after the last transition time stored in the file
+** (with nothing between the newlines if there is no POSIX representation for
+** such instants).
+*/
+
+/*
+** In the current implementation, "tzset()" refuses to deal with files that
+** exceed any of the limits below.
+*/
+
+#ifndef TZ_MAX_TIMES
+#define TZ_MAX_TIMES	1200
+#endif /* !defined TZ_MAX_TIMES */
+
+#ifndef TZ_MAX_TYPES
+#ifndef NOSOLAR
+#define TZ_MAX_TYPES	256 /* Limited by what (unsigned char)'s can hold */
+#endif /* !defined NOSOLAR */
+#ifdef NOSOLAR
+/*
+** Must be at least 14 for Europe/Riga as of Jan 12 1995,
+** as noted by Earl Chew.
+*/
+#define TZ_MAX_TYPES	20	/* Maximum number of local time types */
+#endif /* !defined NOSOLAR */
+#endif /* !defined TZ_MAX_TYPES */
+
+#ifndef TZ_MAX_CHARS
+#define TZ_MAX_CHARS	50	/* Maximum number of abbreviation characters */
+				/* (limited by what unsigned chars can hold) */
+#endif /* !defined TZ_MAX_CHARS */
+
+#ifndef TZ_MAX_LEAPS
+#define TZ_MAX_LEAPS	50	/* Maximum number of leap second corrections */
+#endif /* !defined TZ_MAX_LEAPS */
+
+#define SECSPERMIN	60
+#define MINSPERHOUR	60
+#define HOURSPERDAY	24
+#define DAYSPERWEEK	7
+#define DAYSPERNYEAR	365
+#define DAYSPERLYEAR	366
+#define SECSPERHOUR	(SECSPERMIN * MINSPERHOUR)
+#define SECSPERDAY	((long) SECSPERHOUR * HOURSPERDAY)
+#define MONSPERYEAR	12
+
+#define TM_SUNDAY	0
+#define TM_MONDAY	1
+#define TM_TUESDAY	2
+#define TM_WEDNESDAY	3
+#define TM_THURSDAY	4
+#define TM_FRIDAY	5
+#define TM_SATURDAY	6
+
+#define TM_JANUARY	0
+#define TM_FEBRUARY	1
+#define TM_MARCH	2
+#define TM_APRIL	3
+#define TM_MAY		4
+#define TM_JUNE		5
+#define TM_JULY		6
+#define TM_AUGUST	7
+#define TM_SEPTEMBER	8
+#define TM_OCTOBER	9
+#define TM_NOVEMBER	10
+#define TM_DECEMBER	11
+
+#define TM_YEAR_BASE	1900
+
+#define EPOCH_YEAR	1970
+#define EPOCH_WDAY	TM_THURSDAY
+
+#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+
+/*
+** Since everything in isleap is modulo 400 (or a factor of 400), we know that
+**	isleap(y) == isleap(y % 400)
+** and so
+**	isleap(a + b) == isleap((a + b) % 400)
+** or
+**	isleap(a + b) == isleap(a % 400 + b % 400)
+** This is true even if % means modulo rather than Fortran remainder
+** (which is allowed by C89 but not C99).
+** We use this to avoid addition overflow problems.
+*/
+
+#define isleap_sum(a, b)	isleap((a) % 400 + (b) % 400)
+
+#endif /* !defined TZFILE_H */
diff --git a/libcutils/tzstrftime.c b/libcutils/tzstrftime.c
new file mode 100644
index 0000000..e4f54df
--- /dev/null
+++ b/libcutils/tzstrftime.c
@@ -0,0 +1,842 @@
+#ifndef lint
+#ifndef NOID
+static char	elsieid[] = "@(#)strftime.c	8.1";
+/*
+** Based on the UCB version with the ID appearing below.
+** This is ANSIish only when "multibyte character == plain character".
+*/
+#endif /* !defined NOID */
+#endif /* !defined lint */
+
+#include <stdio.h>
+#include <time.h>
+#include <tzfile.h>
+#include <limits.h>
+#include <cutils/tztime.h>
+
+/*
+** Copyright (c) 1989 The Regents of the University of California.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms are permitted
+** provided that the above copyright notice and this paragraph are
+** duplicated in all such forms and that any documentation,
+** advertising materials, and other materials related to such
+** distribution and use acknowledge that the software was developed
+** by the University of California, Berkeley. The name of the
+** University may not be used to endorse or promote products derived
+** from this software without specific prior written permission.
+** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+** IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+*/
+
+#ifndef LIBC_SCCS
+#ifndef lint
+static const char	sccsid[] = "@(#)strftime.c	5.4 (Berkeley) 3/14/89";
+#endif /* !defined lint */
+#endif /* !defined LIBC_SCCS */
+
+#include <ctype.h>
+
+#define P(x) x
+
+static char *	_add P((const char *, char *, const char *, int));
+static char *	_conv P((int, const char *, char *, const char *));
+static char *	_fmt P((const char *, const struct tm *, char *, const char *,
+			int *, const struct strftime_locale *Locale));
+static char *	_yconv P((int, int, int, int, char *, const char *, int));
+static char *	getformat P((int, char *, char *, char *, char *));
+
+extern char *	tzname[];
+
+
+
+
+
+/* from private.h */
+
+#ifndef TYPE_BIT
+#define TYPE_BIT(type)  (sizeof (type) * CHAR_BIT)
+#endif /* !defined TYPE_BIT */
+
+#ifndef TYPE_SIGNED
+#define TYPE_SIGNED(type) (((type) -1) < 0)
+#endif /* !defined TYPE_SIGNED */
+
+#ifndef INT_STRLEN_MAXIMUM
+/*
+ * ** 302 / 1000 is log10(2.0) rounded up.
+ * ** Subtract one for the sign bit if the type is signed;
+ * ** add one for integer division truncation;
+ * ** add one more for a minus sign if the type is signed.
+ * */
+#define INT_STRLEN_MAXIMUM(type) \
+    ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \
+    1 + TYPE_SIGNED(type))
+#endif /* !defined INT_STRLEN_MAXIMUM */
+
+/* end of part from private.h */
+
+
+
+
+#ifndef YEAR_2000_NAME
+#define YEAR_2000_NAME	"CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS"
+#endif /* !defined YEAR_2000_NAME */
+
+#define IN_NONE	0
+#define IN_SOME	1
+#define IN_THIS	2
+#define IN_ALL	3
+
+#define FORCE_LOWER_CASE 0x100
+
+size_t
+strftime_tz(s, maxsize, format, t, Locale)
+char * const		s;
+const size_t		maxsize;
+const char * const	format;
+const struct tm * const	t;
+const struct strftime_locale *Locale;
+{
+	char *	p;
+	int	warn;
+
+	warn = IN_NONE;
+	p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn, Locale);
+#if 0
+	if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {
+		(void) fprintf(stderr, "\n");
+		if (format == NULL)
+			(void) fprintf(stderr, "NULL strftime format ");
+		else	(void) fprintf(stderr, "strftime format \"%s\" ",
+				format);
+		(void) fprintf(stderr, "yields only two digits of years in ");
+		if (warn == IN_SOME)
+			(void) fprintf(stderr, "some locales");
+		else if (warn == IN_THIS)
+			(void) fprintf(stderr, "the current locale");
+		else	(void) fprintf(stderr, "all locales");
+		(void) fprintf(stderr, "\n");
+	}
+#endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */
+	if (p == s + maxsize)
+		return 0;
+	*p = '\0';
+	return p - s;
+}
+
+static char *getformat(int modifier, char *normal, char *underscore,
+                       char *dash, char *zero) {
+    switch (modifier) {
+    case '_':
+        return underscore;
+
+    case '-':
+        return dash;
+
+    case '0':
+        return zero;
+    }
+
+    return normal;
+}
+
+static char *
+_fmt(format, t, pt, ptlim, warnp, Locale)
+const char *		format;
+const struct tm * const	t;
+char *			pt;
+const char * const	ptlim;
+int *			warnp;
+const struct strftime_locale *Locale;
+{
+	for ( ; *format; ++format) {
+		if (*format == '%') {
+            int modifier = 0;
+label:
+			switch (*++format) {
+			case '\0':
+				--format;
+				break;
+			case 'A':
+				pt = _add((t->tm_wday < 0 ||
+					t->tm_wday >= DAYSPERWEEK) ?
+					"?" : Locale->weekday[t->tm_wday],
+					pt, ptlim, modifier);
+				continue;
+			case 'a':
+				pt = _add((t->tm_wday < 0 ||
+					t->tm_wday >= DAYSPERWEEK) ?
+					"?" : Locale->wday[t->tm_wday],
+					pt, ptlim, modifier);
+				continue;
+			case 'B':
+				if (modifier == '-') {
+					pt = _add((t->tm_mon < 0 ||
+						t->tm_mon >= MONSPERYEAR) ?
+						"?" : Locale->standalone_month[t->tm_mon],
+						pt, ptlim, modifier);
+				} else {
+					pt = _add((t->tm_mon < 0 ||
+						t->tm_mon >= MONSPERYEAR) ?
+						"?" : Locale->month[t->tm_mon],
+						pt, ptlim, modifier);
+				}
+				continue;
+			case 'b':
+			case 'h':
+				pt = _add((t->tm_mon < 0 ||
+					t->tm_mon >= MONSPERYEAR) ?
+					"?" : Locale->mon[t->tm_mon],
+					pt, ptlim, modifier);
+				continue;
+			case 'C':
+				/*
+				** %C used to do a...
+				**	_fmt("%a %b %e %X %Y", t);
+				** ...whereas now POSIX 1003.2 calls for
+				** something completely different.
+				** (ado, 1993-05-24)
+				*/
+				pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 0,
+					pt, ptlim, modifier);
+				continue;
+			case 'c':
+				{
+				int warn2 = IN_SOME;
+
+				pt = _fmt(Locale->c_fmt, t, pt, ptlim, warnp, Locale);
+				if (warn2 == IN_ALL)
+					warn2 = IN_THIS;
+				if (warn2 > *warnp)
+					*warnp = warn2;
+				}
+				continue;
+			case 'D':
+                                pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp, Locale);
+				continue;
+			case 'd':
+                                pt = _conv(t->tm_mday,
+                                           getformat(modifier, "%02d",
+                                                     "%2d", "%d", "%02d"),
+                                           pt, ptlim);
+				continue;
+			case 'E':
+			case 'O':
+				/*
+				** C99 locale modifiers.
+				** The sequences
+				**	%Ec %EC %Ex %EX %Ey %EY
+				**	%Od %oe %OH %OI %Om %OM
+				**	%OS %Ou %OU %OV %Ow %OW %Oy
+				** are supposed to provide alternate
+				** representations.
+				*/
+				goto label;
+            case '_':
+            case '-':
+            case '0':
+            case '^':
+            case '#':
+                modifier = *format;
+                goto label;
+			case 'e':
+				pt = _conv(t->tm_mday,
+                                           getformat(modifier, "%2d",
+                                                     "%2d", "%d", "%02d"),
+                                           pt, ptlim);
+				continue;
+			case 'F':
+				pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp, Locale);
+				continue;
+			case 'H':
+				pt = _conv(t->tm_hour,
+                                           getformat(modifier, "%02d",
+                                                     "%2d", "%d", "%02d"),
+                                           pt, ptlim);
+				continue;
+			case 'I':
+				pt = _conv((t->tm_hour % 12) ?
+					(t->tm_hour % 12) : 12,
+					getformat(modifier, "%02d",
+                                                  "%2d", "%d", "%02d"),
+                                        pt, ptlim);
+				continue;
+			case 'j':
+				pt = _conv(t->tm_yday + 1,
+                           getformat(modifier, "%03d", "%3d", "%d", "%03d"),
+                           pt, ptlim);
+				continue;
+			case 'k':
+				/*
+				** This used to be...
+				**	_conv(t->tm_hour % 12 ?
+				**		t->tm_hour % 12 : 12, 2, ' ');
+				** ...and has been changed to the below to
+				** match SunOS 4.1.1 and Arnold Robbins'
+				** strftime version 3.0. That is, "%k" and
+				** "%l" have been swapped.
+				** (ado, 1993-05-24)
+				*/
+				pt = _conv(t->tm_hour,
+                                           getformat(modifier, "%2d",
+                                                     "%2d", "%d", "%02d"),
+                                           pt, ptlim);
+				continue;
+#ifdef KITCHEN_SINK
+			case 'K':
+				/*
+				** After all this time, still unclaimed!
+				*/
+				pt = _add("kitchen sink", pt, ptlim, modifier);
+				continue;
+#endif /* defined KITCHEN_SINK */
+			case 'l':
+				/*
+				** This used to be...
+				**	_conv(t->tm_hour, 2, ' ');
+				** ...and has been changed to the below to
+				** match SunOS 4.1.1 and Arnold Robbin's
+				** strftime version 3.0. That is, "%k" and
+				** "%l" have been swapped.
+				** (ado, 1993-05-24)
+				*/
+				pt = _conv((t->tm_hour % 12) ?
+					(t->tm_hour % 12) : 12,
+					getformat(modifier, "%2d",
+                                                  "%2d", "%d", "%02d"),
+                                        pt, ptlim);
+				continue;
+			case 'M':
+				pt = _conv(t->tm_min,
+                                           getformat(modifier, "%02d",
+                                                     "%2d", "%d", "%02d"),
+                                           pt, ptlim);
+				continue;
+			case 'm':
+				pt = _conv(t->tm_mon + 1,
+                                           getformat(modifier, "%02d",
+                                                     "%2d", "%d", "%02d"),
+                                           pt, ptlim);
+				continue;
+			case 'n':
+				pt = _add("\n", pt, ptlim, modifier);
+				continue;
+			case 'p':
+				pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?
+					Locale->pm :
+					Locale->am,
+					pt, ptlim, modifier);
+				continue;
+			case 'P':
+				pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?
+					Locale->pm :
+					Locale->am,
+					pt, ptlim, FORCE_LOWER_CASE);
+				continue;
+			case 'R':
+				pt = _fmt("%H:%M", t, pt, ptlim, warnp, Locale);
+				continue;
+			case 'r':
+				pt = _fmt("%I:%M:%S %p", t, pt, ptlim, warnp, Locale);
+				continue;
+			case 'S':
+				pt = _conv(t->tm_sec,
+                                           getformat(modifier, "%02d",
+                                                     "%2d", "%d", "%02d"),
+                                           pt, ptlim);
+				continue;
+			case 's':
+				{
+					struct tm	tm;
+					char		buf[INT_STRLEN_MAXIMUM(
+								time_t) + 1];
+					time_t		mkt;
+
+					tm = *t;
+					mkt = mktime(&tm);
+					if (TYPE_SIGNED(time_t))
+						(void) sprintf(buf, "%ld",
+							(long) mkt);
+					else	(void) sprintf(buf, "%lu",
+							(unsigned long) mkt);
+					pt = _add(buf, pt, ptlim, modifier);
+				}
+				continue;
+			case 'T':
+				pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp, Locale);
+				continue;
+			case 't':
+				pt = _add("\t", pt, ptlim, modifier);
+				continue;
+			case 'U':
+				pt = _conv((t->tm_yday + DAYSPERWEEK -
+					t->tm_wday) / DAYSPERWEEK,
+					getformat(modifier, "%02d",
+                                                  "%2d", "%d", "%02d"),
+                                        pt, ptlim);
+				continue;
+			case 'u':
+				/*
+				** From Arnold Robbins' strftime version 3.0:
+				** "ISO 8601: Weekday as a decimal number
+				** [1 (Monday) - 7]"
+				** (ado, 1993-05-24)
+				*/
+				pt = _conv((t->tm_wday == 0) ?
+					DAYSPERWEEK : t->tm_wday, "%d", pt, ptlim);
+				continue;
+			case 'V':	/* ISO 8601 week number */
+			case 'G':	/* ISO 8601 year (four digits) */
+			case 'g':	/* ISO 8601 year (two digits) */
+/*
+** From Arnold Robbins' strftime version 3.0: "the week number of the
+** year (the first Monday as the first day of week 1) as a decimal number
+** (01-53)."
+** (ado, 1993-05-24)
+**
+** From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn:
+** "Week 01 of a year is per definition the first week which has the
+** Thursday in this year, which is equivalent to the week which contains
+** the fourth day of January. In other words, the first week of a new year
+** is the week which has the majority of its days in the new year. Week 01
+** might also contain days from the previous year and the week before week
+** 01 of a year is the last week (52 or 53) of the previous year even if
+** it contains days from the new year. A week starts with Monday (day 1)
+** and ends with Sunday (day 7). For example, the first week of the year
+** 1997 lasts from 1996-12-30 to 1997-01-05..."
+** (ado, 1996-01-02)
+*/
+				{
+					int	year;
+					int	base;
+					int	yday;
+					int	wday;
+					int	w;
+
+					year = t->tm_year;
+					base = TM_YEAR_BASE;
+					yday = t->tm_yday;
+					wday = t->tm_wday;
+					for ( ; ; ) {
+						int	len;
+						int	bot;
+						int	top;
+
+						len = isleap_sum(year, base) ?
+							DAYSPERLYEAR :
+							DAYSPERNYEAR;
+						/*
+						** What yday (-3 ... 3) does
+						** the ISO year begin on?
+						*/
+						bot = ((yday + 11 - wday) %
+							DAYSPERWEEK) - 3;
+						/*
+						** What yday does the NEXT
+						** ISO year begin on?
+						*/
+						top = bot -
+							(len % DAYSPERWEEK);
+						if (top < -3)
+							top += DAYSPERWEEK;
+						top += len;
+						if (yday >= top) {
+							++base;
+							w = 1;
+							break;
+						}
+						if (yday >= bot) {
+							w = 1 + ((yday - bot) /
+								DAYSPERWEEK);
+							break;
+						}
+						--base;
+						yday += isleap_sum(year, base) ?
+							DAYSPERLYEAR :
+							DAYSPERNYEAR;
+					}
+#ifdef XPG4_1994_04_09
+					if ((w == 52 &&
+						t->tm_mon == TM_JANUARY) ||
+						(w == 1 &&
+						t->tm_mon == TM_DECEMBER))
+							w = 53;
+#endif /* defined XPG4_1994_04_09 */
+					if (*format == 'V')
+						pt = _conv(w,
+                                                           getformat(modifier,
+                                                                     "%02d",
+                                                                     "%2d",
+                                                                     "%d",
+                                                                     "%02d"),
+							   pt, ptlim);
+					else if (*format == 'g') {
+						*warnp = IN_ALL;
+						pt = _yconv(year, base, 0, 1,
+							pt, ptlim, modifier);
+					} else	pt = _yconv(year, base, 1, 1,
+							pt, ptlim, modifier);
+				}
+				continue;
+			case 'v':
+				/*
+				** From Arnold Robbins' strftime version 3.0:
+				** "date as dd-bbb-YYYY"
+				** (ado, 1993-05-24)
+				*/
+				pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp, Locale);
+				continue;
+			case 'W':
+				pt = _conv((t->tm_yday + DAYSPERWEEK -
+					(t->tm_wday ?
+					(t->tm_wday - 1) :
+					(DAYSPERWEEK - 1))) / DAYSPERWEEK,
+					getformat(modifier, "%02d",
+                                                  "%2d", "%d", "%02d"),
+                                        pt, ptlim);
+				continue;
+			case 'w':
+				pt = _conv(t->tm_wday, "%d", pt, ptlim);
+				continue;
+			case 'X':
+				pt = _fmt(Locale->X_fmt, t, pt, ptlim, warnp, Locale);
+				continue;
+			case 'x':
+				{
+				int	warn2 = IN_SOME;
+
+				pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2, Locale);
+				if (warn2 == IN_ALL)
+					warn2 = IN_THIS;
+				if (warn2 > *warnp)
+					*warnp = warn2;
+				}
+				continue;
+			case 'y':
+				*warnp = IN_ALL;
+				pt = _yconv(t->tm_year, TM_YEAR_BASE, 0, 1,
+					pt, ptlim, modifier);
+				continue;
+			case 'Y':
+				pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 1,
+					pt, ptlim, modifier);
+				continue;
+			case 'Z':
+#ifdef TM_ZONE
+				if (t->TM_ZONE != NULL)
+					pt = _add(t->TM_ZONE, pt, ptlim,
+                                                  modifier);
+				else
+#endif /* defined TM_ZONE */
+				if (t->tm_isdst >= 0)
+					pt = _add(tzname[t->tm_isdst != 0],
+						pt, ptlim, modifier);
+				/*
+				** C99 says that %Z must be replaced by the
+				** empty string if the time zone is not
+				** determinable.
+				*/
+				continue;
+			case 'z':
+				{
+				int		diff;
+				char const *	sign;
+
+				if (t->tm_isdst < 0)
+					continue;
+#ifdef TM_GMTOFF
+				diff = t->TM_GMTOFF;
+#else /* !defined TM_GMTOFF */
+				/*
+				** C99 says that the UTC offset must
+				** be computed by looking only at
+				** tm_isdst. This requirement is
+				** incorrect, since it means the code
+				** must rely on magic (in this case
+				** altzone and timezone), and the
+				** magic might not have the correct
+				** offset. Doing things correctly is
+				** tricky and requires disobeying C99;
+				** see GNU C strftime for details.
+				** For now, punt and conform to the
+				** standard, even though it's incorrect.
+				**
+				** C99 says that %z must be replaced by the
+				** empty string if the time zone is not
+				** determinable, so output nothing if the
+				** appropriate variables are not available.
+				*/
+				if (t->tm_isdst == 0)
+#ifdef USG_COMPAT
+					diff = -timezone;
+#else /* !defined USG_COMPAT */
+					continue;
+#endif /* !defined USG_COMPAT */
+				else
+#ifdef ALTZONE
+					diff = -altzone;
+#else /* !defined ALTZONE */
+					continue;
+#endif /* !defined ALTZONE */
+#endif /* !defined TM_GMTOFF */
+				if (diff < 0) {
+					sign = "-";
+					diff = -diff;
+				} else	sign = "+";
+				pt = _add(sign, pt, ptlim, modifier);
+				diff /= SECSPERMIN;
+				diff = (diff / MINSPERHOUR) * 100 +
+					(diff % MINSPERHOUR);
+				pt = _conv(diff,
+                                           getformat(modifier, "%04d",
+                                                     "%4d", "%d", "%04d"),
+                                           pt, ptlim);
+				}
+				continue;
+			case '+':
+				pt = _fmt(Locale->date_fmt, t, pt, ptlim,
+					warnp, Locale);
+				continue;
+			case '%':
+			/*
+			** X311J/88-090 (4.12.3.5): if conversion char is
+			** undefined, behavior is undefined. Print out the
+			** character itself as printf(3) also does.
+			*/
+			default:
+				break;
+			}
+		}
+		if (pt == ptlim)
+			break;
+		*pt++ = *format;
+	}
+	return pt;
+}
+
+static char *
+_conv(n, format, pt, ptlim)
+const int		n;
+const char * const	format;
+char * const		pt;
+const char * const	ptlim;
+{
+	char	buf[INT_STRLEN_MAXIMUM(int) + 1];
+
+	(void) sprintf(buf, format, n);
+	return _add(buf, pt, ptlim, 0);
+}
+
+static char *
+_add(str, pt, ptlim, modifier)
+const char *		str;
+char *			pt;
+const char * const	ptlim;
+int                     modifier;
+{
+        int c;
+
+        switch (modifier) {
+        case FORCE_LOWER_CASE:
+                while (pt < ptlim && (*pt = tolower(*str++)) != '\0') {
+                        ++pt;
+                }
+                break;
+
+        case '^':
+                while (pt < ptlim && (*pt = toupper(*str++)) != '\0') {
+                        ++pt;
+                }
+                break;
+
+        case '#':
+                while (pt < ptlim && (c = *str++) != '\0') {
+                        if (isupper(c)) {
+                                c = tolower(c);
+                        } else if (islower(c)) {
+                                c = toupper(c);
+                        }
+                        *pt = c;
+                        ++pt;
+                }
+
+                break;
+
+        default:
+                while (pt < ptlim && (*pt = *str++) != '\0') {
+                        ++pt;
+                }
+        }
+
+	return pt;
+}
+
+/*
+** POSIX and the C Standard are unclear or inconsistent about
+** what %C and %y do if the year is negative or exceeds 9999.
+** Use the convention that %C concatenated with %y yields the
+** same output as %Y, and that %Y contains at least 4 bytes,
+** with more only if necessary.
+*/
+
+static char *
+_yconv(a, b, convert_top, convert_yy, pt, ptlim, modifier)
+const int		a;
+const int		b;
+const int		convert_top;
+const int		convert_yy;
+char *			pt;
+const char * const	ptlim;
+int                     modifier;
+{
+	register int	lead;
+	register int	trail;
+
+#define DIVISOR	100
+	trail = a % DIVISOR + b % DIVISOR;
+	lead = a / DIVISOR + b / DIVISOR + trail / DIVISOR;
+	trail %= DIVISOR;
+	if (trail < 0 && lead > 0) {
+		trail += DIVISOR;
+		--lead;
+	} else if (lead < 0 && trail > 0) {
+		trail -= DIVISOR;
+		++lead;
+	}
+	if (convert_top) {
+		if (lead == 0 && trail < 0)
+			pt = _add("-0", pt, ptlim, modifier);
+		else	pt = _conv(lead, getformat(modifier, "%02d",
+                                                   "%2d", "%d", "%02d"),
+                                   pt, ptlim);
+	}
+	if (convert_yy)
+		pt = _conv(((trail < 0) ? -trail : trail),
+                           getformat(modifier, "%02d", "%2d", "%d", "%02d"),
+                           pt, ptlim);
+	return pt;
+}
+
+#ifdef LOCALE_HOME
+static struct lc_time_T *
+_loc P((void))
+{
+	static const char	locale_home[] = LOCALE_HOME;
+	static const char	lc_time[] = "LC_TIME";
+	static char *		locale_buf;
+
+	int			fd;
+	int			oldsun;	/* "...ain't got nothin' to do..." */
+	char *			lbuf;
+	char *			name;
+	char *			p;
+	const char **		ap;
+	const char *		plim;
+	char			filename[FILENAME_MAX];
+	struct stat		st;
+	size_t			namesize;
+	size_t			bufsize;
+
+	/*
+	** Use localebuf.mon[0] to signal whether locale is already set up.
+	*/
+	if (localebuf.mon[0])
+		return &localebuf;
+	name = setlocale(LC_TIME, (char *) NULL);
+	if (name == NULL || *name == '\0')
+		goto no_locale;
+	/*
+	** If the locale name is the same as our cache, use the cache.
+	*/
+	lbuf = locale_buf;
+	if (lbuf != NULL && strcmp(name, lbuf) == 0) {
+		p = lbuf;
+		for (ap = (const char **) &localebuf;
+			ap < (const char **) (&localebuf + 1);
+				++ap)
+					*ap = p += strlen(p) + 1;
+		return &localebuf;
+	}
+	/*
+	** Slurp the locale file into the cache.
+	*/
+	namesize = strlen(name) + 1;
+	if (sizeof filename <
+		((sizeof locale_home) + namesize + (sizeof lc_time)))
+			goto no_locale;
+	oldsun = 0;
+	(void) sprintf(filename, "%s/%s/%s", locale_home, name, lc_time);
+	fd = open(filename, O_RDONLY);
+	if (fd < 0) {
+		/*
+		** Old Sun systems have a different naming and data convention.
+		*/
+		oldsun = 1;
+		(void) sprintf(filename, "%s/%s/%s", locale_home,
+			lc_time, name);
+		fd = open(filename, O_RDONLY);
+		if (fd < 0)
+			goto no_locale;
+	}
+	if (fstat(fd, &st) != 0)
+		goto bad_locale;
+	if (st.st_size <= 0)
+		goto bad_locale;
+	bufsize = namesize + st.st_size;
+	locale_buf = NULL;
+	lbuf = (lbuf == NULL) ? malloc(bufsize) : realloc(lbuf, bufsize);
+	if (lbuf == NULL)
+		goto bad_locale;
+	(void) strcpy(lbuf, name);
+	p = lbuf + namesize;
+	plim = p + st.st_size;
+	if (read(fd, p, (size_t) st.st_size) != st.st_size)
+		goto bad_lbuf;
+	if (close(fd) != 0)
+		goto bad_lbuf;
+	/*
+	** Parse the locale file into localebuf.
+	*/
+	if (plim[-1] != '\n')
+		goto bad_lbuf;
+	for (ap = (const char **) &localebuf;
+		ap < (const char **) (&localebuf + 1);
+			++ap) {
+				if (p == plim)
+					goto bad_lbuf;
+				*ap = p;
+				while (*p != '\n')
+					++p;
+				*p++ = '\0';
+	}
+	if (oldsun) {
+		/*
+		** SunOS 4 used an obsolescent format; see localdtconv(3).
+		** c_fmt had the ``short format for dates and times together''
+		** (SunOS 4 date, "%a %b %e %T %Z %Y" in the C locale);
+		** date_fmt had the ``long format for dates''
+		** (SunOS 4 strftime %C, "%A, %B %e, %Y" in the C locale).
+		** Discard the latter in favor of the former.
+		*/
+		localebuf.date_fmt = localebuf.c_fmt;
+	}
+	/*
+	** Record the successful parse in the cache.
+	*/
+	locale_buf = lbuf;
+
+	return &localebuf;
+
+bad_lbuf:
+	free(lbuf);
+bad_locale:
+	(void) close(fd);
+no_locale:
+	localebuf = C_time_locale;
+	locale_buf = NULL;
+	return &localebuf;
+}
+#endif /* defined LOCALE_HOME */
diff --git a/libcutils/tztime.c b/libcutils/tztime.c
new file mode 100644
index 0000000..d6448a1
--- /dev/null
+++ b/libcutils/tztime.c
@@ -0,0 +1,1950 @@
+/*
+** This file is in the public domain, so clarified as of
+** 1996-06-05 by Arthur David Olson.
+*/
+
+#include <stdio.h>
+
+#ifndef lint
+#ifndef NOID
+static char	elsieid[] = "@(#)localtime.c	8.3";
+#endif /* !defined NOID */
+#endif /* !defined lint */
+
+/*
+** Leap second handling from Bradley White.
+** POSIX-style TZ environment variable handling from Guy Harris.
+*/
+
+/*LINTLIBRARY*/
+
+#include "private.h"
+#include "tzfile.h"
+#include "fcntl.h"
+#include "float.h"	/* for FLT_MAX and DBL_MAX */
+
+#ifndef TZ_ABBR_MAX_LEN
+#define TZ_ABBR_MAX_LEN	16
+#endif /* !defined TZ_ABBR_MAX_LEN */
+
+#ifndef TZ_ABBR_CHAR_SET
+#define TZ_ABBR_CHAR_SET \
+	"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
+#endif /* !defined TZ_ABBR_CHAR_SET */
+
+#ifndef TZ_ABBR_ERR_CHAR
+#define TZ_ABBR_ERR_CHAR	'_'
+#endif /* !defined TZ_ABBR_ERR_CHAR */
+
+#define INDEXFILE "/system/usr/share/zoneinfo/zoneinfo.idx"
+#define DATAFILE "/system/usr/share/zoneinfo/zoneinfo.dat"
+#define NAMELEN 40
+#define INTLEN 4
+#define READLEN (NAMELEN + 3 * INTLEN)
+
+/*
+** SunOS 4.1.1 headers lack O_BINARY.
+*/
+
+#ifdef O_BINARY
+#define OPEN_MODE	(O_RDONLY | O_BINARY)
+#endif /* defined O_BINARY */
+#ifndef O_BINARY
+#define OPEN_MODE	O_RDONLY
+#endif /* !defined O_BINARY */
+
+/* Complex computations to determine the min/max of time_t depending
+ * on TYPE_BIT / TYPE_SIGNED / TYPE_INTEGRAL.
+ * These macros cannot be used in pre-processor directives, so we
+ * let the C compiler do the work, which makes things a bit funky.
+ */
+static const time_t TIME_T_MAX =
+    TYPE_INTEGRAL(time_t) ?
+        ( TYPE_SIGNED(time_t) ?
+            ~((time_t)1 << (TYPE_BIT(time_t)-1))
+        :
+            ~(time_t)0
+        )
+    : /* if time_t is a floating point number */
+        ( sizeof(time_t) > sizeof(float) ? (time_t)DBL_MAX : (time_t)FLT_MAX );
+
+static const time_t TIME_T_MIN =
+    TYPE_INTEGRAL(time_t) ?
+        ( TYPE_SIGNED(time_t) ?
+            ((time_t)1 << (TYPE_BIT(time_t)-1))
+        :
+            0
+        )
+    :
+        ( sizeof(time_t) > sizeof(float) ? (time_t)DBL_MIN : (time_t)FLT_MIN );
+
+#ifndef WILDABBR
+/*
+** Someone might make incorrect use of a time zone abbreviation:
+**	1.	They might reference tzname[0] before calling tzset (explicitly
+**		or implicitly).
+**	2.	They might reference tzname[1] before calling tzset (explicitly
+**		or implicitly).
+**	3.	They might reference tzname[1] after setting to a time zone
+**		in which Daylight Saving Time is never observed.
+**	4.	They might reference tzname[0] after setting to a time zone
+**		in which Standard Time is never observed.
+**	5.	They might reference tm.TM_ZONE after calling offtime.
+** What's best to do in the above cases is open to debate;
+** for now, we just set things up so that in any of the five cases
+** WILDABBR is used. Another possibility: initialize tzname[0] to the
+** string "tzname[0] used before set", and similarly for the other cases.
+** And another: initialize tzname[0] to "ERA", with an explanation in the
+** manual page of what this "time zone abbreviation" means (doing this so
+** that tzname[0] has the "normal" length of three characters).
+*/
+#define WILDABBR	"   "
+#endif /* !defined WILDABBR */
+
+static char		wildabbr[] = WILDABBR;
+
+static const char	gmt[] = "GMT";
+
+/*
+** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
+** We default to US rules as of 1999-08-17.
+** POSIX 1003.1 section 8.1.1 says that the default DST rules are
+** implementation dependent; for historical reasons, US rules are a
+** common default.
+*/
+#ifndef TZDEFRULESTRING
+#define TZDEFRULESTRING ",M4.1.0,M10.5.0"
+#endif /* !defined TZDEFDST */
+
+struct ttinfo {				/* time type information */
+	long		tt_gmtoff;	/* UTC offset in seconds */
+	int		tt_isdst;	/* used to set tm_isdst */
+	int		tt_abbrind;	/* abbreviation list index */
+	int		tt_ttisstd;	/* TRUE if transition is std time */
+	int		tt_ttisgmt;	/* TRUE if transition is UTC */
+};
+
+struct lsinfo {				/* leap second information */
+	time_t		ls_trans;	/* transition time */
+	long		ls_corr;	/* correction to apply */
+};
+
+#define BIGGEST(a, b)	(((a) > (b)) ? (a) : (b))
+
+#ifdef TZNAME_MAX
+#define MY_TZNAME_MAX	TZNAME_MAX
+#endif /* defined TZNAME_MAX */
+#ifndef TZNAME_MAX
+#define MY_TZNAME_MAX	255
+#endif /* !defined TZNAME_MAX */
+
+struct state {
+	int		leapcnt;
+	int		timecnt;
+	int		typecnt;
+	int		charcnt;
+	int		goback;
+	int		goahead;
+	time_t		ats[TZ_MAX_TIMES];
+	unsigned char	types[TZ_MAX_TIMES];
+	struct ttinfo	ttis[TZ_MAX_TYPES];
+	char		chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
+				(2 * (MY_TZNAME_MAX + 1)))];
+	struct lsinfo	lsis[TZ_MAX_LEAPS];
+};
+
+struct rule {
+	int		r_type;		/* type of rule--see below */
+	int		r_day;		/* day number of rule */
+	int		r_week;		/* week number of rule */
+	int		r_mon;		/* month number of rule */
+	long		r_time;		/* transition time of rule */
+};
+
+#define JULIAN_DAY		0	/* Jn - Julian day */
+#define DAY_OF_YEAR		1	/* n - day of year */
+#define MONTH_NTH_DAY_OF_WEEK	2	/* Mm.n.d - month, week, day of week */
+
+/*
+** Prototypes for static functions.
+*/
+
+static long		detzcode P((const char * codep));
+static time_t		detzcode64 P((const char * codep));
+static int		differ_by_repeat P((time_t t1, time_t t0));
+static const char *	getzname P((const char * strp));
+static const char *	getqzname P((const char * strp, const int delim));
+static const char *	getnum P((const char * strp, int * nump, int min,
+				int max));
+static const char *	getsecs P((const char * strp, long * secsp));
+static const char *	getoffset P((const char * strp, long * offsetp));
+static const char *	getrule P((const char * strp, struct rule * rulep));
+static void		gmtload P((struct state * sp));
+static struct tm *	gmtsub P((const time_t * timep, long offset,
+				struct tm * tmp));
+static struct tm *	localsub P((const time_t * timep, long offset,
+				struct tm * tmp, const struct state *sp));
+static int		increment_overflow P((int * number, int delta));
+static int		leaps_thru_end_of P((int y));
+static int		long_increment_overflow P((long * number, int delta));
+static int		long_normalize_overflow P((long * tensptr,
+				int * unitsptr, int base));
+static int		normalize_overflow P((int * tensptr, int * unitsptr,
+				int base));
+static void		settzname P((void));
+static time_t		time1 P((struct tm * tmp,
+				struct tm * (*funcp) P((const time_t *,
+				long, struct tm *, const struct state* sp)),
+				long offset, const struct state *	sp));
+static time_t		time2 P((struct tm *tmp,
+				struct tm * (*funcp) P((const time_t *,
+				long, struct tm*, const struct state* sp)),
+				long offset, int * okayp, const struct state *	sp));
+static time_t		time2sub P((struct tm *tmp,
+				struct tm * (*funcp) P((const time_t*, long, struct tm*,const struct state *sp)),
+				long offset, int * okayp, int do_norm_secs,
+                const struct state *sp));
+static struct tm *	timesub P((const time_t * timep, long offset,
+				const struct state * sp, struct tm * tmp));
+static int		tmcomp P((const struct tm * atmp,
+				const struct tm * btmp));
+static time_t		transtime P((time_t janfirst, int year,
+				const struct rule * rulep, long offset));
+static int		tzload P((const char * name, struct state * sp,
+				int doextend));
+static int		tzload_uncached P((const char * name, struct state * sp,
+				int doextend));
+static int		tzparse P((const char * name, struct state * sp,
+				int lastditch));
+
+#ifdef ALL_STATE
+static struct state *	gmtptr;
+#endif /* defined ALL_STATE */
+
+#ifndef ALL_STATE
+static struct state	gmtmem;
+#define gmtptr		(&gmtmem)
+#endif /* State Farm */
+
+#define CACHE_COUNT 4
+static char * g_cacheNames[CACHE_COUNT] = {0,0};
+static struct state	g_cacheStates[CACHE_COUNT];
+static int g_lastCache = 0;
+static struct state g_utc;
+unsigned char g_utcSet = 0;
+
+
+#ifndef TZ_STRLEN_MAX
+#define TZ_STRLEN_MAX 255
+#endif /* !defined TZ_STRLEN_MAX */
+
+static char		lcl_TZname[TZ_STRLEN_MAX + 1];
+static int		lcl_is_set;
+static int		gmt_is_set;
+
+char *			tzname[2] = {
+	wildabbr,
+	wildabbr
+};
+
+/*
+** Section 4.12.3 of X3.159-1989 requires that
+**	Except for the strftime function, these functions [asctime,
+**	ctime, gmtime, localtime] return values in one of two static
+**	objects: a broken-down time structure and an array of char.
+** Thanks to Paul Eggert for noting this.
+*/
+
+static struct tm	tm;
+
+#ifdef USG_COMPAT
+time_t			timezone = 0;
+int			daylight = 0;
+#endif /* defined USG_COMPAT */
+
+#ifdef ALTZONE
+time_t			altzone = 0;
+#endif /* defined ALTZONE */
+
+static long
+detzcode(codep)
+const char * const	codep;
+{
+	register long	result;
+	register int	i;
+
+	result = (codep[0] & 0x80) ? ~0L : 0;
+	for (i = 0; i < 4; ++i)
+		result = (result << 8) | (codep[i] & 0xff);
+	return result;
+}
+
+static time_t
+detzcode64(codep)
+const char * const	codep;
+{
+	register time_t	result;
+	register int	i;
+
+	result = (codep[0] & 0x80) ?  (~(int_fast64_t) 0) : 0;
+	for (i = 0; i < 8; ++i)
+		result = result * 256 + (codep[i] & 0xff);
+	return result;
+}
+
+static int
+differ_by_repeat(t1, t0)
+const time_t	t1;
+const time_t	t0;
+{
+	if (TYPE_INTEGRAL(time_t) &&
+		TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
+			return 0;
+	return t1 - t0 == SECSPERREPEAT;
+}
+
+static int toint(unsigned char *s) {
+    return (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
+}
+
+static int
+tzload(const char *name, struct state * const sp, const int doextend)
+{
+    if (name) {
+        int i, err;
+        if (0 == strcmp(name, "UTC")) {
+            if (!g_utcSet) {
+                tzload_uncached(name, &g_utc, 1);
+                g_utcSet = 1;
+            }
+            //printf("tzload: utc\n");
+            *sp = g_utc;
+            return 0;
+        }
+        for (i=0; i<CACHE_COUNT; i++) {
+            if (g_cacheNames[i] && 0 == strcmp(name, g_cacheNames[i])) {
+                *sp = g_cacheStates[i];
+                //printf("tzload: hit: %s\n", name);
+                return 0;
+            }
+        }
+        //printf("tzload: miss: %s\n", name);
+        g_lastCache++;
+        if (g_lastCache >= CACHE_COUNT) {
+            g_lastCache = 0;
+        }
+        i = g_lastCache;
+        if (g_cacheNames[i]) {
+            free(g_cacheNames[i]);
+        }
+        err = tzload_uncached(name, &(g_cacheStates[i]), 1);
+        if (err == 0) {
+            g_cacheNames[i] = strdup(name);
+            *sp = g_cacheStates[i];
+            return 0;
+        } else {
+            g_cacheNames[i] = NULL;
+            return err;
+        }
+    }
+    return tzload_uncached(name, sp, doextend);
+}
+
+static int
+tzload_uncached(name, sp, doextend)
+register const char *		name;
+register struct state * const	sp;
+register const int		doextend;
+{
+	register const char *		p;
+	register int			i;
+	register int			fid;
+	register int			stored;
+	register int			nread;
+	union {
+		struct tzhead	tzhead;
+		char		buf[2 * sizeof(struct tzhead) +
+					2 * sizeof *sp +
+					4 * TZ_MAX_TIMES];
+	} u;
+    int                     toread = sizeof u.buf;
+
+	if (name == NULL && (name = TZDEFAULT) == NULL)
+		return -1;
+	{
+		register int	doaccess;
+		/*
+		** Section 4.9.1 of the C standard says that
+		** "FILENAME_MAX expands to an integral constant expression
+		** that is the size needed for an array of char large enough
+		** to hold the longest file name string that the implementation
+		** guarantees can be opened."
+		*/
+		char		fullname[FILENAME_MAX + 1];
+		const char	*origname = name;
+
+		if (name[0] == ':')
+			++name;
+		doaccess = name[0] == '/';
+		if (!doaccess) {
+			if ((p = TZDIR) == NULL)
+				return -1;
+			if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
+				return -1;
+			(void) strcpy(fullname, p);
+			(void) strcat(fullname, "/");
+			(void) strcat(fullname, name);
+			/*
+			** Set doaccess if '.' (as in "../") shows up in name.
+			*/
+			if (strchr(name, '.') != NULL)
+				doaccess = TRUE;
+			name = fullname;
+		}
+		if (doaccess && access(name, R_OK) != 0)
+			return -1;
+		if ((fid = open(name, OPEN_MODE)) == -1) {
+            char buf[READLEN];
+            char name[NAMELEN + 1];
+            int fidix = open(INDEXFILE, OPEN_MODE);
+            int off = -1;
+
+            if (fidix < 0) {
+                return -1;
+            }
+
+            while (read(fidix, buf, sizeof(buf)) == sizeof(buf)) {
+                memcpy(name, buf, NAMELEN);
+                name[NAMELEN] = '\0';
+
+                if (strcmp(name, origname) == 0) {
+                    off = toint((unsigned char *) buf + NAMELEN);
+                    toread = toint((unsigned char *) buf + NAMELEN + INTLEN);
+                    break;
+                }
+            }
+
+            close(fidix);
+
+            if (off < 0)
+                return -1;
+
+            fid = open(DATAFILE, OPEN_MODE);
+
+            if (fid < 0) {
+                return -1;
+            }
+
+            if (lseek(fid, off, SEEK_SET) < 0) {
+                return -1;
+            }
+        }
+	}
+	nread = read(fid, u.buf, toread);
+	if (close(fid) < 0 || nread <= 0)
+		return -1;
+	for (stored = 4; stored <= 8; stored *= 2) {
+		int		ttisstdcnt;
+		int		ttisgmtcnt;
+
+		ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
+		ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
+		sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
+		sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
+		sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
+		sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
+		p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
+		if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
+			sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
+			sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
+			sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
+			(ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
+			(ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
+				return -1;
+		if (nread - (p - u.buf) <
+			sp->timecnt * stored +		/* ats */
+			sp->timecnt +			/* types */
+			sp->typecnt * 6 +		/* ttinfos */
+			sp->charcnt +			/* chars */
+			sp->leapcnt * (stored + 4) +	/* lsinfos */
+			ttisstdcnt +			/* ttisstds */
+			ttisgmtcnt)			/* ttisgmts */
+				return -1;
+		for (i = 0; i < sp->timecnt; ++i) {
+			sp->ats[i] = (stored == 4) ?
+				detzcode(p) : detzcode64(p);
+			p += stored;
+		}
+		for (i = 0; i < sp->timecnt; ++i) {
+			sp->types[i] = (unsigned char) *p++;
+			if (sp->types[i] >= sp->typecnt)
+				return -1;
+		}
+		for (i = 0; i < sp->typecnt; ++i) {
+			register struct ttinfo *	ttisp;
+
+			ttisp = &sp->ttis[i];
+			ttisp->tt_gmtoff = detzcode(p);
+			p += 4;
+			ttisp->tt_isdst = (unsigned char) *p++;
+			if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
+				return -1;
+			ttisp->tt_abbrind = (unsigned char) *p++;
+			if (ttisp->tt_abbrind < 0 ||
+				ttisp->tt_abbrind > sp->charcnt)
+					return -1;
+		}
+		for (i = 0; i < sp->charcnt; ++i)
+			sp->chars[i] = *p++;
+		sp->chars[i] = '\0';	/* ensure '\0' at end */
+		for (i = 0; i < sp->leapcnt; ++i) {
+			register struct lsinfo *	lsisp;
+
+			lsisp = &sp->lsis[i];
+			lsisp->ls_trans = (stored == 4) ?
+				detzcode(p) : detzcode64(p);
+			p += stored;
+			lsisp->ls_corr = detzcode(p);
+			p += 4;
+		}
+		for (i = 0; i < sp->typecnt; ++i) {
+			register struct ttinfo *	ttisp;
+
+			ttisp = &sp->ttis[i];
+			if (ttisstdcnt == 0)
+				ttisp->tt_ttisstd = FALSE;
+			else {
+				ttisp->tt_ttisstd = *p++;
+				if (ttisp->tt_ttisstd != TRUE &&
+					ttisp->tt_ttisstd != FALSE)
+						return -1;
+			}
+		}
+		for (i = 0; i < sp->typecnt; ++i) {
+			register struct ttinfo *	ttisp;
+
+			ttisp = &sp->ttis[i];
+			if (ttisgmtcnt == 0)
+				ttisp->tt_ttisgmt = FALSE;
+			else {
+				ttisp->tt_ttisgmt = *p++;
+				if (ttisp->tt_ttisgmt != TRUE &&
+					ttisp->tt_ttisgmt != FALSE)
+						return -1;
+			}
+		}
+		/*
+		** Out-of-sort ats should mean we're running on a
+		** signed time_t system but using a data file with
+		** unsigned values (or vice versa).
+		*/
+		for (i = 0; i < sp->timecnt - 2; ++i)
+			if (sp->ats[i] > sp->ats[i + 1]) {
+				++i;
+				if (TYPE_SIGNED(time_t)) {
+					/*
+					** Ignore the end (easy).
+					*/
+					sp->timecnt = i;
+				} else {
+					/*
+					** Ignore the beginning (harder).
+					*/
+					register int	j;
+
+					for (j = 0; j + i < sp->timecnt; ++j) {
+						sp->ats[j] = sp->ats[j + i];
+						sp->types[j] = sp->types[j + i];
+					}
+					sp->timecnt = j;
+				}
+				break;
+			}
+		/*
+		** If this is an old file, we're done.
+		*/
+		if (u.tzhead.tzh_version[0] == '\0')
+			break;
+		nread -= p - u.buf;
+		for (i = 0; i < nread; ++i)
+			u.buf[i] = p[i];
+		/*
+		** If this is a narrow integer time_t system, we're done.
+		*/
+		if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
+			break;
+	}
+	if (doextend && nread > 2 &&
+		u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
+		sp->typecnt + 2 <= TZ_MAX_TYPES) {
+			struct state	ts;
+			register int	result;
+
+			u.buf[nread - 1] = '\0';
+			result = tzparse(&u.buf[1], &ts, FALSE);
+			if (result == 0 && ts.typecnt == 2 &&
+				sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) {
+					for (i = 0; i < 2; ++i)
+						ts.ttis[i].tt_abbrind +=
+							sp->charcnt;
+					for (i = 0; i < ts.charcnt; ++i)
+						sp->chars[sp->charcnt++] =
+							ts.chars[i];
+					i = 0;
+					while (i < ts.timecnt &&
+						ts.ats[i] <=
+						sp->ats[sp->timecnt - 1])
+							++i;
+					while (i < ts.timecnt &&
+					    sp->timecnt < TZ_MAX_TIMES) {
+						sp->ats[sp->timecnt] =
+							ts.ats[i];
+						sp->types[sp->timecnt] =
+							sp->typecnt +
+							ts.types[i];
+						++sp->timecnt;
+						++i;
+					}
+					sp->ttis[sp->typecnt++] = ts.ttis[0];
+					sp->ttis[sp->typecnt++] = ts.ttis[1];
+			}
+	}
+	i = 2 * YEARSPERREPEAT;
+	sp->goback = sp->goahead = sp->timecnt > i;
+	sp->goback &= sp->types[i] == sp->types[0] &&
+		differ_by_repeat(sp->ats[i], sp->ats[0]);
+	sp->goahead &=
+		sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] &&
+		differ_by_repeat(sp->ats[sp->timecnt - 1],
+			 sp->ats[sp->timecnt - 1 - i]);
+	return 0;
+}
+
+static const int	mon_lengths[2][MONSPERYEAR] = {
+	{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+	{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+};
+
+static const int	year_lengths[2] = {
+	DAYSPERNYEAR, DAYSPERLYEAR
+};
+
+/*
+** Given a pointer into a time zone string, scan until a character that is not
+** a valid character in a zone name is found. Return a pointer to that
+** character.
+*/
+
+static const char *
+getzname(strp)
+register const char *	strp;
+{
+	register char	c;
+
+	while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
+		c != '+')
+			++strp;
+	return strp;
+}
+
+/*
+** Given a pointer into an extended time zone string, scan until the ending
+** delimiter of the zone name is located. Return a pointer to the delimiter.
+**
+** As with getzname above, the legal character set is actually quite
+** restricted, with other characters producing undefined results.
+** We don't do any checking here; checking is done later in common-case code.
+*/
+
+static const char *
+getqzname(register const char *strp, const int delim)
+{
+	register int	c;
+
+	while ((c = *strp) != '\0' && c != delim)
+		++strp;
+	return strp;
+}
+
+/*
+** Given a pointer into a time zone string, extract a number from that string.
+** Check that the number is within a specified range; if it is not, return
+** NULL.
+** Otherwise, return a pointer to the first character not part of the number.
+*/
+
+static const char *
+getnum(strp, nump, min, max)
+register const char *	strp;
+int * const		nump;
+const int		min;
+const int		max;
+{
+	register char	c;
+	register int	num;
+
+	if (strp == NULL || !is_digit(c = *strp))
+		return NULL;
+	num = 0;
+	do {
+		num = num * 10 + (c - '0');
+		if (num > max)
+			return NULL;	/* illegal value */
+		c = *++strp;
+	} while (is_digit(c));
+	if (num < min)
+		return NULL;		/* illegal value */
+	*nump = num;
+	return strp;
+}
+
+/*
+** Given a pointer into a time zone string, extract a number of seconds,
+** in hh[:mm[:ss]] form, from the string.
+** If any error occurs, return NULL.
+** Otherwise, return a pointer to the first character not part of the number
+** of seconds.
+*/
+
+static const char *
+getsecs(strp, secsp)
+register const char *	strp;
+long * const		secsp;
+{
+	int	num;
+
+	/*
+	** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
+	** "M10.4.6/26", which does not conform to Posix,
+	** but which specifies the equivalent of
+	** ``02:00 on the first Sunday on or after 23 Oct''.
+	*/
+	strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
+	if (strp == NULL)
+		return NULL;
+	*secsp = num * (long) SECSPERHOUR;
+	if (*strp == ':') {
+		++strp;
+		strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
+		if (strp == NULL)
+			return NULL;
+		*secsp += num * SECSPERMIN;
+		if (*strp == ':') {
+			++strp;
+			/* `SECSPERMIN' allows for leap seconds. */
+			strp = getnum(strp, &num, 0, SECSPERMIN);
+			if (strp == NULL)
+				return NULL;
+			*secsp += num;
+		}
+	}
+	return strp;
+}
+
+/*
+** Given a pointer into a time zone string, extract an offset, in
+** [+-]hh[:mm[:ss]] form, from the string.
+** If any error occurs, return NULL.
+** Otherwise, return a pointer to the first character not part of the time.
+*/
+
+static const char *
+getoffset(strp, offsetp)
+register const char *	strp;
+long * const		offsetp;
+{
+	register int	neg = 0;
+
+	if (*strp == '-') {
+		neg = 1;
+		++strp;
+	} else if (*strp == '+')
+		++strp;
+	strp = getsecs(strp, offsetp);
+	if (strp == NULL)
+		return NULL;		/* illegal time */
+	if (neg)
+		*offsetp = -*offsetp;
+	return strp;
+}
+
+/*
+** Given a pointer into a time zone string, extract a rule in the form
+** date[/time]. See POSIX section 8 for the format of "date" and "time".
+** If a valid rule is not found, return NULL.
+** Otherwise, return a pointer to the first character not part of the rule.
+*/
+
+static const char *
+getrule(strp, rulep)
+const char *			strp;
+register struct rule * const	rulep;
+{
+	if (*strp == 'J') {
+		/*
+		** Julian day.
+		*/
+		rulep->r_type = JULIAN_DAY;
+		++strp;
+		strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
+	} else if (*strp == 'M') {
+		/*
+		** Month, week, day.
+		*/
+		rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
+		++strp;
+		strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
+		if (strp == NULL)
+			return NULL;
+		if (*strp++ != '.')
+			return NULL;
+		strp = getnum(strp, &rulep->r_week, 1, 5);
+		if (strp == NULL)
+			return NULL;
+		if (*strp++ != '.')
+			return NULL;
+		strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
+	} else if (is_digit(*strp)) {
+		/*
+		** Day of year.
+		*/
+		rulep->r_type = DAY_OF_YEAR;
+		strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
+	} else	return NULL;		/* invalid format */
+	if (strp == NULL)
+		return NULL;
+	if (*strp == '/') {
+		/*
+		** Time specified.
+		*/
+		++strp;
+		strp = getsecs(strp, &rulep->r_time);
+	} else	rulep->r_time = 2 * SECSPERHOUR;	/* default = 2:00:00 */
+	return strp;
+}
+
+/*
+** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
+** year, a rule, and the offset from UTC at the time that rule takes effect,
+** calculate the Epoch-relative time that rule takes effect.
+*/
+
+static time_t
+transtime(janfirst, year, rulep, offset)
+const time_t				janfirst;
+const int				year;
+register const struct rule * const	rulep;
+const long				offset;
+{
+	register int	leapyear;
+	register time_t	value;
+	register int	i;
+	int		d, m1, yy0, yy1, yy2, dow;
+
+	INITIALIZE(value);
+	leapyear = isleap(year);
+	switch (rulep->r_type) {
+
+	case JULIAN_DAY:
+		/*
+		** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
+		** years.
+		** In non-leap years, or if the day number is 59 or less, just
+		** add SECSPERDAY times the day number-1 to the time of
+		** January 1, midnight, to get the day.
+		*/
+		value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
+		if (leapyear && rulep->r_day >= 60)
+			value += SECSPERDAY;
+		break;
+
+	case DAY_OF_YEAR:
+		/*
+		** n - day of year.
+		** Just add SECSPERDAY times the day number to the time of
+		** January 1, midnight, to get the day.
+		*/
+		value = janfirst + rulep->r_day * SECSPERDAY;
+		break;
+
+	case MONTH_NTH_DAY_OF_WEEK:
+		/*
+		** Mm.n.d - nth "dth day" of month m.
+		*/
+		value = janfirst;
+		for (i = 0; i < rulep->r_mon - 1; ++i)
+			value += mon_lengths[leapyear][i] * SECSPERDAY;
+
+		/*
+		** Use Zeller's Congruence to get day-of-week of first day of
+		** month.
+		*/
+		m1 = (rulep->r_mon + 9) % 12 + 1;
+		yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
+		yy1 = yy0 / 100;
+		yy2 = yy0 % 100;
+		dow = ((26 * m1 - 2) / 10 +
+			1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
+		if (dow < 0)
+			dow += DAYSPERWEEK;
+
+		/*
+		** "dow" is the day-of-week of the first day of the month. Get
+		** the day-of-month (zero-origin) of the first "dow" day of the
+		** month.
+		*/
+		d = rulep->r_day - dow;
+		if (d < 0)
+			d += DAYSPERWEEK;
+		for (i = 1; i < rulep->r_week; ++i) {
+			if (d + DAYSPERWEEK >=
+				mon_lengths[leapyear][rulep->r_mon - 1])
+					break;
+			d += DAYSPERWEEK;
+		}
+
+		/*
+		** "d" is the day-of-month (zero-origin) of the day we want.
+		*/
+		value += d * SECSPERDAY;
+		break;
+	}
+
+	/*
+	** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
+	** question. To get the Epoch-relative time of the specified local
+	** time on that day, add the transition time and the current offset
+	** from UTC.
+	*/
+	return value + rulep->r_time + offset;
+}
+
+/*
+** Given a POSIX section 8-style TZ string, fill in the rule tables as
+** appropriate.
+*/
+
+static int
+tzparse(name, sp, lastditch)
+const char *			name;
+register struct state * const	sp;
+const int			lastditch;
+{
+	const char *			stdname;
+	const char *			dstname;
+	size_t				stdlen;
+	size_t				dstlen;
+	long				stdoffset;
+	long				dstoffset;
+	register time_t *		atp;
+	register unsigned char *	typep;
+	register char *			cp;
+	register int			load_result;
+
+	INITIALIZE(dstname);
+	stdname = name;
+	if (lastditch) {
+		stdlen = strlen(name);	/* length of standard zone name */
+		name += stdlen;
+		if (stdlen >= sizeof sp->chars)
+			stdlen = (sizeof sp->chars) - 1;
+		stdoffset = 0;
+	} else {
+		if (*name == '<') {
+			name++;
+			stdname = name;
+			name = getqzname(name, '>');
+			if (*name != '>')
+				return (-1);
+			stdlen = name - stdname;
+			name++;
+		} else {
+			name = getzname(name);
+			stdlen = name - stdname;
+		}
+		if (*name == '\0')
+			return -1;
+		name = getoffset(name, &stdoffset);
+		if (name == NULL)
+			return -1;
+	}
+	load_result = tzload(TZDEFRULES, sp, FALSE);
+	if (load_result != 0)
+		sp->leapcnt = 0;		/* so, we're off a little */
+	sp->timecnt = 0;
+	if (*name != '\0') {
+		if (*name == '<') {
+			dstname = ++name;
+			name = getqzname(name, '>');
+			if (*name != '>')
+				return -1;
+			dstlen = name - dstname;
+			name++;
+		} else {
+			dstname = name;
+			name = getzname(name);
+			dstlen = name - dstname; /* length of DST zone name */
+		}
+		if (*name != '\0' && *name != ',' && *name != ';') {
+			name = getoffset(name, &dstoffset);
+			if (name == NULL)
+				return -1;
+		} else	dstoffset = stdoffset - SECSPERHOUR;
+		if (*name == '\0' && load_result != 0)
+			name = TZDEFRULESTRING;
+		if (*name == ',' || *name == ';') {
+			struct rule	start;
+			struct rule	end;
+			register int	year;
+			register time_t	janfirst;
+			time_t		starttime;
+			time_t		endtime;
+
+			++name;
+			if ((name = getrule(name, &start)) == NULL)
+				return -1;
+			if (*name++ != ',')
+				return -1;
+			if ((name = getrule(name, &end)) == NULL)
+				return -1;
+			if (*name != '\0')
+				return -1;
+			sp->typecnt = 2;	/* standard time and DST */
+			/*
+			** Two transitions per year, from EPOCH_YEAR forward.
+			*/
+			sp->ttis[0].tt_gmtoff = -dstoffset;
+			sp->ttis[0].tt_isdst = 1;
+			sp->ttis[0].tt_abbrind = stdlen + 1;
+			sp->ttis[1].tt_gmtoff = -stdoffset;
+			sp->ttis[1].tt_isdst = 0;
+			sp->ttis[1].tt_abbrind = 0;
+			atp = sp->ats;
+			typep = sp->types;
+			janfirst = 0;
+			for (year = EPOCH_YEAR;
+			    sp->timecnt + 2 <= TZ_MAX_TIMES;
+			    ++year) {
+			    	time_t	newfirst;
+
+				starttime = transtime(janfirst, year, &start,
+					stdoffset);
+				endtime = transtime(janfirst, year, &end,
+					dstoffset);
+				if (starttime > endtime) {
+					*atp++ = endtime;
+					*typep++ = 1;	/* DST ends */
+					*atp++ = starttime;
+					*typep++ = 0;	/* DST begins */
+				} else {
+					*atp++ = starttime;
+					*typep++ = 0;	/* DST begins */
+					*atp++ = endtime;
+					*typep++ = 1;	/* DST ends */
+				}
+				sp->timecnt += 2;
+				newfirst = janfirst;
+				newfirst += year_lengths[isleap(year)] *
+					SECSPERDAY;
+				if (newfirst <= janfirst)
+					break;
+				janfirst = newfirst;
+			}
+		} else {
+			register long	theirstdoffset;
+			register long	theirdstoffset;
+			register long	theiroffset;
+			register int	isdst;
+			register int	i;
+			register int	j;
+
+			if (*name != '\0')
+				return -1;
+			/*
+			** Initial values of theirstdoffset and theirdstoffset.
+			*/
+			theirstdoffset = 0;
+			for (i = 0; i < sp->timecnt; ++i) {
+				j = sp->types[i];
+				if (!sp->ttis[j].tt_isdst) {
+					theirstdoffset =
+						-sp->ttis[j].tt_gmtoff;
+					break;
+				}
+			}
+			theirdstoffset = 0;
+			for (i = 0; i < sp->timecnt; ++i) {
+				j = sp->types[i];
+				if (sp->ttis[j].tt_isdst) {
+					theirdstoffset =
+						-sp->ttis[j].tt_gmtoff;
+					break;
+				}
+			}
+			/*
+			** Initially we're assumed to be in standard time.
+			*/
+			isdst = FALSE;
+			theiroffset = theirstdoffset;
+			/*
+			** Now juggle transition times and types
+			** tracking offsets as you do.
+			*/
+			for (i = 0; i < sp->timecnt; ++i) {
+				j = sp->types[i];
+				sp->types[i] = sp->ttis[j].tt_isdst;
+				if (sp->ttis[j].tt_ttisgmt) {
+					/* No adjustment to transition time */
+				} else {
+					/*
+					** If summer time is in effect, and the
+					** transition time was not specified as
+					** standard time, add the summer time
+					** offset to the transition time;
+					** otherwise, add the standard time
+					** offset to the transition time.
+					*/
+					/*
+					** Transitions from DST to DDST
+					** will effectively disappear since
+					** POSIX provides for only one DST
+					** offset.
+					*/
+					if (isdst && !sp->ttis[j].tt_ttisstd) {
+						sp->ats[i] += dstoffset -
+							theirdstoffset;
+					} else {
+						sp->ats[i] += stdoffset -
+							theirstdoffset;
+					}
+				}
+				theiroffset = -sp->ttis[j].tt_gmtoff;
+				if (sp->ttis[j].tt_isdst)
+					theirdstoffset = theiroffset;
+				else	theirstdoffset = theiroffset;
+			}
+			/*
+			** Finally, fill in ttis.
+			** ttisstd and ttisgmt need not be handled.
+			*/
+			sp->ttis[0].tt_gmtoff = -stdoffset;
+			sp->ttis[0].tt_isdst = FALSE;
+			sp->ttis[0].tt_abbrind = 0;
+			sp->ttis[1].tt_gmtoff = -dstoffset;
+			sp->ttis[1].tt_isdst = TRUE;
+			sp->ttis[1].tt_abbrind = stdlen + 1;
+			sp->typecnt = 2;
+		}
+	} else {
+		dstlen = 0;
+		sp->typecnt = 1;		/* only standard time */
+		sp->timecnt = 0;
+		sp->ttis[0].tt_gmtoff = -stdoffset;
+		sp->ttis[0].tt_isdst = 0;
+		sp->ttis[0].tt_abbrind = 0;
+	}
+	sp->charcnt = stdlen + 1;
+	if (dstlen != 0)
+		sp->charcnt += dstlen + 1;
+	if ((size_t) sp->charcnt > sizeof sp->chars)
+		return -1;
+	cp = sp->chars;
+	(void) strncpy(cp, stdname, stdlen);
+	cp += stdlen;
+	*cp++ = '\0';
+	if (dstlen != 0) {
+		(void) strncpy(cp, dstname, dstlen);
+		*(cp + dstlen) = '\0';
+	}
+	return 0;
+}
+
+static void
+gmtload(sp)
+struct state * const	sp;
+{
+	if (tzload(gmt, sp, TRUE) != 0)
+		(void) tzparse(gmt, sp, TRUE);
+}
+
+/*
+** The easy way to behave "as if no library function calls" localtime
+** is to not call it--so we drop its guts into "localsub", which can be
+** freely called. (And no, the PANS doesn't require the above behavior--
+** but it *is* desirable.)
+**
+** The unused offset argument is for the benefit of mktime variants.
+*/
+
+/*ARGSUSED*/
+static struct tm *
+localsub(timep, offset, tmp, sp)
+const time_t * const	timep;
+const long		offset;
+struct tm * const	tmp;
+const struct state *		sp;
+{
+	register const struct ttinfo *	ttisp;
+	register int			i;
+	register struct tm *		result;
+	const time_t			t = *timep;
+
+#ifdef ALL_STATE
+	if (sp == NULL)
+		return gmtsub(timep, offset, tmp);
+#endif /* defined ALL_STATE */
+	if ((sp->goback && t < sp->ats[0]) ||
+		(sp->goahead && t > sp->ats[sp->timecnt - 1])) {
+			time_t			newt = t;
+			register time_t		seconds;
+			register time_t		tcycles;
+			register int_fast64_t	icycles;
+
+			if (t < sp->ats[0])
+				seconds = sp->ats[0] - t;
+			else	seconds = t - sp->ats[sp->timecnt - 1];
+			--seconds;
+			tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
+			++tcycles;
+			icycles = tcycles;
+			if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
+				return NULL;
+			seconds = icycles;
+			seconds *= YEARSPERREPEAT;
+			seconds *= AVGSECSPERYEAR;
+			if (t < sp->ats[0])
+				newt += seconds;
+			else	newt -= seconds;
+			if (newt < sp->ats[0] ||
+				newt > sp->ats[sp->timecnt - 1])
+					return NULL;	/* "cannot happen" */
+			result = localsub(&newt, offset, tmp, sp);
+			if (result == tmp) {
+				register time_t	newy;
+
+				newy = tmp->tm_year;
+				if (t < sp->ats[0])
+					newy -= icycles * YEARSPERREPEAT;
+				else	newy += icycles * YEARSPERREPEAT;
+				tmp->tm_year = newy;
+				if (tmp->tm_year != newy)
+					return NULL;
+			}
+			return result;
+	}
+	if (sp->timecnt == 0 || t < sp->ats[0]) {
+		i = 0;
+		while (sp->ttis[i].tt_isdst)
+			if (++i >= sp->typecnt) {
+				i = 0;
+				break;
+			}
+	} else {
+		register int	lo = 1;
+		register int	hi = sp->timecnt;
+
+		while (lo < hi) {
+			register int	mid = (lo + hi) >> 1;
+
+			if (t < sp->ats[mid])
+				hi = mid;
+			else	lo = mid + 1;
+		}
+		i = (int) sp->types[lo - 1];
+	}
+	ttisp = &sp->ttis[i];
+	/*
+	** To get (wrong) behavior that's compatible with System V Release 2.0
+	** you'd replace the statement below with
+	**	t += ttisp->tt_gmtoff;
+	**	timesub(&t, 0L, sp, tmp);
+	*/
+	result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
+	tmp->tm_isdst = ttisp->tt_isdst;
+#ifdef HAVE_TM_GMTOFF
+	tmp->tm_gmtoff = ttisp->tt_gmtoff;
+#endif
+	tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
+#ifdef TM_ZONE
+	tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
+#endif /* defined TM_ZONE */
+	return result;
+}
+
+
+// ============================================================================
+#if 0
+struct tm *
+localtime(timep)
+const time_t * const	timep;
+{
+	tzset();
+	return localsub(timep, 0L, &tm);
+}
+#endif
+
+/*
+** Re-entrant version of localtime.
+*/
+
+// ============================================================================
+void
+localtime_tz(const time_t * const timep, struct tm * tmp, const char* tz)
+{
+    struct state st;
+    if (tzload(tz, &st, TRUE) != 0) {
+        // not sure what's best here, but for now, we fall back to gmt
+        gmtload(&st);
+    }
+
+	localsub(timep, 0L, tmp, &st);
+}
+
+/*
+** gmtsub is to gmtime as localsub is to localtime.
+*/
+
+static struct tm *
+gmtsub(timep, offset, tmp)
+const time_t * const	timep;
+const long		offset;
+struct tm * const	tmp;
+{
+	register struct tm *	result;
+
+	if (!gmt_is_set) {
+		gmt_is_set = TRUE;
+#ifdef ALL_STATE
+		gmtptr = (struct state *) malloc(sizeof *gmtptr);
+		if (gmtptr != NULL)
+#endif /* defined ALL_STATE */
+			gmtload(gmtptr);
+	}
+	result = timesub(timep, offset, gmtptr, tmp);
+#ifdef TM_ZONE
+	/*
+	** Could get fancy here and deliver something such as
+	** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
+	** but this is no time for a treasure hunt.
+	*/
+	if (offset != 0)
+		tmp->TM_ZONE = wildabbr;
+	else {
+#ifdef ALL_STATE
+		if (gmtptr == NULL)
+			tmp->TM_ZONE = gmt;
+		else	tmp->TM_ZONE = gmtptr->chars;
+#endif /* defined ALL_STATE */
+#ifndef ALL_STATE
+		tmp->TM_ZONE = gmtptr->chars;
+#endif /* State Farm */
+	}
+#endif /* defined TM_ZONE */
+	return result;
+}
+
+// ============================================================================
+#if 0
+struct tm *
+gmtime(timep)
+const time_t * const	timep;
+{
+	return gmtsub(timep, 0L, &tm);
+}
+#endif
+
+/*
+* Re-entrant version of gmtime.
+*/
+
+// ============================================================================
+#if 0
+struct tm *
+gmtime_r(timep, tmp)
+const time_t * const	timep;
+struct tm *		tmp;
+{
+	return gmtsub(timep, 0L, tmp);
+}
+#endif
+
+#ifdef STD_INSPIRED
+
+// ============================================================================
+#if 0
+struct tm *
+offtime(timep, offset)
+const time_t * const	timep;
+const long		offset;
+{
+	return gmtsub(timep, offset, &tm);
+}
+#endif
+
+#endif /* defined STD_INSPIRED */
+
+/*
+** Return the number of leap years through the end of the given year
+** where, to make the math easy, the answer for year zero is defined as zero.
+*/
+
+static int
+leaps_thru_end_of(y)
+register const int	y;
+{
+	return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
+		-(leaps_thru_end_of(-(y + 1)) + 1);
+}
+
+static struct tm *
+timesub(timep, offset, sp, tmp)
+const time_t * const			timep;
+const long				offset;
+register const struct state * const	sp;
+register struct tm * const		tmp;
+{
+	register const struct lsinfo *	lp;
+	register time_t			tdays;
+	register int			idays;	/* unsigned would be so 2003 */
+	register long			rem;
+	int				y;
+	register const int *		ip;
+	register long			corr;
+	register int			hit;
+	register int			i;
+
+	corr = 0;
+	hit = 0;
+#ifdef ALL_STATE
+	i = (sp == NULL) ? 0 : sp->leapcnt;
+#endif /* defined ALL_STATE */
+#ifndef ALL_STATE
+	i = sp->leapcnt;
+#endif /* State Farm */
+	while (--i >= 0) {
+		lp = &sp->lsis[i];
+		if (*timep >= lp->ls_trans) {
+			if (*timep == lp->ls_trans) {
+				hit = ((i == 0 && lp->ls_corr > 0) ||
+					lp->ls_corr > sp->lsis[i - 1].ls_corr);
+				if (hit)
+					while (i > 0 &&
+						sp->lsis[i].ls_trans ==
+						sp->lsis[i - 1].ls_trans + 1 &&
+						sp->lsis[i].ls_corr ==
+						sp->lsis[i - 1].ls_corr + 1) {
+							++hit;
+							--i;
+					}
+			}
+			corr = lp->ls_corr;
+			break;
+		}
+	}
+	y = EPOCH_YEAR;
+	tdays = *timep / SECSPERDAY;
+	rem = *timep - tdays * SECSPERDAY;
+	while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
+		int		newy;
+		register time_t	tdelta;
+		register int	idelta;
+		register int	leapdays;
+
+		tdelta = tdays / DAYSPERLYEAR;
+		idelta = tdelta;
+		if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
+			return NULL;
+		if (idelta == 0)
+			idelta = (tdays < 0) ? -1 : 1;
+		newy = y;
+		if (increment_overflow(&newy, idelta))
+			return NULL;
+		leapdays = leaps_thru_end_of(newy - 1) -
+			leaps_thru_end_of(y - 1);
+		tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
+		tdays -= leapdays;
+		y = newy;
+	}
+	{
+		register long	seconds;
+
+		seconds = tdays * SECSPERDAY + 0.5;
+		tdays = seconds / SECSPERDAY;
+		rem += seconds - tdays * SECSPERDAY;
+	}
+	/*
+	** Given the range, we can now fearlessly cast...
+	*/
+	idays = tdays;
+	rem += offset - corr;
+	while (rem < 0) {
+		rem += SECSPERDAY;
+		--idays;
+	}
+	while (rem >= SECSPERDAY) {
+		rem -= SECSPERDAY;
+		++idays;
+	}
+	while (idays < 0) {
+		if (increment_overflow(&y, -1))
+			return NULL;
+		idays += year_lengths[isleap(y)];
+	}
+	while (idays >= year_lengths[isleap(y)]) {
+		idays -= year_lengths[isleap(y)];
+		if (increment_overflow(&y, 1))
+			return NULL;
+	}
+	tmp->tm_year = y;
+	if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
+		return NULL;
+	tmp->tm_yday = idays;
+	/*
+	** The "extra" mods below avoid overflow problems.
+	*/
+	tmp->tm_wday = EPOCH_WDAY +
+		((y - EPOCH_YEAR) % DAYSPERWEEK) *
+		(DAYSPERNYEAR % DAYSPERWEEK) +
+		leaps_thru_end_of(y - 1) -
+		leaps_thru_end_of(EPOCH_YEAR - 1) +
+		idays;
+	tmp->tm_wday %= DAYSPERWEEK;
+	if (tmp->tm_wday < 0)
+		tmp->tm_wday += DAYSPERWEEK;
+	tmp->tm_hour = (int) (rem / SECSPERHOUR);
+	rem %= SECSPERHOUR;
+	tmp->tm_min = (int) (rem / SECSPERMIN);
+	/*
+	** A positive leap second requires a special
+	** representation. This uses "... ??:59:60" et seq.
+	*/
+	tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
+	ip = mon_lengths[isleap(y)];
+	for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
+		idays -= ip[tmp->tm_mon];
+	tmp->tm_mday = (int) (idays + 1);
+	tmp->tm_isdst = 0;
+#ifdef TM_GMTOFF
+	tmp->TM_GMTOFF = offset;
+#endif /* defined TM_GMTOFF */
+	return tmp;
+}
+
+// ============================================================================
+#if 0
+char *
+ctime(timep)
+const time_t * const	timep;
+{
+/*
+** Section 4.12.3.2 of X3.159-1989 requires that
+**	The ctime function converts the calendar time pointed to by timer
+**	to local time in the form of a string. It is equivalent to
+**		asctime(localtime(timer))
+*/
+	return asctime(localtime(timep));
+}
+#endif
+
+// ============================================================================
+#if 0
+char *
+ctime_r(timep, buf)
+const time_t * const	timep;
+char *			buf;
+{
+	struct tm	mytm;
+
+	return asctime_r(localtime_r(timep, &mytm), buf);
+}
+#endif
+
+/*
+** Adapted from code provided by Robert Elz, who writes:
+**	The "best" way to do mktime I think is based on an idea of Bob
+**	Kridle's (so its said...) from a long time ago.
+**	It does a binary search of the time_t space. Since time_t's are
+**	just 32 bits, its a max of 32 iterations (even at 64 bits it
+**	would still be very reasonable).
+*/
+
+#ifndef WRONG
+#define WRONG	(-1)
+#endif /* !defined WRONG */
+
+/*
+** Simplified normalize logic courtesy Paul Eggert.
+*/
+
+static int
+increment_overflow(number, delta)
+int *   number;
+int delta;
+{
+    unsigned  number0 = (unsigned)*number;
+    unsigned  number1 = (unsigned)(number0 + delta);
+
+    *number = (int)number1;
+
+    if (delta >= 0) {
+        return ((int)number1 < (int)number0);
+    } else {
+        return ((int)number1 > (int)number0);
+    }
+}
+
+static int
+long_increment_overflow(number, delta)
+long *  number;
+int delta;
+{
+    unsigned long  number0 = (unsigned long)*number;
+    unsigned long  number1 = (unsigned long)(number0 + delta);
+
+    *number = (long)number1;
+
+    if (delta >= 0) {
+        return ((long)number1 < (long)number0);
+    } else {
+        return ((long)number1 > (long)number0);
+    }
+}
+
+static int
+normalize_overflow(tensptr, unitsptr, base)
+int * const	tensptr;
+int * const	unitsptr;
+const int	base;
+{
+	register int	tensdelta;
+
+	tensdelta = (*unitsptr >= 0) ?
+		(*unitsptr / base) :
+		(-1 - (-1 - *unitsptr) / base);
+	*unitsptr -= tensdelta * base;
+	return increment_overflow(tensptr, tensdelta);
+}
+
+static int
+long_normalize_overflow(tensptr, unitsptr, base)
+long * const	tensptr;
+int * const	unitsptr;
+const int	base;
+{
+	register int	tensdelta;
+
+	tensdelta = (*unitsptr >= 0) ?
+		(*unitsptr / base) :
+		(-1 - (-1 - *unitsptr) / base);
+	*unitsptr -= tensdelta * base;
+	return long_increment_overflow(tensptr, tensdelta);
+}
+
+static int
+tmcomp(atmp, btmp)
+register const struct tm * const atmp;
+register const struct tm * const btmp;
+{
+	register int	result;
+
+	if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
+		(result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
+		(result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
+		(result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
+		(result = (atmp->tm_min - btmp->tm_min)) == 0)
+			result = atmp->tm_sec - btmp->tm_sec;
+	return result;
+}
+
+static time_t
+time2sub(tmp, funcp, offset, okayp, do_norm_secs, sp)
+struct tm * const	tmp;
+struct tm * (* const	funcp) P((const time_t*, long, struct tm*,const struct state *sp));
+const long		offset;
+int * const		okayp;
+const int		do_norm_secs;
+const struct state *	sp;
+{
+	register int			dir;
+	register int			i, j;
+	register int			saved_seconds;
+	register long			li;
+	register time_t			lo;
+	register time_t			hi;
+	long				y;
+	time_t				newt;
+	time_t				t;
+	struct tm			yourtm, mytm;
+
+	*okayp = FALSE;
+	yourtm = *tmp;
+	if (do_norm_secs) {
+		if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
+			SECSPERMIN))
+				return WRONG;
+	}
+	if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
+		return WRONG;
+	if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
+		return WRONG;
+	y = yourtm.tm_year;
+	if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
+		return WRONG;
+	/*
+	** Turn y into an actual year number for now.
+	** It is converted back to an offset from TM_YEAR_BASE later.
+	*/
+	if (long_increment_overflow(&y, TM_YEAR_BASE))
+		return WRONG;
+	while (yourtm.tm_mday <= 0) {
+		if (long_increment_overflow(&y, -1))
+			return WRONG;
+		li = y + (1 < yourtm.tm_mon);
+		yourtm.tm_mday += year_lengths[isleap(li)];
+	}
+	while (yourtm.tm_mday > DAYSPERLYEAR) {
+		li = y + (1 < yourtm.tm_mon);
+		yourtm.tm_mday -= year_lengths[isleap(li)];
+		if (long_increment_overflow(&y, 1))
+			return WRONG;
+	}
+	for ( ; ; ) {
+		i = mon_lengths[isleap(y)][yourtm.tm_mon];
+		if (yourtm.tm_mday <= i)
+			break;
+		yourtm.tm_mday -= i;
+		if (++yourtm.tm_mon >= MONSPERYEAR) {
+			yourtm.tm_mon = 0;
+			if (long_increment_overflow(&y, 1))
+				return WRONG;
+		}
+	}
+	if (long_increment_overflow(&y, -TM_YEAR_BASE))
+		return WRONG;
+	yourtm.tm_year = y;
+	if (yourtm.tm_year != y)
+		return WRONG;
+	if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
+		saved_seconds = 0;
+	else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
+		/*
+		** We can't set tm_sec to 0, because that might push the
+		** time below the minimum representable time.
+		** Set tm_sec to 59 instead.
+		** This assumes that the minimum representable time is
+		** not in the same minute that a leap second was deleted from,
+		** which is a safer assumption than using 58 would be.
+		*/
+		if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
+			return WRONG;
+		saved_seconds = yourtm.tm_sec;
+		yourtm.tm_sec = SECSPERMIN - 1;
+	} else {
+		saved_seconds = yourtm.tm_sec;
+		yourtm.tm_sec = 0;
+	}
+	/*
+	** Do a binary search (this works whatever time_t's type is).
+	*/
+	if (!TYPE_SIGNED(time_t)) {
+		lo = 0;
+		hi = lo - 1;
+	} else if (!TYPE_INTEGRAL(time_t)) {
+		if (sizeof(time_t) > sizeof(float))
+			hi = (time_t) DBL_MAX;
+		else	hi = (time_t) FLT_MAX;
+		lo = -hi;
+	} else {
+		lo = 1;
+		for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
+			lo *= 2;
+		hi = -(lo + 1);
+	}
+	for ( ; ; ) {
+		t = lo / 2 + hi / 2;
+		if (t < lo)
+			t = lo;
+		else if (t > hi)
+			t = hi;
+		if ((*funcp)(&t, offset, &mytm, sp) == NULL) {
+			/*
+			** Assume that t is too extreme to be represented in
+			** a struct tm; arrange things so that it is less
+			** extreme on the next pass.
+			*/
+			dir = (t > 0) ? 1 : -1;
+		} else	dir = tmcomp(&mytm, &yourtm);
+		if (dir != 0) {
+			if (t == lo) {
+			        if (t == TIME_T_MAX)
+			             return WRONG;
+				++t;
+				++lo;
+			} else if (t == hi) {
+			        if (t == TIME_T_MIN)
+			             return WRONG;
+				--t;
+				--hi;
+			}
+			if (lo > hi)
+				return WRONG;
+			if (dir > 0)
+				hi = t;
+			else	lo = t;
+			continue;
+		}
+		if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
+			break;
+		/*
+		** Right time, wrong type.
+		** Hunt for right time, right type.
+		** It's okay to guess wrong since the guess
+		** gets checked.
+		*/
+		/*
+		** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
+		*/
+#ifdef ALL_STATE
+		if (sp == NULL)
+			return WRONG;
+#endif /* defined ALL_STATE */
+		for (i = sp->typecnt - 1; i >= 0; --i) {
+			if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
+				continue;
+			for (j = sp->typecnt - 1; j >= 0; --j) {
+				if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
+					continue;
+				newt = t + sp->ttis[j].tt_gmtoff -
+					sp->ttis[i].tt_gmtoff;
+				if ((*funcp)(&newt, offset, &mytm, sp) == NULL)
+					continue;
+				if (tmcomp(&mytm, &yourtm) != 0)
+					continue;
+				if (mytm.tm_isdst != yourtm.tm_isdst)
+					continue;
+				/*
+				** We have a match.
+				*/
+				t = newt;
+				goto label;
+			}
+		}
+		return WRONG;
+	}
+label:
+	newt = t + saved_seconds;
+	if ((newt < t) != (saved_seconds < 0))
+		return WRONG;
+	t = newt;
+	if ((*funcp)(&t, offset, tmp, sp))
+		*okayp = TRUE;
+	return t;
+}
+
+static time_t
+time2(tmp, funcp, offset, okayp, sp)
+struct tm * const	tmp;
+struct tm * (* const	funcp) P((const time_t*, long, struct tm*,
+            const struct state* sp));
+const long		offset;
+int * const		okayp;
+const struct state *	sp;
+{
+	time_t	t;
+
+	/*
+	** First try without normalization of seconds
+	** (in case tm_sec contains a value associated with a leap second).
+	** If that fails, try with normalization of seconds.
+	*/
+	t = time2sub(tmp, funcp, offset, okayp, FALSE, sp);
+	return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp);
+}
+
+static time_t
+time1(tmp, funcp, offset, sp)
+struct tm * const	tmp;
+struct tm * (* const	funcp) P((const time_t *, long, struct tm *, const struct state* sp));
+const long		offset;
+const struct state *	sp;
+{
+	register time_t			t;
+	register int			samei, otheri;
+	register int			sameind, otherind;
+	register int			i;
+	register int			nseen;
+	int				seen[TZ_MAX_TYPES];
+	int				types[TZ_MAX_TYPES];
+	int				okay;
+
+	if (tmp->tm_isdst > 1)
+		tmp->tm_isdst = 1;
+	t = time2(tmp, funcp, offset, &okay, sp);
+#define PCTS 1
+#ifdef PCTS
+	/*
+	** PCTS code courtesy Grant Sullivan.
+	*/
+	if (okay)
+		return t;
+	if (tmp->tm_isdst < 0)
+		tmp->tm_isdst = 0;	/* reset to std and try again */
+#endif /* defined PCTS */
+#ifndef PCTS
+	if (okay || tmp->tm_isdst < 0)
+		return t;
+#endif /* !defined PCTS */
+	/*
+	** We're supposed to assume that somebody took a time of one type
+	** and did some math on it that yielded a "struct tm" that's bad.
+	** We try to divine the type they started from and adjust to the
+	** type they need.
+	*/
+	/*
+	** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
+	*/
+#ifdef ALL_STATE
+	if (sp == NULL)
+		return WRONG;
+#endif /* defined ALL_STATE */
+	for (i = 0; i < sp->typecnt; ++i)
+		seen[i] = FALSE;
+	nseen = 0;
+	for (i = sp->timecnt - 1; i >= 0; --i)
+		if (!seen[sp->types[i]]) {
+			seen[sp->types[i]] = TRUE;
+			types[nseen++] = sp->types[i];
+		}
+	for (sameind = 0; sameind < nseen; ++sameind) {
+		samei = types[sameind];
+		if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
+			continue;
+		for (otherind = 0; otherind < nseen; ++otherind) {
+			otheri = types[otherind];
+			if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
+				continue;
+			tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
+					sp->ttis[samei].tt_gmtoff;
+			tmp->tm_isdst = !tmp->tm_isdst;
+			t = time2(tmp, funcp, offset, &okay, sp);
+			if (okay)
+				return t;
+			tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
+					sp->ttis[samei].tt_gmtoff;
+			tmp->tm_isdst = !tmp->tm_isdst;
+		}
+	}
+	return WRONG;
+}
+
+// ============================================================================
+time_t
+mktime_tz(struct tm * const	tmp, char const * tz)
+{
+    struct state st;
+    if (tzload(tz, &st, TRUE) != 0) {
+        // not sure what's best here, but for now, we fall back to gmt
+        gmtload(&st);
+    }
+	return time1(tmp, localsub, 0L, &st);
+}
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index d812abc..b91de52 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -134,7 +134,6 @@
 {
     struct iovec vec[3];
     log_id_t log_id = LOG_ID_MAIN;
-    char tmp_tag[32];
 
     if (!tag)
         tag = "";
@@ -148,12 +147,8 @@
         !strcmp(tag, "STK") ||
         !strcmp(tag, "CDMA") ||
         !strcmp(tag, "PHONE") ||
-        !strcmp(tag, "SMS")) {
+        !strcmp(tag, "SMS"))
             log_id = LOG_ID_RADIO;
-            // Inform third party apps/ril/radio.. to use Rlog or RLOG
-            snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
-            tag = tmp_tag;
-    }
 
     vec[0].iov_base   = (unsigned char *) &prio;
     vec[0].iov_len    = 1;
@@ -168,14 +163,12 @@
 int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg)
 {
     struct iovec vec[3];
-    char tmp_tag[32];
 
     if (!tag)
         tag = "";
 
     /* XXX: This needs to go! */
-    if ((bufID != LOG_ID_RADIO) &&
-         (!strcmp(tag, "HTC_RIL") ||
+    if (!strcmp(tag, "HTC_RIL") ||
         !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */
         !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */
         !strcmp(tag, "AT") ||
@@ -183,12 +176,8 @@
         !strcmp(tag, "STK") ||
         !strcmp(tag, "CDMA") ||
         !strcmp(tag, "PHONE") ||
-        !strcmp(tag, "SMS"))) {
+        !strcmp(tag, "SMS"))
             bufID = LOG_ID_RADIO;
-            // Inform third party apps/ril/radio.. to use Rlog or RLOG
-            snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
-            tag = tmp_tag;
-    }
 
     vec[0].iov_base   = (unsigned char *) &prio;
     vec[0].iov_len    = 1;
diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c
index b4caaf9..d0ca90a 100644
--- a/libnetutils/dhcp_utils.c
+++ b/libnetutils/dhcp_utils.c
@@ -211,7 +211,7 @@
                  p2p_interface, DHCP_CONFIG_PATH, prop_value, interface);
     else
         snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s:-f %s %s", DAEMON_NAME,
-                 p2p_interface, DHCP_CONFIG_PATH, interface);
+                 DHCP_CONFIG_PATH, p2p_interface, interface);
     memset(prop_value, '\0', PROPERTY_VALUE_MAX);
     property_set(ctrl_prop, daemon_cmd);
     if (wait_for_property(daemon_prop_name, desired_status, 10) < 0) {
diff --git a/libsuspend/Android.mk b/libsuspend/Android.mk
index 45cb701..a2fa3e0 100644
--- a/libsuspend/Android.mk
+++ b/libsuspend/Android.mk
@@ -12,7 +12,6 @@
 	liblog libcutils
 
 include $(CLEAR_VARS)
-
 LOCAL_SRC_FILES := $(libsuspend_src_files)
 LOCAL_MODULE := libsuspend
 LOCAL_MODULE_TAGS := optional
@@ -21,3 +20,12 @@
 LOCAL_SHARED_LIBRARIES := $(libsuspend_libraries)
 #LOCAL_CFLAGS += -DLOG_NDEBUG=0
 include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(libsuspend_src_files)
+LOCAL_MODULE := libsuspend
+LOCAL_MODULE_TAGS := optional
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
+#LOCAL_CFLAGS += -DLOG_NDEBUG=0
+include $(BUILD_STATIC_LIBRARY)
diff --git a/libsuspend/autosuspend.c b/libsuspend/autosuspend.c
index eb1f66e..7d1d973 100644
--- a/libsuspend/autosuspend.c
+++ b/libsuspend/autosuspend.c
@@ -33,6 +33,8 @@
         return 0;
     }
 
+    autosuspend_inited = true;
+
     autosuspend_ops = autosuspend_earlysuspend_init();
     if (autosuspend_ops) {
         goto out;
@@ -54,8 +56,6 @@
     }
 
 out:
-    autosuspend_inited = true;
-
     ALOGV("autosuspend initialized\n");
     return 0;
 }
diff --git a/libsysutils/src/FrameworkListener.cpp b/libsysutils/src/FrameworkListener.cpp
index 02a401d..6731cf1 100644
--- a/libsysutils/src/FrameworkListener.cpp
+++ b/libsysutils/src/FrameworkListener.cpp
@@ -25,8 +25,6 @@
 #include <sysutils/FrameworkCommand.h>
 #include <sysutils/SocketClient.h>
 
-static const int CMD_BUF_SIZE = 1024;
-
 FrameworkListener::FrameworkListener(const char *socketName, bool withSeq) :
                             SocketListener(socketName, true, withSeq) {
     init(socketName, withSeq);
@@ -45,7 +43,7 @@
 }
 
 bool FrameworkListener::onDataAvailable(SocketClient *c) {
-    char buffer[CMD_BUF_SIZE];
+    char buffer[255];
     int len;
 
     len = TEMP_FAILURE_RETRY(read(c->getSocket(), buffer, sizeof(buffer)));
@@ -54,8 +52,6 @@
         return false;
     } else if (!len)
         return false;
-   if(buffer[len-1] != '\0')
-        SLOGW("String is not zero-terminated");
 
     int offset = 0;
     int i;
@@ -67,7 +63,6 @@
             offset = i + 1;
         }
     }
-
     return true;
 }
 
@@ -79,7 +74,7 @@
     FrameworkCommandCollection::iterator i;
     int argc = 0;
     char *argv[FrameworkListener::CMD_ARGS_MAX];
-    char tmp[CMD_BUF_SIZE];
+    char tmp[255];
     char *p = data;
     char *q = tmp;
     char *qlimit = tmp + sizeof(tmp) - 1;
@@ -185,6 +180,7 @@
             goto out;
         }
     }
+
     cli->sendMsg(500, "Command not recognized", false);
 out:
     int j;
diff --git a/libusbhost/Android.mk b/libusbhost/Android.mk
index 9565cc5..52b4ead 100644
--- a/libusbhost/Android.mk
+++ b/libusbhost/Android.mk
@@ -44,13 +44,3 @@
 LOCAL_SHARED_LIBRARIES := libcutils
 
 include $(BUILD_SHARED_LIBRARY)
-
-# Static library for target
-# ========================================================
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libusbhost
-LOCAL_SRC_FILES := usbhost.c
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/libusbhost/usbhost.c b/libusbhost/usbhost.c
index 167fa60..c059b89 100644
--- a/libusbhost/usbhost.c
+++ b/libusbhost/usbhost.c
@@ -33,7 +33,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
-#include <stddef.h>
 
 #include <sys/ioctl.h>
 #include <sys/types.h>
@@ -51,23 +50,16 @@
 #include "usbhost/usbhost.h"
 
 #define DEV_DIR             "/dev"
-#define USB_FS_DIR          DEV_DIR "/bus/usb"
-#define USB_FS_ID_SCANNER   USB_FS_DIR "/%d/%d"
-#define USB_FS_ID_FORMAT    USB_FS_DIR "/%03d/%03d"
+#define USB_FS_DIR          "/dev/bus/usb"
+#define USB_FS_ID_SCANNER   "/dev/bus/usb/%d/%d"
+#define USB_FS_ID_FORMAT    "/dev/bus/usb/%03d/%03d"
 
 // From drivers/usb/core/devio.c
 // I don't know why this isn't in a kernel header
 #define MAX_USBFS_BUFFER_SIZE   16384
 
-#define MAX_USBFS_WD_COUNT      10
-
 struct usb_host_context {
-    int                         fd;
-    usb_device_added_cb         cb_added;
-    usb_device_removed_cb       cb_removed;
-    void                        *data;
-    int                         wds[MAX_USBFS_WD_COUNT];
-    int                         wdd;
+    int fd;
 };
 
 struct usb_device {
@@ -124,10 +116,10 @@
     while ((de = readdir(busdir)) != 0 && !done) {
         if(badname(de->d_name)) continue;
 
-        snprintf(busname, sizeof(busname), USB_FS_DIR "/%s", de->d_name);
+        snprintf(busname, sizeof(busname), "%s/%s", USB_FS_DIR, de->d_name);
         done = find_existing_devices_bus(busname, added_cb,
                                          client_data);
-    } //end of busdir while
+    }
     closedir(busdir);
 
     return done;
@@ -145,7 +137,7 @@
 
     /* watch existing subdirectories of USB_FS_DIR */
     for (i = 1; i < wd_count; i++) {
-        snprintf(path, sizeof(path), USB_FS_DIR "/%03d", i);
+        snprintf(path, sizeof(path), "%s/%03d", USB_FS_DIR, i);
         ret = inotify_add_watch(context->fd, path, IN_CREATE | IN_DELETE);
         if (ret >= 0)
             wds[i] = ret;
@@ -174,126 +166,93 @@
     free(context);
 }
 
-int usb_host_get_fd(struct usb_host_context *context)
-{
-    return context->fd;
-} /* usb_host_get_fd() */
-
-int usb_host_load(struct usb_host_context *context,
-                  usb_device_added_cb added_cb,
-                  usb_device_removed_cb removed_cb,
-                  usb_discovery_done_cb discovery_done_cb,
-                  void *client_data)
-{
-    int done = 0;
-    int i;
-
-    context->cb_added = added_cb;
-    context->cb_removed = removed_cb;
-    context->data = client_data;
-
-    D("Created device discovery thread\n");
-
-    /* watch for files added and deleted within USB_FS_DIR */
-    for (i = 0; i < MAX_USBFS_WD_COUNT; i++)
-        context->wds[i] = -1;
-
-    /* watch the root for new subdirectories */
-    context->wdd = inotify_add_watch(context->fd, DEV_DIR, IN_CREATE | IN_DELETE);
-    if (context->wdd < 0) {
-        fprintf(stderr, "inotify_add_watch failed\n");
-        if (discovery_done_cb)
-            discovery_done_cb(client_data);
-        return done;
-    }
-
-    watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT);
-
-    /* check for existing devices first, after we have inotify set up */
-    done = find_existing_devices(added_cb, client_data);
-    if (discovery_done_cb)
-        done |= discovery_done_cb(client_data);
-
-    return done;
-} /* usb_host_load() */
-
-int usb_host_read_event(struct usb_host_context *context)
-{
-    struct inotify_event* event;
-    char event_buf[512];
-    char path[100];
-    int i, ret, done = 0;
-    int j, event_size;
-    int wd;
-
-    ret = read(context->fd, event_buf, sizeof(event_buf));
-    if (ret >= (int)sizeof(struct inotify_event)) {
-        event = (struct inotify_event *)event_buf;
-        wd = event->wd;
-        if (wd == context->wdd) {
-            if ((event->mask & IN_CREATE) && !strcmp(event->name, "bus")) {
-                watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT);
-                done = find_existing_devices(context->cb_added, context->data);
-            } else if ((event->mask & IN_DELETE) && !strcmp(event->name, "bus")) {
-                for (i = 0; i < MAX_USBFS_WD_COUNT; i++) {
-                    if (context->wds[i] >= 0) {
-                        inotify_rm_watch(context->fd, context->wds[i]);
-                        context->wds[i] = -1;
-                    }
-                }
-            }
-        } else if (wd == context->wds[0]) {
-            i = atoi(event->name);
-            snprintf(path, sizeof(path), USB_FS_DIR "/%s", event->name);
-            D("%s subdirectory %s: index: %d\n", (event->mask & IN_CREATE) ?
-                    "new" : "gone", path, i);
-            if (i > 0 && i < MAX_USBFS_WD_COUNT) {
-                if (event->mask & IN_CREATE) {
-                    ret = inotify_add_watch(context->fd, path,
-                            IN_CREATE | IN_DELETE);
-                    if (ret >= 0)
-                        context->wds[i] = ret;
-                    done = find_existing_devices_bus(path, context->cb_added,
-                            context->data);
-                } else if (event->mask & IN_DELETE) {
-                    inotify_rm_watch(context->fd, context->wds[i]);
-                    context->wds[i] = -1;
-                }
-            }
-        } else {
-            for (i = 1; (i < MAX_USBFS_WD_COUNT) && !done; i++) {
-                if (wd == context->wds[i]) {
-                    snprintf(path, sizeof(path), USB_FS_DIR "/%03d/%s", i, event->name);
-                    if (event->mask == IN_CREATE) {
-                        D("new device %s\n", path);
-                        done = context->cb_added(path, context->data);
-                    } else if (event->mask == IN_DELETE) {
-                        D("gone device %s\n", path);
-                        done = context->cb_removed(path, context->data);
-                    }
-                }
-            }
-        }
-    }
-
-    return done;
-} /* usb_host_read_event() */
-
 void usb_host_run(struct usb_host_context *context,
                   usb_device_added_cb added_cb,
                   usb_device_removed_cb removed_cb,
                   usb_discovery_done_cb discovery_done_cb,
                   void *client_data)
 {
-    int done;
+    struct inotify_event* event;
+    char event_buf[512];
+    char path[100];
+    int i, ret, done = 0;
+    int wd, wdd, wds[10];
+    int wd_count = sizeof(wds) / sizeof(wds[0]);
 
-    done = usb_host_load(context, added_cb, removed_cb, discovery_done_cb, client_data);
+    D("Created device discovery thread\n");
+
+    /* watch for files added and deleted within USB_FS_DIR */
+    for (i = 0; i < wd_count; i++)
+        wds[i] = -1;
+
+    /* watch the root for new subdirectories */
+    wdd = inotify_add_watch(context->fd, DEV_DIR, IN_CREATE | IN_DELETE);
+    if (wdd < 0) {
+        fprintf(stderr, "inotify_add_watch failed\n");
+        if (discovery_done_cb)
+            discovery_done_cb(client_data);
+        return;
+    }
+
+    watch_existing_subdirs(context, wds, wd_count);
+
+    /* check for existing devices first, after we have inotify set up */
+    done = find_existing_devices(added_cb, client_data);
+    if (discovery_done_cb)
+        done |= discovery_done_cb(client_data);
 
     while (!done) {
-
-        done = usb_host_read_event(context);
+        ret = read(context->fd, event_buf, sizeof(event_buf));
+        if (ret >= (int)sizeof(struct inotify_event)) {
+            event = (struct inotify_event *)event_buf;
+            wd = event->wd;
+            if (wd == wdd) {
+                if ((event->mask & IN_CREATE) && !strcmp(event->name, "bus")) {
+                    watch_existing_subdirs(context, wds, wd_count);
+                    done = find_existing_devices(added_cb, client_data);
+                } else if ((event->mask & IN_DELETE) && !strcmp(event->name, "bus")) {
+                    for (i = 0; i < wd_count; i++) {
+                        if (wds[i] >= 0) {
+                            inotify_rm_watch(context->fd, wds[i]);
+                            wds[i] = -1;
+                        }
+                    }
+                }
+            } else if (wd == wds[0]) {
+                i = atoi(event->name);
+                snprintf(path, sizeof(path), "%s/%s", USB_FS_DIR, event->name);
+                D("%s subdirectory %s: index: %d\n", (event->mask & IN_CREATE) ?
+                                                     "new" : "gone", path, i);
+                if (i > 0 && i < wd_count) {
+                    if (event->mask & IN_CREATE) {
+                        ret = inotify_add_watch(context->fd, path,
+                                                IN_CREATE | IN_DELETE);
+                        if (ret >= 0)
+                            wds[i] = ret;
+                        done = find_existing_devices_bus(path, added_cb,
+                                                         client_data);
+                    } else if (event->mask & IN_DELETE) {
+                        inotify_rm_watch(context->fd, wds[i]);
+                        wds[i] = -1;
+                    }
+                }
+            } else {
+                for (i = 1; i < wd_count && !done; i++) {
+                    if (wd == wds[i]) {
+                        snprintf(path, sizeof(path), "%s/%03d/%s", USB_FS_DIR, i, event->name);
+                        if (event->mask == IN_CREATE) {
+                            D("new device %s\n", path);
+                            done = added_cb(path, client_data);
+                        } else if (event->mask == IN_DELETE) {
+                            D("gone device %s\n", path);
+                            done = removed_cb(path, client_data);
+                        }
+                    }
+                }
+            }
+        }
     }
-} /* usb_host_run() */
+}
 
 struct usb_device *usb_device_open(const char *dev_name)
 {
@@ -647,6 +606,7 @@
 {
     struct usbdevfs_urb *urb = NULL;
     struct usb_request *req = NULL;
+    int res;
 
     while (1) {
         int res = ioctl(dev->fd, USBDEVFS_REAPURB, &urb);
diff --git a/rootdir/etc/init.goldfish.rc b/rootdir/etc/init.goldfish.rc
index a0c1c4f..cde9dee 100644
--- a/rootdir/etc/init.goldfish.rc
+++ b/rootdir/etc/init.goldfish.rc
@@ -5,7 +5,7 @@
     symlink /mnt/sdcard /sdcard
 
 on boot
-    setsebool in_qemu 1
+    setsebool in_qemu=1
     restorecon /sys/qemu_trace/process_name
     restorecon /sys/qemu_trace/state
     restorecon /sys/qemu_trace/symbol
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 5205200..caef358 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -120,12 +120,6 @@
     write /dev/cpuctl/apps/bg_non_interactive/cpu.rt_runtime_us 700000
     write /dev/cpuctl/apps/bg_non_interactive/cpu.rt_period_us 1000000
 
-# qtaguid will limit access to specific data based on group memberships.
-#   net_bw_acct grants impersonation of socket owners.
-#   net_bw_stats grants access to other apps' detailed tagged-socket stats.
-    chown root net_bw_acct /proc/net/xt_qtaguid/ctrl
-    chown root net_bw_stats /proc/net/xt_qtaguid/stats
-
 # Allow everybody to read the xt_qtaguid resource tracking misc dev.
 # This is needed by any process that uses socket tagging.
     chmod 0644 /dev/xt_qtaguid
@@ -206,7 +200,6 @@
     mkdir /data/misc/keystore 0700 keystore keystore
     mkdir /data/misc/keychain 0771 system system
     mkdir /data/misc/sms 0770 system radio
-    mkdir /data/misc/zoneinfo 0775 system system
     mkdir /data/misc/vpn 0770 system vpn
     mkdir /data/misc/systemkeys 0700 system system
     # give system access to wpa_supplicant.conf for backup and restore
@@ -501,6 +494,7 @@
     class main
     user keystore
     group keystore drmrpc
+    socket keystore stream 666
 
 service dumpstate /system/bin/dumpstate -s
     class main
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index dbbce06..086ba0d 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -57,7 +57,11 @@
 	touch \
 	lsof \
 	du \
-	md5 \
+	md5
+
+ifeq ($(HAVE_SELINUX),true)
+
+TOOLS += \
 	getenforce \
 	setenforce \
 	chcon \
@@ -67,6 +71,9 @@
 	setsebool \
 	load_policy
 
+endif
+
+
 ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
 TOOLS += r
 endif
@@ -83,13 +90,17 @@
 	cp/cp.c cp/utils.c \
 	grep/grep.c grep/fastgrep.c grep/file.c grep/queue.c grep/util.c
 
+LOCAL_SHARED_LIBRARIES := libcutils libc libusbhost
+
 LOCAL_C_INCLUDES := bionic/libc/bionic
 
-LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-	libc \
-	libusbhost \
-	libselinux
+ifeq ($(HAVE_SELINUX),true)
+
+LOCAL_CFLAGS += -DHAVE_SELINUX
+LOCAL_SHARED_LIBRARIES += libselinux
+LOCAL_C_INCLUDES += external/libselinux/include
+
+endif
 
 LOCAL_MODULE := toolbox
 
diff --git a/toolbox/df.c b/toolbox/df.c
index 9cd0743..63940a1 100644
--- a/toolbox/df.c
+++ b/toolbox/df.c
@@ -9,22 +9,16 @@
 static void printsize(long long n)
 {
     char unit = 'K';
-    long long t;
-
-    n *= 10;
-
-    if (n > 1024*1024*10) {
+    n /= 1024;
+    if (n > 1024) {
         n /= 1024;
         unit = 'M';
     }
-
-    if (n > 1024*1024*10) {
+    if (n > 1024) {
         n /= 1024;
         unit = 'G';
     }
-
-    t = (n + 512) / 1024;
-    printf("%4lld.%1lld%c", t/10, t%10, unit);
+    printf("%4lld%c", n, unit);
 }
 
 static void df(char *s, int always) {
@@ -47,7 +41,7 @@
 }
 
 int df_main(int argc, char *argv[]) {
-    printf("Filesystem               Size     Used     Free   Blksize\n");
+    printf("Filesystem             Size   Used   Free   Blksize\n");
     if (argc == 1) {
         char s[2000];
         FILE *f = fopen("/proc/mounts", "r");
diff --git a/toolbox/id.c b/toolbox/id.c
index 8ec79c1..bc79288 100644
--- a/toolbox/id.c
+++ b/toolbox/id.c
@@ -4,7 +4,10 @@
 #include <sys/types.h>
 #include <pwd.h>
 #include <grp.h>
+
+#ifdef HAVE_SELINUX
 #include <selinux/selinux.h>
+#endif
 
 static void print_uid(uid_t uid)
 {
@@ -31,7 +34,9 @@
 {
     gid_t list[64];
     int n, max;
+#ifdef HAVE_SELINUX
     char *secctx;
+#endif
 
     max = getgroups(64, list);
     if (max < 0) max = 0;
@@ -48,10 +53,12 @@
             print_gid(list[n]);
         }
     }
+#ifdef HAVE_SELINUX
     if (getcon(&secctx) == 0) {
         printf(" context=%s", secctx);
         free(secctx);
     }
+#endif
     printf("\n");
     return 0;
 }
diff --git a/toolbox/ls.c b/toolbox/ls.c
index e530521..a4db99c 100644
--- a/toolbox/ls.c
+++ b/toolbox/ls.c
@@ -5,7 +5,9 @@
 #include <dirent.h>
 #include <errno.h>
 
+#ifdef HAVE_SELINUX
 #include <selinux/selinux.h>
+#endif
 
 #include <sys/stat.h>
 #include <unistd.h>
@@ -258,7 +260,11 @@
         return -1;
     }
 
+#ifdef HAVE_SELINUX
     lgetfilecon(path, &maclabel);
+#else
+    maclabel = strdup("-");
+#endif
     if (!maclabel) {
         return -1;
     }
@@ -270,12 +276,12 @@
     switch(s.st_mode & S_IFMT) {
     case S_IFLNK: {
         char linkto[256];
-        ssize_t len;
+        int len;
 
         len = readlink(path, linkto, sizeof(linkto));
         if(len < 0) return -1;
 
-        if((size_t)len > sizeof(linkto)-1) {
+        if(len > sizeof(linkto)-1) {
             linkto[sizeof(linkto)-4] = '.';
             linkto[sizeof(linkto)-3] = '.';
             linkto[sizeof(linkto)-2] = '.';
@@ -301,7 +307,7 @@
 
 static int listfile(const char *dirname, const char *filename, int flags)
 {
-    if ((flags & (LIST_LONG | LIST_SIZE | LIST_CLASSIFY | LIST_MACLABEL)) == 0) {
+    if ((flags & LIST_LONG | LIST_SIZE | LIST_CLASSIFY | LIST_MACLABEL) == 0) {
         printf("%s\n", filename);
         return 0;
     }
diff --git a/toolbox/setsebool.c b/toolbox/setsebool.c
index f79a612..4a3d87d 100644
--- a/toolbox/setsebool.c
+++ b/toolbox/setsebool.c
@@ -9,26 +9,35 @@
 #include <errno.h>
 
 static int do_setsebool(int nargs, char **args) {
-    const char *name = args[1];
-    const char *value = args[2];
-    SELboolean b;
+    SELboolean *b = alloca(nargs * sizeof(SELboolean));
+    char *v;
+    int i;
 
     if (is_selinux_enabled() <= 0)
         return 0;
 
-    b.name = name;
-    if (!strcmp(value, "1") || !strcasecmp(value, "true") || !strcasecmp(value, "on"))
-        b.value = 1;
-    else if (!strcmp(value, "0") || !strcasecmp(value, "false") || !strcasecmp(value, "off"))
-        b.value = 0;
-    else {
-        fprintf(stderr, "setsebool: invalid value %s\n", value);
-        return -1;
+    for (i = 1; i < nargs; i++) {
+        char *name = args[i];
+        v = strchr(name, '=');
+        if (!v) {
+            fprintf(stderr, "setsebool: argument %s had no =\n", name);
+            return -1;
+        }
+        *v++ = 0;
+        b[i-1].name = name;
+        if (!strcmp(v, "1") || !strcasecmp(v, "true") || !strcasecmp(v, "on"))
+            b[i-1].value = 1;
+        else if (!strcmp(v, "0") || !strcasecmp(v, "false") || !strcasecmp(v, "off"))
+            b[i-1].value = 0;
+        else {
+            fprintf(stderr, "setsebool: invalid value %s\n", v);
+            return -1;
+        }
     }
 
-    if (security_set_boolean_list(1, &b, 0) < 0)
+    if (security_set_boolean_list(nargs - 1, b, 0) < 0)
     {
-        fprintf(stderr, "setsebool: could not set %s to %s:  %s", name, value, strerror(errno));
+        fprintf(stderr, "setsebool: unable to set booleans: %s", strerror(errno));
         return -1;
     }
 
@@ -37,8 +46,8 @@
 
 int setsebool_main(int argc, char **argv)
 {
-    if (argc != 3) {
-        fprintf(stderr, "Usage:  %s name value\n", argv[0]);
+    if (argc < 2) {
+        fprintf(stderr, "Usage:  %s name=value...\n", argv[0]);
         exit(1);
     }