adb: fdevent: move run queue to fdevent_context.
am: 95eef6b097

Change-Id: I131984a407220281364c016f832aef45e0f9a457
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 6f6481f..f6ef906 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -82,3 +82,9 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/sbin/charger)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/sbin)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/sbin)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/product_services)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/product_services.img)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/product_services)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/product_services)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/product_services)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/debug_ramdisk/product_services)
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 24d4292..d5e7be1 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -337,9 +337,12 @@
             case ADB_AUTH_SIGNATURE: {
                 // TODO: Switch to string_view.
                 std::string signature(p->payload.begin(), p->payload.end());
-                if (adbd_auth_verify(t->token, sizeof(t->token), signature)) {
+                std::string auth_key;
+                if (adbd_auth_verify(t->token, sizeof(t->token), signature, &auth_key)) {
                     adbd_auth_verified(t);
                     t->failed_auth_attempts = 0;
+                    t->auth_key = auth_key;
+                    adbd_notify_framework_connected_key(t);
                 } else {
                     if (t->failed_auth_attempts++ > 256) std::this_thread::sleep_for(1s);
                     send_auth_request(t);
@@ -348,7 +351,8 @@
             }
 
             case ADB_AUTH_RSAPUBLICKEY:
-                adbd_auth_confirm_key(p->payload.data(), p->msg.data_length, t);
+                t->auth_key = std::string(p->payload.data());
+                adbd_auth_confirm_key(t);
                 break;
 #endif
             default:
diff --git a/adb/adb.h b/adb/adb.h
index 352b2fe..c6cb06a 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -33,6 +33,7 @@
 
 constexpr size_t MAX_PAYLOAD_V1 = 4 * 1024;
 constexpr size_t MAX_PAYLOAD = 1024 * 1024;
+constexpr size_t MAX_FRAMEWORK_PAYLOAD = 64 * 1024;
 
 constexpr size_t LINUX_MAX_SOCKET_SIZE = 4194304;
 
diff --git a/adb/adb_auth.h b/adb/adb_auth.h
index 2fc8478..2be9a76 100644
--- a/adb/adb_auth.h
+++ b/adb/adb_auth.h
@@ -50,8 +50,10 @@
 void adbd_auth_verified(atransport *t);
 
 void adbd_cloexec_auth_socket();
-bool adbd_auth_verify(const char* token, size_t token_size, const std::string& sig);
-void adbd_auth_confirm_key(const char* data, size_t len, atransport* t);
+bool adbd_auth_verify(const char* token, size_t token_size, const std::string& sig,
+                      std::string* auth_key);
+void adbd_auth_confirm_key(atransport* t);
+void adbd_notify_framework_connected_key(atransport* t);
 
 void send_auth_request(atransport *t);
 
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 7211f72..11a3dfd 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -128,7 +128,7 @@
         " pull [-a] REMOTE... LOCAL\n"
         "     copy files/dirs from device\n"
         "     -a: preserve file timestamp and mode\n"
-        " sync [all|data|odm|oem|product_services|product|system|vendor]\n"
+        " sync [all|data|odm|oem|product|system|system_ext|vendor]\n"
         "     sync a local build from $ANDROID_PRODUCT_OUT to the device (default all)\n"
         "     -l: list but don't copy\n"
         "\n"
@@ -775,17 +775,16 @@
         error_exit("abb is not supported by the device");
     }
 
+    optind = 1;  // argv[0] is always "abb", so set `optind` appropriately.
+
     // Defaults.
     constexpr char escape_char = '~';  // -e
     constexpr bool use_shell_protocol = true;
     constexpr auto shell_type_arg = kShellServiceArgRaw;
     constexpr bool empty_command = false;
 
-    std::string service_string("abb:");
-    for (auto i = optind; i < argc; ++i) {
-        service_string.append(argv[i]);
-        service_string.push_back(ABB_ARG_DELIMETER);
-    }
+    std::vector<const char*> args(argv + optind, argv + argc);
+    std::string service_string = "abb:" + android::base::Join(args, ABB_ARG_DELIMETER);
 
     D("abb -e 0x%x [%*.s]\n", escape_char, static_cast<int>(service_string.size()),
       service_string.data());
@@ -1843,8 +1842,8 @@
         }
 
         if (src.empty()) src = "all";
