Merge "tombstoned: don't create tombstones for failed dumps."
diff --git a/adb/Android.bp b/adb/Android.bp
index 46bc02b..b9a1596 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -369,6 +369,7 @@
         "libusb",
         "libmdnssd",
     ],
+    test_suites: ["device-tests"],
 }
 
 python_binary_host {
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 4fbfafb..3bf281c 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -132,6 +132,7 @@
 {
     D("adb: online");
     t->online = 1;
+    t->SetConnectionEstablished(true);
 }
 
 void handle_offline(atransport *t)
@@ -1221,7 +1222,7 @@
     std::string error;
     atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &error);
     if (!t) {
-        return SendFail(reply_fd, error);
+        return -1;
     }
 
     int ret = handle_forward_request(service, t, reply_fd);
diff --git a/adb/test_adb.py b/adb/test_adb.py
index 3bb433d..32bf029 100644
--- a/adb/test_adb.py
+++ b/adb/test_adb.py
@@ -21,9 +21,11 @@
 """
 from __future__ import print_function
 
+import binascii
 import contextlib
 import os
 import random
+import select
 import socket
 import struct
 import subprocess
@@ -33,6 +35,68 @@
 import adb
 
 
+@contextlib.contextmanager
+def fake_adb_server(protocol=socket.AF_INET, port=0):
+    """Creates a fake ADB server that just replies with a CNXN packet."""
+
+    serversock = socket.socket(protocol, socket.SOCK_STREAM)
+    if protocol == socket.AF_INET:
+        serversock.bind(('127.0.0.1', port))
+    else:
+        serversock.bind(('::1', port))
+    serversock.listen(1)
+
+    # A pipe that is used to signal the thread that it should terminate.
+    readpipe, writepipe = os.pipe()
+
+    def _adb_packet(command, arg0, arg1, data):
+        bin_command = struct.unpack('I', command)[0]
+        buf = struct.pack('IIIIII', bin_command, arg0, arg1, len(data), 0,
+                          bin_command ^ 0xffffffff)
+        buf += data
+        return buf
+
+    def _handle():
+        rlist = [readpipe, serversock]
+        cnxn_sent = {}
+        while True:
+            ready, _, _ = select.select(rlist, [], [])
+            for r in ready:
+                if r == readpipe:
+                    # Closure pipe
+                    os.close(r)
+                    serversock.shutdown(socket.SHUT_RDWR)
+                    serversock.close()
+                    return
+                elif r == serversock:
+                    # Server socket
+                    conn, _ = r.accept()
+                    rlist.append(conn)
+                else:
+                    # Client socket
+                    data = r.recv(1024)
+                    if not data:
+                        if r in cnxn_sent:
+                            del cnxn_sent[r]
+                        rlist.remove(r)
+                        continue
+                    if r in cnxn_sent:
+                        continue
+                    cnxn_sent[r] = True
+                    r.sendall(_adb_packet('CNXN', 0x01000001, 1024 * 1024,
+                                          'device::ro.product.name=fakeadb'))
+
+    port = serversock.getsockname()[1]
+    server_thread = threading.Thread(target=_handle)
+    server_thread.start()
+
+    try:
+        yield port
+    finally:
+        os.close(writepipe)
+        server_thread.join()
+
+
 class NonApiTest(unittest.TestCase):
     """Tests for ADB that aren't a part of the AndroidDevice API."""
 
@@ -211,45 +275,32 @@
 
         Bug: http://b/30313466
         """
-        ipv4 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        ipv4.bind(('127.0.0.1', 0))
-        ipv4.listen(1)
+        for protocol in (socket.AF_INET, socket.AF_INET6):
+            try:
+                with fake_adb_server(protocol=protocol) as port:
+                    output = subprocess.check_output(
+                        ['adb', 'connect', 'localhost:{}'.format(port)])
 
-        ipv6 = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
-        try:
-            ipv6.bind(('::1', ipv4.getsockname()[1] + 1))
-            ipv6.listen(1)
-        except socket.error:
-            print("IPv6 not available, skipping")
-            return
+                    self.assertEqual(
+                        output.strip(), 'connected to localhost:{}'.format(port))
+            except socket.error:
+                print("IPv6 not available, skipping")
+                continue
 
-        for s in (ipv4, ipv6):
-            port = s.getsockname()[1]
+    def test_already_connected(self):
+        with fake_adb_server() as port:
             output = subprocess.check_output(
                 ['adb', 'connect', 'localhost:{}'.format(port)])
 
             self.assertEqual(
                 output.strip(), 'connected to localhost:{}'.format(port))
-            s.close()
 
-    def test_already_connected(self):
-        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        s.bind(('127.0.0.1', 0))
-        s.listen(2)
+            # b/31250450: this always returns 0 but probably shouldn't.
+            output = subprocess.check_output(
+                ['adb', 'connect', 'localhost:{}'.format(port)])
 
-        port = s.getsockname()[1]
-        output = subprocess.check_output(
-            ['adb', 'connect', 'localhost:{}'.format(port)])
-
-        self.assertEqual(
-            output.strip(), 'connected to localhost:{}'.format(port))
-
-        # b/31250450: this always returns 0 but probably shouldn't.
-        output = subprocess.check_output(
-            ['adb', 'connect', 'localhost:{}'.format(port)])
-
-        self.assertEqual(
-            output.strip(), 'already connected to localhost:{}'.format(port))
+            self.assertEqual(
+                output.strip(), 'already connected to localhost:{}'.format(port))
 
 def main():
     random.seed(0)
diff --git a/adb/test_device.py b/adb/test_device.py
index b1ad043..f995be2 100644
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -188,8 +188,6 @@
         finally:
             self.device.reverse_remove_all()
 
-    # Note: If you run this test when adb connect'd to a physical device over
-    # TCP, it will fail in adb reverse due to https://code.google.com/p/android/issues/detail?id=189821
     def test_forward_reverse_echo(self):
         """Send data through adb forward and read it back via adb reverse"""
         forward_port = 12345
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 92c52e2..fa7cc8c 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -64,6 +64,21 @@
 const char* const kFeatureLibusb = "libusb";
 const char* const kFeaturePushSync = "push_sync";
 
+namespace {
+
+// A class that helps the Clang Thread Safety Analysis deal with
+// std::unique_lock. Given that std::unique_lock is movable, and the analysis
+// can not currently perform alias analysis, it is not annotated. In order to
+// assert that the mutex is held, a ScopedAssumeLocked can be created just after
+// the std::unique_lock.
+class SCOPED_CAPABILITY ScopedAssumeLocked {
+  public:
+    ScopedAssumeLocked(std::mutex& mutex) ACQUIRE(mutex) {}
+    ~ScopedAssumeLocked() RELEASE() {}
+};
+
+}  // namespace
+
 TransportId NextTransportId() {
     static std::atomic<TransportId> next(1);
     return next++;
@@ -77,8 +92,6 @@
     Stop();
 }
 
-static void AssumeLocked(std::mutex& mutex) ASSERT_CAPABILITY(mutex) {}
-
 void BlockingConnectionAdapter::Start() {
     std::lock_guard<std::mutex> lock(mutex_);
     if (started_) {
@@ -103,12 +116,11 @@
         LOG(INFO) << this->transport_name_ << ": write thread spawning";
         while (true) {
             std::unique_lock<std::mutex> lock(mutex_);
+            ScopedAssumeLocked assume_locked(mutex_);
             cv_.wait(lock, [this]() REQUIRES(mutex_) {
                 return this->stopped_ || !this->write_queue_.empty();
             });
 
-            AssumeLocked(mutex_);
-
             if (this->stopped_) {
                 return;
             }
@@ -505,8 +517,8 @@
     if (t->GetConnectionState() != kCsNoPerm) {
         /* initial references are the two threads */
         t->ref_count = 1;
-        t->connection->SetTransportName(t->serial_name());
-        t->connection->SetReadCallback([t](Connection*, std::unique_ptr<apacket> p) {
+        t->connection()->SetTransportName(t->serial_name());
+        t->connection()->SetReadCallback([t](Connection*, std::unique_ptr<apacket> p) {
             if (!check_header(p.get(), t)) {
                 D("%s: remote read: bad header", t->serial);
                 return false;
@@ -519,7 +531,7 @@
             fdevent_run_on_main_thread([packet, t]() { handle_packet(packet, t); });
             return true;
         });
-        t->connection->SetErrorCallback([t](Connection*, const std::string& error) {
+        t->connection()->SetErrorCallback([t](Connection*, const std::string& error) {
             D("%s: connection terminated: %s", t->serial, error.c_str());
             fdevent_run_on_main_thread([t]() {
                 handle_offline(t);
@@ -527,7 +539,7 @@
             });
         });
 
-        t->connection->Start();
+        t->connection()->Start();
 #if ADB_HOST
         send_connect(t);
 #endif
@@ -596,7 +608,7 @@
     t->ref_count--;
     if (t->ref_count == 0) {
         D("transport: %s unref (kicking and closing)", t->serial);
-        t->connection->Stop();
+        t->connection()->Stop();
         remove_transport(t);
     } else {
         D("transport: %s unref (count=%zu)", t->serial, t->ref_count);
@@ -721,15 +733,39 @@
     return result;
 }
 
+bool ConnectionWaitable::WaitForConnection(std::chrono::milliseconds timeout) {
+    std::unique_lock<std::mutex> lock(mutex_);
+    ScopedAssumeLocked assume_locked(mutex_);
+    return cv_.wait_for(lock, timeout, [&]() REQUIRES(mutex_) {
+        return connection_established_ready_;
+    }) && connection_established_;
+}
+
+void ConnectionWaitable::SetConnectionEstablished(bool success) {
+    {
+        std::lock_guard<std::mutex> lock(mutex_);
+        if (connection_established_ready_) return;
+        connection_established_ready_ = true;
+        connection_established_ = success;
+        D("connection established with %d", success);
+    }
+    cv_.notify_one();
+}
+
+atransport::~atransport() {
+    // If the connection callback had not been run before, run it now.
+    SetConnectionEstablished(false);
+}
+
 int atransport::Write(apacket* p) {
-    return this->connection->Write(std::unique_ptr<apacket>(p)) ? 0 : -1;
+    return this->connection()->Write(std::unique_ptr<apacket>(p)) ? 0 : -1;
 }
 
 void atransport::Kick() {
     if (!kicked_) {
         D("kicking transport %s", this->serial);
         kicked_ = true;
-        this->connection->Stop();
+        this->connection()->Stop();
     }
 }
 
@@ -742,6 +778,11 @@
     connection_state_ = state;
 }
 
+void atransport::SetConnection(std::unique_ptr<Connection> connection) {
+    std::lock_guard<std::mutex> lock(mutex_);
+    connection_ = std::shared_ptr<Connection>(std::move(connection));
+}
+
 std::string atransport::connection_state_name() const {
     ConnectionState state = GetConnectionState();
     switch (state) {
@@ -873,6 +914,10 @@
            qual_match(target.c_str(), "device:", device, false);
 }
 
+void atransport::SetConnectionEstablished(bool success) {
+    connection_waitable_->SetConnectionEstablished(success);
+}
+
 #if ADB_HOST
 
 // We use newline as our delimiter, make sure to never output it.
@@ -974,7 +1019,7 @@
             VLOG(TRANSPORT) << "socket transport " << transport->serial
                             << " is already in pending_list and fails to register";
             delete t;
-            return -1;
+            return -EALREADY;
         }
     }
 
@@ -983,7 +1028,7 @@
             VLOG(TRANSPORT) << "socket transport " << transport->serial
                             << " is already in transport_list and fails to register";
             delete t;
-            return -1;
+            return -EALREADY;
         }
     }
 
@@ -992,8 +1037,15 @@
 
     lock.unlock();
 
+    auto waitable = t->connection_waitable();
     register_transport(t);
-    return 0;
+
+    if (local == 1) {
+        // Do not wait for emulator transports.
+        return 0;
+    }
+
+    return waitable->WaitForConnection(std::chrono::seconds(10)) ? 0 : -1;
 }
 
 #if ADB_HOST
@@ -1052,8 +1104,9 @@
 void unregister_usb_transport(usb_handle* usb) {
     std::lock_guard<std::recursive_mutex> lock(transport_lock);
     transport_list.remove_if([usb](atransport* t) {
-        if (auto connection = dynamic_cast<UsbConnection*>(t->connection.get())) {
-            return connection->handle_ == usb && t->GetConnectionState() == kCsNoPerm;
+        auto connection = t->connection();
+        if (auto usb_connection = dynamic_cast<UsbConnection*>(connection.get())) {
+            return usb_connection->handle_ == usb && t->GetConnectionState() == kCsNoPerm;
         }
         return false;
     });
diff --git a/adb/transport.h b/adb/transport.h
index d18c362..ebc186b 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -20,6 +20,7 @@
 #include <sys/types.h>
 
 #include <atomic>
+#include <chrono>
 #include <condition_variable>
 #include <deque>
 #include <functional>
@@ -30,6 +31,7 @@
 #include <thread>
 #include <unordered_set>
 
+#include <android-base/macros.h>
 #include <android-base/thread_annotations.h>
 #include <openssl/rsa.h>
 
@@ -160,6 +162,35 @@
     usb_handle* handle_;
 };
 
+// Waits for a transport's connection to be not pending. This is a separate
+// object so that the transport can be destroyed and another thread can be
+// notified of it in a race-free way.
+class ConnectionWaitable {
+  public:
+    ConnectionWaitable() = default;
+    ~ConnectionWaitable() = default;
+
+    // Waits until the first CNXN packet has been received by the owning
+    // atransport, or the specified timeout has elapsed. Can be called from any
+    // thread.
+    //
+    // Returns true if the CNXN packet was received in a timely fashion, false
+    // otherwise.
+    bool WaitForConnection(std::chrono::milliseconds timeout);
+
+    // Can be called from any thread when the connection stops being pending.
+    // Only the first invocation will be acknowledged, the rest will be no-ops.
+    void SetConnectionEstablished(bool success);
+
+  private:
+    bool connection_established_ GUARDED_BY(mutex_) = false;
+    bool connection_established_ready_ GUARDED_BY(mutex_) = false;
+    std::mutex mutex_;
+    std::condition_variable cv_;
+
+    DISALLOW_COPY_AND_ASSIGN(ConnectionWaitable);
+};
+
 class atransport {
   public:
     // TODO(danalbert): We expose waaaaaaay too much stuff because this was
@@ -168,13 +199,16 @@
     // it's better to do this piece by piece.
 
     atransport(ConnectionState state = kCsOffline)
-        : id(NextTransportId()), connection_state_(state) {
+        : id(NextTransportId()),
+          connection_state_(state),
+          connection_waitable_(std::make_shared<ConnectionWaitable>()),
+          connection_(nullptr) {
         // Initialize protocol to min version for compatibility with older versions.
         // Version will be updated post-connect.
         protocol_version = A_VERSION_MIN;
         max_payload = MAX_PAYLOAD;
     }
-    virtual ~atransport() {}
+    virtual ~atransport();
 
     int Write(apacket* p);
     void Kick();
@@ -183,13 +217,17 @@
     ConnectionState GetConnectionState() const;
     void SetConnectionState(ConnectionState state);
 
+    void SetConnection(std::unique_ptr<Connection> connection);
+    std::shared_ptr<Connection> connection() {
+        std::lock_guard<std::mutex> lock(mutex_);
+        return connection_;
+    }
+
     const TransportId id;
     size_t ref_count = 0;
     bool online = false;
     TransportType type = kTransportAny;
 
-    std::unique_ptr<Connection> connection;
-
     // Used to identify transports for clients.
     char* serial = nullptr;
     char* product = nullptr;
@@ -241,7 +279,14 @@
     // This is to make it easier to use the same network target for both fastboot and adb.
     bool MatchesTarget(const std::string& target) const;
 
-private:
+    // Notifies that the atransport is no longer waiting for the connection
+    // being established.
+    void SetConnectionEstablished(bool success);
+
+    // Gets a shared reference to the ConnectionWaitable.
+    std::shared_ptr<ConnectionWaitable> connection_waitable() { return connection_waitable_; }
+
+  private:
     bool kicked_ = false;
 
     // A set of features transmitted in the banner with the initial connection.
@@ -258,6 +303,15 @@
     std::deque<std::shared_ptr<RSA>> keys_;
 #endif
 
+    // A sharable object that can be used to wait for the atransport's
+    // connection to be established.
+    std::shared_ptr<ConnectionWaitable> connection_waitable_;
+
+    // The underlying connection object.
+    std::shared_ptr<Connection> connection_ GUARDED_BY(mutex_);
+
+    std::mutex mutex_;
+
     DISALLOW_COPY_AND_ASSIGN(atransport);
 };
 
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index c09fcb7..e81f27c 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -101,7 +101,11 @@
     int ret = register_socket_transport(fd, serial.c_str(), port, 0);
     if (ret < 0) {
         adb_close(fd);
-        *response = android::base::StringPrintf("already connected to %s", serial.c_str());
+        if (ret == -EALREADY) {
+            *response = android::base::StringPrintf("already connected to %s", serial.c_str());
+        } else {
+            *response = android::base::StringPrintf("failed to connect to %s", serial.c_str());
+        }
     } else {
         *response = android::base::StringPrintf("connected to %s", serial.c_str());
     }
@@ -452,7 +456,8 @@
     // Emulator connection.
     if (local) {
         auto emulator_connection = std::make_unique<EmulatorConnection>(std::move(fd), adb_port);
-        t->connection = std::make_unique<BlockingConnectionAdapter>(std::move(emulator_connection));
+        t->SetConnection(
+            std::make_unique<BlockingConnectionAdapter>(std::move(emulator_connection)));
         std::lock_guard<std::mutex> lock(local_transports_lock);
         atransport* existing_transport = find_emulator_transport_by_adb_port_locked(adb_port);
         if (existing_transport != NULL) {
@@ -472,6 +477,6 @@
 
     // Regular tcp connection.
     auto fd_connection = std::make_unique<FdConnection>(std::move(fd));
-    t->connection = std::make_unique<BlockingConnectionAdapter>(std::move(fd_connection));
+    t->SetConnection(std::make_unique<BlockingConnectionAdapter>(std::move(fd_connection)));
     return fail;
 }
diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp
index e9a75cd..94b2e37 100644
--- a/adb/transport_usb.cpp
+++ b/adb/transport_usb.cpp
@@ -176,7 +176,7 @@
 void init_usb_transport(atransport* t, usb_handle* h) {
     D("transport: usb");
     auto connection = std::make_unique<UsbConnection>(h);
-    t->connection = std::make_unique<BlockingConnectionAdapter>(std::move(connection));
+    t->SetConnection(std::make_unique<BlockingConnectionAdapter>(std::move(connection)));
     t->type = kTransportUsb;
 }
 
diff --git a/base/Android.bp b/base/Android.bp
index 12b3969..ec81f61 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -162,4 +162,5 @@
             suffix: "64",
         },
     },
+    test_suites: ["device-tests"],
 }
diff --git a/base/include/android-base/parseint.h b/base/include/android-base/parseint.h
index 2c8570e..1b7cc5f 100644
--- a/base/include/android-base/parseint.h
+++ b/base/include/android-base/parseint.h
@@ -19,6 +19,7 @@
 
 #include <errno.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include <limits>
 #include <string>
@@ -31,14 +32,20 @@
 // otherwise valid values will be rejected. Returns boolean success; 'out'
 // is untouched if parsing fails.
 template <typename T>
-bool ParseUint(const char* s, T* out,
-               T max = std::numeric_limits<T>::max()) {
+bool ParseUint(const char* s, T* out, T max = std::numeric_limits<T>::max(),
+               bool allow_suffixes = false) {
   int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10;
   errno = 0;
   char* end;
   unsigned long long int result = strtoull(s, &end, base);
-  if (errno != 0 || s == end || *end != '\0') {
-    return false;
+  if (errno != 0 || end == s) return false;
+  if (*end != '\0') {
+    const char* suffixes = "bkmgtpe";
+    const char* suffix;
+    if (!allow_suffixes || (suffix = strchr(suffixes, tolower(*end))) == nullptr) return false;
+#if __clang__  // TODO: win32 still builds with GCC :-(
+    if (__builtin_mul_overflow(result, 1ULL << (10 * (suffix - suffixes)), &result)) return false;
+#endif
   }
   if (max < result) {
     return false;
@@ -49,9 +56,20 @@
 
 // TODO: string_view
 template <typename T>
-bool ParseUint(const std::string& s, T* out,
-               T max = std::numeric_limits<T>::max()) {
-  return ParseUint(s.c_str(), out, max);
+bool ParseUint(const std::string& s, T* out, T max = std::numeric_limits<T>::max(),
+               bool allow_suffixes = false) {
+  return ParseUint(s.c_str(), out, max, allow_suffixes);
+}
+
+template <typename T>
+bool ParseByteCount(const char* s, T* out, T max = std::numeric_limits<T>::max()) {
+  return ParseUint(s, out, max, true);
+}
+
+// TODO: string_view
+template <typename T>
+bool ParseByteCount(const std::string& s, T* out, T max = std::numeric_limits<T>::max()) {
+  return ParseByteCount(s.c_str(), out, max);
 }
 
 // Parses the signed decimal integer in the string 's' and sets 'out' to
diff --git a/base/parseint_test.cpp b/base/parseint_test.cpp
index 483b1d3..fb1c339 100644
--- a/base/parseint_test.cpp
+++ b/base/parseint_test.cpp
@@ -96,3 +96,44 @@
   ASSERT_FALSE(android::base::ParseInt("456x", &u));
   ASSERT_EQ(123u, u);
 }
+
+TEST(parseint, ParseByteCount) {
+  uint64_t i = 0;
+  ASSERT_TRUE(android::base::ParseByteCount("123b", &i));
+  ASSERT_EQ(123ULL, i);
+
+  ASSERT_TRUE(android::base::ParseByteCount("8k", &i));
+  ASSERT_EQ(8ULL * 1024, i);
+
+  ASSERT_TRUE(android::base::ParseByteCount("8M", &i));
+  ASSERT_EQ(8ULL * 1024 * 1024, i);
+
+  ASSERT_TRUE(android::base::ParseByteCount("6g", &i));
+  ASSERT_EQ(6ULL * 1024 * 1024 * 1024, i);
+
+  ASSERT_TRUE(android::base::ParseByteCount("1T", &i));
+  ASSERT_EQ(1ULL * 1024 * 1024 * 1024 * 1024, i);
+
+  ASSERT_TRUE(android::base::ParseByteCount("2p", &i));
+  ASSERT_EQ(2ULL * 1024 * 1024 * 1024 * 1024 * 1024, i);
+
+  ASSERT_TRUE(android::base::ParseByteCount("4e", &i));
+  ASSERT_EQ(4ULL * 1024 * 1024 * 1024 * 1024 * 1024 * 1024, i);
+}
+
+TEST(parseint, ParseByteCount_invalid_suffix) {
+  unsigned u;
+  ASSERT_FALSE(android::base::ParseByteCount("1x", &u));
+}
+
+TEST(parseint, ParseByteCount_overflow) {
+  uint64_t u64;
+  ASSERT_FALSE(android::base::ParseByteCount("4294967295E", &u64));
+
+  uint16_t u16;
+  ASSERT_TRUE(android::base::ParseByteCount("63k", &u16));
+  ASSERT_EQ(63U * 1024, u16);
+  ASSERT_TRUE(android::base::ParseByteCount("65535b", &u16));
+  ASSERT_EQ(65535U, u16);
+  ASSERT_FALSE(android::base::ParseByteCount("65k", &u16));
+}
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index e60e6be..8ce9dfc 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -38,6 +38,7 @@
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/parseint.h>
+#include <android-base/properties.h>
 #include <android-base/strings.h>
 #include <android/log.h>
 #include <cutils/android_reboot.h>
@@ -302,6 +303,9 @@
     {"kernel_panic,init", 158},
     {"kernel_panic,oom", 159},
     {"kernel_panic,stack", 160},
+    {"kernel_panic,sysrq,livelock,alarm", 161},   // llkd
+    {"kernel_panic,sysrq,livelock,driver", 162},  // llkd
+    {"kernel_panic,sysrq,livelock,zombie", 163},  // llkd
 };
 
 // Converts a string value representing the reason the system booted to an
@@ -1096,14 +1100,28 @@
   boot_event_store->AddBootEventWithValue("absolute_boot_time", absolute_total.count());
 }
 
+// Gets the boot time offset. This is useful when Android is running in a
+// container, because the boot_clock is not reset when Android reboots.
+std::chrono::nanoseconds GetBootTimeOffset() {
+  static const int64_t boottime_offset =
+      android::base::GetIntProperty<int64_t>("ro.boot.boottime_offset", 0);
+  return std::chrono::nanoseconds(boottime_offset);
+}
+
+// Returns the current uptime, accounting for any offset in the CLOCK_BOOTTIME
+// clock.
+android::base::boot_clock::duration GetUptime() {
+  return android::base::boot_clock::now().time_since_epoch() - GetBootTimeOffset();
+}
+
 // Records several metrics related to the time it takes to boot the device,
 // including disambiguating boot time on encrypted or non-encrypted devices.
 void RecordBootComplete() {
   BootEventRecordStore boot_event_store;
   BootEventRecordStore::BootEventRecord record;
 
-  auto time_since_epoch = android::base::boot_clock::now().time_since_epoch();
-  auto uptime = std::chrono::duration_cast<std::chrono::seconds>(time_since_epoch);
+  auto uptime_ns = GetUptime();
+  auto uptime_s = std::chrono::duration_cast<std::chrono::seconds>(uptime_ns);
   time_t current_time_utc = time(nullptr);
 
   if (boot_event_store.GetBootEvent("last_boot_time_utc", &record)) {
@@ -1128,19 +1146,20 @@
     // Log the amount of time elapsed until the device is decrypted, which
     // includes the variable amount of time the user takes to enter the
     // decryption password.
-    boot_event_store.AddBootEventWithValue("boot_decryption_complete", uptime.count());
+    boot_event_store.AddBootEventWithValue("boot_decryption_complete", uptime_s.count());
 
     // Subtract the decryption time to normalize the boot cycle timing.
-    std::chrono::seconds boot_complete = std::chrono::seconds(uptime.count() - record.second);
+    std::chrono::seconds boot_complete = std::chrono::seconds(uptime_s.count() - record.second);
     boot_event_store.AddBootEventWithValue(boot_complete_prefix + "_post_decrypt",
                                            boot_complete.count());
   } else {
-    boot_event_store.AddBootEventWithValue(boot_complete_prefix + "_no_encryption", uptime.count());
+    boot_event_store.AddBootEventWithValue(boot_complete_prefix + "_no_encryption",
+                                           uptime_s.count());
   }
 
   // Record the total time from device startup to boot complete, regardless of
   // encryption state.
-  boot_event_store.AddBootEventWithValue(boot_complete_prefix, uptime.count());
+  boot_event_store.AddBootEventWithValue(boot_complete_prefix, uptime_s.count());
 
   RecordInitBootTimeProp(&boot_event_store, "ro.boottime.init");
   RecordInitBootTimeProp(&boot_event_store, "ro.boottime.init.selinux");
@@ -1149,7 +1168,7 @@
   const BootloaderTimingMap bootloader_timings = GetBootLoaderTimings();
   RecordBootloaderTimings(&boot_event_store, bootloader_timings);
 
-  auto uptime_ms = std::chrono::duration_cast<std::chrono::milliseconds>(time_since_epoch);
+  auto uptime_ms = std::chrono::duration_cast<std::chrono::milliseconds>(uptime_ns);
   RecordAbsoluteBootTime(&boot_event_store, bootloader_timings, uptime_ms);
 }
 
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 7e6f24d..9c556c3 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -221,6 +221,8 @@
             stem: "debuggerd_test64",
         },
     },
+
+    test_suites: ["device-tests"],
 }
 
 cc_benchmark {
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index a1f0211..40cf6c3 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -190,6 +190,19 @@
 static unique_fd g_tombstoned_socket;
 static unique_fd g_output_fd;
 
+static void DefuseSignalHandlers() {
+  // Don't try to dump ourselves.
+  struct sigaction action = {};
+  action.sa_handler = SIG_DFL;
+  debuggerd_register_handlers(&action);
+
+  sigset_t mask;
+  sigemptyset(&mask);
+  if (sigprocmask(SIG_SETMASK, &mask, nullptr) != 0) {
+    PLOG(FATAL) << "failed to set signal mask";
+  }
+}
+
 static void Initialize(char** argv) {
   android::base::InitLogging(argv);
   android::base::SetAborter([](const char* abort_msg) {
@@ -213,17 +226,6 @@
 
     _exit(1);
   });
-
-  // Don't try to dump ourselves.
-  struct sigaction action = {};
-  action.sa_handler = SIG_DFL;
-  debuggerd_register_handlers(&action);
-
-  sigset_t mask;
-  sigemptyset(&mask);
-  if (sigprocmask(SIG_SETMASK, &mask, nullptr) != 0) {
-    PLOG(FATAL) << "failed to set signal mask";
-  }
 }
 
 static void ParseArgs(int argc, char** argv, pid_t* pseudothread_tid, DebuggerdDumpType* dump_type) {
@@ -321,6 +323,8 @@
 }
 
 int main(int argc, char** argv) {
+  DefuseSignalHandlers();
+
   atrace_begin(ATRACE_TAG, "before reparent");
   pid_t target_process = getppid();
 
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index e410be9..9b64be7 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -346,7 +346,9 @@
 
   std::string result;
   ConsumeFd(std::move(output_fd), &result);
-  ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 0 \(SI_USER\), fault addr --------)");
+  ASSERT_MATCH(
+      result,
+      R"(signal 11 \(SIGSEGV\), code 0 \(SI_USER from pid \d+, uid \d+\), fault addr --------)");
   ASSERT_MATCH(result, R"(backtrace:)");
 }
 
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 05e6efa..c07a34a 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -169,24 +169,26 @@
     return;
   }
 
-  const char* signal_name = get_signame(info->si_signo);
-  bool has_address = signal_has_si_addr(info->si_signo, info->si_code);
-
-  // Many signals don't have an address.
+  // Many signals don't have an address or sender.
   char addr_desc[32] = "";  // ", fault addr 0x1234"
-  if (has_address) {
+  if (signal_has_si_addr(info)) {
     async_safe_format_buffer(addr_desc, sizeof(addr_desc), ", fault addr %p", info->si_addr);
   }
+  pid_t self_pid = __getpid();
+  char sender_desc[32] = {};  // " from pid 1234, uid 666"
+  if (signal_has_sender(info, self_pid)) {
+    get_signal_sender(sender_desc, sizeof(sender_desc), info);
+  }
 
   char main_thread_name[MAX_TASK_NAME_LEN + 1];
   if (!get_main_thread_name(main_thread_name, sizeof(main_thread_name))) {
     strncpy(main_thread_name, "<unknown>", sizeof(main_thread_name));
   }
 
-  async_safe_format_log(
-      ANDROID_LOG_FATAL, "libc", "Fatal signal %d (%s), code %d (%s)%s in tid %d (%s), pid %d (%s)",
-      info->si_signo, signal_name, info->si_code, get_sigcode(info->si_signo, info->si_code),
-      addr_desc, __gettid(), thread_name, __getpid(), main_thread_name);
+  async_safe_format_log(ANDROID_LOG_FATAL, "libc",
+                        "Fatal signal %d (%s), code %d (%s%s)%s in tid %d (%s), pid %d (%s)",
+                        info->si_signo, get_signame(info), info->si_code, get_sigcode(info),
+                        sender_desc, addr_desc, __gettid(), thread_name, self_pid, main_thread_name);
 }
 
 /*
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
index 7b04e71..7c5304e 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
@@ -74,8 +74,10 @@
 
 void drop_capabilities();
 
-bool signal_has_si_addr(int si_signo, int si_code);
-const char* get_signame(int sig);
-const char* get_sigcode(int signo, int code);
+bool signal_has_sender(const siginfo_t*, pid_t caller_pid);
+bool signal_has_si_addr(const siginfo_t*);
+void get_signal_sender(char* buf, size_t n, const siginfo_t*);
+const char* get_signame(const siginfo_t*);
+const char* get_sigcode(const siginfo_t*);
 
 #endif // _DEBUGGERD_UTILITY_H
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index 55d6204..e11be1e 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -102,18 +102,24 @@
   if (!cause.empty()) _LOG(log, logtype::HEADER, "Cause: %s\n", cause.c_str());
 }
 
-static void dump_signal_info(log_t* log, const siginfo_t* si) {
+static void dump_signal_info(log_t* log, const ThreadInfo& thread_info) {
   char addr_desc[32]; // ", fault addr 0x1234"
-  if (signal_has_si_addr(si->si_signo, si->si_code)) {
-    snprintf(addr_desc, sizeof(addr_desc), "%p", si->si_addr);
+  if (signal_has_si_addr(thread_info.siginfo)) {
+    snprintf(addr_desc, sizeof(addr_desc), "%p", thread_info.siginfo->si_addr);
   } else {
     snprintf(addr_desc, sizeof(addr_desc), "--------");
   }
 
-  _LOG(log, logtype::HEADER, "signal %d (%s), code %d (%s), fault addr %s\n", si->si_signo,
-       get_signame(si->si_signo), si->si_code, get_sigcode(si->si_signo, si->si_code), addr_desc);
+  char sender_desc[32] = {};  // " from pid 1234, uid 666"
+  if (signal_has_sender(thread_info.siginfo, thread_info.pid)) {
+    get_signal_sender(sender_desc, sizeof(sender_desc), thread_info.siginfo);
+  }
 
-  dump_probable_cause(log, si);
+  _LOG(log, logtype::HEADER, "signal %d (%s), code %d (%s%s), fault addr %s\n",
+       thread_info.siginfo->si_signo, get_signame(thread_info.siginfo),
+       thread_info.siginfo->si_code, get_sigcode(thread_info.siginfo), sender_desc, addr_desc);
+
+  dump_probable_cause(log, thread_info.siginfo);
 }
 
 static void dump_thread_info(log_t* log, const ThreadInfo& thread_info) {
@@ -247,14 +253,13 @@
 
   length -= sizeof(size_t);
 
-  std::vector<char> msg(length);
+  // The abort message should be null terminated already, but reserve a spot for NUL just in case.
+  std::vector<char> msg(length + 1);
   if (!process_memory->ReadFully(address + sizeof(length), &msg[0], length)) {
     _LOG(log, logtype::HEADER, "Failed to read abort message: %s\n", strerror(errno));
     return;
   }
 
-  // The abort message should be null terminated already, but just in case...
-  msg[length] = '\0';
   _LOG(log, logtype::HEADER, "Abort message: '%s'\n", &msg[0]);
 }
 
@@ -413,7 +418,7 @@
   dump_thread_info(log, thread_info);
 
   if (thread_info.siginfo) {
-    dump_signal_info(log, thread_info.siginfo);
+    dump_signal_info(log, thread_info);
   }
 
   if (primary_thread) {
@@ -422,8 +427,10 @@
 
   dump_registers(log, thread_info.registers.get());
 
+  // Unwind will mutate the registers, so make a copy first.
+  std::unique_ptr<Regs> regs_copy(thread_info.registers->Clone());
   std::vector<backtrace_frame_data_t> frames;
-  if (!Backtrace::Unwind(thread_info.registers.get(), map, &frames, 0, nullptr)) {
+  if (!Backtrace::Unwind(regs_copy.get(), map, &frames, 0, nullptr)) {
     _LOG(log, logtype::THREAD, "Failed to unwind");
     return false;
   }
@@ -441,7 +448,7 @@
     if (map) {
       uint64_t addr = 0;
       siginfo_t* si = thread_info.siginfo;
-      if (signal_has_si_addr(si->si_signo, si->si_code)) {
+      if (signal_has_si_addr(si)) {
         addr = reinterpret_cast<uint64_t>(si->si_addr);
       }
       dump_all_maps(log, map, process_memory, addr);
diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp
index 1ad1800..1f6f3c8 100644
--- a/debuggerd/libdebuggerd/utility.cpp
+++ b/debuggerd/libdebuggerd/utility.cpp
@@ -254,13 +254,13 @@
   }
 }
 
-bool signal_has_si_addr(int si_signo, int si_code) {
+bool signal_has_si_addr(const siginfo_t* si) {
   // Manually sent signals won't have si_addr.
-  if (si_code == SI_USER || si_code == SI_QUEUE || si_code == SI_TKILL) {
+  if (si->si_code == SI_USER || si->si_code == SI_QUEUE || si->si_code == SI_TKILL) {
     return false;
   }
 
-  switch (si_signo) {
+  switch (si->si_signo) {
     case SIGBUS:
     case SIGFPE:
     case SIGILL:
@@ -272,8 +272,16 @@
   }
 }
 
-const char* get_signame(int sig) {
-  switch (sig) {
+bool signal_has_sender(const siginfo_t* si, pid_t caller_pid) {
+  return SI_FROMUSER(si) && (si->si_pid != 0) && (si->si_pid != caller_pid);
+}
+
+void get_signal_sender(char* buf, size_t n, const siginfo_t* si) {
+  snprintf(buf, n, " from pid %d, uid %d", si->si_pid, si->si_uid);
+}
+
+const char* get_signame(const siginfo_t* si) {
+  switch (si->si_signo) {
     case SIGABRT: return "SIGABRT";
     case SIGBUS: return "SIGBUS";
     case SIGFPE: return "SIGFPE";
@@ -290,11 +298,11 @@
   }
 }
 
-const char* get_sigcode(int signo, int code) {
+const char* get_sigcode(const siginfo_t* si) {
   // Try the signal-specific codes...
-  switch (signo) {
+  switch (si->si_signo) {
     case SIGILL:
-      switch (code) {
+      switch (si->si_code) {
         case ILL_ILLOPC: return "ILL_ILLOPC";
         case ILL_ILLOPN: return "ILL_ILLOPN";
         case ILL_ILLADR: return "ILL_ILLADR";
@@ -307,7 +315,7 @@
       static_assert(NSIGILL == ILL_BADSTK, "missing ILL_* si_code");
       break;
     case SIGBUS:
-      switch (code) {
+      switch (si->si_code) {
         case BUS_ADRALN: return "BUS_ADRALN";
         case BUS_ADRERR: return "BUS_ADRERR";
         case BUS_OBJERR: return "BUS_OBJERR";
@@ -317,7 +325,7 @@
       static_assert(NSIGBUS == BUS_MCEERR_AO, "missing BUS_* si_code");
       break;
     case SIGFPE:
-      switch (code) {
+      switch (si->si_code) {
         case FPE_INTDIV: return "FPE_INTDIV";
         case FPE_INTOVF: return "FPE_INTOVF";
         case FPE_FLTDIV: return "FPE_FLTDIV";
@@ -330,7 +338,7 @@
       static_assert(NSIGFPE == FPE_FLTSUB, "missing FPE_* si_code");
       break;
     case SIGSEGV:
-      switch (code) {
+      switch (si->si_code) {
         case SEGV_MAPERR: return "SEGV_MAPERR";
         case SEGV_ACCERR: return "SEGV_ACCERR";
 #if defined(SEGV_BNDERR)
@@ -350,21 +358,21 @@
       break;
 #if defined(SYS_SECCOMP) // Our glibc is too old, and we build this for the host too.
     case SIGSYS:
-      switch (code) {
+      switch (si->si_code) {
         case SYS_SECCOMP: return "SYS_SECCOMP";
       }
       static_assert(NSIGSYS == SYS_SECCOMP, "missing SYS_* si_code");
       break;
 #endif
     case SIGTRAP:
-      switch (code) {
+      switch (si->si_code) {
         case TRAP_BRKPT: return "TRAP_BRKPT";
         case TRAP_TRACE: return "TRAP_TRACE";
         case TRAP_BRANCH: return "TRAP_BRANCH";
         case TRAP_HWBKPT: return "TRAP_HWBKPT";
       }
-      if ((code & 0xff) == SIGTRAP) {
-        switch ((code >> 8) & 0xff) {
+      if ((si->si_code & 0xff) == SIGTRAP) {
+        switch ((si->si_code >> 8) & 0xff) {
           case PTRACE_EVENT_FORK:
             return "PTRACE_EVENT_FORK";
           case PTRACE_EVENT_VFORK:
@@ -387,7 +395,7 @@
       break;
   }
   // Then the other codes...
-  switch (code) {
+  switch (si->si_code) {
     case SI_USER: return "SI_USER";
     case SI_KERNEL: return "SI_KERNEL";
     case SI_QUEUE: return "SI_QUEUE";
diff --git a/demangle/Android.bp b/demangle/Android.bp
index 8d5b135..f3b4aa0 100644
--- a/demangle/Android.bp
+++ b/demangle/Android.bp
@@ -78,4 +78,6 @@
     shared_libs: [
         "libdemangle",
     ],
+
+    test_suites: ["device-tests"],
 }
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 3a3503e..9463cc9 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -82,7 +82,7 @@
 // libsparse will support INT_MAX, but this results in large allocations, so
 // let's keep it at 1GB to avoid memory pressure on the host.
 static constexpr int64_t RESPARSE_LIMIT = 1 * 1024 * 1024 * 1024;
-static int64_t sparse_limit = -1;
+static uint64_t sparse_limit = 0;
 static int64_t target_sparse_limit = -1;
 
 static unsigned g_base_addr = 0x10000000;
@@ -375,7 +375,7 @@
             " -w                         Wipe userdata.\n"
             " -s SERIAL                  Specify a USB device.\n"
             " -s tcp|udp:HOST[:PORT]     Specify a network device.\n"
-            " -S SIZE[K|M|G]             Use sparse files above this limit (0 to disable).\n"
+            " -S SIZE[K|M|G]             Break into sparse files no larger than SIZE.\n"
             " --slot SLOT                Use SLOT; 'all' for both slots, 'other' for\n"
             "                            non-current slot (default: current active slot).\n"
             " --set-active[=SLOT]        Sets the active slot before rebooting.\n"
@@ -410,12 +410,6 @@
         if (!g_cmdline.empty()) {
             bootimg_set_cmdline(reinterpret_cast<boot_img_hdr_v1*>(kdata), g_cmdline);
         }
-        uint32_t header_version_existing =
-                reinterpret_cast<boot_img_hdr_v1*>(kdata)->header_version;
-        if (g_boot_img_hdr.header_version != header_version_existing) {
-            die("header version mismatch, expected: %" PRIu32 " found %" PRIu32 "",
-                g_boot_img_hdr.header_version, header_version_existing);
-        }
 
         if (!ramdisk.empty()) die("cannot boot a boot.img *and* ramdisk");
 
@@ -699,10 +693,14 @@
     fb_queue_notice("--------------------------------------------");
 }
 
-static struct sparse_file** load_sparse_files(int fd, int max_size) {
+static struct sparse_file** load_sparse_files(int fd, int64_t max_size) {
     struct sparse_file* s = sparse_file_import_auto(fd, false, true);
     if (!s) die("cannot sparse read file");
 
+    if (max_size <= 0 || max_size > std::numeric_limits<uint32_t>::max()) {
+      die("invalid max size %" PRId64, max_size);
+    }
+
     int files = sparse_file_resparse(s, max_size, nullptr, 0);
     if (files < 0) die("Failed to resparse");
 
@@ -736,13 +734,10 @@
 }
 
 static int64_t get_sparse_limit(Transport* transport, int64_t size) {
-    int64_t limit;
-
-    if (sparse_limit == 0) {
-        return 0;
-    } else if (sparse_limit > 0) {
-        limit = sparse_limit;
-    } else {
+    int64_t limit = sparse_limit;
+    if (limit == 0) {
+        // Unlimited, so see what the target device's limit is.
+        // TODO: shouldn't we apply this limit even if you've used -S?
         if (target_sparse_limit == -1) {
             target_sparse_limit = get_target_sparse_limit(transport);
         }
@@ -1203,47 +1198,6 @@
     fb_queue_command(command, "");
 }
 
-static int64_t parse_num(const char *arg)
-{
-    char *endptr;
-    unsigned long long num;
-
-    num = strtoull(arg, &endptr, 0);
-    if (endptr == arg) {
-        return -1;
-    }
-
-    if (*endptr == 'k' || *endptr == 'K') {
-        if (num >= (-1ULL) / 1024) {
-            return -1;
-        }
-        num *= 1024LL;
-        endptr++;
-    } else if (*endptr == 'm' || *endptr == 'M') {
-        if (num >= (-1ULL) / (1024 * 1024)) {
-            return -1;
-        }
-        num *= 1024LL * 1024LL;
-        endptr++;
-    } else if (*endptr == 'g' || *endptr == 'G') {
-        if (num >= (-1ULL) / (1024 * 1024 * 1024)) {
-            return -1;
-        }
-        num *= 1024LL * 1024LL * 1024LL;
-        endptr++;
-    }
-
-    if (*endptr != '\0') {
-        return -1;
-    }
-
-    if (num > INT64_MAX) {
-        return -1;
-    }
-
-    return num;
-}
-
 static std::string fb_fix_numeric_var(std::string var) {
     // Some bootloaders (angler, for example), send spurious leading whitespace.
     var = android::base::Trim(var);
@@ -1477,8 +1431,9 @@
                     serial = optarg;
                     break;
                 case 'S':
-                    sparse_limit = parse_num(optarg);
-                    if (sparse_limit < 0) die("invalid sparse limit");
+                    if (!android::base::ParseByteCount(optarg, &sparse_limit)) {
+                        die("invalid sparse limit %s", optarg);
+                    }
                     break;
                 case 'v':
                     set_verbose();
@@ -1689,20 +1644,20 @@
     }
 
     if (wants_wipe) {
-        fb_queue_erase("userdata");
-        if (set_fbe_marker) {
-            fprintf(stderr, "setting FBE marker on initial userdata...\n");
-            std::string initial_userdata_dir = create_fbemarker_tmpdir();
-            fb_perform_format(transport, "userdata", 1, "", "", initial_userdata_dir);
-            delete_fbemarker_tmpdir(initial_userdata_dir);
-        } else {
-            fb_perform_format(transport, "userdata", 1, "", "", "");
-        }
-
-        std::string cache_type;
-        if (fb_getvar(transport, "partition-type:cache", &cache_type) && !cache_type.empty()) {
-            fb_queue_erase("cache");
-            fb_perform_format(transport, "cache", 1, "", "", "");
+        std::vector<std::string> partitions = { "userdata", "cache", "metadata" };
+        for (const auto& partition : partitions) {
+            std::string partition_type;
+            if (!fb_getvar(transport, std::string{"partition-type:"} + partition, &partition_type)) continue;
+            if (partition_type.empty()) continue;
+            fb_queue_erase(partition);
+            if (partition == "userdata" && set_fbe_marker) {
+                fprintf(stderr, "setting FBE marker on initial userdata...\n");
+                std::string initial_userdata_dir = create_fbemarker_tmpdir();
+                fb_perform_format(transport, partition, 1, "", "", initial_userdata_dir);
+                delete_fbemarker_tmpdir(initial_userdata_dir);
+            } else {
+                fb_perform_format(transport, partition, 1, "", "", "");
+            }
         }
     }
     if (wants_set_active) {
diff --git a/fastboot/protocol.cpp b/fastboot/protocol.cpp
index a089567..fda6f5d 100644
--- a/fastboot/protocol.cpp
+++ b/fastboot/protocol.cpp
@@ -278,19 +278,14 @@
     return _command_end(transport);
 }
 
-#define TRANSPORT_BUF_SIZE 1024
+static constexpr size_t TRANSPORT_BUF_SIZE = 1024;
 static char transport_buf[TRANSPORT_BUF_SIZE];
-static int transport_buf_len;
+static size_t transport_buf_len;
 
-static int fb_download_data_sparse_write(void *priv, const void *data, int len)
-{
-    int r;
-    Transport* transport = reinterpret_cast<Transport*>(priv);
-    int to_write;
-    const char* ptr = reinterpret_cast<const char*>(data);
-
+static int fb_download_data_sparse_write(void* priv, const void* data, size_t len) {
+    const char* ptr = static_cast<const char*>(data);
     if (transport_buf_len) {
-        to_write = std::min(TRANSPORT_BUF_SIZE - transport_buf_len, len);
+        size_t to_write = std::min(TRANSPORT_BUF_SIZE - transport_buf_len, len);
 
         memcpy(transport_buf + transport_buf_len, ptr, to_write);
         transport_buf_len += to_write;
@@ -298,9 +293,10 @@
         len -= to_write;
     }
 
+    Transport* transport = static_cast<Transport*>(priv);
     if (transport_buf_len == TRANSPORT_BUF_SIZE) {
-        r = _command_write_data(transport, transport_buf, TRANSPORT_BUF_SIZE);
-        if (r != TRANSPORT_BUF_SIZE) {
+        int64_t r = _command_write_data(transport, transport_buf, TRANSPORT_BUF_SIZE);
+        if (r != static_cast<int64_t>(TRANSPORT_BUF_SIZE)) {
             return -1;
         }
         transport_buf_len = 0;
@@ -311,9 +307,9 @@
             g_error = "internal error: transport_buf not empty";
             return -1;
         }
-        to_write = round_down(len, TRANSPORT_BUF_SIZE);
-        r = _command_write_data(transport, ptr, to_write);
-        if (r != to_write) {
+        size_t to_write = round_down(len, TRANSPORT_BUF_SIZE);
+        int64_t r = _command_write_data(transport, ptr, to_write);
+        if (r != static_cast<int64_t>(to_write)) {
             return -1;
         }
         ptr += to_write;
@@ -344,12 +340,12 @@
 }
 
 int fb_download_data_sparse(Transport* transport, struct sparse_file* s) {
-    int size = sparse_file_len(s, true, false);
-    if (size <= 0) {
+    int64_t size = sparse_file_len(s, true, false);
+    if (size <= 0 || size > std::numeric_limits<uint32_t>::max()) {
         return -1;
     }
 
-    std::string cmd(android::base::StringPrintf("download:%08x", size));
+    std::string cmd(android::base::StringPrintf("download:%08" PRIx64, size));
     int r = _command_start(transport, cmd, size, 0);
     if (r < 0) {
         return -1;
diff --git a/init/Android.bp b/init/Android.bp
index 70a4ac6..a31c5a5 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -180,6 +180,7 @@
         "util_test.cpp",
     ],
     static_libs: ["libinit"],
+    test_suites: ["device-tests"],
 }
 
 cc_benchmark {
diff --git a/init/README.md b/init/README.md
index 59ddd77..c08b07a 100644
--- a/init/README.md
+++ b/init/README.md
@@ -193,7 +193,7 @@
 
 `disabled`
 > This service will not automatically start with its class.
-  It must be explicitly started by name.
+  It must be explicitly started by name or by interface name.
 
 `file <path> <type>`
 > Open a file path and pass its fd to the launched process. _type_ must be
@@ -282,6 +282,10 @@
   "shutdown critical" will be killed. When the service tagged with "shutdown critical"
   is not running when shut down starts, it will be started.
 
+`sigstop`
+> Send SIGSTOP to the service immediately before exec is called. This is intended for debugging.
+  See the below section on debugging for how this can be used.
+
 `socket <name> <type> <perm> [ <user> [ <group> [ <seclabel> ] ] ]`
 > Create a unix domain socket named /dev/socket/_name_ and pass its fd to the
   launched process.  _type_ must be "dgram", "stream" or "seqpacket".  User and
@@ -708,23 +712,39 @@
 
 Debugging init
 --------------
-By default, programs executed by init will drop stdout and stderr into
-/dev/null. To help with debugging, you can execute your program via the
-Android program logwrapper. This will redirect stdout/stderr into the
-Android logging system (accessed via logcat).
+Launching init services without init is not recommended as init sets up a significant amount of
+environment (user, groups, security label, capabilities, etc) that is hard to replicate manually.
 
-For example
-service akmd /system/bin/logwrapper /sbin/akmd
+If it is required to debug a service from its very start, the `sigstop` service option is added.
+This option will send SIGSTOP to a service immediately before calling exec. This gives a window
+where developers can attach a debugger, strace, etc before continuing the service with SIGCONT.
 
-For quicker turnaround when working on init itself, use:
+This flag can also be dynamically controled via the ctl.sigstop_on and ctl.sigstop_off properties.
 
-    mm -j &&
-    m ramdisk-nodeps &&
-    m bootimage-nodeps &&
-    adb reboot bootloader &&
-    fastboot boot $ANDROID_PRODUCT_OUT/boot.img
+Below is an example of dynamically debugging logd via the above:
 
-Alternatively, use the emulator:
+    stop logd
+    setprop ctl.sigstop_on logd
+    start logd
+    ps -e | grep logd
+    > logd          4343     1   18156   1684 do_signal_stop 538280 T init
+    gdbclient.py -p 4343
+    b main
+    c
+    c
+    c
+    > Breakpoint 1, main (argc=1, argv=0x7ff8c9a488) at system/core/logd/main.cpp:427
 
-    emulator -partition-size 1024 \
-        -verbose -show-kernel -no-window
+Below is an example of doing the same but with strace
+
+    stop logd
+    setprop ctl.sigstop_on logd
+    start logd
+    ps -e | grep logd
+    > logd          4343     1   18156   1684 do_signal_stop 538280 T init
+    strace -p 4343
+
+    (From a different shell)
+    kill -SIGCONT 4343
+
+    > strace runs
diff --git a/init/bootchart.cpp b/init/bootchart.cpp
index 379b4fa..c2cf573 100644
--- a/init/bootchart.cpp
+++ b/init/bootchart.cpp
@@ -32,12 +32,14 @@
 #include <mutex>
 #include <thread>
 
+#include <android-base/chrono_utils.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 
 using android::base::StringPrintf;
+using android::base::boot_clock;
 using namespace std::chrono_literals;
 
 namespace android {
@@ -50,9 +52,9 @@
 static bool g_bootcharting_finished;
 
 static long long get_uptime_jiffies() {
-  std::string uptime;
-  if (!android::base::ReadFileToString("/proc/uptime", &uptime)) return 0;
-  return 100LL * strtod(uptime.c_str(), NULL);
+    constexpr int64_t kNanosecondsPerJiffy = 10000000;
+    boot_clock::time_point uptime = boot_clock::now();
+    return uptime.time_since_epoch().count() / kNanosecondsPerJiffy;
 }
 
 static std::unique_ptr<FILE, decltype(&fclose)> fopen_unique(const char* filename,
diff --git a/init/builtins.cpp b/init/builtins.cpp
index fc74dda..8bd92cc 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -82,6 +82,7 @@
 static constexpr std::chrono::nanoseconds kCommandRetryTimeout = 5s;
 
 static Result<Success> reboot_into_recovery(const std::vector<std::string>& options) {
+    LOG(ERROR) << "Rebooting into recovery";
     std::string err;
     if (!write_bootloader_message(options, &err)) {
         return Error() << "Failed to set bootloader message: " << err;
@@ -285,11 +286,8 @@
 
     if (e4crypt_is_native()) {
         if (e4crypt_set_directory_policy(args[1].c_str())) {
-            const std::vector<std::string> options = {
-                "--prompt_and_wipe_data",
-                "--reason=set_policy_failed:"s + args[1]};
-            reboot_into_recovery(options);
-            return Success();
+            return reboot_into_recovery(
+                {"--prompt_and_wipe_data", "--reason=set_policy_failed:"s + args[1]});
         }
     }
     return Success();
@@ -493,8 +491,7 @@
         /* Setup a wipe via recovery, and reboot into recovery */
         PLOG(ERROR) << "fs_mgr_mount_all suggested recovery, so wiping data via recovery.";
         const std::vector<std::string> options = {"--wipe_data", "--reason=fs_mgr_mount_all" };
-        reboot_into_recovery(options);
-        return Success();
+        return reboot_into_recovery(options);
         /* If reboot worked, there is no return. */
     } else if (code == FS_MGR_MNTALL_DEV_FILE_ENCRYPTED) {
         if (e4crypt_install_keyring()) {
@@ -522,6 +519,7 @@
         if (e4crypt_install_keyring()) {
             return Error() << "e4crypt_install_keyring() failed";
         }
+        property_set("ro.crypto.state", "encrypted");
         property_set("ro.crypto.type", "file");
 
         // Although encrypted, vold has already set the device up, so we do not need to
@@ -987,6 +985,29 @@
     return android::base::GetProperty("ro.crypto.type", "") == "file";
 }
 
+static Result<Success> ExecWithRebootOnFailure(const std::string& reboot_reason,
+                                               const BuiltinArguments& args) {
+    auto service = Service::MakeTemporaryOneshotService(args.args);
+    if (!service) {
+        return Error() << "Could not create exec service";
+    }
+    service->AddReapCallback([reboot_reason](const siginfo_t& siginfo) {
+        if (siginfo.si_code != CLD_EXITED || siginfo.si_status != 0) {
+            if (e4crypt_is_native()) {
+                LOG(ERROR) << "Rebooting into recovery, reason: " << reboot_reason;
+                reboot_into_recovery({"--prompt_and_wipe_data", "--reason="s + reboot_reason});
+            } else {
+                LOG(ERROR) << "Failure (reboot suppressed): " << reboot_reason;
+            }
+        }
+    });
+    if (auto result = service->ExecStart(); !result) {
+        return Error() << "Could not start exec service: " << result.error();
+    }
+    ServiceList::GetInstance().AddService(std::move(service));
+    return Success();
+}
+
 static Result<Success> do_installkey(const BuiltinArguments& args) {
     if (!is_file_crypto()) return Success();
 
@@ -994,15 +1015,15 @@
     if (!make_dir(unencrypted_dir, 0700) && errno != EEXIST) {
         return ErrnoError() << "Failed to create " << unencrypted_dir;
     }
-    std::vector<std::string> exec_args = {"exec", "/system/bin/vdc", "--wait", "cryptfs",
-                                          "enablefilecrypto"};
-    return do_exec({std::move(exec_args), args.context});
+    return ExecWithRebootOnFailure(
+        "enablefilecrypto_failed",
+        {{"exec", "/system/bin/vdc", "--wait", "cryptfs", "enablefilecrypto"}, args.context});
 }
 
 static Result<Success> do_init_user0(const BuiltinArguments& args) {
-    std::vector<std::string> exec_args = {"exec", "/system/bin/vdc", "--wait", "cryptfs",
-                                          "init_user0"};
-    return do_exec({std::move(exec_args), args.context});
+    return ExecWithRebootOnFailure(
+        "init_user0_failed",
+        {{"exec", "/system/bin/vdc", "--wait", "cryptfs", "init_user0"}, args.context});
 }
 
 // Builtin-function-map start
diff --git a/init/init.cpp b/init/init.cpp
index 2f3b28a..0d5690b 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -238,6 +238,10 @@
 static const std::map<std::string, ControlMessageFunction>& get_control_message_map() {
     // clang-format off
     static const std::map<std::string, ControlMessageFunction> control_message_functions = {
+        {"sigstop_on",        {ControlTarget::SERVICE,
+                               [](auto* service) { service->set_sigstop(true); return Success(); }}},
+        {"sigstop_off",       {ControlTarget::SERVICE,
+                               [](auto* service) { service->set_sigstop(false); return Success(); }}},
         {"start",             {ControlTarget::SERVICE,   DoControlStart}},
         {"stop",              {ControlTarget::SERVICE,   DoControlStop}},
         {"restart",           {ControlTarget::SERVICE,   DoControlRestart}},
@@ -624,6 +628,14 @@
         mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8));
         mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9));
 
+        // Mount staging areas for devices managed by vold
+        // See storage config details at http://source.android.com/devices/storage/
+        mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
+              "mode=0755,uid=0,gid=1000");
+        // /mnt/vendor is used to mount vendor-specific partitions that can not be
+        // part of the vendor partition, e.g. because they are mounted read-write.
+        mkdir("/mnt/vendor", 0755);
+
         // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually
         // talk to the outside world...
         InitKernelLogging(argv);
diff --git a/init/init_first_stage.cpp b/init/init_first_stage.cpp
index 0f4cc68..45d3d44 100644
--- a/init/init_first_stage.cpp
+++ b/init/init_first_stage.cpp
@@ -119,10 +119,7 @@
 FirstStageMount::FirstStageMount()
     : need_dm_verity_(false), device_tree_fstab_(fs_mgr_read_fstab_dt(), fs_mgr_free_fstab) {
     if (!device_tree_fstab_) {
-        // The client of FirstStageMount should check the existence of fstab in device-tree
-        // in advance, without parsing it. Reaching here means there is a FATAL error when
-        // parsing the fstab. So stop here to expose the failure.
-        LOG(FATAL) << "Failed to read fstab from device tree";
+        LOG(INFO) << "Failed to read fstab from device tree";
         return;
     }
     // Stores device_tree_fstab_->recs[] into mount_fstab_recs_ (vector<fstab_rec*>)
diff --git a/init/service.cpp b/init/service.cpp
index 694e5e7..03c2cee 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -155,7 +155,7 @@
     }
 }
 
-static bool ExpandArgsAndExecv(const std::vector<std::string>& args) {
+static bool ExpandArgsAndExecv(const std::vector<std::string>& args, bool sigstop) {
     std::vector<std::string> expanded_args;
     std::vector<char*> c_strings;
 
@@ -169,6 +169,10 @@
     }
     c_strings.push_back(nullptr);
 
+    if (sigstop) {
+        kill(getpid(), SIGSTOP);
+    }
+
     return execv(c_strings[0], c_strings.data()) == 0;
 }
 
@@ -303,7 +307,7 @@
     }
 }
 
-void Service::Reap() {
+void Service::Reap(const siginfo_t& siginfo) {
     if (!(flags_ & SVC_ONESHOT) || (flags_ & SVC_RESTART)) {
         KillProcessGroup(SIGKILL);
     }
@@ -312,6 +316,10 @@
     std::for_each(descriptors_.begin(), descriptors_.end(),
                   std::bind(&DescriptorInfo::Clean, std::placeholders::_1));
 
+    for (const auto& f : reap_callbacks_) {
+        f(siginfo);
+    }
+
     if (flags_ & SVC_EXEC) UnSetExec();
 
     if (flags_ & SVC_TEMPORARY) return;
@@ -578,6 +586,11 @@
     return Success();
 }
 
+Result<Success> Service::ParseSigstop(const std::vector<std::string>& args) {
+    sigstop_ = true;
+    return Success();
+}
+
 Result<Success> Service::ParseSetenv(const std::vector<std::string>& args) {
     environment_vars_.emplace_back(args[1], args[2]);
     return Success();
@@ -700,6 +713,7 @@
         {"seclabel",    {1,     1,    &Service::ParseSeclabel}},
         {"setenv",      {2,     2,    &Service::ParseSetenv}},
         {"shutdown",    {1,     1,    &Service::ParseShutdown}},
+        {"sigstop",     {0,     0,    &Service::ParseSigstop}},
         {"socket",      {3,     6,    &Service::ParseSocket}},
         {"user",        {1,     1,    &Service::ParseUser}},
         {"writepid",    {1,     kMax, &Service::ParseWritepid}},
@@ -858,7 +872,7 @@
         // priority. Aborts on failure.
         SetProcessAttributes();
 
-        if (!ExpandArgsAndExecv(args_)) {
+        if (!ExpandArgsAndExecv(args_, sigstop_)) {
             PLOG(ERROR) << "cannot execve('" << args_[0] << "')";
         }
 
diff --git a/init/service.h b/init/service.h
index d46a413..cf38f69 100644
--- a/init/service.h
+++ b/init/service.h
@@ -17,6 +17,7 @@
 #ifndef _INIT_SERVICE_H
 #define _INIT_SERVICE_H
 
+#include <signal.h>
 #include <sys/resource.h>
 #include <sys/types.h>
 
@@ -81,7 +82,7 @@
     void Stop();
     void Terminate();
     void Restart();
-    void Reap();
+    void Reap(const siginfo_t& siginfo);
     void DumpState() const;
     void SetShutdownCritical() { flags_ |= SVC_SHUTDOWN_CRITICAL; }
     bool IsShutdownCritical() const { return (flags_ & SVC_SHUTDOWN_CRITICAL) != 0; }
@@ -89,6 +90,9 @@
         is_exec_service_running_ = false;
         flags_ &= ~SVC_EXEC;
     }
+    void AddReapCallback(std::function<void(const siginfo_t& siginfo)> callback) {
+        reap_callbacks_.emplace_back(std::move(callback));
+    }
 
     static bool is_exec_service_running() { return is_exec_service_running_; }
 
@@ -114,6 +118,7 @@
     bool is_override() const { return override_; }
     bool process_cgroup_empty() const { return process_cgroup_empty_; }
     unsigned long start_order() const { return start_order_; }
+    void set_sigstop(bool value) { sigstop_ = value; }
     const std::vector<std::string>& args() const { return args_; }
 
   private:
@@ -149,6 +154,7 @@
     Result<Success> ParseSeclabel(const std::vector<std::string>& args);
     Result<Success> ParseSetenv(const std::vector<std::string>& args);
     Result<Success> ParseShutdown(const std::vector<std::string>& args);
+    Result<Success> ParseSigstop(const std::vector<std::string>& args);
     Result<Success> ParseSocket(const std::vector<std::string>& args);
     Result<Success> ParseFile(const std::vector<std::string>& args);
     Result<Success> ParseUser(const std::vector<std::string>& args);
@@ -209,7 +215,11 @@
 
     std::vector<std::pair<int, rlimit>> rlimits_;
 
+    bool sigstop_ = false;
+
     std::vector<std::string> args_;
+
+    std::vector<std::function<void(const siginfo_t& siginfo)>> reap_callbacks_;
 };
 
 class ServiceList {
diff --git a/init/sigchld_handler.cpp b/init/sigchld_handler.cpp
index 3ec76df..0b03324 100644
--- a/init/sigchld_handler.cpp
+++ b/init/sigchld_handler.cpp
@@ -81,16 +81,15 @@
         }
     }
 
-    auto status = siginfo.si_status;
-    if (WIFEXITED(status)) {
-        LOG(INFO) << name << " exited with status " << WEXITSTATUS(status) << wait_string;
-    } else if (WIFSIGNALED(status)) {
-        LOG(INFO) << name << " killed by signal " << WTERMSIG(status) << wait_string;
+    if (siginfo.si_code == CLD_EXITED) {
+        LOG(INFO) << name << " exited with status " << siginfo.si_status << wait_string;
+    } else {
+        LOG(INFO) << name << " received signal " << siginfo.si_status << wait_string;
     }
 
     if (!service) return true;
 
-    service->Reap();
+    service->Reap(siginfo);
 
     if (service->flags() & SVC_TEMPORARY) {
         ServiceList::GetInstance().RemoveService(*service);
diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp
index 4bd01d2..49027f3 100644
--- a/libbacktrace/Android.bp
+++ b/libbacktrace/Android.bp
@@ -183,6 +183,7 @@
         "art/runtime",
     ],
 
+    test_suites: ["device-tests"],
     data: [
         "testdata/arm/*",
         "testdata/arm64/*",
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 6d00dc6..dd46750 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -164,6 +164,7 @@
 
     shared_libs: ["liblog"],
     header_libs: [
+        "libbase_headers",
         "libcutils_headers",
         "libutils_headers",
     ],
diff --git a/libcutils/include/cutils/sched_policy.h b/libcutils/include/cutils/sched_policy.h
index 4c1113b..cf91b76 100644
--- a/libcutils/include/cutils/sched_policy.h
+++ b/libcutils/include/cutils/sched_policy.h
@@ -40,16 +40,17 @@
 
 /* Keep in sync with THREAD_GROUP_* in frameworks/base/core/java/android/os/Process.java */
 typedef enum {
-    SP_DEFAULT    = -1,
+    SP_DEFAULT = -1,
     SP_BACKGROUND = 0,
     SP_FOREGROUND = 1,
-    SP_SYSTEM     = 2,  // can't be used with set_sched_policy()
-    SP_AUDIO_APP  = 3,
-    SP_AUDIO_SYS  = 4,
-    SP_TOP_APP    = 5,
-    SP_RT_APP     = 6,
+    SP_SYSTEM = 2,  // can't be used with set_sched_policy()
+    SP_AUDIO_APP = 3,
+    SP_AUDIO_SYS = 4,
+    SP_TOP_APP = 5,
+    SP_RT_APP = 6,
+    SP_RESTRICTED = 7,
     SP_CNT,
-    SP_MAX        = SP_CNT - 1,
+    SP_MAX = SP_CNT - 1,
     SP_SYSTEM_DEFAULT = SP_FOREGROUND,
 } SchedPolicy;
 
diff --git a/libcutils/include/cutils/trace.h b/libcutils/include/cutils/trace.h
index bbb150d..58b9f09 100644
--- a/libcutils/include/cutils/trace.h
+++ b/libcutils/include/cutils/trace.h
@@ -74,7 +74,8 @@
 #define ATRACE_TAG_ADB              (1<<22)
 #define ATRACE_TAG_VIBRATOR         (1<<23)
 #define ATRACE_TAG_AIDL             (1<<24)
-#define ATRACE_TAG_LAST             ATRACE_TAG_AIDL
+#define ATRACE_TAG_NNAPI            (1<<25)
+#define ATRACE_TAG_LAST             ATRACE_TAG_NNAPI
 
 // Reserved for initialization.
 #define ATRACE_TAG_NOT_READY        (1ULL<<63)
diff --git a/libcutils/include/private/android_filesystem_config.h b/libcutils/include/private/android_filesystem_config.h
index 5d17698..3be8ad0 100644
--- a/libcutils/include/private/android_filesystem_config.h
+++ b/libcutils/include/private/android_filesystem_config.h
@@ -129,6 +129,8 @@
 #define AID_STATSD 1066          /* statsd daemon */
 #define AID_INCIDENTD 1067       /* incidentd daemon */
 #define AID_SECURE_ELEMENT 1068  /* secure element subsystem */
+#define AID_LMKD 1069            /* low memory killer daemon */
+#define AID_LLKD 1070            /* live lock daemon */
 /* Changes to this file must be made in AOSP, *not* in internal branches. */
 
 #define AID_SHELL 2000 /* adb and debug shell user */
diff --git a/libcutils/sched_policy.cpp b/libcutils/sched_policy.cpp
index f5ce82f..3fa548f 100644
--- a/libcutils/sched_policy.cpp
+++ b/libcutils/sched_policy.cpp
@@ -25,6 +25,7 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <android-base/macros.h>
 #include <log/log.h>
 
 /* Re-map SP_DEFAULT to the system default policy, and leave other values unchanged.
@@ -57,6 +58,7 @@
 static int bg_cpuset_fd = -1;
 static int fg_cpuset_fd = -1;
 static int ta_cpuset_fd = -1; // special cpuset for top app
+static int rs_cpuset_fd = -1;  // special cpuset for screen off restrictions
 
 // File descriptors open to /dev/stune/../tasks, setup by initialize, or -1 on error
 static int bg_schedboost_fd = -1;
@@ -151,6 +153,8 @@
             system_bg_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC);
             filename = "/dev/cpuset/top-app/tasks";
             ta_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC);
+            filename = "/dev/cpuset/restricted/tasks";
+            rs_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC);
 
             if (schedboost_enabled()) {
                 filename = "/dev/stune/top-app/tasks";
@@ -308,6 +312,9 @@
     case SP_SYSTEM:
         fd = system_bg_cpuset_fd;
         break;
+    case SP_RESTRICTED:
+        fd = rs_cpuset_fd;
+        break;
     default:
         boost_fd = fd = -1;
         break;
@@ -454,20 +461,16 @@
 
 #endif
 
-const char *get_sched_policy_name(SchedPolicy policy)
-{
+const char* get_sched_policy_name(SchedPolicy policy) {
     policy = _policy(policy);
-    static const char * const strings[SP_CNT] = {
-       [SP_BACKGROUND] = "bg",
-       [SP_FOREGROUND] = "fg",
-       [SP_SYSTEM]     = "  ",
-       [SP_AUDIO_APP]  = "aa",
-       [SP_AUDIO_SYS]  = "as",
-       [SP_TOP_APP]    = "ta",
-       [SP_RT_APP]    = "rt",
+    static const char* const kSchedPolicyNames[] = {
+            [SP_BACKGROUND] = "bg", [SP_FOREGROUND] = "fg", [SP_SYSTEM] = "  ",
+            [SP_AUDIO_APP] = "aa",  [SP_AUDIO_SYS] = "as",  [SP_TOP_APP] = "ta",
+            [SP_RT_APP] = "rt",     [SP_RESTRICTED] = "rs",
     };
-    if ((policy < SP_CNT) && (strings[policy] != NULL))
-        return strings[policy];
-    else
+    static_assert(arraysize(kSchedPolicyNames) == SP_CNT, "missing name");
+    if (policy < SP_BACKGROUND || policy >= SP_CNT) {
         return "error";
+    }
+    return kSchedPolicyNames[policy];
 }
diff --git a/libcutils/tests/sched_policy_test.cpp b/libcutils/tests/sched_policy_test.cpp
index 173174a..5942ee5 100644
--- a/libcutils/tests/sched_policy_test.cpp
+++ b/libcutils/tests/sched_policy_test.cpp
@@ -60,6 +60,12 @@
     return sleepTimes[median];
 }
 
+static void AssertPolicy(SchedPolicy expected_policy) {
+    SchedPolicy current_policy;
+    ASSERT_EQ(0, get_sched_policy(0, &current_policy));
+    EXPECT_EQ(expected_policy, current_policy);
+}
+
 TEST(SchedPolicy, set_sched_policy) {
     if (!hasCapSysNice()) {
         GTEST_LOG_(INFO) << "skipping test that requires CAP_SYS_NICE";
@@ -76,23 +82,17 @@
     const unsigned int BG_FG_SLACK_FACTOR = 100;
 
     ASSERT_EQ(0, set_sched_policy(0, SP_BACKGROUND));
+    AssertPolicy(SP_BACKGROUND);
     auto bgSleepTime = medianSleepTime();
 
     ASSERT_EQ(0, set_sched_policy(0, SP_FOREGROUND));
+    AssertPolicy(SP_FOREGROUND);
     auto fgSleepTime = medianSleepTime();
     ASSERT_GT(bgSleepTime, fgSleepTime * BG_FG_SLACK_FACTOR);
 }
 
-TEST(SchedPolicy, get_sched_policy) {
-    SchedPolicy policy;
-    ASSERT_EQ(0, get_sched_policy(0, &policy));
-
-    const char *policyName = get_sched_policy_name(policy);
-    EXPECT_NE(nullptr, policyName);
-    EXPECT_STRNE("error", policyName);
-
-    ASSERT_EQ(0, set_sched_policy(0, SP_BACKGROUND));
-    SchedPolicy newPolicy;
-    ASSERT_EQ(0, get_sched_policy(0, &newPolicy));
-    EXPECT_EQ(SP_BACKGROUND, newPolicy);
+TEST(SchedPolicy, get_sched_policy_name) {
+    EXPECT_STREQ("bg", get_sched_policy_name(SP_BACKGROUND));
+    EXPECT_STREQ("error", get_sched_policy_name(SchedPolicy(-2)));
+    EXPECT_STREQ("error", get_sched_policy_name(SP_CNT));
 }
diff --git a/libkeyutils/Android.bp b/libkeyutils/Android.bp
index 0285259..f3593ff 100644
--- a/libkeyutils/Android.bp
+++ b/libkeyutils/Android.bp
@@ -13,4 +13,5 @@
     cflags: ["-Werror"],
     shared_libs: ["libkeyutils"],
     srcs: ["keyutils_test.cpp"],
+    test_suites: ["device-tests"],
 }
diff --git a/libmemunreachable/Android.bp b/libmemunreachable/Android.bp
index f872d0f..f164a19 100644
--- a/libmemunreachable/Android.bp
+++ b/libmemunreachable/Android.bp
@@ -46,6 +46,12 @@
             static_libs: ["libunwind_llvm"],
         },
     },
+
+    // TODO(b/78118944), clang lld link flags do not work with special link
+    // rules for libunwind_llvm yet. Linked aosp_arm-eng image failed to
+    // boot up in the emulator.
+    use_clang_lld: false,
+
     export_include_dirs: ["include"],
     local_include_dirs: ["include"],
 }
@@ -83,6 +89,8 @@
             enabled: false,
         },
     },
+
+    test_suites: ["device-tests"],
 }
 
 cc_test {
@@ -97,4 +105,5 @@
         "libhwbinder",
         "libutils",
     ],
+    test_suites: ["device-tests"],
 }
diff --git a/libprocinfo/Android.bp b/libprocinfo/Android.bp
index 83b0a7f..b35882c 100644
--- a/libprocinfo/Android.bp
+++ b/libprocinfo/Android.bp
@@ -83,4 +83,6 @@
             suffix: "64",
         },
     },
+
+    test_suites: ["device-tests"],
 }
diff --git a/libsparse/include/sparse/sparse.h b/libsparse/include/sparse/sparse.h
index 356f65f..1b91ead 100644
--- a/libsparse/include/sparse/sparse.h
+++ b/libsparse/include/sparse/sparse.h
@@ -18,6 +18,7 @@
 #define _LIBSPARSE_SPARSE_H_
 
 #include <stdbool.h>
+#include <stddef.h>
 #include <stdint.h>
 
 #ifdef	__cplusplus
@@ -26,6 +27,11 @@
 
 struct sparse_file;
 
+// The callbacks in sparse_file_callback() and sparse_file_foreach_chunk() take
+// size_t as the length type (was `int` in past). This allows clients to keep
+// their codes compatibile with both versions as needed.
+#define	SPARSE_CALLBACK_USES_SIZE_T
+
 /**
  * sparse_file_new - create a new sparse file cookie
  *
@@ -201,7 +207,7 @@
  * Returns 0 on success, negative errno on error.
  */
 int sparse_file_callback(struct sparse_file *s, bool sparse, bool crc,
-		int (*write)(void *priv, const void *data, int len), void *priv);
+		int (*write)(void *priv, const void *data, size_t len), void *priv);
 
 /**
  * sparse_file_foreach_chunk - call a callback for data blocks in sparse file
@@ -218,7 +224,7 @@
  * Returns 0 on success, negative errno on error.
  */
 int sparse_file_foreach_chunk(struct sparse_file *s, bool sparse, bool crc,
-	int (*write)(void *priv, const void *data, int len, unsigned int block,
+	int (*write)(void *priv, const void *data, size_t len, unsigned int block,
 		     unsigned int nr_blocks),
 	void *priv);
 /**
diff --git a/libsparse/output_file.c b/libsparse/output_file.c
index 51e60ef..002ad27 100644
--- a/libsparse/output_file.c
+++ b/libsparse/output_file.c
@@ -109,7 +109,7 @@
 struct output_file_callback {
 	struct output_file out;
 	void *priv;
-	int (*write)(void *priv, const void *buf, int len);
+	int (*write)(void *priv, const void *buf, size_t len);
 };
 
 #define to_output_file_callback(_o) \
@@ -634,7 +634,8 @@
 	return &outn->out;
 }
 
-struct output_file *output_file_open_callback(int (*write)(void *, const void *, int),
+struct output_file *output_file_open_callback(
+		int (*write)(void *, const void *, size_t),
 		void *priv, unsigned int block_size, int64_t len,
 		int gz __unused, int sparse, int chunks, int crc)
 {
diff --git a/libsparse/output_file.h b/libsparse/output_file.h
index b67e94e..690f610 100644
--- a/libsparse/output_file.h
+++ b/libsparse/output_file.h
@@ -27,7 +27,8 @@
 
 struct output_file *output_file_open_fd(int fd, unsigned int block_size, int64_t len,
 		int gz, int sparse, int chunks, int crc);
-struct output_file *output_file_open_callback(int (*write)(void *, const void *, int),
+struct output_file *output_file_open_callback(
+		int (*write)(void *, const void *, size_t),
 		void *priv, unsigned int block_size, int64_t len, int gz, int sparse,
 		int chunks, int crc);
 int write_data_chunk(struct output_file *out, unsigned int len, void *data);
diff --git a/libsparse/sparse.c b/libsparse/sparse.c
index b175860..466435f 100644
--- a/libsparse/sparse.c
+++ b/libsparse/sparse.c
@@ -179,7 +179,7 @@
 }
 
 int sparse_file_callback(struct sparse_file *s, bool sparse, bool crc,
-		int (*write)(void *priv, const void *data, int len), void *priv)
+		int (*write)(void *priv, const void *data, size_t len), void *priv)
 {
 	int ret;
 	int chunks;
@@ -203,11 +203,11 @@
 	void		*priv;
 	unsigned int	block;
 	unsigned int	nr_blocks;
-	int (*write)(void *priv, const void *data, int len, unsigned int block,
-		     unsigned int nr_blocks);
+	int (*write)(void *priv, const void *data, size_t len,
+		     unsigned int block, unsigned int nr_blocks);
 };
 
-static int foreach_chunk_write(void *priv, const void *data, int len)
+static int foreach_chunk_write(void *priv, const void *data, size_t len)
 {
 	struct chunk_data *chk = priv;
 
@@ -215,7 +215,7 @@
 }
 
 int sparse_file_foreach_chunk(struct sparse_file *s, bool sparse, bool crc,
-	int (*write)(void *priv, const void *data, int len, unsigned int block,
+	int (*write)(void *priv, const void *data, size_t len, unsigned int block,
 		     unsigned int nr_blocks),
 	void *priv)
 {
@@ -250,7 +250,7 @@
 	return ret;
 }
 
-static int out_counter_write(void *priv, const void *data __unused, int len)
+static int out_counter_write(void *priv, const void *data __unused, size_t len)
 {
 	int64_t *count = priv;
 	*count += len;
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index 6868f18..d411cee 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -186,6 +186,7 @@
         "libgmock",
     ],
 
+    test_suites: ["device-tests"],
     data: [
         "tests/files/elf32.xz",
         "tests/files/elf64.xz",
diff --git a/libunwindstack/RegsArm.cpp b/libunwindstack/RegsArm.cpp
index 27cab43..de22bde 100644
--- a/libunwindstack/RegsArm.cpp
+++ b/libunwindstack/RegsArm.cpp
@@ -197,4 +197,8 @@
   return true;
 }
 
+Regs* RegsArm::Clone() {
+  return new RegsArm(*this);
+}
+
 }  // namespace unwindstack
diff --git a/libunwindstack/RegsArm64.cpp b/libunwindstack/RegsArm64.cpp
index 4a2a6c4..a68f6e0 100644
--- a/libunwindstack/RegsArm64.cpp
+++ b/libunwindstack/RegsArm64.cpp
@@ -148,4 +148,8 @@
   return true;
 }
 
+Regs* RegsArm64::Clone() {
+  return new RegsArm64(*this);
+}
+
 }  // namespace unwindstack
diff --git a/libunwindstack/RegsMips.cpp b/libunwindstack/RegsMips.cpp
index c87e69b..2e6908c 100644
--- a/libunwindstack/RegsMips.cpp
+++ b/libunwindstack/RegsMips.cpp
@@ -173,4 +173,8 @@
   return true;
 }
 
+Regs* RegsMips::Clone() {
+  return new RegsMips(*this);
+}
+
 }  // namespace unwindstack
diff --git a/libunwindstack/RegsMips64.cpp b/libunwindstack/RegsMips64.cpp
index 236a922..0b835a1 100644
--- a/libunwindstack/RegsMips64.cpp
+++ b/libunwindstack/RegsMips64.cpp
@@ -160,4 +160,8 @@
   return true;
 }
 
+Regs* RegsMips64::Clone() {
+  return new RegsMips64(*this);
+}
+
 }  // namespace unwindstack
diff --git a/libunwindstack/RegsX86.cpp b/libunwindstack/RegsX86.cpp
index f7e0614..9bb39d1 100644
--- a/libunwindstack/RegsX86.cpp
+++ b/libunwindstack/RegsX86.cpp
@@ -179,4 +179,8 @@
   return false;
 }
 
+Regs* RegsX86::Clone() {
+  return new RegsX86(*this);
+}
+
 }  // namespace unwindstack
diff --git a/libunwindstack/RegsX86_64.cpp b/libunwindstack/RegsX86_64.cpp
index 7d6ad86..ebad3f4 100644
--- a/libunwindstack/RegsX86_64.cpp
+++ b/libunwindstack/RegsX86_64.cpp
@@ -168,4 +168,8 @@
   return true;
 }
 
+Regs* RegsX86_64::Clone() {
+  return new RegsX86_64(*this);
+}
+
 }  // namespace unwindstack
diff --git a/libunwindstack/include/unwindstack/Regs.h b/libunwindstack/include/unwindstack/Regs.h
index 4bac473..878ced3 100644
--- a/libunwindstack/include/unwindstack/Regs.h
+++ b/libunwindstack/include/unwindstack/Regs.h
@@ -73,6 +73,8 @@
 
   uint16_t total_regs() { return total_regs_; }
 
+  virtual Regs* Clone() = 0;
+
   static ArchEnum CurrentArch();
   static Regs* RemoteGet(pid_t pid);
   static Regs* CreateFromUcontext(ArchEnum arch, void* ucontext);
diff --git a/libunwindstack/include/unwindstack/RegsArm.h b/libunwindstack/include/unwindstack/RegsArm.h
index 31e6797..44f6744 100644
--- a/libunwindstack/include/unwindstack/RegsArm.h
+++ b/libunwindstack/include/unwindstack/RegsArm.h
@@ -50,6 +50,8 @@
   void set_pc(uint64_t pc) override;
   void set_sp(uint64_t sp) override;
 
+  Regs* Clone() override final;
+
   static Regs* Read(void* data);
 
   static Regs* CreateFromUcontext(void* ucontext);
diff --git a/libunwindstack/include/unwindstack/RegsArm64.h b/libunwindstack/include/unwindstack/RegsArm64.h
index 0c45eba..a72f91f 100644
--- a/libunwindstack/include/unwindstack/RegsArm64.h
+++ b/libunwindstack/include/unwindstack/RegsArm64.h
@@ -50,6 +50,8 @@
   void set_pc(uint64_t pc) override;
   void set_sp(uint64_t sp) override;
 
+  Regs* Clone() override final;
+
   static Regs* Read(void* data);
 
   static Regs* CreateFromUcontext(void* ucontext);
diff --git a/libunwindstack/include/unwindstack/RegsMips.h b/libunwindstack/include/unwindstack/RegsMips.h
index 709f9e2..c9dd202 100644
--- a/libunwindstack/include/unwindstack/RegsMips.h
+++ b/libunwindstack/include/unwindstack/RegsMips.h
@@ -50,6 +50,8 @@
   void set_pc(uint64_t pc) override;
   void set_sp(uint64_t sp) override;
 
+  Regs* Clone() override final;
+
   static Regs* Read(void* data);
 
   static Regs* CreateFromUcontext(void* ucontext);
diff --git a/libunwindstack/include/unwindstack/RegsMips64.h b/libunwindstack/include/unwindstack/RegsMips64.h
index 1de83ea..7c42812 100644
--- a/libunwindstack/include/unwindstack/RegsMips64.h
+++ b/libunwindstack/include/unwindstack/RegsMips64.h
@@ -50,6 +50,8 @@
   void set_pc(uint64_t pc) override;
   void set_sp(uint64_t sp) override;
 
+  Regs* Clone() override final;
+
   static Regs* Read(void* data);
 
   static Regs* CreateFromUcontext(void* ucontext);
diff --git a/libunwindstack/include/unwindstack/RegsX86.h b/libunwindstack/include/unwindstack/RegsX86.h
index 586c9d8..d19e449 100644
--- a/libunwindstack/include/unwindstack/RegsX86.h
+++ b/libunwindstack/include/unwindstack/RegsX86.h
@@ -53,6 +53,8 @@
   void set_pc(uint64_t pc) override;
   void set_sp(uint64_t sp) override;
 
+  Regs* Clone() override final;
+
   static Regs* Read(void* data);
 
   static Regs* CreateFromUcontext(void* ucontext);
diff --git a/libunwindstack/include/unwindstack/RegsX86_64.h b/libunwindstack/include/unwindstack/RegsX86_64.h
index 061f479..dc9a220 100644
--- a/libunwindstack/include/unwindstack/RegsX86_64.h
+++ b/libunwindstack/include/unwindstack/RegsX86_64.h
@@ -53,6 +53,8 @@
   void set_pc(uint64_t pc) override;
   void set_sp(uint64_t sp) override;
 
+  Regs* Clone() override final;
+
   static Regs* Read(void* data);
 
   static Regs* CreateFromUcontext(void* ucontext);
diff --git a/libunwindstack/tests/RegsFake.h b/libunwindstack/tests/RegsFake.h
index ede16b3..d6ca9b7 100644
--- a/libunwindstack/tests/RegsFake.h
+++ b/libunwindstack/tests/RegsFake.h
@@ -58,6 +58,8 @@
   void FakeSetReturnAddress(uint64_t return_address) { fake_return_address_ = return_address; }
   void FakeSetReturnAddressValid(bool valid) { fake_return_address_valid_ = valid; }
 
+  Regs* Clone() override { return nullptr; }
+
  private:
   ArchEnum fake_arch_ = ARCH_UNKNOWN;
   uint64_t fake_pc_ = 0;
@@ -83,6 +85,8 @@
   bool SetPcFromReturnAddress(Memory*) override { return false; }
   bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
 
+  Regs* Clone() override { return nullptr; }
+
  private:
   uint64_t fake_pc_ = 0;
   uint64_t fake_sp_ = 0;
diff --git a/libunwindstack/tests/RegsTest.cpp b/libunwindstack/tests/RegsTest.cpp
index d15823e..90c3fe6 100644
--- a/libunwindstack/tests/RegsTest.cpp
+++ b/libunwindstack/tests/RegsTest.cpp
@@ -286,4 +286,39 @@
   EXPECT_EQ(ARCH_MIPS64, mips64_regs.Arch());
 }
 
+template <typename RegisterType>
+void clone_test(Regs* regs) {
+  RegisterType* register_values = reinterpret_cast<RegisterType*>(regs->RawData());
+  int num_regs = regs->total_regs();
+  for (int i = 0; i < num_regs; ++i) {
+    register_values[i] = i;
+  }
+
+  std::unique_ptr<Regs> clone(regs->Clone());
+  ASSERT_EQ(regs->total_regs(), clone->total_regs());
+  RegisterType* clone_values = reinterpret_cast<RegisterType*>(clone->RawData());
+  for (int i = 0; i < num_regs; ++i) {
+    EXPECT_EQ(register_values[i], clone_values[i]);
+    EXPECT_NE(&register_values[i], &clone_values[i]);
+  }
+}
+
+TEST_F(RegsTest, clone) {
+  std::vector<std::unique_ptr<Regs>> regs;
+  regs.emplace_back(new RegsArm());
+  regs.emplace_back(new RegsArm64());
+  regs.emplace_back(new RegsX86());
+  regs.emplace_back(new RegsX86_64());
+  regs.emplace_back(new RegsMips());
+  regs.emplace_back(new RegsMips64());
+
+  for (auto& r : regs) {
+    if (r->Is32Bit()) {
+      clone_test<uint32_t>(r.get());
+    } else {
+      clone_test<uint64_t>(r.get());
+    }
+  }
+}
+
 }  // namespace unwindstack
diff --git a/libziparchive/Android.bp b/libziparchive/Android.bp
index 075fb86..6c06618 100644
--- a/libziparchive/Android.bp
+++ b/libziparchive/Android.bp
@@ -61,6 +61,7 @@
     vndk: {
         enabled: true,
     },
+    double_loadable: true,
 
     defaults: [
         "libziparchive_defaults",
@@ -92,6 +93,10 @@
     host_supported: true,
     defaults: ["libziparchive_flags"],
 
+    data: [
+        "testdata/**/*",
+    ],
+
     srcs: [
         "entry_name_utils_test.cc",
         "zip_archive_test.cc",
diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc
index ad673dc..377479f 100644
--- a/libziparchive/zip_archive_test.cc
+++ b/libziparchive/zip_archive_test.cc
@@ -34,7 +34,7 @@
 #include <ziparchive/zip_archive.h>
 #include <ziparchive/zip_archive_stream_entry.h>
 
-static std::string test_data_dir;
+static std::string test_data_dir = android::base::GetExecutableDirectory() + "/testdata";
 
 static const std::string kMissingZip = "missing.zip";
 static const std::string kValidZip = "valid.zip";
@@ -729,41 +729,3 @@
     ASSERT_EQ(0u, writer.GetOutput().size());
   }
 }
-
-int main(int argc, char** argv) {
-  ::testing::InitGoogleTest(&argc, argv);
-
-  static struct option options[] = {{"test_data_dir", required_argument, nullptr, 't'},
-                                    {nullptr, 0, nullptr, 0}};
-
-  while (true) {
-    int option_index;
-    const int c = getopt_long_only(argc, argv, "", options, &option_index);
-    if (c == -1) {
-      break;
-    }
-
-    if (c == 't') {
-      test_data_dir = optarg;
-    }
-  }
-
-  if (test_data_dir.size() == 0) {
-    printf("Test data flag (--test_data_dir) required\n\n");
-    return -1;
-  }
-
-  if (test_data_dir[0] != '/') {
-    std::vector<char> cwd_buffer(1024);
-    const char* cwd = getcwd(cwd_buffer.data(), cwd_buffer.size() - 1);
-    if (cwd == nullptr) {
-      printf("Cannot get current working directory, use an absolute path instead, was %s\n\n",
-             test_data_dir.c_str());
-      return -2;
-    }
-    test_data_dir = '/' + test_data_dir;
-    test_data_dir = cwd + test_data_dir;
-  }
-
-  return RUN_ALL_TESTS();
-}
diff --git a/llkd/Android.bp b/llkd/Android.bp
new file mode 100644
index 0000000..a6edd26
--- /dev/null
+++ b/llkd/Android.bp
@@ -0,0 +1,42 @@
+cc_library_headers {
+    name: "llkd_headers",
+
+    export_include_dirs: ["include"],
+}
+
+cc_library_static {
+    name: "libllkd",
+
+    srcs: [
+        "libllkd.cpp",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "liblog",
+    ],
+
+    export_include_dirs: ["include"],
+
+    cflags: ["-Werror"],
+}
+
+cc_binary {
+    name: "llkd",
+
+    srcs: [
+        "llkd.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "liblog",
+    ],
+    static_libs: [
+        "libllkd",
+    ],
+    cflags: ["-Werror"],
+
+    init_rc: ["llkd.rc"],
+}
diff --git a/llkd/OWNERS b/llkd/OWNERS
new file mode 100644
index 0000000..b6af537
--- /dev/null
+++ b/llkd/OWNERS
@@ -0,0 +1,2 @@
+salyzyn@google.com
+surenb@google.com
diff --git a/llkd/README.md b/llkd/README.md
new file mode 100644
index 0000000..b2ba2a2
--- /dev/null
+++ b/llkd/README.md
@@ -0,0 +1,117 @@
+Android Live-LocK Daemon
+========================
+
+Introduction
+------------
+
+Android Live-LocK Daemon (llkd) is used to catch kernel deadlocks and mitigate.
+
+Code is structured to allow integration into another service as either as part
+of the main loop, or spun off as a thread should that be necessary.  A default
+standalone implementation is provided by llkd component.
+
+The 'C' interface from libllkd component is thus:
+
+    #include "llkd.h"
+    bool llkInit(const char* threadname) /* return true if enabled */
+    unsigned llkCheckMillseconds(void)   /* ms to sleep for next check */
+
+If a threadname is provided, a thread will be automatically spawned, otherwise
+caller must call llkCheckMilliseconds in its main loop.  Function will return
+the period of time before the next expected call to this handler.
+
+Operations
+----------
+
+If a thread is in D or Z state with no forward progress for longer than
+ro.llk.timeout_ms, or ro.llk.[D|Z].timeout_ms, kill the process or parent
+process respectively.  If another scan shows the same process continues to
+exist, then have a confirmed live-lock condition and need to panic.  Panic
+the kernel in a manner to provide the greatest bugreporting details as to the
+condition.  Add a alarm self watchdog should llkd ever get locked up that is
+double the expected time to flow through the mainloop.  Sampling is every
+ro.llk_sample_ms.
+
+Default will not monitor init, or [kthreadd] and all that [kthreadd] spawns.
+This reduces the effectiveness of llkd by limiting its coverage.  If there is
+value in covering [kthreadd] spawned threads, the requirement will be that
+the drivers not remain in a persistent 'D' state, or that they have mechanisms
+to recover the thread should it be killed externally (this is good driver
+coding hygiene, a common request to add such to publicly reviewed kernel.org
+maintained drivers).  For instance use wait_event_interruptible() instead of
+wait_event().  The blacklists can be adjusted accordingly if these
+conditions are met to cover kernel components.
+
+An accompanying gTest set have been added, and will setup a persistent D or Z
+process, with and without forward progress, but not in a live-lock state
+because that would require a buggy kernel, or a module or kernel modification
+to stimulate.  The test will check that llkd will mitigate first by killing
+the appropriate process.  D state is setup by vfork() waiting for exec() in
+child process.  Z state is setup by fork() and an un-waited for child process.
+Should be noted that both of these conditions should never happen on Android
+on purpose, and llkd effectively sweeps up processes that create these
+conditions.  If the test can, it will reconfigure llkd to expedite the test
+duration by adjusting the ro.llk.* Android properties.  Tests run the D state
+with some scheduling progress to ensure that ABA checking prevents false
+triggers. If 100% reliable ABA on platform, then ro.llk.killtest can be
+set to false; however this will result in some of the unit tests to panic
+kernel instead of deal with more graceful kill operation.
+
+Android Properties
+------------------
+
+Android Properties llkd respond to (<prop>_ms parms are in milliseconds):
+
+#### ro.config.low_ram
+default false, if true do not sysrq t (dump all threads).
+
+#### ro.llk.enable
+default false, allow live-lock daemon to be enabled.
+
+#### llk.enable
+default ro.llk.enable, and evaluated for eng.
+
+#### ro.khungtask.enable
+default false, allow [khungtask] daemon to be enabled.
+
+#### khungtask.enable
+default ro.khungtask.enable and evaluated for eng.
+
+#### ro.llk.mlockall
+default false, enable call to mlockall().
+
+#### ro.khungtask.timeout
+default value 12 minutes, [khungtask] maximum timelimit.
+
+#### ro.llk.timeout_ms
+default 10 minutes, D or Z maximum timelimit, double this value and it sets
+the alarm watchdog for llkd.
+
+#### ro.llk.D.timeout_ms
+default ro.llk.timeout_ms, D maximum timelimit.
+
+#### ro.llk.Z.timeout_ms
+default ro.llk.timeout_ms, Z maximum timelimit.
+
+#### ro.llk.check_ms
+default 2 minutes samples of threads for D or Z.
+
+#### ro.llk.blacklist.process
+default 0,1,2 (kernel, init and [kthreadd]) plus process names
+init,[kthreadd],[khungtaskd],lmkd,lmkd.llkd,llkd,watchdogd,
+[watchdogd],[watchdogd/0],...,[watchdogd/<get_nprocs-1>].
+
+#### ro.llk.blacklist.parent
+default 0,2 (kernel and [kthreadd]).
+
+#### ro.llk.blacklist.uid
+default <empty>, comma separated list of uid numbers or names.
+
+Architectural Concerns
+----------------------
+
+- Create kernel module and associated gTest to actually test panic.
+- Create gTest to test out blacklist (ro.llk.blacklist.<properties> generally
+  not be inputs).  Could require more test-only interfaces to libllkd.
+- Speed up gTest using something else than ro.llk.<properties>, which should
+  not be inputs.
diff --git a/llkd/include/llkd.h b/llkd/include/llkd.h
new file mode 100644
index 0000000..e3ae4bb
--- /dev/null
+++ b/llkd/include/llkd.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LLKD_H_
+#define _LLKD_H_
+
+#ifndef LOG_TAG
+#define LOG_TAG "livelock"
+#endif
+
+#include <stdbool.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+bool llkInit(const char* threadname); /* threadname NULL, not spawned */
+unsigned llkCheckMilliseconds(void);
+
+/* clang-format off */
+#define LLK_ENABLE_WRITEABLE_PROPERTY  "llk.enable"
+#define LLK_ENABLE_PROPERTY            "ro." LLK_ENABLE_WRITEABLE_PROPERTY
+#define LLK_ENABLE_DEFAULT             false /* "eng" and userdebug true */
+#define KHT_ENABLE_WRITEABLE_PROPERTY  "khungtask.enable"
+#define KHT_ENABLE_PROPERTY            "ro." KHT_ENABLE_WRITEABLE_PROPERTY
+#define LLK_MLOCKALL_PROPERTY          "ro.llk.mlockall"
+#define LLK_MLOCKALL_DEFAULT           true
+#define LLK_KILLTEST_PROPERTY          "ro.llk.killtest"
+#define LLK_KILLTEST_DEFAULT           true
+#define LLK_TIMEOUT_MS_PROPERTY        "ro.llk.timeout_ms"
+#define KHT_TIMEOUT_PROPERTY           "ro.khungtask.timeout"
+#define LLK_D_TIMEOUT_MS_PROPERTY      "ro.llk.D.timeout_ms"
+#define LLK_Z_TIMEOUT_MS_PROPERTY      "ro.llk.Z.timeout_ms"
+#define LLK_CHECK_MS_PROPERTY          "ro.llk.check_ms"
+/* LLK_CHECK_MS_DEFAULT = actual timeout_ms / LLK_CHECKS_PER_TIMEOUT_DEFAULT */
+#define LLK_CHECKS_PER_TIMEOUT_DEFAULT 5
+#define LLK_BLACKLIST_PROCESS_PROPERTY "ro.llk.blacklist.process"
+#define LLK_BLACKLIST_PROCESS_DEFAULT  \
+    "0,1,2,init,[kthreadd],[khungtaskd],lmkd,lmkd.llkd,llkd,watchdogd,[watchdogd],[watchdogd/0]"
+#define LLK_BLACKLIST_PARENT_PROPERTY  "ro.llk.blacklist.parent"
+#define LLK_BLACKLIST_PARENT_DEFAULT   "0,2,[kthreadd]"
+#define LLK_BLACKLIST_UID_PROPERTY     "ro.llk.blacklist.uid"
+#define LLK_BLACKLIST_UID_DEFAULT      ""
+/* clang-format on */
+
+__END_DECLS
+
+#ifdef __cplusplus
+extern "C++" { /* In case this included wrapped with __BEGIN_DECLS */
+
+#include <chrono>
+
+__BEGIN_DECLS
+/* C++ code allowed to not specify threadname argument for this C linkage */
+bool llkInit(const char* threadname = nullptr);
+__END_DECLS
+std::chrono::milliseconds llkCheck(bool checkRunning = false);
+
+/* clang-format off */
+#define LLK_TIMEOUT_MS_DEFAULT  std::chrono::duration_cast<milliseconds>(std::chrono::minutes(10))
+#define LLK_TIMEOUT_MS_MINIMUM  std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::seconds(10))
+#define LLK_CHECK_MS_MINIMUM    std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::seconds(1))
+/* clang-format on */
+
+} /* extern "C++" */
+#endif /* __cplusplus */
+
+#endif /* _LLKD_H_ */
diff --git a/llkd/libllkd.cpp b/llkd/libllkd.cpp
new file mode 100644
index 0000000..f357cc2
--- /dev/null
+++ b/llkd/libllkd.cpp
@@ -0,0 +1,1168 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "llkd.h"
+
+#include <ctype.h>
+#include <dirent.h>  // opendir() and readdir()
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <pwd.h>  // getpwuid()
+#include <signal.h>
+#include <stdint.h>
+#include <sys/cdefs.h>  // ___STRING, __predict_true() and _predict_false()
+#include <sys/mman.h>   // mlockall()
+#include <sys/prctl.h>
+#include <sys/stat.h>     // lstat()
+#include <sys/syscall.h>  // __NR_getdents64
+#include <sys/sysinfo.h>  // get_nprocs_conf()
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <chrono>
+#include <ios>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/parseint.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <cutils/android_get_control_file.h>
+#include <log/log_main.h>
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
+
+#define TASK_COMM_LEN 16  // internal kernel, not uapi, from .../linux/include/linux/sched.h
+
+using namespace std::chrono_literals;
+using namespace std::chrono;
+
+namespace {
+
+constexpr pid_t kernelPid = 0;
+constexpr pid_t initPid = 1;
+constexpr pid_t kthreaddPid = 2;
+
+constexpr char procdir[] = "/proc/";
+
+// Configuration
+milliseconds llkUpdate;                              // last check ms signature
+milliseconds llkCycle;                               // ms to next thread check
+bool llkEnable = LLK_ENABLE_DEFAULT;                 // llk daemon enabled
+bool llkRunning = false;                             // thread is running
+bool llkMlockall = LLK_MLOCKALL_DEFAULT;             // run mlocked
+bool llkTestWithKill = LLK_KILLTEST_DEFAULT;         // issue test kills
+milliseconds llkTimeoutMs = LLK_TIMEOUT_MS_DEFAULT;  // default timeout
+enum { llkStateD, llkStateZ, llkNumStates };         // state indexes
+milliseconds llkStateTimeoutMs[llkNumStates];        // timeout override for each detection state
+milliseconds llkCheckMs;                             // checking interval to inspect any
+                                                     // persistent live-locked states
+bool llkLowRam;                                      // ro.config.low_ram
+bool khtEnable = LLK_ENABLE_DEFAULT;                 // [khungtaskd] panic
+// [khungtaskd] should have a timeout beyond the granularity of llkTimeoutMs.
+// Provides a wide angle of margin b/c khtTimeout is also its granularity.
+seconds khtTimeout = duration_cast<seconds>(llkTimeoutMs * (1 + LLK_CHECKS_PER_TIMEOUT_DEFAULT) /
+                                            LLK_CHECKS_PER_TIMEOUT_DEFAULT);
+
+// Blacklist variables, initialized with comma separated lists of high false
+// positive and/or dangerous references, e.g. without self restart, for pid,
+// ppid, name and uid:
+
+// list of pids, or tids or names to skip. kernel pid (0), init pid (1),
+// [kthreadd] pid (2), ourselves, "init", "[kthreadd]", "lmkd", "llkd" or
+// combinations of watchdogd in kernel and user space.
+std::unordered_set<std::string> llkBlacklistProcess;
+// list of parent pids, comm or cmdline names to skip. default:
+// kernel pid (0), [kthreadd] (2), or ourselves, enforced and implied
+std::unordered_set<std::string> llkBlacklistParent;
+// list of uids, and uid names, to skip, default nothing
+std::unordered_set<std::string> llkBlacklistUid;
+
+class dir {
+  public:
+    enum level { proc, task, numLevels };
+
+  private:
+    int fd;
+    size_t available_bytes;
+    dirent* next;
+    // each directory level picked to be just north of 4K in size
+    static constexpr size_t buffEntries = 15;
+    static dirent buff[numLevels][buffEntries];
+
+    bool fill(enum level index) {
+        if (index >= numLevels) return false;
+        if (available_bytes != 0) return true;
+        if (__predict_false(fd < 0)) return false;
+        // getdents64 has no libc wrapper
+        auto rc = TEMP_FAILURE_RETRY(syscall(__NR_getdents64, fd, buff[index], sizeof(buff[0]), 0));
+        if (rc <= 0) return false;
+        available_bytes = rc;
+        next = buff[index];
+        return true;
+    }
+
+  public:
+    dir() : fd(-1), available_bytes(0), next(nullptr) {}
+
+    explicit dir(const char* directory)
+        : fd(__predict_true(directory != nullptr)
+                 ? ::open(directory, O_CLOEXEC | O_DIRECTORY | O_RDONLY)
+                 : -1),
+          available_bytes(0),
+          next(nullptr) {}
+
+    explicit dir(const std::string&& directory)
+        : fd(::open(directory.c_str(), O_CLOEXEC | O_DIRECTORY | O_RDONLY)),
+          available_bytes(0),
+          next(nullptr) {}
+
+    explicit dir(const std::string& directory)
+        : fd(::open(directory.c_str(), O_CLOEXEC | O_DIRECTORY | O_RDONLY)),
+          available_bytes(0),
+          next(nullptr) {}
+
+    // Don't need any copy or move constructors.
+    explicit dir(const dir& c) = delete;
+    explicit dir(dir& c) = delete;
+    explicit dir(dir&& c) = delete;
+
+    ~dir() {
+        if (fd >= 0) {
+            ::close(fd);
+        }
+    }
+
+    operator bool() const { return fd >= 0; }
+
+    void reset(void) {
+        if (fd >= 0) {
+            ::close(fd);
+            fd = -1;
+            available_bytes = 0;
+            next = nullptr;
+        }
+    }
+
+    dir& reset(const char* directory) {
+        reset();
+        // available_bytes will _always_ be zero here as its value is
+        // intimately tied to fd < 0 or not.
+        fd = ::open(directory, O_CLOEXEC | O_DIRECTORY | O_RDONLY);
+        return *this;
+    }
+
+    void rewind(void) {
+        if (fd >= 0) {
+            ::lseek(fd, off_t(0), SEEK_SET);
+            available_bytes = 0;
+            next = nullptr;
+        }
+    }
+
+    dirent* read(enum level index = proc, dirent* def = nullptr) {
+        if (!fill(index)) return def;
+        auto ret = next;
+        available_bytes -= next->d_reclen;
+        next = reinterpret_cast<dirent*>(reinterpret_cast<char*>(next) + next->d_reclen);
+        return ret;
+    }
+} llkTopDirectory;
+
+dirent dir::buff[dir::numLevels][dir::buffEntries];
+
+// helper functions
+
+bool llkIsMissingExeLink(pid_t tid) {
+    char c;
+    // CAP_SYS_PTRACE is required to prevent ret == -1, but ENOENT is signal
+    auto ret = ::readlink((procdir + std::to_string(tid) + "/exe").c_str(), &c, sizeof(c));
+    return (ret == -1) && (errno == ENOENT);
+}
+
+// Common routine where caller accepts empty content as error/passthrough.
+// Reduces the churn of reporting read errors in the callers.
+std::string ReadFile(std::string&& path) {
+    std::string content;
+    if (!android::base::ReadFileToString(path, &content)) {
+        PLOG(DEBUG) << "Read " << path << " failed";
+        content = "";
+    }
+    return content;
+}
+
+std::string llkProcGetName(pid_t tid, const char* node = "/cmdline") {
+    std::string content = ReadFile(procdir + std::to_string(tid) + node);
+    static constexpr char needles[] = " \t\r\n";  // including trailing nul
+    auto pos = content.find_first_of(needles, 0, sizeof(needles));
+    if (pos != std::string::npos) {
+        content.erase(pos);
+    }
+    return content;
+}
+
+uid_t llkProcGetUid(pid_t tid) {
+    // Get the process' uid.  The following read from /status is admittedly
+    // racy, prone to corruption due to shape-changes.  The consequences are
+    // not catastrophic as we sample a few times before taking action.
+    //
+    // If /loginuid worked on reliably, or on Android (all tasks report -1)...
+    // Android lmkd causes /cgroup to contain memory:/<dom>/uid_<uid>/pid_<pid>
+    // which is tighter, but also not reliable.
+    std::string content = ReadFile(procdir + std::to_string(tid) + "/status");
+    static constexpr char Uid[] = "\nUid:";
+    auto pos = content.find(Uid);
+    if (pos == std::string::npos) {
+        return -1;
+    }
+    pos += ::strlen(Uid);
+    while ((pos < content.size()) && ::isblank(content[pos])) {
+        ++pos;
+    }
+    content.erase(0, pos);
+    for (pos = 0; (pos < content.size()) && ::isdigit(content[pos]); ++pos) {
+        ;
+    }
+    // Content of form 'Uid:	0	0	0	0', newline is error
+    if ((pos >= content.size()) || !::isblank(content[pos])) {
+        return -1;
+    }
+    content.erase(pos);
+    uid_t ret;
+    if (!android::base::ParseInt(content, &ret, uid_t(0))) {
+        return -1;
+    }
+    return ret;
+}
+
+struct proc {
+    pid_t tid;                     // monitored thread id (in Z or D state).
+    nanoseconds schedUpdate;       // /proc/<tid>/sched "se.avg.lastUpdateTime",
+    uint64_t nrSwitches;           // /proc/<tid>/sched "nr_switches" for
+                                   // refined ABA problem detection, determine
+                                   // forward scheduling progress.
+    milliseconds update;           // llkUpdate millisecond signature of last.
+    milliseconds count;            // duration in state.
+    pid_t pid;                     // /proc/<pid> before iterating through
+                                   // /proc/<pid>/task/<tid> for threads.
+    pid_t ppid;                    // /proc/<tid>/stat field 4 parent pid.
+    uid_t uid;                     // /proc/<tid>/status Uid: field.
+    unsigned time;                 // sum of /proc/<tid>/stat field 14 utime &
+                                   // 15 stime for coarse ABA problem detection.
+    std::string cmdline;           // cached /cmdline content
+    char state;                    // /proc/<tid>/stat field 3: Z or D
+                                   // (others we do not monitor: S, R, T or ?)
+    char comm[TASK_COMM_LEN + 3];  // space for adding '[' and ']'
+    bool exeMissingValid;          // exeMissing has been cached
+    bool cmdlineValid;             // cmdline has been cached
+    bool updated;                  // cleared before monitoring pass.
+    bool killed;                   // sent a kill to this thread, next panic...
+
+    void setComm(const char* _comm) { strncpy(comm + 1, _comm, sizeof(comm) - 2); }
+
+    proc(pid_t tid, pid_t pid, pid_t ppid, const char* _comm, int time, char state)
+        : tid(tid),
+          schedUpdate(0),
+          nrSwitches(0),
+          update(llkUpdate),
+          count(0),
+          pid(pid),
+          ppid(ppid),
+          uid(-1),
+          time(time),
+          state(state),
+          exeMissingValid(false),
+          cmdlineValid(false),
+          updated(true),
+          killed(!llkTestWithKill) {
+        memset(comm, '\0', sizeof(comm));
+        setComm(_comm);
+    }
+
+    const char* getComm(void) {
+        if (comm[1] == '\0') {  // comm Valid?
+            strncpy(comm + 1, llkProcGetName(tid, "/comm").c_str(), sizeof(comm) - 2);
+        }
+        if (!exeMissingValid) {
+            if (llkIsMissingExeLink(tid)) {
+                comm[0] = '[';
+            }
+            exeMissingValid = true;
+        }
+        size_t len = strlen(comm + 1);
+        if (__predict_true(len < (sizeof(comm) - 1))) {
+            if (comm[0] == '[') {
+                if ((comm[len] != ']') && __predict_true(len < (sizeof(comm) - 2))) {
+                    comm[++len] = ']';
+                    comm[++len] = '\0';
+                }
+            } else {
+                if (comm[len] == ']') {
+                    comm[len] = '\0';
+                }
+            }
+        }
+        return &comm[comm[0] != '['];
+    }
+
+    const char* getCmdline(void) {
+        if (!cmdlineValid) {
+            cmdline = llkProcGetName(tid);
+            cmdlineValid = true;
+        }
+        return cmdline.c_str();
+    }
+
+    uid_t getUid(void) {
+        if (uid <= 0) {  // Churn on root user, because most likely to setuid()
+            uid = llkProcGetUid(tid);
+        }
+        return uid;
+    }
+
+    void reset(void) {  // reset cache, if we detected pid rollover
+        uid = -1;
+        state = '?';
+        cmdline = "";
+        comm[0] = '\0';
+        exeMissingValid = false;
+        cmdlineValid = false;
+    }
+};
+
+std::unordered_map<pid_t, proc> tids;
+
+// Check range and setup defaults, in order of propagation:
+//     llkTimeoutMs
+//     llkCheckMs
+//     ...
+// KISS to keep it all self-contained, and called multiple times as parameters
+// are interpreted so that defaults, llkCheckMs and llkCycle make sense.
+void llkValidate() {
+    if (llkTimeoutMs == 0ms) {
+        llkTimeoutMs = LLK_TIMEOUT_MS_DEFAULT;
+    }
+    llkTimeoutMs = std::max(llkTimeoutMs, LLK_TIMEOUT_MS_MINIMUM);
+    if (llkCheckMs == 0ms) {
+        llkCheckMs = llkTimeoutMs / LLK_CHECKS_PER_TIMEOUT_DEFAULT;
+    }
+    llkCheckMs = std::min(llkCheckMs, llkTimeoutMs);
+
+    for (size_t state = 0; state < ARRAY_SIZE(llkStateTimeoutMs); ++state) {
+        if (llkStateTimeoutMs[state] == 0ms) {
+            llkStateTimeoutMs[state] = llkTimeoutMs;
+        }
+        llkStateTimeoutMs[state] =
+            std::min(std::max(llkStateTimeoutMs[state], LLK_TIMEOUT_MS_MINIMUM), llkTimeoutMs);
+        llkCheckMs = std::min(llkCheckMs, llkStateTimeoutMs[state]);
+    }
+
+    llkCheckMs = std::max(llkCheckMs, LLK_CHECK_MS_MINIMUM);
+    if (llkCycle == 0ms) {
+        llkCycle = llkCheckMs;
+    }
+    llkCycle = std::min(llkCycle, llkCheckMs);
+}
+
+milliseconds llkGetTimespecDiffMs(timespec* from, timespec* to) {
+    return duration_cast<milliseconds>(seconds(to->tv_sec - from->tv_sec)) +
+           duration_cast<milliseconds>(nanoseconds(to->tv_nsec - from->tv_nsec));
+}
+
+std::string llkProcGetName(pid_t tid, const char* comm, const char* cmdline) {
+    if ((cmdline != nullptr) && (*cmdline != '\0')) {
+        return cmdline;
+    }
+    if ((comm != nullptr) && (*comm != '\0')) {
+        return comm;
+    }
+
+    // UNLIKELY! Here because killed before we kill it?
+    // Assume change is afoot, do not call llkTidAlloc
+
+    // cmdline ?
+    std::string content = llkProcGetName(tid);
+    if (content.size() != 0) {
+        return content;
+    }
+    // Comm instead?
+    content = llkProcGetName(tid, "/comm");
+    if (llkIsMissingExeLink(tid) && (content.size() != 0)) {
+        return '[' + content + ']';
+    }
+    return content;
+}
+
+int llkKillOneProcess(pid_t pid, char state, pid_t tid, const char* tcomm = nullptr,
+                      const char* tcmdline = nullptr, const char* pcomm = nullptr,
+                      const char* pcmdline = nullptr) {
+    std::string forTid;
+    if (tid != pid) {
+        forTid = " for '" + llkProcGetName(tid, tcomm, tcmdline) + "' (" + std::to_string(tid) + ")";
+    }
+    LOG(INFO) << "Killing '" << llkProcGetName(pid, pcomm, pcmdline) << "' (" << pid
+              << ") to check forward scheduling progress in " << state << " state" << forTid;
+    // CAP_KILL required
+    errno = 0;
+    auto r = ::kill(pid, SIGKILL);
+    if (r) {
+        PLOG(ERROR) << "kill(" << pid << ")=" << r << ' ';
+    }
+
+    return r;
+}
+
+// Kill one process
+int llkKillOneProcess(pid_t pid, proc* tprocp) {
+    return llkKillOneProcess(pid, tprocp->state, tprocp->tid, tprocp->getComm(),
+                             tprocp->getCmdline());
+}
+
+// Kill one process specified by kprocp
+int llkKillOneProcess(proc* kprocp, proc* tprocp) {
+    if (kprocp == nullptr) {
+        return -2;
+    }
+
+    return llkKillOneProcess(kprocp->tid, tprocp->state, tprocp->tid, tprocp->getComm(),
+                             tprocp->getCmdline(), kprocp->getComm(), kprocp->getCmdline());
+}
+
+// Acquire file descriptor from environment, or open and cache it.
+// NB: cache is unnecessary in our current context, pedantically
+//     required to prevent leakage of file descriptors in the future.
+int llkFileToWriteFd(const std::string& file) {
+    static std::unordered_map<std::string, int> cache;
+    auto search = cache.find(file);
+    if (search != cache.end()) return search->second;
+    auto fd = android_get_control_file(file.c_str());
+    if (fd >= 0) return fd;
+    fd = TEMP_FAILURE_RETRY(::open(file.c_str(), O_WRONLY | O_CLOEXEC));
+    if (fd >= 0) cache.emplace(std::make_pair(file, fd));
+    return fd;
+}
+
+// Wrap android::base::WriteStringToFile to use android_get_control_file.
+bool llkWriteStringToFile(const std::string& string, const std::string& file) {
+    auto fd = llkFileToWriteFd(file);
+    if (fd < 0) return false;
+    return android::base::WriteStringToFd(string, fd);
+}
+
+bool llkWriteStringToFileConfirm(const std::string& string, const std::string& file) {
+    auto fd = llkFileToWriteFd(file);
+    auto ret = (fd < 0) ? false : android::base::WriteStringToFd(string, fd);
+    std::string content;
+    if (!android::base::ReadFileToString(file, &content)) return ret;
+    return android::base::Trim(content) == string;
+}
+
+void llkPanicKernel(bool dump, pid_t tid, const char* state) __noreturn;
+void llkPanicKernel(bool dump, pid_t tid, const char* state) {
+    auto sysrqTriggerFd = llkFileToWriteFd("/proc/sysrq-trigger");
+    if (sysrqTriggerFd < 0) {
+        // DYB
+        llkKillOneProcess(initPid, 'R', tid);
+        // The answer to life, the universe and everything
+        ::exit(42);
+        // NOTREACHED
+    }
+    ::sync();
+    if (dump) {
+        // Show all locks that are held
+        android::base::WriteStringToFd("d", sysrqTriggerFd);
+        // This can trigger hardware watchdog, that is somewhat _ok_.
+        // But useless if pstore configured for <256KB, low ram devices ...
+        if (!llkLowRam) {
+            android::base::WriteStringToFd("t", sysrqTriggerFd);
+        }
+        ::usleep(200000);  // let everything settle
+    }
+    llkWriteStringToFile(std::string("SysRq : Trigger a crash : 'livelock,") + state + "'\n",
+                         "/dev/kmsg");
+    android::base::WriteStringToFd("c", sysrqTriggerFd);
+    // NOTREACHED
+    // DYB
+    llkKillOneProcess(initPid, 'R', tid);
+    // I sat at my desk, stared into the garden and thought '42 will do'.
+    // I typed it out. End of story
+    ::exit(42);
+    // NOTREACHED
+}
+
+void llkAlarmHandler(int) {
+    llkPanicKernel(false, ::getpid(), "alarm");
+}
+
+milliseconds GetUintProperty(const std::string& key, milliseconds def) {
+    return milliseconds(android::base::GetUintProperty(key, static_cast<uint64_t>(def.count()),
+                                                       static_cast<uint64_t>(def.max().count())));
+}
+
+seconds GetUintProperty(const std::string& key, seconds def) {
+    return seconds(android::base::GetUintProperty(key, static_cast<uint64_t>(def.count()),
+                                                  static_cast<uint64_t>(def.max().count())));
+}
+
+proc* llkTidLookup(pid_t tid) {
+    auto search = tids.find(tid);
+    if (search == tids.end()) {
+        return nullptr;
+    }
+    return &search->second;
+}
+
+void llkTidRemove(pid_t tid) {
+    tids.erase(tid);
+}
+
+proc* llkTidAlloc(pid_t tid, pid_t pid, pid_t ppid, const char* comm, int time, char state) {
+    auto it = tids.emplace(std::make_pair(tid, proc(tid, pid, ppid, comm, time, state)));
+    return &it.first->second;
+}
+
+std::string llkFormat(milliseconds ms) {
+    auto sec = duration_cast<seconds>(ms);
+    std::ostringstream s;
+    s << sec.count() << '.';
+    auto f = s.fill('0');
+    auto w = s.width(3);
+    s << std::right << (ms - sec).count();
+    s.width(w);
+    s.fill(f);
+    s << 's';
+    return s.str();
+}
+
+std::string llkFormat(seconds s) {
+    return std::to_string(s.count()) + 's';
+}
+
+std::string llkFormat(bool flag) {
+    return flag ? "true" : "false";
+}
+
+std::string llkFormat(const std::unordered_set<std::string>& blacklist) {
+    std::string ret;
+    for (auto entry : blacklist) {
+        if (ret.size()) {
+            ret += ",";
+        }
+        ret += entry;
+    }
+    return ret;
+}
+
+// We only officially support comma separators, but wetware being what they
+// are will take some liberty and I do not believe they should be punished.
+std::unordered_set<std::string> llkSplit(const std::string& s,
+                                         const std::string& delimiters = ", \t:") {
+    std::unordered_set<std::string> result;
+
+    size_t base = 0;
+    size_t found;
+    while (true) {
+        found = s.find_first_of(delimiters, base);
+        result.emplace(s.substr(base, found - base));
+        if (found == s.npos) break;
+        base = found + 1;
+    }
+    return result;
+}
+
+bool llkSkipName(const std::string& name,
+                 const std::unordered_set<std::string>& blacklist = llkBlacklistProcess) {
+    if ((name.size() == 0) || (blacklist.size() == 0)) {
+        return false;
+    }
+
+    return blacklist.find(name) != blacklist.end();
+}
+
+bool llkSkipPid(pid_t pid) {
+    return llkSkipName(std::to_string(pid), llkBlacklistProcess);
+}
+
+bool llkSkipPpid(pid_t ppid) {
+    return llkSkipName(std::to_string(ppid), llkBlacklistParent);
+}
+
+bool llkSkipUid(uid_t uid) {
+    // Match by number?
+    if (llkSkipName(std::to_string(uid), llkBlacklistUid)) {
+        return true;
+    }
+
+    // Match by name?
+    auto pwd = ::getpwuid(uid);
+    return (pwd != nullptr) && __predict_true(pwd->pw_name != nullptr) &&
+           __predict_true(pwd->pw_name[0] != '\0') && llkSkipName(pwd->pw_name, llkBlacklistUid);
+}
+
+bool getValidTidDir(dirent* dp, std::string* piddir) {
+    if (!::isdigit(dp->d_name[0])) {
+        return false;
+    }
+
+    // Corner case can not happen in reality b/c of above ::isdigit check
+    if (__predict_false(dp->d_type != DT_DIR)) {
+        if (__predict_false(dp->d_type == DT_UNKNOWN)) {  // can't b/c procfs
+            struct stat st;
+            *piddir = procdir;
+            *piddir += dp->d_name;
+            return (lstat(piddir->c_str(), &st) == 0) && (st.st_mode & S_IFDIR);
+        }
+        return false;
+    }
+
+    *piddir = procdir;
+    *piddir += dp->d_name;
+    return true;
+}
+
+bool llkIsMonitorState(char state) {
+    return (state == 'Z') || (state == 'D');
+}
+
+// returns -1 if not found
+long long getSchedValue(const std::string& schedString, const char* key) {
+    auto pos = schedString.find(key);
+    if (pos == std::string::npos) {
+        return -1;
+    }
+    pos = schedString.find(':', pos);
+    if (__predict_false(pos == std::string::npos)) {
+        return -1;
+    }
+    while ((++pos < schedString.size()) && ::isblank(schedString[pos])) {
+        ;
+    }
+    long long ret;
+    if (!android::base::ParseInt(schedString.substr(pos), &ret, static_cast<long long>(0))) {
+        return -1;
+    }
+    return ret;
+}
+
+// Primary ABA mitigation watching last time schedule activity happened
+void llkCheckSchedUpdate(proc* procp, const std::string& piddir) {
+    // Audit finds /proc/<tid>/sched is just over 1K, and
+    // is rarely larger than 2K, even less on Android.
+    // For example, the "se.avg.lastUpdateTime" field we are
+    // interested in typically within the primary set in
+    // the first 1K.
+    //
+    // Proc entries can not be read >1K atomically via libbase,
+    // but if there are problems we assume at least a few
+    // samples of reads occur before we take any real action.
+    std::string schedString = ReadFile(piddir + "/sched");
+    if (schedString.size() == 0) {
+        // /schedstat is not as standardized, but in 3.1+
+        // Android devices, the third field is nr_switches
+        // from /sched:
+        schedString = ReadFile(piddir + "/schedstat");
+        if (schedString.size() == 0) {
+            return;
+        }
+        auto val = static_cast<unsigned long long>(-1);
+        if (((::sscanf(schedString.c_str(), "%*d %*d %llu", &val)) == 1) &&
+            (val != static_cast<unsigned long long>(-1)) && (val != 0) &&
+            (val != procp->nrSwitches)) {
+            procp->nrSwitches = val;
+            procp->count = 0ms;
+            procp->killed = !llkTestWithKill;
+        }
+        return;
+    }
+
+    auto val = getSchedValue(schedString, "\nse.avg.lastUpdateTime");
+    if (val == -1) {
+        val = getSchedValue(schedString, "\nse.svg.last_update_time");
+    }
+    if (val != -1) {
+        auto schedUpdate = nanoseconds(val);
+        if (schedUpdate != procp->schedUpdate) {
+            procp->schedUpdate = schedUpdate;
+            procp->count = 0ms;
+            procp->killed = !llkTestWithKill;
+        }
+    }
+
+    val = getSchedValue(schedString, "\nnr_switches");
+    if (val != -1) {
+        if (static_cast<uint64_t>(val) != procp->nrSwitches) {
+            procp->nrSwitches = val;
+            procp->count = 0ms;
+            procp->killed = !llkTestWithKill;
+        }
+    }
+}
+
+void llkLogConfig(void) {
+    LOG(INFO) << "ro.config.low_ram=" << llkFormat(llkLowRam) << "\n"
+              << LLK_ENABLE_PROPERTY "=" << llkFormat(llkEnable) << "\n"
+              << KHT_ENABLE_PROPERTY "=" << llkFormat(khtEnable) << "\n"
+              << LLK_MLOCKALL_PROPERTY "=" << llkFormat(llkMlockall) << "\n"
+              << LLK_KILLTEST_PROPERTY "=" << llkFormat(llkTestWithKill) << "\n"
+              << KHT_TIMEOUT_PROPERTY "=" << llkFormat(khtTimeout) << "\n"
+              << LLK_TIMEOUT_MS_PROPERTY "=" << llkFormat(llkTimeoutMs) << "\n"
+              << LLK_D_TIMEOUT_MS_PROPERTY "=" << llkFormat(llkStateTimeoutMs[llkStateD]) << "\n"
+              << LLK_Z_TIMEOUT_MS_PROPERTY "=" << llkFormat(llkStateTimeoutMs[llkStateZ]) << "\n"
+              << LLK_CHECK_MS_PROPERTY "=" << llkFormat(llkCheckMs) << "\n"
+              << LLK_BLACKLIST_PROCESS_PROPERTY "=" << llkFormat(llkBlacklistProcess) << "\n"
+              << LLK_BLACKLIST_PARENT_PROPERTY "=" << llkFormat(llkBlacklistParent) << "\n"
+              << LLK_BLACKLIST_UID_PROPERTY "=" << llkFormat(llkBlacklistUid);
+}
+
+void* llkThread(void* obj) {
+    LOG(INFO) << "started";
+
+    std::string name = std::to_string(::gettid());
+    if (!llkSkipName(name)) {
+        llkBlacklistProcess.emplace(name);
+    }
+    name = static_cast<const char*>(obj);
+    prctl(PR_SET_NAME, name.c_str());
+    if (__predict_false(!llkSkipName(name))) {
+        llkBlacklistProcess.insert(name);
+    }
+    // No longer modifying llkBlacklistProcess.
+    llkRunning = true;
+    llkLogConfig();
+    while (llkRunning) {
+        ::usleep(duration_cast<microseconds>(llkCheck(true)).count());
+    }
+    // NOTREACHED
+    LOG(INFO) << "exiting";
+    return nullptr;
+}
+
+}  // namespace
+
+milliseconds llkCheck(bool checkRunning) {
+    if (!llkEnable || (checkRunning != llkRunning)) {
+        return milliseconds::max();
+    }
+
+    // Reset internal watchdog, which is a healthy engineering margin of
+    // double the maximum wait or cycle time for the mainloop that calls us.
+    //
+    // This alarm is effectively the live lock detection of llkd, as
+    // we understandably can not monitor ourselves otherwise.
+    ::alarm(duration_cast<seconds>(llkTimeoutMs * 2).count());
+
+    // kernel jiffy precision fastest acquisition
+    static timespec last;
+    timespec now;
+    ::clock_gettime(CLOCK_MONOTONIC_COARSE, &now);
+    auto ms = llkGetTimespecDiffMs(&last, &now);
+    if (ms < llkCycle) {
+        return llkCycle - ms;
+    }
+    last = now;
+
+    LOG(VERBOSE) << "opendir(\"" << procdir << "\")";
+    if (__predict_false(!llkTopDirectory)) {
+        // gid containing AID_READPROC required
+        llkTopDirectory.reset(procdir);
+        if (__predict_false(!llkTopDirectory)) {
+            // Most likely reason we could be here is a resource limit.
+            // Keep our processing down to a minimum, but not so low that
+            // we do not recover in a timely manner should the issue be
+            // transitory.
+            LOG(DEBUG) << "opendir(\"" << procdir << "\") failed";
+            return llkTimeoutMs;
+        }
+    }
+
+    for (auto& it : tids) {
+        it.second.updated = false;
+    }
+
+    auto prevUpdate = llkUpdate;
+    llkUpdate += ms;
+    ms -= llkCycle;
+    auto myPid = ::getpid();
+    auto myTid = ::gettid();
+    for (auto dp = llkTopDirectory.read(); dp != nullptr; dp = llkTopDirectory.read()) {
+        std::string piddir;
+
+        if (!getValidTidDir(dp, &piddir)) {
+            continue;
+        }
+
+        // Get the process tasks
+        std::string taskdir = piddir + "/task/";
+        int pid = -1;
+        LOG(VERBOSE) << "+opendir(\"" << taskdir << "\")";
+        dir taskDirectory(taskdir);
+        if (__predict_false(!taskDirectory)) {
+            LOG(DEBUG) << "+opendir(\"" << taskdir << "\") failed";
+        }
+        for (auto tp = taskDirectory.read(dir::task, dp); tp != nullptr;
+             tp = taskDirectory.read(dir::task)) {
+            if (!getValidTidDir(tp, &piddir)) {
+                continue;
+            }
+
+            // Get the process stat
+            std::string stat = ReadFile(piddir + "/stat");
+            if (stat.size() == 0) {
+                continue;
+            }
+            unsigned tid = -1;
+            char pdir[TASK_COMM_LEN + 1];
+            char state = '?';
+            unsigned ppid = -1;
+            unsigned utime = -1;
+            unsigned stime = -1;
+            int dummy;
+            pdir[0] = '\0';
+            // tid should not change value
+            auto match = ::sscanf(
+                stat.c_str(),
+                "%u (%" ___STRING(
+                    TASK_COMM_LEN) "[^)]) %c %u %*d %*d %*d %*d %*d %*d %*d %*d %*d %u %u %d",
+                &tid, pdir, &state, &ppid, &utime, &stime, &dummy);
+            if (pid == -1) {
+                pid = tid;
+            }
+            LOG(VERBOSE) << "match " << match << ' ' << tid << " (" << pdir << ") " << state << ' '
+                         << ppid << " ... " << utime << ' ' << stime << ' ' << dummy;
+            if (match != 7) {
+                continue;
+            }
+
+            auto procp = llkTidLookup(tid);
+            if (procp == nullptr) {
+                procp = llkTidAlloc(tid, pid, ppid, pdir, utime + stime, state);
+            } else {
+                // comm can change ...
+                procp->setComm(pdir);
+                procp->updated = true;
+                // pid/ppid/tid wrap?
+                if (((procp->update != prevUpdate) && (procp->update != llkUpdate)) ||
+                    (procp->ppid != ppid) || (procp->pid != pid)) {
+                    procp->reset();
+                } else if (procp->time != (utime + stime)) {  // secondary ABA.
+                    // watching utime+stime granularity jiffy
+                    procp->state = '?';
+                }
+                procp->update = llkUpdate;
+                procp->pid = pid;
+                procp->ppid = ppid;
+                procp->time = utime + stime;
+                if (procp->state != state) {
+                    procp->count = 0ms;
+                    procp->killed = !llkTestWithKill;
+                    procp->state = state;
+                } else {
+                    procp->count += llkCycle;
+                }
+            }
+
+            // Filter checks in intuitive order of CPU cost to evaluate
+            // If tid unique continue, if ppid or pid unique break
+
+            if (pid == myPid) {
+                break;
+            }
+            if (!llkIsMonitorState(state)) {
+                continue;
+            }
+            if ((tid == myTid) || llkSkipPid(tid)) {
+                continue;
+            }
+            if (llkSkipPpid(ppid)) {
+                break;
+            }
+
+            if (llkSkipName(procp->getComm())) {
+                continue;
+            }
+            if (llkSkipName(procp->getCmdline())) {
+                break;
+            }
+
+            auto pprocp = llkTidLookup(ppid);
+            if (pprocp == nullptr) {
+                pprocp = llkTidAlloc(ppid, ppid, 0, "", 0, '?');
+            }
+            if ((pprocp != nullptr) && (llkSkipName(pprocp->getComm(), llkBlacklistParent) ||
+                                        llkSkipName(pprocp->getCmdline(), llkBlacklistParent))) {
+                break;
+            }
+
+            if ((llkBlacklistUid.size() != 0) && llkSkipUid(procp->getUid())) {
+                continue;
+            }
+
+            // ABA mitigation watching last time schedule activity happened
+            llkCheckSchedUpdate(procp, piddir);
+
+            // Can only fall through to here if registered D or Z state !!!
+            if (procp->count < llkStateTimeoutMs[(state == 'Z') ? llkStateZ : llkStateD]) {
+                LOG(VERBOSE) << state << ' ' << llkFormat(procp->count) << ' ' << ppid << "->"
+                             << pid << "->" << tid << ' ' << procp->getComm();
+                continue;
+            }
+
+            // We have to kill it to determine difference between live lock
+            // and persistent state blocked on a resource.  Is there something
+            // wrong with a process that has no forward scheduling progress in
+            // Z or D?  Yes, generally means improper accounting in the
+            // process, but not always ...
+            //
+            // Whomever we hit with a test kill must accept the Android
+            // Aphorism that everything can be burned to the ground and
+            // must survive.
+            if (procp->killed == false) {
+                procp->killed = true;
+                // confirm: re-read uid before committing to a panic.
+                procp->uid = -1;
+                switch (state) {
+                    case 'Z':  // kill ppid to free up a Zombie
+                        // Killing init will kernel panic without diagnostics
+                        // so skip right to controlled kernel panic with
+                        // diagnostics.
+                        if (ppid == initPid) {
+                            break;
+                        }
+                        LOG(WARNING) << "Z " << llkFormat(procp->count) << ' ' << ppid << "->"
+                                     << pid << "->" << tid << ' ' << procp->getComm() << " [kill]";
+                        if ((llkKillOneProcess(pprocp, procp) >= 0) ||
+                            (llkKillOneProcess(ppid, procp) >= 0)) {
+                            continue;
+                        }
+                        break;
+
+                    case 'D':  // kill tid to free up an uninterruptible D
+                        // If ABA is doing its job, we would not need or
+                        // want the following.  Test kill is a Hail Mary
+                        // to make absolutely sure there is no forward
+                        // scheduling progress.  The cost when ABA is
+                        // not working is we kill a process that likes to
+                        // stay in 'D' state, instead of panicing the
+                        // kernel (worse).
+                        LOG(WARNING) << "D " << llkFormat(procp->count) << ' ' << pid << "->" << tid
+                                     << ' ' << procp->getComm() << " [kill]";
+                        if ((llkKillOneProcess(llkTidLookup(pid), procp) >= 0) ||
+                            (llkKillOneProcess(pid, 'D', tid) >= 0) ||
+                            (llkKillOneProcess(procp, procp) >= 0) ||
+                            (llkKillOneProcess(tid, 'D', tid) >= 0)) {
+                            continue;
+                        }
+                        break;
+                }
+            }
+            // We are here because we have confirmed kernel live-lock
+            LOG(ERROR) << state << ' ' << llkFormat(procp->count) << ' ' << ppid << "->" << pid
+                       << "->" << tid << ' ' << procp->getComm() << " [panic]";
+            llkPanicKernel(true, tid, (state == 'Z') ? "zombie" : "driver");
+        }
+        LOG(VERBOSE) << "+closedir()";
+    }
+    llkTopDirectory.rewind();
+    LOG(VERBOSE) << "closedir()";
+
+    // garbage collection of old process references
+    for (auto p = tids.begin(); p != tids.end();) {
+        if (!p->second.updated) {
+            IF_ALOG(LOG_VERBOSE, LOG_TAG) {
+                std::string ppidCmdline = llkProcGetName(p->second.ppid, nullptr, nullptr);
+                if (ppidCmdline.size()) {
+                    ppidCmdline = "(" + ppidCmdline + ")";
+                }
+                std::string pidCmdline;
+                if (p->second.pid != p->second.tid) {
+                    pidCmdline = llkProcGetName(p->second.pid, nullptr, p->second.getCmdline());
+                    if (pidCmdline.size()) {
+                        pidCmdline = "(" + pidCmdline + ")";
+                    }
+                }
+                std::string tidCmdline =
+                    llkProcGetName(p->second.tid, p->second.getComm(), p->second.getCmdline());
+                if (tidCmdline.size()) {
+                    tidCmdline = "(" + tidCmdline + ")";
+                }
+                LOG(VERBOSE) << "thread " << p->second.ppid << ppidCmdline << "->" << p->second.pid
+                             << pidCmdline << "->" << p->second.tid << tidCmdline << " removed";
+            }
+            p = tids.erase(p);
+        } else {
+            ++p;
+        }
+    }
+    if (__predict_false(tids.empty())) {
+        llkTopDirectory.reset();
+    }
+
+    llkCycle = llkCheckMs;
+
+    timespec end;
+    ::clock_gettime(CLOCK_MONOTONIC_COARSE, &end);
+    auto milli = llkGetTimespecDiffMs(&now, &end);
+    LOG((milli > 10s) ? ERROR : (milli > 1s) ? WARNING : VERBOSE) << "sample " << llkFormat(milli);
+
+    // cap to minimum sleep for 1 second since last cycle
+    if (llkCycle < (ms + 1s)) {
+        return 1s;
+    }
+    return llkCycle - ms;
+}
+
+unsigned llkCheckMilliseconds() {
+    return duration_cast<milliseconds>(llkCheck()).count();
+}
+
+bool llkInit(const char* threadname) {
+    llkLowRam = android::base::GetBoolProperty("ro.config.low_ram", false);
+    if (!LLK_ENABLE_DEFAULT && android::base::GetBoolProperty("ro.debuggable", false)) {
+        llkEnable = android::base::GetProperty(LLK_ENABLE_PROPERTY, "eng") == "eng";
+        khtEnable = android::base::GetProperty(KHT_ENABLE_PROPERTY, "eng") == "eng";
+    }
+    llkEnable = android::base::GetBoolProperty(LLK_ENABLE_PROPERTY, llkEnable);
+    if (llkEnable && !llkTopDirectory.reset(procdir)) {
+        // Most likely reason we could be here is llkd was started
+        // incorrectly without the readproc permissions.  Keep our
+        // processing down to a minimum.
+        llkEnable = false;
+    }
+    khtEnable = android::base::GetBoolProperty(KHT_ENABLE_PROPERTY, khtEnable);
+    llkMlockall = android::base::GetBoolProperty(LLK_MLOCKALL_PROPERTY, llkMlockall);
+    llkTestWithKill = android::base::GetBoolProperty(LLK_KILLTEST_PROPERTY, llkTestWithKill);
+    // if LLK_TIMOUT_MS_PROPERTY was not set, we will use a set
+    // KHT_TIMEOUT_PROPERTY as co-operative guidance for the default value.
+    khtTimeout = GetUintProperty(KHT_TIMEOUT_PROPERTY, khtTimeout);
+    if (khtTimeout == 0s) {
+        khtTimeout = duration_cast<seconds>(llkTimeoutMs * (1 + LLK_CHECKS_PER_TIMEOUT_DEFAULT) /
+                                            LLK_CHECKS_PER_TIMEOUT_DEFAULT);
+    }
+    llkTimeoutMs =
+        khtTimeout * LLK_CHECKS_PER_TIMEOUT_DEFAULT / (1 + LLK_CHECKS_PER_TIMEOUT_DEFAULT);
+    llkTimeoutMs = GetUintProperty(LLK_TIMEOUT_MS_PROPERTY, llkTimeoutMs);
+    llkValidate();  // validate llkTimeoutMs, llkCheckMs and llkCycle
+    llkStateTimeoutMs[llkStateD] = GetUintProperty(LLK_D_TIMEOUT_MS_PROPERTY, llkTimeoutMs);
+    llkStateTimeoutMs[llkStateZ] = GetUintProperty(LLK_Z_TIMEOUT_MS_PROPERTY, llkTimeoutMs);
+    llkCheckMs = GetUintProperty(LLK_CHECK_MS_PROPERTY, llkCheckMs);
+    llkValidate();  // validate all (effectively minus llkTimeoutMs)
+    std::string defaultBlacklistProcess(
+        std::to_string(kernelPid) + "," + std::to_string(initPid) + "," +
+        std::to_string(kthreaddPid) + "," + std::to_string(::getpid()) + "," +
+        std::to_string(::gettid()) + "," LLK_BLACKLIST_PROCESS_DEFAULT);
+    if (threadname) {
+        defaultBlacklistProcess += std::string(",") + threadname;
+    }
+    for (int cpu = 1; cpu < get_nprocs_conf(); ++cpu) {
+        defaultBlacklistProcess += ",[watchdog/" + std::to_string(cpu) + "]";
+    }
+    defaultBlacklistProcess =
+        android::base::GetProperty(LLK_BLACKLIST_PROCESS_PROPERTY, defaultBlacklistProcess);
+    llkBlacklistProcess = llkSplit(defaultBlacklistProcess);
+    if (!llkSkipName("[khungtaskd]")) {  // ALWAYS ignore as special
+        llkBlacklistProcess.emplace("[khungtaskd]");
+    }
+    llkBlacklistParent = llkSplit(android::base::GetProperty(
+        LLK_BLACKLIST_PARENT_PROPERTY, std::to_string(kernelPid) + "," + std::to_string(kthreaddPid) +
+                                           "," LLK_BLACKLIST_PARENT_DEFAULT));
+    llkBlacklistUid =
+        llkSplit(android::base::GetProperty(LLK_BLACKLIST_UID_PROPERTY, LLK_BLACKLIST_UID_DEFAULT));
+
+    // internal watchdog
+    ::signal(SIGALRM, llkAlarmHandler);
+
+    // kernel hung task configuration? Otherwise leave it as-is
+    if (khtEnable) {
+        // EUID must be AID_ROOT to write to /proc/sys/kernel/ nodes, there
+        // are no capability overrides.  For security reasons we do not want
+        // to run as AID_ROOT.  We may not be able to write them successfully,
+        // we will try, but the least we can do is read the values back to
+        // confirm expectations and report whether configured or not.
+        auto configured = llkWriteStringToFileConfirm(std::to_string(khtTimeout.count()),
+                                                      "/proc/sys/kernel/hung_task_timeout_secs");
+        if (configured) {
+            llkWriteStringToFile("65535", "/proc/sys/kernel/hung_task_warnings");
+            llkWriteStringToFile("65535", "/proc/sys/kernel/hung_task_check_count");
+            configured = llkWriteStringToFileConfirm("1", "/proc/sys/kernel/hung_task_panic");
+        }
+        if (configured) {
+            LOG(INFO) << "[khungtaskd] configured";
+        } else {
+            LOG(WARNING) << "[khungtaskd] not configurable";
+        }
+    }
+
+    bool logConfig = true;
+    if (llkEnable) {
+        if (llkMlockall &&
+            // MCL_ONFAULT pins pages as they fault instead of loading
+            // everything immediately all at once. (Which would be bad,
+            // because as of this writing, we have a lot of mapped pages we
+            // never use.) Old kernels will see MCL_ONFAULT and fail with
+            // EINVAL; we ignore this failure.
+            //
+            // N.B. read the man page for mlockall. MCL_CURRENT | MCL_ONFAULT
+            // pins ⊆ MCL_CURRENT, converging to just MCL_CURRENT as we fault
+            // in pages.
+
+            // CAP_IPC_LOCK required
+            mlockall(MCL_CURRENT | MCL_FUTURE | MCL_ONFAULT) && (errno != EINVAL)) {
+            PLOG(WARNING) << "mlockall failed ";
+        }
+
+        if (threadname) {
+            pthread_attr_t attr;
+
+            if (!pthread_attr_init(&attr)) {
+                sched_param param;
+
+                memset(&param, 0, sizeof(param));
+                pthread_attr_setschedparam(&attr, &param);
+                pthread_attr_setschedpolicy(&attr, SCHED_BATCH);
+                if (!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) {
+                    pthread_t thread;
+                    if (!pthread_create(&thread, &attr, llkThread, const_cast<char*>(threadname))) {
+                        // wait a second for thread to start
+                        for (auto retry = 50; retry && !llkRunning; --retry) {
+                            ::usleep(20000);
+                        }
+                        logConfig = !llkRunning;  // printed in llkd context?
+                    } else {
+                        LOG(ERROR) << "failed to spawn llkd thread";
+                    }
+                } else {
+                    LOG(ERROR) << "failed to detach llkd thread";
+                }
+                pthread_attr_destroy(&attr);
+            } else {
+                LOG(ERROR) << "failed to allocate attibutes for llkd thread";
+            }
+        }
+    } else {
+        LOG(DEBUG) << "[khungtaskd] left unconfigured";
+    }
+    if (logConfig) {
+        llkLogConfig();
+    }
+
+    return llkEnable;
+}
diff --git a/llkd/llkd.cpp b/llkd/llkd.cpp
new file mode 100644
index 0000000..f10253d
--- /dev/null
+++ b/llkd/llkd.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "llkd.h"
+
+#include <sched.h>
+#include <unistd.h>
+
+#include <chrono>
+
+#include <android-base/logging.h>
+
+using namespace std::chrono;
+
+int main(int, char**) {
+    LOG(INFO) << "started";
+
+    bool enabled = llkInit();
+
+    // Would like this policy to be automatic as part of libllkd,
+    // but that would be presumptuous and bad side-effect.
+    struct sched_param param;
+    memset(&param, 0, sizeof(param));
+    sched_setscheduler(0, SCHED_BATCH, &param);
+
+    while (true) {
+        if (enabled) {
+            ::usleep(duration_cast<microseconds>(llkCheck()).count());
+        } else {
+            ::pause();
+        }
+    }
+    // NOTREACHED
+
+    LOG(INFO) << "exiting";
+    return 0;
+}
diff --git a/llkd/llkd.rc b/llkd/llkd.rc
new file mode 100644
index 0000000..e538cdb
--- /dev/null
+++ b/llkd/llkd.rc
@@ -0,0 +1,49 @@
+# eng default for ro.llk.enable and ro.khungtask.enable
+on property:ro.debuggable=*
+    setprop llk.enable ${ro.llk.enable:-0}
+    setprop khungtask.enable ${ro.khungtask.enable:-0}
+
+on property:ro.debuggable=1
+    setprop llk.enable ${ro.llk.enable:-1}
+    setprop khungtask.enable ${ro.khungtask.enable:-1}
+
+on property:ro.llk.enable=eng
+    setprop llk.enable ${ro.debuggable:-0}
+
+on property:ro.khungtask.enable=eng
+    setprop khungtask.enable ${ro.debuggable:-0}
+
+on property:llk.enable=1
+    setprop llk.enable true
+
+on property:llk.enable=0
+    setprop llk.enable false
+
+on property:khungtask.enable=1
+    setprop khungtask.enable true
+
+on property:khungtask.enable=0
+    setprop khungtask.enable false
+
+# Configure [khungtaskd]
+on property:khungtask.enable=true
+    write /proc/sys/kernel/hung_task_timeout_secs ${ro.khungtask.timeout:-720}
+    write /proc/sys/kernel/hung_task_warnings 65535
+    write /proc/sys/kernel/hung_task_check_count 65535
+    write /proc/sys/kernel/hung_task_panic 1
+
+on property:khungtask.enable=false
+    write /proc/sys/kernel/hung_task_panic 0
+
+on property:llk.enable=true
+    start llkd
+
+service llkd /system/bin/llkd
+    class late_start
+    disabled
+    user llkd
+    group llkd readproc
+    capabilities KILL IPC_LOCK
+    file /dev/kmsg w
+    file /proc/sysrq-trigger w
+    writepid /dev/cpuset/system-background/tasks
diff --git a/llkd/tests/Android.bp b/llkd/tests/Android.bp
new file mode 100644
index 0000000..6dd5938
--- /dev/null
+++ b/llkd/tests/Android.bp
@@ -0,0 +1,41 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_test {
+    name: "llkd_unit_test",
+
+    shared_libs: [
+        "libbase",
+        "liblog",
+    ],
+    header_libs: [
+        "llkd_headers",
+    ],
+
+    target: {
+        android: {
+            srcs: [
+                "llkd_test.cpp",
+            ],
+        },
+    },
+
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+
+    compile_multilib: "first",
+}
diff --git a/llkd/tests/llkd_test.cpp b/llkd/tests/llkd_test.cpp
new file mode 100644
index 0000000..3a15ff1
--- /dev/null
+++ b/llkd/tests/llkd_test.cpp
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <signal.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <chrono>
+#include <iostream>
+#include <string>
+
+#include <android-base/properties.h>
+#include <gtest/gtest.h>
+#include <log/log_time.h>  // for MS_PER_SEC and US_PER_SEC
+
+#include "llkd.h"
+
+using namespace std::chrono;
+using namespace std::chrono_literals;
+
+namespace {
+
+milliseconds GetUintProperty(const std::string& key, milliseconds def) {
+    return milliseconds(android::base::GetUintProperty(key, static_cast<uint64_t>(def.count()),
+                                                       static_cast<uint64_t>(def.max().count())));
+}
+
+seconds GetUintProperty(const std::string& key, seconds def) {
+    return seconds(android::base::GetUintProperty(key, static_cast<uint64_t>(def.count()),
+                                                  static_cast<uint64_t>(def.max().count())));
+}
+
+// GTEST_LOG_(WARNING) output is fugly, this has much less noise
+// ToDo: look into fixing googletest to produce output that matches style of
+//       all the other status messages, and can switch off __line__ and
+//       __function__ noise
+#define GTEST_LOG_WARNING std::cerr << "[ WARNING  ] "
+#define GTEST_LOG_INFO std::cerr << "[   INFO   ] "
+
+// Properties is _not_ a high performance ABI!
+void rest() {
+    usleep(200000);
+}
+
+void execute(const char* command) {
+    if (getuid() || system(command)) {
+        system((std::string("su root ") + command).c_str());
+    }
+}
+
+seconds llkdSleepPeriod(char state) {
+    auto default_eng = android::base::GetProperty(LLK_ENABLE_PROPERTY, "eng") == "eng";
+    auto default_enable = LLK_ENABLE_DEFAULT;
+    if (!LLK_ENABLE_DEFAULT && default_eng &&
+        android::base::GetBoolProperty("ro.debuggable", false)) {
+        default_enable = true;
+    }
+    default_enable = android::base::GetBoolProperty(LLK_ENABLE_PROPERTY, default_enable);
+    if (default_eng) {
+        GTEST_LOG_INFO << LLK_ENABLE_PROPERTY " defaults to \"eng\" thus "
+                       << (default_enable ? "true" : "false") << "\n";
+    }
+    // Hail Mary hope is unconfigured.
+    if ((GetUintProperty(LLK_TIMEOUT_MS_PROPERTY, LLK_TIMEOUT_MS_DEFAULT) !=
+         duration_cast<milliseconds>(120s)) ||
+        (GetUintProperty(LLK_CHECK_MS_PROPERTY,
+                         LLK_TIMEOUT_MS_DEFAULT / LLK_CHECKS_PER_TIMEOUT_DEFAULT) !=
+         duration_cast<milliseconds>(10s))) {
+        execute("stop llkd");
+        rest();
+        std::string setprop("setprop ");
+        execute((setprop + LLK_ENABLE_WRITEABLE_PROPERTY + " false").c_str());
+        rest();
+        execute((setprop + LLK_TIMEOUT_MS_PROPERTY + " 120000").c_str());
+        rest();
+        execute((setprop + KHT_TIMEOUT_PROPERTY + " 130").c_str());
+        rest();
+        execute((setprop + LLK_CHECK_MS_PROPERTY + " 10000").c_str());
+        rest();
+        execute((setprop + LLK_ENABLE_PROPERTY + " true").c_str());
+        rest();
+        execute((setprop + LLK_ENABLE_WRITEABLE_PROPERTY + " true").c_str());
+        rest();
+    }
+    default_enable = LLK_ENABLE_DEFAULT;
+    if (!LLK_ENABLE_DEFAULT && (android::base::GetProperty(LLK_ENABLE_PROPERTY, "eng") == "eng") &&
+        android::base::GetBoolProperty("ro.debuggable", false)) {
+        default_enable = true;
+    }
+    default_enable = android::base::GetBoolProperty(LLK_ENABLE_PROPERTY, default_enable);
+    if (default_enable) {
+        execute("start llkd");
+        rest();
+        GTEST_LOG_INFO << "llkd enabled\n";
+    } else {
+        GTEST_LOG_WARNING << "llkd disabled\n";
+    }
+
+    /* KISS follows llk_init() */
+    milliseconds llkTimeoutMs = LLK_TIMEOUT_MS_DEFAULT;
+    seconds khtTimeout = duration_cast<seconds>(
+        llkTimeoutMs * (1 + LLK_CHECKS_PER_TIMEOUT_DEFAULT) / LLK_CHECKS_PER_TIMEOUT_DEFAULT);
+    khtTimeout = GetUintProperty(KHT_TIMEOUT_PROPERTY, khtTimeout);
+    llkTimeoutMs =
+        khtTimeout * LLK_CHECKS_PER_TIMEOUT_DEFAULT / (1 + LLK_CHECKS_PER_TIMEOUT_DEFAULT);
+    llkTimeoutMs = GetUintProperty(LLK_TIMEOUT_MS_PROPERTY, llkTimeoutMs);
+    if (llkTimeoutMs < LLK_TIMEOUT_MS_MINIMUM) {
+        llkTimeoutMs = LLK_TIMEOUT_MS_MINIMUM;
+    }
+    milliseconds llkCheckMs = llkTimeoutMs / LLK_CHECKS_PER_TIMEOUT_DEFAULT;
+    auto timeout = GetUintProperty(
+        (state == 'Z') ? LLK_Z_TIMEOUT_MS_PROPERTY : LLK_D_TIMEOUT_MS_PROPERTY, llkTimeoutMs);
+    if (timeout < LLK_TIMEOUT_MS_MINIMUM) {
+        timeout = LLK_TIMEOUT_MS_MINIMUM;
+    }
+
+    if (llkCheckMs > timeout) {
+        llkCheckMs = timeout;
+    }
+    llkCheckMs = GetUintProperty(LLK_CHECK_MS_PROPERTY, llkCheckMs);
+    timeout += llkCheckMs;
+    auto sec = duration_cast<seconds>(timeout);
+    if (sec == 0s) {
+        ++sec;
+    } else if (sec > 59s) {
+        GTEST_LOG_WARNING << "llkd is configured for about " << duration_cast<minutes>(sec).count()
+                          << " minutes to react\n";
+    }
+
+    // 33% margin for the test to naturally timeout waiting for llkd to respond
+    return (sec * 4 + 2s) / 3;
+}
+
+inline void waitForPid(pid_t child_pid) {
+    int wstatus;
+    ASSERT_LE(0, waitpid(child_pid, &wstatus, 0));
+    EXPECT_FALSE(WIFEXITED(wstatus)) << "[   INFO   ] exit=" << WEXITSTATUS(wstatus);
+    ASSERT_TRUE(WIFSIGNALED(wstatus));
+    ASSERT_EQ(WTERMSIG(wstatus), SIGKILL);
+}
+
+bool checkKill(const char* reason) {
+    if (android::base::GetBoolProperty(LLK_KILLTEST_PROPERTY, LLK_KILLTEST_DEFAULT)) {
+        return false;
+    }
+    auto bootreason = android::base::GetProperty("sys.boot.reason", "nothing");
+    if (bootreason == reason) {
+        GTEST_LOG_INFO << "Expected test result confirmed " << reason << "\n";
+        return true;
+    }
+    GTEST_LOG_WARNING << "Expected test result is " << reason << "\n";
+
+    // apct adjustment if needed (set LLK_KILLTEST_PROPERTY to "off" to allow test)
+    //
+    // if (android::base::GetProperty(LLK_KILLTEST_PROPERTY, "") == "false") {
+    //     GTEST_LOG_WARNING << "Bypassing test\n";
+    //     return true;
+    // }
+
+    return false;
+}
+
+}  // namespace
+
+// The tests that use this helper are to simulate processes stuck in 'D'
+// state that are experiencing forward scheduled progress. As such the
+// expectation is that llkd will _not_ perform any mitigations. The sleepfor
+// argument helps us set the amount of forward scheduler progress.
+static void llkd_driver_ABA(const microseconds sleepfor) {
+    const auto period = llkdSleepPeriod('D');
+    if (period <= sleepfor) {
+        GTEST_LOG_WARNING << "llkd configuration too short for "
+                          << duration_cast<milliseconds>(sleepfor).count() << "ms work cycle\n";
+        return;
+    }
+
+    auto child_pid = fork();
+    ASSERT_LE(0, child_pid);
+    int wstatus;
+    if (!child_pid) {
+        auto ratio = period / sleepfor;
+        ASSERT_LT(0, ratio);
+        // vfork() parent is uninterruptable D state waiting for child to exec()
+        while (--ratio > 0) {
+            auto driver_pid = vfork();
+            ASSERT_LE(0, driver_pid);
+            if (driver_pid) {  // parent
+                waitpid(driver_pid, &wstatus, 0);
+                if (!WIFEXITED(wstatus)) {
+                    exit(42);
+                }
+                if (WEXITSTATUS(wstatus) != 42) {
+                    exit(42);
+                }
+            } else {
+                usleep(sleepfor.count());
+                exit(42);
+            }
+        }
+        exit(0);
+    }
+    ASSERT_LE(0, waitpid(child_pid, &wstatus, 0));
+    EXPECT_TRUE(WIFEXITED(wstatus));
+    if (WIFEXITED(wstatus)) {
+        EXPECT_EQ(0, WEXITSTATUS(wstatus));
+    }
+    ASSERT_FALSE(WIFSIGNALED(wstatus)) << "[   INFO   ] signo=" << WTERMSIG(wstatus);
+}
+
+TEST(llkd, driver_ABA_fast) {
+    llkd_driver_ABA(5ms);
+}
+
+TEST(llkd, driver_ABA_slow) {
+    llkd_driver_ABA(1s);
+}
+
+TEST(llkd, driver_ABA_glacial) {
+    llkd_driver_ABA(1min);
+}
+
+// Following tests must be last in this file to capture possible errant
+// kernel_panic mitigation failure.
+
+// The following tests simulate processes stick in 'Z' or 'D' state with
+// no forward scheduling progress, but interruptible. As such the expectation
+// is that llkd will perform kill mitigation and not progress to kernel_panic.
+
+TEST(llkd, zombie) {
+    if (checkKill("kernel_panic,sysrq,livelock,zombie")) {
+        return;
+    }
+
+    const auto period = llkdSleepPeriod('Z');
+
+    /* Create a Persistent Zombie Process */
+    pid_t child_pid = fork();
+    ASSERT_LE(0, child_pid);
+    if (!child_pid) {
+        auto zombie_pid = fork();
+        ASSERT_LE(0, zombie_pid);
+        if (!zombie_pid) {
+            sleep(1);
+            exit(0);
+        }
+        sleep(period.count());
+        exit(42);
+    }
+
+    waitForPid(child_pid);
+}
+
+TEST(llkd, driver) {
+    if (checkKill("kernel_panic,sysrq,livelock,driver")) {
+        return;
+    }
+
+    const auto period = llkdSleepPeriod('D');
+
+    /* Create a Persistent Device Process */
+    auto child_pid = fork();
+    ASSERT_LE(0, child_pid);
+    if (!child_pid) {
+        // vfork() parent is uninterruptable D state waiting for child to exec()
+        auto driver_pid = vfork();
+        ASSERT_LE(0, driver_pid);
+        sleep(period.count());
+        exit(driver_pid ? 42 : 0);
+    }
+
+    waitForPid(child_pid);
+}
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 151e1dc..80711bc 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -68,6 +68,7 @@
 #define MEMINFO_PATH "/proc/meminfo"
 #define LINE_MAX 128
 
+/* gid containing AID_SYSTEM required */
 #define INKERNEL_MINFREE_PATH "/sys/module/lowmemorykiller/parameters/minfree"
 #define INKERNEL_ADJ_PATH "/sys/module/lowmemorykiller/parameters/adj"
 
@@ -455,6 +456,9 @@
         return;
     }
 
+    /* gid containing AID_READPROC required */
+    /* CAP_SYS_RESOURCE required */
+    /* CAP_DAC_OVERRIDE required */
     snprintf(path, sizeof(path), "/proc/%d/oom_score_adj", params.pid);
     snprintf(val, sizeof(val), "%d", params.oomadj);
     if (!writefilestring(path, val, false)) {
@@ -496,8 +500,7 @@
         soft_limit_mult = 64;
     }
 
-    snprintf(path, sizeof(path),
-             "/dev/memcg/apps/uid_%d/pid_%d/memory.soft_limit_in_bytes",
+    snprintf(path, sizeof(path), MEMCG_SYSFS_PATH "apps/uid_%d/pid_%d/memory.soft_limit_in_bytes",
              params.uid, params.pid);
     snprintf(val, sizeof(val), "%d", soft_limit_mult * EIGHT_MEGA);
 
@@ -859,6 +862,7 @@
     int total;
     ssize_t ret;
 
+    /* gid containing AID_READPROC required */
     snprintf(path, PATH_MAX, "/proc/%d/statm", pid);
     fd = open(path, O_RDONLY | O_CLOEXEC);
     if (fd == -1)
@@ -882,6 +886,7 @@
     char *cp;
     ssize_t ret;
 
+    /* gid containing AID_READPROC required */
     snprintf(path, PATH_MAX, "/proc/%d/cmdline", pid);
     fd = open(path, O_RDONLY | O_CLOEXEC);
     if (fd == -1)
@@ -949,6 +954,7 @@
 
     TRACE_KILL_START(pid);
 
+    /* CAP_KILL required */
     r = kill(pid, SIGKILL);
     ALOGI(
         "Killing '%s' (%d), uid %d, adj %d\n"
@@ -1267,6 +1273,7 @@
     int level_idx = (int)level;
     const char *levelstr = level_name[level_idx];
 
+    /* gid containing AID_SYSTEM required */
     mpfd = open(MEMCG_SYSFS_PATH "memory.pressure_level", O_RDONLY | O_CLOEXEC);
     if (mpfd < 0) {
         ALOGI("No kernel memory.pressure_level support (errno=%d)", errno);
@@ -1478,11 +1485,15 @@
              * pins ⊆ MCL_CURRENT, converging to just MCL_CURRENT as we fault
              * in pages.
              */
+            /* CAP_IPC_LOCK required */
             if (mlockall(MCL_CURRENT | MCL_FUTURE | MCL_ONFAULT) && (errno != EINVAL)) {
                 ALOGW("mlockall failed %s", strerror(errno));
             }
 
-            sched_setscheduler(0, SCHED_FIFO, &param);
+            /* CAP_NICE required */
+            if (sched_setscheduler(0, SCHED_FIFO, &param)) {
+                ALOGW("set SCHED_FIFO failed %s", strerror(errno));
+            }
         }
 
         mainloop();
diff --git a/lmkd/lmkd.rc b/lmkd/lmkd.rc
index 3bb84ab..76b6055 100644
--- a/lmkd/lmkd.rc
+++ b/lmkd/lmkd.rc
@@ -1,6 +1,8 @@
 service lmkd /system/bin/lmkd
     class core
-    group root readproc
+    user lmkd
+    group lmkd system readproc
+    capabilities DAC_OVERRIDE KILL IPC_LOCK SYS_NICE SYS_RESOURCE
     critical
     socket lmkd seqpacket 0660 system system
     writepid /dev/cpuset/system-background/tasks
diff --git a/logcat/event.logtags b/logcat/event.logtags
index 0983676..7c40a77 100644
--- a/logcat/event.logtags
+++ b/logcat/event.logtags
@@ -119,6 +119,9 @@
 70200 aggregation (aggregation time|2|3)
 70201 aggregation_test (field1|1|2),(field2|1|2),(field3|1|2),(field4|1|2),(field5|1|2)
 
+# gms refuses to register this log tag, b/30156345
+70220 gms_unknown
+
 # libc failure logging
 80100 bionic_event_memcpy_buffer_overflow (uid|1)
 80105 bionic_event_strcat_buffer_overflow (uid|1)
diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp
index 7a7ac7d..ab980ac 100755
--- a/logd/LogKlog.cpp
+++ b/logd/LogKlog.cpp
@@ -825,7 +825,7 @@
                          (unsigned short)n);
 
     // notify readers
-    if (!rc) {
+    if (rc > 0) {
         reader->notifyNewLog(static_cast<log_mask_t>(1 << LOG_ID_KERNEL));
     }
 
diff --git a/logwrapper/Android.bp b/logwrapper/Android.bp
index 54506dc..d4ba4f4 100644
--- a/logwrapper/Android.bp
+++ b/logwrapper/Android.bp
@@ -41,14 +41,11 @@
     defaults: ["logwrapper_common"],
 }
 
-// Build vendor logwrapper.
-// TODO: Add vendor_available to "logwrapper" module and remove "logwrapper_vendor" module
-//       when vendor_available is fully supported.
 cc_binary {
     name: "logwrapper_vendor",
+    defaults: ["logwrapper_common"],
     stem: "logwrapper",
     vendor: true,
-    defaults: ["logwrapper_common"],
 }
 
 // ========================================================
diff --git a/property_service/libpropertyinfoserializer/Android.bp b/property_service/libpropertyinfoserializer/Android.bp
index 72ae19a..3c4bdc3 100644
--- a/property_service/libpropertyinfoserializer/Android.bp
+++ b/property_service/libpropertyinfoserializer/Android.bp
@@ -35,4 +35,5 @@
         "property_info_serializer_test.cpp",
     ],
     static_libs: ["libpropertyinfoserializer"],
+    test_suites: ["device-tests"],
 }
diff --git a/rootdir/etc/public.libraries.iot.txt b/rootdir/etc/public.libraries.iot.txt
new file mode 100644
index 0000000..ff0813d
--- /dev/null
+++ b/rootdir/etc/public.libraries.iot.txt
@@ -0,0 +1,27 @@
+# See https://android.googlesource.com/platform/ndk/+/master/docs/PlatformApis.md
+libandroid.so
+libandroidthings.so
+libaaudio.so
+libc.so
+libcamera2ndk.so
+libdl.so
+libEGL.so
+libGLESv1_CM.so
+libGLESv2.so
+libGLESv3.so
+libicui18n.so
+libicuuc.so
+libjnigraphics.so
+liblog.so
+libmediandk.so
+libm.so
+libnativewindow.so
+libneuralnetworks.so
+libOpenMAXAL.so
+libOpenSLES.so
+libRS.so
+libstdc++.so
+libsync.so
+libvulkan.so
+libwebviewchromium_plat_support.so
+libz.so
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 1462570..d3504ad 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -21,9 +21,6 @@
     # Set the security context of /adb_keys if present.
     restorecon /adb_keys
 
-    # Shouldn't be necessary, but sdcard won't start without it. http://b/22568628.
-    mkdir /mnt 0775 root system
-
     # Set the security context of /postinstall if present.
     restorecon /postinstall
 
@@ -34,6 +31,9 @@
     # root memory control cgroup, used by lmkd
     mkdir /dev/memcg 0700 root system
     mount cgroup none /dev/memcg nodev noexec nosuid memory
+    # memory.pressure_level used by lmkd
+    chown root system /dev/memcg/memory.pressure_level
+    chmod 0040 /dev/memcg/memory.pressure_level
     # app mem cgroups, used by activity manager, lmkd and zygote
     mkdir /dev/memcg/apps/ 0755 system system
     # cgroup for system_server and surfaceflinger
@@ -80,9 +80,6 @@
     chmod 0664 /dev/stune/top-app/tasks
     chmod 0664 /dev/stune/rt/tasks
 
-    # Mount staging areas for devices managed by vold
-    # See storage config details at http://source.android.com/tech/storage/
-    mount tmpfs tmpfs /mnt nodev noexec nosuid mode=0755,uid=0,gid=1000
     restorecon_recursive /mnt
 
     mount configfs none /config nodev noexec nosuid
@@ -509,6 +506,7 @@
     mkdir /data/ss 0700 system system
 
     mkdir /data/system 0775 system system
+    mkdir /data/system/dropbox 0700 system system
     mkdir /data/system/heapdump 0700 system system
     mkdir /data/system/users 0775 system system
 
diff --git a/shell_and_utilities/README.md b/shell_and_utilities/README.md
index c423c69..4fbea86 100644
--- a/shell_and_utilities/README.md
+++ b/shell_and_utilities/README.md
@@ -191,3 +191,29 @@
 sysctl tac tail tar taskset tee time timeout top touch tr true truncate
 tty ulimit umount uname uniq unix2dos uptime usleep uudecode uuencode
 vmstat wc which whoami xargs xxd yes zcat
+
+Android Q
+---------
+
+bzip2: bzcat bzip2 bunzip2
+
+one-true-awk: awk
+
+PCRE: egrep fgrep grep
+
+toolbox: getevent getprop newfs\_msdos
+
+toybox: acpi base64 basename blockdev cal cat chcon chgrp chmod chown
+chroot chrt cksum clear cmp comm cp cpio cut date dd df diff dirname dmesg
+dos2unix du echo env expand expr fallocate false file find flock free
+getenforce groups gunzip gzip head hostname hwclock id ifconfig inotifyd
+insmod ionice iorenice kill killall ln load\_policy log logname losetup
+ls lsmod lsof lspci lsusb md5sum microcom mkdir mkfifo mknod mkswap
+mktemp modinfo modprobe more mount mountpoint mv netstat nice nl nohup
+od paste patch pgrep pidof pkill pmap printenv printf ps pwd readlink
+realpath renice restorecon rm rmdir rmmod runcon sed sendevent seq
+setenforce setprop setsid sha1sum sha224sum sha256sum sha384sum
+sha512sum sleep sort split start stat stop strings swapoff swapon sync
+sysctl tac tail tar taskset tee time timeout top touch tr true truncate
+tty ulimit umount uname uniq unix2dos uptime usleep uudecode uuencode
+vmstat wc which whoami xargs xxd yes zcat
diff --git a/toolbox/Android.bp b/toolbox/Android.bp
index ddd95b2..a0c2497 100644
--- a/toolbox/Android.bp
+++ b/toolbox/Android.bp
@@ -5,32 +5,8 @@
         "-Werror",
         "-Wno-unused-parameter",
         "-Wno-unused-const-variable",
-        "-include bsd-compatibility.h",
         "-D_FILE_OFFSET_BITS=64",
-    ],
-    local_include_dirs: ["upstream-netbsd/include/"],
-}
-
-cc_library_static {
-    name: "libtoolbox_dd",
-    defaults: ["toolbox_defaults"],
-    vendor_available: true,
-    srcs: [
-        "upstream-netbsd/bin/dd/args.c",
-        "upstream-netbsd/bin/dd/conv.c",
-        "upstream-netbsd/bin/dd/dd.c",
-        "upstream-netbsd/bin/dd/dd_hostops.c",
-        "upstream-netbsd/bin/dd/misc.c",
-        "upstream-netbsd/bin/dd/position.c",
-        "upstream-netbsd/lib/libc/gen/getbsize.c",
-        "upstream-netbsd/lib/libc/gen/humanize_number.c",
-        "upstream-netbsd/lib/libc/stdlib/strsuftoll.c",
-        "upstream-netbsd/lib/libc/string/swab.c",
-        "upstream-netbsd/lib/libutil/raise_default_signal.c",
-    ],
-    cflags: [
-        "-Dmain=dd_main",
-        "-DNO_CONV",
+        "-DWITHOUT_NLS",
     ],
 }
 
@@ -55,15 +31,12 @@
     generated_headers: [
         "toolbox_input_labels",
     ],
-    whole_static_libs: ["libtoolbox_dd"],
     shared_libs: [
         "libbase",
-        "libcutils",
     ],
     static_libs: ["libpropertyinfoparser"],
 
     symlinks: [
-        "dd",
         "getevent",
         "getprop",
         "newfs_msdos",
@@ -88,39 +61,3 @@
     defaults: ["toolbox_defaults"],
     srcs: ["r.c"],
 }
-
-// We build BSD grep separately, so it can provide egrep and fgrep too.
-cc_defaults {
-    name: "grep_common",
-    defaults: ["toolbox_defaults"],
-    srcs: [
-        "upstream-netbsd/usr.bin/grep/fastgrep.c",
-        "upstream-netbsd/usr.bin/grep/file.c",
-        "upstream-netbsd/usr.bin/grep/grep.c",
-        "upstream-netbsd/usr.bin/grep/queue.c",
-        "upstream-netbsd/usr.bin/grep/util.c",
-    ],
-    symlinks: [
-        "egrep",
-        "fgrep",
-    ],
-
-    sanitize: {
-        integer_overflow: false,
-    },
-}
-
-cc_binary {
-    name: "grep",
-    defaults: ["grep_common"],
-}
-
-// Build vendor grep.
-// TODO: Add vendor_available to "grep" module and remove "grep_vendor" module
-//       when vendor_available is fully supported.
-cc_binary {
-    name: "grep_vendor",
-    stem: "grep",
-    vendor: true,
-    defaults: ["grep_common"],
-}
diff --git a/toolbox/bsd-compatibility.h b/toolbox/bsd-compatibility.h
deleted file mode 100644
index 7c3ddd4..0000000
--- a/toolbox/bsd-compatibility.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2014, The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <stdbool.h>
-#include <sys/types.h>
-
-/* We want chown to support user.group as well as user:group. */
-#define SUPPORT_DOT
-
-/* We don't localize /system/bin! */
-#define WITHOUT_NLS
-
-// NetBSD uses _DIAGASSERT to null-check arguments and the like.
-#include <assert.h>
-#define _DIAGASSERT(e) ((e) ? (void) 0 : __assert2(__FILE__, __LINE__, __func__, #e))
-
-// TODO: update our <sys/cdefs.h> to support this properly.
-#define __type_fit(t, a) (0 == 0)
-
-// TODO: should this be in our <sys/cdefs.h>?
-#define __arraycount(a) (sizeof(a) / sizeof((a)[0]))
-
-// This at least matches GNU dd(1) behavior.
-#define SIGINFO SIGUSR1
-
-#define S_ISWHT(x) false
-
-__BEGIN_DECLS
-
-/* From NetBSD <stdlib.h>. */
-#define HN_DECIMAL              0x01
-#define HN_NOSPACE              0x02
-#define HN_B                    0x04
-#define HN_DIVISOR_1000         0x08
-#define HN_GETSCALE             0x10
-#define HN_AUTOSCALE            0x20
-int	humanize_number(char *, size_t, int64_t, const char *, int, int);
-int	dehumanize_number(const char *, int64_t *);
-char	*getbsize(int *, long *);
-long long strsuftoll(const char *, const char *, long long, long long);
-long long strsuftollx(const char *, const char *, long long, long long,
-			char *, size_t);
-
-/* From NetBSD <string.h>. */
-void strmode(mode_t, char*);
-
-/* From NetBSD <sys/param.h>. */
-#define MAXBSIZE 65536
-
-/* From NetBSD <sys/stat.h>. */
-#define DEFFILEMODE (S_IRUSR | S_IWUSR)
-
-/* From NetBSD <unistd.h>. */
-void	swab(const void * __restrict, void * __restrict, ssize_t);
-
-/* From NetBSD <util.h>. */
-int		raise_default_signal(int);
-
-__END_DECLS
diff --git a/toolbox/tools.h b/toolbox/tools.h
index 505f528..3d4bc3e 100644
--- a/toolbox/tools.h
+++ b/toolbox/tools.h
@@ -1,4 +1,3 @@
-TOOL(dd)
 TOOL(getevent)
 TOOL(getprop)
 TOOL(newfs_msdos)
diff --git a/toolbox/upstream-netbsd/bin/dd/args.c b/toolbox/upstream-netbsd/bin/dd/args.c
deleted file mode 100644
index 207e300..0000000
--- a/toolbox/upstream-netbsd/bin/dd/args.c
+++ /dev/null
@@ -1,391 +0,0 @@
-/*	$NetBSD: args.c,v 1.38 2013/07/17 12:55:48 christos Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993, 1994
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Keith Muller of the University of California, San Diego and Lance
- * Visser of Convex Computer Corporation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)args.c	8.3 (Berkeley) 4/2/94";
-#else
-__RCSID("$NetBSD: args.c,v 1.38 2013/07/17 12:55:48 christos Exp $");
-#endif
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/time.h>
-
-#include <err.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "dd.h"
-#include "extern.h"
-
-static int	c_arg(const void *, const void *);
-
-#ifdef NO_MSGFMT
-static void	f_msgfmt(char *) __dead;
-#else
-static void	f_msgfmt(char *);
-#endif /* NO_MSGFMT */
-
-#ifdef NO_CONV
-static void	f_conv(char *) __dead;
-#else
-static void	f_conv(char *);
-static int	c_conv(const void *, const void *);
-#endif /* NO_CONV */
-
-static void	f_bs(char *);
-static void	f_cbs(char *);
-static void	f_count(char *);
-static void	f_files(char *);
-static void	f_ibs(char *);
-static void	f_if(char *);
-static void	f_obs(char *);
-static void	f_of(char *);
-static void	f_seek(char *);
-static void	f_skip(char *);
-static void	f_progress(char *);
-
-static const struct arg {
-	const char *name;
-	void (*f)(char *);
-	u_int set, noset;
-} args[] = {
-     /* the array needs to be sorted by the first column so
-	bsearch() can be used to find commands quickly */
-	{ "bs",		f_bs,		C_BS,	 C_BS|C_IBS|C_OBS|C_OSYNC },
-	{ "cbs",	f_cbs,		C_CBS,	 C_CBS },
-	{ "conv",	f_conv,		0,	 0 },
-	{ "count",	f_count,	C_COUNT, C_COUNT },
-	{ "files",	f_files,	C_FILES, C_FILES },
-	{ "ibs",	f_ibs,		C_IBS,	 C_BS|C_IBS },
-	{ "if",		f_if,		C_IF,	 C_IF },
-	{ "iseek",	f_skip,		C_SKIP,	 C_SKIP },
-	{ "msgfmt",	f_msgfmt,	0,	 0 },
-	{ "obs",	f_obs,		C_OBS,	 C_BS|C_OBS },
-	{ "of",		f_of,		C_OF,	 C_OF },
-	{ "oseek",	f_seek,		C_SEEK,	 C_SEEK },
-	{ "progress",	f_progress,	0,	 0 },
-	{ "seek",	f_seek,		C_SEEK,	 C_SEEK },
-	{ "skip",	f_skip,		C_SKIP,	 C_SKIP },
-};
-
-/*
- * args -- parse JCL syntax of dd.
- */
-void
-jcl(char **argv)
-{
-	struct arg *ap, tmp;
-	char *oper, *arg;
-
-	in.dbsz = out.dbsz = 512;
-
-	while ((oper = *++argv) != NULL) {
-		if ((oper = strdup(oper)) == NULL) {
-			errx(EXIT_FAILURE,
-			    "unable to allocate space for the argument %s",
-			    *argv);
-			/* NOTREACHED */
-		}
-		if ((arg = strchr(oper, '=')) == NULL) {
-			errx(EXIT_FAILURE, "unknown operand %s", oper);
-			/* NOTREACHED */
-		}
-		*arg++ = '\0';
-		if (!*arg) {
-			errx(EXIT_FAILURE, "no value specified for %s", oper);
-			/* NOTREACHED */
-		}
-		tmp.name = oper;
-		if (!(ap = bsearch(&tmp, args,
-		    __arraycount(args), sizeof(*args), c_arg))) {
-			errx(EXIT_FAILURE, "unknown operand %s", tmp.name);
-			/* NOTREACHED */
-		}
-		if (ddflags & ap->noset) {
-			errx(EXIT_FAILURE,
-			    "%s: illegal argument combination or already set",
-			    tmp.name);
-			/* NOTREACHED */
-		}
-		ddflags |= ap->set;
-		ap->f(arg);
-	}
-
-	/* Final sanity checks. */
-
-	if (ddflags & C_BS) {
-		/*
-		 * Bs is turned off by any conversion -- we assume the user
-		 * just wanted to set both the input and output block sizes
-		 * and didn't want the bs semantics, so we don't warn.
-		 */
-		if (ddflags & (C_BLOCK | C_LCASE | C_SWAB | C_UCASE |
-		    C_UNBLOCK | C_OSYNC | C_ASCII | C_EBCDIC | C_SPARSE)) {
-			ddflags &= ~C_BS;
-			ddflags |= C_IBS|C_OBS;
-		}
-
-		/* Bs supersedes ibs and obs. */
-		if (ddflags & C_BS && ddflags & (C_IBS|C_OBS))
-			warnx("bs supersedes ibs and obs");
-	}
-
-	/*
-	 * Ascii/ebcdic and cbs implies block/unblock.
-	 * Block/unblock requires cbs and vice-versa.
-	 */
-	if (ddflags & (C_BLOCK|C_UNBLOCK)) {
-		if (!(ddflags & C_CBS)) {
-			errx(EXIT_FAILURE, "record operations require cbs");
-			/* NOTREACHED */
-		}
-		cfunc = ddflags & C_BLOCK ? block : unblock;
-	} else if (ddflags & C_CBS) {
-		if (ddflags & (C_ASCII|C_EBCDIC)) {
-			if (ddflags & C_ASCII) {
-				ddflags |= C_UNBLOCK;
-				cfunc = unblock;
-			} else {
-				ddflags |= C_BLOCK;
-				cfunc = block;
-			}
-		} else {
-			errx(EXIT_FAILURE,
-			    "cbs meaningless if not doing record operations");
-			/* NOTREACHED */
-		}
-	} else
-		cfunc = def;
-
-	/* Read, write and seek calls take off_t as arguments.
-	 *
-	 * The following check is not done because an off_t is a quad
-	 *  for current NetBSD implementations.
-	 *
-	 * if (in.offset > INT_MAX/in.dbsz || out.offset > INT_MAX/out.dbsz)
-	 *	errx(1, "seek offsets cannot be larger than %d", INT_MAX);
-	 */
-}
-
-static int
-c_arg(const void *a, const void *b)
-{
-
-	return (strcmp(((const struct arg *)a)->name,
-	    ((const struct arg *)b)->name));
-}
-
-static void
-f_bs(char *arg)
-{
-
-	in.dbsz = out.dbsz = strsuftoll("block size", arg, 1, UINT_MAX);
-}
-
-static void
-f_cbs(char *arg)
-{
-
-	cbsz = strsuftoll("conversion record size", arg, 1, UINT_MAX);
-}
-
-static void
-f_count(char *arg)
-{
-
-	cpy_cnt = strsuftoll("block count", arg, 0, LLONG_MAX);
-	if (!cpy_cnt)
-		terminate(0);
-}
-
-static void
-f_files(char *arg)
-{
-
-	files_cnt = (u_int)strsuftoll("file count", arg, 0, UINT_MAX);
-	if (!files_cnt)
-		terminate(0);
-}
-
-static void
-f_ibs(char *arg)
-{
-
-	if (!(ddflags & C_BS))
-		in.dbsz = strsuftoll("input block size", arg, 1, UINT_MAX);
-}
-
-static void
-f_if(char *arg)
-{
-
-	in.name = arg;
-}
-
-#ifdef NO_MSGFMT
-/* Build a small version (i.e. for a ramdisk root) */
-static void
-f_msgfmt(char *arg)
-{
-
-	errx(EXIT_FAILURE, "msgfmt option disabled");
-	/* NOTREACHED */
-}
-#else	/* NO_MSGFMT */
-static void
-f_msgfmt(char *arg)
-{
-
-	/*
-	 * If the format string is not valid, dd_write_msg() will print
-	 * an error and exit.
-	 */
-	dd_write_msg(arg, 0);
-
-	msgfmt = arg;
-}
-#endif	/* NO_MSGFMT */
-
-static void
-f_obs(char *arg)
-{
-
-	if (!(ddflags & C_BS))
-		out.dbsz = strsuftoll("output block size", arg, 1, UINT_MAX);
-}
-
-static void
-f_of(char *arg)
-{
-
-	out.name = arg;
-}
-
-static void
-f_seek(char *arg)
-{
-
-	out.offset = strsuftoll("seek blocks", arg, 0, LLONG_MAX);
-}
-
-static void
-f_skip(char *arg)
-{
-
-	in.offset = strsuftoll("skip blocks", arg, 0, LLONG_MAX);
-}
-
-static void
-f_progress(char *arg)
-{
-
-	progress = strsuftoll("progress blocks", arg, 0, LLONG_MAX);
-}
-
-#ifdef	NO_CONV
-/* Build a small version (i.e. for a ramdisk root) */
-static void
-f_conv(char *arg)
-{
-
-	errx(EXIT_FAILURE, "conv option disabled");
-	/* NOTREACHED */
-}
-#else	/* NO_CONV */
-
-static const struct conv {
-	const char *name;
-	u_int set, noset;
-	const u_char *ctab;
-} clist[] = {
-	{ "ascii",	C_ASCII,	C_EBCDIC,	e2a_POSIX },
-	{ "block",	C_BLOCK,	C_UNBLOCK,	NULL },
-	{ "ebcdic",	C_EBCDIC,	C_ASCII,	a2e_POSIX },
-	{ "ibm",	C_EBCDIC,	C_ASCII,	a2ibm_POSIX },
-	{ "lcase",	C_LCASE,	C_UCASE,	NULL },
-	{ "noerror",	C_NOERROR,	0,		NULL },
-	{ "notrunc",	C_NOTRUNC,	0,		NULL },
-	{ "oldascii",	C_ASCII,	C_EBCDIC,	e2a_32V },
-	{ "oldebcdic",	C_EBCDIC,	C_ASCII,	a2e_32V },
-	{ "oldibm",	C_EBCDIC,	C_ASCII,	a2ibm_32V },
-	{ "osync",	C_OSYNC,	C_BS,		NULL },
-	{ "sparse",	C_SPARSE,	0,		NULL },
-	{ "swab",	C_SWAB,		0,		NULL },
-	{ "sync",	C_SYNC,		0,		NULL },
-	{ "ucase",	C_UCASE,	C_LCASE,	NULL },
-	{ "unblock",	C_UNBLOCK,	C_BLOCK,	NULL },
-	/* If you add items to this table, be sure to add the
-	 * conversions to the C_BS check in the jcl routine above.
-	 */
-};
-
-static void
-f_conv(char *arg)
-{
-	struct conv *cp, tmp;
-
-	while (arg != NULL) {
-		tmp.name = strsep(&arg, ",");
-		if (!(cp = bsearch(&tmp, clist,
-		    __arraycount(clist), sizeof(*clist), c_conv))) {
-			errx(EXIT_FAILURE, "unknown conversion %s", tmp.name);
-			/* NOTREACHED */
-		}
-		if (ddflags & cp->noset) {
-			errx(EXIT_FAILURE,
-			    "%s: illegal conversion combination", tmp.name);
-			/* NOTREACHED */
-		}
-		ddflags |= cp->set;
-		if (cp->ctab)
-			ctab = cp->ctab;
-	}
-}
-
-static int
-c_conv(const void *a, const void *b)
-{
-
-	return (strcmp(((const struct conv *)a)->name,
-	    ((const struct conv *)b)->name));
-}
-
-#endif	/* NO_CONV */
diff --git a/toolbox/upstream-netbsd/bin/dd/conv.c b/toolbox/upstream-netbsd/bin/dd/conv.c
deleted file mode 100644
index d4a8a09..0000000
--- a/toolbox/upstream-netbsd/bin/dd/conv.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/*	$NetBSD: conv.c,v 1.17 2003/08/07 09:05:10 agc Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993, 1994
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Keith Muller of the University of California, San Diego and Lance
- * Visser of Convex Computer Corporation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)conv.c	8.3 (Berkeley) 4/2/94";
-#else
-__RCSID("$NetBSD: conv.c,v 1.17 2003/08/07 09:05:10 agc Exp $");
-#endif
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/time.h>
-
-#include <err.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "dd.h"
-#include "extern.h"
-
-/*
- * def --
- * Copy input to output.  Input is buffered until reaches obs, and then
- * output until less than obs remains.  Only a single buffer is used.
- * Worst case buffer calculation is (ibs + obs - 1).
- */
-void
-def(void)
-{
-	uint64_t cnt;
-	u_char *inp;
-	const u_char *t;
-
-	if ((t = ctab) != NULL)
-		for (inp = in.dbp - (cnt = in.dbrcnt); cnt--; ++inp)
-			*inp = t[*inp];
-
-	/* Make the output buffer look right. */
-	out.dbp = in.dbp;
-	out.dbcnt = in.dbcnt;
-
-	if (in.dbcnt >= out.dbsz) {
-		/* If the output buffer is full, write it. */
-		dd_out(0);
-
-		/*
-		 * Ddout copies the leftover output to the beginning of
-		 * the buffer and resets the output buffer.  Reset the
-		 * input buffer to match it.
-	 	 */
-		in.dbp = out.dbp;
-		in.dbcnt = out.dbcnt;
-	}
-}
-
-void
-def_close(void)
-{
-
-	/* Just update the count, everything is already in the buffer. */
-	if (in.dbcnt)
-		out.dbcnt = in.dbcnt;
-}
-
-#ifdef	NO_CONV
-/* Build a smaller version (i.e. for a miniroot) */
-/* These can not be called, but just in case...  */
-static const char no_block[] = "unblock and -DNO_CONV?";
-void block(void)		{ errx(EXIT_FAILURE, "%s", no_block + 2); }
-void block_close(void)		{ errx(EXIT_FAILURE, "%s", no_block + 2); }
-void unblock(void)		{ errx(EXIT_FAILURE, "%s", no_block); }
-void unblock_close(void)	{ errx(EXIT_FAILURE, "%s", no_block); }
-#else	/* NO_CONV */
-
-/*
- * Copy variable length newline terminated records with a max size cbsz
- * bytes to output.  Records less than cbs are padded with spaces.
- *
- * max in buffer:  MAX(ibs, cbsz)
- * max out buffer: obs + cbsz
- */
-void
-block(void)
-{
-	static int intrunc;
-	int ch = 0;	/* pacify gcc */
-	uint64_t cnt, maxlen;
-	u_char *inp, *outp;
-	const u_char *t;
-
-	/*
-	 * Record truncation can cross block boundaries.  If currently in a
-	 * truncation state, keep tossing characters until reach a newline.
-	 * Start at the beginning of the buffer, as the input buffer is always
-	 * left empty.
-	 */
-	if (intrunc) {
-		for (inp = in.db, cnt = in.dbrcnt;
-		    cnt && *inp++ != '\n'; --cnt);
-		if (!cnt) {
-			in.dbcnt = 0;
-			in.dbp = in.db;
-			return;
-		}
-		intrunc = 0;
-		/* Adjust the input buffer numbers. */
-		in.dbcnt = cnt - 1;
-		in.dbp = inp + cnt - 1;
-	}
-
-	/*
-	 * Copy records (max cbsz size chunks) into the output buffer.  The
-	 * translation is done as we copy into the output buffer.
-	 */
-	for (inp = in.dbp - in.dbcnt, outp = out.dbp; in.dbcnt;) {
-		maxlen = MIN(cbsz, in.dbcnt);
-		if ((t = ctab) != NULL)
-			for (cnt = 0;
-			    cnt < maxlen && (ch = *inp++) != '\n'; ++cnt)
-				*outp++ = t[ch];
-		else
-			for (cnt = 0;
-			    cnt < maxlen && (ch = *inp++) != '\n'; ++cnt)
-				*outp++ = ch;
-		/*
-		 * Check for short record without a newline.  Reassemble the
-		 * input block.
-		 */
-		if (ch != '\n' && in.dbcnt < cbsz) {
-			(void)memmove(in.db, in.dbp - in.dbcnt, in.dbcnt);
-			break;
-		}
-
-		/* Adjust the input buffer numbers. */
-		in.dbcnt -= cnt;
-		if (ch == '\n')
-			--in.dbcnt;
-
-		/* Pad short records with spaces. */
-		if (cnt < cbsz)
-			(void)memset(outp, ctab ? ctab[' '] : ' ', cbsz - cnt);
-		else {
-			/*
-			 * If the next character wouldn't have ended the
-			 * block, it's a truncation.
-			 */
-			if (!in.dbcnt || *inp != '\n')
-				++st.trunc;
-
-			/* Toss characters to a newline. */
-			for (; in.dbcnt && *inp++ != '\n'; --in.dbcnt);
-			if (!in.dbcnt)
-				intrunc = 1;
-			else
-				--in.dbcnt;
-		}
-
-		/* Adjust output buffer numbers. */
-		out.dbp += cbsz;
-		if ((out.dbcnt += cbsz) >= out.dbsz)
-			dd_out(0);
-		outp = out.dbp;
-	}
-	in.dbp = in.db + in.dbcnt;
-}
-
-void
-block_close(void)
-{
-
-	/*
-	 * Copy any remaining data into the output buffer and pad to a record.
-	 * Don't worry about truncation or translation, the input buffer is
-	 * always empty when truncating, and no characters have been added for
-	 * translation.  The bottom line is that anything left in the input
-	 * buffer is a truncated record.  Anything left in the output buffer
-	 * just wasn't big enough.
-	 */
-	if (in.dbcnt) {
-		++st.trunc;
-		(void)memmove(out.dbp, in.dbp - in.dbcnt, in.dbcnt);
-		(void)memset(out.dbp + in.dbcnt,
-		    ctab ? ctab[' '] : ' ', cbsz - in.dbcnt);
-		out.dbcnt += cbsz;
-	}
-}
-
-/*
- * Convert fixed length (cbsz) records to variable length.  Deletes any
- * trailing blanks and appends a newline.
- *
- * max in buffer:  MAX(ibs, cbsz) + cbsz
- * max out buffer: obs + cbsz
- */
-void
-unblock(void)
-{
-	uint64_t cnt;
-	u_char *inp;
-	const u_char *t;
-
-	/* Translation and case conversion. */
-	if ((t = ctab) != NULL)
-		for (cnt = in.dbrcnt, inp = in.dbp - 1; cnt--; inp--)
-			*inp = t[*inp];
-	/*
-	 * Copy records (max cbsz size chunks) into the output buffer.  The
-	 * translation has to already be done or we might not recognize the
-	 * spaces.
-	 */
-	for (inp = in.db; in.dbcnt >= cbsz; inp += cbsz, in.dbcnt -= cbsz) {
-		for (t = inp + cbsz - 1; t >= inp && *t == ' '; --t);
-		if (t >= inp) {
-			cnt = t - inp + 1;
-			(void)memmove(out.dbp, inp, cnt);
-			out.dbp += cnt;
-			out.dbcnt += cnt;
-		}
-		++out.dbcnt;
-		*out.dbp++ = '\n';
-		if (out.dbcnt >= out.dbsz)
-			dd_out(0);
-	}
-	if (in.dbcnt)
-		(void)memmove(in.db, in.dbp - in.dbcnt, in.dbcnt);
-	in.dbp = in.db + in.dbcnt;
-}
-
-void
-unblock_close(void)
-{
-	uint64_t cnt;
-	u_char *t;
-
-	if (in.dbcnt) {
-		warnx("%s: short input record", in.name);
-		for (t = in.db + in.dbcnt - 1; t >= in.db && *t == ' '; --t);
-		if (t >= in.db) {
-			cnt = t - in.db + 1;
-			(void)memmove(out.dbp, in.db, cnt);
-			out.dbp += cnt;
-			out.dbcnt += cnt;
-		}
-		++out.dbcnt;
-		*out.dbp++ = '\n';
-	}
-}
-
-#endif	/* NO_CONV */
diff --git a/toolbox/upstream-netbsd/bin/dd/dd.c b/toolbox/upstream-netbsd/bin/dd/dd.c
deleted file mode 100644
index 03d080c..0000000
--- a/toolbox/upstream-netbsd/bin/dd/dd.c
+++ /dev/null
@@ -1,598 +0,0 @@
-/*	$NetBSD: dd.c,v 1.49 2012/02/21 01:49:01 matt Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993, 1994
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Keith Muller of the University of California, San Diego and Lance
- * Visser of Convex Computer Corporation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#ifndef lint
-__COPYRIGHT("@(#) Copyright (c) 1991, 1993, 1994\
- The Regents of the University of California.  All rights reserved.");
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)dd.c	8.5 (Berkeley) 4/2/94";
-#else
-__RCSID("$NetBSD: dd.c,v 1.49 2012/02/21 01:49:01 matt Exp $");
-#endif
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/mtio.h>
-#include <sys/time.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <locale.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "dd.h"
-#include "extern.h"
-
-static void dd_close(void);
-static void dd_in(void);
-static void getfdtype(IO *);
-static void redup_clean_fd(IO *);
-static void setup(void);
-
-int main(int, char *[]);
-
-IO		in, out;		/* input/output state */
-STAT		st;			/* statistics */
-void		(*cfunc)(void);		/* conversion function */
-uint64_t	cpy_cnt;		/* # of blocks to copy */
-static off_t	pending = 0;		/* pending seek if sparse */
-u_int		ddflags;		/* conversion options */
-uint64_t	cbsz;			/* conversion block size */
-u_int		files_cnt = 1;		/* # of files to copy */
-uint64_t	progress = 0;		/* display sign of life */
-const u_char	*ctab;			/* conversion table */
-sigset_t	infoset;		/* a set blocking SIGINFO */
-const char	*msgfmt = "posix";	/* default summary() message format */
-
-/*
- * Ops for stdin/stdout and crunch'd dd.  These are always host ops.
- */
-static const struct ddfops ddfops_stdfd = {
-	.op_open = open,
-	.op_close = close,
-	.op_fcntl = fcntl,
-	.op_ioctl = ioctl,
-	.op_fstat = fstat,
-	.op_fsync = fsync,
-	.op_ftruncate = ftruncate,
-	.op_lseek = lseek,
-	.op_read = read,
-	.op_write = write,
-};
-extern const struct ddfops ddfops_prog;
-
-int
-main(int argc, char *argv[])
-{
-	int ch;
-
-	setprogname(argv[0]);
-	(void)setlocale(LC_ALL, "");
-
-	while ((ch = getopt(argc, argv, "")) != -1) {
-		switch (ch) {
-		default:
-			errx(EXIT_FAILURE, "usage: dd [operand ...]");
-			/* NOTREACHED */
-		}
-	}
-	argc -= (optind - 1);
-	argv += (optind - 1);
-
-	jcl(argv);
-#ifndef CRUNCHOPS
-	if (ddfops_prog.op_init && ddfops_prog.op_init() == -1)
-		err(1, "prog init");
-#endif
-	setup();
-
-	(void)signal(SIGINFO, summaryx);
-	(void)signal(SIGINT, terminate);
-	(void)sigemptyset(&infoset);
-	(void)sigaddset(&infoset, SIGINFO);
-
-	(void)atexit(summary);
-
-	while (files_cnt--)
-		dd_in();
-
-	dd_close();
-	exit(0);
-	/* NOTREACHED */
-}
-
-static void
-setup(void)
-{
-#ifdef CRUNCHOPS
-	const struct ddfops *prog_ops = &ddfops_stdfd;
-#else
-	const struct ddfops *prog_ops = &ddfops_prog;
-#endif
-
-	if (in.name == NULL) {
-		in.name = "stdin";
-		in.fd = STDIN_FILENO;
-		in.ops = &ddfops_stdfd;
-	} else {
-		in.ops = prog_ops;
-		in.fd = ddop_open(in, in.name, O_RDONLY, 0);
-		if (in.fd < 0)
-			err(EXIT_FAILURE, "%s", in.name);
-			/* NOTREACHED */
-
-		/* Ensure in.fd is outside the stdio descriptor range */
-		redup_clean_fd(&in);
-	}
-
-	getfdtype(&in);
-
-	if (files_cnt > 1 && !(in.flags & ISTAPE)) {
-		errx(EXIT_FAILURE, "files is not supported for non-tape devices");
-		/* NOTREACHED */
-	}
-
-	if (out.name == NULL) {
-		/* No way to check for read access here. */
-		out.fd = STDOUT_FILENO;
-		out.name = "stdout";
-		out.ops = &ddfops_stdfd;
-	} else {
-		out.ops = prog_ops;
-#define	OFLAGS \
-    (O_CREAT | (ddflags & (C_SEEK | C_NOTRUNC) ? 0 : O_TRUNC))
-		out.fd = ddop_open(out, out.name, O_RDWR | OFLAGS, DEFFILEMODE);
-		/*
-		 * May not have read access, so try again with write only.
-		 * Without read we may have a problem if output also does
-		 * not support seeks.
-		 */
-		if (out.fd < 0) {
-			out.fd = ddop_open(out, out.name, O_WRONLY | OFLAGS,
-			    DEFFILEMODE);
-			out.flags |= NOREAD;
-		}
-		if (out.fd < 0) {
-			err(EXIT_FAILURE, "%s", out.name);
-			/* NOTREACHED */
-		}
-
-		/* Ensure out.fd is outside the stdio descriptor range */
-		redup_clean_fd(&out);
-	}
-
-	getfdtype(&out);
-
-	/*
-	 * Allocate space for the input and output buffers.  If not doing
-	 * record oriented I/O, only need a single buffer.
-	 */
-	if (!(ddflags & (C_BLOCK|C_UNBLOCK))) {
-		size_t dbsz = out.dbsz;
-		if (!(ddflags & C_BS))
-			dbsz += in.dbsz - 1;
-		if ((in.db = malloc(dbsz)) == NULL) {
-			err(EXIT_FAILURE, NULL);
-			/* NOTREACHED */
-		}
-		out.db = in.db;
-	} else if ((in.db =
-	    malloc((u_int)(MAX(in.dbsz, cbsz) + cbsz))) == NULL ||
-	    (out.db = malloc((u_int)(out.dbsz + cbsz))) == NULL) {
-		err(EXIT_FAILURE, NULL);
-		/* NOTREACHED */
-	}
-	in.dbp = in.db;
-	out.dbp = out.db;
-
-	/* Position the input/output streams. */
-	if (in.offset)
-		pos_in();
-	if (out.offset)
-		pos_out();
-
-	/*
-	 * Truncate the output file; ignore errors because it fails on some
-	 * kinds of output files, tapes, for example.
-	 */
-	if ((ddflags & (C_OF | C_SEEK | C_NOTRUNC)) == (C_OF | C_SEEK))
-		(void)ddop_ftruncate(out, out.fd, (off_t)out.offset * out.dbsz);
-
-	/*
-	 * If converting case at the same time as another conversion, build a
-	 * table that does both at once.  If just converting case, use the
-	 * built-in tables.
-	 */
-	if (ddflags & (C_LCASE|C_UCASE)) {
-#ifdef	NO_CONV
-		/* Should not get here, but just in case... */
-		errx(EXIT_FAILURE, "case conv and -DNO_CONV");
-		/* NOTREACHED */
-#else	/* NO_CONV */
-		u_int cnt;
-
-		if (ddflags & C_ASCII || ddflags & C_EBCDIC) {
-			if (ddflags & C_LCASE) {
-				for (cnt = 0; cnt < 256; ++cnt)
-					casetab[cnt] = tolower(ctab[cnt]);
-			} else {
-				for (cnt = 0; cnt < 256; ++cnt)
-					casetab[cnt] = toupper(ctab[cnt]);
-			}
-		} else {
-			if (ddflags & C_LCASE) {
-				for (cnt = 0; cnt < 256; ++cnt)
-					casetab[cnt] = tolower(cnt);
-			} else {
-				for (cnt = 0; cnt < 256; ++cnt)
-					casetab[cnt] = toupper(cnt);
-			}
-		}
-
-		ctab = casetab;
-#endif	/* NO_CONV */
-	}
-
-	(void)gettimeofday(&st.start, NULL);	/* Statistics timestamp. */
-}
-
-static void
-getfdtype(IO *io)
-{
-	struct mtget mt;
-	struct stat sb;
-
-	if (io->ops->op_fstat(io->fd, &sb)) {
-		err(EXIT_FAILURE, "%s", io->name);
-		/* NOTREACHED */
-	}
-	if (S_ISCHR(sb.st_mode))
-		io->flags |= io->ops->op_ioctl(io->fd, MTIOCGET, &mt)
-		    ? ISCHR : ISTAPE;
-	else if (io->ops->op_lseek(io->fd, (off_t)0, SEEK_CUR) == -1
-	    && errno == ESPIPE)
-		io->flags |= ISPIPE;		/* XXX fixed in 4.4BSD */
-}
-
-/*
- * Move the parameter file descriptor to a descriptor that is outside the
- * stdio descriptor range, if necessary.  This is required to avoid
- * accidentally outputting completion or error messages into the
- * output file that were intended for the tty.
- */
-static void
-redup_clean_fd(IO *io)
-{
-	int fd = io->fd;
-	int newfd;
-
-	if (fd != STDIN_FILENO && fd != STDOUT_FILENO &&
-	    fd != STDERR_FILENO)
-		/* File descriptor is ok, return immediately. */
-		return;
-
-	/*
-	 * 3 is the first descriptor greater than STD*_FILENO.  Any
-	 * free descriptor valued 3 or above is acceptable...
-	 */
-	newfd = io->ops->op_fcntl(fd, F_DUPFD, 3);
-	if (newfd < 0) {
-		err(EXIT_FAILURE, "dupfd IO");
-		/* NOTREACHED */
-	}
-
-	io->ops->op_close(fd);
-	io->fd = newfd;
-}
-
-static void
-dd_in(void)
-{
-	int flags;
-	int64_t n;
-
-	for (flags = ddflags;;) {
-		if (cpy_cnt && (st.in_full + st.in_part) >= cpy_cnt)
-			return;
-
-		/*
-		 * Clear the buffer first if doing "sync" on input.
-		 * If doing block operations use spaces.  This will
-		 * affect not only the C_NOERROR case, but also the
-		 * last partial input block which should be padded
-		 * with zero and not garbage.
-		 */
-		if (flags & C_SYNC) {
-			if (flags & (C_BLOCK|C_UNBLOCK))
-				(void)memset(in.dbp, ' ', in.dbsz);
-			else
-				(void)memset(in.dbp, 0, in.dbsz);
-		}
-
-		n = ddop_read(in, in.fd, in.dbp, in.dbsz);
-		if (n == 0) {
-			in.dbrcnt = 0;
-			return;
-		}
-
-		/* Read error. */
-		if (n < 0) {
-
-			/*
-			 * If noerror not specified, die.  POSIX requires that
-			 * the warning message be followed by an I/O display.
-			 */
-			if (!(flags & C_NOERROR)) {
-				err(EXIT_FAILURE, "%s", in.name);
-				/* NOTREACHED */
-			}
-			warn("%s", in.name);
-			summary();
-
-			/*
-			 * If it's not a tape drive or a pipe, seek past the
-			 * error.  If your OS doesn't do the right thing for
-			 * raw disks this section should be modified to re-read
-			 * in sector size chunks.
-			 */
-			if (!(in.flags & (ISPIPE|ISTAPE)) &&
-			    ddop_lseek(in, in.fd, (off_t)in.dbsz, SEEK_CUR))
-				warn("%s", in.name);
-
-			/* If sync not specified, omit block and continue. */
-			if (!(ddflags & C_SYNC))
-				continue;
-
-			/* Read errors count as full blocks. */
-			in.dbcnt += in.dbrcnt = in.dbsz;
-			++st.in_full;
-
-		/* Handle full input blocks. */
-		} else if ((uint64_t)n == in.dbsz) {
-			in.dbcnt += in.dbrcnt = n;
-			++st.in_full;
-
-		/* Handle partial input blocks. */
-		} else {
-			/* If sync, use the entire block. */
-			if (ddflags & C_SYNC)
-				in.dbcnt += in.dbrcnt = in.dbsz;
-			else
-				in.dbcnt += in.dbrcnt = n;
-			++st.in_part;
-		}
-
-		/*
-		 * POSIX states that if bs is set and no other conversions
-		 * than noerror, notrunc or sync are specified, the block
-		 * is output without buffering as it is read.
-		 */
-		if (ddflags & C_BS) {
-			out.dbcnt = in.dbcnt;
-			dd_out(1);
-			in.dbcnt = 0;
-			continue;
-		}
-
-		if (ddflags & C_SWAB) {
-			if ((n = in.dbrcnt) & 1) {
-				++st.swab;
-				--n;
-			}
-			swab(in.dbp, in.dbp, n);
-		}
-
-		in.dbp += in.dbrcnt;
-		(*cfunc)();
-	}
-}
-
-/*
- * Cleanup any remaining I/O and flush output.  If necessary, output file
- * is truncated.
- */
-static void
-dd_close(void)
-{
-
-	if (cfunc == def)
-		def_close();
-	else if (cfunc == block)
-		block_close();
-	else if (cfunc == unblock)
-		unblock_close();
-	if (ddflags & C_OSYNC && out.dbcnt < out.dbsz) {
-		(void)memset(out.dbp, 0, out.dbsz - out.dbcnt);
-		out.dbcnt = out.dbsz;
-	}
-	/* If there are pending sparse blocks, make sure
-	 * to write out the final block un-sparse
-	 */
-	if ((out.dbcnt == 0) && pending) {
-		memset(out.db, 0, out.dbsz);
-		out.dbcnt = out.dbsz;
-		out.dbp = out.db + out.dbcnt;
-		pending -= out.dbsz;
-	}
-	if (out.dbcnt)
-		dd_out(1);
-
-	/*
-	 * Reporting nfs write error may be deferred until next
-	 * write(2) or close(2) system call.  So, we need to do an
-	 * extra check.  If an output is stdout, the file structure
-	 * may be shared with other processes and close(2) just
-	 * decreases the reference count.
-	 */
-	if (out.fd == STDOUT_FILENO && ddop_fsync(out, out.fd) == -1
-	    && errno != EINVAL) {
-		err(EXIT_FAILURE, "fsync stdout");
-		/* NOTREACHED */
-	}
-	if (ddop_close(out, out.fd) == -1) {
-		err(EXIT_FAILURE, "close");
-		/* NOTREACHED */
-	}
-}
-
-void
-dd_out(int force)
-{
-	static int warned;
-	int64_t cnt, n, nw;
-	u_char *outp;
-
-	/*
-	 * Write one or more blocks out.  The common case is writing a full
-	 * output block in a single write; increment the full block stats.
-	 * Otherwise, we're into partial block writes.  If a partial write,
-	 * and it's a character device, just warn.  If a tape device, quit.
-	 *
-	 * The partial writes represent two cases.  1: Where the input block
-	 * was less than expected so the output block was less than expected.
-	 * 2: Where the input block was the right size but we were forced to
-	 * write the block in multiple chunks.  The original versions of dd(1)
-	 * never wrote a block in more than a single write, so the latter case
-	 * never happened.
-	 *
-	 * One special case is if we're forced to do the write -- in that case
-	 * we play games with the buffer size, and it's usually a partial write.
-	 */
-	outp = out.db;
-	for (n = force ? out.dbcnt : out.dbsz;; n = out.dbsz) {
-		for (cnt = n;; cnt -= nw) {
-
-			if (!force && ddflags & C_SPARSE) {
-				int sparse, i;
-				sparse = 1;	/* Is buffer sparse? */
-				for (i = 0; i < cnt; i++)
-					if (outp[i] != 0) {
-						sparse = 0;
-						break;
-					}
-				if (sparse) {
-					pending += cnt;
-					outp += cnt;
-					nw = 0;
-					break;
-				}
-			}
-			if (pending != 0) {
-				if (ddop_lseek(out,
-				    out.fd, pending, SEEK_CUR) == -1)
-					err(EXIT_FAILURE, "%s: seek error creating sparse file",
-					    out.name);
-			}
-			nw = bwrite(&out, outp, cnt);
-			if (nw <= 0) {
-				if (nw == 0)
-					errx(EXIT_FAILURE,
-						"%s: end of device", out.name);
-					/* NOTREACHED */
-				if (errno != EINTR)
-					err(EXIT_FAILURE, "%s", out.name);
-					/* NOTREACHED */
-				nw = 0;
-			}
-			if (pending) {
-				st.bytes += pending;
-				st.sparse += pending/out.dbsz;
-				st.out_full += pending/out.dbsz;
-				pending = 0;
-			}
-			outp += nw;
-			st.bytes += nw;
-			if (nw == n) {
-				if ((uint64_t)n != out.dbsz)
-					++st.out_part;
-				else
-					++st.out_full;
-				break;
-			}
-			++st.out_part;
-			if (nw == cnt)
-				break;
-			if (out.flags & ISCHR && !warned) {
-				warned = 1;
-				warnx("%s: short write on character device", out.name);
-			}
-			if (out.flags & ISTAPE)
-				errx(EXIT_FAILURE,
-					"%s: short write on tape device", out.name);
-				/* NOTREACHED */
-
-		}
-		if ((out.dbcnt -= n) < out.dbsz)
-			break;
-	}
-
-	/* Reassemble the output block. */
-	if (out.dbcnt)
-		(void)memmove(out.db, out.dbp - out.dbcnt, out.dbcnt);
-	out.dbp = out.db + out.dbcnt;
-
-	if (progress && (st.out_full + st.out_part) % progress == 0)
-		(void)write(STDERR_FILENO, ".", 1);
-}
-
-/*
- * A protected against SIGINFO write
- */
-ssize_t
-bwrite(IO *io, const void *buf, size_t len)
-{
-	sigset_t oset;
-	ssize_t rv;
-	int oerrno;
-
-	(void)sigprocmask(SIG_BLOCK, &infoset, &oset);
-	rv = io->ops->op_write(io->fd, buf, len);
-	oerrno = errno;
-	(void)sigprocmask(SIG_SETMASK, &oset, NULL);
-	errno = oerrno;
-	return (rv);
-}
diff --git a/toolbox/upstream-netbsd/bin/dd/dd.h b/toolbox/upstream-netbsd/bin/dd/dd.h
deleted file mode 100644
index b01c7b3..0000000
--- a/toolbox/upstream-netbsd/bin/dd/dd.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*	$NetBSD: dd.h,v 1.15 2011/02/04 19:42:12 pooka Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993, 1994
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Keith Muller of the University of California, San Diego and Lance
- * Visser of Convex Computer Corporation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)dd.h	8.3 (Berkeley) 4/2/94
- */
-
-#include <sys/stat.h>
-
-struct ddfops {
-	int (*op_init)(void);
-
-	int (*op_open)(const char *, int, ...);
-	int (*op_close)(int);
-
-	int (*op_fcntl)(int, int, ...);
-#ifdef __ANDROID__
-	int (*op_ioctl)(int, int, ...);
-#else
-	int (*op_ioctl)(int, unsigned long, ...);
-#endif
-
-	int (*op_fstat)(int, struct stat *);
-	int (*op_fsync)(int);
-	int (*op_ftruncate)(int, off_t);
-
-	off_t (*op_lseek)(int, off_t, int);
-
-	ssize_t (*op_read)(int, void *, size_t);
-	ssize_t (*op_write)(int, const void *, size_t);
-};
-
-#define ddop_open(dir, a1, a2, ...)	dir.ops->op_open(a1, a2, __VA_ARGS__)
-#define ddop_close(dir, a1)		dir.ops->op_close(a1)
-#define ddop_fcntl(dir, a1, a2, ...)	dir.ops->op_fcntl(a1, a2, __VA_ARGS__)
-#define ddop_ioctl(dir, a1, a2, ...)	dir.ops->op_ioctl(a1, a2, __VA_ARGS__)
-#define ddop_fsync(dir, a1)		dir.ops->op_fsync(a1)
-#define ddop_ftruncate(dir, a1, a2)	dir.ops->op_ftruncate(a1, a2)
-#define ddop_lseek(dir, a1, a2, a3)	dir.ops->op_lseek(a1, a2, a3)
-#define ddop_read(dir, a1, a2, a3)	dir.ops->op_read(a1, a2, a3)
-#define ddop_write(dir, a1, a2, a3)	dir.ops->op_write(a1, a2, a3)
-
-/* Input/output stream state. */
-typedef struct {
-	u_char		*db;		/* buffer address */
-	u_char		*dbp;		/* current buffer I/O address */
-	uint64_t	dbcnt;		/* current buffer byte count */
-	int64_t		dbrcnt;		/* last read byte count */
-	uint64_t	dbsz;		/* buffer size */
-
-#define	ISCHR		0x01		/* character device (warn on short) */
-#define	ISPIPE		0x02		/* pipe (not truncatable) */
-#define	ISTAPE		0x04		/* tape (not seekable) */
-#define	NOREAD		0x08		/* not readable */
-	u_int		flags;
-
-	const char  	*name;		/* name */
-	int		fd;		/* file descriptor */
-	uint64_t	offset;		/* # of blocks to skip */
-	struct ddfops	const *ops;	/* ops to use with fd */
-} IO;
-
-typedef struct {
-	uint64_t	in_full;	/* # of full input blocks */
-	uint64_t	in_part;	/* # of partial input blocks */
-	uint64_t	out_full;	/* # of full output blocks */
-	uint64_t	out_part;	/* # of partial output blocks */
-	uint64_t	trunc;		/* # of truncated records */
-	uint64_t	swab;		/* # of odd-length swab blocks */
-	uint64_t	sparse;		/* # of sparse output blocks */
-	uint64_t	bytes;		/* # of bytes written */
-	struct timeval	start;		/* start time of dd */
-} STAT;
-
-/* Flags (in ddflags). */
-#define	C_ASCII		0x00001
-#define	C_BLOCK		0x00002
-#define	C_BS		0x00004
-#define	C_CBS		0x00008
-#define	C_COUNT		0x00010
-#define	C_EBCDIC	0x00020
-#define	C_FILES		0x00040
-#define	C_IBS		0x00080
-#define	C_IF		0x00100
-#define	C_LCASE		0x00200
-#define	C_NOERROR	0x00400
-#define	C_NOTRUNC	0x00800
-#define	C_OBS		0x01000
-#define	C_OF		0x02000
-#define	C_SEEK		0x04000
-#define	C_SKIP		0x08000
-#define	C_SWAB		0x10000
-#define	C_SYNC		0x20000
-#define	C_UCASE		0x40000
-#define	C_UNBLOCK	0x80000
-#define	C_OSYNC		0x100000
-#define	C_SPARSE	0x200000
diff --git a/toolbox/upstream-netbsd/bin/dd/dd_hostops.c b/toolbox/upstream-netbsd/bin/dd/dd_hostops.c
deleted file mode 100644
index d6e7a89..0000000
--- a/toolbox/upstream-netbsd/bin/dd/dd_hostops.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*      $NetBSD: dd_hostops.c,v 1.1 2011/02/04 19:42:12 pooka Exp $	*/
-
-/*-
- * Copyright (c) 2010 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#ifndef lint
-__RCSID("$NetBSD: dd_hostops.c,v 1.1 2011/02/04 19:42:12 pooka Exp $");
-#endif /* !lint */
-
-#include <sys/types.h>
-#include <sys/ioctl.h>
-
-#include <fcntl.h>
-#include <unistd.h>
-
-#include "dd.h"
-
-const struct ddfops ddfops_prog = {
-	.op_open = open,
-	.op_close = close,
-	.op_fcntl = fcntl,
-	.op_ioctl = ioctl,
-	.op_fstat = fstat,
-	.op_fsync = fsync,
-	.op_ftruncate = ftruncate,
-	.op_lseek = lseek,
-	.op_read = read,
-	.op_write = write,
-};
diff --git a/toolbox/upstream-netbsd/bin/dd/extern.h b/toolbox/upstream-netbsd/bin/dd/extern.h
deleted file mode 100644
index 9c59021..0000000
--- a/toolbox/upstream-netbsd/bin/dd/extern.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*	$NetBSD: extern.h,v 1.22 2011/11/07 22:24:23 jym Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993, 1994
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Keith Muller of the University of California, San Diego and Lance
- * Visser of Convex Computer Corporation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)extern.h	8.3 (Berkeley) 4/2/94
- */
-
-#include <sys/cdefs.h>
-
-#ifdef NO_CONV
-__dead void block(void);
-__dead void block_close(void);
-__dead void unblock(void);
-__dead void unblock_close(void);
-#else
-void block(void);
-void block_close(void);
-void unblock(void);
-void unblock_close(void);
-#endif
-
-#ifndef NO_MSGFMT
-int dd_write_msg(const char *, int);
-#endif
-
-void dd_out(int);
-void def(void);
-void def_close(void);
-void jcl(char **);
-void pos_in(void);
-void pos_out(void);
-void summary(void);
-void summaryx(int);
-__dead void terminate(int);
-void unblock(void);
-void unblock_close(void);
-ssize_t bwrite(IO *, const void *, size_t);
-
-extern IO		in, out;
-extern STAT		st;
-extern void		(*cfunc)(void);
-extern uint64_t		cpy_cnt;
-extern uint64_t		cbsz;
-extern u_int		ddflags;
-extern u_int		files_cnt;
-extern uint64_t		progress;
-extern const u_char	*ctab;
-extern const u_char	a2e_32V[], a2e_POSIX[];
-extern const u_char	e2a_32V[], e2a_POSIX[];
-extern const u_char	a2ibm_32V[], a2ibm_POSIX[];
-extern u_char		casetab[];
-extern const char	*msgfmt;
diff --git a/toolbox/upstream-netbsd/bin/dd/misc.c b/toolbox/upstream-netbsd/bin/dd/misc.c
deleted file mode 100644
index 0fac98b..0000000
--- a/toolbox/upstream-netbsd/bin/dd/misc.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/*	$NetBSD: misc.c,v 1.23 2011/11/07 22:24:23 jym Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993, 1994
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Keith Muller of the University of California, San Diego and Lance
- * Visser of Convex Computer Corporation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)misc.c	8.3 (Berkeley) 4/2/94";
-#else
-__RCSID("$NetBSD: misc.c,v 1.23 2011/11/07 22:24:23 jym Exp $");
-#endif
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/time.h>
-
-#include <err.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <util.h>
-#include <inttypes.h>
-
-#include "dd.h"
-#include "extern.h"
-
-#define	tv2mS(tv) ((tv).tv_sec * 1000LL + ((tv).tv_usec + 500) / 1000)
-
-static void posix_summary(void);
-#ifndef NO_MSGFMT
-static void custom_summary(void);
-static void human_summary(void);
-static void quiet_summary(void);
-
-static void buffer_write(const char *, size_t, int);
-#endif /* NO_MSGFMT */
-
-void
-summary(void)
-{
-
-	if (progress)
-		(void)write(STDERR_FILENO, "\n", 1);
-
-#ifdef NO_MSGFMT
-	return posix_summary();
-#else /* NO_MSGFMT */
-	if (strncmp(msgfmt, "human", sizeof("human")) == 0)
-		return human_summary();
-
-	if (strncmp(msgfmt, "posix", sizeof("posix")) == 0)
-		return posix_summary();
-
-	if (strncmp(msgfmt, "quiet", sizeof("quiet")) == 0)
-		return quiet_summary();
-
-	return custom_summary();
-#endif /* NO_MSGFMT */
-}
-
-static void
-posix_summary(void)
-{
-	char buf[100];
-	int64_t mS;
-	struct timeval tv;
-
-	if (progress)
-		(void)write(STDERR_FILENO, "\n", 1);
-
-	(void)gettimeofday(&tv, NULL);
-	mS = tv2mS(tv) - tv2mS(st.start);
-	if (mS == 0)
-		mS = 1;
-
-	/* Use snprintf(3) so that we don't reenter stdio(3). */
-	(void)snprintf(buf, sizeof(buf),
-	    "%llu+%llu records in\n%llu+%llu records out\n",
-	    (unsigned long long)st.in_full,  (unsigned long long)st.in_part,
-	    (unsigned long long)st.out_full, (unsigned long long)st.out_part);
-	(void)write(STDERR_FILENO, buf, strlen(buf));
-	if (st.swab) {
-		(void)snprintf(buf, sizeof(buf), "%llu odd length swab %s\n",
-		    (unsigned long long)st.swab,
-		    (st.swab == 1) ? "block" : "blocks");
-		(void)write(STDERR_FILENO, buf, strlen(buf));
-	}
-	if (st.trunc) {
-		(void)snprintf(buf, sizeof(buf), "%llu truncated %s\n",
-		    (unsigned long long)st.trunc,
-		    (st.trunc == 1) ? "block" : "blocks");
-		(void)write(STDERR_FILENO, buf, strlen(buf));
-	}
-	if (st.sparse) {
-		(void)snprintf(buf, sizeof(buf), "%llu sparse output %s\n",
-		    (unsigned long long)st.sparse,
-		    (st.sparse == 1) ? "block" : "blocks");
-		(void)write(STDERR_FILENO, buf, strlen(buf));
-	}
-	(void)snprintf(buf, sizeof(buf),
-	    "%llu bytes transferred in %lu.%03d secs (%llu bytes/sec)\n",
-	    (unsigned long long) st.bytes,
-	    (long) (mS / 1000),
-	    (int) (mS % 1000),
-	    (unsigned long long) (st.bytes * 1000LL / mS));
-	(void)write(STDERR_FILENO, buf, strlen(buf));
-}
-
-/* ARGSUSED */
-void
-summaryx(int notused)
-{
-
-	summary();
-}
-
-/* ARGSUSED */
-void
-terminate(int signo)
-{
-
-	summary();
-	(void)raise_default_signal(signo);
-	_exit(127);
-}
-
-#ifndef NO_MSGFMT
-/*
- * Buffer write(2) calls
- */
-static void
-buffer_write(const char *str, size_t size, int flush)
-{
-	static char wbuf[128];
-	static size_t cnt = 0; /* Internal counter to allow wbuf to wrap */
-	
-	unsigned int i;
-
-	for (i = 0; i < size; i++) {
-		if (str != NULL) {
-			wbuf[cnt++] = str[i];
-		}
-		if (cnt >= sizeof(wbuf)) {
-			(void)write(STDERR_FILENO, wbuf, cnt);
-			cnt = 0;
-		}
-	}
-
-	if (flush != 0) {
-		(void)write(STDERR_FILENO, wbuf, cnt);
-		cnt = 0;
-	}
-}
-
-/*
- * Write summary to stderr according to format 'fmt'. If 'enable' is 0, it
- * will not attempt to write anything. Can be used to validate the
- * correctness of the 'fmt' string.
- */
-int
-dd_write_msg(const char *fmt, int enable)
-{
-	char hbuf[7], nbuf[32];
-	const char *ptr;
-	int64_t mS;
-	struct timeval tv;
-
-	(void)gettimeofday(&tv, NULL);
-	mS = tv2mS(tv) - tv2mS(st.start);
-	if (mS == 0)
-		mS = 1;
-
-#define ADDC(c) do { if (enable != 0) buffer_write(&c, 1, 0); } \
-	while (/*CONSTCOND*/0)
-#define ADDS(p) do { if (enable != 0) buffer_write(p, strlen(p), 0); } \
-	while (/*CONSTCOND*/0)
-
-	for (ptr = fmt; *ptr; ptr++) {
-		if (*ptr != '%') {
-			ADDC(*ptr);
-			continue;
-		}
-
- 		switch (*++ptr) {
-		case 'b':
-			(void)snprintf(nbuf, sizeof(nbuf), "%llu",
-			    (unsigned long long)st.bytes);
-			ADDS(nbuf);
-			break;
-		case 'B':
-			if (humanize_number(hbuf, sizeof(hbuf),
-			    st.bytes, "B",
-			    HN_AUTOSCALE, HN_DECIMAL) == -1)
-				warnx("humanize_number (bytes transferred)");
-			ADDS(hbuf);
-			break;
-		case 'e':
-			(void)snprintf(nbuf, sizeof(nbuf), "%llu",
-			    (unsigned long long) (st.bytes * 1000LL / mS));
-			ADDS(nbuf);
-			break;
-		case 'E':
-			if (humanize_number(hbuf, sizeof(hbuf),
-			    st.bytes * 1000LL / mS, "B",
-			    HN_AUTOSCALE, HN_DECIMAL) == -1)
-				warnx("humanize_number (bytes per second)");
-			ADDS(hbuf); ADDS("/sec");
-			break;
-		case 'i':
-			(void)snprintf(nbuf, sizeof(nbuf), "%llu",
-			    (unsigned long long)st.in_part);
-			ADDS(nbuf);
-			break;
-		case 'I':
-			(void)snprintf(nbuf, sizeof(nbuf), "%llu",
-			    (unsigned long long)st.in_full);
-			ADDS(nbuf);
-			break;
-		case 'o':
-			(void)snprintf(nbuf, sizeof(nbuf), "%llu",
-			    (unsigned long long)st.out_part);
-			ADDS(nbuf);
-			break;
-		case 'O':
-			(void)snprintf(nbuf, sizeof(nbuf), "%llu",
-			    (unsigned long long)st.out_full);
-			ADDS(nbuf);
-			break;
-		case 's':
-			(void)snprintf(nbuf, sizeof(nbuf), "%li.%03d",
-			    (long) (mS / 1000), (int) (mS % 1000));
-			ADDS(nbuf);
-			break;
-		case 'p':
-			(void)snprintf(nbuf, sizeof(nbuf), "%llu",
-			    (unsigned long long)st.sparse);
-			ADDS(nbuf);
-			break;
-		case 't':
-			(void)snprintf(nbuf, sizeof(nbuf), "%llu",
-			    (unsigned long long)st.trunc);
-			ADDS(nbuf);
-			break;
-		case 'w':
-			(void)snprintf(nbuf, sizeof(nbuf), "%llu",
-			    (unsigned long long)st.swab);
-			ADDS(nbuf);
-			break;
-		case 'P':
-			ADDS("block");
-			if (st.sparse != 1) ADDS("s");
-			break;
-		case 'T':
-			ADDS("block");
-			if (st.trunc != 1) ADDS("s");
-			break;
-		case 'W':
-			ADDS("block");
-			if (st.swab != 1) ADDS("s");
-			break;
-		case '%':
-			ADDC(*ptr);
-			break;
-		default:
-			if (*ptr == '\0')
-				goto done;
-			errx(EXIT_FAILURE, "unknown specifier '%c' in "
-			    "msgfmt string", *ptr);
-			/* NOTREACHED */
-		}
-	}
-
-done:
-	/* flush buffer */
-	buffer_write(NULL, 0, 1);
-	return 0;
-}
-
-static void
-custom_summary(void)
-{
-
-	dd_write_msg(msgfmt, 1);
-}
-
-static void
-human_summary(void)
-{
-	(void)dd_write_msg("%I+%i records in\n%O+%o records out\n", 1);
-	if (st.swab) {
-		(void)dd_write_msg("%w odd length swab %W\n", 1);
-	}
-	if (st.trunc) {
-		(void)dd_write_msg("%t truncated %T\n", 1);
-	}
-	if (st.sparse) {
-		(void)dd_write_msg("%p sparse output %P\n", 1);
-	}
-	(void)dd_write_msg("%b bytes (%B) transferred in %s secs "
-	    "(%e bytes/sec - %E)\n", 1);
-}
-
-static void
-quiet_summary(void)
-{
-
-	/* stay quiet */
-}
-#endif /* NO_MSGFMT */
diff --git a/toolbox/upstream-netbsd/bin/dd/position.c b/toolbox/upstream-netbsd/bin/dd/position.c
deleted file mode 100644
index 36dd580..0000000
--- a/toolbox/upstream-netbsd/bin/dd/position.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/*	$NetBSD: position.c,v 1.18 2010/11/22 21:04:28 pooka Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993, 1994
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Keith Muller of the University of California, San Diego and Lance
- * Visser of Convex Computer Corporation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)position.c	8.3 (Berkeley) 4/2/94";
-#else
-__RCSID("$NetBSD: position.c,v 1.18 2010/11/22 21:04:28 pooka Exp $");
-#endif
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/mtio.h>
-#include <sys/time.h>
-
-#include <err.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "dd.h"
-#include "extern.h"
-
-/*
- * Position input/output data streams before starting the copy.  Device type
- * dependent.  Seekable devices use lseek, and the rest position by reading.
- * Seeking past the end of file can cause null blocks to be written to the
- * output.
- */
-void
-pos_in(void)
-{
-	int bcnt, cnt, nr, warned;
-
-	/* If not a pipe or tape device, try to seek on it. */
-	if (!(in.flags & (ISPIPE|ISTAPE))) {
-		if (ddop_lseek(in, in.fd,
-		    (off_t)in.offset * (off_t)in.dbsz, SEEK_CUR) == -1) {
-			err(EXIT_FAILURE, "%s", in.name);
-			/* NOTREACHED */
-		}
-		return;
-		/* NOTREACHED */
-	}
-
-	/*
-	 * Read the data.  If a pipe, read until satisfy the number of bytes
-	 * being skipped.  No differentiation for reading complete and partial
-	 * blocks for other devices.
-	 */
-	for (bcnt = in.dbsz, cnt = in.offset, warned = 0; cnt;) {
-		if ((nr = ddop_read(in, in.fd, in.db, bcnt)) > 0) {
-			if (in.flags & ISPIPE) {
-				if (!(bcnt -= nr)) {
-					bcnt = in.dbsz;
-					--cnt;
-				}
-			} else
-				--cnt;
-			continue;
-		}
-
-		if (nr == 0) {
-			if (files_cnt > 1) {
-				--files_cnt;
-				continue;
-			}
-			errx(EXIT_FAILURE, "skip reached end of input");
-			/* NOTREACHED */
-		}
-
-		/*
-		 * Input error -- either EOF with no more files, or I/O error.
-		 * If noerror not set die.  POSIX requires that the warning
-		 * message be followed by an I/O display.
-		 */
-		if (ddflags & C_NOERROR) {
-			if (!warned) {
-
-				warn("%s", in.name);
-				warned = 1;
-				summary();
-			}
-			continue;
-		}
-		err(EXIT_FAILURE, "%s", in.name);
-		/* NOTREACHED */
-	}
-}
-
-void
-pos_out(void)
-{
-	struct mtop t_op;
-	int n;
-	uint64_t cnt;
-
-	/*
-	 * If not a tape, try seeking on the file.  Seeking on a pipe is
-	 * going to fail, but don't protect the user -- they shouldn't
-	 * have specified the seek operand.
-	 */
-	if (!(out.flags & ISTAPE)) {
-		if (ddop_lseek(out, out.fd,
-		    (off_t)out.offset * (off_t)out.dbsz, SEEK_SET) == -1)
-			err(EXIT_FAILURE, "%s", out.name);
-			/* NOTREACHED */
-		return;
-	}
-
-	/* If no read access, try using mtio. */
-	if (out.flags & NOREAD) {
-		t_op.mt_op = MTFSR;
-		t_op.mt_count = out.offset;
-
-		if (ddop_ioctl(out, out.fd, MTIOCTOP, &t_op) < 0)
-			err(EXIT_FAILURE, "%s", out.name);
-			/* NOTREACHED */
-		return;
-	}
-
-	/* Read it. */
-	for (cnt = 0; cnt < out.offset; ++cnt) {
-		if ((n = ddop_read(out, out.fd, out.db, out.dbsz)) > 0)
-			continue;
-
-		if (n < 0)
-			err(EXIT_FAILURE, "%s", out.name);
-			/* NOTREACHED */
-
-		/*
-		 * If reach EOF, fill with NUL characters; first, back up over
-		 * the EOF mark.  Note, cnt has not yet been incremented, so
-		 * the EOF read does not count as a seek'd block.
-		 */
-		t_op.mt_op = MTBSR;
-		t_op.mt_count = 1;
-		if (ddop_ioctl(out, out.fd, MTIOCTOP, &t_op) == -1)
-			err(EXIT_FAILURE, "%s", out.name);
-			/* NOTREACHED */
-
-		while (cnt++ < out.offset)
-			if ((uint64_t)(n = bwrite(&out,
-			    out.db, out.dbsz)) != out.dbsz)
-				err(EXIT_FAILURE, "%s", out.name);
-				/* NOTREACHED */
-		break;
-	}
-}
diff --git a/toolbox/upstream-netbsd/include/namespace.h b/toolbox/upstream-netbsd/include/namespace.h
deleted file mode 100644
index e69de29..0000000
--- a/toolbox/upstream-netbsd/include/namespace.h
+++ /dev/null
diff --git a/toolbox/upstream-netbsd/include/sys/extattr.h b/toolbox/upstream-netbsd/include/sys/extattr.h
deleted file mode 100644
index e69de29..0000000
--- a/toolbox/upstream-netbsd/include/sys/extattr.h
+++ /dev/null
diff --git a/toolbox/upstream-netbsd/include/util.h b/toolbox/upstream-netbsd/include/util.h
deleted file mode 100644
index e69de29..0000000
--- a/toolbox/upstream-netbsd/include/util.h
+++ /dev/null
diff --git a/toolbox/upstream-netbsd/lib/libc/gen/getbsize.c b/toolbox/upstream-netbsd/lib/libc/gen/getbsize.c
deleted file mode 100644
index a9ce2c1..0000000
--- a/toolbox/upstream-netbsd/lib/libc/gen/getbsize.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*	$NetBSD: getbsize.c,v 1.17 2012/06/25 22:32:43 abs Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)getbsize.c	8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: getbsize.c,v 1.17 2012/06/25 22:32:43 abs Exp $");
-#endif
-#endif /* not lint */
-
-#include "namespace.h"
-
-#include <assert.h>
-#include <err.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef __weak_alias
-__weak_alias(getbsize,_getbsize)
-#endif
-
-char *
-getbsize(int *headerlenp, long *blocksizep)
-{
-	static char header[20];
-	long n, max, mul, blocksize;
-	char *ep, *p;
-	const char *form;
-
-#define	KB	(1024L)
-#define	MB	(1024L * 1024L)
-#define	GB	(1024L * 1024L * 1024L)
-#define	MAXB	GB		/* No tera, peta, nor exa. */
-	form = "";
-	if ((p = getenv("BLOCKSIZE")) != NULL && *p != '\0') {
-		if ((n = strtol(p, &ep, 10)) < 0)
-			goto underflow;
-		if (n == 0)
-			n = 1;
-		if (*ep && ep[1])
-			goto fmterr;
-		switch (*ep) {
-		case 'G': case 'g':
-			form = "G";
-			max = MAXB / GB;
-			mul = GB;
-			break;
-		case 'K': case 'k':
-			form = "K";
-			max = MAXB / KB;
-			mul = KB;
-			break;
-		case 'M': case 'm':
-			form = "M";
-			max = MAXB / MB;
-			mul = MB;
-			break;
-		case '\0':
-			max = MAXB;
-			mul = 1;
-			break;
-		default:
-fmterr:			warnx("%s: unknown blocksize", p);
-			n = 512;
-			mul = 1;
-			max = 0;
-			break;
-		}
-		if (n > max) {
-			warnx("maximum blocksize is %ldG", MAXB / GB);
-			n = max;
-		}
-		if ((blocksize = n * mul) < 512) {
-underflow:		warnx("%s: minimum blocksize is 512", p);
-			form = "";
-			blocksize = n = 512;
-		}
-	} else
-		blocksize = n = 512;
-
-	if (headerlenp)
-		*headerlenp =
-		    snprintf(header, sizeof(header), "%ld%s-blocks", n, form);
-	if (blocksizep)
-		*blocksizep = blocksize;
-	return (header);
-}
diff --git a/toolbox/upstream-netbsd/lib/libc/gen/humanize_number.c b/toolbox/upstream-netbsd/lib/libc/gen/humanize_number.c
deleted file mode 100644
index 533560f..0000000
--- a/toolbox/upstream-netbsd/lib/libc/gen/humanize_number.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*	$NetBSD: humanize_number.c,v 1.16 2012/03/17 20:01:14 christos Exp $	*/
-
-/*
- * Copyright (c) 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
- * NASA Ames Research Center, by Luke Mewburn and by Tomas Svensson.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: humanize_number.c,v 1.16 2012/03/17 20:01:14 christos Exp $");
-#endif /* LIBC_SCCS and not lint */
-
-#include "namespace.h"
-#include <assert.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <locale.h>
-
-int
-humanize_number(char *buf, size_t len, int64_t bytes,
-    const char *suffix, int scale, int flags)
-{
-	const char *prefixes, *sep;
-	int	b, r, s1, s2, sign;
-	int64_t	divisor, max, post = 1;
-	size_t	i, baselen, maxscale;
-
-	_DIAGASSERT(buf != NULL);
-	_DIAGASSERT(suffix != NULL);
-	_DIAGASSERT(scale >= 0);
-
-	if (flags & HN_DIVISOR_1000) {
-		/* SI for decimal multiplies */
-		divisor = 1000;
-		if (flags & HN_B)
-			prefixes = "B\0k\0M\0G\0T\0P\0E";
-		else
-			prefixes = "\0\0k\0M\0G\0T\0P\0E";
-	} else {
-		/*
-		 * binary multiplies
-		 * XXX IEC 60027-2 recommends Ki, Mi, Gi...
-		 */
-		divisor = 1024;
-		if (flags & HN_B)
-			prefixes = "B\0K\0M\0G\0T\0P\0E";
-		else
-			prefixes = "\0\0K\0M\0G\0T\0P\0E";
-	}
-
-#define	SCALE2PREFIX(scale)	(&prefixes[(scale) << 1])
-	maxscale = 7;
-
-	if ((size_t)scale >= maxscale &&
-	    (scale & (HN_AUTOSCALE | HN_GETSCALE)) == 0)
-		return (-1);
-
-	if (buf == NULL || suffix == NULL)
-		return (-1);
-
-	if (len > 0)
-		buf[0] = '\0';
-	if (bytes < 0) {
-		sign = -1;
-		baselen = 3;		/* sign, digit, prefix */
-		if (-bytes < INT64_MAX / 100)
-			bytes *= -100;
-		else {
-			bytes = -bytes;
-			post = 100;
-			baselen += 2;
-		}
-	} else {
-		sign = 1;
-		baselen = 2;		/* digit, prefix */
-		if (bytes < INT64_MAX / 100)
-			bytes *= 100;
-		else {
-			post = 100;
-			baselen += 2;
-		}
-	}
-	if (flags & HN_NOSPACE)
-		sep = "";
-	else {
-		sep = " ";
-		baselen++;
-	}
-	baselen += strlen(suffix);
-
-	/* Check if enough room for `x y' + suffix + `\0' */
-	if (len < baselen + 1)
-		return (-1);
-
-	if (scale & (HN_AUTOSCALE | HN_GETSCALE)) {
-		/* See if there is additional columns can be used. */
-		for (max = 100, i = len - baselen; i-- > 0;)
-			max *= 10;
-
-		/*
-		 * Divide the number until it fits the given column.
-		 * If there will be an overflow by the rounding below,
-		 * divide once more.
-		 */
-		for (i = 0; bytes >= max - 50 && i < maxscale; i++)
-			bytes /= divisor;
-
-		if (scale & HN_GETSCALE) {
-			_DIAGASSERT(__type_fit(int, i));
-			return (int)i;
-		}
-	} else
-		for (i = 0; i < (size_t)scale && i < maxscale; i++)
-			bytes /= divisor;
-	bytes *= post;
-
-	/* If a value <= 9.9 after rounding and ... */
-	if (bytes < 995 && i > 0 && flags & HN_DECIMAL) {
-		/* baselen + \0 + .N */
-		if (len < baselen + 1 + 2)
-			return (-1);
-		b = ((int)bytes + 5) / 10;
-		s1 = b / 10;
-		s2 = b % 10;
-		r = snprintf(buf, len, "%d%s%d%s%s%s",
-		    sign * s1, localeconv()->decimal_point, s2,
-		    sep, SCALE2PREFIX(i), suffix);
-	} else
-		r = snprintf(buf, len, "%" PRId64 "%s%s%s",
-		    sign * ((bytes + 50) / 100),
-		    sep, SCALE2PREFIX(i), suffix);
-
-	return (r);
-}
diff --git a/toolbox/upstream-netbsd/lib/libc/stdlib/strsuftoll.c b/toolbox/upstream-netbsd/lib/libc/stdlib/strsuftoll.c
deleted file mode 100644
index 80fc52f..0000000
--- a/toolbox/upstream-netbsd/lib/libc/stdlib/strsuftoll.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*	$NetBSD: strsuftoll.c,v 1.9 2011/10/22 22:08:47 christos Exp $	*/
-/*-
- * Copyright (c) 2001-2002,2004 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Luke Mewburn.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-/*-
- * Copyright (c) 1991, 1993, 1994
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Keith Muller of the University of California, San Diego and Lance
- * Visser of Convex Computer Corporation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if HAVE_NBTOOL_CONFIG_H
-#include "nbtool_config.h"
-#endif
-
-#include <sys/cdefs.h>
-
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: strsuftoll.c,v 1.9 2011/10/22 22:08:47 christos Exp $");
-#endif /* LIBC_SCCS and not lint */
-
-#ifdef _LIBC
-#include "namespace.h"
-#endif
-
-#if !HAVE_STRSUFTOLL
-
-#include <sys/types.h>
-#include <sys/time.h>
-
-#include <assert.h>
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef _LIBC
-# ifdef __weak_alias
-__weak_alias(strsuftoll, _strsuftoll)
-__weak_alias(strsuftollx, _strsuftollx)
-# endif
-#endif /* LIBC */
-
-/*
- * Convert an expression of the following forms to a (u)int64_t.
- * 	1) A positive decimal number.
- *	2) A positive decimal number followed by a b (mult by 512).
- *	3) A positive decimal number followed by a k (mult by 1024).
- *	4) A positive decimal number followed by a m (mult by 1048576).
- *	5) A positive decimal number followed by a g (mult by 1073741824).
- *	6) A positive decimal number followed by a t (mult by 1099511627776).
- *	7) A positive decimal number followed by a w (mult by sizeof int)
- *	8) Two or more positive decimal numbers (with/without k,b or w).
- *	   separated by x (also * for backwards compatibility), specifying
- *	   the product of the indicated values.
- * Returns the result upon successful conversion, or exits with an
- * appropriate error.
- * 
- */
-/* LONGLONG */
-long long
-strsuftoll(const char *desc, const char *val,
-    long long min, long long max)
-{
-	long long result;
-	char	errbuf[100];
-
-	result = strsuftollx(desc, val, min, max, errbuf, sizeof(errbuf));
-	if (*errbuf != '\0')
-		errx(EXIT_FAILURE, "%s", errbuf);
-	return result;
-}
-
-/*
- * As strsuftoll(), but returns the error message into the provided buffer
- * rather than exiting with it.
- */
-/* LONGLONG */
-static long long
-__strsuftollx(const char *desc, const char *val,
-    long long min, long long max, char *ebuf, size_t ebuflen, size_t depth)
-{
-	long long num, t;
-	char	*expr;
-
-	_DIAGASSERT(desc != NULL);
-	_DIAGASSERT(val != NULL);
-	_DIAGASSERT(ebuf != NULL);
-
-	if (depth > 16) {
-		snprintf(ebuf, ebuflen, "%s: Recursion limit exceeded", desc);
-		return 0;
-	}
-
-	while (isspace((unsigned char)*val))	/* Skip leading space */
-		val++;
-
-	errno = 0;
-	num = strtoll(val, &expr, 10);
-	if (errno == ERANGE)
-		goto erange;			/* Overflow */
-
-	if (expr == val)			/* No digits */
-		goto badnum;
-
-	switch (*expr) {
-	case 'b':
-		t = num;
-		num *= 512;			/* 1 block */
-		if (t > num)
-			goto erange;
-		++expr;
-		break;
-	case 'k':
-		t = num;
-		num *= 1024;			/* 1 kibibyte */
-		if (t > num)
-			goto erange;
-		++expr;
-		break;
-	case 'm':
-		t = num;
-		num *= 1048576;			/* 1 mebibyte */
-		if (t > num)
-			goto erange;
-		++expr;
-		break;
-	case 'g':
-		t = num;
-		num *= 1073741824;		/* 1 gibibyte */
-		if (t > num)
-			goto erange;
-		++expr;
-		break;
-	case 't':
-		t = num;
-		num *= 1099511627776LL;		/* 1 tebibyte */
-		if (t > num)
-			goto erange;
-		++expr;
-		break;
-	case 'w':
-		t = num;
-		num *= sizeof(int);		/* 1 word */
-		if (t > num)
-			goto erange;
-		++expr;
-		break;
-	}
-
-	switch (*expr) {
-	case '\0':
-		break;
-	case '*':				/* Backward compatible */
-	case 'x':
-		t = num;
-		num *= __strsuftollx(desc, expr + 1, min, max, ebuf, ebuflen,
-			depth + 1);
-		if (*ebuf != '\0')
-			return 0;
-		if (t > num) {
- erange:	 	
-			errno = ERANGE;
-			snprintf(ebuf, ebuflen, "%s: %s", desc, strerror(errno));
-			return 0;
-		}
-		break;
-	default:
- badnum:
-		snprintf(ebuf, ebuflen, "%s `%s': illegal number", desc, val);
-		return 0;
-	}
-	if (num < min) {
-		/* LONGLONG */
-		snprintf(ebuf, ebuflen, "%s %lld is less than %lld.",
-		    desc, (long long)num, (long long)min);
-		return 0;
-	}
-	if (num > max) {
-		/* LONGLONG */
-		snprintf(ebuf, ebuflen, "%s %lld is greater than %lld.",
-		    desc, (long long)num, (long long)max);
-		return 0;
-	}
-	*ebuf = '\0';
-	return num;
-}
-
-long long
-strsuftollx(const char *desc, const char *val,
-    long long min, long long max, char *ebuf, size_t ebuflen)
-{
-	return __strsuftollx(desc, val, min, max, ebuf, ebuflen, 0);
-}
-#endif /* !HAVE_STRSUFTOLL */
diff --git a/toolbox/upstream-netbsd/lib/libc/string/swab.c b/toolbox/upstream-netbsd/lib/libc/string/swab.c
deleted file mode 100644
index 392b186..0000000
--- a/toolbox/upstream-netbsd/lib/libc/string/swab.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*	$NetBSD: swab.c,v 1.18 2011/01/04 17:14:07 martin Exp $	*/
-
-/*
- * Copyright (c) 1988, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jeffrey Mogul.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)swab.c	8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: swab.c,v 1.18 2011/01/04 17:14:07 martin Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
-
-#include <assert.h>
-#include <unistd.h>
-
-void
-swab(const void * __restrict from, void * __restrict to, ssize_t len)
-{
-	char temp;
-	const char *fp;
-	char *tp;
-
-	if (len <= 1)
-		return;
-
-	_DIAGASSERT(from != NULL);
-	_DIAGASSERT(to != NULL);
-
-	len /= 2;
-	fp = (const char *)from;
-	tp = (char *)to;
-#define	STEP	temp = *fp++,*tp++ = *fp++,*tp++ = temp
-
-	if (__predict_false(len == 1)) {
-		STEP;
-		return;
-	}
-
-	/* round to multiple of 8 */
-	while ((--len % 8) != 0)
-		STEP;
-	len /= 8;
-	if (len == 0)
-		return;
-	while (len-- != 0) {
-		STEP; STEP; STEP; STEP;
-		STEP; STEP; STEP; STEP;
-	}
-}
diff --git a/toolbox/upstream-netbsd/lib/libutil/raise_default_signal.c b/toolbox/upstream-netbsd/lib/libutil/raise_default_signal.c
deleted file mode 100644
index 50cffd4..0000000
--- a/toolbox/upstream-netbsd/lib/libutil/raise_default_signal.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*	$NetBSD: raise_default_signal.c,v 1.3 2008/04/28 20:23:03 martin Exp $	 */
-
-/*-
- * Copyright (c) 2007 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Luke Mewburn.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if HAVE_NBTOOL_CONFIG_H
-#include "nbtool_config.h"
-#endif
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: raise_default_signal.c,v 1.3 2008/04/28 20:23:03 martin Exp $");
-#endif
-
-#include <errno.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <util.h>
-
-#if ! HAVE_RAISE_DEFAULT_SIGNAL
-/*
- * raise_default_signal sig
- *	Raise the default signal handler for sig, by
- *	- block all signals
- *	- set the signal handler to SIG_DFL
- *	- raise the signal
- *	- unblock the signal to deliver it
- *
- *	The original signal mask and signal handler is restored on exit
- *	(whether successful or not).
- *
- *	Returns 0 on success, or -1 on failure with errno set to
- *	on of the values for sigemptyset(), sigaddset(), sigprocmask(),
- *	sigaction(), or raise().
- */
-int
-raise_default_signal(int sig)
-{
-	struct sigaction origact, act;
-	sigset_t origmask, fullmask, mask;
-	int retval, oerrno;
-
-	retval = -1;
-
-		/* Setup data structures */
-		/* XXX memset(3) isn't async-safe according to signal(7) */
-	(void)memset(&act, 0, sizeof(act));
-	act.sa_handler = SIG_DFL;
-	act.sa_flags = 0;
-	if ((sigemptyset(&act.sa_mask) == -1) ||
-	    (sigfillset(&fullmask) == -1) ||
-	    (sigemptyset(&mask) == -1) ||
-	    (sigaddset(&mask, sig) == -1))
-		goto restore_none;
-
-		/* Block all signals */
-	if (sigprocmask(SIG_BLOCK, &fullmask, &origmask) == -1)
-		goto restore_none;
-		/* (use 'goto restore_mask' to restore state) */
-
-		/* Enable the SIG_DFL handler */
-	if (sigaction(sig, &act, &origact) == -1)
-		goto restore_mask;
-		/* (use 'goto restore_act' to restore state) */
-
-		/* Raise the signal, and unblock the signal to deliver it */
-	if ((raise(sig) == -1) ||
-	    (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1))
-		goto restore_act;
-
-		/* Flag successful raise() */
-	retval = 0;
-
-		/* Restore the original handler */
- restore_act:
-	oerrno = errno;
-	(void)sigaction(sig, &origact, NULL);
-	errno = oerrno;
-
-		/* Restore the original mask */
- restore_mask:
-	oerrno = errno;
-	(void)sigprocmask(SIG_SETMASK, &origmask, NULL);
-	errno = oerrno;
-
- restore_none:
-	return retval;
-}
-
-#endif	/* ! HAVE_RAISE_DEFAULT_SIGNAL */
diff --git a/toolbox/upstream-netbsd/usr.bin/grep/fastgrep.c b/toolbox/upstream-netbsd/usr.bin/grep/fastgrep.c
deleted file mode 100644
index 2fcd864..0000000
--- a/toolbox/upstream-netbsd/usr.bin/grep/fastgrep.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/*	$OpenBSD: util.c,v 1.36 2007/10/02 17:59:18 otto Exp $	*/
-/*	$FreeBSD: head/usr.bin/grep/fastgrep.c 211496 2010-08-19 09:28:59Z des $ */
-
-/*-
- * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
- * Copyright (C) 2008 Gabor Kovesdan <gabor@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * XXX: This file is a speed up for grep to cover the defects of the
- * regex library.  These optimizations should practically be implemented
- * there keeping this code clean.  This is a future TODO, but for the
- * meantime, we need to use this workaround.
- */
-
-#if HAVE_NBTOOL_CONFIG_H
-#include "nbtool_config.h"
-#endif
-
-#include <sys/cdefs.h>
-__RCSID("$NetBSD: fastgrep.c,v 1.5 2011/04/18 03:27:40 joerg Exp $");
-
-#include <limits.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <wchar.h>
-#include <wctype.h>
-
-#include "grep.h"
-
-static inline int	grep_cmp(const unsigned char *, const unsigned char *, size_t);
-static inline void	grep_revstr(unsigned char *, int);
-
-void
-fgrepcomp(fastgrep_t *fg, const char *pat)
-{
-	unsigned int i;
-
-	/* Initialize. */
-	fg->len = strlen(pat);
-	fg->bol = false;
-	fg->eol = false;
-	fg->reversed = false;
-
-	fg->pattern = (unsigned char *)grep_strdup(pat);
-
-	/* Preprocess pattern. */
-	for (i = 0; i <= UCHAR_MAX; i++)
-		fg->qsBc[i] = fg->len;
-	for (i = 1; i < fg->len; i++)
-		fg->qsBc[fg->pattern[i]] = fg->len - i;
-}
-
-/*
- * Returns: -1 on failure, 0 on success
- */
-int
-fastcomp(fastgrep_t *fg, const char *pat)
-{
-	unsigned int i;
-	int firstHalfDot = -1;
-	int firstLastHalfDot = -1;
-	int hasDot = 0;
-	int lastHalfDot = 0;
-	int shiftPatternLen;
-
-	/* Initialize. */
-	fg->len = strlen(pat);
-	fg->bol = false;
-	fg->eol = false;
-	fg->reversed = false;
-	fg->word = wflag;
-
-	/* Remove end-of-line character ('$'). */
-	if (fg->len > 0 && pat[fg->len - 1] == '$') {
-		fg->eol = true;
-		fg->len--;
-	}
-
-	/* Remove beginning-of-line character ('^'). */
-	if (pat[0] == '^') {
-		fg->bol = true;
-		fg->len--;
-		pat++;
-	}
-
-	if (fg->len >= 14 &&
-	    memcmp(pat, "[[:<:]]", 7) == 0 &&
-	    memcmp(pat + fg->len - 7, "[[:>:]]", 7) == 0) {
-		fg->len -= 14;
-		pat += 7;
-		/* Word boundary is handled separately in util.c */
-		fg->word = true;
-	}
-
-	/*
-	 * pat has been adjusted earlier to not include '^', '$' or
-	 * the word match character classes at the beginning and ending
-	 * of the string respectively.
-	 */
-	fg->pattern = grep_malloc(fg->len + 1);
-	memcpy(fg->pattern, pat, fg->len);
-	fg->pattern[fg->len] = '\0';
-
-	/* Look for ways to cheat...er...avoid the full regex engine. */
-	for (i = 0; i < fg->len; i++) {
-		/* Can still cheat? */
-		if (fg->pattern[i] == '.') {
-			hasDot = i;
-			if (i < fg->len / 2) {
-				if (firstHalfDot < 0)
-					/* Closest dot to the beginning */
-					firstHalfDot = i;
-			} else {
-				/* Closest dot to the end of the pattern. */
-				lastHalfDot = i;
-				if (firstLastHalfDot < 0)
-					firstLastHalfDot = i;
-			}
-		} else {
-			/* Free memory and let others know this is empty. */
-			free(fg->pattern);
-			fg->pattern = NULL;
-			return (-1);
-		}
-	}
-
-	/*
-	 * Determine if a reverse search would be faster based on the placement
-	 * of the dots.
-	 */
-	if ((!(lflag || cflag)) && ((!(fg->bol || fg->eol)) &&
-	    ((lastHalfDot) && ((firstHalfDot < 0) ||
-	    ((fg->len - (lastHalfDot + 1)) < (size_t)firstHalfDot)))) &&
-	    !oflag && !color) {
-		fg->reversed = true;
-		hasDot = fg->len - (firstHalfDot < 0 ?
-		    firstLastHalfDot : firstHalfDot) - 1;
-		grep_revstr(fg->pattern, fg->len);
-	}
-
-	/*
-	 * Normal Quick Search would require a shift based on the position the
-	 * next character after the comparison is within the pattern.  With
-	 * wildcards, the position of the last dot effects the maximum shift
-	 * distance.
-	 * The closer to the end the wild card is the slower the search.  A
-	 * reverse version of this algorithm would be useful for wildcards near
-	 * the end of the string.
-	 *
-	 * Examples:
-	 * Pattern	Max shift
-	 * -------	---------
-	 * this		5
-	 * .his		4
-	 * t.is		3
-	 * th.s		2
-	 * thi.		1
-	 */
-
-	/* Adjust the shift based on location of the last dot ('.'). */
-	shiftPatternLen = fg->len - hasDot;
-
-	/* Preprocess pattern. */
-	for (i = 0; i <= (signed)UCHAR_MAX; i++)
-		fg->qsBc[i] = shiftPatternLen;
-	for (i = hasDot + 1; i < fg->len; i++) {
-		fg->qsBc[fg->pattern[i]] = fg->len - i;
-	}
-
-	/*
-	 * Put pattern back to normal after pre-processing to allow for easy
-	 * comparisons later.
-	 */
-	if (fg->reversed)
-		grep_revstr(fg->pattern, fg->len);
-
-	return (0);
-}
-
-int
-grep_search(fastgrep_t *fg, const unsigned char *data, size_t len, regmatch_t *pmatch)
-{
-	unsigned int j;
-	int ret = REG_NOMATCH;
-
-	if (pmatch->rm_so == (ssize_t)len)
-		return (ret);
-
-	if (fg->bol && pmatch->rm_so != 0) {
-		pmatch->rm_so = len;
-		pmatch->rm_eo = len;
-		return (ret);
-	}
-
-	/* No point in going farther if we do not have enough data. */
-	if (len < fg->len)
-		return (ret);
-
-	/* Only try once at the beginning or ending of the line. */
-	if (fg->bol || fg->eol) {
-		/* Simple text comparison. */
-		/* Verify data is >= pattern length before searching on it. */
-		if (len >= fg->len) {
-			/* Determine where in data to start search at. */
-			j = fg->eol ? len - fg->len : 0;
-			if (!((fg->bol && fg->eol) && (len != fg->len)))
-				if (grep_cmp(fg->pattern, data + j,
-				    fg->len) == -1) {
-					pmatch->rm_so = j;
-					pmatch->rm_eo = j + fg->len;
-						ret = 0;
-				}
-		}
-	} else if (fg->reversed) {
-		/* Quick Search algorithm. */
-		j = len;
-		do {
-			if (grep_cmp(fg->pattern, data + j - fg->len,
-				fg->len) == -1) {
-				pmatch->rm_so = j - fg->len;
-				pmatch->rm_eo = j;
-				ret = 0;
-				break;
-			}
-			/* Shift if within bounds, otherwise, we are done. */
-			if (j == fg->len)
-				break;
-			j -= fg->qsBc[data[j - fg->len - 1]];
-		} while (j >= fg->len);
-	} else {
-		/* Quick Search algorithm. */
-		j = pmatch->rm_so;
-		do {
-			if (grep_cmp(fg->pattern, data + j, fg->len) == -1) {
-				pmatch->rm_so = j;
-				pmatch->rm_eo = j + fg->len;
-				ret = 0;
-				break;
-			}
-
-			/* Shift if within bounds, otherwise, we are done. */
-			if (j + fg->len == len)
-				break;
-			else
-				j += fg->qsBc[data[j + fg->len]];
-		} while (j <= (len - fg->len));
-	}
-
-	return (ret);
-}
-
-/*
- * Returns:	i >= 0 on failure (position that it failed)
- *		-1 on success
- */
-static inline int
-grep_cmp(const unsigned char *pat, const unsigned char *data, size_t len)
-{
-	size_t size;
-	wchar_t *wdata, *wpat;
-	unsigned int i;
-
-	if (iflag) {
-		if ((size = mbstowcs(NULL, (const char *)data, 0)) ==
-		    ((size_t) - 1))
-			return (-1);
-
-		wdata = grep_malloc(size * sizeof(wint_t));
-
-		if (mbstowcs(wdata, (const char *)data, size) ==
-		    ((size_t) - 1))
-			return (-1);
-
-		if ((size = mbstowcs(NULL, (const char *)pat, 0)) ==
-		    ((size_t) - 1))
-			return (-1);
-
-		wpat = grep_malloc(size * sizeof(wint_t));
-
-		if (mbstowcs(wpat, (const char *)pat, size) == ((size_t) - 1))
-			return (-1);
-		for (i = 0; i < len; i++) {
-			if ((towlower(wpat[i]) == towlower(wdata[i])) ||
-			    ((grepbehave != GREP_FIXED) && wpat[i] == L'.'))
-				continue;
-			free(wpat);
-			free(wdata);
-				return (i);
-		}
-	} else {
-		for (i = 0; i < len; i++) {
-			if ((pat[i] == data[i]) || ((grepbehave != GREP_FIXED) &&
-			    pat[i] == '.'))
-				continue;
-			return (i);
-		}
-	}
-	return (-1);
-}
-
-static inline void
-grep_revstr(unsigned char *str, int len)
-{
-	int i;
-	char c;
-
-	for (i = 0; i < len / 2; i++) {
-		c = str[i];
-		str[i] = str[len - i - 1];
-		str[len - i - 1] = c;
-	}
-}
diff --git a/toolbox/upstream-netbsd/usr.bin/grep/file.c b/toolbox/upstream-netbsd/usr.bin/grep/file.c
deleted file mode 100644
index cf4a0fa..0000000
--- a/toolbox/upstream-netbsd/usr.bin/grep/file.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/*	$NetBSD: file.c,v 1.7 2011/04/18 22:46:48 joerg Exp $	*/
-/*	$FreeBSD: head/usr.bin/grep/file.c 211496 2010-08-19 09:28:59Z des $	*/
-/*	$OpenBSD: file.c,v 1.11 2010/07/02 20:48:48 nicm Exp $	*/
-
-/*-
- * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
- * Copyright (C) 2008-2010 Gabor Kovesdan <gabor@FreeBSD.org>
- * Copyright (C) 2010 Dimitry Andric <dimitry@andric.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if HAVE_NBTOOL_CONFIG_H
-#include "nbtool_config.h"
-#endif
-
-#include <sys/cdefs.h>
-__RCSID("$NetBSD: file.c,v 1.7 2011/04/18 22:46:48 joerg Exp $");
-
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#ifndef __ANDROID__
-#include <bzlib.h>
-#endif
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <wchar.h>
-#include <wctype.h>
-#ifndef __ANDROID__
-#include <zlib.h>
-#endif
-
-#include "grep.h"
-
-#define	MAXBUFSIZ	(32 * 1024)
-#define	LNBUFBUMP	80
-
-#ifndef __ANDROID__
-static gzFile gzbufdesc;
-static BZFILE* bzbufdesc;
-#endif
-
-static unsigned char buffer[MAXBUFSIZ];
-static unsigned char *bufpos;
-static size_t bufrem;
-
-static unsigned char *lnbuf;
-static size_t lnbuflen;
-
-static inline int
-grep_refill(struct file *f)
-{
-	ssize_t nr;
-#ifndef __ANDROID__
-	int bzerr;
-#endif
-
-	bufpos = buffer;
-	bufrem = 0;
-
-#ifndef __ANDROID__
-	if (filebehave == FILE_GZIP)
-		nr = gzread(gzbufdesc, buffer, MAXBUFSIZ);
-	else if (filebehave == FILE_BZIP && bzbufdesc != NULL) {
-		nr = BZ2_bzRead(&bzerr, bzbufdesc, buffer, MAXBUFSIZ);
-		switch (bzerr) {
-		case BZ_OK:
-		case BZ_STREAM_END:
-			/* No problem, nr will be okay */
-			break;
-		case BZ_DATA_ERROR_MAGIC:
-			/*
-			 * As opposed to gzread(), which simply returns the
-			 * plain file data, if it is not in the correct
-			 * compressed format, BZ2_bzRead() instead aborts.
-			 *
-			 * So, just restart at the beginning of the file again,
-			 * and use plain reads from now on.
-			 */
-			BZ2_bzReadClose(&bzerr, bzbufdesc);
-			bzbufdesc = NULL;
-			if (lseek(f->fd, 0, SEEK_SET) == -1)
-				return (-1);
-			nr = read(f->fd, buffer, MAXBUFSIZ);
-			break;
-		default:
-			/* Make sure we exit with an error */
-			nr = -1;
-		}
-	} else
-#endif
-		nr = read(f->fd, buffer, MAXBUFSIZ);
-
-	if (nr < 0)
-		return (-1);
-
-	bufrem = nr;
-	return (0);
-}
-
-static inline int
-grep_lnbufgrow(size_t newlen)
-{
-
-	if (lnbuflen < newlen) {
-		lnbuf = grep_realloc(lnbuf, newlen);
-		lnbuflen = newlen;
-	}
-
-	return (0);
-}
-
-char *
-grep_fgetln(struct file *f, size_t *lenp)
-{
-	unsigned char *p;
-	char *ret;
-	size_t len;
-	size_t off;
-	ptrdiff_t diff;
-
-	/* Fill the buffer, if necessary */
-	if (bufrem == 0 && grep_refill(f) != 0)
-		goto error;
-
-	if (bufrem == 0) {
-		/* Return zero length to indicate EOF */
-		*lenp = 0;
-		return ((char *)bufpos);
-	}
-
-	/* Look for a newline in the remaining part of the buffer */
-	if ((p = memchr(bufpos, line_sep, bufrem)) != NULL) {
-		++p; /* advance over newline */
-		ret = (char *)bufpos;
-		len = p - bufpos;
-		bufrem -= len;
-		bufpos = p;
-		*lenp = len;
-		return (ret);
-	}
-
-	/* We have to copy the current buffered data to the line buffer */
-	for (len = bufrem, off = 0; ; len += bufrem) {
-		/* Make sure there is room for more data */
-		if (grep_lnbufgrow(len + LNBUFBUMP))
-			goto error;
-		memcpy(lnbuf + off, bufpos, len - off);
-		off = len;
-		if (grep_refill(f) != 0)
-			goto error;
-		if (bufrem == 0)
-			/* EOF: return partial line */
-			break;
-		if ((p = memchr(bufpos, line_sep, bufrem)) == NULL)
-			continue;
-		/* got it: finish up the line (like code above) */
-		++p;
-		diff = p - bufpos;
-		len += diff;
-		if (grep_lnbufgrow(len))
-		    goto error;
-		memcpy(lnbuf + off, bufpos, diff);
-		bufrem -= diff;
-		bufpos = p;
-		break;
-	}
-	*lenp = len;
-	return ((char *)lnbuf);
-
-error:
-	*lenp = 0;
-	return (NULL);
-}
-
-static inline struct file *
-grep_file_init(struct file *f)
-{
-
-#ifndef __ANDROID__
-	if (filebehave == FILE_GZIP &&
-	    (gzbufdesc = gzdopen(f->fd, "r")) == NULL)
-		goto error;
-
-	if (filebehave == FILE_BZIP &&
-	    (bzbufdesc = BZ2_bzdopen(f->fd, "r")) == NULL)
-		goto error;
-#endif
-
-	/* Fill read buffer, also catches errors early */
-	if (grep_refill(f) != 0)
-		goto error;
-
-	/* Check for binary stuff, if necessary */
-	if (!nulldataflag && binbehave != BINFILE_TEXT &&
-	    memchr(bufpos, '\0', bufrem) != NULL)
-		f->binary = true;
-
-	return (f);
-error:
-	close(f->fd);
-	free(f);
-	return (NULL);
-}
-
-/*
- * Opens a file for processing.
- */
-struct file *
-grep_open(const char *path)
-{
-	struct file *f;
-
-	f = grep_malloc(sizeof *f);
-	memset(f, 0, sizeof *f);
-	if (path == NULL) {
-		/* Processing stdin implies --line-buffered. */
-		lbflag = true;
-		f->fd = STDIN_FILENO;
-	} else if ((f->fd = open(path, O_RDONLY)) == -1) {
-		free(f);
-		return (NULL);
-	}
-
-	return (grep_file_init(f));
-}
-
-/*
- * Closes a file.
- */
-void
-grep_close(struct file *f)
-{
-
-	close(f->fd);
-
-	/* Reset read buffer and line buffer */
-	bufpos = buffer;
-	bufrem = 0;
-
-	free(lnbuf);
-	lnbuf = NULL;
-	lnbuflen = 0;
-}
diff --git a/toolbox/upstream-netbsd/usr.bin/grep/grep.c b/toolbox/upstream-netbsd/usr.bin/grep/grep.c
deleted file mode 100644
index 1ea6ed3..0000000
--- a/toolbox/upstream-netbsd/usr.bin/grep/grep.c
+++ /dev/null
@@ -1,707 +0,0 @@
-/*	$NetBSD: grep.c,v 1.12 2014/07/11 16:30:45 christos Exp $	*/
-/* 	$FreeBSD: head/usr.bin/grep/grep.c 211519 2010-08-19 22:55:17Z delphij $	*/
-/*	$OpenBSD: grep.c,v 1.42 2010/07/02 22:18:03 tedu Exp $	*/
-
-/*-
- * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
- * Copyright (C) 2008-2009 Gabor Kovesdan <gabor@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if HAVE_NBTOOL_CONFIG_H
-#include "nbtool_config.h"
-#endif
-
-#include <sys/cdefs.h>
-__RCSID("$NetBSD: grep.c,v 1.12 2014/07/11 16:30:45 christos Exp $");
-
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <getopt.h>
-#include <limits.h>
-#include <libgen.h>
-#include <locale.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "grep.h"
-
-#ifndef WITHOUT_NLS
-#include <nl_types.h>
-nl_catd	 catalog;
-#endif
-
-/*
- * Default messags to use when NLS is disabled or no catalogue
- * is found.
- */
-const char	*errstr[] = {
-	"",
-/* 1*/	"(standard input)",
-/* 2*/	"cannot read bzip2 compressed file",
-/* 3*/	"unknown %s option",
-/* 4*/	"usage: %s [-abcDEFGHhIiJLlmnOoPqRSsUVvwxZz] [-A num] [-B num] [-C[num]]\n",
-/* 5*/	"\t[-e pattern] [-f file] [--binary-files=value] [--color=when]\n",
-/* 6*/	"\t[--context[=num]] [--directories=action] [--label] [--line-buffered]\n",
-/* 7*/	"\t[pattern] [file ...]\n",
-/* 8*/	"Binary file %s matches\n",
-/* 9*/	"%s (BSD grep) %s\n",
-};
-
-/* Flags passed to regcomp() and regexec() */
-int		 cflags = 0;
-int		 eflags = REG_STARTEND;
-
-/* Searching patterns */
-unsigned int	 patterns, pattern_sz;
-char		**pattern;
-regex_t		*r_pattern;
-fastgrep_t	*fg_pattern;
-
-/* Filename exclusion/inclusion patterns */
-unsigned int	 fpatterns, fpattern_sz;
-unsigned int	 dpatterns, dpattern_sz;
-struct epat	*dpattern, *fpattern;
-
-/* For regex errors  */
-char	 re_error[RE_ERROR_BUF + 1];
-
-/* Command-line flags */
-unsigned long long Aflag;	/* -A x: print x lines trailing each match */
-unsigned long long Bflag;	/* -B x: print x lines leading each match */
-bool	 Hflag;		/* -H: always print file name */
-bool	 Lflag;		/* -L: only show names of files with no matches */
-bool	 bflag;		/* -b: show block numbers for each match */
-bool	 cflag;		/* -c: only show a count of matching lines */
-bool	 hflag;		/* -h: don't print filename headers */
-bool	 iflag;		/* -i: ignore case */
-bool	 lflag;		/* -l: only show names of files with matches */
-bool	 mflag;		/* -m x: stop reading the files after x matches */
-unsigned long long mcount;	/* count for -m */
-bool	 nflag;		/* -n: show line numbers in front of matching lines */
-bool	 oflag;		/* -o: print only matching part */
-bool	 qflag;		/* -q: quiet mode (don't output anything) */
-bool	 sflag;		/* -s: silent mode (ignore errors) */
-bool	 vflag;		/* -v: only show non-matching lines */
-bool	 wflag;		/* -w: pattern must start and end on word boundaries */
-bool	 xflag;		/* -x: pattern must match entire line */
-bool	 lbflag;	/* --line-buffered */
-bool	 nullflag;	/* --null */
-bool	 nulldataflag;	/* --null-data */
-unsigned char line_sep = '\n';	/* 0 for --null-data */
-char	*label;		/* --label */
-const char *color;	/* --color */
-int	 grepbehave = GREP_BASIC;	/* -EFGP: type of the regex */
-int	 binbehave = BINFILE_BIN;	/* -aIU: handling of binary files */
-int	 filebehave = FILE_STDIO;	/* -JZ: normal, gzip or bzip2 file */
-int	 devbehave = DEV_READ;		/* -D: handling of devices */
-int	 dirbehave = DIR_READ;		/* -dRr: handling of directories */
-int	 linkbehave = LINK_READ;	/* -OpS: handling of symlinks */
-
-bool	 dexclude, dinclude;	/* --exclude-dir and --include-dir */
-bool	 fexclude, finclude;	/* --exclude and --include */
-
-enum {
-	BIN_OPT = CHAR_MAX + 1,
-	COLOR_OPT,
-	DECOMPRESS_OPT,
-	HELP_OPT,
-	MMAP_OPT,
-	LINEBUF_OPT,
-	LABEL_OPT,
-	R_EXCLUDE_OPT,
-	R_INCLUDE_OPT,
-	R_DEXCLUDE_OPT,
-	R_DINCLUDE_OPT
-};
-
-static inline const char	*init_color(const char *);
-
-/* Housekeeping */
-int	 tail;		/* lines left to print */
-bool	 notfound;	/* file not found */
-
-extern char	*__progname;
-
-/*
- * Prints usage information and returns 2.
- */
-__dead static void
-usage(void)
-{
-	fprintf(stderr, getstr(4), __progname);
-	fprintf(stderr, "%s", getstr(5));
-	fprintf(stderr, "%s", getstr(6));
-	fprintf(stderr, "%s", getstr(7));
-	exit(2);
-}
-
-static const char optstr[] =
-    "0123456789A:B:C:D:EFGHIJLOPSRUVZabcd:e:f:hilm:nopqrsuvwxyz";
-
-struct option long_options[] =
-{
-	{"binary-files",	required_argument,	NULL, BIN_OPT},
-	{"decompress",          no_argument,            NULL, DECOMPRESS_OPT},
-	{"help",		no_argument,		NULL, HELP_OPT},
-	{"mmap",		no_argument,		NULL, MMAP_OPT},
-	{"line-buffered",	no_argument,		NULL, LINEBUF_OPT},
-	{"label",		required_argument,	NULL, LABEL_OPT},
-	{"color",		optional_argument,	NULL, COLOR_OPT},
-	{"colour",		optional_argument,	NULL, COLOR_OPT},
-	{"exclude",		required_argument,	NULL, R_EXCLUDE_OPT},
-	{"include",		required_argument,	NULL, R_INCLUDE_OPT},
-	{"exclude-dir",		required_argument,	NULL, R_DEXCLUDE_OPT},
-	{"include-dir",		required_argument,	NULL, R_DINCLUDE_OPT},
-	{"after-context",	required_argument,	NULL, 'A'},
-	{"text",		no_argument,		NULL, 'a'},
-	{"before-context",	required_argument,	NULL, 'B'},
-	{"byte-offset",		no_argument,		NULL, 'b'},
-	{"context",		optional_argument,	NULL, 'C'},
-	{"count",		no_argument,		NULL, 'c'},
-	{"devices",		required_argument,	NULL, 'D'},
-        {"directories",		required_argument,	NULL, 'd'},
-	{"extended-regexp",	no_argument,		NULL, 'E'},
-	{"regexp",		required_argument,	NULL, 'e'},
-	{"fixed-strings",	no_argument,		NULL, 'F'},
-	{"file",		required_argument,	NULL, 'f'},
-	{"basic-regexp",	no_argument,		NULL, 'G'},
-	{"no-filename",		no_argument,		NULL, 'h'},
-	{"with-filename",	no_argument,		NULL, 'H'},
-	{"ignore-case",		no_argument,		NULL, 'i'},
-	{"bz2decompress",	no_argument,		NULL, 'J'},
-	{"files-with-matches",	no_argument,		NULL, 'l'},
-	{"files-without-match", no_argument,            NULL, 'L'},
-	{"max-count",		required_argument,	NULL, 'm'},
-	{"line-number",		no_argument,		NULL, 'n'},
-	{"only-matching",	no_argument,		NULL, 'o'},
-	{"quiet",		no_argument,		NULL, 'q'},
-	{"silent",		no_argument,		NULL, 'q'},
-	{"recursive",		no_argument,		NULL, 'r'},
-	{"no-messages",		no_argument,		NULL, 's'},
-	{"binary",		no_argument,		NULL, 'U'},
-	{"unix-byte-offsets",	no_argument,		NULL, 'u'},
-	{"invert-match",	no_argument,		NULL, 'v'},
-	{"version",		no_argument,		NULL, 'V'},
-	{"word-regexp",		no_argument,		NULL, 'w'},
-	{"line-regexp",		no_argument,		NULL, 'x'},
-	{"null",		no_argument,		NULL, 'Z'},
-	{"null-data",		no_argument,		NULL, 'z'},
-	{NULL,			no_argument,		NULL, 0}
-};
-
-/*
- * Adds a searching pattern to the internal array.
- */
-static void
-add_pattern(char *pat, size_t len)
-{
-
-	/* TODO: Check for empty patterns and shortcut */
-
-	/* Increase size if necessary */
-	if (patterns == pattern_sz) {
-		pattern_sz *= 2;
-		pattern = grep_realloc(pattern, ++pattern_sz *
-		    sizeof(*pattern));
-	}
-	if (len > 0 && pat[len - 1] == '\n')
-		--len;
-	/* pat may not be NUL-terminated */
-	pattern[patterns] = grep_malloc(len + 1);
-	memcpy(pattern[patterns], pat, len);
-	pattern[patterns][len] = '\0';
-	++patterns;
-}
-
-/*
- * Adds a file include/exclude pattern to the internal array.
- */
-static void
-add_fpattern(const char *pat, int mode)
-{
-
-	/* Increase size if necessary */
-	if (fpatterns == fpattern_sz) {
-		fpattern_sz *= 2;
-		fpattern = grep_realloc(fpattern, ++fpattern_sz *
-		    sizeof(struct epat));
-	}
-	fpattern[fpatterns].pat = grep_strdup(pat);
-	fpattern[fpatterns].mode = mode;
-	++fpatterns;
-}
-
-/*
- * Adds a directory include/exclude pattern to the internal array.
- */
-static void
-add_dpattern(const char *pat, int mode)
-{
-
-	/* Increase size if necessary */
-	if (dpatterns == dpattern_sz) {
-		dpattern_sz *= 2;
-		dpattern = grep_realloc(dpattern, ++dpattern_sz *
-		    sizeof(struct epat));
-	}
-	dpattern[dpatterns].pat = grep_strdup(pat);
-	dpattern[dpatterns].mode = mode;
-	++dpatterns;
-}
-
-/*
- * Reads searching patterns from a file and adds them with add_pattern().
- */
-static void
-read_patterns(const char *fn)
-{
-	FILE *f;
-	char *line;
-	size_t len;
-	ssize_t rlen;
-
-	if ((f = fopen(fn, "r")) == NULL)
-		err(2, "%s", fn);
-	line = NULL;
-	len = 0;
-	while ((rlen = getline(&line, &len, f)) != -1)
-		add_pattern(line, *line == '\n' ? 0 : (size_t)rlen);
-	free(line);
-	if (ferror(f))
-		err(2, "%s", fn);
-	fclose(f);
-}
-
-static inline const char *
-init_color(const char *d)
-{
-	char *c;
-
-	c = getenv("GREP_COLOR");
-	return (c != NULL ? c : d);
-}
-
-int
-main(int argc, char *argv[])
-{
-	char **aargv, **eargv, *eopts;
-	char *ep;
-	unsigned long long l;
-	unsigned int aargc, eargc, i, j;
-	int c, lastc, needpattern, newarg, prevoptind;
-
-	setlocale(LC_ALL, "");
-
-#ifndef WITHOUT_NLS
-	catalog = catopen("grep", NL_CAT_LOCALE);
-#endif
-
-	/* Check what is the program name of the binary.  In this
-	   way we can have all the funcionalities in one binary
-	   without the need of scripting and using ugly hacks. */
-	switch (__progname[0]) {
-	case 'e':
-		grepbehave = GREP_EXTENDED;
-		break;
-	case 'f':
-		grepbehave = GREP_FIXED;
-		break;
-	case 'g':
-		grepbehave = GREP_BASIC;
-		break;
-	case 'z':
-		filebehave = FILE_GZIP;
-		switch(__progname[1]) {
-		case 'e':
-			grepbehave = GREP_EXTENDED;
-			break;
-		case 'f':
-			grepbehave = GREP_FIXED;
-			break;
-		case 'g':
-			grepbehave = GREP_BASIC;
-			break;
-		}
-		break;
-	}
-
-	lastc = '\0';
-	newarg = 1;
-	prevoptind = 1;
-	needpattern = 1;
-
-	eopts = getenv("GREP_OPTIONS");
-
-	/* support for extra arguments in GREP_OPTIONS */
-	eargc = 0;
-	if (eopts != NULL) {
-		char *str;
-
-		/* make an estimation of how many extra arguments we have */
-		for (j = 0; j < strlen(eopts); j++)
-			if (eopts[j] == ' ')
-				eargc++;
-
-		eargv = (char **)grep_malloc(sizeof(char *) * (eargc + 1));
-
-		eargc = 0;
-		/* parse extra arguments */
-		while ((str = strsep(&eopts, " ")) != NULL)
-			eargv[eargc++] = grep_strdup(str);
-
-		aargv = (char **)grep_calloc(eargc + argc + 1,
-		    sizeof(char *));
-
-		aargv[0] = argv[0];
-		for (i = 0; i < eargc; i++)
-			aargv[i + 1] = eargv[i];
-		for (j = 1; j < (unsigned int)argc; j++, i++)
-			aargv[i + 1] = argv[j];
-
-		aargc = eargc + argc;
-	} else {
-		aargv = argv;
-		aargc = argc;
-	}
-
-	while (((c = getopt_long(aargc, aargv, optstr, long_options, NULL)) !=
-	    -1)) {
-		switch (c) {
-		case '0': case '1': case '2': case '3': case '4':
-		case '5': case '6': case '7': case '8': case '9':
-			if (newarg || !isdigit(lastc))
-				Aflag = 0;
-			else if (Aflag > LLONG_MAX / 10) {
-				errno = ERANGE;
-				err(2, NULL);
-			}
-			Aflag = Bflag = (Aflag * 10) + (c - '0');
-			break;
-		case 'C':
-			if (optarg == NULL) {
-				Aflag = Bflag = 2;
-				break;
-			}
-			/* FALLTHROUGH */
-		case 'A':
-			/* FALLTHROUGH */
-		case 'B':
-			errno = 0;
-			l = strtoull(optarg, &ep, 10);
-			if (((errno == ERANGE) && (l == ULLONG_MAX)) ||
-			    ((errno == EINVAL) && (l == 0)))
-				err(2, NULL);
-			else if (ep[0] != '\0') {
-				errno = EINVAL;
-				err(2, NULL);
-			}
-			if (c == 'A')
-				Aflag = l;
-			else if (c == 'B')
-				Bflag = l;
-			else
-				Aflag = Bflag = l;
-			break;
-		case 'a':
-			binbehave = BINFILE_TEXT;
-			break;
-		case 'b':
-			bflag = true;
-			break;
-		case 'c':
-			cflag = true;
-			break;
-		case 'D':
-			if (strcasecmp(optarg, "skip") == 0)
-				devbehave = DEV_SKIP;
-			else if (strcasecmp(optarg, "read") == 0)
-				devbehave = DEV_READ;
-			else
-				errx(2, getstr(3), "--devices");
-			break;
-		case 'd':
-			if (strcasecmp("recurse", optarg) == 0) {
-				Hflag = true;
-				dirbehave = DIR_RECURSE;
-			} else if (strcasecmp("skip", optarg) == 0)
-				dirbehave = DIR_SKIP;
-			else if (strcasecmp("read", optarg) == 0)
-				dirbehave = DIR_READ;
-			else
-				errx(2, getstr(3), "--directories");
-			break;
-		case 'E':
-			grepbehave = GREP_EXTENDED;
-			break;
-		case 'e':
-			add_pattern(optarg, strlen(optarg));
-			needpattern = 0;
-			break;
-		case 'F':
-			grepbehave = GREP_FIXED;
-			break;
-		case 'f':
-			read_patterns(optarg);
-			needpattern = 0;
-			break;
-		case 'G':
-			grepbehave = GREP_BASIC;
-			break;
-		case 'H':
-			Hflag = true;
-			break;
-		case 'h':
-			Hflag = false;
-			hflag = true;
-			break;
-		case 'I':
-			binbehave = BINFILE_SKIP;
-			break;
-		case 'i':
-		case 'y':
-			iflag =  true;
-			cflags |= REG_ICASE;
-			break;
-		case 'J':
-			filebehave = FILE_BZIP;
-			break;
-		case 'L':
-			lflag = false;
-			Lflag = true;
-			break;
-		case 'l':
-			Lflag = false;
-			lflag = true;
-			break;
-		case 'm':
-			mflag = true;
-			errno = 0;
-			mcount = strtoull(optarg, &ep, 10);
-			if (((errno == ERANGE) && (mcount == ULLONG_MAX)) ||
-			    ((errno == EINVAL) && (mcount == 0)))
-				err(2, NULL);
-			else if (ep[0] != '\0') {
-				errno = EINVAL;
-				err(2, NULL);
-			}
-			break;
-		case 'n':
-			nflag = true;
-			break;
-		case 'O':
-			linkbehave = LINK_EXPLICIT;
-			break;
-		case 'o':
-			oflag = true;
-			break;
-		case 'p':
-			linkbehave = LINK_SKIP;
-			break;
-		case 'q':
-			qflag = true;
-			break;
-		case 'S':
-			linkbehave = LINK_READ;
-			break;
-		case 'R':
-		case 'r':
-			dirbehave = DIR_RECURSE;
-			Hflag = true;
-			break;
-		case 's':
-			sflag = true;
-			break;
-		case 'U':
-			binbehave = BINFILE_BIN;
-			break;
-		case 'u':
-		case MMAP_OPT:
-			/* noop, compatibility */
-			break;
-		case 'V':
-			printf(getstr(9), __progname, VERSION);
-			exit(0);
-		case 'v':
-			vflag = true;
-			break;
-		case 'w':
-			wflag = true;
-			break;
-		case 'x':
-			xflag = true;
-			break;
-		case 'Z':
-			nullflag = true;
-			break;
-		case 'z':
-			nulldataflag = true;
-			line_sep = '\0';
-			break;
-		case BIN_OPT:
-			if (strcasecmp("binary", optarg) == 0)
-				binbehave = BINFILE_BIN;
-			else if (strcasecmp("without-match", optarg) == 0)
-				binbehave = BINFILE_SKIP;
-			else if (strcasecmp("text", optarg) == 0)
-				binbehave = BINFILE_TEXT;
-			else
-				errx(2, getstr(3), "--binary-files");
-			break;
-		case COLOR_OPT:
-			color = NULL;
-			if (optarg == NULL || strcasecmp("auto", optarg) == 0 ||
-			    strcasecmp("tty", optarg) == 0 ||
-			    strcasecmp("if-tty", optarg) == 0) {
-				char *term;
-
-				term = getenv("TERM");
-				if (isatty(STDOUT_FILENO) && term != NULL &&
-				    strcasecmp(term, "dumb") != 0)
-					color = init_color("01;31");
-			} else if (strcasecmp("always", optarg) == 0 ||
-			    strcasecmp("yes", optarg) == 0 ||
-			    strcasecmp("force", optarg) == 0) {
-				color = init_color("01;31");
-			} else if (strcasecmp("never", optarg) != 0 &&
-			    strcasecmp("none", optarg) != 0 &&
-			    strcasecmp("no", optarg) != 0)
-				errx(2, getstr(3), "--color");
-			break;
-		case DECOMPRESS_OPT:
-			filebehave = FILE_GZIP;
-			break;
-		case LABEL_OPT:
-			label = optarg;
-			break;
-		case LINEBUF_OPT:
-			lbflag = true;
-			break;
-		case R_INCLUDE_OPT:
-			finclude = true;
-			add_fpattern(optarg, INCL_PAT);
-			break;
-		case R_EXCLUDE_OPT:
-			fexclude = true;
-			add_fpattern(optarg, EXCL_PAT);
-			break;
-		case R_DINCLUDE_OPT:
-			dinclude = true;
-			add_dpattern(optarg, INCL_PAT);
-			break;
-		case R_DEXCLUDE_OPT:
-			dexclude = true;
-			add_dpattern(optarg, EXCL_PAT);
-			break;
-		case HELP_OPT:
-		default:
-			usage();
-		}
-		lastc = c;
-		newarg = optind != prevoptind;
-		prevoptind = optind;
-	}
-	aargc -= optind;
-	aargv += optind;
-
-	/* Fail if we don't have any pattern */
-	if (aargc == 0 && needpattern)
-		usage();
-
-	/* Process patterns from command line */
-	if (aargc != 0 && needpattern) {
-		add_pattern(*aargv, strlen(*aargv));
-		--aargc;
-		++aargv;
-	}
-
-	switch (grepbehave) {
-	case GREP_FIXED:
-	case GREP_BASIC:
-		break;
-	case GREP_EXTENDED:
-		cflags |= REG_EXTENDED;
-		break;
-	default:
-		/* NOTREACHED */
-		usage();
-	}
-
-	fg_pattern = grep_calloc(patterns, sizeof(*fg_pattern));
-	r_pattern = grep_calloc(patterns, sizeof(*r_pattern));
-/*
- * XXX: fgrepcomp() and fastcomp() are workarounds for regexec() performance.
- * Optimizations should be done there.
- */
-		/* Check if cheating is allowed (always is for fgrep). */
-	if (grepbehave == GREP_FIXED) {
-		for (i = 0; i < patterns; ++i)
-			fgrepcomp(&fg_pattern[i], pattern[i]);
-	} else {
-		for (i = 0; i < patterns; ++i) {
-			if (fastcomp(&fg_pattern[i], pattern[i])) {
-				/* Fall back to full regex library */
-				c = regcomp(&r_pattern[i], pattern[i], cflags);
-				if (c != 0) {
-					regerror(c, &r_pattern[i], re_error,
-					    RE_ERROR_BUF);
-					errx(2, "%s", re_error);
-				}
-			}
-		}
-	}
-
-	if (lbflag)
-		setlinebuf(stdout);
-
-	if ((aargc == 0 || aargc == 1) && !Hflag)
-		hflag = true;
-
-	if (aargc == 0)
-		exit(!procfile("-"));
-
-	if (dirbehave == DIR_RECURSE)
-		c = grep_tree(aargv);
-	else
-		for (c = 0; aargc--; ++aargv) {
-			if ((finclude || fexclude) && !file_matching(*aargv))
-				continue;
-			c+= procfile(*aargv);
-		}
-
-#ifndef WITHOUT_NLS
-	catclose(catalog);
-#endif
-
-	/* Find out the correct return value according to the
-	   results and the command line option. */
-	exit(c ? (notfound ? (qflag ? 0 : 2) : 0) : (notfound ? 2 : 1));
-}
diff --git a/toolbox/upstream-netbsd/usr.bin/grep/grep.h b/toolbox/upstream-netbsd/usr.bin/grep/grep.h
deleted file mode 100644
index fa2a3e3..0000000
--- a/toolbox/upstream-netbsd/usr.bin/grep/grep.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*	$NetBSD: grep.h,v 1.8 2012/05/06 22:27:00 joerg Exp $	*/
-/*	$OpenBSD: grep.h,v 1.15 2010/04/05 03:03:55 tedu Exp $	*/
-/*	$FreeBSD: head/usr.bin/grep/grep.h 211496 2010-08-19 09:28:59Z des $	*/
-
-/*-
- * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
- * Copyright (c) 2008-2009 Gabor Kovesdan <gabor@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef __ANDROID__
-#include <bzlib.h>
-#endif
-#include <limits.h>
-#include <regex.h>
-#include <stdbool.h>
-#include <stdio.h>
-#ifndef __ANDROID__
-#include <zlib.h>
-#endif
-
-#ifdef WITHOUT_NLS
-#define getstr(n)	 errstr[n]
-#else
-#include <nl_types.h>
-
-extern nl_catd		 catalog;
-#define getstr(n)	 catgets(catalog, 1, n, errstr[n])
-#endif
-
-extern const char		*errstr[];
-
-#define VERSION		"2.5.1-FreeBSD"
-
-#define GREP_FIXED	0
-#define GREP_BASIC	1
-#define GREP_EXTENDED	2
-
-#define BINFILE_BIN	0
-#define BINFILE_SKIP	1
-#define BINFILE_TEXT	2
-
-#define FILE_STDIO	0
-#define FILE_GZIP	1
-#define FILE_BZIP	2
-
-#define DIR_READ	0
-#define DIR_SKIP	1
-#define DIR_RECURSE	2
-
-#define DEV_READ	0
-#define DEV_SKIP	1
-
-#define LINK_READ	0
-#define LINK_EXPLICIT	1
-#define LINK_SKIP	2
-
-#define EXCL_PAT	0
-#define INCL_PAT	1
-
-#define MAX_LINE_MATCHES	32
-
-struct file {
-	int		 fd;
-	bool		 binary;
-};
-
-struct str {
-	off_t		 off;
-	size_t		 len;
-	char		*dat;
-	char		*file;
-	int		 line_no;
-};
-
-struct epat {
-	char		*pat;
-	int		 mode;
-};
-
-typedef struct {
-	size_t		 len;
-	unsigned char	*pattern;
-	int		 qsBc[UCHAR_MAX + 1];
-	/* flags */
-	bool		 bol;
-	bool		 eol;
-	bool		 reversed;
-	bool		 word;
-} fastgrep_t;
-
-/* Flags passed to regcomp() and regexec() */
-extern int	 cflags, eflags;
-
-/* Command line flags */
-extern bool	 Eflag, Fflag, Gflag, Hflag, Lflag,
-		 bflag, cflag, hflag, iflag, lflag, mflag, nflag, oflag,
-		 qflag, sflag, vflag, wflag, xflag;
-extern bool	 dexclude, dinclude, fexclude, finclude, lbflag, nullflag, nulldataflag;
-extern unsigned char line_sep;
-extern unsigned long long Aflag, Bflag, mcount;
-extern char	*label;
-extern const char *color;
-extern int	 binbehave, devbehave, dirbehave, filebehave, grepbehave, linkbehave;
-
-extern bool	 notfound;
-extern int	 tail;
-extern unsigned int dpatterns, fpatterns, patterns;
-extern char    **pattern;
-extern struct epat *dpattern, *fpattern;
-extern regex_t	*er_pattern, *r_pattern;
-extern fastgrep_t *fg_pattern;
-
-/* For regex errors  */
-#define RE_ERROR_BUF	512
-extern char	 re_error[RE_ERROR_BUF + 1];	/* Seems big enough */
-
-/* util.c */
-bool	 file_matching(const char *fname);
-int	 procfile(const char *fn);
-int	 grep_tree(char **argv);
-void	*grep_malloc(size_t size);
-void	*grep_calloc(size_t nmemb, size_t size);
-void	*grep_realloc(void *ptr, size_t size);
-char	*grep_strdup(const char *str);
-void	 printline(struct str *line, int sep, regmatch_t *matches, int m);
-
-/* queue.c */
-void	 enqueue(struct str *x);
-void	 printqueue(void);
-void	 clearqueue(void);
-
-/* file.c */
-void		 grep_close(struct file *f);
-struct file	*grep_open(const char *path);
-char		*grep_fgetln(struct file *f, size_t *len);
-
-/* fastgrep.c */
-int		 fastcomp(fastgrep_t *, const char *);
-void		 fgrepcomp(fastgrep_t *, const char *);
-int		 grep_search(fastgrep_t *, const unsigned char *, size_t, regmatch_t *);
diff --git a/toolbox/upstream-netbsd/usr.bin/grep/queue.c b/toolbox/upstream-netbsd/usr.bin/grep/queue.c
deleted file mode 100644
index e3c6be1..0000000
--- a/toolbox/upstream-netbsd/usr.bin/grep/queue.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*	$NetBSD: queue.c,v 1.5 2011/08/31 16:24:57 plunky Exp $	*/
-/*	$FreeBSD: head/usr.bin/grep/queue.c 211496 2010-08-19 09:28:59Z des $	*/
-/*-
- * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * A really poor man's queue.  It does only what it has to and gets out of
- * Dodge.  It is used in place of <sys/queue.h> to get a better performance.
- */
-
-#if HAVE_NBTOOL_CONFIG_H
-#include "nbtool_config.h"
-#endif
-
-#include <sys/cdefs.h>
-__RCSID("$NetBSD: queue.c,v 1.5 2011/08/31 16:24:57 plunky Exp $");
-
-#include <sys/param.h>
-#include <sys/queue.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "grep.h"
-
-struct qentry {
-	STAILQ_ENTRY(qentry)	list;
-	struct str	 	data;
-};
-
-static STAILQ_HEAD(, qentry)	queue = STAILQ_HEAD_INITIALIZER(queue);
-static unsigned long long	count;
-
-static struct qentry	*dequeue(void);
-
-void
-enqueue(struct str *x)
-{
-	struct qentry *item;
-
-	item = grep_malloc(sizeof(struct qentry));
-	item->data.dat = grep_malloc(sizeof(char) * x->len);
-	item->data.len = x->len;
-	item->data.line_no = x->line_no;
-	item->data.off = x->off;
-	memcpy(item->data.dat, x->dat, x->len);
-	item->data.file = x->file;
-
-	STAILQ_INSERT_TAIL(&queue, item, list);
-
-	if (++count > Bflag) {
-		item = dequeue();
-		free(item->data.dat);
-		free(item);
-	}
-}
-
-static struct qentry *
-dequeue(void)
-{
-	struct qentry *item;
-
-	item = STAILQ_FIRST(&queue);
-	if (item == NULL)
-		return (NULL);
-
-	STAILQ_REMOVE_HEAD(&queue, list);
-	--count;
-	return (item);
-}
-
-void
-printqueue(void)
-{
-	struct qentry *item;
-
-	while ((item = dequeue()) != NULL) {
-		printline(&item->data, '-', NULL, 0);
-		free(item->data.dat);
-		free(item);
-	}
-}
-
-void
-clearqueue(void)
-{
-	struct qentry *item;
-
-	while ((item = dequeue()) != NULL) {
-		free(item->data.dat);
-		free(item);
-	}
-}
diff --git a/toolbox/upstream-netbsd/usr.bin/grep/util.c b/toolbox/upstream-netbsd/usr.bin/grep/util.c
deleted file mode 100644
index ecd948d..0000000
--- a/toolbox/upstream-netbsd/usr.bin/grep/util.c
+++ /dev/null
@@ -1,499 +0,0 @@
-/*	$NetBSD: util.c,v 1.17 2013/01/21 03:24:43 msaitoh Exp $	*/
-/*	$FreeBSD: head/usr.bin/grep/util.c 211496 2010-08-19 09:28:59Z des $	*/
-/*	$OpenBSD: util.c,v 1.39 2010/07/02 22:18:03 tedu Exp $	*/
-
-/*-
- * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
- * Copyright (C) 2008-2010 Gabor Kovesdan <gabor@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if HAVE_NBTOOL_CONFIG_H
-#include "nbtool_config.h"
-#endif
-
-#include <sys/cdefs.h>
-__RCSID("$NetBSD: util.c,v 1.17 2013/01/21 03:24:43 msaitoh Exp $");
-
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <fnmatch.h>
-#include <fts.h>
-#include <libgen.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <wchar.h>
-#include <wctype.h>
-
-#include "grep.h"
-
-static bool	 first, first_global = true;
-static unsigned long long since_printed;
-
-static int	 procline(struct str *l, int);
-
-bool
-file_matching(const char *fname)
-{
-	char *fname_base, *fname_copy;
-	unsigned int i;
-	bool ret;
-
-	ret = finclude ? false : true;
-	fname_copy = grep_strdup(fname);
-	fname_base = basename(fname_copy);
-
-	for (i = 0; i < fpatterns; ++i) {
-		if (fnmatch(fpattern[i].pat, fname, 0) == 0 ||
-		    fnmatch(fpattern[i].pat, fname_base, 0) == 0) {
-			if (fpattern[i].mode == EXCL_PAT) {
-				free(fname_copy);
-				return (false);
-			} else
-				ret = true;
-		}
-	}
-	free(fname_copy);
-	return (ret);
-}
-
-static inline bool
-dir_matching(const char *dname)
-{
-	unsigned int i;
-	bool ret;
-
-	ret = dinclude ? false : true;
-
-	for (i = 0; i < dpatterns; ++i) {
-		if (dname != NULL &&
-		    fnmatch(dname, dpattern[i].pat, 0) == 0) {
-			if (dpattern[i].mode == EXCL_PAT)
-				return (false);
-			else
-				ret = true;
-		}
-	}
-	return (ret);
-}
-
-/*
- * Processes a directory when a recursive search is performed with
- * the -R option.  Each appropriate file is passed to procfile().
- */
-int
-grep_tree(char **argv)
-{
-	FTS *fts;
-	FTSENT *p;
-	char *d, *dir = NULL;
-	int c, fts_flags;
-	bool ok;
-
-	c = fts_flags = 0;
-
-	switch(linkbehave) {
-	case LINK_EXPLICIT:
-		fts_flags = FTS_COMFOLLOW;
-		break;
-	case LINK_SKIP:
-		fts_flags = FTS_PHYSICAL;
-		break;
-	default:
-		fts_flags = FTS_LOGICAL;
-			
-	}
-
-	fts_flags |= FTS_NOSTAT | FTS_NOCHDIR;
-
-	if (!(fts = fts_open(argv, fts_flags, NULL)))
-		err(2, "fts_open");
-	while ((p = fts_read(fts)) != NULL) {
-		switch (p->fts_info) {
-		case FTS_DNR:
-			/* FALLTHROUGH */
-		case FTS_ERR:
-			errx(2, "%s: %s", p->fts_path, strerror(p->fts_errno));
-			break;
-		case FTS_D:
-			/* FALLTHROUGH */
-		case FTS_DP:
-			break;
-		case FTS_DC:
-			/* Print a warning for recursive directory loop */
-			warnx("warning: %s: recursive directory loop",
-				p->fts_path);
-			break;
-		default:
-			/* Check for file exclusion/inclusion */
-			ok = true;
-			if (dexclude || dinclude) {
-				if ((d = strrchr(p->fts_path, '/')) != NULL) {
-					dir = grep_malloc(sizeof(char) *
-					    (d - p->fts_path + 1));
-					memcpy(dir, p->fts_path,
-					    d - p->fts_path);
-					dir[d - p->fts_path] = '\0';
-				}
-				ok = dir_matching(dir);
-				free(dir);
-				dir = NULL;
-			}
-			if (fexclude || finclude)
-				ok &= file_matching(p->fts_path);
-
-			if (ok)
-				c += procfile(p->fts_path);
-			break;
-		}
-	}
-
-	fts_close(fts);
-	return (c);
-}
-
-/*
- * Opens a file and processes it.  Each file is processed line-by-line
- * passing the lines to procline().
- */
-int
-procfile(const char *fn)
-{
-	struct file *f;
-	struct stat sb;
-	struct str ln;
-	mode_t s;
-	int c, t;
-
-	if (mflag && (mcount <= 0))
-		return (0);
-
-	if (strcmp(fn, "-") == 0) {
-		fn = label != NULL ? label : getstr(1);
-		f = grep_open(NULL);
-	} else {
-		if (!stat(fn, &sb)) {
-			/* Check if we need to process the file */
-			s = sb.st_mode & S_IFMT;
-			if (s == S_IFDIR && dirbehave == DIR_SKIP)
-				return (0);
-			if ((s == S_IFIFO || s == S_IFCHR || s == S_IFBLK
-				|| s == S_IFSOCK) && devbehave == DEV_SKIP)
-					return (0);
-		}
-		f = grep_open(fn);
-	}
-	if (f == NULL) {
-		if (!sflag)
-			warn("%s", fn);
-		if (errno == ENOENT)
-			notfound = true;
-		return (0);
-	}
-
-	ln.file = grep_malloc(strlen(fn) + 1);
-	strcpy(ln.file, fn);
-	ln.line_no = 0;
-	ln.len = 0;
-	tail = 0;
-	ln.off = -1;
-
-	for (first = true, c = 0;  c == 0 || !(lflag || qflag); ) {
-		ln.off += ln.len + 1;
-		if ((ln.dat = grep_fgetln(f, &ln.len)) == NULL || ln.len == 0)
-			break;
-		if (ln.len > 0 && ln.dat[ln.len - 1] == line_sep)
-			--ln.len;
-		ln.line_no++;
-
-		/* Return if we need to skip a binary file */
-		if (f->binary && binbehave == BINFILE_SKIP) {
-			grep_close(f);
-			free(ln.file);
-			free(f);
-			return (0);
-		}
-		/* Process the file line-by-line */
-		t = procline(&ln, f->binary);
-		c += t;
-
-		/* Count the matches if we have a match limit */
-		if (mflag) {
-			mcount -= t;
-			if (mcount <= 0)
-				break;
-		}
-	}
-	if (Bflag > 0)
-		clearqueue();
-	grep_close(f);
-
-	if (cflag) {
-		if (!hflag)
-			printf("%s:", ln.file);
-		printf("%u%c", c, line_sep);
-	}
-	if (lflag && !qflag && c != 0)
-		printf("%s%c", fn, line_sep);
-	if (Lflag && !qflag && c == 0)
-		printf("%s%c", fn, line_sep);
-	if (c && !cflag && !lflag && !Lflag &&
-	    binbehave == BINFILE_BIN && f->binary && !qflag)
-		printf(getstr(8), fn);
-
-	free(ln.file);
-	free(f);
-	return (c);
-}
-
-#define iswword(x)	(iswalnum((x)) || (x) == L'_')
-
-/*
- * Processes a line comparing it with the specified patterns.  Each pattern
- * is looped to be compared along with the full string, saving each and every
- * match, which is necessary to colorize the output and to count the
- * matches.  The matching lines are passed to printline() to display the
- * appropriate output.
- */
-static int
-procline(struct str *l, int nottext)
-{
-	regmatch_t matches[MAX_LINE_MATCHES];
-	regmatch_t pmatch;
-	size_t st = 0;
-	unsigned int i;
-	int c = 0, m = 0, r = 0;
-
-	/* Loop to process the whole line */
-	while (st <= l->len) {
-		pmatch.rm_so = st;
-		pmatch.rm_eo = l->len;
-
-		/* Loop to compare with all the patterns */
-		for (i = 0; i < patterns; i++) {
-/*
- * XXX: grep_search() is a workaround for speed up and should be
- * removed in the future.  See fastgrep.c.
- */
-			if (fg_pattern[i].pattern) {
-				r = grep_search(&fg_pattern[i],
-				    (unsigned char *)l->dat,
-				    l->len, &pmatch);
-				r = (r == 0) ? 0 : REG_NOMATCH;
-				st = pmatch.rm_eo;
-			} else {
-				r = regexec(&r_pattern[i], l->dat, 1,
-				    &pmatch, eflags);
-				r = (r == 0) ? 0 : REG_NOMATCH;
-				st = pmatch.rm_eo;
-			}
-			if (r == REG_NOMATCH)
-				continue;
-			/* Check for full match */
-			if (xflag &&
-			    (pmatch.rm_so != 0 ||
-			     (size_t)pmatch.rm_eo != l->len))
-				continue;
-			/* Check for whole word match */
-			if (fg_pattern[i].word && pmatch.rm_so != 0) {
-				wchar_t wbegin, wend;
-
-				wbegin = wend = L' ';
-				if (pmatch.rm_so != 0 &&
-				    sscanf(&l->dat[pmatch.rm_so - 1],
-				    "%lc", &wbegin) != 1)
-					continue;
-				if ((size_t)pmatch.rm_eo != l->len &&
-				    sscanf(&l->dat[pmatch.rm_eo],
-				    "%lc", &wend) != 1)
-					continue;
-				if (iswword(wbegin) || iswword(wend))
-					continue;
-			}
-			c = 1;
-			if (m < MAX_LINE_MATCHES)
-				matches[m++] = pmatch;
-			/* matches - skip further patterns */
-			if ((color != NULL && !oflag) || qflag || lflag)
-				break;
-		}
-
-		if (vflag) {
-			c = !c;
-			break;
-		}
-		/* One pass if we are not recording matches */
-		if ((color != NULL && !oflag) || qflag || lflag)
-			break;
-
-		if (st == (size_t)pmatch.rm_so)
-			break; 	/* No matches */
-	}
-
-	if (c && binbehave == BINFILE_BIN && nottext)
-		return (c); /* Binary file */
-
-	/* Dealing with the context */
-	if ((tail || c) && !cflag && !qflag && !lflag && !Lflag) {
-		if (c) {
-			if ((Aflag || Bflag) && !first_global &&
-			    (first || since_printed > Bflag))
-				printf("--\n");
-			tail = Aflag;
-			if (Bflag > 0)
-				printqueue();
-			printline(l, ':', matches, m);
-		} else {
-			printline(l, '-', matches, m);
-			tail--;
-		}
-		first = false;
-		first_global = false;
-		since_printed = 0;
-	} else {
-		if (Bflag)
-			enqueue(l);
-		since_printed++;
-	}
-	return (c);
-}
-
-/*
- * Safe malloc() for internal use.
- */
-void *
-grep_malloc(size_t size)
-{
-	void *ptr;
-
-	if ((ptr = malloc(size)) == NULL)
-		err(2, "malloc");
-	return (ptr);
-}
-
-/*
- * Safe calloc() for internal use.
- */
-void *
-grep_calloc(size_t nmemb, size_t size)
-{
-	void *ptr;
-
-	if ((ptr = calloc(nmemb, size)) == NULL)
-		err(2, "calloc");
-	return (ptr);
-}
-
-/*
- * Safe realloc() for internal use.
- */
-void *
-grep_realloc(void *ptr, size_t size)
-{
-
-	if ((ptr = realloc(ptr, size)) == NULL)
-		err(2, "realloc");
-	return (ptr);
-}
-
-/*
- * Safe strdup() for internal use.
- */
-char *
-grep_strdup(const char *str)
-{
-	char *ret;
-
-	if ((ret = strdup(str)) == NULL)
-		err(2, "strdup");
-	return (ret);
-}
-
-/*
- * Prints a matching line according to the command line options.
- */
-void
-printline(struct str *line, int sep, regmatch_t *matches, int m)
-{
-	size_t a = 0;
-	int i, n = 0;
-
-	if (!hflag) {
-		if (nullflag == 0)
-			fputs(line->file, stdout);
-		else {
-			printf("%s", line->file);
-			putchar(0);
-		}
-		++n;
-	}
-	if (nflag) {
-		if (n > 0)
-			putchar(sep);
-		printf("%d", line->line_no);
-		++n;
-	}
-	if (bflag) {
-		if (n > 0)
-			putchar(sep);
-		printf("%lld", (long long)line->off);
-		++n;
-	}
-	if (n)
-		putchar(sep);
-	/* --color and -o */
-	if ((oflag || color) && m > 0) {
-		for (i = 0; i < m; i++) {
-			if (!oflag)
-				fwrite(line->dat + a, matches[i].rm_so - a, 1,
-				    stdout);
-			if (color) 
-				fprintf(stdout, "\33[%sm\33[K", color);
-
-				fwrite(line->dat + matches[i].rm_so, 
-				    matches[i].rm_eo - matches[i].rm_so, 1,
-				    stdout);
-			if (color) 
-				fprintf(stdout, "\33[m\33[K");
-			a = matches[i].rm_eo;
-			if (oflag)
-				putchar('\n');
-		}
-		if (!oflag) {
-			if (line->len - a > 0)
-				fwrite(line->dat + a, line->len - a, 1, stdout);
-			putchar(line_sep);
-		}
-	} else {
-		fwrite(line->dat, line->len, 1, stdout);
-		putchar(line_sep);
-	}
-}