Loading fs_mgr/fs_mgr_fstab.cpp +7 −6 Original line number Original line Diff line number Diff line Loading @@ -402,16 +402,17 @@ std::string ReadFstabFromDt() { return fstab_result; return fstab_result; } } // Identify path to fstab file. Lookup is based on pattern fstab.<hardware>, // Identify path to fstab file. Lookup is based on pattern // fstab.<hardware.platform> in folders /odm/etc, vendor/etc, or /. // fstab.<fstab_suffix>, fstab.<hardware>, fstab.<hardware.platform> in // folders /odm/etc, vendor/etc, or /. std::string GetFstabPath() { std::string GetFstabPath() { for (const char* prop : {"hardware", "hardware.platform"}) { for (const char* prop : {"fstab_suffix", "hardware", "hardware.platform"}) { std::string hw; std::string suffix; if (!fs_mgr_get_boot_config(prop, &hw)) continue; if (!fs_mgr_get_boot_config(prop, &suffix)) continue; for (const char* prefix : {"/odm/etc/fstab.", "/vendor/etc/fstab.", "/fstab."}) { for (const char* prefix : {"/odm/etc/fstab.", "/vendor/etc/fstab.", "/fstab."}) { std::string fstab_path = prefix + hw; std::string fstab_path = prefix + suffix; if (access(fstab_path.c_str(), F_OK) == 0) { if (access(fstab_path.c_str(), F_OK) == 0) { return fstab_path; return fstab_path; } } Loading init/README.md +4 −1 Original line number Original line Diff line number Diff line Loading @@ -547,13 +547,16 @@ provides the `aidl_lazy_test_1` interface. * `ref`: use the systemwide DE key * `ref`: use the systemwide DE key * `per_boot_ref`: use the key freshly generated on each boot. * `per_boot_ref`: use the key freshly generated on each boot. `mount_all <fstab> [ <path> ]\* [--<option>]` `mount_all [ <fstab> ] [--<option>]` > Calls fs\_mgr\_mount\_all on the given fs\_mgr-format fstab with optional > Calls fs\_mgr\_mount\_all on the given fs\_mgr-format fstab with optional options "early" and "late". options "early" and "late". With "--early" set, the init executable will skip mounting entries with With "--early" set, the init executable will skip mounting entries with "latemount" flag and triggering fs encryption state event. With "--late" set, "latemount" flag and triggering fs encryption state event. With "--late" set, init executable will only mount entries with "latemount" flag. By default, init executable will only mount entries with "latemount" flag. By default, no option is set, and mount\_all will process all entries in the given fstab. no option is set, and mount\_all will process all entries in the given fstab. If the fstab parameter is not specified, fstab.${ro.boot.fstab_suffix}, fstab.${ro.hardware} or fstab.${ro.hardware.platform} will be scanned for under /odm/etc, /vendor/etc, or / at runtime, in that order. `mount <type> <device> <dir> [ <flag>\* ] [<options>]` `mount <type> <device> <dir> [ <flag>\* ] [<options>]` > Attempt to mount the named device at the directory _dir_ > Attempt to mount the named device at the directory _dir_ Loading init/builtins.cpp +41 −36 Original line number Original line Diff line number Diff line Loading @@ -518,21 +518,21 @@ static Result<void> do_mount(const BuiltinArguments& args) { /* Imports .rc files from the specified paths. Default ones are applied if none is given. /* Imports .rc files from the specified paths. Default ones are applied if none is given. * * * start_index: index of the first path in the args list * rc_paths: list of paths to rc files to import */ */ static void import_late(const std::vector<std::string>& args, size_t start_index, size_t end_index) { static void import_late(const std::vector<std::string>& rc_paths) { auto& action_manager = ActionManager::GetInstance(); auto& action_manager = ActionManager::GetInstance(); auto& service_list = ServiceList::GetInstance(); auto& service_list = ServiceList::GetInstance(); Parser parser = CreateParser(action_manager, service_list); Parser parser = CreateParser(action_manager, service_list); if (end_index <= start_index) { if (rc_paths.empty()) { // Fallbacks for partitions on which early mount isn't enabled. // Fallbacks for partitions on which early mount isn't enabled. for (const auto& path : late_import_paths) { for (const auto& path : late_import_paths) { parser.ParseConfig(path); parser.ParseConfig(path); } } late_import_paths.clear(); late_import_paths.clear(); } else { } else { for (size_t i = start_index; i < end_index; ++i) { for (const auto& rc_path : rc_paths) { parser.ParseConfig(args[i]); parser.ParseConfig(rc_path); } } } } Loading Loading @@ -633,48 +633,44 @@ static Result<void> queue_fs_event(int code, bool userdata_remount) { static int initial_mount_fstab_return_code = -1; static int initial_mount_fstab_return_code = -1; /* mount_all <fstab> [ <path> ]* [--<options>]* /* <= Q: mount_all <fstab> [ <path> ]* [--<options>]* * >= R: mount_all [ <fstab> ] [--<options>]* * * * This function might request a reboot, in which case it will * This function might request a reboot, in which case it will * not return. * not return. */ */ static Result<void> do_mount_all(const BuiltinArguments& args) { static Result<void> do_mount_all(const BuiltinArguments& args) { std::size_t na = 0; auto mount_all = ParseMountAll(args.args); bool import_rc = true; if (!mount_all.ok()) return mount_all.error(); bool queue_event = true; int mount_mode = MOUNT_MODE_DEFAULT; const auto& fstab_file = args[1]; std::size_t path_arg_end = args.size(); const char* prop_post_fix = "default"; for (na = args.size() - 1; na > 1; --na) { const char* prop_post_fix = "default"; if (args[na] == "--early") { bool queue_event = true; path_arg_end = na; if (mount_all->mode == MOUNT_MODE_EARLY) { queue_event = false; mount_mode = MOUNT_MODE_EARLY; prop_post_fix = "early"; prop_post_fix = "early"; } else if (args[na] == "--late") { queue_event = false; path_arg_end = na; } else if (mount_all->mode == MOUNT_MODE_LATE) { import_rc = false; mount_mode = MOUNT_MODE_LATE; prop_post_fix = "late"; prop_post_fix = "late"; } } } std::string prop_name = "ro.boottime.init.mount_all."s + prop_post_fix; std::string prop_name = "ro.boottime.init.mount_all."s + prop_post_fix; android::base::Timer t; android::base::Timer t; Fstab fstab; Fstab fstab; if (!ReadFstabFromFile(fstab_file, &fstab)) { if (mount_all->fstab_path.empty()) { if (!ReadDefaultFstab(&fstab)) { return Error() << "Could not read default fstab"; } } else { if (!ReadFstabFromFile(mount_all->fstab_path, &fstab)) { return Error() << "Could not read fstab"; return Error() << "Could not read fstab"; } } } auto mount_fstab_return_code = fs_mgr_mount_all(&fstab, mount_mode); auto mount_fstab_return_code = fs_mgr_mount_all(&fstab, mount_all->mode); SetProperty(prop_name, std::to_string(t.duration().count())); SetProperty(prop_name, std::to_string(t.duration().count())); if (import_rc && SelinuxGetVendorAndroidVersion() <= __ANDROID_API_Q__) { if (mount_all->import_rc) { /* Paths of .rc files are specified at the 2nd argument and beyond */ import_late(mount_all->rc_paths); import_late(args.args, 2, path_arg_end); } } if (queue_event) { if (queue_event) { Loading @@ -690,12 +686,21 @@ static Result<void> do_mount_all(const BuiltinArguments& args) { return {}; return {}; } } /* umount_all <fstab> */ /* umount_all [ <fstab> ] */ static Result<void> do_umount_all(const BuiltinArguments& args) { static Result<void> do_umount_all(const BuiltinArguments& args) { auto umount_all = ParseUmountAll(args.args); if (!umount_all.ok()) return umount_all.error(); Fstab fstab; Fstab fstab; if (!ReadFstabFromFile(args[1], &fstab)) { if (umount_all->empty()) { if (!ReadDefaultFstab(&fstab)) { return Error() << "Could not read default fstab"; } } else { if (!ReadFstabFromFile(*umount_all, &fstab)) { return Error() << "Could not read fstab"; return Error() << "Could not read fstab"; } } } if (auto result = fs_mgr_umount_all(&fstab); result != 0) { if (auto result = fs_mgr_umount_all(&fstab); result != 0) { return Error() << "umount_fstab() failed " << result; return Error() << "umount_fstab() failed " << result; Loading Loading @@ -1349,11 +1354,11 @@ const BuiltinFunctionMap& GetBuiltinFunctionMap() { // mount_all is currently too complex to run in vendor_init as it queues action triggers, // mount_all is currently too complex to run in vendor_init as it queues action triggers, // imports rc scripts, etc. It should be simplified and run in vendor_init context. // imports rc scripts, etc. It should be simplified and run in vendor_init context. // mount and umount are run in the same context as mount_all for symmetry. // mount and umount are run in the same context as mount_all for symmetry. {"mount_all", {1, kMax, {false, do_mount_all}}}, {"mount_all", {0, kMax, {false, do_mount_all}}}, {"mount", {3, kMax, {false, do_mount}}}, {"mount", {3, kMax, {false, do_mount}}}, {"perform_apex_config", {0, 0, {false, do_perform_apex_config}}}, {"perform_apex_config", {0, 0, {false, do_perform_apex_config}}}, {"umount", {1, 1, {false, do_umount}}}, {"umount", {1, 1, {false, do_umount}}}, {"umount_all", {1, 1, {false, do_umount_all}}}, {"umount_all", {0, 1, {false, do_umount_all}}}, {"update_linker_config", {0, 0, {false, do_update_linker_config}}}, {"update_linker_config", {0, 0, {false, do_update_linker_config}}}, {"readahead", {1, 2, {true, do_readahead}}}, {"readahead", {1, 2, {true, do_readahead}}}, {"remount_userdata", {0, 0, {false, do_remount_userdata}}}, {"remount_userdata", {0, 0, {false, do_remount_userdata}}}, Loading init/check_builtins.cpp +16 −0 Original line number Original line Diff line number Diff line Loading @@ -123,6 +123,14 @@ Result<void> check_loglevel(const BuiltinArguments& args) { return {}; return {}; } } Result<void> check_mount_all(const BuiltinArguments& args) { auto options = ParseMountAll(args.args); if (!options.ok()) { return options.error(); } return {}; } Result<void> check_mkdir(const BuiltinArguments& args) { Result<void> check_mkdir(const BuiltinArguments& args) { auto options = ParseMkdir(args.args); auto options = ParseMkdir(args.args); if (!options.ok()) { if (!options.ok()) { Loading Loading @@ -204,6 +212,14 @@ Result<void> check_sysclktz(const BuiltinArguments& args) { return {}; return {}; } } Result<void> check_umount_all(const BuiltinArguments& args) { auto options = ParseUmountAll(args.args); if (!options.ok()) { return options.error(); } return {}; } Result<void> check_wait(const BuiltinArguments& args) { Result<void> check_wait(const BuiltinArguments& args) { if (args.size() == 3 && !args[2].empty()) { if (args.size() == 3 && !args[2].empty()) { double timeout_double; double timeout_double; Loading init/check_builtins.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -32,11 +32,13 @@ Result<void> check_interface_stop(const BuiltinArguments& args); Result<void> check_load_system_props(const BuiltinArguments& args); Result<void> check_load_system_props(const BuiltinArguments& args); Result<void> check_loglevel(const BuiltinArguments& args); Result<void> check_loglevel(const BuiltinArguments& args); Result<void> check_mkdir(const BuiltinArguments& args); Result<void> check_mkdir(const BuiltinArguments& args); Result<void> check_mount_all(const BuiltinArguments& args); Result<void> check_restorecon(const BuiltinArguments& args); Result<void> check_restorecon(const BuiltinArguments& args); Result<void> check_restorecon_recursive(const BuiltinArguments& args); Result<void> check_restorecon_recursive(const BuiltinArguments& args); Result<void> check_setprop(const BuiltinArguments& args); Result<void> check_setprop(const BuiltinArguments& args); Result<void> check_setrlimit(const BuiltinArguments& args); Result<void> check_setrlimit(const BuiltinArguments& args); Result<void> check_sysclktz(const BuiltinArguments& args); Result<void> check_sysclktz(const BuiltinArguments& args); Result<void> check_umount_all(const BuiltinArguments& args); Result<void> check_wait(const BuiltinArguments& args); Result<void> check_wait(const BuiltinArguments& args); Result<void> check_wait_for_prop(const BuiltinArguments& args); Result<void> check_wait_for_prop(const BuiltinArguments& args); Loading Loading
fs_mgr/fs_mgr_fstab.cpp +7 −6 Original line number Original line Diff line number Diff line Loading @@ -402,16 +402,17 @@ std::string ReadFstabFromDt() { return fstab_result; return fstab_result; } } // Identify path to fstab file. Lookup is based on pattern fstab.<hardware>, // Identify path to fstab file. Lookup is based on pattern // fstab.<hardware.platform> in folders /odm/etc, vendor/etc, or /. // fstab.<fstab_suffix>, fstab.<hardware>, fstab.<hardware.platform> in // folders /odm/etc, vendor/etc, or /. std::string GetFstabPath() { std::string GetFstabPath() { for (const char* prop : {"hardware", "hardware.platform"}) { for (const char* prop : {"fstab_suffix", "hardware", "hardware.platform"}) { std::string hw; std::string suffix; if (!fs_mgr_get_boot_config(prop, &hw)) continue; if (!fs_mgr_get_boot_config(prop, &suffix)) continue; for (const char* prefix : {"/odm/etc/fstab.", "/vendor/etc/fstab.", "/fstab."}) { for (const char* prefix : {"/odm/etc/fstab.", "/vendor/etc/fstab.", "/fstab."}) { std::string fstab_path = prefix + hw; std::string fstab_path = prefix + suffix; if (access(fstab_path.c_str(), F_OK) == 0) { if (access(fstab_path.c_str(), F_OK) == 0) { return fstab_path; return fstab_path; } } Loading
init/README.md +4 −1 Original line number Original line Diff line number Diff line Loading @@ -547,13 +547,16 @@ provides the `aidl_lazy_test_1` interface. * `ref`: use the systemwide DE key * `ref`: use the systemwide DE key * `per_boot_ref`: use the key freshly generated on each boot. * `per_boot_ref`: use the key freshly generated on each boot. `mount_all <fstab> [ <path> ]\* [--<option>]` `mount_all [ <fstab> ] [--<option>]` > Calls fs\_mgr\_mount\_all on the given fs\_mgr-format fstab with optional > Calls fs\_mgr\_mount\_all on the given fs\_mgr-format fstab with optional options "early" and "late". options "early" and "late". With "--early" set, the init executable will skip mounting entries with With "--early" set, the init executable will skip mounting entries with "latemount" flag and triggering fs encryption state event. With "--late" set, "latemount" flag and triggering fs encryption state event. With "--late" set, init executable will only mount entries with "latemount" flag. By default, init executable will only mount entries with "latemount" flag. By default, no option is set, and mount\_all will process all entries in the given fstab. no option is set, and mount\_all will process all entries in the given fstab. If the fstab parameter is not specified, fstab.${ro.boot.fstab_suffix}, fstab.${ro.hardware} or fstab.${ro.hardware.platform} will be scanned for under /odm/etc, /vendor/etc, or / at runtime, in that order. `mount <type> <device> <dir> [ <flag>\* ] [<options>]` `mount <type> <device> <dir> [ <flag>\* ] [<options>]` > Attempt to mount the named device at the directory _dir_ > Attempt to mount the named device at the directory _dir_ Loading
init/builtins.cpp +41 −36 Original line number Original line Diff line number Diff line Loading @@ -518,21 +518,21 @@ static Result<void> do_mount(const BuiltinArguments& args) { /* Imports .rc files from the specified paths. Default ones are applied if none is given. /* Imports .rc files from the specified paths. Default ones are applied if none is given. * * * start_index: index of the first path in the args list * rc_paths: list of paths to rc files to import */ */ static void import_late(const std::vector<std::string>& args, size_t start_index, size_t end_index) { static void import_late(const std::vector<std::string>& rc_paths) { auto& action_manager = ActionManager::GetInstance(); auto& action_manager = ActionManager::GetInstance(); auto& service_list = ServiceList::GetInstance(); auto& service_list = ServiceList::GetInstance(); Parser parser = CreateParser(action_manager, service_list); Parser parser = CreateParser(action_manager, service_list); if (end_index <= start_index) { if (rc_paths.empty()) { // Fallbacks for partitions on which early mount isn't enabled. // Fallbacks for partitions on which early mount isn't enabled. for (const auto& path : late_import_paths) { for (const auto& path : late_import_paths) { parser.ParseConfig(path); parser.ParseConfig(path); } } late_import_paths.clear(); late_import_paths.clear(); } else { } else { for (size_t i = start_index; i < end_index; ++i) { for (const auto& rc_path : rc_paths) { parser.ParseConfig(args[i]); parser.ParseConfig(rc_path); } } } } Loading Loading @@ -633,48 +633,44 @@ static Result<void> queue_fs_event(int code, bool userdata_remount) { static int initial_mount_fstab_return_code = -1; static int initial_mount_fstab_return_code = -1; /* mount_all <fstab> [ <path> ]* [--<options>]* /* <= Q: mount_all <fstab> [ <path> ]* [--<options>]* * >= R: mount_all [ <fstab> ] [--<options>]* * * * This function might request a reboot, in which case it will * This function might request a reboot, in which case it will * not return. * not return. */ */ static Result<void> do_mount_all(const BuiltinArguments& args) { static Result<void> do_mount_all(const BuiltinArguments& args) { std::size_t na = 0; auto mount_all = ParseMountAll(args.args); bool import_rc = true; if (!mount_all.ok()) return mount_all.error(); bool queue_event = true; int mount_mode = MOUNT_MODE_DEFAULT; const auto& fstab_file = args[1]; std::size_t path_arg_end = args.size(); const char* prop_post_fix = "default"; for (na = args.size() - 1; na > 1; --na) { const char* prop_post_fix = "default"; if (args[na] == "--early") { bool queue_event = true; path_arg_end = na; if (mount_all->mode == MOUNT_MODE_EARLY) { queue_event = false; mount_mode = MOUNT_MODE_EARLY; prop_post_fix = "early"; prop_post_fix = "early"; } else if (args[na] == "--late") { queue_event = false; path_arg_end = na; } else if (mount_all->mode == MOUNT_MODE_LATE) { import_rc = false; mount_mode = MOUNT_MODE_LATE; prop_post_fix = "late"; prop_post_fix = "late"; } } } std::string prop_name = "ro.boottime.init.mount_all."s + prop_post_fix; std::string prop_name = "ro.boottime.init.mount_all."s + prop_post_fix; android::base::Timer t; android::base::Timer t; Fstab fstab; Fstab fstab; if (!ReadFstabFromFile(fstab_file, &fstab)) { if (mount_all->fstab_path.empty()) { if (!ReadDefaultFstab(&fstab)) { return Error() << "Could not read default fstab"; } } else { if (!ReadFstabFromFile(mount_all->fstab_path, &fstab)) { return Error() << "Could not read fstab"; return Error() << "Could not read fstab"; } } } auto mount_fstab_return_code = fs_mgr_mount_all(&fstab, mount_mode); auto mount_fstab_return_code = fs_mgr_mount_all(&fstab, mount_all->mode); SetProperty(prop_name, std::to_string(t.duration().count())); SetProperty(prop_name, std::to_string(t.duration().count())); if (import_rc && SelinuxGetVendorAndroidVersion() <= __ANDROID_API_Q__) { if (mount_all->import_rc) { /* Paths of .rc files are specified at the 2nd argument and beyond */ import_late(mount_all->rc_paths); import_late(args.args, 2, path_arg_end); } } if (queue_event) { if (queue_event) { Loading @@ -690,12 +686,21 @@ static Result<void> do_mount_all(const BuiltinArguments& args) { return {}; return {}; } } /* umount_all <fstab> */ /* umount_all [ <fstab> ] */ static Result<void> do_umount_all(const BuiltinArguments& args) { static Result<void> do_umount_all(const BuiltinArguments& args) { auto umount_all = ParseUmountAll(args.args); if (!umount_all.ok()) return umount_all.error(); Fstab fstab; Fstab fstab; if (!ReadFstabFromFile(args[1], &fstab)) { if (umount_all->empty()) { if (!ReadDefaultFstab(&fstab)) { return Error() << "Could not read default fstab"; } } else { if (!ReadFstabFromFile(*umount_all, &fstab)) { return Error() << "Could not read fstab"; return Error() << "Could not read fstab"; } } } if (auto result = fs_mgr_umount_all(&fstab); result != 0) { if (auto result = fs_mgr_umount_all(&fstab); result != 0) { return Error() << "umount_fstab() failed " << result; return Error() << "umount_fstab() failed " << result; Loading Loading @@ -1349,11 +1354,11 @@ const BuiltinFunctionMap& GetBuiltinFunctionMap() { // mount_all is currently too complex to run in vendor_init as it queues action triggers, // mount_all is currently too complex to run in vendor_init as it queues action triggers, // imports rc scripts, etc. It should be simplified and run in vendor_init context. // imports rc scripts, etc. It should be simplified and run in vendor_init context. // mount and umount are run in the same context as mount_all for symmetry. // mount and umount are run in the same context as mount_all for symmetry. {"mount_all", {1, kMax, {false, do_mount_all}}}, {"mount_all", {0, kMax, {false, do_mount_all}}}, {"mount", {3, kMax, {false, do_mount}}}, {"mount", {3, kMax, {false, do_mount}}}, {"perform_apex_config", {0, 0, {false, do_perform_apex_config}}}, {"perform_apex_config", {0, 0, {false, do_perform_apex_config}}}, {"umount", {1, 1, {false, do_umount}}}, {"umount", {1, 1, {false, do_umount}}}, {"umount_all", {1, 1, {false, do_umount_all}}}, {"umount_all", {0, 1, {false, do_umount_all}}}, {"update_linker_config", {0, 0, {false, do_update_linker_config}}}, {"update_linker_config", {0, 0, {false, do_update_linker_config}}}, {"readahead", {1, 2, {true, do_readahead}}}, {"readahead", {1, 2, {true, do_readahead}}}, {"remount_userdata", {0, 0, {false, do_remount_userdata}}}, {"remount_userdata", {0, 0, {false, do_remount_userdata}}}, Loading
init/check_builtins.cpp +16 −0 Original line number Original line Diff line number Diff line Loading @@ -123,6 +123,14 @@ Result<void> check_loglevel(const BuiltinArguments& args) { return {}; return {}; } } Result<void> check_mount_all(const BuiltinArguments& args) { auto options = ParseMountAll(args.args); if (!options.ok()) { return options.error(); } return {}; } Result<void> check_mkdir(const BuiltinArguments& args) { Result<void> check_mkdir(const BuiltinArguments& args) { auto options = ParseMkdir(args.args); auto options = ParseMkdir(args.args); if (!options.ok()) { if (!options.ok()) { Loading Loading @@ -204,6 +212,14 @@ Result<void> check_sysclktz(const BuiltinArguments& args) { return {}; return {}; } } Result<void> check_umount_all(const BuiltinArguments& args) { auto options = ParseUmountAll(args.args); if (!options.ok()) { return options.error(); } return {}; } Result<void> check_wait(const BuiltinArguments& args) { Result<void> check_wait(const BuiltinArguments& args) { if (args.size() == 3 && !args[2].empty()) { if (args.size() == 3 && !args[2].empty()) { double timeout_double; double timeout_double; Loading
init/check_builtins.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -32,11 +32,13 @@ Result<void> check_interface_stop(const BuiltinArguments& args); Result<void> check_load_system_props(const BuiltinArguments& args); Result<void> check_load_system_props(const BuiltinArguments& args); Result<void> check_loglevel(const BuiltinArguments& args); Result<void> check_loglevel(const BuiltinArguments& args); Result<void> check_mkdir(const BuiltinArguments& args); Result<void> check_mkdir(const BuiltinArguments& args); Result<void> check_mount_all(const BuiltinArguments& args); Result<void> check_restorecon(const BuiltinArguments& args); Result<void> check_restorecon(const BuiltinArguments& args); Result<void> check_restorecon_recursive(const BuiltinArguments& args); Result<void> check_restorecon_recursive(const BuiltinArguments& args); Result<void> check_setprop(const BuiltinArguments& args); Result<void> check_setprop(const BuiltinArguments& args); Result<void> check_setrlimit(const BuiltinArguments& args); Result<void> check_setrlimit(const BuiltinArguments& args); Result<void> check_sysclktz(const BuiltinArguments& args); Result<void> check_sysclktz(const BuiltinArguments& args); Result<void> check_umount_all(const BuiltinArguments& args); Result<void> check_wait(const BuiltinArguments& args); Result<void> check_wait(const BuiltinArguments& args); Result<void> check_wait_for_prop(const BuiltinArguments& args); Result<void> check_wait_for_prop(const BuiltinArguments& args); Loading