-        std::vector<std::string> partitions{"data",   "odm",   "oem", "product", "product_services",
-                                            "system", "vendor"};
+        std::vector<std::string> partitions{"data",   "odm",        "oem",   "product",
+                                            "system", "system_ext", "vendor"};
         bool found = false;
         for (const auto& partition : partitions) {
             if (src == "all" || src == partition) {
diff --git a/adb/daemon/auth.cpp b/adb/daemon/auth.cpp
index 2b8f461..7a3a4f5 100644
--- a/adb/daemon/auth.cpp
+++ b/adb/daemon/auth.cpp
@@ -26,7 +26,9 @@
 #include <resolv.h>
 #include <stdio.h>
 #include <string.h>
+#include <iomanip>
 
+#include <algorithm>
 #include <memory>
 
 #include <android-base/file.h>
@@ -38,22 +40,24 @@
 
 static fdevent* listener_fde = nullptr;
 static fdevent* framework_fde = nullptr;
-static int framework_fd = -1;
+static auto& framework_mutex = *new std::mutex();
+static int framework_fd GUARDED_BY(framework_mutex) = -1;
+static auto& connected_keys GUARDED_BY(framework_mutex) = *new std::vector<std::string>;
 
-static void usb_disconnected(void* unused, atransport* t);
-static struct adisconnect usb_disconnect = { usb_disconnected, nullptr};
-static atransport* usb_transport;
+static void adb_disconnected(void* unused, atransport* t);
+static struct adisconnect adb_disconnect = {adb_disconnected, nullptr};
+static atransport* adb_transport;
 static bool needs_retry = false;
 
 bool auth_required = true;
 
-bool adbd_auth_verify(const char* token, size_t token_size, const std::string& sig) {
+bool adbd_auth_verify(const char* token, size_t token_size, const std::string& sig,
+                      std::string* auth_key) {
     static constexpr const char* key_paths[] = { "/adb_keys", "/data/misc/adb/adb_keys", nullptr };
 
     for (const auto& path : key_paths) {
         if (access(path, R_OK) == 0) {
             LOG(INFO) << "Loading keys from " << path;
-
             std::string content;
             if (!android::base::ReadFileToString(path, &content)) {
                 PLOG(ERROR) << "Couldn't read " << path;
@@ -61,6 +65,8 @@
             }
 
             for (const auto& line : android::base::Split(content, "\n")) {
+                if (line.empty()) continue;
+                *auth_key = line;
                 // TODO: do we really have to support both ' ' and '\t'?
                 char* sep = strpbrk(const_cast<char*>(line.c_str()), " \t");
                 if (sep) *sep = '\0';
@@ -88,9 +94,31 @@
             }
         }
     }
+    auth_key->clear();
     return false;
 }
 
+static bool adbd_send_key_message_locked(std::string_view msg_type, std::string_view key)
+        REQUIRES(framework_mutex) {
+    if (framework_fd < 0) {
+        LOG(ERROR) << "Client not connected to send msg_type " << msg_type;
+        return false;
+    }
+    std::string msg = std::string(msg_type) + std::string(key);
+    int msg_len = msg.length();
+    if (msg_len >= static_cast<int>(MAX_FRAMEWORK_PAYLOAD)) {
+        LOG(ERROR) << "Key too long (" << msg_len << ")";
+        return false;
+    }
+
+    LOG(DEBUG) << "Sending '" << msg << "'";
+    if (!WriteFdExactly(framework_fd, msg.c_str(), msg_len)) {
+        PLOG(ERROR) << "Failed to write " << msg_type;
+        return false;
+    }
+    return true;
+}
+
 static bool adbd_auth_generate_token(void* token, size_t token_size) {
     FILE* fp = fopen("/dev/urandom", "re");
     if (!fp) return false;
@@ -99,17 +127,28 @@
     return okay;
 }
 
-static void usb_disconnected(void* unused, atransport* t) {
-    LOG(INFO) << "USB disconnect";
-    usb_transport = nullptr;
+static void adb_disconnected(void* unused, atransport* t) {
+    LOG(INFO) << "ADB disconnect";
+    adb_transport = nullptr;
     needs_retry = false;
+    {
+        std::lock_guard<std::mutex> lock(framework_mutex);
+        if (framework_fd >= 0) {
+            adbd_send_key_message_locked("DC", t->auth_key);
+        }
+        connected_keys.erase(std::remove(connected_keys.begin(), connected_keys.end(), t->auth_key),
+                             connected_keys.end());
+    }
 }
 
 static void framework_disconnected() {
     LOG(INFO) << "Framework disconnect";
     if (framework_fde) {
         fdevent_destroy(framework_fde);
-        framework_fd = -1;
+        {
+            std::lock_guard<std::mutex> lock(framework_mutex);
+            framework_fd = -1;
+        }
     }
 }
 
@@ -120,41 +159,28 @@
         if (ret <= 0) {
             framework_disconnected();
         } else if (ret == 2 && response[0] == 'O' && response[1] == 'K') {
-            if (usb_transport) {
-                adbd_auth_verified(usb_transport);
+            if (adb_transport) {
+                adbd_auth_verified(adb_transport);
             }
         }
     }
 }
 
-void adbd_auth_confirm_key(const char* key, size_t len, atransport* t) {
-    if (!usb_transport) {
-        usb_transport = t;
-        t->AddDisconnect(&usb_disconnect);
+void adbd_auth_confirm_key(atransport* t) {
+    if (!adb_transport) {
+        adb_transport = t;
+        t->AddDisconnect(&adb_disconnect);
     }
 
-    if (framework_fd < 0) {
-        LOG(ERROR) << "Client not connected";
-        needs_retry = true;
-        return;
-    }
+    {
+        std::lock_guard<std::mutex> lock(framework_mutex);
+        if (framework_fd < 0) {
+            LOG(ERROR) << "Client not connected";
+            needs_retry = true;
+            return;
+        }
 
-    if (key[len - 1] != '\0') {
-        LOG(ERROR) << "Key must be a null-terminated string";
-        return;
-    }
-
-    char msg[MAX_PAYLOAD_V1];
-    int msg_len = snprintf(msg, sizeof(msg), "PK%s", key);
-    if (msg_len >= static_cast<int>(sizeof(msg))) {
-        LOG(ERROR) << "Key too long (" << msg_len << ")";
-        return;
-    }
-    LOG(DEBUG) << "Sending '" << msg << "'";
-
-    if (unix_write(framework_fd, msg, msg_len) == -1) {
-        PLOG(ERROR) << "Failed to write PK";
-        return;
+        adbd_send_key_message_locked("PK", t->auth_key);
     }
 }
 
@@ -165,18 +191,46 @@
         return;
     }
 
-    if (framework_fd >= 0) {
-        LOG(WARNING) << "adb received framework auth socket connection again";
-        framework_disconnected();
+    {
+        std::lock_guard<std::mutex> lock(framework_mutex);
+        if (framework_fd >= 0) {
+            LOG(WARNING) << "adb received framework auth socket connection again";
+            framework_disconnected();
+        }
+
+        framework_fd = s;
+        framework_fde = fdevent_create(framework_fd, adbd_auth_event, nullptr);
+        fdevent_add(framework_fde, FDE_READ);
+
+        if (needs_retry) {
+            needs_retry = false;
+            send_auth_request(adb_transport);
+        }
+
+        // if a client connected before the framework was available notify the framework of the
+        // connected key now.
+        if (!connected_keys.empty()) {
+            for (const auto& key : connected_keys) {
+                adbd_send_key_message_locked("CK", key);
+            }
+        }
     }
+}
 
-    framework_fd = s;
-    framework_fde = fdevent_create(framework_fd, adbd_auth_event, nullptr);
-    fdevent_add(framework_fde, FDE_READ);
-
-    if (needs_retry) {
-        needs_retry = false;
-        send_auth_request(usb_transport);
+void adbd_notify_framework_connected_key(atransport* t) {
+    if (!adb_transport) {
+        adb_transport = t;
+        t->AddDisconnect(&adb_disconnect);
+    }
+    {
+        std::lock_guard<std::mutex> lock(framework_mutex);
+        if (std::find(connected_keys.begin(), connected_keys.end(), t->auth_key) ==
+            connected_keys.end()) {
+            connected_keys.push_back(t->auth_key);
+        }
+        if (framework_fd >= 0) {
+            adbd_send_key_message_locked("CK", t->auth_key);
+        }
     }
 }
 
diff --git a/adb/daemon/usb.cpp b/adb/daemon/usb.cpp
index f4aa9fb..1abae87 100644
--- a/adb/daemon/usb.cpp
+++ b/adb/daemon/usb.cpp
@@ -509,16 +509,14 @@
             }
 
             if (id.direction == TransferDirection::READ) {
-                if (!HandleRead(id, event.res)) {
-                    return;
-                }
+                HandleRead(id, event.res);
             } else {
                 HandleWrite(id);
             }
         }
     }
 
-    bool HandleRead(TransferId id, int64_t size) {
+    void HandleRead(TransferId id, int64_t size) {
         uint64_t read_idx = id.id % kUsbReadQueueDepth;
         IoBlock* block = &read_requests_[read_idx];
         block->pending = false;
@@ -528,7 +526,7 @@
         if (block->id().id != needed_read_id_) {
             LOG(VERBOSE) << "read " << block->id().id << " completed while waiting for "
                          << needed_read_id_;
-            return true;
+            return;
         }
 
         for (uint64_t id = needed_read_id_;; ++id) {
@@ -537,22 +535,15 @@
             if (current_block->pending) {
                 break;
             }
-            if (!ProcessRead(current_block)) {
-                return false;
-            }
+            ProcessRead(current_block);
             ++needed_read_id_;
         }
-
-        return true;
     }
 
-    bool ProcessRead(IoBlock* block) {
+    void ProcessRead(IoBlock* block) {
         if (!block->payload->empty()) {
             if (!incoming_header_.has_value()) {
-                if (block->payload->size() != sizeof(amessage)) {
-                    HandleError("received packet of unexpected length while reading header");
-                    return false;
-                }
+                CHECK_EQ(sizeof(amessage), block->payload->size());
                 amessage msg;
                 memcpy(&msg, block->payload->data(), sizeof(amessage));
                 LOG(DEBUG) << "USB read:" << dump_header(&msg);
@@ -560,10 +551,7 @@
             } else {
                 size_t bytes_left = incoming_header_->data_length - incoming_payload_.size();
                 Block payload = std::move(*block->payload);
-                if (block->payload->size() > bytes_left) {
-                    HandleError("received too many bytes while waiting for payload");
-                    return false;
-                }
+                CHECK_LE(payload.size(), bytes_left);
                 incoming_payload_.append(std::make_unique<Block>(std::move(payload)));
             }
 
@@ -582,7 +570,6 @@
 
         PrepareReadBlock(block, block->id().id + kUsbReadQueueDepth);
         SubmitRead(block);
-        return true;
     }
 
     bool SubmitRead(IoBlock* block) {
diff --git a/adb/daemon/usb_ffs.cpp b/adb/daemon/usb_ffs.cpp
index a64ce40..338d776 100644
--- a/adb/daemon/usb_ffs.cpp
+++ b/adb/daemon/usb_ffs.cpp
@@ -299,7 +299,6 @@
         }
         // Signal only when writing the descriptors to ffs
         android::base::SetProperty("sys.usb.ffs.ready", "1");
-        *out_control = std::move(control);
     }
 
     bulk_out.reset(adb_open(USB_FFS_ADB_OUT, O_RDONLY));
@@ -314,6 +313,7 @@
         return false;
     }
 
+    *out_control = std::move(control);
     *out_bulk_in = std::move(bulk_in);
     *out_bulk_out = std::move(bulk_out);
     return true;
diff --git a/adb/transport.h b/adb/transport.h
index f4490ed..3473ca2 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -274,6 +274,9 @@
     std::string device;
     std::string devpath;
 
+    // Used to provide the key to the framework.
+    std::string auth_key;
+
     bool IsTcpDevice() const { return type == kTransportLocal; }
 
 #if ADB_HOST
diff --git a/base/include/android-base/logging.h b/base/include/android-base/logging.h
index f94cc25..ab6476c 100644
--- a/base/include/android-base/logging.h
+++ b/base/include/android-base/logging.h
@@ -469,7 +469,7 @@
 }  // namespace base
 }  // namespace android
 
-namespace std {
+namespace std {  // NOLINT(cert-dcl58-cpp)
 
 // Emit a warning of ostream<< with std::string*. The intention was most likely to print *string.
 //
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index 6936cc2..8e7d918 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -1093,8 +1093,8 @@
 void LogBootInfoToStatsd(std::chrono::milliseconds end_time,
                          std::chrono::milliseconds total_duration, int32_t bootloader_duration_ms,
                          double time_since_last_boot_sec) {
-  const auto reason = android::base::GetProperty(bootloader_reboot_reason_property, "<EMPTY>");
-  const auto system_reason = android::base::GetProperty(system_reboot_reason_property, "<EMPTY>");
+  auto reason = android::base::GetProperty(bootloader_reboot_reason_property, "<EMPTY>");
+  auto system_reason = android::base::GetProperty(system_reboot_reason_property, "<EMPTY>");
   android::util::stats_write(android::util::BOOT_SEQUENCE_REPORTED, reason.c_str(),
                              system_reason.c_str(), end_time.count(), total_duration.count(),
                              (int64_t)bootloader_duration_ms,
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index c436be3..8923f40 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -144,14 +144,13 @@
     { "dts",      "dt.img",           "dt.sig",       "dts",      true,  ImageType::BootCritical },
     { "odm",      "odm.img",          "odm.sig",      "odm",      true,  ImageType::Normal },
     { "product",  "product.img",      "product.sig",  "product",  true,  ImageType::Normal },
-    { "product_services",
-                  "product_services.img",
-                                      "product_services.sig",
-                                                      "product_services",
-                                                                  true,  ImageType::Normal },
     { "recovery", "recovery.img",     "recovery.sig", "recovery", true,  ImageType::BootCritical },
     { "super",    "super.img",        "super.sig",    "super",    true,  ImageType::Extra },
     { "system",   "system.img",       "system.sig",   "system",   false, ImageType::Normal },
+    { "system_ext",
+                  "system_ext.img",   "system_ext.sig",
+                                                      "system_ext",
+                                                                  true,  ImageType::Normal },
     { nullptr,    "system_other.img", "system.sig",   "system",   true,  ImageType::Normal },
     { "userdata", "userdata.img",     "userdata.sig", "userdata", true,  ImageType::Extra },
     { "vbmeta",   "vbmeta.img",       "vbmeta.sig",   "vbmeta",   true,  ImageType::BootCritical },
diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h
index afcb090..08376c0 100644
--- a/fs_mgr/libdm/include/libdm/dm.h
+++ b/fs_mgr/libdm/include/libdm/dm.h
@@ -38,7 +38,7 @@
 #define DM_VERSION2 (0)
 
 #define DM_ALIGN_MASK (7)
-#define DM_ALIGN(x) ((x + DM_ALIGN_MASK) & ~DM_ALIGN_MASK)
+#define DM_ALIGN(x) (((x) + DM_ALIGN_MASK) & ~DM_ALIGN_MASK)
 
 namespace android {
 namespace dm {
diff --git a/fs_mgr/libfiemap_writer/split_fiemap_writer.cpp b/fs_mgr/libfiemap_writer/split_fiemap_writer.cpp
index a0ccc10..16a82d2 100644
--- a/fs_mgr/libfiemap_writer/split_fiemap_writer.cpp
+++ b/fs_mgr/libfiemap_writer/split_fiemap_writer.cpp
@@ -95,8 +95,9 @@
         // To make sure the alignment doesn't create too much inconsistency, we
         // account the *actual* size, not the requested size.
         total_bytes_written += writer->size();
-        remaining_bytes -= writer->size();
-
+        // writer->size() is block size aligned and could be bigger than remaining_bytes
+        // If remaining_bytes is bigger, set remaining_bytes to 0 to avoid underflow error.
+        remaining_bytes = remaining_bytes > writer->size() ? (remaining_bytes - writer->size()) : 0;
         out->AddFile(std::move(writer));
     }
 
diff --git a/healthd/Android.mk b/healthd/Android.mk
index d18f15a..05123af 100644
--- a/healthd/Android.mk
+++ b/healthd/Android.mk
@@ -93,7 +93,6 @@
     libbinderthreadstate \
     libhidltransport \
     libhidlbase \
-    libhwbinder_noltopgo \
     libhealthstoragedefault \
     libvndksupport \
     libhealthd_charger \
@@ -152,7 +151,6 @@
     libbinderthreadstate \
     libhidltransport \
     libhidlbase \
-    libhwbinder_noltopgo \
     libhealthstoragedefault \
     libvndksupport \
     libhealthd_charger_nops \
diff --git a/init/Android.bp b/init/Android.bp
index 6bc581d..86dcb4c 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -26,6 +26,7 @@
         "-Wextra",
         "-Wno-unused-parameter",
         "-Werror",
+        "-DALLOW_FIRST_STAGE_CONSOLE=0",
         "-DALLOW_LOCAL_PROP_OVERRIDE=0",
         "-DALLOW_PERMISSIVE_SELINUX=0",
         "-DREBOOT_BOOTLOADER_ON_PANIC=0",
@@ -36,6 +37,8 @@
     product_variables: {
         debuggable: {
             cppflags: [
+                "-UALLOW_FIRST_STAGE_CONSOLE",
+                "-DALLOW_FIRST_STAGE_CONSOLE=1",
                 "-UALLOW_LOCAL_PROP_OVERRIDE",
                 "-DALLOW_LOCAL_PROP_OVERRIDE=1",
                 "-UALLOW_PERMISSIVE_SELINUX",
diff --git a/init/Android.mk b/init/Android.mk
index b24f757..9017772 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -8,6 +8,7 @@
 
 ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
 init_options += \
+    -DALLOW_FIRST_STAGE_CONSOLE=1 \
     -DALLOW_LOCAL_PROP_OVERRIDE=1 \
     -DALLOW_PERMISSIVE_SELINUX=1 \
     -DREBOOT_BOOTLOADER_ON_PANIC=1 \
@@ -15,6 +16,7 @@
     -DDUMP_ON_UMOUNT_FAILURE=1
 else
 init_options += \
+    -DALLOW_FIRST_STAGE_CONSOLE=0 \
     -DALLOW_LOCAL_PROP_OVERRIDE=0 \
     -DALLOW_PERMISSIVE_SELINUX=0 \
     -DREBOOT_BOOTLOADER_ON_PANIC=0 \
diff --git a/init/action_manager.cpp b/init/action_manager.cpp
index 9de4085..985b8ad 100644
--- a/init/action_manager.cpp
+++ b/init/action_manager.cpp
@@ -88,7 +88,8 @@
         current_command_ = 0;
         if (action->oneshot()) {
             auto eraser = [&action](std::unique_ptr<Action>& a) { return a.get() == action; };
-            actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser));
+            actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser),
+                           actions_.end());
         }
     }
 }
diff --git a/init/builtins.cpp b/init/builtins.cpp
index cc84aa0..ba2c7ac 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -243,7 +243,7 @@
 
     strlcpy(ifr.ifr_name, args[1].c_str(), IFNAMSIZ);
 
-    unique_fd s(TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_DGRAM, 0)));
+    unique_fd s(TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0)));
     if (s < 0) return ErrnoError() << "opening socket failed";
 
     if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) {
@@ -784,7 +784,7 @@
 }
 
 static Result<void> readahead_file(const std::string& filename, bool fully) {
-    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filename.c_str(), O_RDONLY)));
+    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filename.c_str(), O_RDONLY | O_CLOEXEC)));
     if (fd == -1) {
         return ErrnoError() << "Error opening file";
     }
