From 11b1e877194b27d637d8c114d6f43c4a6bddfdaa Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Wed, 9 Apr 2025 21:48:01 -0500 Subject: [PATCH] Progress: Continue working on completing the remove program. I want to remove the multiple `fl_directory_do()` calls. This means that I need to change how pre-processing and removal is performed. The pre-processing needs to happen before each remove. The recursion needs to happen during the remove. This begins refactoring the code to allow for this design change. The recursive functions do not use the `main.setting.state.status` and so the functions need to be updated to instead return the status. I placed a delete on the top level, but recursion is not necessarily properly done yet. I only partially changed the structure to test out some of the recent changes, primarily trying to confirm/deny if the simulate is working as desired. I still need to complete/correct the logic for proper deletion with recursion. Update to utilize the newly added `fll_program_signal_check_loop()` and `fll_program_signal_check_simple()`. Remove all stale and no longer needed signal check defines. --- data/build/stand_alone/configs/remove-config.h | 3 + sources/c/program/kevux/tools/remove/main/common.c | 2 +- .../kevux/tools/remove/main/common/define.h | 13 +- .../program/kevux/tools/remove/main/common/print.c | 1 + .../program/kevux/tools/remove/main/common/print.h | 1 + .../c/program/kevux/tools/remove/main/convert.c | 4 +- .../c/program/kevux/tools/remove/main/operate.c | 216 +++++++++------------ .../c/program/kevux/tools/remove/main/operate.h | 79 +++++--- .../c/program/kevux/tools/remove/main/preprocess.c | 71 +------ .../c/program/kevux/tools/remove/main/preprocess.h | 53 ----- sources/c/program/kevux/tools/remove/main/remove.c | 4 +- sources/c/program/kevux/tools/remove/main/signal.c | 39 +--- sources/c/program/kevux/tools/remove/main/signal.h | 36 ---- sources/c/program/kevux/tools/remove/remove/main.c | 2 +- sources/c/program/kevux/tools/remove/rm/main.c | 2 +- sources/c/program/kevux/tools/remove/rmdir/main.c | 2 +- sources/c/program/kevux/tools/remove/unlink/main.c | 2 +- tests/unit/remove/c/main-test-remove.c | 8 +- 18 files changed, 189 insertions(+), 349 deletions(-) diff --git a/data/build/stand_alone/configs/remove-config.h b/data/build/stand_alone/configs/remove-config.h index ef897bc..7aea9e8 100644 --- a/data/build/stand_alone/configs/remove-config.h +++ b/data/build/stand_alone/configs/remove-config.h @@ -1784,6 +1784,9 @@ //#define _di_fll_program_print_version_ //#define _di_fll_program_s_a_ //#define _di_fll_program_s_e_ +//#define _di_fll_program_signal_check_loop_ +//#define _di_fll_program_signal_check_simple_ +//#define _di_fll_program_signal_d_ //#define _di_fll_program_standard_set_down_ //#define _di_fll_program_standard_set_up_ //#define _di_fll_program_standard_signal_handle_ diff --git a/sources/c/program/kevux/tools/remove/main/common.c b/sources/c/program/kevux/tools/remove/main/common.c index 8f15738..be56022 100644 --- a/sources/c/program/kevux/tools/remove/main/common.c +++ b/sources/c/program/kevux/tools/remove/main/common.c @@ -207,7 +207,7 @@ extern "C" { break; } - if (kt_remove_signal_check(main)) return; + if (macro_kt_remove_signal_check(&main->program, &main->setting.state)) return; } // for if (j == 12) { diff --git a/sources/c/program/kevux/tools/remove/main/common/define.h b/sources/c/program/kevux/tools/remove/main/common/define.h index c8958b8..26efe62 100644 --- a/sources/c/program/kevux/tools/remove/main/common/define.h +++ b/sources/c/program/kevux/tools/remove/main/common/define.h @@ -29,7 +29,6 @@ extern "C" { * - max: The maximum recursion depth to perform when recursing into a directory. * * kt_remove_signal_*_d: - * - check: When not using threads, this is how often to perform the check (lower numbers incur more kernel I/O). * - check_failsafe: When using threads, how many consecutive failures to check signal before aborting (as a recursion failsafe). * * kt_remove_time_seconds_in_*_d: @@ -48,7 +47,6 @@ extern "C" { #define kt_remove_poll_timeout_d 200 - #define kt_remove_signal_check_d 20000 #define kt_remove_signal_check_failsafe_d 20000 #define kt_remove_time_seconds_in_day_d 86400 @@ -332,6 +330,17 @@ extern "C" { #define kt_remove_print_flag_warning_d 0x40 #endif // _di_kt_remove_print_flag_d_ +/** + * A macro wrapping the appropriate signal check function based on threaded/non-threaded support. + */ +#ifndef _di_kt_remove_signal_check_d_ + #ifdef _di_thread_support_ + #define macro_kt_remove_signal_check(program, state) fll_program_signal_check_loop(program, state) + #else + #define macro_kt_remove_signal_check(program, state) fll_program_signal_check_simple(program, state) + #endif // _di_thread_support_ +#endif // _di_kt_remove_signal_check_d_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/sources/c/program/kevux/tools/remove/main/common/print.c b/sources/c/program/kevux/tools/remove/main/common/print.c index 25876b4..0a0c84b 100644 --- a/sources/c/program/kevux/tools/remove/main/common/print.c +++ b/sources/c/program/kevux/tools/remove/main/common/print.c @@ -36,6 +36,7 @@ extern "C" { "kt_remove_get_id", "kt_remove_modes_resize", "kt_remove_operate_memory_save", + "kt_remove_preprocess_file", "kt_remove_setting_load", }; #endif // _di_kt_remove_f_a_ diff --git a/sources/c/program/kevux/tools/remove/main/common/print.h b/sources/c/program/kevux/tools/remove/main/common/print.h index 9aabec0..d8bda1e 100644 --- a/sources/c/program/kevux/tools/remove/main/common/print.h +++ b/sources/c/program/kevux/tools/remove/main/common/print.h @@ -69,6 +69,7 @@ extern "C" { kt_remove_f_kt_remove_get_id_e, kt_remove_f_kt_remove_modes_resize_e, kt_remove_f_kt_remove_operate_memory_save_e, + kt_remove_f_kt_remove_preprocess_file_e, kt_remove_f_kt_remove_setting_load_e, }; // enum #endif // _di_kt_remove_f_e_ diff --git a/sources/c/program/kevux/tools/remove/main/convert.c b/sources/c/program/kevux/tools/remove/main/convert.c index 9d108d1..b4fda78 100644 --- a/sources/c/program/kevux/tools/remove/main/convert.c +++ b/sources/c/program/kevux/tools/remove/main/convert.c @@ -63,7 +63,7 @@ extern "C" { for (; range.start <= range.stop; range.start += width, width_max -= width) { - if (kt_remove_signal_check(main)) return; + if (macro_kt_remove_signal_check(&main->program, &main->setting.state)) return; // Skip past NULL characters. if (!buffer.string[range.start]) { @@ -325,7 +325,7 @@ extern "C" { for (f_number_unsigned_t i = 0; i < 15; ++i) { - if (kt_remove_signal_check(main)) return; + if (macro_kt_remove_signal_check(&main->program, &main->setting.state)) return; memset(&time, 0, sizeof(struct tm)); diff --git a/sources/c/program/kevux/tools/remove/main/operate.c b/sources/c/program/kevux/tools/remove/main/operate.c index 00e2c2c..658e321 100644 --- a/sources/c/program/kevux/tools/remove/main/operate.c +++ b/sources/c/program/kevux/tools/remove/main/operate.c @@ -17,77 +17,68 @@ extern "C" { recurse.state.interrupt = &kt_remove_signal_check_recurse; recurse.depth_max = main->setting.flag & kt_remove_main_flag_recurse_d ? kt_remove_depth_max_d : 0; - recurse.flag = main->setting.flag & kt_remove_main_flag_recurse_d ? f_directory_recurse_do_flag_top_after_e : 0; + recurse.flag = 0; recurse.path_top = &path; recurse.action = &kt_remove_operate_recurse_action; recurse.handle = &kt_remove_operate_recurse_handle; fl_directory_do(path, &recurse); + if (F_status_is_error(recurse.state.status)) return recurse.state.status; - const f_status_t status = f_directory_recurse_do_delete(&recurse); + f_status_t status_remove = F_no; - return F_status_is_error(recurse.state.status) - ? recurse.state.status - : F_status_is_error(status) - ? status - : F_yes; + // Remove the directory, if not simulating. + if (!(main->setting.flag & kt_remove_main_flag_simulate_d)) { + status_remove = kt_remove_operate_remove(main, path, flag_operate); + } + + { + const f_status_t status = f_directory_recurse_do_delete(&recurse); + if (F_status_is_error(status)) return status; + } + + return status_remove; } #endif // _di_kt_remove_operate_directory_ #ifndef _di_kt_remove_operate_file_ - void kt_remove_operate_file(kt_remove_main_t * const main, const f_string_static_t path) { + f_status_t kt_remove_operate_file(kt_remove_main_t * const main, const f_string_static_t path) { - if (!main) return; - - if (!path.used) { - main->setting.state.status = F_data_not; - - return; - } + if (!main) return F_status_set_error(F_parameter); + if (!path.used) return F_data_not; + if (F_status_is_error(main->setting.state.status)) return F_no; - if (kt_remove_signal_check(main)) return; + if (macro_kt_remove_signal_check(&main->program, &main->setting.state)) return F_status_set_error(F_interrupt); const uint32_t flag_operate = kt_remove_preprocess_file(main, path, 0); - f_status_t status = F_no; - if (F_status_is_error_not(main->setting.state.status) && !(flag_operate & kt_remove_flag_file_operate_processed_d)) { - if (flag_operate & kt_remove_flag_file_operate_missing_d) { - if (main->setting.flag & kt_remove_main_flag_force_simulate_d) { - status = main->setting.state.status = F_no; - } - else { - main->setting.state.status = F_status_set_error(F_file_found_not); + if (F_status_is_error(main->setting.state.status)) return main->setting.state.status; + if (flag_operate & kt_remove_flag_file_operate_processed_d) return F_no; - kt_remove_print_error_file(&main->program.error, macro_kt_remove_f(f_file_exists), path, f_file_operation_delete_s, fll_error_file_type_file_e); - } - } - else { - kt_remove_operate_file_prompt(main, path, flag_operate); + f_status_t status_remove = F_no; - if (!(main->setting.flag & kt_remove_main_flag_simulate_d)) { - if (F_status_is_error_not(main->setting.state.status) && main->setting.state.status != F_skip) { - main->setting.state.status = F_okay; + if (flag_operate & kt_remove_flag_file_operate_missing_d) { + if (!(main->setting.flag & kt_remove_main_flag_force_simulate_d)) { + main->setting.state.status = F_status_set_error(F_file_found_not); - status = main->setting.state.status = (flag_operate & kt_remove_flag_file_operate_directory_d) - ? kt_remove_operate_directory(main, path, flag_operate) - : kt_remove_operate_remove(main, path, flag_operate); - } - } - } - } - - if (F_status_is_error_not(main->setting.state.status)) { - kt_remove_operate_memory_save(main, path, flag_operate); + kt_remove_print_error_file(&main->program.error, macro_kt_remove_f(kt_remove_preprocess_file), path, f_file_operation_delete_s, fll_error_file_type_file_e); - if (F_status_is_error(main->setting.state.status)) { - kt_remove_print_error_file(&main->program.error, macro_kt_remove_f(kt_remove_operate_memory_save), path, f_file_operation_process_s, fll_error_file_type_path_e); + return main->setting.state.status; } } + else if (main->setting.state.status != F_skip) { + main->setting.state.status = kt_remove_operate_file_prompt(main, path, flag_operate); + if (F_status_is_error(main->setting.state.status)) return main->setting.state.status; - if (F_status_is_error_not(main->setting.state.status)) { - main->setting.state.status = status; + return (flag_operate & kt_remove_flag_file_operate_directory_d) + ? kt_remove_operate_directory(main, path, flag_operate) + : !(main->setting.flag & kt_remove_main_flag_simulate_d) + ? kt_remove_operate_remove(main, path, flag_operate) + : F_no; } + + return F_no; } #endif // _di_kt_remove_operate_file_ @@ -102,7 +93,7 @@ extern "C" { return; } - if (kt_remove_signal_check(main)) return; + if (macro_kt_remove_signal_check(&main->program, &main->setting.state)) return; const uint32_t flag_operate = kt_remove_preprocess_file(main, path, kt_remove_flag_file_operate_parent_d); @@ -130,44 +121,36 @@ extern "C" { #endif // _di_kt_remove_operate_file_parent_ #ifndef _di_kt_remove_operate_file_prompt_ - void kt_remove_operate_file_prompt(kt_remove_main_t * const main, const f_string_static_t path, const uint flag_operate) { - - if (!main) return; - - if (!(main->setting.flag & kt_remove_main_flag_prompt_all_d) || (main->setting.flag & kt_remove_main_flag_prompt_never_d)) { - main->setting.state.status = F_okay; - - return; - } - - if (!path.used) { - main->setting.state.status = F_data_not; + f_status_t kt_remove_operate_file_prompt(kt_remove_main_t * const main, const f_string_static_t path, const uint flag_operate) { - return; - } + if (!main) return F_status_set_error(F_parameter); + if (!(main->setting.flag & kt_remove_main_flag_prompt_all_d) || (main->setting.flag & kt_remove_main_flag_prompt_never_d)) return F_okay; + if (!path.used) return F_data_not; if (main->setting.flag & kt_remove_main_flag_prompt_once_d) { - if (main->setting.prompt) return; + if (main->setting.prompt) return F_okay; main->setting.prompt = 1; } else if (main->setting.flag & kt_remove_main_flag_prompt_follow_d) { - if (!(flag_operate & kt_remove_flag_file_operate_link_d)) return; + if (!(flag_operate & kt_remove_flag_file_operate_link_d)) return F_okay; } - if (main->setting.flag & kt_remove_main_flag_simulate_d) return; + if (main->setting.flag & kt_remove_main_flag_simulate_d) return F_okay; + + f_status_t status = F_okay; main->cache.input.used = 0; kt_remove_print_message_remove_confirm(&main->program.message, path); if (!main->cache.polls.size) { - main->setting.state.status = f_memory_array_increase(1, sizeof(f_poll_t), (void **) &main->cache.polls.array, &main->cache.polls.used, &main->cache.polls.size); + status = f_memory_array_increase(1, sizeof(f_poll_t), (void **) &main->cache.polls.array, &main->cache.polls.used, &main->cache.polls.size); - if (F_status_is_error(main->setting.state.status)) { + if (F_status_is_error(status)) { kt_remove_print_error(&main->program.error, macro_kt_remove_f(f_memory_array_increase)); - return; + return status; } // This is only every used here so assign this once and never again. @@ -179,23 +162,23 @@ extern "C" { // Use polling to read input while allowing interrupt signals to be received (the read() function blocks signals). do { - main->setting.state.status = f_file_poll(main->cache.polls, kt_remove_poll_timeout_d); + status = f_file_poll(main->cache.polls, kt_remove_poll_timeout_d); - if (F_status_is_error(main->setting.state.status)) { + if (F_status_is_error(status)) { kt_remove_print_error(&main->program.error, macro_kt_remove_f(f_file_poll)); - return; + return status; } - if (kt_remove_signal_check(main)) return; - } while (F_status_set_fine(main->setting.state.status) == F_time_out); + if (macro_kt_remove_signal_check(&main->program, &main->setting.state)) return F_status_set_error(F_interrupt); + } while (F_status_set_fine(status) == F_time_out); - main->setting.state.status = f_file_read_block(main->program.input, &main->cache.input); + status = f_file_read_block(main->program.input, &main->cache.input); - if (F_status_is_error(main->setting.state.status)) { + if (F_status_is_error(status)) { kt_remove_print_error_file(&main->program.error, macro_kt_remove_f(f_file_read_block), f_string_empty_s, f_file_operation_read_s, fll_error_file_type_input_e); - return; + return status; } // Skip past any NULL characters in the input. @@ -203,19 +186,18 @@ extern "C" { f_number_unsigned_t i = 0; for (; i < main->cache.input.used && !main->cache.input.string[i]; ++i) { - if (kt_remove_signal_check(main)) return; + if (macro_kt_remove_signal_check(&main->program, &main->setting.state)) return F_status_set_error(F_interrupt); } // for // Only 'y' and 'Y' are treated as confimation and all others equate to 'no'. if (main->cache.input.string[i] == f_string_ascii_y_s.string[0] || main->cache.input.string[i] == f_string_ascii_Y_s.string[0]) { - main->setting.state.status = F_okay; // Shrink an oversized input buffer. if (main->cache.input.size > kt_remove_allocation_large_d) { f_memory_array_resize(0, sizeof(f_char_t), (void **) &main->cache.input.string, &main->cache.input.used, &main->cache.input.size); } - return; + return F_okay; } } @@ -224,7 +206,7 @@ extern "C" { f_memory_array_resize(0, sizeof(f_char_t), (void **) &main->cache.input.string, &main->cache.input.used, &main->cache.input.size); } - main->setting.state.status = (main->setting.flag & kt_remove_main_flag_prompt_once_d) ? F_status_set_error(F_skip) : F_skip; + return (main->setting.flag & kt_remove_main_flag_prompt_once_d) ? F_status_set_error(F_skip) : F_skip; } #endif // _di_kt_remove_operate_file_prompt_ @@ -251,7 +233,7 @@ extern "C" { if (main->setting.flag & kt_remove_main_flag_recurse_d) { for (; i < main->cache.memory.used; ++i) { - if (kt_remove_signal_check(main)) return; + if (macro_kt_remove_signal_check(&main->program, &main->setting.state)) return; if (!main->cache.memory.array[i].used) continue; // The memory cache is nulless and top-most directories end in slashes. @@ -290,7 +272,7 @@ extern "C" { // Only perform exact matches when not using recursion. for (; i < main->cache.memory.used; ++i) { - if (kt_remove_signal_check(main)) return; + if (macro_kt_remove_signal_check(&main->program, &main->setting.state)) return; if (f_compare_dynamic(main->cache.memory.array[i], path) == F_equal_to) { *flag_operate |= kt_remove_flag_file_operate_processed_d; @@ -303,32 +285,22 @@ extern "C" { #endif // _di_kt_remove_operate_memory_check_ #ifndef _di_kt_remove_operate_memory_save_ - void kt_remove_operate_memory_save(kt_remove_main_t * const main, const f_string_static_t path, const uint32_t flag_operate) { - - if (!main) return; - - if (!path.used) { - main->setting.state.status = F_data_not; + f_status_t kt_remove_operate_memory_save(kt_remove_main_t * const main, const f_string_static_t path, const uint32_t flag_operate) { - return; - } - - if (!(main->setting.flag & kt_remove_main_flag_remember_d)) { - main->setting.state.status = F_okay; - - return; - } + if (!main) return F_status_set_error(F_parameter); + if (!path.used) return F_data_not; + if (!(main->setting.flag & kt_remove_main_flag_remember_d)) return F_okay; - main->setting.state.status = f_memory_array_increase(main->setting.state.step_small, sizeof(f_string_dynamic_t), (void **) &main->cache.memory.array, &main->cache.memory.used, &main->cache.memory.size); + f_status_t status = f_memory_array_increase(main->setting.state.step_small, sizeof(f_string_dynamic_t), (void **) &main->cache.memory.array, &main->cache.memory.used, &main->cache.memory.size); // Find any child paths that would be included by this and remove them from the paths list. - if (F_status_is_error_not(main->setting.state.status) && (flag_operate & kt_remove_flag_file_operate_directory_d)) { + if (F_status_is_error_not(status) && (flag_operate & kt_remove_flag_file_operate_directory_d)) { const f_range_t range = macro_f_range_t_initialize_2(path.used); f_number_unsigned_t i = 0; for (; i < main->cache.memory.used; ++i) { - if (kt_remove_signal_check(main)) return; + if (macro_kt_remove_signal_check(&main->program, &main->setting.state)) return F_status_set_error(F_interrupt); if (path.used > main->cache.memory.array[i].used) continue; if (f_compare_dynamic_partial_dynamic(path, main->cache.memory.array[i], range) == F_equal_to) break; @@ -348,14 +320,17 @@ extern "C" { } } - if (F_status_is_error_not(main->setting.state.status)) { - main->setting.state.status = f_string_dynamic_append_nulless(path, &main->cache.memory.array[main->cache.memory.used]); + if (F_status_is_error_not(status)) { + status = f_string_dynamic_append_nulless(path, &main->cache.memory.array[main->cache.memory.used]); } - if (F_status_is_error_not(main->setting.state.status)) { + if (F_status_is_error_not(status)) { ++main->cache.memory.used; - main->setting.state.status = F_okay; + + status = F_okay; } + + return status; } #endif // _di_kt_remove_operate_memory_save_ @@ -365,25 +340,13 @@ extern "C" { if (!recurse || !recurse->state.custom || F_status_set_fine(recurse->state.status) == F_interrupt) return; if (!kt_remove_operate_shall_remove(recurse->state.code) || !(flag & f_directory_recurse_do_flag_action_e)) return; - const f_string_static_t path = flag & f_directory_recurse_do_flag_top_after_e - ? recurse->path_top - ? *recurse->path_top - : f_string_null_s - : recurse->path; - kt_remove_main_t * const main = (kt_remove_main_t *) recurse->state.custom; - recurse->state.status = F_okay; + if (main->setting.flag & kt_remove_main_flag_simulate_d) { + f_print_dynamic(f_string_eol_s, main->program.output.to); + } - recurse->state.status = kt_remove_operate_remove( - main, - path, - flag & f_directory_recurse_do_flag_top_after_e - ? (uint32_t) recurse->state.code - : flag & f_directory_recurse_do_flag_directory_e - ? (((uint32_t) recurse->state.code) | kt_remove_flag_file_operate_child_d | kt_remove_flag_file_operate_directory_d) & ~kt_remove_flag_file_operate_parent_d - : (((uint32_t) recurse->state.code) | kt_remove_flag_file_operate_child_d) & ~kt_remove_flag_file_operate_directory_parent_d - ); + recurse->state.status = kt_remove_operate_file(main, recurse->path); if (F_status_is_error_not(recurse->state.status)) { recurse->state.status = F_okay; @@ -451,9 +414,11 @@ extern "C" { } } + const f_string_static_t target = (flag_operate & kt_remove_flag_file_operate_follow_d) ? main->cache.buffer : path; + status = flag_operate & kt_remove_flag_file_operate_directory_d - ? f_directory_remove((flag_operate & kt_remove_flag_file_operate_follow_d) ? main->cache.buffer : path, (main->setting.state.status & kt_remove_main_flag_recurse_d) ? kt_remove_depth_max_d : 0, F_false) - : f_file_remove((flag_operate & kt_remove_flag_file_operate_follow_d) ? main->cache.buffer : path); + ? f_directory_remove(target, (main->setting.flag & kt_remove_main_flag_recurse_d) ? kt_remove_depth_max_d : 0, F_false) + : f_file_remove(target); if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_directory_empty_not && (flag_operate & kt_remove_flag_file_operate_remove_not_d)) { @@ -481,7 +446,16 @@ extern "C" { } if (status == F_yes) { - kt_remove_print_verbose_operate_file_remove(&main->program.output, path, flag_operate); + kt_remove_print_verbose_operate_file_remove(&main->program.output, target, flag_operate); + + status = kt_remove_operate_memory_save(main, target, flag_operate); + + if (F_status_is_error(status)) { + kt_remove_print_error_file(&main->program.error, macro_kt_remove_f(kt_remove_operate_memory_save), path, f_file_operation_process_s, fll_error_file_type_path_e); + } + else { + status = F_yes; + } } return status; diff --git a/sources/c/program/kevux/tools/remove/main/operate.h b/sources/c/program/kevux/tools/remove/main/operate.h index 6043de6..e9e587e 100644 --- a/sources/c/program/kevux/tools/remove/main/operate.h +++ b/sources/c/program/kevux/tools/remove/main/operate.h @@ -53,23 +53,36 @@ extern "C" { * * Must not be NULL. * - * This alters main.setting.state.status: - * F_no on success and not removed. - * F_data_not on success but path is an empty string. - * - * Success from: kt_remove_operate_directory() - * Success from: kt_remove_operate_remove() - * - * Errors (with error bit) from: kt_remove_operate_directory(). - * Errors (with error bit) from: kt_remove_operate_memory_save(). - * Errors (with error bit) from: kt_remove_operate_remove(). - * Errors (with error bit) from: kt_remove_preprocess_file(). + * This does not directly alter main.setting.state.status. * @param path * The path to the file to operate on. * * This should always be TRUE when calling from the top level. * This should always be FALSE if calling from within a fl_directory_do() callback. * This is because fl_directory_do() handles directory traversal and processing. + * @param state + * The state information for processing. + * A new state should be created rather than using the main.setting.state to prevent conflicts during recursion. + * The first state outside of recursion can use main.setting.state. + * + * Must not be NULL. + * + * @return + * F_yes on success and removed. + * F_no on success and not removed. + * F_data_not on success but path is an empty string. + * + * F_file_found_not (with error bit) on file not found. + * F_interrupt (with error bit) on interrupt. + * F_parameter (with error bit) on invalid parameter. + * + * Success from: kt_remove_operate_directory() + * Success from: kt_remove_operate_remove() + * + * Errors (with error bit) from: kt_remove_operate_directory(). + * Errors (with error bit) from: kt_remove_operate_memory_save(). + * Errors (with error bit) from: kt_remove_operate_remove(). + * Errors (with error bit) from: kt_remove_preprocess_file(). * * @see kt_remove_operate_directory() * @see kt_remove_operate_memory_save() @@ -77,7 +90,7 @@ extern "C" { * @see kt_remove_preprocess_file() */ #ifndef _di_kt_remove_operate_file_ - extern void kt_remove_operate_file(kt_remove_main_t * const main, const f_string_static_t path); + extern f_status_t kt_remove_operate_file(kt_remove_main_t * const main, const f_string_static_t path); #endif // _di_kt_remove_operate_file_ /** @@ -120,17 +133,26 @@ extern "C" { * * Must not be NULL. * - * This alters main.setting.state.status: - * F_okay on success or if prompting is not requested. - * F_data_not on success but path is an empty string. - * F_skip on success and the file is not to be removed (skipped). + * This does not alter main.setting.state.status. * - * F_skip (with error bit) if skipping should be applied to all paths to be removed from this point forward. * @param path * The path to the file to operate on. + * + * @return + * F_okay on success or if prompting is not requested. + * F_data_not on success but path is an empty string. + * F_skip on success and the file is not to be removed (skipped). + * + * F_interrupt (with error bit) on interrupt. + * F_parameter (with error bit) on invalid parameter. + * F_skip (with error bit) if skipping should be applied to all paths to be removed from this point forward. + * + * Errors (with error bit) from: f_file_poll(). + * Errors (with error bit) from: f_file_read_block(). + * Errors (with error bit) from: f_memory_array_increase(). */ #ifndef _di_kt_remove_operate_file_prompt_ - extern void kt_remove_operate_file_prompt(kt_remove_main_t * const main, const f_string_static_t path, const uint flag_operate); + extern f_status_t kt_remove_operate_file_prompt(kt_remove_main_t * const main, const f_string_static_t path, const uint flag_operate); #endif // _di_kt_remove_operate_file_prompt_ /** @@ -171,20 +193,27 @@ extern "C" { * * Must not be NULL. * - * This alters main.setting.state.status: - * F_okay on success. - * F_data_not on success but path is an empty string. - * - * Errors (with error bit) from: f_string_dynamic_append(). + * This does not alter main.setting.state.status. * @param path * The path to the file to operate on. * @param flag_operate * The operate file specific flags from kt_remove_flag_file_operate_*_e. * - * @see f_string_dynamic_append() + * @return + * F_okay on success. + * F_data_not on success but path is an empty string. + * + * F_interrupt (with error bit) on interrupt. + * F_parameter (with error bit) on invalid parameter. + * + * Errors (with error bit) from: f_memory_array_increase(). + * Errors (with error bit) from: f_string_dynamic_append_nulless(). + * + * @see f_memory_array_increase() + * @see f_string_dynamic_append_nulless() */ #ifndef _di_kt_remove_operate_memory_save_ - extern void kt_remove_operate_memory_save(kt_remove_main_t * const main, const f_string_static_t path, const uint32_t flag_operate); + extern f_status_t kt_remove_operate_memory_save(kt_remove_main_t * const main, const f_string_static_t path, const uint32_t flag_operate); #endif // _di_kt_remove_operate_memory_save_ /** diff --git a/sources/c/program/kevux/tools/remove/main/preprocess.c b/sources/c/program/kevux/tools/remove/main/preprocess.c index 2b2f236..4265642 100644 --- a/sources/c/program/kevux/tools/remove/main/preprocess.c +++ b/sources/c/program/kevux/tools/remove/main/preprocess.c @@ -15,7 +15,7 @@ extern "C" { return 0; } - if (kt_remove_signal_check(main)) return 0; + if (macro_kt_remove_signal_check(&main->program, &main->setting.state)) return 0; uint32_t flag_out = (main->setting.flag & kt_remove_main_flag_option_type_used_d) ? 0 : kt_remove_flag_file_operate_remove_d; @@ -64,7 +64,7 @@ extern "C" { return 0; } - if (kt_remove_signal_check(main)) return 0; + if (macro_kt_remove_signal_check(&main->program, &main->setting.state)) return 0; if (main->setting.flag & kt_remove_main_flag_follow_d) { flag_out |= kt_remove_flag_file_operate_follow_d; @@ -109,7 +109,7 @@ extern "C" { if (main->setting.flag & kt_remove_main_flag_user_d) { for (i = 0; i < main->setting.users.used; ++i) { - if (kt_remove_signal_check(main)) return flag_out; + if (macro_kt_remove_signal_check(&main->program, &main->setting.state)) return flag_out; if (statistics.st_uid == (uid_t) main->setting.users.array[i]) break; } // for @@ -139,7 +139,7 @@ extern "C" { if (main->setting.flag & kt_remove_main_flag_group_d) { for (i = 0; i < main->setting.groups.used; ++i) { - if (kt_remove_signal_check(main)) return flag_out; + if (macro_kt_remove_signal_check(&main->program, &main->setting.state)) return flag_out; if (statistics.st_gid == (gid_t) main->setting.groups.array[i]) break; } // for @@ -171,7 +171,7 @@ extern "C" { for (i = 0; i < main->setting.modes.used; ++i) { - if (kt_remove_signal_check(main)) return flag_out; + if (macro_kt_remove_signal_check(&main->program, &main->setting.state)) return flag_out; if (main->setting.modes.array[i].type == kt_remove_flag_mode_different_d) { if (main->setting.modes.array[i].mode ^ mode) break; @@ -319,16 +319,6 @@ extern "C" { } } - // At this point, the remove situation should be known so recurse into parent or child paths as appropriate before returning. - if (flag_out & kt_remove_flag_file_operate_directory_d) { - main->setting.state.status = F_okay; - - // Recurse only on non-parent directories. - if ((main->setting.flag & kt_remove_main_flag_recurse_d) && !(flag_operate & kt_remove_flag_file_operate_parent_d)) { - main->setting.state.status = kt_remove_preprocess_file_recurse(main, path, flag_out); - } - } - if (F_status_is_error_not(main->setting.state.status)) { main->setting.state.status = F_okay; } @@ -337,38 +327,6 @@ extern "C" { } #endif // _di_kt_remove_preprocess_file_ -#ifndef _di_kt_remove_preprocess_file_recurse_ - f_status_t kt_remove_preprocess_file_recurse(kt_remove_main_t * const main, const f_string_static_t path, const uint32_t flag_operate) { - - if (!kt_remove_operate_shall_remove(flag_operate)) return (flag_operate & kt_remove_flag_file_operate_remove_fail_d) ? F_status_set_error(F_no) : F_no; - - f_directory_recurse_do_t recurse = f_directory_recurse_do_t_initialize; - - // The recurse.state.code flags represent the top-level directory being recursed on. - recurse.state.code = flag_operate; - recurse.state.custom = (void *) main; - recurse.state.interrupt = &kt_remove_signal_check_recurse; - - // The pre-process does not need the fl_directory_do() to operate on the top-level because it is already doing this and so the top_after recurse.flag must not be set. - recurse.depth_max = main->setting.flag & kt_remove_main_flag_recurse_d ? kt_remove_depth_max_d : 0; - recurse.flag = 0; - recurse.path_top = &path; - - recurse.action = &kt_remove_preprocess_recurse_action; - recurse.handle = &kt_remove_operate_recurse_handle; - - fl_directory_do(path, &recurse); - - const f_status_t status = f_directory_recurse_do_delete(&recurse); - - return F_status_is_error(recurse.state.status) - ? recurse.state.status - : F_status_is_error(status) - ? status - : F_yes; - } -#endif // _di_kt_remove_preprocess_file_recurse_ - #ifndef _di_kt_remove_preprocess_file_dates_ void kt_remove_preprocess_file_dates(kt_remove_main_t * const main, const f_string_static_t path, const uint32_t flag_operate, const struct stat statistics) { @@ -419,7 +377,7 @@ extern "C" { for (j = 0; j < dates[i]->used; ++j) { - if (kt_remove_signal_check(main)) return; + if (macro_kt_remove_signal_check(&main->program, &main->setting.state)) return; match_nanosecond = times[i].tv_nsec; match_second = times[i].tv_sec % kt_remove_time_seconds_in_year_d; @@ -649,23 +607,6 @@ extern "C" { } #endif // _di_kt_remove_preprocess_file_type_ -#ifndef _di_kt_remove_preprocess_recurse_action_ - void kt_remove_preprocess_recurse_action(f_directory_recurse_do_t * const recurse, const f_string_static_t name, const uint32_t flag) { - - if (!recurse || !recurse->state.custom || F_status_set_fine(recurse->state.status) == F_interrupt) return; - - if (flag & f_directory_recurse_do_flag_action_e) { - kt_remove_preprocess_file( - (kt_remove_main_t *) recurse->state.custom, - recurse->path, - flag & f_directory_recurse_do_flag_directory_e - ? (recurse->state.code | kt_remove_flag_file_operate_child_d | kt_remove_flag_file_operate_directory_d) & ~kt_remove_flag_file_operate_parent_d - : (recurse->state.code | kt_remove_flag_file_operate_child_d) & ~kt_remove_flag_file_operate_directory_parent_d - ); - } - } -#endif // _di_kt_remove_preprocess_recurse_action_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/sources/c/program/kevux/tools/remove/main/preprocess.h b/sources/c/program/kevux/tools/remove/main/preprocess.h index 4f48405..3720c6b 100644 --- a/sources/c/program/kevux/tools/remove/main/preprocess.h +++ b/sources/c/program/kevux/tools/remove/main/preprocess.h @@ -48,38 +48,6 @@ extern "C" { #endif // _di_kt_remove_preprocess_file_ /** - * Perform actual file removal for directory files. - * - * @param main - * The main program and settings data. - * - * Must not be NULL. - * - * This does not directly alter main.setting.state.status. - * @param path - * The path to the file to operate on. - * @param flag_operate - * The operate file specific flags from kt_remove_flag_file_operate_*_e. - * - * @return - * F_yes on success and file remove. - * F_no on success and file not removed. - * F_data_not on success but path is an empty string. - * - * F_no (with error bit) on failure and file is not to be removed or cannot be removed. - * F_recurse (with error bit) on max recursion depth reached. - * - * Errors (with error bit) from: f_directory_recurse_do_delete() - * Errors (with error bit) from: fl_directory_do() - * - * @see f_directory_recurse_do_delete() - * @see fl_directory_do() - */ -#ifndef _di_kt_remove_preprocess_file_recurse_ - extern f_status_t kt_remove_preprocess_file_recurse(kt_remove_main_t * const main, const f_string_static_t path, const uint32_t flag_operate); -#endif // _di_kt_remove_preprocess_file_recurse_ - -/** * Perform pre-processing (including simulation) of the file operation, specifically handling dates. * * @param main @@ -134,27 +102,6 @@ extern "C" { extern void kt_remove_preprocess_file_type(kt_remove_main_t * const main, const f_string_static_t path, const bool is, f_string_static_t name, const uint64_t type, const uint8_t code, uint32_t * const flag_out); #endif // _di_kt_remove_preprocess_file_type_ -/** - * Perform directory recursion for a single file operation action. - * - * @param recurse - * The directory recurse data. - * - * Must not be NULL. - * @param name - * The name of the file or directory the action is being performed on. - * Does not have the parent directory path. - * May be empty at the top level. - * @param flag - * A flag representing the particular directory action being performed. - * - * @see f_directory_remove() - * @see fl_directory_do() - */ -#ifndef _di_kt_remove_preprocess_recurse_action_ - extern void kt_remove_preprocess_recurse_action(f_directory_recurse_do_t * const recurse, const f_string_static_t name, const uint32_t flag); -#endif // _di_kt_remove_preprocess_recurse_action_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/sources/c/program/kevux/tools/remove/main/remove.c b/sources/c/program/kevux/tools/remove/main/remove.c index 523bca8..5b1750e 100644 --- a/sources/c/program/kevux/tools/remove/main/remove.c +++ b/sources/c/program/kevux/tools/remove/main/remove.c @@ -33,7 +33,7 @@ extern "C" { kt_remove_normal_operate(main); - if (kt_remove_signal_check(main)) { + if (macro_kt_remove_signal_check(&main->program, &main->setting.state)) { fll_program_print_signal_received(&main->program.warning, main->program.signal_received); } } @@ -65,7 +65,7 @@ extern "C" { for (; i < main->setting.files.used; ++i) { - kt_remove_operate_file(main, main->setting.files.array[i]); + main->setting.state.status = kt_remove_operate_file(main, main->setting.files.array[i]); if ((main->setting.flag & kt_remove_main_flag_simulate_d) && i + 1 < main->setting.files.used && (F_status_is_error_not(main->setting.state.status) || F_status_set_fine(main->setting.state.status) == F_interrupt)) { f_print_dynamic(f_string_eol_s, main->program.output.to); diff --git a/sources/c/program/kevux/tools/remove/main/signal.c b/sources/c/program/kevux/tools/remove/main/signal.c index 805d7c4..2d5a3a7 100644 --- a/sources/c/program/kevux/tools/remove/main/signal.c +++ b/sources/c/program/kevux/tools/remove/main/signal.c @@ -4,41 +4,6 @@ extern "C" { #endif -#if !defined(_di_kt_remove_signal_check_) && defined(_di_thread_support_) - f_status_t kt_remove_signal_check(kt_remove_main_t * const main) { - - if (!main) return F_false; - if (main->program.signal_received) return F_true; - - if (!((++main->program.signal_check) % kt_remove_signal_check_d)) { - if (F_status_set_fine(fll_program_standard_signal_received(&main->program)) == F_interrupt) { - main->setting.state.status = F_status_set_error(F_interrupt); - - return F_true; - } - - main->program.signal_check = 0; - } - - return F_false; - } -#endif // !defined(_di_kt_remove_signal_check_) && defined(_di_thread_support_) - -#if !defined(_di_kt_remove_signal_check_) && !defined(_di_thread_support_) - f_status_t kt_remove_signal_check(kt_remove_main_t * const main) { - - if (!main) return F_false; - - if (main->program.signal_received) { - main->setting.state.status = F_status_set_error(F_interrupt); - - return F_true; - } - - return F_false; - } -#endif // !defined(_di_kt_remove_signal_check_) && !defined(_di_thread_support_) - #ifndef _di_kt_remove_signal_check_recurse_ void kt_remove_signal_check_recurse(f_state_t * const state, void * const internal) { @@ -48,7 +13,9 @@ extern "C" { if (!recurse->state.custom) return; - if (kt_remove_signal_check((kt_remove_main_t *) recurse->state.custom)) { + kt_remove_main_t * const main = (kt_remove_main_t *) recurse->state.custom; + + if (macro_kt_remove_signal_check(&main->program, &main->setting.state)) { recurse->state.status = F_status_set_error(F_interrupt); } } diff --git a/sources/c/program/kevux/tools/remove/main/signal.h b/sources/c/program/kevux/tools/remove/main/signal.h index 3b5edf5..e7ad5fc 100644 --- a/sources/c/program/kevux/tools/remove/main/signal.h +++ b/sources/c/program/kevux/tools/remove/main/signal.h @@ -13,40 +13,6 @@ extern "C" { #endif /** - * Check to see if a signal is received. - * - * If main.signal is non-zero, then this handles the following signals: - * - F_signal_abort - * - F_signal_broken_pipe - * - F_signal_hangup - * - F_signal_interrupt - * - F_signal_quit - * - F_signal_termination - * - * There is a threaded and a non-threaded version of this. - * The non-threaded version checks periodically using kt_remove_signal_check_d and updates main->signal_check as needed. - * The threaded version checks the flag state which is set by a separate thread that is blocking until signal is received. - * - * @param main - * The main program and settings data. - * - * Must not be NULL. - * - * This does not alter main.setting.state.status. - * - * @return - * F_true on signal received. - * F_false otherwise. - * - * @see kt_remove_signal_handler() - * - * @see fll_program_standard_signal_received() - */ -#ifndef _di_kt_remove_signal_check_ - extern f_status_t kt_remove_signal_check(kt_remove_main_t * const main); -#endif // _di_kt_remove_signal_check_ - -/** * Check to see if a signal is received, for a recursive directory function. * * This is intended to be passed as a state.interrupt function for use in the fl_directory_do() recursion process. @@ -66,8 +32,6 @@ extern "C" { * * This alters recurse.state.status: * F_interrupt (with error bit) on interrupt signal received. - * - * @see kt_remove_signal_check() */ #ifndef _di_kt_remove_signal_check_recurse_ extern void kt_remove_signal_check_recurse(f_state_t * const state, void * const internal); diff --git a/sources/c/program/kevux/tools/remove/remove/main.c b/sources/c/program/kevux/tools/remove/remove/main.c index 1b927e4..751f2c1 100644 --- a/sources/c/program/kevux/tools/remove/remove/main.c +++ b/sources/c/program/kevux/tools/remove/remove/main.c @@ -74,7 +74,7 @@ int kt_remove_setting_load(arguments, &data); } - if (!kt_remove_signal_check(&data)) { + if (!macro_kt_remove_signal_check(&data.program, &data.setting.state)) { kt_remove_main(&data); } diff --git a/sources/c/program/kevux/tools/remove/rm/main.c b/sources/c/program/kevux/tools/remove/rm/main.c index 60a1c66..cd15282 100644 --- a/sources/c/program/kevux/tools/remove/rm/main.c +++ b/sources/c/program/kevux/tools/remove/rm/main.c @@ -68,7 +68,7 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { kt_remove_rm_setting_load(arguments, &data); } - if (!kt_remove_signal_check(&data)) { + if (!macro_kt_remove_signal_check(&data.program, &data.setting.state)) { kt_remove_main(&data); } diff --git a/sources/c/program/kevux/tools/remove/rmdir/main.c b/sources/c/program/kevux/tools/remove/rmdir/main.c index f7022bd..4d824af 100644 --- a/sources/c/program/kevux/tools/remove/rmdir/main.c +++ b/sources/c/program/kevux/tools/remove/rmdir/main.c @@ -68,7 +68,7 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { kt_remove_rmdir_setting_load(arguments, &data); } - if (!kt_remove_signal_check(&data)) { + if (!macro_kt_remove_signal_check(&data.program, &data.setting.state)) { kt_remove_main(&data); } diff --git a/sources/c/program/kevux/tools/remove/unlink/main.c b/sources/c/program/kevux/tools/remove/unlink/main.c index 81e9bd2..e6fc1de 100644 --- a/sources/c/program/kevux/tools/remove/unlink/main.c +++ b/sources/c/program/kevux/tools/remove/unlink/main.c @@ -68,7 +68,7 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { kt_remove_unlink_setting_load(arguments, &data); } - if (!kt_remove_signal_check(&data)) { + if (!macro_kt_remove_signal_check(&data.program, &data.setting.state)) { kt_remove_main(&data); } diff --git a/tests/unit/remove/c/main-test-remove.c b/tests/unit/remove/c/main-test-remove.c index ad36ce5..a41d352 100644 --- a/tests/unit/remove/c/main-test-remove.c +++ b/tests/unit/remove/c/main-test-remove.c @@ -67,7 +67,7 @@ int main_test__remove(const int argc, const f_string_t *argv, const f_string_t * kt_remove_setting_load(arguments, &data); } - if (!kt_remove_signal_check(&data)) { + if (!macro_kt_remove_signal_check(&data.program, &data.setting.state)) { kt_remove_main(&data); } @@ -81,7 +81,11 @@ int main_test__remove(const int argc, const f_string_t *argv, const f_string_t * fll_program_standard_set_down(&data.program); - return (F_status_is_error(data.setting.state.status) || data.setting.state.status == F_false) ? 1 : 0; + if (F_status_is_error(data.setting.state.status)) { + return F_status_set_fine(data.setting.state.status) == F_support_not ? 2 : 1; + } + + return data.setting.state.status == F_false ? 1 : 0; } #ifdef __cplusplus -- 1.8.3.1