mirror of
https://github.com/drakmor/ShadowMountPlus.git
synced 2026-10-22 06:32:25 -05:00
Unify scan and watcher tree traversal with a shared scan walker
This commit is contained in:
1 parent
cec94656c6
commit
ef814ad56b
4 files changed
+239
-227
No files matched your search
@@ -0,0 +1,31 @@
|
||||
#ifndef SM_SCAN_TREE_H
|
||||
#define SM_SCAN_TREE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef enum {
|
||||
SM_SCAN_TREE_DIR_DESCEND = 0,
|
||||
SM_SCAN_TREE_DIR_SKIP_DESCEND,
|
||||
SM_SCAN_TREE_DIR_ABORT,
|
||||
} sm_scan_tree_dir_visit_t;
|
||||
|
||||
typedef sm_scan_tree_dir_visit_t (*sm_scan_tree_dir_fn)(const char *dir_path,
|
||||
unsigned int depth_from_root,
|
||||
void *ctx);
|
||||
typedef bool (*sm_scan_tree_image_fn)(const char *image_path,
|
||||
const char *image_name,
|
||||
unsigned int depth_from_root,
|
||||
void *ctx);
|
||||
|
||||
typedef struct {
|
||||
sm_scan_tree_dir_fn on_directory;
|
||||
sm_scan_tree_image_fn on_image_file;
|
||||
} sm_scan_tree_callbacks_t;
|
||||
|
||||
// Walk a managed scan subtree using the shared scan-depth and path filtering rules.
|
||||
bool sm_scan_tree_walk(const char *scan_root, const char *dir_path,
|
||||
unsigned int depth_from_root,
|
||||
unsigned int remaining_depth,
|
||||
const sm_scan_tree_callbacks_t *callbacks, void *ctx);
|
||||
|
||||
#endif
|
||||
+46
-127
@@ -1,6 +1,7 @@
|
||||
#include "sm_platform.h"
|
||||
#include "sm_runtime.h"
|
||||
#include "sm_scan.h"
|
||||
#include "sm_scan_tree.h"
|
||||
#include "sm_types.h"
|
||||
#include "sm_game_cache.h"
|
||||
#include "sm_gameinfo.h"
|
||||
@@ -31,43 +32,6 @@ static bool is_under_discovered_param_root(
|
||||
return false;
|
||||
}
|
||||
|
||||
static void classify_scan_entry(const char *full_path, unsigned char d_type,
|
||||
bool *is_dir_out, bool *is_regular_out) {
|
||||
bool is_dir = false;
|
||||
bool is_regular = false;
|
||||
|
||||
if (d_type == DT_DIR) {
|
||||
is_dir = true;
|
||||
} else if (d_type == DT_REG) {
|
||||
is_regular = true;
|
||||
} else if (d_type == DT_UNKNOWN) {
|
||||
struct stat st;
|
||||
if (lstat(full_path, &st) == 0) {
|
||||
is_dir = S_ISDIR(st.st_mode);
|
||||
is_regular = S_ISREG(st.st_mode);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_dir_out)
|
||||
*is_dir_out = is_dir;
|
||||
if (is_regular_out)
|
||||
*is_regular_out = is_regular;
|
||||
}
|
||||
|
||||
static bool is_distinct_configured_scan_root(const char *current_scan_root,
|
||||
const char *path) {
|
||||
for (int i = 0; i < get_scan_path_count(); i++) {
|
||||
const char *scan_path = get_scan_path(i);
|
||||
if (strcmp(scan_path, path) != 0)
|
||||
continue;
|
||||
if (current_scan_root && strcmp(current_scan_root, path) == 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// --- Candidate Discovery ---
|
||||
static bool try_collect_candidate_for_directory(
|
||||
const char *full_path, scan_candidate_t *candidates, int max_candidates,
|
||||
@@ -200,65 +164,43 @@ static bool try_collect_candidate_for_directory(
|
||||
return true;
|
||||
}
|
||||
|
||||
static void collect_candidates_with_depth(
|
||||
const char *current_scan_root, const char *dir_path,
|
||||
unsigned int remaining_depth, scan_candidate_t *candidates,
|
||||
int max_candidates, int *candidate_count,
|
||||
const struct AppDbTitleList *app_db_titles, bool app_db_titles_ready,
|
||||
char discovered_param_roots[][MAX_PATH],
|
||||
int *discovered_param_root_count, bool *unstable_found_out) {
|
||||
if (should_stop_requested())
|
||||
return;
|
||||
typedef struct {
|
||||
scan_candidate_t *candidates;
|
||||
int max_candidates;
|
||||
int *candidate_count;
|
||||
const struct AppDbTitleList *app_db_titles;
|
||||
bool app_db_titles_ready;
|
||||
char (*discovered_param_roots)[MAX_PATH];
|
||||
int *discovered_param_root_count;
|
||||
bool *unstable_found_out;
|
||||
} collect_candidates_walk_ctx_t;
|
||||
|
||||
if (is_distinct_configured_scan_root(current_scan_root, dir_path))
|
||||
return;
|
||||
static sm_scan_tree_dir_visit_t collect_candidate_directory_visit(
|
||||
const char *dir_path, unsigned int depth_from_root, void *ctx_ptr) {
|
||||
if (depth_from_root == 0u)
|
||||
return SM_SCAN_TREE_DIR_DESCEND;
|
||||
|
||||
// Once a directory has sce_sys/param.json (valid or not),
|
||||
// it is treated as a terminal game root and descendants are skipped.
|
||||
collect_candidates_walk_ctx_t *ctx = (collect_candidates_walk_ctx_t *)ctx_ptr;
|
||||
if (try_collect_candidate_for_directory(
|
||||
dir_path, candidates, max_candidates, candidate_count, app_db_titles,
|
||||
app_db_titles_ready, discovered_param_roots,
|
||||
discovered_param_root_count, unstable_found_out)) {
|
||||
return;
|
||||
dir_path, ctx->candidates, ctx->max_candidates, ctx->candidate_count,
|
||||
ctx->app_db_titles, ctx->app_db_titles_ready,
|
||||
ctx->discovered_param_roots, ctx->discovered_param_root_count,
|
||||
ctx->unstable_found_out)) {
|
||||
return SM_SCAN_TREE_DIR_SKIP_DESCEND;
|
||||
}
|
||||
|
||||
if (remaining_depth == 0)
|
||||
return;
|
||||
return SM_SCAN_TREE_DIR_DESCEND;
|
||||
}
|
||||
|
||||
DIR *d = opendir(dir_path);
|
||||
if (!d)
|
||||
return;
|
||||
static bool collect_candidate_image_visit(const char *image_path,
|
||||
const char *image_name,
|
||||
unsigned int depth_from_root,
|
||||
void *ctx_ptr) {
|
||||
(void)depth_from_root;
|
||||
|
||||
struct dirent *entry;
|
||||
while ((entry = readdir(d)) != NULL) {
|
||||
if (should_stop_requested())
|
||||
break;
|
||||
if (entry->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
char full_path[MAX_PATH];
|
||||
snprintf(full_path, sizeof(full_path), "%s/%s", dir_path, entry->d_name);
|
||||
|
||||
bool is_dir = false;
|
||||
bool is_regular = false;
|
||||
classify_scan_entry(full_path, entry->d_type, &is_dir, &is_regular);
|
||||
|
||||
if (!path_matches_root_or_child(current_scan_root, IMAGE_MOUNT_BASE) &&
|
||||
is_regular && is_supported_image_file_name(entry->d_name)) {
|
||||
maybe_mount_image_file(full_path, entry->d_name, unstable_found_out);
|
||||
}
|
||||
|
||||
if (!is_dir)
|
||||
continue;
|
||||
|
||||
collect_candidates_with_depth(
|
||||
current_scan_root, full_path, remaining_depth - 1u, candidates,
|
||||
max_candidates, candidate_count, app_db_titles, app_db_titles_ready,
|
||||
discovered_param_roots, discovered_param_root_count,
|
||||
unstable_found_out);
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
collect_candidates_walk_ctx_t *ctx = (collect_candidates_walk_ctx_t *)ctx_ptr;
|
||||
maybe_mount_image_file(image_path, image_name, ctx->unstable_found_out);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool build_backport_mount_context(const char *title_id,
|
||||
@@ -366,47 +308,24 @@ static void collect_scan_candidates_from_root(
|
||||
return;
|
||||
|
||||
unsigned int scan_depth = runtime_config()->scan_depth;
|
||||
bool has_backports_root = !is_under_image_mount_base(scan_path);
|
||||
|
||||
if (scan_depth < MIN_SCAN_DEPTH)
|
||||
scan_depth = MIN_SCAN_DEPTH;
|
||||
|
||||
DIR *d = opendir(scan_path);
|
||||
if (!d)
|
||||
return;
|
||||
|
||||
struct dirent *entry;
|
||||
while ((entry = readdir(d)) != NULL) {
|
||||
if (should_stop_requested())
|
||||
break;
|
||||
if (entry->d_name[0] == '.')
|
||||
continue;
|
||||
if (has_backports_root &&
|
||||
strcmp(entry->d_name, DEFAULT_BACKPORTS_DIR_NAME) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
char full_path[MAX_PATH];
|
||||
snprintf(full_path, sizeof(full_path), "%s/%s", scan_path, entry->d_name);
|
||||
|
||||
bool is_dir = false;
|
||||
bool is_regular = false;
|
||||
classify_scan_entry(full_path, entry->d_type, &is_dir, &is_regular);
|
||||
|
||||
if (!path_matches_root_or_child(scan_path, IMAGE_MOUNT_BASE) && is_regular &&
|
||||
is_supported_image_file_name(entry->d_name))
|
||||
maybe_mount_image_file(full_path, entry->d_name, unstable_found_out);
|
||||
if (!is_dir)
|
||||
continue;
|
||||
|
||||
collect_candidates_with_depth(
|
||||
scan_path, full_path, scan_depth - 1u, candidates, max_candidates,
|
||||
candidate_count, app_db_titles, app_db_titles_ready,
|
||||
discovered_param_roots, discovered_param_root_count,
|
||||
unstable_found_out);
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
collect_candidates_walk_ctx_t ctx = {
|
||||
.candidates = candidates,
|
||||
.max_candidates = max_candidates,
|
||||
.candidate_count = candidate_count,
|
||||
.app_db_titles = app_db_titles,
|
||||
.app_db_titles_ready = app_db_titles_ready,
|
||||
.discovered_param_roots = discovered_param_roots,
|
||||
.discovered_param_root_count = discovered_param_root_count,
|
||||
.unstable_found_out = unstable_found_out,
|
||||
};
|
||||
sm_scan_tree_callbacks_t callbacks = {
|
||||
.on_directory = collect_candidate_directory_visit,
|
||||
.on_image_file = collect_candidate_image_visit,
|
||||
};
|
||||
(void)sm_scan_tree_walk(scan_path, scan_path, 0u, scan_depth, &callbacks, &ctx);
|
||||
}
|
||||
|
||||
int collect_scan_candidates_for_scan_root(const char *scan_root,
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
#include "sm_platform.h"
|
||||
#include "sm_scan_tree.h"
|
||||
|
||||
#include "sm_config_mount.h"
|
||||
#include "sm_filesystem.h"
|
||||
#include "sm_image.h"
|
||||
#include "sm_path_utils.h"
|
||||
#include "sm_paths.h"
|
||||
#include "sm_runtime.h"
|
||||
|
||||
static void classify_scan_tree_entry(const char *full_path, unsigned char d_type,
|
||||
bool *is_dir_out, bool *is_regular_out) {
|
||||
bool is_dir = false;
|
||||
bool is_regular = false;
|
||||
|
||||
if (d_type == DT_DIR) {
|
||||
is_dir = true;
|
||||
} else if (d_type == DT_REG) {
|
||||
is_regular = true;
|
||||
} else if (d_type == DT_UNKNOWN) {
|
||||
struct stat st;
|
||||
if (lstat(full_path, &st) == 0) {
|
||||
is_dir = S_ISDIR(st.st_mode);
|
||||
is_regular = S_ISREG(st.st_mode);
|
||||
}
|
||||
}
|
||||
|
||||
*is_dir_out = is_dir;
|
||||
*is_regular_out = is_regular;
|
||||
}
|
||||
|
||||
static bool is_distinct_configured_scan_root(const char *current_scan_root,
|
||||
const char *path) {
|
||||
for (int i = 0; i < get_scan_path_count(); i++) {
|
||||
const char *scan_path = get_scan_path(i);
|
||||
if (strcmp(scan_path, path) != 0)
|
||||
continue;
|
||||
if (strcmp(current_scan_root, path) == 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool sm_scan_tree_walk(const char *scan_root, const char *dir_path,
|
||||
unsigned int depth_from_root,
|
||||
unsigned int remaining_depth,
|
||||
const sm_scan_tree_callbacks_t *callbacks, void *ctx) {
|
||||
if (should_stop_requested())
|
||||
return true;
|
||||
|
||||
if (depth_from_root > 0u &&
|
||||
is_distinct_configured_scan_root(scan_root, dir_path)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
sm_scan_tree_dir_visit_t dir_visit = SM_SCAN_TREE_DIR_DESCEND;
|
||||
if (callbacks->on_directory) {
|
||||
dir_visit = callbacks->on_directory(dir_path, depth_from_root, ctx);
|
||||
if (dir_visit == SM_SCAN_TREE_DIR_ABORT)
|
||||
return false;
|
||||
if (dir_visit == SM_SCAN_TREE_DIR_SKIP_DESCEND)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (remaining_depth == 0u)
|
||||
return true;
|
||||
|
||||
DIR *d = opendir(dir_path);
|
||||
if (!d)
|
||||
return true;
|
||||
|
||||
bool skip_backports_root =
|
||||
(depth_from_root == 0u && !is_under_image_mount_base(scan_root));
|
||||
bool allow_image_file_visits =
|
||||
callbacks->on_image_file &&
|
||||
!path_matches_root_or_child(scan_root, IMAGE_MOUNT_BASE);
|
||||
|
||||
struct dirent *entry;
|
||||
while ((entry = readdir(d)) != NULL) {
|
||||
if (should_stop_requested()) {
|
||||
closedir(d);
|
||||
return true;
|
||||
}
|
||||
if (entry->d_name[0] == '.')
|
||||
continue;
|
||||
if (skip_backports_root &&
|
||||
strcmp(entry->d_name, DEFAULT_BACKPORTS_DIR_NAME) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
char full_path[MAX_PATH];
|
||||
snprintf(full_path, sizeof(full_path), "%s/%s", dir_path, entry->d_name);
|
||||
|
||||
bool is_dir = false;
|
||||
bool is_regular = false;
|
||||
classify_scan_tree_entry(full_path, entry->d_type, &is_dir, &is_regular);
|
||||
|
||||
if (allow_image_file_visits && is_regular &&
|
||||
is_supported_image_file_name(entry->d_name)) {
|
||||
if (!callbacks->on_image_file(full_path, entry->d_name, depth_from_root + 1u,
|
||||
ctx)) {
|
||||
closedir(d);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_dir)
|
||||
continue;
|
||||
|
||||
if (!sm_scan_tree_walk(scan_root, full_path, depth_from_root + 1u,
|
||||
remaining_depth - 1u, callbacks, ctx)) {
|
||||
closedir(d);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
return true;
|
||||
}
|
||||
+41
-100
@@ -14,6 +14,7 @@
|
||||
#include "sm_paths.h"
|
||||
#include "sm_runtime.h"
|
||||
#include "sm_scan.h"
|
||||
#include "sm_scan_tree.h"
|
||||
#include "sm_scanner.h"
|
||||
#include "sm_time.h"
|
||||
#include "sm_types.h"
|
||||
@@ -225,41 +226,6 @@ static bool rebuild_scanner_watch_fd_index(void) {
|
||||
return rebuild_scanner_watch_fd_index_with_count(g_scanner_watch_count);
|
||||
}
|
||||
|
||||
static bool is_distinct_configured_scan_root(const char *current_scan_root,
|
||||
const char *path) {
|
||||
for (int i = 0; i < get_scan_path_count(); i++) {
|
||||
const char *scan_path = get_scan_path(i);
|
||||
if (strcmp(scan_path, path) != 0)
|
||||
continue;
|
||||
if (current_scan_root && strcmp(current_scan_root, path) == 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void classify_watch_entry(const char *full_path, unsigned char d_type,
|
||||
bool *is_dir_out, bool *is_regular_out) {
|
||||
bool is_dir = false;
|
||||
bool is_regular = false;
|
||||
|
||||
if (d_type == DT_DIR) {
|
||||
is_dir = true;
|
||||
} else if (d_type == DT_REG) {
|
||||
is_regular = true;
|
||||
} else if (d_type == DT_UNKNOWN) {
|
||||
struct stat st;
|
||||
if (lstat(full_path, &st) == 0) {
|
||||
is_dir = S_ISDIR(st.st_mode);
|
||||
is_regular = S_ISREG(st.st_mode);
|
||||
}
|
||||
}
|
||||
|
||||
*is_dir_out = is_dir;
|
||||
*is_regular_out = is_regular;
|
||||
}
|
||||
|
||||
static void link_scanner_watch_entry_to_root(size_t index) {
|
||||
scanner_watch_entry_t *entry = &g_scanner_watch_entries[index];
|
||||
size_t head = g_scanner_root_watch_heads[entry->scan_root_index];
|
||||
@@ -464,76 +430,35 @@ static bool resolve_watch_tree_rebuild_target(const scanner_watch_entry_t *entry
|
||||
}
|
||||
}
|
||||
|
||||
static bool register_scan_dir_tree(int kq, int scan_root_index,
|
||||
const char *current_scan_root,
|
||||
const char *dir_path,
|
||||
unsigned int depth_from_root,
|
||||
unsigned int remaining_depth) {
|
||||
if (depth_from_root > 0 &&
|
||||
is_distinct_configured_scan_root(current_scan_root, dir_path)) {
|
||||
return true;
|
||||
}
|
||||
typedef struct {
|
||||
int kq;
|
||||
int scan_root_index;
|
||||
} register_watch_tree_ctx_t;
|
||||
|
||||
static sm_scan_tree_dir_visit_t register_watch_directory_visit(
|
||||
const char *dir_path, unsigned int depth_from_root, void *ctx_ptr) {
|
||||
register_watch_tree_ctx_t *ctx = (register_watch_tree_ctx_t *)ctx_ptr;
|
||||
scanner_watch_kind_t kind =
|
||||
(depth_from_root == 0u) ? SCANNER_WATCH_SCAN_ROOT
|
||||
: SCANNER_WATCH_SCAN_SUBDIR;
|
||||
if (!register_scanner_watch_entry(kq, scan_root_index, dir_path, kind,
|
||||
if (!register_scanner_watch_entry(ctx->kq, ctx->scan_root_index, dir_path, kind,
|
||||
(uint8_t)depth_from_root)) {
|
||||
return false;
|
||||
return SM_SCAN_TREE_DIR_ABORT;
|
||||
}
|
||||
|
||||
if (remaining_depth == 0u)
|
||||
return true;
|
||||
return SM_SCAN_TREE_DIR_DESCEND;
|
||||
}
|
||||
|
||||
DIR *d = opendir(dir_path);
|
||||
if (!d)
|
||||
return true;
|
||||
static bool register_watch_image_visit(const char *image_path,
|
||||
const char *image_name,
|
||||
unsigned int depth_from_root,
|
||||
void *ctx_ptr) {
|
||||
(void)image_name;
|
||||
|
||||
bool skip_backports_root =
|
||||
(depth_from_root == 0u && !is_under_image_mount_base(current_scan_root));
|
||||
|
||||
struct dirent *entry;
|
||||
while ((entry = readdir(d)) != NULL) {
|
||||
if (should_stop_requested()) {
|
||||
closedir(d);
|
||||
return true;
|
||||
}
|
||||
if (entry->d_name[0] == '.')
|
||||
continue;
|
||||
if (skip_backports_root &&
|
||||
strcmp(entry->d_name, DEFAULT_BACKPORTS_DIR_NAME) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
char full_path[MAX_PATH];
|
||||
snprintf(full_path, sizeof(full_path), "%s/%s", dir_path, entry->d_name);
|
||||
|
||||
bool is_dir = false;
|
||||
bool is_regular = false;
|
||||
classify_watch_entry(full_path, entry->d_type, &is_dir, &is_regular);
|
||||
|
||||
if (!path_matches_root_or_child(current_scan_root, IMAGE_MOUNT_BASE) &&
|
||||
is_regular && is_supported_image_file_name(entry->d_name)) {
|
||||
if (!register_scanner_watch_entry(kq, scan_root_index, full_path,
|
||||
SCANNER_WATCH_SCAN_IMAGE_FILE,
|
||||
(uint8_t)(depth_from_root + 1u))) {
|
||||
closedir(d);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!is_dir)
|
||||
continue;
|
||||
|
||||
if (!register_scan_dir_tree(kq, scan_root_index, current_scan_root,
|
||||
full_path, depth_from_root + 1u,
|
||||
remaining_depth - 1u)) {
|
||||
closedir(d);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
return true;
|
||||
register_watch_tree_ctx_t *ctx = (register_watch_tree_ctx_t *)ctx_ptr;
|
||||
return register_scanner_watch_entry(ctx->kq, ctx->scan_root_index, image_path,
|
||||
SCANNER_WATCH_SCAN_IMAGE_FILE,
|
||||
(uint8_t)depth_from_root);
|
||||
}
|
||||
|
||||
static bool rebuild_scan_root_watch_tree(int kq, int scan_root_index) {
|
||||
@@ -545,8 +470,16 @@ static bool rebuild_scan_root_watch_tree(int kq, int scan_root_index) {
|
||||
if (scan_depth < MIN_SCAN_DEPTH)
|
||||
scan_depth = MIN_SCAN_DEPTH;
|
||||
|
||||
if (!register_scan_dir_tree(kq, scan_root_index, scan_root, scan_root, 0u,
|
||||
scan_depth)) {
|
||||
register_watch_tree_ctx_t walk_ctx = {
|
||||
.kq = kq,
|
||||
.scan_root_index = scan_root_index,
|
||||
};
|
||||
sm_scan_tree_callbacks_t callbacks = {
|
||||
.on_directory = register_watch_directory_visit,
|
||||
.on_image_file = register_watch_image_visit,
|
||||
};
|
||||
if (!sm_scan_tree_walk(scan_root, scan_root, 0u, scan_depth, &callbacks,
|
||||
&walk_ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -596,8 +529,16 @@ static bool rebuild_scan_root_watch_subtree(int kq, int scan_root_index,
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!register_scan_dir_tree(kq, scan_root_index, scan_root, rebuild_path,
|
||||
rebuild_depth, scan_depth - rebuild_depth)) {
|
||||
register_watch_tree_ctx_t walk_ctx = {
|
||||
.kq = kq,
|
||||
.scan_root_index = scan_root_index,
|
||||
};
|
||||
sm_scan_tree_callbacks_t callbacks = {
|
||||
.on_directory = register_watch_directory_visit,
|
||||
.on_image_file = register_watch_image_visit,
|
||||
};
|
||||
if (!sm_scan_tree_walk(scan_root, rebuild_path, rebuild_depth,
|
||||
scan_depth - rebuild_depth, &callbacks, &walk_ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user