From f46d2c9ba9bb744688043a7c7b8ebb278774b68c Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Sun, 18 Jun 2023 11:58:44 -0500 Subject: [PATCH] Progress: Implement actual file removal for non-directory files. This stubs out the directory removal but does not peform directory removal. The symbolic link following is implemented on removal as well. --- sources/c/remove/main/common/define.h | 15 ++++ sources/c/remove/main/common/enumeration.h | 8 +- sources/c/remove/main/common/print.c | 1 + sources/c/remove/main/common/print.h | 1 + sources/c/remove/main/operate.c | 118 ++++++++++++++++++++++++----- sources/c/remove/main/operate.h | 44 ++++++++++- sources/c/remove/main/remove.h | 6 -- 7 files changed, 162 insertions(+), 31 deletions(-) diff --git a/sources/c/remove/main/common/define.h b/sources/c/remove/main/common/define.h index 5c6772a..cfa4b46 100644 --- a/sources/c/remove/main/common/define.h +++ b/sources/c/remove/main/common/define.h @@ -60,6 +60,21 @@ extern "C" { #define kt_remove_time_year_unix_epoch_d 1970 #endif // _di_kt_remove_d_ +/** + * Defines for bitwise flag enumeration combinations. + * + * kt_remove_main_flag_empty_*_d: + * - all: All empty flag bits are combined. + * + * kt_remove_main_flag_prompt_*_d: + * - all: All prompt flag bits are combined. + */ +#ifndef _di_kt_remove_flag_d_ + #define kt_remove_main_flag_empty_all_d (kt_remove_main_flag_empty_only_e | kt_remove_main_flag_empty_only_fail_e | kt_remove_main_flag_empty_not_e | kt_remove_main_flag_empty_not_fail_e) + + #define kt_remove_main_flag_prompt_all_d (kt_remove_main_flag_prompt_all_e | kt_remove_main_flag_prompt_follow_e | kt_remove_main_flag_prompt_never_e | kt_remove_main_flag_prompt_once_e) +#endif // _di_kt_remove_flag_d_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/sources/c/remove/main/common/enumeration.h b/sources/c/remove/main/common/enumeration.h index 1686a2d..79e0df6 100644 --- a/sources/c/remove/main/common/enumeration.h +++ b/sources/c/remove/main/common/enumeration.h @@ -33,7 +33,7 @@ extern "C" { * - empty_not: Remove not empty directories. * - empty_not_fail: Fail on not empty directories. * - fifo: Remove by file type: FIFO. - * - follow: Follow symbolic links deleting the file being pointed to rather than the link itself (when not set the link itself is deleted). + * - follow: Follow symbolic links for deleting the file being pointed to rather than the link itself (when not set the link itself is deleted). * - force: Forcibly delete. * - group: Remove by GID. * - help: Print help. @@ -202,6 +202,7 @@ extern "C" { * kt_remove_flag_file_operate_*_e: * - none: No flags set. * - directory: Is a directory. + * - follow: Follow the symbolic link. * - recurse: Perform recursively (only on directories). * - remove: Perform remove. */ @@ -209,8 +210,9 @@ extern "C" { enum { kt_remove_flag_file_operate_none_e = 0x0, kt_remove_flag_file_operate_directory_e = 0x1, - kt_remove_flag_file_operate_recurse_e = 0x2, - kt_remove_flag_file_operate_remove_e = 0x4, + kt_remove_flag_file_operate_follow_e = 0x2, + kt_remove_flag_file_operate_recurse_e = 0x4, + kt_remove_flag_file_operate_remove_e = 0x8, }; // enum #endif // _di_kt_remove_flag_file_operate_e_ diff --git a/sources/c/remove/main/common/print.c b/sources/c/remove/main/common/print.c index 54d7e31..b7195ad 100644 --- a/sources/c/remove/main/common/print.c +++ b/sources/c/remove/main/common/print.c @@ -10,6 +10,7 @@ extern "C" { "f_console_parameter_process", "f_file_mode_from_string", "f_file_mode_to_mode", + "f_file_remove", "f_string_dynamics_increase_by", "f_thread_create", "f_uint32s_increase_by", diff --git a/sources/c/remove/main/common/print.h b/sources/c/remove/main/common/print.h index 8f6c053..21e0dcf 100644 --- a/sources/c/remove/main/common/print.h +++ b/sources/c/remove/main/common/print.h @@ -43,6 +43,7 @@ extern "C" { kt_remove_f_f_console_parameter_process_e, kt_remove_f_f_file_mode_from_string_e, kt_remove_f_f_file_mode_to_mode_e, + kt_remove_f_f_file_remove_e, kt_remove_f_f_string_dynamics_increase_by_e, kt_remove_f_f_thread_create_e, kt_remove_f_f_uint32s_increase_by_e, diff --git a/sources/c/remove/main/operate.c b/sources/c/remove/main/operate.c index ed6ac28..3da1421 100644 --- a/sources/c/remove/main/operate.c +++ b/sources/c/remove/main/operate.c @@ -50,6 +50,10 @@ extern "C" { f_number_unsigned_t i = 0; uint8_t flag = (main->setting.flag & kt_remove_main_flag_option_used_e) ? 0 : kt_remove_flag_file_operate_remove_e; + if (main->setting.flag & kt_remove_main_flag_follow_e) { + flag |= kt_remove_flag_file_operate_follow_e; + } + struct stat statistics; memset(&statistics, 0, sizeof(struct stat)); @@ -67,18 +71,19 @@ extern "C" { } if (main->setting.flag & kt_remove_main_flag_block_e) { - if (macro_f_file_type_get(statistics.st_mode) == F_file_type_block_d) { + if (macro_f_file_type_is_block(statistics.st_mode)) { flag |= kt_remove_flag_file_operate_remove_e; } } if (main->setting.flag & kt_remove_main_flag_character_e) { - if (macro_f_file_type_get(statistics.st_mode) == F_file_type_character_d) { + if (macro_f_file_type_is_character(statistics.st_mode)) { flag |= kt_remove_flag_file_operate_remove_e; } } - if (macro_f_file_type_get(statistics.st_mode) == F_file_type_directory_d) { + + if (macro_f_file_type_is_directory(statistics.st_mode)) { flag |= kt_remove_flag_file_operate_directory_e; if (main->setting.flag & kt_remove_main_flag_directory_e) { @@ -87,25 +92,25 @@ extern "C" { } if (main->setting.flag & kt_remove_main_flag_fifo_e) { - if (macro_f_file_type_get(statistics.st_mode) == F_file_type_fifo_d) { + if (macro_f_file_type_is_fifo(statistics.st_mode)) { flag |= kt_remove_flag_file_operate_remove_e; } } if (main->setting.flag & kt_remove_main_flag_link_e) { - if (macro_f_file_type_get(statistics.st_mode) == F_file_type_link_d) { + if (macro_f_file_type_is_link(statistics.st_mode)) { flag |= kt_remove_flag_file_operate_remove_e; } } if (main->setting.flag & kt_remove_main_flag_regular_e) { - if (macro_f_file_type_get(statistics.st_mode) == F_file_type_regular_d) { + if (macro_f_file_type_is_regular(statistics.st_mode)) { flag |= kt_remove_flag_file_operate_remove_e; } } if (main->setting.flag & kt_remove_main_flag_socket_e) { - if (macro_f_file_type_get(statistics.st_mode) == F_file_type_socket_d) { + if (macro_f_file_type_is_socket(statistics.st_mode)) { flag |= kt_remove_flag_file_operate_remove_e; } } @@ -204,25 +209,98 @@ extern "C" { kt_remove_print_simulate_operate_boolean(&main->program.output, kt_remove_recurse_s, flag & kt_remove_flag_file_operate_recurse_e); } - // @todo add check here to see if file is a directory, apply any appropriate restrictions (such as not removing non-empty directories without force or recursive). - // @todo be sure too handle all of the remaining flags, such as tree, force, recurse, etc...: - // - kt_remove_main_flag_empty_only_e - // - kt_remove_main_flag_empty_only_fail_e - // - kt_remove_main_flag_empty_not_e - // - kt_remove_main_flag_empty_not_fail_e - // - kt_remove_main_flag_prompt_all_e - // - kt_remove_main_flag_prompt_follow_e - // - kt_remove_main_flag_prompt_never_e - // - kt_remove_main_flag_prompt_once_e - // - kt_remove_main_flag_recurse_e - // - kt_remove_main_flag_tree_e + if (flag & kt_remove_flag_file_operate_directory_e) { + if (main->setting.flag & kt_remove_main_flag_empty_all_d) { + // @todo handle simulate for this. + } + + // Recurse effectively forces tree. + if (main->setting.flag & kt_remove_main_flag_recurse_e) { + // @todo handle simulate for this. + // @todo consider not following "rm" and having recurse not act like "--force" is specified. + } + else if (main->setting.flag & kt_remove_main_flag_tree_e) { + // @todo handle simulate for this. + } + } + + if (main->setting.flag & kt_remove_main_flag_prompt_all_d) { + // @todo handle simulate for this. + } kt_remove_print_simulate_operate_boolean(&main->program.output, kt_remove_remove_s, flag & kt_remove_flag_file_operate_remove_e); - // @todo do actual removal. + if (!(main->setting.flag & kt_remove_main_flag_simulate_e)) { + if (flag & kt_remove_flag_file_operate_directory_e) { + kt_remove_operate_file_directory(main, path, flag); + if (F_status_is_error(main->setting.state.status)) return; + } + else { + kt_remove_operate_file_normal(main, path, flag); + if (F_status_is_error(main->setting.state.status)) return; + } + } + + main->setting.state.status = F_none; } #endif // _di_kt_remove_operate_file_ +#ifndef _di_kt_remove_operate_file_directory_ + void kt_remove_operate_file_directory(kt_remove_main_t * const main, const f_string_static_t path, const uint8_t flag) { + + if (!(flag & kt_remove_flag_file_operate_remove_e)) { + main->setting.state.status = F_no; + + return; + } + + main->setting.state.status = F_yes; + } +#endif // _di_kt_remove_operate_file_directory_ + +#ifndef _di_kt_remove_operate_file_normal_ + void kt_remove_operate_file_normal(kt_remove_main_t * const main, const f_string_static_t path, const uint8_t flag) { + + if (!(flag & kt_remove_flag_file_operate_remove_e)) { + main->setting.state.status = F_no; + + return; + } + + // @todo consider providing a "follow deep" parameter for recursively following until a non-link is reached. + if (flag & kt_remove_flag_file_operate_follow_e) { + main->setting.buffer.used = 0; + + main->setting.state.status = f_file_link_read(path, F_false, &main->setting.buffer); + + if (F_status_is_error(main->setting.state.status)) { + kt_remove_print_error_file(&main->program.error, macro_kt_remove_f(f_file_remove), path, f_file_operation_stat_s, fll_error_file_type_link_e); + + return; + } + + main->setting.state.status = f_file_remove(main->setting.buffer); + + if (F_status_is_error(main->setting.state.status)) { + kt_remove_print_error_file(&main->program.error, macro_kt_remove_f(f_file_remove), main->setting.buffer, f_file_operation_delete_s, fll_error_file_type_file_e); + + return; + } + } + else { + main->setting.state.status = f_file_remove(path); + + if (F_status_is_error(main->setting.state.status)) { + kt_remove_print_error_file(&main->program.error, macro_kt_remove_f(f_file_remove), path, f_file_operation_delete_s, fll_error_file_type_file_e); + + return; + } + } + + main->setting.state.status = F_yes; + } +#endif // _di_kt_remove_operate_file_normal_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/sources/c/remove/main/operate.h b/sources/c/remove/main/operate.h index c609166..1253df3 100644 --- a/sources/c/remove/main/operate.h +++ b/sources/c/remove/main/operate.h @@ -21,8 +21,6 @@ extern "C" { * This alters main.setting.state.status: * F_none on success. * F_data_not on success but file is an empty string. - * - * F_parameter (with error bit) if main is NULL or setting is NULL. * @param path * The path to the file to operate on. */ @@ -30,6 +28,48 @@ extern "C" { extern void kt_remove_operate_file(kt_remove_main_t * const main, const f_string_static_t path); #endif // _di_kt_remove_operate_file_ +/** + * Perform actual file removal for directory files. + * + * @param main + * The main program and settings data. + * + * This alters main.setting.state.status: + * F_no on success but file is not to be removed. + * F_yes on success and file is removed. + * + * Errors (with error bit) from: f_file_remove(). + * @param path + * The path to the file to operate on. + * @param flag + * The operate file specific flags from kt_remove_flag_file_operate_*_e. + */ +#ifndef _di_kt_remove_operate_file_directory_ + extern void kt_remove_operate_file_directory(kt_remove_main_t * const main, const f_string_static_t path, const uint8_t flag); +#endif // _di_kt_remove_operate_file_directory_ + +/** + * Perform actual file removal for non-directory files. + * + * @param main + * The main program and settings data. + * + * This alters main.setting.state.status: + * F_no on success but file is not to be removed. + * F_yes on success and file is removed. + * + * Errors (with error bit) from: f_file_remove(). + * @param path + * The path to the file to operate on. + * @param flag + * The operate file specific flags from kt_remove_flag_file_operate_*_e. + * + * @see f_file_remove() + */ +#ifndef _di_kt_remove_operate_file_normal_ + extern void kt_remove_operate_file_normal(kt_remove_main_t * const main, const f_string_static_t path, const uint8_t flag); +#endif // _di_kt_remove_operate_file_normal_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/sources/c/remove/main/remove.h b/sources/c/remove/main/remove.h index 125d828..bb03653 100644 --- a/sources/c/remove/main/remove.h +++ b/sources/c/remove/main/remove.h @@ -85,8 +85,6 @@ extern "C" { * F_true on success when performing verification and verify passed. * F_false on success when performing verification and verify failed. * F_interrupt on (exit) signal received. - * - * F_parameter (with error bit) if main is NULL or setting is NULL. */ #ifndef _di_kt_remove_main_ extern void kt_remove_main(kt_remove_main_t * const main); @@ -121,8 +119,6 @@ extern "C" { * This alters main.setting.state.status: * F_none on success. * - * F_parameter (with error bit) if main is NULL or setting is NULL. - * * Errors with (error bit set) from: kt_remove_process_normal_operate() * * @see kt_remove_process_normal_operate() @@ -139,8 +135,6 @@ extern "C" { * * This alters main.setting.state.status: * F_none on success. - * - * F_parameter (with error bit) if main is NULL or setting is NULL. */ #ifndef _di_kt_remove_process_normal_operate_ extern void kt_remove_process_normal_operate(kt_remove_main_t * const main); -- 1.8.3.1