@@ -1107,7 +1107,7 @@
         // /apex/<name> paths, so unless we filter them out, we will parse the
         // same file twice.
         std::vector<std::string> paths = android::base::Split(path, "/");
-        if (paths.size() >= 2 && paths[1].find('@') != std::string::npos) {
+        if (paths.size() >= 3 && paths[2].find('@') != std::string::npos) {
             continue;
         }
         configs.push_back(path);
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index 17387e2..b60c450 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -24,10 +24,12 @@
 #include <sys/stat.h>
 #include <sys/sysmacros.h>
 #include <sys/types.h>
+#include <sys/wait.h>
 #include <unistd.h>
 
 #include <filesystem>
 #include <string>
+#include <thread>
 #include <vector>
 
 #include <android-base/chrono_utils.h>
@@ -76,7 +78,7 @@
 
             if (S_ISDIR(info.st_mode)) {
                 is_dir = true;
-                auto fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY);
+                auto fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
                 if (fd >= 0) {
                     auto subdir =
                             std::unique_ptr<DIR, decltype(&closedir)>{fdopendir(fd), closedir};
@@ -92,9 +94,50 @@
     }
 }
 
-bool ForceNormalBoot() {
-    std::string cmdline;
-    android::base::ReadFileToString("/proc/cmdline", &cmdline);
+void StartConsole() {
+    if (mknod("/dev/console", S_IFCHR | 0600, makedev(5, 1))) {
+        PLOG(ERROR) << "unable to create /dev/console";
+        return;
+    }
+    pid_t pid = fork();
+    if (pid != 0) {
+        int status;
+        waitpid(pid, &status, 0);
+        LOG(ERROR) << "console shell exited with status " << status;
+        return;
+    }
+    int fd = -1;
+    int tries = 10;
+    // The device driver for console may not be ready yet so retry for a while in case of failure.
+    while (tries--) {
+        fd = open("/dev/console", O_RDWR);
+        if (fd != -1) {
+            break;
+        }
+        std::this_thread::sleep_for(100ms);
+    }
+    if (fd == -1) {
+        LOG(ERROR) << "Could not open /dev/console, errno = " << errno;
+        _exit(127);
+    }
+    ioctl(fd, TIOCSCTTY, 0);
+    dup2(fd, 0);
+    dup2(fd, 1);
+    dup2(fd, 2);
+    close(fd);
+
+    const char* path = "/system/bin/sh";
+    const char* args[] = {path, nullptr};
+    int rv = execv(path, const_cast<char**>(args));
+    LOG(ERROR) << "unable to execv, returned " << rv << " errno " << errno;
+    _exit(127);
+}
+
+bool FirstStageConsole(const std::string& cmdline) {
+    return cmdline.find("androidboot.first_stage_console=1") != std::string::npos;
+}
+
+bool ForceNormalBoot(const std::string& cmdline) {
     return cmdline.find("androidboot.force_normal_boot=1") != std::string::npos;
 }
 
@@ -109,7 +152,7 @@
 
     std::vector<std::pair<std::string, int>> errors;
 #define CHECKCALL(x) \
-    if (x != 0) errors.emplace_back(#x " failed", errno);
+    if ((x) != 0) errors.emplace_back(#x " failed", errno);
 
     // Clear the umask.
     umask(0);
@@ -127,6 +170,8 @@
 #undef MAKE_STR
     // Don't expose the raw commandline to unprivileged processes.
     CHECKCALL(chmod("/proc/cmdline", 0440));
+    std::string cmdline;
+    android::base::ReadFileToString("/proc/cmdline", &cmdline);
     gid_t groups[] = {AID_READPROC};
     CHECKCALL(setgroups(arraysize(groups), groups));
     CHECKCALL(mount("sysfs", "/sys", "sysfs", 0, NULL));
@@ -198,7 +243,11 @@
         LOG(FATAL) << "Failed to load kernel modules";
     }
 
-    if (ForceNormalBoot()) {
+    if (ALLOW_FIRST_STAGE_CONSOLE && FirstStageConsole(cmdline)) {
+        StartConsole();
+    }
+
+    if (ForceNormalBoot(cmdline)) {
         mkdir("/first_stage_ramdisk", 0755);
         // SwitchRoot() must be called with a mount point as the target, so we bind mount the
         // target directory to itself here.
diff --git a/init/persistent_properties.cpp b/init/persistent_properties.cpp
index 73787b9..baa9ad4 100644
--- a/init/persistent_properties.cpp
+++ b/init/persistent_properties.cpp
@@ -69,7 +69,7 @@
             continue;
         }
 
-        unique_fd fd(openat(dirfd(dir.get()), entry->d_name, O_RDONLY | O_NOFOLLOW));
+        unique_fd fd(openat(dirfd(dir.get()), entry->d_name, O_RDONLY | O_NOFOLLOW | O_CLOEXEC));
         if (fd == -1) {
             PLOG(ERROR) << "Unable to open persistent property file \"" << entry->d_name << "\"";
             continue;
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 1520c9f..b89914f 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -667,9 +667,9 @@
 
             if (flen > 0) {
                 if (filter[flen - 1] == '*') {
-                    if (strncmp(key, filter, flen - 1)) continue;
+                    if (strncmp(key, filter, flen - 1) != 0) continue;
                 } else {
-                    if (strcmp(key, filter)) continue;
+                    if (strcmp(key, filter) != 0) continue;
                 }
             }
 
diff --git a/init/service.cpp b/init/service.cpp
index cd08f3d..f95b675 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -126,7 +126,7 @@
     : Service(name, 0, 0, 0, {}, 0, "", subcontext_for_restart_commands, args) {}
 
 Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
-                 const std::vector<gid_t>& supp_gids, unsigned namespace_flags,
+                 const std::vector<gid_t>& supp_gids, int namespace_flags,
                  const std::string& seclabel, Subcontext* subcontext_for_restart_commands,
                  const std::vector<std::string>& args)
     : name_(name),
diff --git a/init/service.h b/init/service.h
index 78f94ce..cc35a8d 100644
--- a/init/service.h
+++ b/init/service.h
@@ -69,9 +69,8 @@
             const std::vector<std::string>& args);
 
     Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
-            const std::vector<gid_t>& supp_gids, unsigned namespace_flags,
-            const std::string& seclabel, Subcontext* subcontext_for_restart_commands,
-            const std::vector<std::string>& args);
+            const std::vector<gid_t>& supp_gids, int namespace_flags, const std::string& seclabel,
+            Subcontext* subcontext_for_restart_commands, const std::vector<std::string>& args);
 
     static std::unique_ptr<Service> MakeTemporaryOneshotService(const std::vector<std::string>& args);
 
