Merge "libsnapshot: forward declare IImageManager"
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index 8797ea9..a434c93 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -19,6 +19,7 @@
 #include <string.h>
 
 #include <algorithm>
+#include <string_view>
 
 #include <android-base/properties.h>
 #include <android-base/unique_fd.h>
@@ -33,7 +34,7 @@
 std::optional<bool> MetadataBuilder::sABOverride;
 std::optional<bool> MetadataBuilder::sRetrofitDap;
 
-static const std::string kDefaultGroup = "default";
+static constexpr std::string_view kDefaultGroup = "default";
 
 bool LinearExtent::AddTo(LpMetadata* out) const {
     if (device_index_ >= out->block_devices.size()) {
@@ -414,7 +415,7 @@
     geometry_.metadata_slot_count = metadata_slot_count;
     geometry_.logical_block_size = logical_block_size;
 
-    if (!AddGroup(kDefaultGroup, 0)) {
+    if (!AddGroup(std::string(kDefaultGroup), 0)) {
         return false;
     }
     return true;
@@ -430,7 +431,7 @@
 }
 
 Partition* MetadataBuilder::AddPartition(const std::string& name, uint32_t attributes) {
-    return AddPartition(name, kDefaultGroup, attributes);
+    return AddPartition(name, std::string(kDefaultGroup), attributes);
 }
 
 Partition* MetadataBuilder::AddPartition(const std::string& name, const std::string& group_name,
diff --git a/init/action.cpp b/init/action.cpp
index 65ba25d..1a66eee 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -161,18 +161,8 @@
     auto result = command.InvokeFunc(subcontext_);
     auto duration = t.duration();
 
-    // There are many legacy paths in rootdir/init.rc that will virtually never exist on a new
-    // device, such as '/sys/class/leds/jogball-backlight/brightness'.  As of this writing, there
-    // are 198 such failures on bullhead.  Instead of spamming the log reporting them, we do not
-    // report such failures unless we're running at the DEBUG log level.
-    bool report_failure = !result.has_value();
-    if (report_failure && android::base::GetMinimumLogSeverity() > android::base::DEBUG &&
-        result.error().code() == ENOENT) {
-        report_failure = false;
-    }
-
     // Any action longer than 50ms will be warned to user as slow operation
-    if (report_failure || duration > 50ms ||
+    if (!result.has_value() || duration > 50ms ||
         android::base::GetMinimumLogSeverity() <= android::base::DEBUG) {
         std::string trigger_name = BuildTriggersString();
         std::string cmd_str = command.BuildCommandString();
diff --git a/init/builtins.cpp b/init/builtins.cpp
index e75f5cb..a2d782b 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -89,6 +89,43 @@
 namespace android {
 namespace init {
 
+// There are many legacy paths in rootdir/init.rc that will virtually never exist on a new
+// device, such as '/sys/class/leds/jogball-backlight/brightness'.  As of this writing, there
+// are 81 such failures on cuttlefish.  Instead of spamming the log reporting them, we do not
+// report such failures unless we're running at the DEBUG log level.
+class ErrorIgnoreEnoent {
+  public:
+    ErrorIgnoreEnoent()
+        : ignore_error_(errno == ENOENT &&
+                        android::base::GetMinimumLogSeverity() > android::base::DEBUG) {}
+    explicit ErrorIgnoreEnoent(int errno_to_append)
+        : error_(errno_to_append),
+          ignore_error_(errno_to_append == ENOENT &&
+                        android::base::GetMinimumLogSeverity() > android::base::DEBUG) {}
+
+    template <typename T>
+    operator android::base::expected<T, ResultError>() {
+        if (ignore_error_) {
+            return {};
+        }
+        return error_;
+    }
+
+    template <typename T>
+    ErrorIgnoreEnoent& operator<<(T&& t) {
+        error_ << t;
+        return *this;
+    }
+
+  private:
+    Error error_;
+    bool ignore_error_;
+};
+
+inline ErrorIgnoreEnoent ErrnoErrorIgnoreEnoent() {
+    return ErrorIgnoreEnoent(errno);
+}
+
 std::vector<std::string> late_import_paths;
 
 static constexpr std::chrono::nanoseconds kCommandRetryTimeout = 5s;
@@ -330,7 +367,7 @@
                 return ErrnoError() << "fchmodat() failed";
             }
         } else {
-            return ErrnoError() << "mkdir() failed";
+            return ErrnoErrorIgnoreEnoent() << "mkdir() failed";
         }
     }
 
@@ -459,7 +496,7 @@
         if (wait)
             wait_for_file(source, kCommandRetryTimeout);
         if (mount(source, target, system, flags, options) < 0) {
-            return ErrnoError() << "mount() failed";
+            return ErrnoErrorIgnoreEnoent() << "mount() failed";
         }
 
     }
@@ -683,7 +720,7 @@
     Service* svc = ServiceList::GetInstance().FindService(args[1]);
     if (!svc) return Error() << "service " << args[1] << " not found";
     if (auto result = svc->Start(); !result) {
-        return Error() << "Could not start service: " << result.error();
+        return ErrorIgnoreEnoent() << "Could not start service: " << result.error();
     }
     return {};
 }
@@ -729,10 +766,7 @@
     if (MakeSymlink(args[1], args[2]) < 0) {
         // The symlink builtin is often used to create symlinks for older devices to be backwards
         // compatible with new paths, therefore we skip reporting this error.
-        if (errno == EEXIST && android::base::GetMinimumLogSeverity() > android::base::DEBUG) {
-            return {};
-        }
-        return ErrnoError() << "symlink() failed";
+        return ErrnoErrorIgnoreEnoent() << "symlink() failed";
     }
     return {};
 }
@@ -790,7 +824,8 @@
 
 static Result<void> do_write(const BuiltinArguments& args) {
     if (auto result = WriteFile(args[1], args[2]); !result) {
-        return Error() << "Unable to write to file '" << args[1] << "': " << result.error();
+        return ErrorIgnoreEnoent()
+               << "Unable to write to file '" << args[1] << "': " << result.error();
     }
 
     return {};
@@ -908,7 +943,7 @@
     }
 
     if (lchown(path.c_str(), *uid, *gid) == -1) {
-        return ErrnoError() << "lchown() failed";
+        return ErrnoErrorIgnoreEnoent() << "lchown() failed";
     }
 
     return {};
@@ -930,7 +965,7 @@
 static Result<void> do_chmod(const BuiltinArguments& args) {
     mode_t mode = get_mode(args[1].c_str());
     if (fchmodat(AT_FDCWD, args[2].c_str(), mode, AT_SYMLINK_NOFOLLOW) < 0) {
-        return ErrnoError() << "fchmodat() failed";
+        return ErrnoErrorIgnoreEnoent() << "fchmodat() failed";
     }
     return {};
 }
@@ -950,7 +985,7 @@
         }
     }
 