@@ -109,7 +108,7 @@
     int crash_count() const { return crash_count_; }
     uid_t uid() const { return proc_attr_.uid; }
     gid_t gid() const { return proc_attr_.gid; }
-    unsigned namespace_flags() const { return namespaces_.flags; }
+    int namespace_flags() const { return namespaces_.flags; }
     const std::vector<gid_t>& supp_gids() const { return proc_attr_.supp_gids; }
     const std::string& seclabel() const { return seclabel_; }
     const std::vector<int>& keycodes() const { return keycodes_; }
diff --git a/init/service_test.cpp b/init/service_test.cpp
index 4bfaa6b..6a34acc 100644
--- a/init/service_test.cpp
+++ b/init/service_test.cpp
@@ -30,7 +30,7 @@
 
 TEST(service, pod_initialized) {
     constexpr auto memory_size = sizeof(Service);
-    alignas(alignof(Service)) char old_memory[memory_size];
+    alignas(alignof(Service)) unsigned char old_memory[memory_size];
 
     for (std::size_t i = 0; i < memory_size; ++i) {
         old_memory[i] = 0xFF;
@@ -45,7 +45,7 @@
     EXPECT_EQ(0, service_in_old_memory->crash_count());
     EXPECT_EQ(0U, service_in_old_memory->uid());
     EXPECT_EQ(0U, service_in_old_memory->gid());
-    EXPECT_EQ(0U, service_in_old_memory->namespace_flags());
+    EXPECT_EQ(0, service_in_old_memory->namespace_flags());
     EXPECT_EQ(IoSchedClass_NONE, service_in_old_memory->ioprio_class());
     EXPECT_EQ(0, service_in_old_memory->ioprio_pri());
     EXPECT_EQ(0, service_in_old_memory->priority());
@@ -64,7 +64,7 @@
     EXPECT_EQ(0, service_in_old_memory2->crash_count());
     EXPECT_EQ(0U, service_in_old_memory2->uid());
     EXPECT_EQ(0U, service_in_old_memory2->gid());
-    EXPECT_EQ(0U, service_in_old_memory2->namespace_flags());
+    EXPECT_EQ(0, service_in_old_memory2->namespace_flags());
     EXPECT_EQ(IoSchedClass_NONE, service_in_old_memory2->ioprio_class());
     EXPECT_EQ(0, service_in_old_memory2->ioprio_pri());
     EXPECT_EQ(0, service_in_old_memory2->priority());
diff --git a/init/service_utils.cpp b/init/service_utils.cpp
index f88ea97..34aa837 100644
--- a/init/service_utils.cpp
+++ b/init/service_utils.cpp
@@ -120,22 +120,19 @@
 }
 
 void ZapStdio() {
-    int fd;
-    fd = open("/dev/null", O_RDWR);
+    auto fd = unique_fd{open("/dev/null", O_RDWR | O_CLOEXEC)};
     dup2(fd, 0);
     dup2(fd, 1);
     dup2(fd, 2);
-    close(fd);
 }
 
 void OpenConsole(const std::string& console) {
-    int fd = open(console.c_str(), O_RDWR);
-    if (fd == -1) fd = open("/dev/null", O_RDWR);
+    auto fd = unique_fd{open(console.c_str(), O_RDWR | O_CLOEXEC)};
+    if (fd == -1) fd.reset(open("/dev/null", O_RDWR | O_CLOEXEC));
     ioctl(fd, TIOCSCTTY, 0);
     dup2(fd, 0);
     dup2(fd, 1);
     dup2(fd, 2);
-    close(fd);
 }
 
 }  // namespace
diff --git a/init/service_utils.h b/init/service_utils.h
index c26b123..365cb29 100644
--- a/init/service_utils.h
+++ b/init/service_utils.h
@@ -30,7 +30,7 @@
 namespace init {
 
 struct NamespaceInfo {
-    unsigned flags;
+    int flags;
     // Pair of namespace type, path to name.
     std::vector<std::pair<int, std::string>> namespaces_to_enter;
 };
diff --git a/init/subcontext.cpp b/init/subcontext.cpp
index 02ed507..2f9541b 100644
--- a/init/subcontext.cpp
+++ b/init/subcontext.cpp
@@ -246,7 +246,7 @@
 
         // We explicitly do not use O_CLOEXEC here, such that we can reference this FD by number
         // in the subcontext process after we exec.
-        int child_fd = dup(subcontext_socket);
+        int child_fd = dup(subcontext_socket);  // NOLINT(android-cloexec-dup)
         if (child_fd < 0) {
             PLOG(FATAL) << "Could not dup child_fd";
         }
diff --git a/init/tokenizer_test.cpp b/init/tokenizer_test.cpp
index acfc7c7..6b31683 100644
--- a/init/tokenizer_test.cpp
+++ b/init/tokenizer_test.cpp
@@ -46,6 +46,7 @@
                 return;
             case T_NEWLINE:
                 tokens.emplace_back(std::move(current_line));
+                current_line.clear();
                 break;
             case T_TEXT:
                 current_line.emplace_back(state.text);
diff --git a/init/uevent_listener.cpp b/init/uevent_listener.cpp
index 62cd2be..ac633776 100644
--- a/init/uevent_listener.cpp
+++ b/init/uevent_listener.cpp
@@ -131,7 +131,7 @@
                                                        const ListenerCallback& callback) const {
     int dfd = dirfd(d);
 
-    int fd = openat(dfd, "uevent", O_WRONLY);
+    int fd = openat(dfd, "uevent", O_WRONLY | O_CLOEXEC);
     if (fd >= 0) {
         write(fd, "add\n", 4);
         close(fd);
@@ -146,7 +146,7 @@
     while ((de = readdir(d)) != nullptr) {
         if (de->d_type != DT_DIR || de->d_name[0] == '.') continue;
 
-        fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY);
+        fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
         if (fd < 0) continue;
 
         std::unique_ptr<DIR, decltype(&closedir)> d2(fdopendir(fd), closedir);
diff --git a/init/util.cpp b/init/util.cpp
index 2b34242..058a111 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -450,7 +450,7 @@
 // SetStdioToDevNull() must be called again in second stage init.
 void SetStdioToDevNull(char** argv) {
     // Make stdin/stdout/stderr all point to /dev/null.
-    int fd = open("/dev/null", O_RDWR);
+    int fd = open("/dev/null", O_RDWR);  // NOLINT(android-cloexec-open)
     if (fd == -1) {
         int saved_errno = errno;
         android::base::InitLogging(argv, &android::base::KernelLogger, InitAborter);
diff --git a/libappfuse/FuseBridgeLoop.cc b/libappfuse/FuseBridgeLoop.cc
index f1ca446..f71d0c3 100644
--- a/libappfuse/FuseBridgeLoop.cc
+++ b/libappfuse/FuseBridgeLoop.cc
@@ -86,6 +86,7 @@
         const bool proxy_read_ready = last_proxy_events_.events & EPOLLIN;
         const bool proxy_write_ready = last_proxy_events_.events & EPOLLOUT;
 
+        last_state_ = state_;
         last_device_events_.events = 0;
         last_proxy_events_.events = 0;
 
diff --git a/libcutils/include/cutils/native_handle.h b/libcutils/include/cutils/native_handle.h
index f6cae36..4f07456 100644
--- a/libcutils/include/cutils/native_handle.h
+++ b/libcutils/include/cutils/native_handle.h
@@ -69,10 +69,11 @@
 
 /*
  * native_handle_create
- * 
+ *
  * creates a native_handle_t and initializes it. must be destroyed with
- * native_handle_delete().
- * 
+ * native_handle_delete(). Note that numFds must be <= NATIVE_HANDLE_MAX_FDS,
+ * numInts must be <= NATIVE_HANDLE_MAX_INTS, and both must be >= 0.
+ *
  */
 native_handle_t* native_handle_create(int numFds, int numInts);
 
diff --git a/libmeminfo/procmeminfo.cpp b/libmeminfo/procmeminfo.cpp
index caf6e86..a8b43c1 100644
--- a/libmeminfo/procmeminfo.cpp
+++ b/libmeminfo/procmeminfo.cpp
@@ -312,12 +312,12 @@
                                     cur_page * sizeof(uint64_t));
             if (bytes != total_bytes) {
                 if (bytes == -1) {
-                    PLOG(ERROR) << "Failed to read page data at offset "
+                    PLOG(ERROR) << "Failed to read page data at offset 0x" << std::hex
                                 << cur_page * sizeof(uint64_t);
                 } else {
-                    LOG(ERROR) << "Failed to read page data at offset "
-                               << cur_page * sizeof(uint64_t) << " read bytes " << sizeof(uint64_t)
-                               << " expected bytes " << bytes;
+                    LOG(ERROR) << "Failed to read page data at offset 0x" << std::hex
+                               << cur_page * sizeof(uint64_t) << std::dec << " read bytes " << bytes
+                               << " expected bytes " << total_bytes;
                 }
                 return false;
             }
diff --git a/libmemunreachable/Android.bp b/libmemunreachable/Android.bp
index 62a7266..f1abdd2 100644
--- a/libmemunreachable/Android.bp
+++ b/libmemunreachable/Android.bp
@@ -111,7 +111,7 @@
     static_libs: ["libmemunreachable"],
     shared_libs: [
         "libbinder",
-        "libhwbinder",
+        "libhidlbase",
         "libutils",
     ],
     test_suites: ["device-tests"],
diff --git a/libstats/statsd_writer.c b/libstats/statsd_writer.c
index b778f92..b1c05ea 100644
--- a/libstats/statsd_writer.c
+++ b/libstats/statsd_writer.c
@@ -109,6 +109,11 @@
         if (sock < 0) {
             ret = -errno;
         } else {
+            int sndbuf = 1 * 1024 * 1024;  // set max send buffer size 1MB
+            socklen_t bufLen = sizeof(sndbuf);
+            // SO_RCVBUF does not have an effect on unix domain socket, but SO_SNDBUF does.
+            // Proceed to connect even setsockopt fails.
+            setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sndbuf, bufLen);
             struct sockaddr_un un;
             memset(&un, 0, sizeof(struct sockaddr_un));
             un.sun_family = AF_UNIX;
diff --git a/libsystem/include/system/graphics-base-v1.2.h b/libsystem/include/system/graphics-base-v1.2.h
new file mode 100644
index 0000000..2194f5e
--- /dev/null
+++ b/libsystem/include/system/graphics-base-v1.2.h
@@ -0,0 +1,31 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+// Source: android.hardware.graphics.common@1.2
+// Location: hardware/interfaces/graphics/common/1.2/
+
+#ifndef HIDL_GENERATED_ANDROID_HARDWARE_GRAPHICS_COMMON_V1_2_EXPORTED_CONSTANTS_H_
+#define HIDL_GENERATED_ANDROID_HARDWARE_GRAPHICS_COMMON_V1_2_EXPORTED_CONSTANTS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    HAL_HDR_HDR10_PLUS = 4,
+} android_hdr_v1_2_t;
+
+typedef enum {
+    HAL_DATASPACE_DISPLAY_BT2020 = 142999552 /* ((STANDARD_BT2020 | TRANSFER_SRGB) | RANGE_FULL) */,
+    HAL_DATASPACE_DYNAMIC_DEPTH = 4098 /* 0x1002 */,
+    HAL_DATASPACE_JPEG_APP_SEGMENTS = 4099 /* 0x1003 */,
+    HAL_DATASPACE_HEIF = 4100 /* 0x1004 */,
+} android_dataspace_v1_2_t;
+
+typedef enum {
+    HAL_PIXEL_FORMAT_HSV_888 = 55 /* 0x37 */,
+} android_pixel_format_v1_2_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // HIDL_GENERATED_ANDROID_HARDWARE_GRAPHICS_COMMON_V1_2_EXPORTED_CONSTANTS_H_
diff --git a/libsystem/include/system/graphics-base.h b/libsystem/include/system/graphics-base.h
index ea92007..92ee077 100644
--- a/libsystem/include/system/graphics-base.h
+++ b/libsystem/include/system/graphics-base.h
@@ -3,5 +3,6 @@
 
 #include "graphics-base-v1.0.h"
 #include "graphics-base-v1.1.h"
+#include "graphics-base-v1.2.h"
 
 #endif  // SYSTEM_CORE_GRAPHICS_BASE_H_
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 48140b8..521f92e 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -1373,8 +1373,8 @@
     set_process_group_and_prio(pid, SP_FOREGROUND, ANDROID_PRIORITY_HIGHEST);
 
     inc_killcnt(procp->oomadj);
-    ALOGI("Kill '%s' (%d), uid %d, oom_adj %d to free %ldkB",
-        taskname, pid, uid, procp->oomadj, tasksize * page_k);
+    ALOGE("Kill '%s' (%d), uid %d, oom_adj %d to free %ldkB", taskname, pid, uid, procp->oomadj,
+          tasksize * page_k);
 
     TRACE_KILL_END();
 
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 15e07fe..6e38d95 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -483,7 +483,8 @@
                     "                  Additionally, 'kernel' for userdebug and eng builds, and\n"
                     "                  'security' for Device Owner installations.\n"
                     "                  Multiple -b parameters or comma separated list of buffers are\n"
-                    "                  allowed. Buffers interleaved. Default -b main,system,crash.\n"
+                    "                  allowed. Buffers interleaved.\n"
+                    "                  Default -b main,system,crash,kernel.\n"
                     "  -B, --binary    Output the log in binary.\n"
                     "  -S, --statistics                       Output statistics.\n"
                     "  -p, --prune     Print prune white and ~black list. Service is specified as\n"
@@ -1312,6 +1313,10 @@
             dev = dev->next = new log_device_t("crash", false);
             context->devCount++;
         }
+        if (android_name_to_log_id("kernel") == LOG_ID_KERNEL) {
+            dev = dev->next = new log_device_t("kernel", false);
+            context->devCount++;
+        }
     }
 
     if (!!context->logRotateSizeKBytes && !context->outputFileName) {
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index f084cd2..246f9ac 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -113,10 +113,10 @@
 else
   LOCAL_POST_INSTALL_CMD += ; ln -sf /system/product $(TARGET_ROOT_OUT)/product
 endif
-ifdef BOARD_USES_PRODUCT_SERVICESIMAGE
-  LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/product_services
+ifdef BOARD_USES_SYSTEM_EXTIMAGE
+  LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/system_ext
 else
-  LOCAL_POST_INSTALL_CMD += ; ln -sf /system/product_services $(TARGET_ROOT_OUT)/product_services
+  LOCAL_POST_INSTALL_CMD += ; ln -sf /system/system_ext $(TARGET_ROOT_OUT)/system_ext
 endif
 ifdef BOARD_USES_METADATA_PARTITION
   LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/metadata
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index b1616d3..f732b3c 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -183,6 +183,7 @@
 namespace.media.asan.search.paths = /apex/com.android.media/${LIB}
 
 namespace.media.permitted.paths = /apex/com.android.media/${LIB}/extractors
+namespace.media.asan.permitted.paths = /apex/com.android.media/${LIB}/extractors
 
 namespace.media.links = default
 namespace.media.link.default.shared_libs  = %LLNDK_LIBRARIES%
@@ -651,6 +652,7 @@
 namespace.media.asan.search.paths = /apex/com.android.media/${LIB}
 
 namespace.media.permitted.paths = /apex/com.android.media/${LIB}/extractors
+namespace.media.asan.permitted.paths = /apex/com.android.media/${LIB}/extractors
 
 namespace.media.links = default
 namespace.media.link.default.shared_libs  = %LLNDK_LIBRARIES%
diff --git a/rootdir/etc/public.libraries.android.txt b/rootdir/etc/public.libraries.android.txt
index d8f6095..27e855f 100644
--- a/rootdir/etc/public.libraries.android.txt
+++ b/rootdir/etc/public.libraries.android.txt
@@ -1,6 +1,7 @@
 # See https://android.googlesource.com/platform/ndk/+/master/docs/PlatformApis.md
 libandroid.so
 libaaudio.so
+libamidi.so
 libbinder_ndk.so
 libc.so
 libcamera2ndk.so
diff --git a/rootdir/etc/public.libraries.iot.txt b/rootdir/etc/public.libraries.iot.txt
index 20905bf..b565340 100644
--- a/rootdir/etc/public.libraries.iot.txt
+++ b/rootdir/etc/public.libraries.iot.txt
@@ -2,6 +2,7 @@
 libandroid.so
 libandroidthings.so
 libaaudio.so
+libamidi.so
 libbinder_ndk.so
 libc.so
 libcamera2ndk.so
diff --git a/rootdir/etc/public.libraries.wear.txt b/rootdir/etc/public.libraries.wear.txt
index 4ece5b5..7cbda08 100644
--- a/rootdir/etc/public.libraries.wear.txt
+++ b/rootdir/etc/public.libraries.wear.txt
@@ -1,6 +1,7 @@
 # See https://android.googlesource.com/platform/ndk/+/master/docs/PlatformApis.md
 libandroid.so
 libaaudio.so
+libamidi.so
 libbinder_ndk.so
 libc.so
 libcamera2ndk.so
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 3acf301..55a1623 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -590,7 +590,6 @@
     symlink /data/data /data/user/0
 
     mkdir /data/media 0770 media_rw media_rw
-    mkdir /data/media/obb 0770 media_rw media_rw
 
     mkdir /data/cache 0770 system cache
     mkdir /data/cache/recovery 0770 system cache
@@ -667,6 +666,12 @@
     chown root system /sys/module/lowmemorykiller/parameters/minfree
     chmod 0664 /sys/module/lowmemorykiller/parameters/minfree
 
+    # System server manages zram writeback
+    chown root system /sys/block/zram0/idle
+    chmod 0664 /sys/block/zram0/idle
+    chown root system /sys/block/zram0/writeback
+    chmod 0664 /sys/block/zram0/writeback
+
     # Tweak background writeout
     write /proc/sys/vm/dirty_expire_centisecs 200
     write /proc/sys/vm/dirty_background_ratio  5
diff --git a/rootdir/init.usb.rc b/rootdir/init.usb.rc
index f0681d2..b6cba90 100644
--- a/rootdir/init.usb.rc
+++ b/rootdir/init.usb.rc
@@ -14,7 +14,7 @@
 # adbd is controlled via property triggers in init.<platform>.usb.rc
 service adbd /system/bin/adbd --root_seclabel=u:r:su:s0
     class core
-    socket adbd stream 660 system system
+    socket adbd seqpacket 660 system system
     disabled
     seclabel u:r:adbd:s0
 
diff --git a/rootdir/init.zygote32.rc b/rootdir/init.zygote32.rc
index f8e680d..bf3fb42 100644
--- a/rootdir/init.zygote32.rc
+++ b/rootdir/init.zygote32.rc
@@ -4,7 +4,7 @@
     user root
     group root readproc reserved_disk
     socket zygote stream 660 root system
-    socket blastula_pool stream 660 root system
+    socket usap_pool_primary stream 660 root system
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
     onrestart restart audioserver
diff --git a/rootdir/init.zygote32_64.rc b/rootdir/init.zygote32_64.rc
index 0235370..1bab588 100644
--- a/rootdir/init.zygote32_64.rc
+++ b/rootdir/init.zygote32_64.rc
@@ -4,7 +4,7 @@
     user root
     group root readproc reserved_disk
     socket zygote stream 660 root system
-    socket blastula_pool stream 660 root system
+    socket usap_pool_primary stream 660 root system
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
     onrestart restart audioserver
@@ -20,6 +20,6 @@
     user root
     group root readproc reserved_disk
     socket zygote_secondary stream 660 root system
-    socket blastula_pool_secondary stream 660 root system
+    socket usap_pool_secondary stream 660 root system
     onrestart restart zygote
     writepid /dev/cpuset/foreground/tasks
diff --git a/rootdir/init.zygote64.rc b/rootdir/init.zygote64.rc
index 3f3cc15..6fa210a 100644
--- a/rootdir/init.zygote64.rc
+++ b/rootdir/init.zygote64.rc
@@ -4,7 +4,7 @@
     user root
     group root readproc reserved_disk
     socket zygote stream 660 root system
-    socket blastula_pool stream 660 root system
+    socket usap_pool_primary stream 660 root system
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
     onrestart restart audioserver
diff --git a/rootdir/init.zygote64_32.rc b/rootdir/init.zygote64_32.rc
index fae38c9..48461ec 100644
--- a/rootdir/init.zygote64_32.rc
+++ b/rootdir/init.zygote64_32.rc
@@ -4,7 +4,7 @@
     user root
     group root readproc reserved_disk
     socket zygote stream 660 root system
-    socket blastula_pool stream 660 root system
+    socket usap_pool_primary stream 660 root system
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
     onrestart restart audioserver
@@ -20,6 +20,6 @@
     user root
     group root readproc reserved_disk
     socket zygote_secondary stream 660 root system
-    socket blastula_pool_secondary stream 660 root system
+    socket usap_pool_secondary stream 660 root system
     onrestart restart zygote
     writepid /dev/cpuset/foreground/tasks
diff --git a/sdcard/sdcard.cpp b/sdcard/sdcard.cpp
index 2b35819..0acea72 100644
--- a/sdcard/sdcard.cpp
+++ b/sdcard/sdcard.cpp
@@ -214,7 +214,14 @@
 
     if (multi_user) {
         std::string obb_path = source_path + "/obb";
-        fs_prepare_dir(obb_path.c_str(), 0775, uid, gid);
+        // Only attempt to prepare the /obb dir if it already exists. We want
+        // the legacy obb path "/data/media/obb" to be fixed up so that we can
+        // migrate it to its new location, but we don't want the directory to be
+        // created if it doesn't already exist.
+        struct stat sb;
+        if (TEMP_FAILURE_RETRY(lstat(obb_path.c_str(), &sb)) == 0) {
+            fs_prepare_dir(obb_path.c_str(), 0775, uid, gid);
+        }
     }
 
     exit(0);
diff --git a/shell_and_utilities/Android.bp b/shell_and_utilities/Android.bp
index 3bc3883..bac3dc3 100644
--- a/shell_and_utilities/Android.bp
+++ b/shell_and_utilities/Android.bp
@@ -13,7 +13,6 @@
         "auditctl",
         "awk",
         "bzip2",
-        "grep",
         "logwrapper",
         "mini-keyctl",
         "mkshrc",
@@ -32,7 +31,6 @@
 phony {
     name: "shell_and_utilities_recovery",
     required: [
-        "grep.recovery",
         "sh.recovery",
         "toolbox.recovery",
         "toybox.recovery",
@@ -44,7 +42,6 @@
     name: "shell_and_utilities_vendor",
     required: [
         "awk_vendor",
-        "grep_vendor",
         "logwrapper_vendor",
         "mkshrc_vendor",
         "sh_vendor",
diff --git a/toolbox/Android.bp b/toolbox/Android.bp
index 9ca5607..0cc603a 100644
--- a/toolbox/Android.bp
+++ b/toolbox/Android.bp
@@ -1,14 +1,10 @@
 cc_defaults {
     name: "toolbox_defaults",
-
     cflags: [
         "-Werror",
         "-Wno-unused-parameter",
         "-Wno-unused-const-variable",
         "-D_FILE_OFFSET_BITS=64",
-        "-DWITHOUT_NLS",
-        "-DWITHOUT_BZ2",
-        "-DWITHOUT_GZIP",
     ],
 }
 
@@ -60,39 +56,3 @@
     vendor: true,
     defaults: ["toolbox_binary_defaults"],
 }
-
-// We build BSD grep separately (but see http://b/111849261).
-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"],
-    recovery_available: true,
-}
-
-// 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/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 428bf58..0000000
--- a/toolbox/upstream-netbsd/usr.bin/grep/file.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/*	$NetBSD: file.c,v 1.10 2018/08/12 09:03:21 christos 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.10 2018/08/12 09:03:21 christos Exp $");
-
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#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>
-
-#include "grep.h"
-
-#define	MAXBUFSIZ	(32 * 1024)
-#define	LNBUFBUMP	80
-
-#ifndef WITHOUT_GZIP
-static gzFile gzbufdesc;
-#endif
-#ifndef WITHOUT_BZ2
-static BZFILE* bzbufdesc;
-#endif
-
-static unsigned char buffer[MAXBUFSIZ + 1];
-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 = -1;
-	int bzerr;
-
-	bufpos = buffer;
-	bufrem = 0;
-
-#ifndef WITHOUT_GZIP
-	if (filebehave == FILE_GZIP) {
-		nr = gzread(gzbufdesc, buffer, MAXBUFSIZ);
-		if (nr == -1)
-			return -1;
-	}
-#endif
-#ifndef WITHOUT_BZ2
-	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;
-		}
-		if (nr == -1)
-			return -1;
-	}
-#endif
-	if (nr == -1) {
-		nr = read(f->fd, buffer, MAXBUFSIZ);
-	}
-
-	if (nr < 0)
-		return (-1);
-
-	bufrem = nr;
-	return (0);
-}
-
-static inline void
-grep_lnbufgrow(size_t newlen)
-{
-
-	if (lnbuflen < newlen) {
-		lnbuf = grep_realloc(lnbuf, newlen);
-		lnbuflen = newlen;
-	}
-}
-
-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 */
-		len = p - bufpos;
-		grep_lnbufgrow(len + 1);
-		memcpy(lnbuf, bufpos, len);
-		lnbuf[len] = '\0';
-		*lenp = len;
-		bufrem -= len;
-		bufpos = p;
-		return ((char *)lnbuf);
-	}
-
-	/* 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 */
-		grep_lnbufgrow(len + LNBUFBUMP);
-		memcpy(lnbuf + off, bufpos, len - off);
-		lnbuf[len] = '\0';
-		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;
-		grep_lnbufgrow(len + 1);
-		memcpy(lnbuf + off, bufpos, diff);
-		lnbuf[off + diff] = '\0';
-		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 WITHOUT_GZIP
-	if (filebehave == FILE_GZIP &&
-	    (gzbufdesc = gzdopen(f->fd, "r")) == NULL)
-		goto error;
-#endif
-
-#ifndef WITHOUT_BZ2
-	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 bad2a73..0000000
--- a/toolbox/upstream-netbsd/usr.bin/grep/grep.c
+++ /dev/null
@@ -1,722 +0,0 @@
-/*	$NetBSD: grep.c,v 1.15 2018/08/12 09:03:21 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.15 2018/08/12 09:03:21 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},
-#ifndef WITHOUT_GZIP
-	{"decompress",          no_argument,            NULL, DECOMPRESS_OPT},
-#endif
-	{"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'},
-#ifndef WITHOUT_BZ2
-	{"bz2decompress",	no_argument,		NULL, 'J'},
-#endif
-	{"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;
-#ifndef WITHOUT_GZIP
-	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;
-#endif
-	}
-
-	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;
-#ifndef WITHOUT_BZ2
-		case 'J':
-			filebehave = FILE_BZIP;
-			break;
-#endif
-		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;
-#ifndef WITHOUT_GZIP
-		case DECOMPRESS_OPT:
-			filebehave = FILE_GZIP;
-			break;
-#endif
-		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) {
-#ifdef _IOLBF
-		setvbuf(stdout, NULL, _IOLBF, 0);
-#else
-		setlinebuf(stdout);
-#endif
-	}
-
-	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 b7ef7fa..0000000
--- a/toolbox/upstream-netbsd/usr.bin/grep/grep.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*	$NetBSD: grep.h,v 1.10 2018/08/12 09:03:21 christos 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 WITHOUT_BZ2
-#include <bzlib.h>
-#endif
-#include <limits.h>
-#include <regex.h>
-#include <stdbool.h>
-#include <stdio.h>
-#ifndef WITHOUT_GZIP
-#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 a3c9e4c..0000000
--- a/toolbox/upstream-netbsd/usr.bin/grep/util.c
+++ /dev/null
@@ -1,500 +0,0 @@
-/*	$NetBSD: util.c,v 1.19 2018/02/05 22:14:26 mrg 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.19 2018/02/05 22:14:26 mrg 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);
-	}
-}