-    if (ret) return ErrnoError() << "selinux_android_restorecon() failed";
+    if (ret) return ErrnoErrorIgnoreEnoent() << "selinux_android_restorecon() failed";
     return {};
 }
 
diff --git a/init/host_init_verifier.cpp b/init/host_init_verifier.cpp
index dce3eda..076e8b0 100644
--- a/init/host_init_verifier.cpp
+++ b/init/host_init_verifier.cpp
@@ -239,7 +239,7 @@
         LOG(ERROR) << "Failed to open init rc script '" << *argv << "'";
         return EXIT_FAILURE;
     }
-    size_t failures = parser.parse_error_count() + am.CheckAllCommands();
+    size_t failures = parser.parse_error_count() + am.CheckAllCommands() + sl.CheckAllCommands();
     if (failures > 0) {
         LOG(ERROR) << "Failed to parse init script '" << *argv << "' with " << failures
                    << " errors";
diff --git a/init/service.h b/init/service.h
index 6f79faa..ccefc8e 100644
--- a/init/service.h
+++ b/init/service.h
@@ -97,6 +97,7 @@
     void AddReapCallback(std::function<void(const siginfo_t& siginfo)> callback) {
         reap_callbacks_.emplace_back(std::move(callback));
     }
+    size_t CheckAllCommands() const { return onrestart_.CheckAllCommands(); }
 
     static bool is_exec_service_running() { return is_exec_service_running_; }
 
diff --git a/init/service_list.cpp b/init/service_list.cpp
index 3a48183..c51a9cf 100644
--- a/init/service_list.cpp
+++ b/init/service_list.cpp
@@ -28,6 +28,14 @@
     return instance;
 }
 
+size_t ServiceList::CheckAllCommands() {
+    size_t failures = 0;
+    for (const auto& service : services_) {
+        failures += service->CheckAllCommands();
+    }
+    return failures;
+}
+
 void ServiceList::AddService(std::unique_ptr<Service> service) {
     services_.emplace_back(std::move(service));
 }
diff --git a/init/service_list.h b/init/service_list.h
index 2136a21..ee2c702 100644
--- a/init/service_list.h
+++ b/init/service_list.h
@@ -30,6 +30,7 @@
 
     // Exposed for testing
     ServiceList();
+    size_t CheckAllCommands();
 
     void AddService(std::unique_ptr<Service> service);
     void RemoveService(const Service& svc);