Much of the work is drafted out and likely to change.
The core of the 'remove' program is implemented.
The 'date' related functionality is actively being worked on.
The actual removal functionality will be implemented after all of the simulation is completed.
Once the remove is implemented and working, then supplementary 'remove' programs, such as 'rm', 'unlink', and 'rmdir' will be implemented.
--- /dev/null
+# fss-0000
+
+_di_thread_support_ Disable thread support, handling signals without using a separate thread.
+_en_kt_settings_path_ Enable support for processing that settings path, such as /etc/.
+_en_kt_process_path_ Enable support for processing that process path, such as /proc/.
+_en_kt_default_to_utc_ Default to UTC mode rather than local time.
--- /dev/null
+# fss-0000
+
+f_type
+f_status
+f_memory
+f_type_array
+f_string
+f_utf
+f_account
+f_color
+f_console
+f_conversion
+f_file
+f_print
+f_signal
+f_thread
+
+fl_conversion
+fl_string
+fl_print
+
+fll_program
--- /dev/null
+# fss-0005 iki-0002
+
+settings:
+ fail exit
+ modes individual level monolithic clang test
+
+ environment PATH LD_LIBRARY_PATH
+
+main:
+ build remove/settings
--- /dev/null
+# fss-0001
+
+build_name remove
+
+version_major 0
+version_minor 5
+version_micro 0
+version_file micro
+version_target minor
+
+modes individual level monolithic clang test threaded threadless
+modes_default monolithic threaded
+
+build_compiler gcc
+build_compiler-clang clang
+build_indexer ar
+build_indexer_arguments rcs
+build_language c
+
+build_libraries -lc
+build_libraries-individual -lfll_error -lfll_print -lfll_program -lfl_conversion -lfl_print -lfl_string -lf_account -lf_color -lf_console -lf_conversion -lf_file -lf_memory -lf_pipe -lf_print -lf_signal -lf_string -lf_type_array -lf_utf
+build_libraries-level -lfll_2 -lfll_1 -lfll_0
+build_libraries-monolithic -lfll
+
+build_sources_library common.c common-print.c convert.c operate.c print.c remove.c signal.c simulate.c thread.c
+
+build_sources_program main.c
+
+build_sources_headers common.h common-print.h convert.h operate.h print.h remove.h signal.h simulate.h thread.h
+
+build_script yes
+build_shared yes
+build_static no
+
+path_headers program/kevux/tools/remove
+path_library_script script
+path_library_shared shared
+path_library_static static
+path_object_script script
+path_object_shared shared
+path_object_static static
+path_program_script script
+path_program_shared shared
+path_program_static static
+path_sources sources/c/remove/main
+
+has_path_standard no
+preserve_path_headers yes
+
+search_exclusive yes
+search_shared yes
+search_static yes
+
+environment PATH LD_LIBRARY_PATH
+
+#defines -D_di_libcap_
+defines -D_libcap_legacy_only_
+defines-threaded -D_pthread_attr_unsupported_ -D_pthread_sigqueue_unsupported_
+defines-threadless -D_di_thread_support_
+
+flags -O2 -z now -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-parentheses -Wno-missing-braces
+flags-clang -Wno-logical-op-parentheses
+flags-test -O0 -fstack-protector -Wall
+flags-coverage -O0 --coverage -fprofile-abs-path -fprofile-dir=build/coverage/
+
+flags_library -fPIC
+flags_object -fPIC
+flags_program -fPIE
# license: cc-by-sa-4.0
#
# This file (assumed to be named readme.build.txt) can be more easily read using the following iki_read commands:
-# iki_read readme.build.txt +Q -w -rr abbreviation-FLL FLL abbreviation-FSS FSS -WW character "'" "'" code '"' '"'
+# iki_read readme.build.txt +Q -w -rr FLL FLL FSS FSS -WW character "'" "'" code '"' '"'
#
# To read the "Build Readme Documentation" section of this file, use this command sequence:
-# fss_basic_list_read readme.build.txt +Q -cn "Build Readme Documentation" | iki_read +Q -w -rr abbreviation-FLL FLL abbreviation-FSS FSS -WW character "'" "'" code '"' '"'
+# fss_basic_list_read readme.build.txt +Q -cn "Build Readme Documentation" | iki_read +Q -w -rr FLL FLL FSS FSS -WW character "'" "'" code '"' '"'
#
Build Readme Documentation:
Build Example, using "make"\:
code:"fake"
- See: The abbreviation-FLL:"Featureless Linux Library" bold:"Featureless Make" project documents for further details on how to use the bold:"Featureless Make" system.
- See: The abbreviation-FLL:"Featureless Linux Library" bold:"Featureless Make" project specifications for how to configure the write abbreviation-FSS:"Featureless Settings Specification" files.
+ See: The FLL:"Featureless Linux Library" bold:"Featureless Make" project documents for further details on how to use the bold:"Featureless Make" system.
+ See: The FLL:"Featureless Linux Library" bold:"Featureless Make" project specifications for how to configure the write FSS:"Featureless Settings Specification" files.
--- /dev/null
+# fss-0002 iki-0000
+#
+# license: cc-by-sa-4.0
+#
+# This file (assumed to be named readme.remove.txt) can be more easily read using the following iki_read commands:
+# iki_read readme.remove.txt +Q -w -r FLL FLL -WW character "'" "'" code '"' '"'
+#
+# To read the "Remove Readme Documentation" section of this file, use this command sequence:
+# fss_basic_list_read readme.remove.txt +Q -cn "Remove Readme Documentation" | iki_read +Q -w -r FLL FLL -WW character "'" "'" code '"' '"'
+#
+
+Remove Readme Documentation:
+ The bold:"remove" is a program for removing files and directories.
+
+ This program is similar to code:"rm", code:"rmdir", and code:"unlink".
+ Compatibility helpers are provided for code:"rm", code:"rmdir", and code:"unlink" programs to closely match functionality.
+ Not everything may be supported but these compatibility helpers should help ease the transition.
+
+ The default behavior is to remove all non-directory files and to fail when a directory is attempted to be removed.
+ When any of the file type parameters are specified, then the default behavior is completely overwritten.
+ Once a single file type parameter is specified, then the removals happen for all specified file type parameters combined.
+
+ The standard code:"FLL-0.6" help options are supported and two of the code:"FLL-0.7" options are brought in (code:"--line_first_no" and code:"--line_last_no").
+ The code:"--line_first_no" parameter suppresses printing the first line that is not data related.
+ The code:"--line_last_no" parameter suppresses printing the last line that is not data related.
+
+ The bold:"remove" program has the following arguments\:
+
+ The code:"--block" (code:"-b") parameter is a file type parameter that restricts removal to block device files.
+ The code:"--character" (code:"-c") parameter is a file type parameter that restricts removal to character device files.
+ The code:"--date" (code:"-D") parameter accepts three additional parameters and restricts removal based on the relationship to some date.
+ The code:"--different" (code:"-O") parameter restricts removal of files whose owner is not the user of the caller of the program.
+ The code:"--directory" (code:"-d") parameter is a file type parameter that restricts removal to directory files.
+ The code:"--empty" (code:"-e") parameter to remove empty directories.
+ The code:"--empty_fail" (code:"-y") parameter to fail on empty directories.
+ The code:"--empty_fail_not" (code:"-Y") parameter to fail on not empty directories.
+ The code:"--empty_not" (code:"-E") parameter to fail on not-empty directories.
+ The code:"--follow" (code:"-F") parameter alters removal to remove the files pointed to by a symbolic link rather than the link itself.
+ The code:"--force" (code:"-f") parameter to never prompt and ignore non-existent files and arguments.
+ The code:"--group" (code:"-g") parameter accepts two additional parameters that restrict removal to the given group identifier.
+ The code:"--isolate" (code:"-i") parameter accepts one additional parameter that restricts removal to a single file system.
+ The code:"--link" (code:"-l") parameter is a file type parameter that restricts removal to a symbolic link file.
+ The code:"--mode" (code:"-m") parameter accepts two additional parameters that restrict removal to the given file mode.
+ The code:"--prompt" (code:"-p") parameter accepts one additional parameter that designates operating in interactive mode and prompts the user for input.
+ The code:"--recurse" (code:"-g") parameter remove directories and their contents recursively.
+ The code:"--regular" (code:"-R") parameter is a file type parameter that restricts removal to regular files (commonly referred to as just bold:"file").
+ The code:"--same" (code:"-s") parameter restricts removal of files whose owner is the user of the caller of the program.
+ The code:"--simulate" (code:"-S") parameter designates that the program operates in simulation mode, never removing anything and instead printing what would have been mode (unless in quiet mode).
+ The code:"--socket" (code:"-k") parameter is a file type parameter that restricts removal to socket files.
+ The code:"--tree" (code:"-t") parameter designates that the specified directory tree is also deleted (may require --force and --recurse if directory tree is not empty).
+ The code:"--user" (code:"-u") parameter accepts two additional parameters that restrict removal to the given group identifier.
+
+ The code:"--date" (code:"-d") parameter's arguments three are (and in this order)\:
+ 1) Either bold:"create" or bold:"modify" to represent file created date or file modified date.
+ 2) One of bold:"<", bold:"<=", bold:"==", bold:">=", and bold:">" to represent the relationship between the date in argument 3.
+ 3) The date (can be in Time format, such as code:"2020:86.4 TT" and code:"2020:86400000000000" (copy the documentation from Featureless Make and/or Controller to describe this)).
# license: cc-by-sa-4.0
#
# This file (assumed to be named readme.build.txt) can be more easily read using the following iki_read commands:
-# iki_read readme.txt +Q -w -rrr abbreviation-API API abbreviation-FLL FLL abbreviation-FSS FSS -WW character "'" "'" code '"' '"'
+# iki_read readme.txt +Q -w -r FLL FLL -WW character "'" "'" code '"' '"'
#
# To read the "Readme Documentation" section of this file, use this command sequence:
-# fss_basic_list_read readme.txt +Q -cn "Readme Documentation" | iki_read +Q -w -rrr abbreviation-API API abbreviation-FLL FLL abbreviation-FSS FSS -WW character "'" "'" code '"' '"'
+# fss_basic_list_read readme.txt +Q -cn "Readme Documentation" | iki_read +Q -w -r FLL FLL -WW character "'" "'" code '"' '"'
#
Readme Documentation:
This should help make the bold:"Turtle Kevux" distribution more ready in regards to the designers and developers future plans.
- A need to improve maintainability of basic toolchain dependencies.
- Using a project already maintained by the same person who builds and writes both the abbreviation-FLL:"Featureless Linux Library" and the bold:"Turtle Kevux" distribution makes this even easier.
+ Using a project already maintained by the same person who builds and writes both the FLL:"Featureless Linux Library" and the bold:"Turtle Kevux" distribution makes this even easier.
Having fewer third-party dependencies to monitor and work with can make development and maintenance a lot easier when those replaced dependencies are simple enough.
- - Provides more exposure to the abbreviation-FLL:"Featureless Linux Library".
+ - Provides more exposure to the FLL:"Featureless Linux Library".
This results in more testing through real-word use.
- Makes the system more familiar.
- The developer behind both the abbreviation-FLL:"Featureless Linux Library" and this project can work better in a more comfortable environment.
+ The developer behind both the FLL:"Featureless Linux Library" and this project can work better in a more comfortable environment.
See: file:"dependencies" for specific dependencies of this project.
See: file:"readme.build.txt" for notes building (compiling) and installing.
+ See: file:"readme.remove.txt" for notes the bold:"remove" program.
--- /dev/null
+# fss-0002 iki-0000
+#
+# license: cc-by-sa-4.0
+#
+# This file (assumed to be named time.txt) can be more easily read using the following iki_read commands:
+# iki_read time.txt +Q -r UTC UTC -w -WW character "'" "'" code '"' '"'
+#
+# To read the "Time Documentation" section of this file, use this command sequence:
+# fss_basic_list_read time.txt +Q -cn "Time Documentation" | iki_read +Q -r UTC UTC -w -WW character "'" "'" code '"' '"'
+#
+
+Time Documentation:
+ This documents a unit of measurement called a bold:"Time", represented with uppercase bold:"T".
+ For comparison, a unit of bold:"Time" is equivalent to a nanosecond, or 10^-9 seconds.
+ A bold:"MegaTime (MT)" is therefore equivalent to a millisecond such that a millisecond is 10^-3 seconds.
+
+ A unit of bold:"Time" is intended to represent some unit of bold:"Time" such that a single 64-bit integer may hold all units of bold:"Time" for a single calendar year.
+ This unit of bold:"Time" does not and must not include bold:"Years" (unlike bold:"Unix time").
+ To convert from bold:"Time" to bold:"Unix time", one must have a year (which could be assumed to be the current year) and then calculate all of those calendar oddities.
+
+ A unit of bold:"Time" by default is assumed to be in UTC:"Coordinated Universal Time".
+ - code:"1 (Earth) year ~= 31536000000000000 Time or 31536000 GT (GigaTime)".
+ - code:"1 (Earth) day = 86400000000000 Time or 86400 GT (GigaTime)".
+ - code:"1 (Earth) hour = 3600000000000 Time or 3600 GT (GigaTime)".
+ - code:"1 (Earth) minute = 60000000000 Time or 60 GT (GigaTime)".
+ - code:"1 (Earth) second = 1000000000 Time or 1 GT (GigaTime)".
+
+ Consequentially, 1 day is easily represented in units of bold:"Time" as code:"86.4 TT (TeraTime)".
+
+ The Time may be stored in its "year string format".
+ In this format, a Year may be prepended to the Time followed by a single colon ':' to associate a year with the Time.
+ This Year has no minimum or maximum but may not have decimals.
+ For example, "2020:86400000000000" would represent: January 02, 2020 0:00 UTC.
+ For example, "2020:86.4 TT" would represent: January 02, 2020 0:00 UTC.
+
+ A second unit of bold:"Time", called bold:"EpochTime", works the same way as bold:"Time" except it represents seconds.
+ This unit is designated code:"ET".
+ The format is similar to bold:"Time", except there are two colons: code:"1970::1620874738" would represent: code:"May 13, 2021 2:58:58 UTC".
+ When the year is not specified, then this is identical to bold:"UNIX Epoch".
+
+ A unit of bold:"EpochTime" by default is assumed to be in UTC:"Coordinated Universal Time".
+ - code:"1 (Earth) year ~= 31536000 EpochTime or 31.536 GE (GigaEpochTime)".
+ - code:"1 (Earth) day = 86400 EpochTime".
+ - code:"1 (Earth) hour = 3600 EpochTime".
+ - code:"1 (Earth) minute = 60 EpochTime".
+ - code:"1 (Earth) second = 1 EpochTime".
+ - code:"1 GT (GigaTime) = 1 EpochTime".
+
+ Consequentially, 1 day is easily represented in units of bold:"EpochTime" as code:"86.4 KE (KiloEpochTime)".
+
+ See the specification file:"time.txt" for more precise technical details.
--- /dev/null
+#include "remove.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_remove_f_a_
+ const f_string_t kt_remove_f_a[] = {
+ "f_console_parameter_prioritize_right",
+ "f_file_mode_from_string",
+ "f_file_mode_to_mode",
+ "f_string_dynamics_increase_by",
+ "f_thread_create",
+ "f_utf_is_digit",
+ "f_uint32s_increase_by",
+ "f_utf_is_whitespace",
+ "fl_conversion_dynamic_partial_to_unsigned_detect",
+ "fll_program_parameter_process_empty",
+ "kt_remove_dates_resize",
+ "kt_remove_modes_resize",
+ "kt_remove_get_id_group",
+ "kt_remove_get_id_user",
+ };
+#endif // _di_kt_remove_f_a_
+
+#ifndef _di_kt_remove_print_reason_s_
+ const f_string_static_t kt_remove_print_reason_no_access_s = macro_f_string_static_t_initialize(KT_REMOVE_print_reason_no_access_s, 0, KT_REMOVE_print_reason_no_access_s_length);
+ const f_string_static_t kt_remove_print_reason_not_found_s = macro_f_string_static_t_initialize(KT_REMOVE_print_reason_not_found_s, 0, KT_REMOVE_print_reason_not_found_s_length);
+ const f_string_static_t kt_remove_print_reason_stat_fail_s = macro_f_string_static_t_initialize(KT_REMOVE_print_reason_stat_fail_s, 0, KT_REMOVE_print_reason_stat_fail_s_length);
+#endif // _di_kt_remove_date_s_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * Kevux Tools - Remove
+ *
+ * Project: Kevux Tools
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides the common data structures.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_remove_common_print_h
+#define _kt_remove_common_print_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * A special array of strings intended for representing funciton names.
+ *
+ * These are primarily used for printing errors with the function names.
+ *
+ * The macro macro_kt_remove_f() is used to reference the array index by the enum name.
+ *
+ * macro_kt_remove_f():
+ * - name: The name of the function.
+ */
+#ifndef _di_kt_remove_f_a_
+ extern const f_string_t kt_remove_f_a[];
+
+ #define macro_kt_remove_f(name) kt_remove_f_a[kt_remove_f_##name##_e]
+#endif // _di_kt_remove_f_a_
+
+/**
+ * An enum representing specific indexes within the above array.
+ *
+ * This is a convenience enum used to make code slightly more readable.
+ */
+#ifndef _di_kt_remove_f_e_
+ enum {
+ kt_remove_f_f_console_parameter_prioritize_right_e,
+ kt_remove_f_f_file_mode_from_string_e,
+ kt_remove_f_f_file_mode_to_mode_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,
+ kt_remove_f_f_utf_is_digit_e,
+ kt_remove_f_f_utf_is_whitespace_e,
+ kt_remove_f_fl_conversion_dynamic_partial_to_unsigned_detect_e,
+ kt_remove_f_fll_program_parameter_process_empty_e,
+ kt_remove_f_kt_remove_dates_resize_e,
+ kt_remove_f_kt_remove_modes_resize_e,
+ kt_remove_f_kt_remove_get_id_group_e,
+ kt_remove_f_kt_remove_get_id_user_e,
+ }; // enum
+#endif // _di_kt_remove_f_e_
+
+/**
+ * Strings used printing the reason why a removal failed.
+ */
+#ifndef _di_kt_remove_print_reason_s_
+ #define KT_REMOVE_print_reason_no_access_s "file be accessed"
+ #define KT_REMOVE_print_reason_not_found_s "file cannot be found"
+ #define KT_REMOVE_print_reason_stat_fail_s "cannot read file statistics"
+
+ #define KT_REMOVE_print_reason_no_access_s_length 16
+ #define KT_REMOVE_print_reason_not_found_s_length 20
+ #define KT_REMOVE_print_reason_stat_fail_s_length 27
+
+ extern const f_string_static_t kt_remove_print_reason_no_access_s;
+ extern const f_string_static_t kt_remove_print_reason_not_found_s;
+ extern const f_string_static_t kt_remove_print_reason_stat_fail_s;
+#endif // _di_kt_remove_print_reason_s_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_remove_common_print_h
--- /dev/null
+#include "remove.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_remove_program_version_s_
+ const f_string_static_t kt_remove_program_version_s = macro_f_string_static_t_initialize(KT_REMOVE_program_version_s, 0, KT_REMOVE_program_version_s_length);
+#endif // _di_kt_remove_program_version_s_
+
+#ifndef _di_kt_remove_program_name_s_
+ const f_string_static_t kt_remove_program_name_s = macro_f_string_static_t_initialize(KT_REMOVE_program_name_s, 0, KT_REMOVE_program_name_s_length);
+ const f_string_static_t kt_remove_program_name_long_s = macro_f_string_static_t_initialize(KT_REMOVE_program_name_long_s, 0, KT_REMOVE_program_name_long_s_length);
+#endif // _di_kt_remove_program_name_s_
+
+#ifndef kt_remove_program_help_parameters_s_
+ const f_string_static_t kt_remove_program_help_parameters_s = macro_f_string_static_t_initialize(KT_REMOVE_program_help_parameters_s, 0, KT_REMOVE_program_help_parameters_s_length);
+#endif // _di_utf8_program_help_parameters_s_
+
+#ifndef _di_kt_remove_date_s_
+ const f_string_static_t kt_remove_date_symbol_equal_s = macro_f_string_static_t_initialize(KT_REMOVE_date_symbol_equal_s, 0, KT_REMOVE_date_symbol_equal_s_length);
+ const f_string_static_t kt_remove_date_symbol_less_s = macro_f_string_static_t_initialize(KT_REMOVE_date_symbol_less_s, 0, KT_REMOVE_date_symbol_less_s_length);
+ const f_string_static_t kt_remove_date_symbol_less_equal_s = macro_f_string_static_t_initialize(KT_REMOVE_date_symbol_less_equal_s, 0, KT_REMOVE_date_symbol_less_equal_s_length);
+ const f_string_static_t kt_remove_date_symbol_more_s = macro_f_string_static_t_initialize(KT_REMOVE_date_symbol_more_s, 0, KT_REMOVE_date_symbol_more_s_length);
+ const f_string_static_t kt_remove_date_symbol_more_equal_s = macro_f_string_static_t_initialize(KT_REMOVE_date_symbol_more_equal_s, 0, KT_REMOVE_date_symbol_more_equal_s_length);
+ const f_string_static_t kt_remove_date_symbol_not_s = macro_f_string_static_t_initialize(KT_REMOVE_date_symbol_not_s, 0, KT_REMOVE_date_symbol_not_s_length);
+
+ const f_string_static_t kt_remove_date_word_equal_s = macro_f_string_static_t_initialize(KT_REMOVE_date_word_equal_s, 0, KT_REMOVE_date_word_equal_s_length);
+ const f_string_static_t kt_remove_date_word_less_s = macro_f_string_static_t_initialize(KT_REMOVE_date_word_less_s, 0, KT_REMOVE_date_word_less_s_length);
+ const f_string_static_t kt_remove_date_word_less_equal_s = macro_f_string_static_t_initialize(KT_REMOVE_date_word_less_equal_s, 0, KT_REMOVE_date_word_less_equal_s_length);
+ const f_string_static_t kt_remove_date_word_more_s = macro_f_string_static_t_initialize(KT_REMOVE_date_word_more_s, 0, KT_REMOVE_date_word_more_s_length);
+ const f_string_static_t kt_remove_date_word_more_equal_s = macro_f_string_static_t_initialize(KT_REMOVE_date_word_more_equal_s, 0, KT_REMOVE_date_word_more_equal_s_length);
+ const f_string_static_t kt_remove_date_word_not_s = macro_f_string_static_t_initialize(KT_REMOVE_date_word_not_s, 0, KT_REMOVE_date_word_not_s_length);
+#endif // _di_kt_remove_date_s_
+
+/**
+ * Strings associated with the mode parameters.
+ */
+#ifndef _di_kt_remove_mode_s_
+ const f_string_static_t kt_remove_mode_symbol_different_s = macro_f_string_static_t_initialize(KT_REMOVE_mode_symbol_different_s, 0, KT_REMOVE_mode_symbol_different_s_length);
+ const f_string_static_t kt_remove_mode_symbol_same_s = macro_f_string_static_t_initialize(KT_REMOVE_mode_symbol_same_s, 0, KT_REMOVE_mode_symbol_same_s_length);
+ const f_string_static_t kt_remove_mode_symbol_similar_s = macro_f_string_static_t_initialize(KT_REMOVE_mode_symbol_similar_s, 0, KT_REMOVE_mode_symbol_similar_s_length);
+ const f_string_static_t kt_remove_mode_symbol_not_s = macro_f_string_static_t_initialize(KT_REMOVE_mode_symbol_not_s, 0, KT_REMOVE_mode_symbol_not_s_length);
+
+ const f_string_static_t kt_remove_mode_word_different_s = macro_f_string_static_t_initialize(KT_REMOVE_mode_word_different_s, 0, KT_REMOVE_mode_word_different_s_length);
+ const f_string_static_t kt_remove_mode_word_same_s = macro_f_string_static_t_initialize(KT_REMOVE_mode_word_same_s, 0, KT_REMOVE_mode_word_same_s_length);
+ const f_string_static_t kt_remove_mode_word_similar_s = macro_f_string_static_t_initialize(KT_REMOVE_mode_word_similar_s, 0, KT_REMOVE_mode_word_similar_s_length);
+ const f_string_static_t kt_remove_mode_word_not_s = macro_f_string_static_t_initialize(KT_REMOVE_mode_word_not_s, 0, KT_REMOVE_mode_word_not_s_length);
+#endif // _di_kt_remove_mode_s_
+
+#ifndef _di_kt_remove_s_
+ const f_string_static_t kt_remove_all_s = macro_f_string_static_t_initialize(KT_REMOVE_all_s, 0, KT_REMOVE_all_s_length);
+ const f_string_static_t kt_remove_follow_s = macro_f_string_static_t_initialize(KT_REMOVE_follow_s, 0, KT_REMOVE_follow_s_length);
+ const f_string_static_t kt_remove_ignore_s = macro_f_string_static_t_initialize(KT_REMOVE_ignore_s, 0, KT_REMOVE_ignore_s_length);
+ const f_string_static_t kt_remove_never_s = macro_f_string_static_t_initialize(KT_REMOVE_never_s, 0, KT_REMOVE_never_s_length);
+ const f_string_static_t kt_remove_no_s = macro_f_string_static_t_initialize(KT_REMOVE_no_s, 0, KT_REMOVE_no_s_length);
+ const f_string_static_t kt_remove_not_s = macro_f_string_static_t_initialize(KT_REMOVE_not_s, 0, KT_REMOVE_not_s_length);
+ const f_string_static_t kt_remove_not_fail_s = macro_f_string_static_t_initialize(KT_REMOVE_not_fail_s, 0, KT_REMOVE_not_fail_s_length);
+ const f_string_static_t kt_remove_now_s = macro_f_string_static_t_initialize(KT_REMOVE_now_s, 0, KT_REMOVE_now_s_length);
+ const f_string_static_t kt_remove_once_s = macro_f_string_static_t_initialize(KT_REMOVE_once_s, 0, KT_REMOVE_once_s_length);
+ const f_string_static_t kt_remove_only_s = macro_f_string_static_t_initialize(KT_REMOVE_only_s, 0, KT_REMOVE_only_s_length);
+ const f_string_static_t kt_remove_only_fail_s = macro_f_string_static_t_initialize(KT_REMOVE_only_fail_s, 0, KT_REMOVE_only_fail_s_length);
+ const f_string_static_t kt_remove_root_s = macro_f_string_static_t_initialize(KT_REMOVE_root_s, 0, KT_REMOVE_root_s_length);
+ const f_string_static_t kt_remove_today_s = macro_f_string_static_t_initialize(KT_REMOVE_today_s, 0, KT_REMOVE_today_s_length);
+ const f_string_static_t kt_remove_tomorrow_s = macro_f_string_static_t_initialize(KT_REMOVE_tomorrow_s, 0, KT_REMOVE_tomorrow_s_length);
+ const f_string_static_t kt_remove_yes_s = macro_f_string_static_t_initialize(KT_REMOVE_yes_s, 0, KT_REMOVE_yes_s_length);
+ const f_string_static_t kt_remove_yesterday_s = macro_f_string_static_t_initialize(KT_REMOVE_yesterday_s, 0, KT_REMOVE_yesterday_s_length);
+#endif // _di_kt_remove_s_
+
+#ifndef _di_kt_remove_parameter_d_
+ const f_string_static_t kt_remove_short_accessed_s = macro_f_string_static_t_initialize(KT_REMOVE_short_accessed_s, 0, KT_REMOVE_short_accessed_s_length);
+ const f_string_static_t kt_remove_short_block_s = macro_f_string_static_t_initialize(KT_REMOVE_short_block_s, 0, KT_REMOVE_short_block_s_length);
+ const f_string_static_t kt_remove_short_character_s = macro_f_string_static_t_initialize(KT_REMOVE_short_character_s, 0, KT_REMOVE_short_character_s_length);
+ const f_string_static_t kt_remove_short_created_s = macro_f_string_static_t_initialize(KT_REMOVE_short_created_s, 0, KT_REMOVE_short_created_s_length);
+ const f_string_static_t kt_remove_short_different_s = macro_f_string_static_t_initialize(KT_REMOVE_short_different_s, 0, KT_REMOVE_short_different_s_length);
+ const f_string_static_t kt_remove_short_directory_s = macro_f_string_static_t_initialize(KT_REMOVE_short_directory_s, 0, KT_REMOVE_short_directory_s_length);
+ const f_string_static_t kt_remove_short_empty_s = macro_f_string_static_t_initialize(KT_REMOVE_short_empty_s, 0, KT_REMOVE_short_empty_s_length);
+ const f_string_static_t kt_remove_short_fifo_s = macro_f_string_static_t_initialize(KT_REMOVE_short_fifo_s, 0, KT_REMOVE_short_fifo_s_length);
+ const f_string_static_t kt_remove_short_follow_s = macro_f_string_static_t_initialize(KT_REMOVE_short_follow_s, 0, KT_REMOVE_short_follow_s_length);
+ const f_string_static_t kt_remove_short_force_s = macro_f_string_static_t_initialize(KT_REMOVE_short_force_s, 0, KT_REMOVE_short_force_s_length);
+ const f_string_static_t kt_remove_short_group_s = macro_f_string_static_t_initialize(KT_REMOVE_short_group_s, 0, KT_REMOVE_short_group_s_length);
+ const f_string_static_t kt_remove_short_isolate_s = macro_f_string_static_t_initialize(KT_REMOVE_short_isolate_s, 0, KT_REMOVE_short_isolate_s_length);
+ const f_string_static_t kt_remove_short_link_s = macro_f_string_static_t_initialize(KT_REMOVE_short_link_s, 0, KT_REMOVE_short_link_s_length);
+ const f_string_static_t kt_remove_short_mode_s = macro_f_string_static_t_initialize(KT_REMOVE_short_mode_s, 0, KT_REMOVE_short_mode_s_length);
+ const f_string_static_t kt_remove_short_prompt_s = macro_f_string_static_t_initialize(KT_REMOVE_short_prompt_s, 0, KT_REMOVE_short_prompt_s_length);
+ const f_string_static_t kt_remove_short_recurse_s = macro_f_string_static_t_initialize(KT_REMOVE_short_recurse_s, 0, KT_REMOVE_short_recurse_s_length);
+ const f_string_static_t kt_remove_short_regular_s = macro_f_string_static_t_initialize(KT_REMOVE_short_regular_s, 0, KT_REMOVE_short_regular_s_length);
+ const f_string_static_t kt_remove_short_same_s = macro_f_string_static_t_initialize(KT_REMOVE_short_same_s, 0, KT_REMOVE_short_same_s_length);
+ const f_string_static_t kt_remove_short_simulate_s = macro_f_string_static_t_initialize(KT_REMOVE_short_simulate_s, 0, KT_REMOVE_short_simulate_s_length);
+ const f_string_static_t kt_remove_short_socket_s = macro_f_string_static_t_initialize(KT_REMOVE_short_socket_s, 0, KT_REMOVE_short_socket_s_length);
+ const f_string_static_t kt_remove_short_stay_s = macro_f_string_static_t_initialize(KT_REMOVE_short_stay_s, 0, KT_REMOVE_short_stay_s_length);
+ const f_string_static_t kt_remove_short_tree_s = macro_f_string_static_t_initialize(KT_REMOVE_short_tree_s, 0, KT_REMOVE_short_tree_s_length);
+ const f_string_static_t kt_remove_short_updated_s = macro_f_string_static_t_initialize(KT_REMOVE_short_updated_s, 0, KT_REMOVE_short_updated_s_length);
+ const f_string_static_t kt_remove_short_user_s = macro_f_string_static_t_initialize(KT_REMOVE_short_user_s, 0, KT_REMOVE_short_user_s_length);
+
+ const f_string_static_t kt_remove_long_accessed_s = macro_f_string_static_t_initialize(KT_REMOVE_long_accessed_s, 0, KT_REMOVE_long_accessed_s_length);
+ const f_string_static_t kt_remove_long_block_s = macro_f_string_static_t_initialize(KT_REMOVE_long_block_s, 0, KT_REMOVE_long_block_s_length);
+ const f_string_static_t kt_remove_long_character_s = macro_f_string_static_t_initialize(KT_REMOVE_long_character_s, 0, KT_REMOVE_long_character_s_length);
+ const f_string_static_t kt_remove_long_created_s = macro_f_string_static_t_initialize(KT_REMOVE_long_created_s, 0, KT_REMOVE_long_created_s_length);
+ const f_string_static_t kt_remove_long_different_s = macro_f_string_static_t_initialize(KT_REMOVE_long_different_s, 0, KT_REMOVE_long_different_s_length);
+ const f_string_static_t kt_remove_long_directory_s = macro_f_string_static_t_initialize(KT_REMOVE_long_directory_s, 0, KT_REMOVE_long_directory_s_length);
+ const f_string_static_t kt_remove_long_empty_s = macro_f_string_static_t_initialize(KT_REMOVE_long_empty_s, 0, KT_REMOVE_long_empty_s_length);
+ const f_string_static_t kt_remove_long_fifo_s = macro_f_string_static_t_initialize(KT_REMOVE_long_fifo_s, 0, KT_REMOVE_long_fifo_s_length);
+ const f_string_static_t kt_remove_long_follow_s = macro_f_string_static_t_initialize(KT_REMOVE_long_follow_s, 0, KT_REMOVE_long_follow_s_length);
+ const f_string_static_t kt_remove_long_force_s = macro_f_string_static_t_initialize(KT_REMOVE_long_force_s, 0, KT_REMOVE_long_force_s_length);
+ const f_string_static_t kt_remove_long_group_s = macro_f_string_static_t_initialize(KT_REMOVE_long_group_s, 0, KT_REMOVE_long_group_s_length);
+ const f_string_static_t kt_remove_long_isolate_s = macro_f_string_static_t_initialize(KT_REMOVE_long_isolate_s, 0, KT_REMOVE_long_isolate_s_length);
+ const f_string_static_t kt_remove_long_link_s = macro_f_string_static_t_initialize(KT_REMOVE_long_link_s, 0, KT_REMOVE_long_link_s_length);
+ const f_string_static_t kt_remove_long_local_s = macro_f_string_static_t_initialize(KT_REMOVE_long_local_s, 0, KT_REMOVE_long_local_s_length);
+ const f_string_static_t kt_remove_long_mode_s = macro_f_string_static_t_initialize(KT_REMOVE_long_mode_s, 0, KT_REMOVE_long_mode_s_length);
+ const f_string_static_t kt_remove_long_prompt_s = macro_f_string_static_t_initialize(KT_REMOVE_long_prompt_s, 0, KT_REMOVE_long_prompt_s_length);
+ const f_string_static_t kt_remove_long_recurse_s = macro_f_string_static_t_initialize(KT_REMOVE_long_recurse_s, 0, KT_REMOVE_long_recurse_s_length);
+ const f_string_static_t kt_remove_long_regular_s = macro_f_string_static_t_initialize(KT_REMOVE_long_regular_s, 0, KT_REMOVE_long_regular_s_length);
+ const f_string_static_t kt_remove_long_same_s = macro_f_string_static_t_initialize(KT_REMOVE_long_same_s, 0, KT_REMOVE_long_same_s_length);
+ const f_string_static_t kt_remove_long_simulate_s = macro_f_string_static_t_initialize(KT_REMOVE_long_simulate_s, 0, KT_REMOVE_long_simulate_s_length);
+ const f_string_static_t kt_remove_long_socket_s = macro_f_string_static_t_initialize(KT_REMOVE_long_socket_s, 0, KT_REMOVE_long_socket_s_length);
+ const f_string_static_t kt_remove_long_stay_s = macro_f_string_static_t_initialize(KT_REMOVE_long_stay_s, 0, KT_REMOVE_long_stay_s_length);
+ const f_string_static_t kt_remove_long_tree_s = macro_f_string_static_t_initialize(KT_REMOVE_long_tree_s, 0, KT_REMOVE_long_tree_s_length);
+ const f_string_static_t kt_remove_long_updated_s = macro_f_string_static_t_initialize(KT_REMOVE_long_updated_s, 0, KT_REMOVE_long_updated_s_length);
+ const f_string_static_t kt_remove_long_user_s = macro_f_string_static_t_initialize(KT_REMOVE_long_user_s, 0, KT_REMOVE_long_user_s_length);
+ const f_string_static_t kt_remove_long_utc_s = macro_f_string_static_t_initialize(KT_REMOVE_long_utc_s, 0, KT_REMOVE_long_utc_s_length);
+#endif // _di_kt_remove_parameter_d_
+
+#ifndef _di_kt_remove_dates_resize_
+ f_status_t kt_remove_dates_resize(const f_array_length_t length, kt_remove_dates_t * const dates) {
+
+ if (!dates) return F_status_set_error(F_parameter);
+
+ if (dates->used + length > F_array_length_t_size_d) return F_status_set_error(F_array_too_large);
+
+ const f_status_t status = f_memory_resize(dates->size, length, sizeof(kt_remove_date_t), (void **) & dates->array);
+ if (F_status_is_error(status)) return status;
+
+ dates->size = length;
+
+ if (dates->used > dates->size) {
+ dates->used = length;
+ }
+
+ return F_none;
+ }
+#endif // _di_kt_remove_dates_resize_
+
+#ifndef _di_kt_remove_modes_resize_
+ f_status_t kt_remove_modes_resize(const f_array_length_t length, kt_remove_modes_t * const modes) {
+
+ if (!modes) return F_status_set_error(F_parameter);
+
+ if (modes->used + length > F_array_length_t_size_d) return F_status_set_error(F_array_too_large);
+
+ const f_status_t status = f_memory_resize(modes->size, length, sizeof(kt_remove_mode_t), (void **) & modes->array);
+ if (F_status_is_error(status)) return status;
+
+ modes->size = length;
+
+ if (modes->used > modes->size) {
+ modes->used = length;
+ }
+
+ return F_none;
+ }
+#endif // _di_kt_remove_modes_resize_
+
+#ifndef _di_kt_remove_setting_delete_
+ f_status_t kt_remove_setting_delete(kt_remove_setting_t * const setting) {
+
+ if (!setting) return F_status_set_error(F_parameter);
+
+ f_string_dynamic_resize(0, &setting->buffer);
+ f_string_dynamics_resize(0, &setting->files);
+
+ kt_remove_dates_resize(0, &setting->accessed);
+ kt_remove_dates_resize(0, &setting->created);
+ kt_remove_dates_resize(0, &setting->updated);
+ kt_remove_modes_resize(0, &setting->modes);
+
+ f_uint32s_resize(0, &setting->groups);
+ f_uint32s_resize(0, &setting->users);
+
+ return F_none;
+ }
+#endif // _di_kt_remove_setting_delete_
+
+#ifndef _di_kt_remove_setting_load_
+ void kt_remove_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, kt_remove_setting_t * const setting) {
+
+ if (!main || !setting) return;
+
+ setting->flag -= setting->flag & kt_remove_flag_option_used_e;
+
+ // Identify priority of color parameters.
+ {
+ f_console_parameter_id_t ids[3] = { kt_remove_parameter_no_color_e, kt_remove_parameter_light_e, kt_remove_parameter_dark_e };
+ const f_console_parameter_ids_t choices = macro_f_console_parameter_ids_t_initialize(ids, 3);
+
+ setting->status = fll_program_parameter_process(arguments, &main->parameters, choices, F_true, &main->context);
+
+ main->output.set = &main->context.set;
+ main->error.set = &main->context.set;
+ main->warning.set = &main->context.set;
+
+ if (main->context.set.error.before) {
+ main->output.context = f_color_set_empty_s;
+ main->output.notable = main->context.set.notable;
+
+ main->error.context = main->context.set.error;
+ main->error.notable = main->context.set.notable;
+
+ main->warning.context = main->context.set.warning;
+ main->warning.notable = main->context.set.notable;
+ }
+ else {
+ f_color_set_t *sets[] = { &main->output.context, &main->output.notable, &main->error.context, &main->error.notable, &main->warning.context, &main->warning.notable, 0 };
+
+ fll_program_parameter_process_empty(&main->context, sets);
+ }
+
+ if (F_status_is_error(setting->status)) {
+ kt_remove_print_error(setting, main->error, macro_kt_remove_f(fll_program_parameter_process_empty));
+
+ return;
+ }
+ }
+
+ // Identify priority of verbosity related parameters.
+ {
+ f_console_parameter_id_t ids[5] = { kt_remove_parameter_verbosity_quiet_e, kt_remove_parameter_verbosity_error_e, kt_remove_parameter_verbosity_normal_e, kt_remove_parameter_verbosity_verbose_e, kt_remove_parameter_verbosity_debug_e };
+ f_console_parameter_id_t choice = 0;
+ const f_console_parameter_ids_t choices = macro_f_console_parameter_ids_t_initialize(ids, 5);
+
+ setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice);
+
+ if (F_status_is_error(setting->status)) {
+ kt_remove_print_error(setting, main->error, macro_kt_remove_f(f_console_parameter_prioritize_right));
+
+ return;
+ }
+
+ if (choice == kt_remove_parameter_verbosity_quiet_e) {
+ main->output.verbosity = f_console_verbosity_quiet_e;
+ main->error.verbosity = f_console_verbosity_quiet_e;
+ main->warning.verbosity = f_console_verbosity_quiet_e;
+ }
+ else if (choice == kt_remove_parameter_verbosity_error_e) {
+ main->output.verbosity = f_console_verbosity_error_e;
+ main->error.verbosity = f_console_verbosity_error_e;
+ main->warning.verbosity = f_console_verbosity_error_e;
+ }
+ else if (choice == kt_remove_parameter_verbosity_normal_e) {
+ main->output.verbosity = f_console_verbosity_normal_e;
+ main->error.verbosity = f_console_verbosity_normal_e;
+ main->warning.verbosity = f_console_verbosity_normal_e;
+ }
+ else if (choice == kt_remove_parameter_verbosity_verbose_e) {
+ main->output.verbosity = f_console_verbosity_verbose_e;
+ main->error.verbosity = f_console_verbosity_verbose_e;
+ main->warning.verbosity = f_console_verbosity_verbose_e;
+ }
+ else if (choice == kt_remove_parameter_verbosity_debug_e) {
+ main->output.verbosity = f_console_verbosity_debug_e;
+ main->error.verbosity = f_console_verbosity_debug_e;
+ main->warning.verbosity = f_console_verbosity_debug_e;
+ }
+ }
+
+ main->output.to.id = F_type_descriptor_output_d;
+ main->output.to.stream = F_type_output_d;
+ main->output.to.flag = F_file_flag_create_d | F_file_flag_write_only_d | F_file_flag_append_d;
+
+ f_array_length_t i = 0;
+ f_array_length_t index = 0;
+ f_array_length_t index2 = 0;
+ f_array_length_t total_locations = 0;
+ f_array_length_t total_arguments = 0;
+
+ uint8_t j = 0;
+
+ if (main->parameters.array[kt_remove_parameter_help_e].result == f_console_result_found_e) {
+ setting->flag |= kt_remove_flag_help_e;
+ }
+
+ if (main->parameters.array[kt_remove_parameter_version_e].result == f_console_result_found_e) {
+ setting->flag |= kt_remove_flag_version_e;
+ }
+
+ if (main->parameters.array[kt_remove_parameter_block_e].result == f_console_result_found_e) {
+ setting->flag |= kt_remove_flag_block_e;
+ setting->flag |= kt_remove_flag_option_used_e;
+ }
+
+ if (main->parameters.array[kt_remove_parameter_character_e].result == f_console_result_found_e) {
+ setting->flag |= kt_remove_flag_character_e;
+ setting->flag |= kt_remove_flag_option_used_e;
+ }
+
+ if (main->parameters.array[kt_remove_parameter_different_e].result == f_console_result_found_e) {
+ if (main->parameters.array[kt_remove_parameter_same_e].result == f_console_result_found_e) {
+ index = main->parameters.array[kt_remove_parameter_different_e].locations.used;
+ index2 = main->parameters.array[kt_remove_parameter_same_e].locations.used;
+
+ if (main->parameters.array[kt_remove_parameter_different_e].locations.array[index] > main->parameters.array[kt_remove_parameter_same_e].locations.array[index2]) {
+ setting->flag |= kt_remove_flag_different_e;
+
+ if (setting->flag & kt_remove_flag_same_e) {
+ setting->flag -= kt_remove_flag_same_e;
+ }
+ }
+ else {
+ setting->flag |= kt_remove_flag_same_e;
+
+ if (setting->flag & kt_remove_flag_different_e) {
+ setting->flag -= kt_remove_flag_different_e;
+ }
+ }
+ }
+ else {
+ setting->flag |= kt_remove_flag_different_e;
+
+ if (setting->flag & kt_remove_flag_same_e) {
+ setting->flag -= kt_remove_flag_same_e;
+ }
+ }
+
+ setting->flag |= kt_remove_flag_option_used_e;
+ }
+ else if (main->parameters.array[kt_remove_parameter_same_e].result == f_console_result_found_e) {
+ setting->flag |= kt_remove_flag_same_e;
+
+ if (setting->flag & kt_remove_flag_different_e) {
+ setting->flag -= kt_remove_flag_different_e;
+ }
+
+ setting->flag |= kt_remove_flag_option_used_e;
+ }
+
+ if (main->parameters.array[kt_remove_parameter_fifo_e].result == f_console_result_found_e) {
+ setting->flag |= kt_remove_flag_fifo_e;
+ setting->flag |= kt_remove_flag_option_used_e;
+ }
+
+ if (main->parameters.array[kt_remove_parameter_follow_e].result == f_console_result_found_e) {
+ if (main->parameters.array[kt_remove_parameter_stay_e].result == f_console_result_found_e) {
+ index = main->parameters.array[kt_remove_parameter_follow_e].locations.used;
+ index2 = main->parameters.array[kt_remove_parameter_stay_e].locations.used;
+
+ if (main->parameters.array[kt_remove_parameter_follow_e].locations.array[index] > main->parameters.array[kt_remove_parameter_stay_e].locations.array[index2]) {
+ setting->flag |= kt_remove_flag_follow_e;
+ }
+ else {
+ if (setting->flag & kt_remove_flag_follow_e) {
+ setting->flag -= kt_remove_flag_follow_e;
+ }
+ }
+ }
+ else {
+ setting->flag |= kt_remove_flag_follow_e;
+ }
+ }
+ else if (main->parameters.array[kt_remove_parameter_stay_e].result == f_console_result_found_e) {
+ if (setting->flag & kt_remove_flag_follow_e) {
+ setting->flag -= kt_remove_flag_follow_e;
+ }
+ }
+
+ if (main->parameters.array[kt_remove_parameter_force_e].result == f_console_result_found_e) {
+ setting->flag |= kt_remove_flag_force_e;
+ }
+
+ if (main->parameters.array[kt_remove_parameter_link_e].result == f_console_result_found_e) {
+ setting->flag |= kt_remove_flag_link_e;
+ setting->flag |= kt_remove_flag_option_used_e;
+ }
+
+ if (main->parameters.array[kt_remove_parameter_recurse_e].result == f_console_result_found_e) {
+ setting->flag |= kt_remove_flag_recurse_e;
+ }
+
+ if (main->parameters.array[kt_remove_parameter_regular_e].result == f_console_result_found_e) {
+ setting->flag |= kt_remove_flag_regular_e;
+ setting->flag |= kt_remove_flag_option_used_e;
+ }
+
+ if (main->parameters.array[kt_remove_parameter_simulate_e].result == f_console_result_found_e) {
+ setting->flag |= kt_remove_flag_simulate_e;
+ }
+
+ if (main->parameters.array[kt_remove_parameter_socket_e].result == f_console_result_found_e) {
+ setting->flag |= kt_remove_flag_socket_e;
+ setting->flag |= kt_remove_flag_option_used_e;
+ }
+
+ if (main->parameters.array[kt_remove_parameter_tree_e].result == f_console_result_found_e) {
+ setting->flag |= kt_remove_flag_tree_e;
+ }
+
+ {
+ f_console_parameter_t * const parameters[] = {
+ &main->parameters.array[kt_remove_parameter_accessed_e],
+ &main->parameters.array[kt_remove_parameter_created_e],
+ &main->parameters.array[kt_remove_parameter_updated_e],
+ };
+
+ kt_remove_dates_t * const dates[] = {
+ &setting->accessed,
+ &setting->created,
+ &setting->updated,
+ };
+
+ const f_string_static_t longs[] = {
+ kt_remove_long_accessed_s,
+ kt_remove_long_created_s,
+ kt_remove_long_updated_s,
+ };
+
+ for (uint8_t p = 0; p < 3; ++p) {
+
+ // kt_remove_parameter_accessed_e, kt_remove_parameter_created_e, kt_remove_parameter_updated_e, needs additional parameters, ==, <, <=, >, >=, <>.
+ if (parameters[p]->result == f_console_result_found_e) {
+ setting->status = F_status_set_error(F_parameter);
+
+ kt_remove_print_error_parameter_missing_value_requires_amount(main->error, f_console_symbol_long_enable_s, longs[p], 2);
+
+ return;
+ }
+
+ if (parameters[p]->result == f_console_result_additional_e) {
+ total_locations = parameters[p]->locations.used;
+ total_arguments = parameters[p]->values.used;
+
+ if (total_locations * 2 != total_arguments) {
+ setting->status = F_status_set_error(F_parameter);
+
+ kt_remove_print_error_parameter_missing_value_requires_amount(main->error, f_console_symbol_long_enable_s, longs[p], 2);
+
+ return;
+ }
+
+ if (dates[p]->used + total_locations > dates[p]->size) {
+ setting->status = kt_remove_dates_resize(dates[p]->size + (total_locations - dates[p]->size), dates[p]);
+
+ if (F_status_is_error(setting->status)) {
+ kt_remove_print_error(setting, main->error, macro_kt_remove_f(kt_remove_dates_resize));
+
+ return;
+ }
+ }
+
+ uint8_t enumerations[] = {
+ kt_remove_flag_date_equal_e,
+ kt_remove_flag_date_less_e,
+ kt_remove_flag_date_less_equal_e,
+ kt_remove_flag_date_more_e,
+ kt_remove_flag_date_more_equal_e,
+ kt_remove_flag_date_not_e,
+ kt_remove_flag_date_equal_e,
+ kt_remove_flag_date_less_e,
+ kt_remove_flag_date_less_equal_e,
+ kt_remove_flag_date_more_e,
+ kt_remove_flag_date_more_equal_e,
+ kt_remove_flag_date_not_e,
+ };
+
+ f_string_static_t strings[] = {
+ kt_remove_date_symbol_equal_s,
+ kt_remove_date_symbol_less_s,
+ kt_remove_date_symbol_less_equal_s,
+ kt_remove_date_symbol_more_s,
+ kt_remove_date_symbol_more_equal_s,
+ kt_remove_date_symbol_not_s,
+ kt_remove_date_word_equal_s,
+ kt_remove_date_word_less_s,
+ kt_remove_date_word_less_equal_s,
+ kt_remove_date_word_more_s,
+ kt_remove_date_word_more_equal_s,
+ kt_remove_date_word_not_s,
+ };
+
+ setting->status = F_known_not;
+
+ {
+ for (i = 0; i < total_arguments; i += 2) {
+
+ index = parameters[p]->values.array[i];
+ dates[p]->array[dates[p]->used].operation = 0;
+ dates[p]->array[dates[p]->used].type = 0;
+
+ for (j = 0; j < 12; ++j) {
+
+ if (fl_string_dynamic_compare(main->parameters.arguments.array[index], strings[j]) == F_equal_to) {
+ dates[p]->array[dates[p]->used].operation = enumerations[j];
+
+ index2 = parameters[p]->values.array[i + 1];
+
+ kt_remove_get_date(main, setting, main->parameters.arguments.array[index2], &dates[p]->array[dates[p]->used].type);
+ if (F_status_is_error(setting->status)) return;
+
+ ++dates[p]->used;
+
+ break;
+ }
+ } // for
+
+ if (j == 12) {
+ setting->status = F_status_set_error(F_parameter);
+
+ kt_remove_print_error_parameter_unknown_value(main->error, f_console_symbol_long_enable_s, longs[p], main->parameters.arguments.array[index]);
+
+ return;
+ }
+ } // for
+ }
+
+ setting->flag |= kt_remove_flag_option_used_e;
+ } // for
+ }
+ }
+
+ // kt_remove_parameter_group_e, needs additional parameters (group).
+ if (main->parameters.array[kt_remove_parameter_empty_e].result == f_console_result_found_e) {
+ setting->status = F_status_set_error(F_parameter);
+
+ kt_remove_print_error_parameter_missing_value_requires_amount(main->error, f_console_symbol_long_enable_s, kt_remove_long_empty_s, 1);
+
+ return;
+ }
+
+ if (main->parameters.array[kt_remove_parameter_empty_e].result == f_console_result_additional_e) {
+ total_arguments = main->parameters.array[kt_remove_parameter_empty_e].values.used;
+
+ if (main->parameters.array[kt_remove_parameter_empty_e].locations.used != total_arguments) {
+ setting->status = F_status_set_error(F_parameter);
+
+ kt_remove_print_error_parameter_missing_value_requires_amount(main->error, f_console_symbol_long_enable_s, kt_remove_long_empty_s, 1);
+
+ return;
+ }
+
+ index = main->parameters.array[kt_remove_parameter_empty_e].values.array[total_arguments - 1];
+
+ if (fl_string_dynamic_compare(kt_remove_not_s, main->parameters.arguments.array[index]) == F_equal_to) {
+ setting->flag |= kt_remove_flag_empty_not_e;
+
+ if (setting->flag & kt_remove_flag_empty_not_fail_e) {
+ setting->flag -= kt_remove_flag_empty_not_fail_e;
+ }
+
+ if (setting->flag & kt_remove_flag_empty_only_e) {
+ setting->flag -= kt_remove_flag_empty_only_e;
+ }
+
+ if (setting->flag & kt_remove_flag_empty_only_fail_e) {
+ setting->flag -= kt_remove_flag_empty_only_fail_e;
+ }
+ }
+ else if (fl_string_dynamic_compare(kt_remove_not_fail_s, main->parameters.arguments.array[index]) == F_equal_to) {
+ setting->flag |= kt_remove_flag_empty_not_fail_e;
+
+ if (setting->flag & kt_remove_flag_empty_not_e) {
+ setting->flag -= kt_remove_flag_empty_not_e;
+ }
+
+ if (setting->flag & kt_remove_flag_empty_only_e) {
+ setting->flag -= kt_remove_flag_empty_only_e;
+ }
+
+ if (setting->flag & kt_remove_flag_empty_only_fail_e) {
+ setting->flag -= kt_remove_flag_empty_only_fail_e;
+ }
+ }
+ else if (fl_string_dynamic_compare(kt_remove_only_s, main->parameters.arguments.array[index]) == F_equal_to) {
+ setting->flag |= kt_remove_flag_empty_only_e;
+
+ if (setting->flag & kt_remove_flag_empty_not_e) {
+ setting->flag -= kt_remove_flag_empty_not_e;
+ }
+
+ if (setting->flag & kt_remove_flag_empty_not_fail_e) {
+ setting->flag -= kt_remove_flag_empty_not_fail_e;
+ }
+
+ if (setting->flag & kt_remove_flag_empty_only_fail_e) {
+ setting->flag -= kt_remove_flag_empty_only_fail_e;
+ }
+ }
+ else if (fl_string_dynamic_compare(kt_remove_only_fail_s, main->parameters.arguments.array[index]) == F_equal_to) {
+ setting->flag |= kt_remove_flag_empty_only_fail_e;
+
+ if (setting->flag & kt_remove_flag_empty_not_e) {
+ setting->flag -= kt_remove_flag_empty_not_e;
+ }
+
+ if (setting->flag & kt_remove_flag_empty_not_fail_e) {
+ setting->flag -= kt_remove_flag_empty_not_fail_e;
+ }
+
+ if (setting->flag & kt_remove_flag_empty_only_e) {
+ setting->flag -= kt_remove_flag_empty_only_e;
+ }
+ }
+ else {
+ setting->status = F_status_set_error(F_parameter);
+
+ kt_remove_print_error_parameter_unknown_value(main->error, f_console_symbol_long_enable_s, kt_remove_long_empty_s, main->parameters.arguments.array[index]);
+
+ return;
+ }
+
+ setting->flag |= kt_remove_flag_option_used_e;
+ }
+
+ // kt_remove_parameter_group_e, needs additional parameters (gid).
+ if (main->parameters.array[kt_remove_parameter_group_e].result == f_console_result_found_e) {
+ setting->status = F_status_set_error(F_parameter);
+
+ kt_remove_print_error_parameter_missing_value_requires_amount(main->error, f_console_symbol_long_enable_s, kt_remove_long_group_s, 1);
+
+ return;
+ }
+
+ if (main->parameters.array[kt_remove_parameter_group_e].result == f_console_result_additional_e) {
+ total_arguments = main->parameters.array[kt_remove_parameter_group_e].values.used;
+
+ if (main->parameters.array[kt_remove_parameter_group_e].locations.used != total_arguments) {
+ setting->status = F_status_set_error(F_parameter);
+
+ kt_remove_print_error_parameter_missing_value_requires_amount(main->error, f_console_symbol_long_enable_s, kt_remove_long_group_s, 1);
+
+ return;
+ }
+
+ setting->status = f_uint32s_increase_by(total_arguments, &setting->groups);
+
+ if (F_status_is_error(setting->status)) {
+ kt_remove_print_error(setting, main->error, macro_kt_remove_f(f_uint32s_increase_by));
+
+ return;
+ }
+
+ for (i = 0; i < total_arguments; ++i) {
+
+ index = main->parameters.array[kt_remove_parameter_group_e].values.array[i];
+
+ setting->groups.array[setting->groups.used] = kt_remove_get_id_group(setting, main->parameters.arguments.array[index]);
+
+ if (F_status_is_error(setting->status)) {
+ kt_remove_print_error(setting, main->error, macro_kt_remove_f(kt_remove_get_id_group));
+
+ return;
+ }
+
+ ++setting->groups.used;
+ } // for
+
+ setting->flag |= kt_remove_flag_group_e;
+ setting->flag |= kt_remove_flag_option_used_e;
+ }
+
+ // kt_remove_parameter_isolate_e, needs additional parameters (all, ignore, or root).
+ if (main->parameters.array[kt_remove_parameter_isolate_e].result == f_console_result_found_e) {
+ setting->status = F_status_set_error(F_parameter);
+
+ kt_remove_print_error_parameter_missing_value_requires_amount(main->error, f_console_symbol_long_enable_s, kt_remove_long_isolate_s, 1);
+
+ return;
+ }
+
+ if (main->parameters.array[kt_remove_parameter_isolate_e].result == f_console_result_additional_e) {
+ total_arguments = main->parameters.array[kt_remove_parameter_isolate_e].values.used;
+
+ if (main->parameters.array[kt_remove_parameter_isolate_e].locations.used != total_arguments) {
+ setting->status = F_status_set_error(F_parameter);
+
+ kt_remove_print_error_parameter_missing_value_requires_amount(main->error, f_console_symbol_long_enable_s, kt_remove_long_isolate_s, 1);
+
+ return;
+ }
+
+ index = main->parameters.array[kt_remove_parameter_isolate_e].values.array[total_arguments - 1];
+
+ if (fl_string_dynamic_compare(kt_remove_all_s, main->parameters.arguments.array[index]) == F_equal_to) {
+ setting->flag |= kt_remove_flag_isolate_all_e;
+
+ if (setting->flag & kt_remove_flag_isolate_ignore_e) {
+ setting->flag -= kt_remove_flag_isolate_ignore_e;
+ }
+
+ if (setting->flag & kt_remove_flag_isolate_root_e) {
+ setting->flag -= kt_remove_flag_isolate_root_e;
+ }
+ }
+ else if (fl_string_dynamic_compare(kt_remove_ignore_s, main->parameters.arguments.array[index]) == F_equal_to) {
+ setting->flag |= kt_remove_flag_isolate_ignore_e;
+
+ if (setting->flag & kt_remove_flag_isolate_all_e) {
+ setting->flag -= kt_remove_flag_isolate_all_e;
+ }
+
+ if (setting->flag & kt_remove_flag_isolate_root_e) {
+ setting->flag -= kt_remove_flag_isolate_root_e;
+ }
+ }
+ else if (fl_string_dynamic_compare(kt_remove_root_s, main->parameters.arguments.array[index]) == F_equal_to) {
+ setting->flag |= kt_remove_flag_isolate_root_e;
+
+ if (setting->flag & kt_remove_flag_isolate_all_e) {
+ setting->flag -= kt_remove_flag_isolate_all_e;
+ }
+
+ if (setting->flag & kt_remove_flag_isolate_ignore_e) {
+ setting->flag -= kt_remove_flag_isolate_ignore_e;
+ }
+ }
+ else {
+ setting->status = F_status_set_error(F_parameter);
+
+ kt_remove_print_error_parameter_unknown_value(main->error, f_console_symbol_long_enable_s, kt_remove_long_isolate_s, main->parameters.arguments.array[index]);
+
+ return;
+ }
+ }
+
+ // kt_remove_parameter_mode_e, needs additional parameters (modes, match parameters).
+ if (main->parameters.array[kt_remove_parameter_mode_e].result == f_console_result_found_e) {
+ setting->status = F_status_set_error(F_parameter);
+
+ kt_remove_print_error_parameter_missing_value_requires_amount(main->error, f_console_symbol_long_enable_s, kt_remove_long_mode_s, 2);
+
+ return;
+ }
+
+ if (main->parameters.array[kt_remove_parameter_mode_e].result == f_console_result_additional_e) {
+ total_locations = main->parameters.array[kt_remove_parameter_mode_e].locations.used;
+ total_arguments = main->parameters.array[kt_remove_parameter_mode_e].values.used;
+
+ if (total_locations * 2 != total_arguments) {
+ setting->status = F_status_set_error(F_parameter);
+
+ kt_remove_print_error_parameter_missing_value_requires_amount(main->error, f_console_symbol_long_enable_s, kt_remove_long_mode_s, 2);
+
+ return;
+ }
+
+ if (setting->modes.used + total_locations > setting->modes.size) {
+ setting->status = kt_remove_modes_resize(setting->modes.size + (total_locations - setting->modes.size), &setting->modes);
+
+ if (F_status_is_error(setting->status)) {
+ kt_remove_print_error(setting, main->error, macro_kt_remove_f(kt_remove_modes_resize));
+
+ return;
+ }
+ }
+
+ uint8_t enumerations[] = {
+ kt_remove_flag_mode_different_e,
+ kt_remove_flag_mode_same_e,
+ kt_remove_flag_mode_similar_e,
+ kt_remove_flag_mode_not_e,
+ kt_remove_flag_mode_different_e,
+ kt_remove_flag_mode_same_e,
+ kt_remove_flag_mode_similar_e,
+ kt_remove_flag_mode_not_e,
+ };
+
+ f_string_static_t strings[] = {
+ kt_remove_mode_symbol_different_s,
+ kt_remove_mode_symbol_same_s,
+ kt_remove_mode_symbol_similar_s,
+ kt_remove_mode_symbol_not_s,
+ kt_remove_mode_word_different_s,
+ kt_remove_mode_word_same_s,
+ kt_remove_mode_word_similar_s,
+ kt_remove_mode_word_not_s,
+ };
+
+ for (i = 0; i < total_locations; i += 2) {
+
+ index = main->parameters.array[kt_remove_parameter_mode_e].values.array[i];
+
+ setting->modes.array[setting->modes.used].type = 0;
+
+ for (j = 0; j < 8; ++j) {
+
+ if (fl_string_dynamic_compare(main->parameters.arguments.array[index], strings[j]) == F_equal_to) {
+ setting->modes.array[setting->modes.used].type = enumerations[j];
+
+ index2 = main->parameters.array[kt_remove_parameter_mode_e].values.array[i + 1];
+
+ setting->modes.array[setting->modes.used].mode = kt_remove_get_mode(main, setting, main->parameters.arguments.array[index2]);
+ if (F_status_is_error(setting->status)) return;
+
+ ++setting->modes.used;
+
+ break;
+ }
+ } // for
+
+ if (j == 8) {
+ setting->status = F_status_set_error(F_parameter);
+
+ kt_remove_print_error_parameter_unknown_value(main->error, f_console_symbol_long_enable_s, kt_remove_long_mode_s, main->parameters.arguments.array[index]);
+
+ return;
+ }
+ } // for
+
+ setting->flag |= kt_remove_flag_mode_e;
+ setting->flag |= kt_remove_flag_option_used_e;
+ }
+
+ // kt_remove_parameter_user_e, needs additional parameters.
+ if (main->parameters.array[kt_remove_parameter_user_e].result == f_console_result_found_e) {
+ setting->status = F_status_set_error(F_parameter);
+
+ kt_remove_print_error_parameter_missing_value_requires_amount(main->error, f_console_symbol_long_enable_s, kt_remove_long_user_s, 1);
+
+ return;
+ }
+
+ if (main->parameters.array[kt_remove_parameter_user_e].result == f_console_result_additional_e) {
+ total_arguments = main->parameters.array[kt_remove_parameter_user_e].values.used;
+
+ if (main->parameters.array[kt_remove_parameter_user_e].locations.used != total_arguments) {
+ setting->status = F_status_set_error(F_parameter);
+
+ kt_remove_print_error_parameter_missing_value_requires_amount(main->error, f_console_symbol_long_enable_s, kt_remove_long_user_s, 1);
+
+ return;
+ }
+
+ setting->status = f_uint32s_increase_by(total_arguments, &setting->users);
+
+ if (F_status_is_error(setting->status)) {
+ kt_remove_print_error(setting, main->error, macro_kt_remove_f(f_uint32s_increase_by));
+
+ return;
+ }
+
+ for (i = 0; i < total_arguments; ++i) {
+
+ index = main->parameters.array[kt_remove_parameter_user_e].values.array[i];
+
+ setting->users.array[setting->users.used] = kt_remove_get_id_user(setting, main->parameters.arguments.array[index]);
+
+ if (F_status_is_error(setting->status)) {
+ kt_remove_print_error(setting, main->error, macro_kt_remove_f(kt_remove_get_id_user));
+
+ return;
+ }
+
+ ++setting->users.used;
+ } // for
+
+ setting->flag |= kt_remove_flag_user_e;
+ setting->flag |= kt_remove_flag_option_used_e;
+ }
+
+ // kt_remove_parameter_prompt_e, needs additional parameters (all, follow, once).
+ if (main->parameters.array[kt_remove_parameter_prompt_e].result == f_console_result_found_e) {
+ setting->status = F_status_set_error(F_parameter);
+
+ kt_remove_print_error_parameter_missing_value_requires_amount(main->error, f_console_symbol_long_enable_s, kt_remove_long_prompt_s, 1);
+
+ return;
+ }
+
+ if (main->parameters.array[kt_remove_parameter_prompt_e].result == f_console_result_additional_e) {
+ total_arguments = main->parameters.array[kt_remove_parameter_prompt_e].values.used;
+
+ if (main->parameters.array[kt_remove_parameter_prompt_e].locations.used != total_arguments) {
+ setting->status = F_status_set_error(F_parameter);
+
+ kt_remove_print_error_parameter_missing_value_requires_amount(main->error, f_console_symbol_long_enable_s, kt_remove_long_prompt_s, 1);
+
+ return;
+ }
+
+ index = main->parameters.array[kt_remove_parameter_prompt_e].values.array[total_arguments - 1];
+
+ if (fl_string_dynamic_compare(kt_remove_all_s, main->parameters.arguments.array[index]) == F_equal_to) {
+ setting->flag |= kt_remove_flag_prompt_all_e;
+
+ if (setting->flag & kt_remove_flag_prompt_follow_e) {
+ setting->flag -= kt_remove_flag_prompt_follow_e;
+ }
+
+ if (setting->flag & kt_remove_flag_prompt_once_e) {
+ setting->flag -= kt_remove_flag_prompt_once_e;
+ }
+
+ if (setting->flag & kt_remove_flag_prompt_never_e) {
+ setting->flag -= kt_remove_flag_prompt_never_e;
+ }
+ }
+ else if (fl_string_dynamic_compare(kt_remove_follow_s, main->parameters.arguments.array[index]) == F_equal_to) {
+ setting->flag |= kt_remove_flag_prompt_follow_e;
+
+ if (setting->flag & kt_remove_flag_prompt_all_e) {
+ setting->flag -= kt_remove_flag_prompt_all_e;
+ }
+
+ if (setting->flag & kt_remove_flag_prompt_once_e) {
+ setting->flag -= kt_remove_flag_prompt_once_e;
+ }
+
+ if (setting->flag & kt_remove_flag_prompt_never_e) {
+ setting->flag -= kt_remove_flag_prompt_never_e;
+ }
+ }
+ else if (fl_string_dynamic_compare(kt_remove_once_s, main->parameters.arguments.array[index]) == F_equal_to) {
+ setting->flag |= kt_remove_flag_prompt_once_e;
+
+ if (setting->flag & kt_remove_flag_prompt_all_e) {
+ setting->flag -= kt_remove_flag_prompt_all_e;
+ }
+
+ if (setting->flag & kt_remove_flag_prompt_follow_e) {
+ setting->flag -= kt_remove_flag_prompt_follow_e;
+ }
+
+ if (setting->flag & kt_remove_flag_prompt_never_e) {
+ setting->flag -= kt_remove_flag_prompt_never_e;
+ }
+ }
+ else if (fl_string_dynamic_compare(kt_remove_never_s, main->parameters.arguments.array[index]) == F_equal_to) {
+ setting->flag |= kt_remove_flag_prompt_never_e;
+
+ if (setting->flag & kt_remove_flag_prompt_all_e) {
+ setting->flag -= kt_remove_flag_prompt_all_e;
+ }
+
+ if (setting->flag & kt_remove_flag_prompt_follow_e) {
+ setting->flag -= kt_remove_flag_prompt_follow_e;
+ }
+
+ if (setting->flag & kt_remove_flag_prompt_once_e) {
+ setting->flag -= kt_remove_flag_prompt_once_e;
+ }
+ }
+ else {
+ setting->status = F_status_set_error(F_parameter);
+
+ kt_remove_print_error_parameter_unknown_value(main->error, f_console_symbol_long_enable_s, kt_remove_long_prompt_s, main->parameters.arguments.array[index]);
+
+ return;
+ }
+ }
+
+ if (main->parameters.array[kt_remove_parameter_utc_e].result == f_console_result_found_e) {
+
+ // Use the right most parameter when both --utc and --local are passed.
+ if (main->parameters.array[kt_remove_parameter_local_e].result == f_console_result_found_e) {
+ const f_array_length_t last_local = main->parameters.array[kt_remove_parameter_local_e].locations.array[main->parameters.array[kt_remove_parameter_local_e].locations.used];
+ const f_array_length_t last_utc = main->parameters.array[kt_remove_parameter_utc_e].locations.array[main->parameters.array[kt_remove_parameter_utc_e].locations.used];
+
+ if (last_local > kt_remove_parameter_utc_e) {
+ if (setting->flag & kt_remove_flag_utc_e) {
+ setting->flag -= kt_remove_flag_utc_e;
+ }
+ }
+ else {
+ setting->flag |= kt_remove_flag_utc_e;
+ }
+ }
+ else {
+ setting->flag |= kt_remove_flag_utc_e;
+ }
+ }
+ else if (main->parameters.array[kt_remove_parameter_local_e].result == f_console_result_found_e) {
+ if (setting->flag & kt_remove_flag_utc_e) {
+ setting->flag -= kt_remove_flag_utc_e;
+ }
+ }
+
+ // Load all remaining files as static strings (setting size to 0).
+ if (main->parameters.remaining.used) {
+ setting->status = f_string_dynamics_increase_by(main->parameters.remaining.used, &setting->files);
+
+ if (F_status_is_error(setting->status)) {
+ kt_remove_print_error(setting, main->error, macro_kt_remove_f(f_string_dynamics_increase_by));
+
+ return;
+ }
+
+ for (i = 0; i < main->parameters.remaining.used; ++i) {
+
+ index = main->parameters.remaining.array[i];
+
+ setting->files.array[setting->files.used].string = main->parameters.arguments.array[index].string;
+ setting->files.array[setting->files.used].used = main->parameters.arguments.array[index].used;
+ setting->files.array[setting->files.used++].size = 0;
+ } // for
+ }
+ }
+#endif // _di_kt_remove_setting_load_
+
+#ifndef _di_kt_remove_setting_unload_
+ f_status_t kt_remove_setting_unload(fll_program_data_t * const main, kt_remove_setting_t * const setting) {
+
+ if (!main || !setting) return F_status_set_error(F_parameter);
+
+ kt_remove_setting_delete(setting);
+
+ return F_none;
+ }
+#endif // _di_kt_remove_setting_unload_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * Kevux Tools - Remove
+ *
+ * Project: Kevux Tools
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides the common data structures.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _kt_remove_common_h
+#define _kt_remove_common_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The program version.
+ */
+#ifndef _di_kt_remove_program_version_s_
+ #define KT_REMOVE_program_version_major_s F_string_ascii_0_s
+ #define KT_REMOVE_program_version_minor_s F_string_ascii_5_s
+ #define KT_REMOVE_program_version_micro_s F_string_ascii_0_s
+
+ #define KT_REMOVE_program_version_major_s_length F_string_ascii_0_s_length
+ #define KT_REMOVE_program_version_minor_s_length F_string_ascii_5_s_length
+ #define KT_REMOVE_program_version_micro_s_length F_string_ascii_0_s_length
+
+ #if !(defined(KT_REMOVE_program_version_nano_prefix_s) && defined(KT_REMOVE_program_version_nano_prefix_s_length))
+ #define KT_REMOVE_program_version_nano_prefix_s
+ #define KT_REMOVE_program_version_nano_prefix_s_length 0
+ #endif // !(defined(KT_REMOVE_program_version_nano_prefix_s) && defined(KT_REMOVE_program_version_nano_prefix_s_length))
+
+ #if !(defined(KT_REMOVE_program_version_nano_s) && defined(KT_REMOVE_program_version_nano_s_length))
+ #define KT_REMOVE_program_version_nano_s
+ #define KT_REMOVE_program_version_nano_s_length 0
+ #endif // !(defined(KT_REMOVE_program_version_nano_s) && defined(KT_REMOVE_program_version_nano_s_length))
+
+ #define KT_REMOVE_program_version_s KT_REMOVE_program_version_major_s F_string_ascii_period_s KT_REMOVE_program_version_minor_s F_string_ascii_period_s KT_REMOVE_program_version_micro_s KT_REMOVE_program_version_nano_prefix_s KT_REMOVE_program_version_nano_s
+
+ #define KT_REMOVE_program_version_s_length KT_REMOVE_program_version_major_s_length + F_string_ascii_period_s_length + KT_REMOVE_program_version_minor_s_length + F_string_ascii_period_s_length + KT_REMOVE_program_version_micro_s_length + KT_REMOVE_program_version_nano_prefix_s_length + KT_REMOVE_program_version_nano_s_length
+
+ extern const f_string_static_t kt_remove_program_version_s;
+#endif // _di_kt_remove_program_version_s_
+
+/**
+ * The program name.
+ */
+#ifndef _di_kt_remove_program_name_s_
+ #define KT_REMOVE_program_name_s "remove"
+ #define KT_REMOVE_program_name_long_s "Remove"
+
+ #define KT_REMOVE_program_name_s_length 6
+ #define KT_REMOVE_program_name_long_s_length 6
+
+ extern const f_string_static_t kt_remove_program_name_s;
+ extern const f_string_static_t kt_remove_program_name_long_s;
+#endif // _di_kt_remove_program_name_s_
+
+/**
+ * The program help related data.
+ */
+#ifndef kt_remove_program_help_parameters_s_
+ #define KT_REMOVE_program_help_parameters_s "file(s)"
+ #define KT_REMOVE_program_help_parameters_s_length 7
+
+ extern const f_string_static_t kt_remove_program_help_parameters_s;
+#endif // _di_utf8_program_help_parameters_s_
+
+/**
+ * The program default defines.
+ *
+ * kt_remove_default_allocation_*:
+ * - large: An allocation step used for buffers that are anticipated to have large buffers.
+ * - small: An allocation step used for buffers that are anticipated to have small buffers.
+ */
+#ifndef _di_kt_remove_default_d_
+ #define kt_remove_default_allocation_large_d 2048
+ #define kt_remove_default_allocation_small_d 128
+#endif // _di_kt_remove_default_d_
+
+/**
+ * The program defines.
+ *
+ * Leap Year:
+ * - If can be evenly divided by 4, then this is a leap year.
+ *
+ * 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:
+ * - day: Number of seconds in a day.
+ * - hour: Number of seconds in a hour.
+ * - minute: Number of seconds in a minute.
+ * - nanosecond: Number of seconds in a nanosecond.
+ * - week: Number of seconds in a week.
+ * - year: Number of seconds in a year (does not include leap years).
+ *
+ * kt_remove_time_year_*_d:
+ * - unix_epoch: The year in which the UNIX Epoch starts.
+ */
+#ifndef _di_kt_remove_d_
+ #define kt_remove_signal_check_d 20000
+ #define kt_remove_signal_check_failsafe_d 20000
+
+ #define kt_remove_time_seconds_in_day_d 86400
+ #define kt_remove_time_seconds_in_hour_d 3600
+ #define kt_remove_time_seconds_in_minute_d 60
+ #define kt_remove_time_seconds_in_nanosecond_d 1000000000
+ #define kt_remove_time_seconds_in_week_d 604800
+ #define kt_remove_time_seconds_in_year_d 31536000
+
+ #define kt_remove_time_year_unix_epoch_d 1970
+#endif // _di_kt_remove_d_
+
+/**
+ * Strings associated with the date parameters.
+ */
+#ifndef _di_kt_remove_date_s_
+ #define KT_REMOVE_date_symbol_equal_s "=="
+ #define KT_REMOVE_date_symbol_less_s "<"
+ #define KT_REMOVE_date_symbol_less_equal_s "<="
+ #define KT_REMOVE_date_symbol_more_s ">"
+ #define KT_REMOVE_date_symbol_more_equal_s ">="
+ #define KT_REMOVE_date_symbol_not_s "<>"
+
+ #define KT_REMOVE_date_symbol_equal_s_length 2
+ #define KT_REMOVE_date_symbol_less_s_length 1
+ #define KT_REMOVE_date_symbol_less_equal_s_length 2
+ #define KT_REMOVE_date_symbol_more_s_length 1
+ #define KT_REMOVE_date_symbol_more_equal_s_length 2
+ #define KT_REMOVE_date_symbol_not_s_length 2
+
+ extern const f_string_static_t kt_remove_date_symbol_equal_s;
+ extern const f_string_static_t kt_remove_date_symbol_less_s;
+ extern const f_string_static_t kt_remove_date_symbol_less_equal_s;
+ extern const f_string_static_t kt_remove_date_symbol_more_s;
+ extern const f_string_static_t kt_remove_date_symbol_more_equal_s;
+ extern const f_string_static_t kt_remove_date_symbol_not_s;
+
+ #define KT_REMOVE_date_word_equal_s "equal"
+ #define KT_REMOVE_date_word_less_s "less"
+ #define KT_REMOVE_date_word_less_equal_s "less_equal"
+ #define KT_REMOVE_date_word_more_s "more"
+ #define KT_REMOVE_date_word_more_equal_s "more_equal"
+ #define KT_REMOVE_date_word_not_s "not"
+
+ #define KT_REMOVE_date_word_equal_s_length 5
+ #define KT_REMOVE_date_word_less_s_length 4
+ #define KT_REMOVE_date_word_less_equal_s_length 10
+ #define KT_REMOVE_date_word_more_s_length 4
+ #define KT_REMOVE_date_word_more_equal_s_length 10
+ #define KT_REMOVE_date_word_not_s_length 3
+
+ extern const f_string_static_t kt_remove_date_word_equal_s;
+ extern const f_string_static_t kt_remove_date_word_less_s;
+ extern const f_string_static_t kt_remove_date_word_less_equal_s;
+ extern const f_string_static_t kt_remove_date_word_more_s;
+ extern const f_string_static_t kt_remove_date_word_more_equal_s;
+ extern const f_string_static_t kt_remove_date_word_not_s;
+#endif // _di_kt_remove_date_s_
+
+/**
+ * Strings associated with the mode parameters.
+ */
+#ifndef _di_kt_remove_mode_s_
+ #define KT_REMOVE_mode_symbol_different_s "~~"
+ #define KT_REMOVE_mode_symbol_same_s "=="
+ #define KT_REMOVE_mode_symbol_similar_s "~="
+ #define KT_REMOVE_mode_symbol_not_s "<>"
+
+ #define KT_REMOVE_mode_symbol_different_s_length 2
+ #define KT_REMOVE_mode_symbol_same_s_length 2
+ #define KT_REMOVE_mode_symbol_similar_s_length 2
+ #define KT_REMOVE_mode_symbol_not_s_length 2
+
+ extern const f_string_static_t kt_remove_mode_symbol_different_s;
+ extern const f_string_static_t kt_remove_mode_symbol_same_s;
+ extern const f_string_static_t kt_remove_mode_symbol_similar_s;
+ extern const f_string_static_t kt_remove_mode_symbol_not_s;
+
+ #define KT_REMOVE_mode_word_different_s "different"
+ #define KT_REMOVE_mode_word_same_s "same"
+ #define KT_REMOVE_mode_word_similar_s "similar"
+ #define KT_REMOVE_mode_word_not_s "not"
+
+ #define KT_REMOVE_mode_word_different_s_length 9
+ #define KT_REMOVE_mode_word_same_s_length 4
+ #define KT_REMOVE_mode_word_similar_s_length 7
+ #define KT_REMOVE_mode_word_not_s_length 3
+
+ extern const f_string_static_t kt_remove_mode_word_different_s;
+ extern const f_string_static_t kt_remove_mode_word_same_s;
+ extern const f_string_static_t kt_remove_mode_word_similar_s;
+ extern const f_string_static_t kt_remove_mode_word_not_s;
+#endif // _di_kt_remove_mode_s_
+
+/**
+ * Additional strings used for various purposes.
+ */
+#ifndef _di_kt_remove_s_
+ #define KT_REMOVE_all_s "all"
+ #define KT_REMOVE_follow_s "follow"
+ #define KT_REMOVE_ignore_s "ignore"
+ #define KT_REMOVE_never_s "never"
+ #define KT_REMOVE_no_s "no"
+ #define KT_REMOVE_not_s "not"
+ #define KT_REMOVE_not_fail_s "not_fail"
+ #define KT_REMOVE_now_s "now"
+ #define KT_REMOVE_once_s "once"
+ #define KT_REMOVE_only_s "only"
+ #define KT_REMOVE_only_fail_s "only_fail"
+ #define KT_REMOVE_root_s "root"
+ #define KT_REMOVE_today_s "today"
+ #define KT_REMOVE_tomorrow_s "tomorrow"
+ #define KT_REMOVE_yes_s "yes"
+ #define KT_REMOVE_yesterday_s "yesterday"
+
+ #define KT_REMOVE_all_s_length 3
+ #define KT_REMOVE_follow_s_length 6
+ #define KT_REMOVE_ignore_s_length 6
+ #define KT_REMOVE_never_s_length 5
+ #define KT_REMOVE_no_s_length 2
+ #define KT_REMOVE_not_s_length 3
+ #define KT_REMOVE_not_fail_s_length 8
+ #define KT_REMOVE_now_s_length 3
+ #define KT_REMOVE_once_s_length 4
+ #define KT_REMOVE_only_s_length 4
+ #define KT_REMOVE_only_fail_s_length 9
+ #define KT_REMOVE_root_s_length 4
+ #define KT_REMOVE_today_s_length 5
+ #define KT_REMOVE_tomorrow_s_length 8
+ #define KT_REMOVE_yes_s_length 3
+ #define KT_REMOVE_yesterday_s_length 9
+
+ extern const f_string_static_t kt_remove_all_s;
+ extern const f_string_static_t kt_remove_follow_s;
+ extern const f_string_static_t kt_remove_ignore_s;
+ extern const f_string_static_t kt_remove_never_s;
+ extern const f_string_static_t kt_remove_no_s;
+ extern const f_string_static_t kt_remove_not_s;
+ extern const f_string_static_t kt_remove_not_fail_s;
+ extern const f_string_static_t kt_remove_now_s;
+ extern const f_string_static_t kt_remove_once_s;
+ extern const f_string_static_t kt_remove_only_s;
+ extern const f_string_static_t kt_remove_only_fail_s;
+ extern const f_string_static_t kt_remove_root_s;
+ extern const f_string_static_t kt_remove_today_s;
+ extern const f_string_static_t kt_remove_tomorrow_s;
+ extern const f_string_static_t kt_remove_yes_s;
+ extern const f_string_static_t kt_remove_yesterday_s;
+#endif // _di_kt_remove_s_
+
+/**
+ * A processed Date parameter.
+ *
+ * operation: The comparison operation.
+ * type: The date type.
+ *
+ * seconds: The entire date value in seconds.
+ * nanoseconds: The remaining nanosecond not represented in the seconds.
+ */
+#ifndef _di_kt_remove_date_t_
+ typedef struct {
+ uint8_t operation;
+ uint8_t type;
+
+ f_number_unsigned_t seconds;
+ f_number_unsigned_t nanoseconds;
+ } kt_remove_date_t;
+
+ #define kt_remove_date_t_initialize { \
+ 0, \
+ 0, \
+ 0, \
+ 0, \
+ }
+#endif // _di_kt_remove_date_t_
+
+/**
+ * Date parameters.
+ *
+ * array: An array of data parameters.
+ * size: Total amount of allocated space.
+ * used: Total number of allocated spaces used.
+ */
+#ifndef _di_kt_remove_dates_t_
+ typedef struct {
+ kt_remove_date_t *array;
+
+ f_array_length_t size;
+ f_array_length_t used;
+ } kt_remove_dates_t;
+
+ #define kt_remove_dates_t_initialize { \
+ 0, \
+ 0, \
+ 0, \
+ }
+
+ #define macro_kt_remove_dates_t_clear(dates) \
+ dates.array = 0; \
+ dates.size = 0; \
+ dates.used = 0;
+#endif // _di_kt_remove_dates_t_
+
+/**
+ * A processed mode parameter.
+ *
+ * type: The mode type.
+ * mode: The right side date value.
+ */
+#ifndef _di_kt_remove_mode_t_
+ typedef struct {
+ uint8_t type;
+ mode_t mode;
+ } kt_remove_mode_t;
+
+ #define kt_remove_mode_t_initialize { \
+ 0, \
+ 0, \
+ }
+#endif // _di_kt_remove_mode_t_
+
+/**
+ * Mode parameters.
+ *
+ * array: An array of mode parameters.
+ * size: Total amount of allocated space.
+ * used: Total number of allocated spaces used.
+ */
+#ifndef _di_kt_remove_modes_t_
+ typedef struct {
+ kt_remove_mode_t *array;
+
+ f_array_length_t size;
+ f_array_length_t used;
+ } kt_remove_modes_t;
+
+ #define kt_remove_modes_t_initialize { \
+ 0, \
+ 0, \
+ 0, \
+ }
+
+ #define macro_kt_remove_modes_t_clear(dates) \
+ dates.array = 0; \
+ dates.size = 0; \
+ dates.used = 0;
+#endif // _di_kt_remove_modes_t_
+
+/**
+ * Flags passed to the main function or program.
+ *
+ * @todo /proc needs to be implemented, but before that try to understand how --one-file-system, --no-preserve-root, and --preserve-root work in coreutils rm command.
+ *
+ * kt_remove_flag_*_e:
+ * - none: No flags set.
+ * - block: Remove by file type: block.
+ * - character: Remove by file type: character.
+ * - date: Remove by date (separate flag for <, <=, ==, >=, and >).
+ * - different: Remove by user different from caller.
+ * - directory: Remove by file type: directory.
+ * - empty_only: Remove empty directories.
+ * - empty_only_fail: Fail on empty directories.
+ * - 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).
+ * - force: Forcibly delete.
+ * - group: Remove by GID.
+ * - help: Print help.
+ * - isolate_all: Isolate to a single file system, error on all outside file system files (@todo requires /proc support).
+ * - isolate_ignore: Ignore rather than fail for anything on a different file system (@todo requires /proc support).
+ * - isolate_root: Isolate to a single file system, error on remove on '/' (@todo requires /proc support).
+ * - link: Remove by file type: link.
+ * - mode: Remove by mode.
+ * - option_used: This gets set when when certain options are specified to toggle the default match detection boolean during removal of each file.
+ * - print_warning: When specified, warnings are still printed even when verbosity is less than verbose.
+ * - prompt_all: Operate in interactive mode, prompting for every file.
+ * - prompt_follow: Operate in interactive mode: prompting for every link that is being followed.
+ * - prompt_never: Do not operate in interactive mode.
+ * - prompt_once: Operate in interactive mode: prompting if removing 3 or more files.
+ * - recurse: Recurse directories.
+ * - regular: Remove by file type: regular.
+ * - same: Remove by same user as caller.
+ * - simulate: Do not actually perform deletes, instead print messages (when silent, should still return 0 or 1).
+ * - socket: Remove by file type: socket.
+ * - tree: Remove directory tree (parent directories) (remove a/b/c, removes a/b/c, then a/b/, then a).
+ * - user: Remove by UID.
+ * - utc: Process dates in UTC mode.
+ * - version: Print version.
+ */
+#ifndef _di_kt_remove_flag_e_
+ enum {
+ kt_remove_flag_none_e = 0x0,
+ kt_remove_flag_accessed_e = 0x1,
+ kt_remove_flag_block_e = 0x2,
+ kt_remove_flag_character_e = 0x4,
+ kt_remove_flag_created_e = 0x8,
+ kt_remove_flag_different_e = 0x10,
+ kt_remove_flag_directory_e = 0x20,
+ kt_remove_flag_empty_only_e = 0x40,
+ kt_remove_flag_empty_only_fail_e = 0x80,
+ kt_remove_flag_empty_not_e = 0x100,
+ kt_remove_flag_empty_not_fail_e = 0x200,
+ kt_remove_flag_fifo_e = 0x400,
+ kt_remove_flag_follow_e = 0x800,
+ kt_remove_flag_force_e = 0x1000,
+ kt_remove_flag_group_e = 0x2000,
+ kt_remove_flag_help_e = 0x4000,
+ kt_remove_flag_isolate_all_e = 0x8000,
+ kt_remove_flag_isolate_ignore_e = 0x10000,
+ kt_remove_flag_isolate_root_e = 0x20000,
+ kt_remove_flag_link_e = 0x40000,
+ kt_remove_flag_mode_e = 0x80000,
+ kt_remove_flag_option_used_e = 0x100000,
+ kt_remove_flag_print_warning_e = 0x200000,
+ kt_remove_flag_prompt_all_e = 0x400000,
+ kt_remove_flag_prompt_follow_e = 0x800000,
+ kt_remove_flag_prompt_never_e = 0x1000000,
+ kt_remove_flag_prompt_once_e = 0x2000000,
+ kt_remove_flag_recurse_e = 0x4000000,
+ kt_remove_flag_regular_e = 0x8000000,
+ kt_remove_flag_same_e = 0x10000000,
+ kt_remove_flag_simulate_e = 0x20000000,
+ kt_remove_flag_socket_e = 0x40000000,
+ kt_remove_flag_tree_e = 0x80000000,
+ kt_remove_flag_updated_e = 0x100000000,
+ kt_remove_flag_user_e = 0x200000000,
+ kt_remove_flag_utc_e = 0x400000000,
+ kt_remove_flag_version_e = 0x800000000,
+ }; // enum
+#endif // _di_kt_remove_flag_e_
+
+/**
+ * Flags associated with a date.
+ *
+ * @todo Consider (K H D B D C M) for both Time and EpochTime (entire metric?).
+ *
+ * kt_remove_flag_date_*_e:
+ * - none: No flags set.
+ * - equal: Perform equal to on date, '==' or 'equal'.
+ * - less: Perform less than on date, '<' or 'less'.
+ * - less_equal: Perform less than or equal to on date, '<=' or 'less_equal'.
+ * - more: Perform greater than on date, '>' or 'more'.
+ * - more_equal: Perform greater than or equal to on date, '>=' or 'more_equal'.
+ * - not: Perform not equal to on date. '<>' or 'not'
+ *
+ * - has_year: Date has a year.
+ * - now: Date is relative to 'now'.
+ * - string: Date is processed via the string date functions (such as via strftime_r() or getdate_r()).
+ * - time: Date is based off of Time format.
+ * - time_epoch: Date is based off of EpochTime format.
+ * - today: Date is relative to 'today'.
+ * - tomorrow: Date is relative to 'tomorrow'.
+ * - unix: Date is based off of Unix Epoch format.
+ * - yesterday: Date is relative to 'yesterday'.
+ */
+#ifndef _di_kt_remove_flag_date_e_
+ enum {
+ kt_remove_flag_date_none_e = 0x0,
+
+ // Used for comparisons.
+ kt_remove_flag_date_equal_e = 0x1,
+ kt_remove_flag_date_less_e = 0x2,
+ kt_remove_flag_date_less_equal_e = 0x4,
+ kt_remove_flag_date_more_e = 0x8,
+ kt_remove_flag_date_more_equal_e = 0x10,
+ kt_remove_flag_date_not_e = 0x20,
+
+ // Used for processing and converting.
+ kt_remove_flag_date_has_year_e = 0x1,
+ kt_remove_flag_date_now_e = 0x2,
+ kt_remove_flag_date_string_e = 0x4,
+ kt_remove_flag_date_time_e = 0x8,
+ kt_remove_flag_date_time_epoch_e = 0x10,
+ kt_remove_flag_date_today_e = 0x20,
+ kt_remove_flag_date_tomorrow_e = 0x40,
+ kt_remove_flag_date_unix_e = 0x80,
+ kt_remove_flag_date_yesterday_e = 0x100,
+ }; // enum
+#endif // _di_kt_remove_flag_date_e_
+
+/**
+ * Flags associated with a mode.
+ *
+ * kt_remove_flag_mode_*_e:
+ * - none: No flags set.
+ * - different: Remove by mode matching different parts.
+ * - same: Remove by exact mode match.
+ * - similar: Remove by mode matching same parts.
+ * - not: Remove by not exact mode match.
+ */
+#ifndef _di_kt_remove_flag_mode_e_
+ enum {
+ kt_remove_flag_mode_none_e = 0x0,
+ kt_remove_flag_mode_different_e = 0x1, // '~~' or 'different'
+ kt_remove_flag_mode_same_e = 0x2, // '==' or 'same'
+ kt_remove_flag_mode_similar_e = 0x4, // '~=' or 'similar'
+ kt_remove_flag_mode_not_e = 0x8, // '<>' or 'not'
+ }; // enum
+#endif // _di_kt_remove_flag_mode_e_
+
+/**
+ * The main program settings.
+ *
+ * This is passed to the program-specific main entry point to designate program settings.
+ * These program settings are often processed from the program arguments (often called the command line arguments).
+ *
+ * flag: Flags passed to the main function.
+ *
+ * status: The main status code, generally used by the load settings and main functions.
+ * status_thread: A status used eclusively by the threaded signal handler.
+ * state: The state data used when processing data.
+ *
+ * program_name: The short name of the program.
+ * program_name_long: The human friendly name of the program.
+ *
+ * buffer: A string buffer used for caching purposes.
+ * files: An array of file names (full paths to the files) to remove.
+ *
+ * accessed: An array of last accessed dates used for comparison.
+ * created: An array of created on dates used for comparison.
+ * updated: An array of last updated dates used for comparison.
+ * modes: An array of modes used for comparison.
+ * groups: An array of Group IDs (gid_t) represented via an unsigned 32-bit integer.
+ * users: An array of Group IDs (uid_t) represented via an unsigned 32-bit integer.
+ *
+ * process_help: Process help (generally printing help).
+ * process_normal: Process normally (data from parameters and files).
+ *
+ * macro_kt_remove_setting:
+ * - Used to represent a cast to ((kt_remove_setting_t *) setting).
+ * - Simplifies the number of parenthesis used to make code slightly cleaner.
+ * - Is wrapped in a parenthesis and not a block.
+ */
+#ifndef _di_kt_remove_setting_t_
+ typedef struct {
+ uint64_t flag;
+
+ f_status_t status;
+ f_status_t status_thread;
+ f_state_t state;
+
+ f_string_dynamic_t buffer;
+ f_string_dynamics_t files;
+
+ kt_remove_dates_t accessed;
+ kt_remove_dates_t created;
+ kt_remove_dates_t updated;
+ kt_remove_modes_t modes;
+ f_uint32s_t groups;
+ f_uint32s_t users;
+
+ const f_string_static_t *program_name;
+ const f_string_static_t *program_name_long;
+
+ f_status_t (*process_help)(fll_program_data_t * const main, void * const setting);
+ void (*process_normal)(fll_program_data_t * const main, void * const setting);
+ } kt_remove_setting_t;
+
+ #define kt_remove_setting_t_initialize \
+ { \
+ kt_remove_flag_none_e, \
+ F_none, \
+ F_none, \
+ macro_f_state_t_initialize(kt_remove_default_allocation_large_d, kt_remove_default_allocation_small_d, 0, 0, &fll_program_standard_signal_state, 0, 0, 0), \
+ f_string_dynamic_t_initialize, \
+ f_string_dynamics_t_initialize, \
+ kt_remove_dates_t_initialize, \
+ kt_remove_dates_t_initialize, \
+ kt_remove_dates_t_initialize, \
+ kt_remove_modes_t_initialize, \
+ f_uint32s_t_initialize, \
+ f_uint32s_t_initialize, \
+ 0, \
+ 0, \
+ 0, \
+ 0, \
+ }
+
+ #define macro_kt_remove_setting(setting) ((kt_remove_setting_t *) setting)
+#endif // _di_kt_remove_setting_t_
+/**
+ * An arguments array for passing the standard variables to a thread callback.
+ *
+ * main: The main program data.
+ * setting: The main program settings.
+ *
+ * macro_kt_remove_arguments:
+ * - Used to represent a cast to ((kt_remove_setting_t *) setting).
+ * - Simplifies the number of parenthesis used to make code slightly cleaner.
+ * - Is wrapped in a parenthesis and not a block.
+ */
+#ifndef _di_kt_remove_arguments_t_
+ typedef struct {
+ fll_program_data_t *main;
+ kt_remove_setting_t *setting;
+ } kt_remove_arguments_t;
+
+ #define kt_remove_arguments_t_initialize { \
+ 0, \
+ 0, \
+ }
+
+ #define macro_kt_remove_arguments_t_initialize(main, setting) { \
+ main, \
+ setting, \
+ }
+
+ #define macro_kt_remove_arguments(arguments) ((kt_remove_arguments_t *) arguments)
+#endif // _di_kt_remove_arguments_t_
+
+/**
+ * The main program parameters.
+ */
+#ifndef _di_kt_remove_parameter_d_
+ #define KT_REMOVE_short_accessed_s "A"
+ #define KT_REMOVE_short_block_s "b"
+ #define KT_REMOVE_short_character_s "c"
+ #define KT_REMOVE_short_created_s "C"
+ #define KT_REMOVE_short_different_s "O"
+ #define KT_REMOVE_short_directory_s "d"
+ #define KT_REMOVE_short_empty_s "e"
+ #define KT_REMOVE_short_fifo_s "o"
+ #define KT_REMOVE_short_follow_s "F"
+ #define KT_REMOVE_short_force_s "f"
+ #define KT_REMOVE_short_group_s "g"
+ #define KT_REMOVE_short_isolate_s "i"
+ #define KT_REMOVE_short_link_s "l"
+ #define KT_REMOVE_short_mode_s "m"
+ #define KT_REMOVE_short_prompt_s "p"
+ #define KT_REMOVE_short_recurse_s "r"
+ #define KT_REMOVE_short_regular_s "R"
+ #define KT_REMOVE_short_same_s "s"
+ #define KT_REMOVE_short_simulate_s "S"
+ #define KT_REMOVE_short_socket_s "k"
+ #define KT_REMOVE_short_stay_s "Y"
+ #define KT_REMOVE_short_tree_s "t"
+ #define KT_REMOVE_short_updated_s "U"
+ #define KT_REMOVE_short_user_s "u"
+
+ #define KT_REMOVE_long_accessed_s "accessed"
+ #define KT_REMOVE_long_block_s "block"
+ #define KT_REMOVE_long_character_s "character"
+ #define KT_REMOVE_long_created_s "created"
+ #define KT_REMOVE_long_different_s "different"
+ #define KT_REMOVE_long_directory_s "directory"
+ #define KT_REMOVE_long_empty_s "empty"
+ #define KT_REMOVE_long_fifo_s "fifo"
+ #define KT_REMOVE_long_follow_s "follow"
+ #define KT_REMOVE_long_force_s "force"
+ #define KT_REMOVE_long_group_s "group"
+ #define KT_REMOVE_long_isolate_s "isolate"
+ #define KT_REMOVE_long_link_s "link"
+ #define KT_REMOVE_long_local_s "local"
+ #define KT_REMOVE_long_mode_s "mode"
+ #define KT_REMOVE_long_prompt_s "prompt"
+ #define KT_REMOVE_long_recurse_s "recurse"
+ #define KT_REMOVE_long_regular_s "regular"
+ #define KT_REMOVE_long_same_s "same"
+ #define KT_REMOVE_long_simulate_s "simulate"
+ #define KT_REMOVE_long_socket_s "socket"
+ #define KT_REMOVE_long_stay_s "stay"
+ #define KT_REMOVE_long_tree_s "tree"
+ #define KT_REMOVE_long_updated_s "updated"
+ #define KT_REMOVE_long_user_s "user"
+ #define KT_REMOVE_long_utc_s "utc"
+
+ #define KT_REMOVE_short_accessed_s_length 1
+ #define KT_REMOVE_short_block_s_length 1
+ #define KT_REMOVE_short_character_s_length 1
+ #define KT_REMOVE_short_created_s_length 1
+ #define KT_REMOVE_short_different_s_length 1
+ #define KT_REMOVE_short_directory_s_length 1
+ #define KT_REMOVE_short_empty_s_length 1
+ #define KT_REMOVE_short_fifo_s_length 1
+ #define KT_REMOVE_short_follow_s_length 1
+ #define KT_REMOVE_short_force_s_length 1
+ #define KT_REMOVE_short_group_s_length 1
+ #define KT_REMOVE_short_isolate_s_length 1
+ #define KT_REMOVE_short_link_s_length 1
+ #define KT_REMOVE_short_mode_s_length 1
+ #define KT_REMOVE_short_prompt_s_length 1
+ #define KT_REMOVE_short_recurse_s_length 1
+ #define KT_REMOVE_short_regular_s_length 1
+ #define KT_REMOVE_short_same_s_length 1
+ #define KT_REMOVE_short_simulate_s_length 1
+ #define KT_REMOVE_short_socket_s_length 1
+ #define KT_REMOVE_short_stay_s_length 1
+ #define KT_REMOVE_short_tree_s_length 1
+ #define KT_REMOVE_short_updated_s_length 1
+ #define KT_REMOVE_short_user_s_length 1
+
+ #define KT_REMOVE_long_accessed_s_length 8
+ #define KT_REMOVE_long_block_s_length 6
+ #define KT_REMOVE_long_character_s_length 9
+ #define KT_REMOVE_long_created_s_length 7
+ #define KT_REMOVE_long_different_s_length 9
+ #define KT_REMOVE_long_directory_s_length 9
+ #define KT_REMOVE_long_empty_s_length 5
+ #define KT_REMOVE_long_fifo_s_length 4
+ #define KT_REMOVE_long_follow_s_length 6
+ #define KT_REMOVE_long_force_s_length 5
+ #define KT_REMOVE_long_group_s_length 5
+ #define KT_REMOVE_long_isolate_s_length 7
+ #define KT_REMOVE_long_link_s_length 4
+ #define KT_REMOVE_long_local_s_length 5
+ #define KT_REMOVE_long_mode_s_length 4
+ #define KT_REMOVE_long_prompt_s_length 6
+ #define KT_REMOVE_long_recurse_s_length 7
+ #define KT_REMOVE_long_regular_s_length 7
+ #define KT_REMOVE_long_same_s_length 4
+ #define KT_REMOVE_long_simulate_s_length 8
+ #define KT_REMOVE_long_socket_s_length 6
+ #define KT_REMOVE_long_stay_s_length 4
+ #define KT_REMOVE_long_tree_s_length 4
+ #define KT_REMOVE_long_updated_s_length 7
+ #define KT_REMOVE_long_user_s_length 4
+ #define KT_REMOVE_long_utc_s_length 3
+
+ extern const f_string_static_t kt_remove_short_accessed_s;
+ extern const f_string_static_t kt_remove_short_block_s;
+ extern const f_string_static_t kt_remove_short_character_s;
+ extern const f_string_static_t kt_remove_short_created_s;
+ extern const f_string_static_t kt_remove_short_different_s;
+ extern const f_string_static_t kt_remove_short_directory_s;
+ extern const f_string_static_t kt_remove_short_empty_s;
+ extern const f_string_static_t kt_remove_short_fifo_s;
+ extern const f_string_static_t kt_remove_short_follow_s;
+ extern const f_string_static_t kt_remove_short_force_s;
+ extern const f_string_static_t kt_remove_short_group_s;
+ extern const f_string_static_t kt_remove_short_isolate_s;
+ extern const f_string_static_t kt_remove_short_link_s;
+ extern const f_string_static_t kt_remove_short_mode_s;
+ extern const f_string_static_t kt_remove_short_prompt_s;
+ extern const f_string_static_t kt_remove_short_recurse_s;
+ extern const f_string_static_t kt_remove_short_regular_s;
+ extern const f_string_static_t kt_remove_short_same_s;
+ extern const f_string_static_t kt_remove_short_simulate_s;
+ extern const f_string_static_t kt_remove_short_socket_s;
+ extern const f_string_static_t kt_remove_short_stay_s;
+ extern const f_string_static_t kt_remove_short_tree_s;
+ extern const f_string_static_t kt_remove_short_updated_s;
+ extern const f_string_static_t kt_remove_short_user_s;
+
+ extern const f_string_static_t kt_remove_long_accessed_s;
+ extern const f_string_static_t kt_remove_long_block_s;
+ extern const f_string_static_t kt_remove_long_character_s;
+ extern const f_string_static_t kt_remove_long_created_s;
+ extern const f_string_static_t kt_remove_long_different_s;
+ extern const f_string_static_t kt_remove_long_directory_s;
+ extern const f_string_static_t kt_remove_long_empty_s;
+ extern const f_string_static_t kt_remove_long_fifo_s;
+ extern const f_string_static_t kt_remove_long_follow_s;
+ extern const f_string_static_t kt_remove_long_force_s;
+ extern const f_string_static_t kt_remove_long_group_s;
+ extern const f_string_static_t kt_remove_long_isolate_s;
+ extern const f_string_static_t kt_remove_long_link_s;
+ extern const f_string_static_t kt_remove_long_local_s;
+ extern const f_string_static_t kt_remove_long_mode_s;
+ extern const f_string_static_t kt_remove_long_prompt_s;
+ extern const f_string_static_t kt_remove_long_recurse_s;
+ extern const f_string_static_t kt_remove_long_regular_s;
+ extern const f_string_static_t kt_remove_long_same_s;
+ extern const f_string_static_t kt_remove_long_simulate_s;
+ extern const f_string_static_t kt_remove_long_socket_s;
+ extern const f_string_static_t kt_remove_long_stay_s;
+ extern const f_string_static_t kt_remove_long_tree_s;
+ extern const f_string_static_t kt_remove_long_updated_s;
+ extern const f_string_static_t kt_remove_long_user_s;
+ extern const f_string_static_t kt_remove_long_utc_s;
+
+ enum {
+ kt_remove_parameter_help_e,
+ kt_remove_parameter_light_e,
+ kt_remove_parameter_dark_e,
+ kt_remove_parameter_no_color_e,
+ kt_remove_parameter_verbosity_quiet_e,
+ kt_remove_parameter_verbosity_error_e,
+ kt_remove_parameter_verbosity_normal_e,
+ kt_remove_parameter_verbosity_verbose_e,
+ kt_remove_parameter_verbosity_debug_e,
+ kt_remove_parameter_version_e,
+ kt_remove_parameter_accessed_e,
+ kt_remove_parameter_block_e,
+ kt_remove_parameter_character_e,
+ kt_remove_parameter_created_e,
+ kt_remove_parameter_different_e,
+ kt_remove_parameter_directory_e,
+ kt_remove_parameter_empty_e,
+ kt_remove_parameter_fifo_e,
+ kt_remove_parameter_follow_e,
+ kt_remove_parameter_force_e,
+ kt_remove_parameter_group_e,
+ kt_remove_parameter_isolate_e,
+ kt_remove_parameter_link_e,
+ kt_remove_parameter_local_e,
+ kt_remove_parameter_mode_e,
+ kt_remove_parameter_prompt_e,
+ kt_remove_parameter_recurse_e,
+ kt_remove_parameter_regular_e,
+ kt_remove_parameter_same_e,
+ kt_remove_parameter_simulate_e,
+ kt_remove_parameter_socket_e,
+ kt_remove_parameter_stay_e,
+ kt_remove_parameter_tree_e,
+ kt_remove_parameter_updated_e,
+ kt_remove_parameter_user_e,
+ kt_remove_parameter_utc_e,
+ }; // enum
+
+ #define kt_remove_console_parameter_t_initialize \
+ { \
+ macro_f_console_parameter_t_initialize(f_console_standard_short_help_s.string, f_console_standard_long_help_s.string, 0, 0, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(f_console_standard_short_light_s.string, f_console_standard_long_light_s.string, 0, 0, f_console_type_inverse_e), \
+ macro_f_console_parameter_t_initialize(f_console_standard_short_dark_s.string, f_console_standard_long_dark_s.string, 0, 0, f_console_type_inverse_e), \
+ macro_f_console_parameter_t_initialize(f_console_standard_short_no_color_s.string, f_console_standard_long_no_color_s.string, 0, 0, f_console_type_inverse_e), \
+ macro_f_console_parameter_t_initialize(f_console_standard_short_quiet_s.string, f_console_standard_long_quiet_s.string, 0, 0, f_console_type_inverse_e), \
+ macro_f_console_parameter_t_initialize(f_console_standard_short_error_s.string, f_console_standard_long_error_s.string, 0, 0, f_console_type_inverse_e), \
+ macro_f_console_parameter_t_initialize(f_console_standard_short_normal_s.string, f_console_standard_long_normal_s.string, 0, 0, f_console_type_inverse_e), \
+ macro_f_console_parameter_t_initialize(f_console_standard_short_verbose_s.string, f_console_standard_long_verbose_s.string, 0, 0, f_console_type_inverse_e), \
+ macro_f_console_parameter_t_initialize(f_console_standard_short_debug_s.string, f_console_standard_long_debug_s.string, 0, 0, f_console_type_inverse_e), \
+ macro_f_console_parameter_t_initialize(f_console_standard_short_version_s.string, f_console_standard_long_version_s.string, 0, 0, f_console_type_inverse_e), \
+ \
+ macro_f_console_parameter_t_initialize(kt_remove_short_accessed_s.string, kt_remove_long_accessed_s.string, 0, 2, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(kt_remove_short_block_s.string, kt_remove_long_block_s.string, 0, 0, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(kt_remove_short_character_s.string, kt_remove_long_character_s.string, 0, 0, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(kt_remove_short_created_s.string, kt_remove_long_created_s.string, 0, 2, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(kt_remove_short_different_s.string, kt_remove_long_different_s.string, 0, 0, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(kt_remove_short_directory_s.string, kt_remove_long_directory_s.string, 0, 0, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(kt_remove_short_empty_s.string, kt_remove_long_empty_s.string, 0, 1, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(kt_remove_short_fifo_s.string, kt_remove_long_fifo_s.string, 0, 0, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(kt_remove_short_follow_s.string, kt_remove_long_follow_s.string, 0, 0, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(kt_remove_short_force_s.string, kt_remove_long_force_s.string, 0, 0, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(kt_remove_short_group_s.string, kt_remove_long_group_s.string, 0, 1, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(kt_remove_short_isolate_s.string, kt_remove_long_isolate_s.string, 0, 1, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(kt_remove_short_link_s.string, kt_remove_long_link_s.string, 0, 0, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(0, kt_remove_long_local_s.string, 0, 0, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(kt_remove_short_mode_s.string, kt_remove_long_mode_s.string, 0, 2, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(kt_remove_short_prompt_s.string, kt_remove_long_prompt_s.string, 0, 1, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(kt_remove_short_recurse_s.string, kt_remove_long_recurse_s.string, 0, 0, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(kt_remove_short_regular_s.string, kt_remove_long_regular_s.string, 0, 0, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(kt_remove_short_same_s.string, kt_remove_long_same_s.string, 0, 0, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(kt_remove_short_simulate_s.string, kt_remove_long_simulate_s.string, 0, 0, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(kt_remove_short_socket_s.string, kt_remove_long_socket_s.string, 0, 0, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(kt_remove_short_stay_s.string, kt_remove_long_stay_s.string, 0, 0, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(kt_remove_short_tree_s.string, kt_remove_long_tree_s.string, 0, 0, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(kt_remove_short_updated_s.string, kt_remove_long_updated_s.string, 0, 2, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(kt_remove_short_user_s.string, kt_remove_long_user_s.string, 0, 1, f_console_type_normal_e), \
+ macro_f_console_parameter_t_initialize(0, kt_remove_long_utc_s.string, 0, 0, f_console_type_normal_e), \
+ }
+
+ #define kt_remove_total_parameters_d 36
+#endif // _di_kt_remove_parameter_d_
+
+/**
+ * Resize a date array.
+ *
+ * @param length
+ * The new size to use.
+ * @param ranges
+ * The Date Comparison array to resize.
+ *
+ * @return
+ * F_none on success.
+ *
+ * F_array_too_large (with error bit) if the combined array is too large.
+ * F_parameter (with error bit) if a parameter is invalid.
+ *
+ * Errors (with error bit) from: f_memory_resize().
+ */
+#ifndef _di_kt_remove_dates_resize_
+ extern f_status_t kt_remove_dates_resize(const f_array_length_t length, kt_remove_dates_t * const dates);
+#endif // _di_kt_remove_dates_resize_
+
+/**
+ * Resize a mode array.
+ *
+ * @param length
+ * The new size to use.
+ * @param ranges
+ * The Date Comparison array to resize.
+ *
+ * @return
+ * F_none on success.
+ *
+ * F_array_too_large (with error bit) if the combined array is too large.
+ * F_parameter (with error bit) if a parameter is invalid.
+ *
+ * Errors (with error bit) from: f_memory_resize().
+ */
+#ifndef _di_kt_remove_modes_resize_
+ extern f_status_t kt_remove_modes_resize(const f_array_length_t length, kt_remove_modes_t * const modes);
+#endif // _di_kt_remove_modes_resize_
+
+/**
+ * Delete the program main setting data.
+ *
+ * @param setting
+ * The program main setting data.
+ *
+ * This does not alter setting.status.
+ *
+ * @return
+ * F_none on success.
+ *
+ * F_parameter (with error bit) if a parameter is invalid.
+ */
+#ifndef _di_kt_remove_setting_delete_
+ extern f_status_t kt_remove_setting_delete(kt_remove_setting_t * const setting);
+#endif // _di_kt_remove_setting_delete_
+
+/**
+ * Perform the standard program setting load process.
+ *
+ * This prints error messages as appropriate.
+ *
+ * If either main or setting is NULL, then this immediately returns without doing anything.
+ *
+ * @param arguments
+ * The parameters passed to the process (often referred to as command line arguments).
+ * @param main
+ * The main program data.
+ * @param setting
+ * The main program settings.
+ *
+ * The setting.flag has kt_remove_flag_option_used_e forcibly cleared on the start of this function.
+ *
+ * This alters setting.status:
+ * F_none on success.
+ * F_data_not on success but nothing was provided to operate with.
+ *
+ * F_parameter (with error bit) on parameter error.
+ *
+ * Errors (with error bit) from: f_console_parameter_process().
+ * Errors (with error bit) from: f_file_stream_open().
+ * Errors (with error bit) from: f_string_dynamics_resize().
+ *
+ * @see f_console_parameter_process()
+ * @see f_file_stream_open()
+ * @see f_string_dynamics_resize()
+ */
+#ifndef _di_kt_remove_setting_load_
+ extern void kt_remove_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, kt_remove_setting_t * const setting);
+#endif // _di_kt_remove_setting_load_
+
+/**
+ * Perform the standard program setting unload process.
+ *
+ * @param main
+ * The main program data.
+ * @param setting
+ * The main program settings.
+ * All buffers are deallocated.
+ *
+ * This does not alter setting.status.
+ *
+ * @return
+ * F_none on success.
+ *
+ * F_parameter (with error bit) if a parameter is invalid.
+ *
+ * Errors (with error bit) from: utf8_setting_delete().
+ *
+ * @see utf8_setting_delete()
+ */
+#ifndef _di_kt_remove_setting_unload_
+ extern f_status_t kt_remove_setting_unload(fll_program_data_t * const main, kt_remove_setting_t * const setting);
+#endif // _di_kt_remove_setting_unload_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_remove_common_h
--- /dev/null
+#include "remove.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_remove_get_date_
+ struct timespec kt_remove_get_date(fll_program_data_t * const main, kt_remove_setting_t * const setting, const f_string_static_t buffer, uint8_t * const type) {
+
+ if (!setting || !buffer.used) {
+ struct timespec result;
+
+ memset(&result, 0, sizeof(struct timespec));
+
+ if (setting) setting->status = F_data_not;
+
+ return result;
+ }
+
+ {
+ f_string_static_t strings[] = {
+ kt_remove_now_s,
+ kt_remove_today_s,
+ kt_remove_tomorrow_s,
+ kt_remove_yesterday_s,
+ };
+
+ uint16_t enumerations[] = {
+ kt_remove_flag_date_now_e,
+ kt_remove_flag_date_today_e,
+ kt_remove_flag_date_tomorrow_e,
+ kt_remove_flag_date_yesterday_e,
+ };
+
+ for (uint8_t i = 0; i < 4; ++i) {
+
+ if (fl_string_dynamic_compare(buffer, strings[i]) == F_equal_to) {
+ setting->status = F_none;
+
+ if (type) {
+ *type = enumerations[i];
+ }
+
+ return kt_remove_get_date_relative(setting, enumerations[i]);
+ }
+ } // for
+ }
+
+ // 0x1 = single colon, 0x2 = double colon, 0x4 = matched first, 0x8 = matched second, 0x10 = matched negative on first, 0x20 = matched negative on second, 0x40 = matched positive on first, 0x80 = matched positive on second.
+ uint8_t matches = 0;
+ uint64_t digit_first = 0;
+ uint64_t digit_second = 0;
+ f_string_range_t range_first = f_string_range_t_initialize;
+ f_string_range_t range_second = f_string_range_t_initialize;
+
+ struct timespec result;
+
+ memset(&result, 0, sizeof(struct timespec));
+
+ {
+ uint8_t width = 0;
+ f_string_range_t range = macro_f_string_range_t_initialize2(buffer.used);
+ f_array_length_t width_max = (range.stop - range.start) + 1;
+
+ for (; range.start <= range.stop; range.start += width, width_max -= width) {
+
+ // Skip past NULL characters.
+ if (!buffer.string[range.start]) {
+ width = 1;
+
+ continue;
+ }
+
+ width = macro_f_utf_byte_width_is(buffer.string[range.start]);
+
+ if (matches & 0x8) {
+ setting->status = f_utf_is_digit(buffer.string + range.start, width_max, 0);
+
+ if (F_status_is_error(setting->status)) {
+ kt_remove_print_error(setting, main->error, macro_kt_remove_f(f_utf_is_digit));
+
+ return result;
+ }
+
+ if (setting->status == F_true) {
+ range_second.stop = range.start;
+
+ continue;
+ }
+
+ // Not digit matches at this point are invalid.
+ matches = 0;
+
+ break;
+ }
+
+ // @todo review this, this is 0x1, 0x2, and 0x20 (why match second negative?).
+ if (matches & 0x23) {
+
+ // Search until a colon, a digit, or a minus is found.
+ if (fl_string_dynamic_compare_string(buffer.string + range.start, f_string_ascii_colon_s, width) == F_equal_to) {
+
+ // A third colon is not valid.
+ if (matches & 0x2) {
+ matches = 0;
+
+ break;
+ }
+
+ matches |= 0x2;
+
+ continue;
+ }
+
+ if (fl_string_dynamic_compare_string(buffer.string + range.start, f_string_ascii_minus_s, width) == F_equal_to) {
+
+ // An out of place minus sign is not valid.
+ if (matches & 0x20) {
+ matches = 0;
+
+ break;
+ }
+
+ matches |= 0x20;
+
+ continue;
+ }
+
+ setting->status = f_utf_is_digit(buffer.string + range.start, width_max, 0);
+
+ if (F_status_is_error(setting->status)) {
+ kt_remove_print_error(setting, main->error, macro_kt_remove_f(f_utf_is_digit));
+
+ return result;
+ }
+
+ if (setting->status == F_true) {
+ matches |= 0x8;
+ range_second.start = range.start;
+ }
+ }
+ else if (matches & 0x4) {
+
+ // Only a colon is expected.
+ if (fl_string_dynamic_compare_string(buffer.string + range.start, f_string_ascii_colon_s, width) == F_equal_to) {
+ matches |= 0x1;
+ }
+ else {
+ matches = 0;
+
+ break;
+ }
+ }
+ else {
+ setting->status = f_utf_is_whitespace(buffer.string + range.start, width_max, F_false);
+
+ if (F_status_is_error(setting->status)) {
+ kt_remove_print_error(setting, main->error, macro_kt_remove_f(f_utf_is_whitespace));
+
+ return result;
+ }
+
+ if (setting->status == F_true) continue;
+
+ if (fl_string_dynamic_compare_string(buffer.string + range.start, f_string_ascii_colon_s, width) == F_equal_to) {
+ matches |= 0x1;
+
+ continue;
+ }
+
+ if (fl_string_dynamic_compare_string(buffer.string + range.start, f_string_ascii_minus_s, width) == F_equal_to) {
+
+ // An out of place minus sign is not valid.
+ if (matches & 0x50) {
+ matches = 0;
+
+ break;
+ }
+
+ matches |= 0x10;
+
+ continue;
+ }
+
+ setting->status = f_utf_is_digit(buffer.string + range.start, width_max, 0);
+
+ if (F_status_is_error(setting->status)) {
+ kt_remove_print_error(setting, main->error, macro_kt_remove_f(f_utf_is_digit));
+
+ return result;
+ }
+
+ if (setting->status == F_true) {
+ if (matches & 0x4) {
+ range_first.stop = range.start;
+ }
+ else {
+ matches |= 0x4;
+ range_first.start = range.start;
+
+ // A digit is found before a leading minus, so assume this is a positive number.
+ if (!(matches & 0x10)) {
+ matches |= 0x40;
+ }
+ }
+ }
+ else if (!(matches & 0x50) && fl_string_dynamic_compare_string(buffer.string + range.start, f_string_ascii_minus_s, width) == F_equal_to) {
+ matches |= 0x10;
+ }
+ else {
+ matches = 0;
+
+ break;
+ }
+ }
+ } // for
+
+ setting->status = F_none;
+ }
+
+ // If the first and possibly the second digit matches.
+ if (matches & 0xc) {
+ fl_conversion_data_t conversion_data = fl_conversion_data_base_10_c;
+
+ // Process the first character.
+ if (matches & 0x4) {
+ if (matches & 0x10) {
+ conversion_data.flag |= FL_conversion_data_flag_negative_d;
+ }
+
+ setting->status = fl_conversion_dynamic_partial_to_unsigned_detect(conversion_data, buffer, range_first, &digit_first);
+
+ if (F_status_is_error(setting->status)) {
+ kt_remove_print_error(setting, main->error, macro_kt_remove_f(fl_conversion_dynamic_partial_to_unsigned_detect));
+
+ return result;
+ }
+
+ // Remove the negative bit for next use.
+ conversion_data.flag -= conversion_data.flag & FL_conversion_data_flag_negative_d;
+ }
+ else {
+ if (matches & 0x2) {
+
+ // The Unix Epoch is used for double colons when no year is specified.
+ digit_first = kt_remove_time_year_unix_epoch_d;
+
+ if (type) {
+ *type = kt_remove_flag_date_time_epoch_e;
+ }
+ }
+ else {
+
+ // The current year is used for single colon when no year is specified.
+ digit_first = (time(0) / kt_remove_time_seconds_in_year_d) + kt_remove_time_year_unix_epoch_d;
+
+ if (type) {
+ *type = kt_remove_flag_date_time_e;
+ }
+ }
+ }
+
+ // Process the second character.
+ if (matches & 0x8) {
+ if (matches & 0x20) {
+ conversion_data.flag |= FL_conversion_data_flag_negative_d;
+ }
+
+ setting->status = fl_conversion_dynamic_partial_to_unsigned_detect(conversion_data, buffer, range_second, &digit_second);
+
+ if (F_status_is_error(setting->status)) {
+ kt_remove_print_error(setting, main->error, macro_kt_remove_f(fl_conversion_dynamic_partial_to_unsigned_detect));
+
+ return result;
+ }
+
+ if (matches & 0x2) {
+ result.tv_sec = setting->flag & kt_remove_flag_utc_e ? digit_second : digit_second - timezone;
+
+ // This is a double colon, so it is in UnixTime format.
+ if (digit_first > kt_remove_time_year_unix_epoch_d) {
+ result.tv_sec += (digit_first - kt_remove_time_year_unix_epoch_d) * kt_remove_time_seconds_in_year_d;
+ }
+ else if (digit_first < kt_remove_time_year_unix_epoch_d) {
+ result.tv_sec -= (kt_remove_time_year_unix_epoch_d - digit_first) * kt_remove_time_seconds_in_year_d;
+ }
+ }
+ else {
+ result.tv_sec = (digit_second / kt_remove_time_seconds_in_nanosecond_d);
+ result.tv_nsec = digit_second % kt_remove_time_seconds_in_nanosecond_d;
+
+ if (setting->flag & kt_remove_flag_utc_e) {
+ result.tv_sec -= timezone;
+ }
+
+ const uint64_t year_current = (time(0) / kt_remove_time_seconds_in_year_d) + kt_remove_time_year_unix_epoch_d;
+
+ // This is a single colon, so it is in Time format.
+ if (digit_first > kt_remove_time_year_unix_epoch_d) {
+ result.tv_sec += (digit_first - kt_remove_time_year_unix_epoch_d) * kt_remove_time_seconds_in_year_d;
+ }
+ else if (digit_first < kt_remove_time_year_unix_epoch_d) {
+ result.tv_sec -= (kt_remove_time_year_unix_epoch_d - digit_first) * kt_remove_time_seconds_in_year_d;
+ }
+ }
+ }
+ else {
+
+ // A colon after the end without a digit following it is not valid (such as '1234:' or '1234::').
+ if (matches & 0x3) {
+ matches = 0;
+ }
+ else {
+
+ // This is a UNIX timestamp by itself (has no colons).
+ result.tv_sec = setting->flag & kt_remove_flag_utc_e ? digit_first : digit_first - timezone;
+ }
+ }
+ }
+ else {
+ // @todo check to see if this is just a digit, and if so then it is UNIX Epoch time (kt_remove_flag_date_unix_e).
+ }
+
+ if (!matches) {
+ // @todo attempt to process using the string date time conversion libc functions or return an error.
+ // @todo formats:
+ // - YYYY/MM/DD hh:ii:ss a +0000
+ // - YYYY/MM/DD HH:ii:ss +0000
+ // - YYYY/MM/DD hh:ii a +0000
+ // - YYYY/MM/DD HH:ii +0000
+ // - YYYY/MM/DD hh a +0000
+ // - YYYY/MM/DD HH +0000
+ // - YYYY/MM/DD hh:ii:ss a
+ // - YYYY/MM/DD HH:ii:ss
+ // - YYYY/MM/DD hh:ii a
+ // - YYYY/MM/DD HH:ii
+ // - YYYY/MM/DD hh a
+ // - YYYY/MM/DD HH
+ // - YYYY/MM/DD
+ // - YYYY/MM
+ // - YYYY/
+ // (Note how the year by itselfs still has a trailing '/'. this is done to ensure it is not confused with the Unix timestamp.
+
+ //if (type) {
+ // *type = kt_remove_flag_date_string_e;
+ //}
+ }
+
+ setting->status = matches ? F_none : F_status_set_error(F_known_not);
+
+ return result;
+ }
+#endif // _di_kt_remove_get_date_
+
+#ifndef _di_kt_remove_get_date_relative_
+ struct timespec kt_remove_get_date_relative(kt_remove_setting_t * const setting, const uint8_t type) {
+
+ struct timespec result;
+
+ memset(&result, 0, sizeof(struct timespec));
+
+ if (!setting) return result;
+
+ const time_t since_epoch = time(0);
+
+ if (type == kt_remove_flag_date_now_e) {
+ result.tv_sec = since_epoch;
+
+ if (setting->flag & kt_remove_flag_utc_e) {
+ result.tv_sec -= timezone;
+ }
+
+ return result;
+ }
+
+ // Determine start of day.
+ const time_t today = since_epoch - ((setting->flag & kt_remove_flag_utc_e ? since_epoch : since_epoch - timezone) % kt_remove_time_seconds_in_day_d);
+
+ if (type == kt_remove_flag_date_today_e) {
+ result.tv_sec = today;
+ }
+ else if (type == kt_remove_flag_date_tomorrow_e) {
+ result.tv_sec = today + kt_remove_time_seconds_in_day_d;
+ }
+ else {
+ result.tv_sec = today - kt_remove_time_seconds_in_day_d;
+ }
+
+ return result;
+ }
+#endif // _di_kt_remove_get_date_relative_
+
+#ifndef _di_kt_remove_get_id_group_
+ uint32_t kt_remove_get_id_group(kt_remove_setting_t * const setting, const f_string_static_t buffer) {
+
+ if (!setting) return 0;
+
+ f_number_unsigned_t number = 0;
+
+ setting->status = fl_conversion_dynamic_to_unsigned_detect(fl_conversion_data_base_10_c, buffer, &number);
+
+ if (F_status_is_error(setting->status)) {
+ if (F_status_set_fine(setting->status) == F_number) {
+ setting->buffer.used = 0;
+
+ setting->status = fl_string_dynamic_rip_nulless(buffer, &setting->buffer);
+ if (F_status_is_error(setting->status)) return 0;
+
+ gid_t gid = 0;
+
+ setting->status = f_account_group_id_by_name(setting->buffer, &gid);
+ if (F_status_is_error(setting->status)) return 0;
+
+ if (setting->status == F_exist_not) {
+ setting->status = F_status_set_error(F_exist_not);
+
+ return 0;
+ }
+
+ setting->status = F_none;
+
+ return (uint32_t) gid;
+ }
+
+ return 0;
+ }
+
+ if (number > F_type_size_32_unsigned_d) {
+ setting->status = F_status_set_error(F_number_too_large);
+
+ return 0;
+ }
+
+ setting->status = F_none;
+
+ return (uint32_t) number;
+ }
+#endif // _di_kt_remove_get_id_group_
+
+#ifndef _di_kt_remove_get_id_user_
+ uint32_t kt_remove_get_id_user(kt_remove_setting_t * const setting, const f_string_static_t buffer) {
+
+ if (!setting) return 0;
+
+ f_number_unsigned_t number = 0;
+
+ setting->status = fl_conversion_dynamic_to_unsigned_detect(fl_conversion_data_base_10_c, buffer, &number);
+
+ if (F_status_is_error(setting->status)) {
+ if (F_status_set_fine(setting->status) == F_number) {
+ setting->buffer.used = 0;
+
+ setting->status = fl_string_dynamic_rip_nulless(buffer, &setting->buffer);
+ if (F_status_is_error(setting->status)) return 0;
+
+ uid_t uid = 0;
+
+ setting->status = f_account_id_by_name(setting->buffer, &uid);
+ if (F_status_is_error(setting->status)) return 0;
+
+ if (setting->status == F_exist_not) {
+ setting->status = F_status_set_error(F_exist_not);
+
+ return 0;
+ }
+
+ setting->status = F_none;
+
+ return (uint32_t) uid;
+ }
+
+ return 0;
+ }
+
+ if (number > F_type_size_32_unsigned_d) {
+ setting->status = F_status_set_error(F_number_too_large);
+
+ return 0;
+ }
+
+ setting->status = F_none;
+
+ return (uint32_t) number;
+ }
+#endif // _di_kt_remove_get_id_user_
+
+#ifndef _di_kt_remove_get_mode_
+ mode_t kt_remove_get_mode(fll_program_data_t * const main, kt_remove_setting_t * const setting, const f_string_static_t buffer) {
+
+ if (!setting) return 0;
+
+ f_file_mode_t mode_file = f_file_mode_t_initialize;
+ uint8_t mode_replace = 0;
+
+ setting->status = f_file_mode_from_string(buffer, main->umask, &mode_file, &mode_replace);
+
+ if (F_status_is_error(setting->status)) {
+ kt_remove_print_error(setting, main->error, macro_kt_remove_f(f_file_mode_from_string));
+
+ return 0;
+ }
+
+ mode_t mode = 0;
+
+ setting->status = f_file_mode_to_mode(mode_file, &mode);
+
+ if (F_status_is_error(setting->status)) {
+ kt_remove_print_error(setting, main->error, macro_kt_remove_f(f_file_mode_to_mode));
+
+ return 0;
+ }
+
+ setting->status = F_none;
+
+ return mode;
+ }
+#endif // _di_kt_remove_get_mode_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * Kevux Tools - Remove
+ *
+ * Project: Kevux Tools
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ */
+#ifndef _kt_remove_convert_h
+#define _kt_remove_convert_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Convert the string from a string representation of date into the numeric representation of that date.
+ *
+ * This accepts the following formats:
+ * - Time, with or without year (2022:1234, :1234).
+ * - EpochTime, with or without year (2022::1234, ::1234).
+ * - Relative strings: 'now', 'today', 'tomorrow', 'yesterday'.
+ *
+ * Note that 'today', 'tomorrow', and 'yesterday' represent whole days.
+ * Any greater than like values starts at the end of the day.
+ * Any lesser than like values start at the beginning of the day.
+ *
+ * Note that the 'now' is the current moment in time down to the lowest supported unit of time.
+ *
+ * Only a limited set of 'time' string values are implemented in this project.
+ * More 'time' string values will likely be implemented in a not yet existent 'f_time' project in FLL 0.7 or greater (possibly including fl_time and fll_time).
+ *
+ * @param main
+ * The main program data.
+ * @param setting
+ * The main program settings.
+ *
+ * This alters setting.status:
+ * F_none on success.
+ * F_data_not on success, but buffer is empty and there is no data to process.
+ *
+ * F_number_too_large (with error bit) if the given ID is too large.
+ * F_number_too_small (with error bit) if the given ID is too small.
+ * F_known_not (with error bit) if the given string is not of a known format
+ *
+ * Errors (with error bit) from: fl_conversion_dynamic_partial_to_unsigned_detect().
+ * Errors (with error bit) from: fl_string_dynamic_partial_rip_nulless().
+ *
+ * Errors (with error bit) from: kt_remove_get_date_relative().
+ * @param buffer
+ * A string containing group name or ID.
+ * @param type
+ * (optional) The type of date that is detected from the buffer.
+ * This is generally only altered on success.
+ *
+ * Set to NULL to disable.
+ *
+ * @return
+ * The timestamp structure.
+ *
+ * @see fl_conversion_dynamic_partial_to_unsigned_detect()
+ * @see fl_string_dynamic_partial_rip_nulless()
+ *
+ * @see kt_remove_get_date_relative()
+ */
+#ifndef _di_kt_remove_get_date_
+ extern struct timespec kt_remove_get_date(fll_program_data_t * const main, kt_remove_setting_t * const setting, const f_string_static_t buffer, uint8_t * const type);
+#endif // _di_kt_remove_get_date_
+
+/**
+ * Convert the string from a string representation of date into the numeric representation of that date in seconds since epoch.
+ *
+ * This accepts the following formats:
+ * - Relative strings: 'now', 'today', 'tomorrow', and 'yesterday'.
+ *
+ * For 'now', the current time in seconds is returned.
+ * For 'today', the start of the day is returned.
+ * For 'tomorrow', the start of the day after 'today' is returned.
+ * For 'yesterday', the start of the day before 'today' is returned.
+ *
+ * Only a limited set of 'time' string values are implemented in this project.
+ * More 'time' string values will likely be implemented in a not yet existent 'f_time' project in FLL 0.7 or greater (possibly including fl_time and fll_time).
+ *
+ * @param setting
+ * The main program settings.
+ *
+ * This does not alter setting.status.
+ * @param type
+ * The code representing the relative string.
+ * Use appropriate enumeration type code, such as kt_remove_flag_date_now_e.
+ *
+ * @return
+ * The timestamp structure.
+ *
+ * @see time()
+ *
+ * @see f_utf_is_digit()
+ * @see f_utf_is_whitespace()
+ * @see fl_conversion_dynamic_partial_to_unsigned_detect()
+ *
+ * @see kt_remove_get_date_relative()
+ */
+#ifndef _di_kt_remove_get_date_relative_
+ extern struct timespec kt_remove_get_date_relative(kt_remove_setting_t * const setting, const uint8_t type);
+#endif // _di_kt_remove_get_date_relative_
+
+
+/**
+ * Convert the string from a string representation of an ID or a group name into the numeric representation of that ID or group name.
+ *
+ * @param setting
+ * The main program settings.
+ *
+ * This alters setting.status:
+ * F_none on success.
+ *
+ * F_number_too_large (with error bit) if the given ID is too large.
+ *
+ * Errors (with error bit) from: f_account_group_id_by_name().
+ * Errors (with error bit) from: fl_conversion_dynamic_to_unsigned_detect().
+ * Errors (with error bit) from: fl_string_dynamic_rip_nulless().
+ * @param buffer
+ * A string containing group name or ID.
+ *
+ * @see f_account_group_id_by_name()
+ * @see fl_conversion_dynamic_to_unsigned_detect()
+ * @see fl_string_dynamic_rip_nulless()
+ */
+#ifndef _di_kt_remove_get_id_group_
+ extern uint32_t kt_remove_get_id_group(kt_remove_setting_t * const setting, const f_string_static_t buffer);
+#endif // _di_kt_remove_get_id_group_
+
+/**
+ * Convert the string from a string representation of an ID or a user name into the numeric representation of that ID or user name.
+ *
+ * @param setting
+ * The main program settings.
+ *
+ * This alters setting.status:
+ * F_none on success.
+ *
+ * F_number_too_large (with error bit) if the given ID is too large.
+ *
+ * Errors (with error bit) from: f_account_group_id_by_name().
+ * Errors (with error bit) from: fl_conversion_dynamic_to_unsigned_detect().
+ * Errors (with error bit) from: fl_string_dynamic_rip_nulless().
+ * @param buffer
+ * A string containing group name or ID.
+ *
+ * @see f_account_id_by_name()
+ * @see fl_conversion_dynamic_to_unsigned_detect()
+ * @see fl_string_dynamic_rip_nulless()
+ */
+#ifndef _di_kt_remove_get_id_user_
+ extern uint32_t kt_remove_get_id_user(kt_remove_setting_t * const setting, const f_string_static_t buffer);
+#endif // _di_kt_remove_get_id_user_
+
+/**
+ * Convert the string from a string representation of a mode into the numeric representation of that mode.
+ *
+ * @param setting
+ * The main program settings.
+ *
+ * This alters setting.status:
+ * F_none on success.
+ *
+ * Errors (with error bit) from: f_file_mode_from_string().
+ * Errors (with error bit) from: f_file_mode_to_mode().
+ * @param buffer
+ * A string containing group name or ID.
+ *
+ * @see f_file_mode_from_string()
+ * @see f_file_mode_to_mode()
+ */
+#ifndef _di_kt_remove_get_mode_
+ extern mode_t kt_remove_get_mode(fll_program_data_t * const main, kt_remove_setting_t * const setting, const f_string_static_t buffer);
+#endif // _di_kt_remove_get_mode_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_remove_convert_h
--- /dev/null
+#include "remove.h"
+#include "main.h"
+
+int main(const int argc, const f_string_t *argv, const f_string_t *envp) {
+
+ fll_program_data_t data = fll_program_data_t_initialize;
+ kt_remove_setting_t setting = kt_remove_setting_t_initialize;
+ setting.state.data = (void *) &data;
+ setting.program_name = &kt_remove_program_name_s;
+ setting.program_name_long = &kt_remove_program_name_long_s;
+ setting.process_help = &kt_remove_process_help;
+ setting.process_normal = &kt_remove_process_normal;
+
+ #ifdef _en_kt_default_to_utc_
+ setting.flag |= kt_remove_flag_utc_e;
+ #endif // _en_kt_default_to_utc_
+
+ f_console_parameter_t parameters[] = kt_remove_console_parameter_t_initialize;
+ data.parameters.array = parameters;
+ data.parameters.used = kt_remove_total_parameters_d;
+
+ fll_program_standard_setup(&data.signal);
+
+ {
+ const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp);
+
+ kt_remove_setting_load(arguments, &data, &setting);
+ }
+
+ kt_remove_main(&data, &setting);
+
+ kt_remove_setting_unload(&data, &setting);
+
+ fll_program_data_delete(&data);
+
+ fll_program_standard_setdown(&data.signal);
+
+ return F_status_is_error(setting.status) ? 1 : 0;
+}
--- /dev/null
+/**
+ * Kevux Tools - Remove
+ *
+ * Project: Kevux Tools
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ *
+ * This file is only ever included by main.c and should not normally be included anywhere else.
+ * Anything that wants to include this should be providing the "remove" program functionality in some manner.
+ */
+#ifndef _kt_remove_h
+#define _kt_remove_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Standard program entry point.
+ *
+ * @param argc
+ * The number of arguments.
+ * @param argv
+ * The array of arguments.
+ * @param envp
+ * The array of all environment variables on program start.
+ *
+ * @return
+ * 0 on success.
+ * 1 on error.
+ */
+extern int main(const int argc, const f_string_t *argv, const f_string_t *envp);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_remove_h
--- /dev/null
+#include "remove.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_remove_operate_file_
+ void kt_remove_operate_file(fll_program_data_t * const main, kt_remove_setting_t * const setting, const f_string_static_t path) {
+
+ if (!main || !setting) return;
+
+ if (!path.used) {
+ setting->status = F_data_not;
+
+ return;
+ }
+
+ if (main->signal_received) return;
+
+ kt_remove_simulate_operate_file(main, setting, path);
+
+ setting->status = f_file_exists(path, setting->flag & kt_remove_flag_follow_e);
+
+ kt_remove_simulate_operate_file_exists(main, setting, path);
+
+ if (setting->status == F_false) {
+ if (!(setting->flag & kt_remove_flag_simulate_e)) {
+ remove_print_warning_file_reason(setting, main->warning, path, kt_remove_print_reason_not_found_s);
+ }
+
+ return;
+ }
+
+ if (F_status_is_error(setting->status)) {
+ if (!(setting->flag & kt_remove_flag_simulate_e)) {
+ remove_print_warning_file_reason(setting, main->warning, path, kt_remove_print_reason_no_access_s);
+ }
+
+ return;
+ }
+
+ if (setting->status == F_false) {
+ kt_remove_simulate_operate_remove_no(main, setting);
+
+ return;
+ }
+
+ if (main->signal_received) return;
+
+ f_array_length_t i = 0;
+ f_status_t remove = (setting->flag & kt_remove_flag_option_used_e) ? F_false : F_true;
+
+ struct stat statistics;
+
+ memset(&statistics, 0, sizeof(struct stat));
+
+ setting->status = f_file_stat(path, setting->flag & kt_remove_flag_follow_e, &statistics);
+
+ kt_remove_simulate_operate_file_stat(main, setting, statistics);
+
+ if (F_status_is_error(setting->status)) {
+ if (!(setting->flag & kt_remove_flag_simulate_e)) {
+ remove_print_warning_file_reason(setting, main->warning, path, kt_remove_print_reason_stat_fail_s);
+ }
+
+ return;
+ }
+
+ if (setting->flag & kt_remove_flag_block_e) {
+ if (macro_f_file_type_get(statistics.st_mode) == F_file_type_block_d) {
+ remove = F_true;
+ }
+ }
+
+ if (setting->flag & kt_remove_flag_character_e) {
+ if (macro_f_file_type_get(statistics.st_mode) == F_file_type_character_d) {
+ remove = F_true;
+ }
+ }
+
+ if (setting->flag & kt_remove_flag_directory_e) {
+ if (macro_f_file_type_get(statistics.st_mode) == F_file_type_directory_d) {
+ remove = F_true;
+ }
+ }
+
+ if (setting->flag & kt_remove_flag_fifo_e) {
+ if (macro_f_file_type_get(statistics.st_mode) == F_file_type_fifo_d) {
+ remove = F_true;
+ }
+ }
+
+ if (setting->flag & kt_remove_flag_link_e) {
+ if (macro_f_file_type_get(statistics.st_mode) == F_file_type_link_d) {
+ remove = F_true;
+ }
+ }
+
+ if (setting->flag & kt_remove_flag_regular_e) {
+ if (macro_f_file_type_get(statistics.st_mode) == F_file_type_regular_d) {
+ remove = F_true;
+ }
+ }
+
+ if (setting->flag & kt_remove_flag_socket_e) {
+ if (macro_f_file_type_get(statistics.st_mode) == F_file_type_socket_d) {
+ remove = F_true;
+ }
+ }
+
+ if (main->signal_received) return;
+
+ if (setting->flag & kt_remove_flag_user_e) {
+ for (i = 0; i < setting->users.used; ++i) {
+ if (statistics.st_uid == (uid_t) setting->users.array[i]) break;
+ } // for
+
+ if (i < setting->users.used) {
+ remove = F_true;
+ }
+ }
+
+ if (setting->flag & kt_remove_flag_same_e) {
+ if (statistics.st_uid != geteuid()) {
+ remove = F_true;
+ }
+ }
+
+ if (setting->flag & kt_remove_flag_different_e) {
+ if (statistics.st_uid == geteuid()) {
+ remove = F_true;
+ }
+ }
+
+ if (setting->flag & kt_remove_flag_group_e) {
+ for (i = 0; i < setting->groups.used; ++i) {
+ if (statistics.st_gid == (gid_t) setting->groups.array[i]) break;
+ } // for
+
+ if (i < setting->groups.used) {
+ remove = F_true;
+ }
+ }
+
+ if (setting->flag & kt_remove_flag_mode_e) {
+ const mode_t mode = statistics.st_mode & F_file_mode_all_d;
+
+ for (i = 0; i < setting->modes.used; ++i) {
+
+ if (setting->modes.array[i].type == kt_remove_flag_mode_different_e) {
+ if (setting->modes.array[i].mode & ~mode) break;
+ }
+ else if (setting->modes.array[i].type == kt_remove_flag_mode_same_e) {
+ if (setting->modes.array[i].mode == mode) break;
+ }
+ else if (setting->modes.array[i].type == kt_remove_flag_mode_similar_e) {
+ if (setting->modes.array[i].mode & mode) break;
+ }
+ else if (setting->modes.array[i].type == kt_remove_flag_mode_not_e) {
+ if (setting->modes.array[i].mode != mode) break;
+ }
+ } // for
+
+ if (i < setting->modes.used) {
+ remove = F_true;
+ }
+ }
+
+ if (main->signal_received) return;
+
+ setting->status = F_none;
+
+ if (setting->flag & kt_remove_flag_force_e) {
+ if (remove == F_false) {
+ kt_remove_simulate_operate_remove_force_yes(main, setting);
+
+ remove = F_true;
+ }
+ else {
+ kt_remove_simulate_operate_remove_force_no(main, setting);
+ }
+ }
+
+ // @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
+
+ if (remove == F_true) {
+ kt_remove_simulate_operate_remove_yes(main, setting);
+ }
+ else {
+ kt_remove_simulate_operate_remove_no(main, setting);
+ }
+
+ // @todo do actual removal.
+ // @todo be sure too handle all of the remaining flags, such as tree, force, recurse, etc...
+ }
+#endif // _di_kt_remove_operate_file_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * Kevux Tools - Remove
+ *
+ * Project: Kevux Tools
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ */
+#ifndef _kt_remove_operate_h
+#define _kt_remove_operate_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Operate on a single file.
+ *
+ * @param main
+ * The main program data.
+ * @param setting
+ * The main program settings.
+ * Must be of type (kt_remove_setting_t *).
+ *
+ * This alters setting.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.
+ */
+#ifndef _di_kt_remove_operate_file_
+ extern void kt_remove_operate_file(fll_program_data_t * const main, kt_remove_setting_t * const setting, const f_string_static_t path);
+#endif // _di_kt_remove_operate_file_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_remove_operate_h
--- /dev/null
+#include "remove.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_remove_print_error_
+ f_status_t kt_remove_print_error(kt_remove_setting_t * const setting, const fl_print_t print, const f_string_t function) {
+
+ if (print.verbosity == f_console_verbosity_quiet_e) return F_output_not;
+
+ fll_error_print(print, F_status_set_fine(setting->status), function, F_true);
+
+ return F_none;
+ }
+#endif // _di_kt_remove_print_error_
+
+#ifndef _di_kt_remove_print_error_file_
+ f_status_t kt_remove_print_error_file(kt_remove_setting_t * const setting, const fl_print_t print, const f_string_t function, const f_string_static_t name, const f_string_static_t operation, const uint8_t type) {
+
+ if (print.verbosity == f_console_verbosity_quiet_e) return F_output_not;
+
+ fll_error_file_print(print, F_status_set_fine(setting->status), function, F_true, name, operation, type);
+
+ return F_none;
+ }
+#endif // _di_kt_remove_print_error_file_
+
+#ifndef _di_kt_remove_print_error_parameter_missing_value_requires_amount_
+ f_status_t kt_remove_print_error_parameter_missing_value_requires_amount(const fl_print_t print, const f_string_static_t symbol, const f_string_static_t parameter, const f_number_unsigned_t amount) {
+
+ if (print.verbosity == f_console_verbosity_quiet_e) return F_output_not;
+
+ flockfile(print.to.stream);
+
+ fl_print_format("%[%QThe parameter%] ", print.to.stream, print.set->error, print.prefix, print.set->error);
+ fl_print_format("%[%Q%Q%]", print.to.stream, print.set->notable, symbol, parameter, print.set->notable);
+ fl_print_format("%[ is specified, but%] ", print.to.stream, print.set->error, print.set->error);
+ fl_print_format("%[%un%]", print.to.stream, print.set->notable, amount, print.set->notable);
+ fl_print_format(" %[values are not given.%]%r", print.to.stream, print.set->error, print.set->error, f_string_eol_s);
+
+ funlockfile(print.to.stream);
+
+ return F_none;
+ }
+#endif // _di_kt_remove_print_error_parameter_missing_value_requires_amount_
+
+#ifndef _di_kt_remove_print_error_parameter_no_files_
+ f_status_t kt_remove_print_error_parameter_no_files(const fl_print_t print) {
+
+ if (print.verbosity == f_console_verbosity_quiet_e) return F_output_not;
+
+ fll_print_format("%[%QNo files have been specified to be removed.%]%r", print.to.stream, print.set->error, print.prefix, print.set->error, f_string_eol_s);
+
+ return F_none;
+ }
+#endif // _di_kt_remove_print_error_parameter_no_files_
+
+#ifndef _di_kt_remove_print_error_parameter_unknown_value_
+ f_status_t kt_remove_print_error_parameter_unknown_value(const fl_print_t print, const f_string_static_t symbol, const f_string_static_t parameter, const f_string_static_t value) {
+
+ if (print.verbosity == f_console_verbosity_quiet_e) return F_output_not;
+
+ flockfile(print.to.stream);
+
+ fl_print_format("%[%QThe parameter%] ", print.to.stream, print.set->error, print.prefix, print.set->error);
+ fl_print_format("%[%Q%Q%]", print.to.stream, print.set->notable, symbol, parameter, print.set->notable);
+ fl_print_format("%[ is passed an unknown value '%]", print.to.stream, print.set->error, print.set->error);
+ fl_print_format("%[%Q%]", print.to.stream, print.set->notable, value, print.set->notable);
+ fl_print_format("%['.%]%r", print.to.stream, print.set->error, print.set->error, f_string_eol_s);
+
+ funlockfile(print.to.stream);
+
+ return F_none;
+ }
+#endif // _di_kt_remove_print_error_parameter_unknown_value_
+
+#ifndef _di_kt_remove_print_help_
+ f_status_t kt_remove_print_help(kt_remove_setting_t * const setting, const fl_print_t print, const f_color_context_t context) {
+
+ if (!setting) return F_output_not;
+
+ flockfile(print.to.stream);
+
+ fll_program_print_help_header(print.to, context, *setting->program_name_long, kt_remove_program_version_s);
+
+ fll_program_print_help_option(print.to, context, f_console_standard_short_help_s, f_console_standard_long_help_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print this help message.");
+ fll_program_print_help_option(print.to, context, f_console_standard_short_dark_s, f_console_standard_long_dark_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Output using colors that show up better on dark backgrounds.");
+ fll_program_print_help_option(print.to, context, f_console_standard_short_light_s, f_console_standard_long_light_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Output using colors that show up better on light backgrounds.");
+ fll_program_print_help_option(print.to, context, f_console_standard_short_no_color_s, f_console_standard_long_no_color_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, "Do not print.to using color.");
+ fll_program_print_help_option(print.to, context, f_console_standard_short_quiet_s, f_console_standard_long_quiet_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Decrease verbosity, silencing most output.");
+ fll_program_print_help_option(print.to, context, f_console_standard_short_error_s, f_console_standard_long_error_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Decrease verbosity, using only error output.");
+ fll_program_print_help_option(print.to, context, f_console_standard_short_normal_s, f_console_standard_long_normal_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Set verbosity to normal.");
+ fll_program_print_help_option(print.to, context, f_console_standard_short_verbose_s, f_console_standard_long_verbose_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Increase verbosity beyond normal output.");
+ fll_program_print_help_option(print.to, context, f_console_standard_short_debug_s, f_console_standard_long_debug_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Enable debugging, significantly increasing verbosity beyond normal output.");
+ fll_program_print_help_option(print.to, context, f_console_standard_short_version_s, f_console_standard_long_version_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Print only the version number.");
+
+ f_print_dynamic_raw(f_string_eol_s, print.to.stream);
+
+ fll_program_print_help_option(print.to, context, kt_remove_short_accessed_s, kt_remove_long_accessed_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Remove by file last accessed date and time.");
+ fll_program_print_help_option(print.to, context, kt_remove_short_block_s, kt_remove_long_block_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Remove by file type of block.");
+ fll_program_print_help_option(print.to, context, kt_remove_short_character_s, kt_remove_long_character_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Remove by file type of character.");
+ fll_program_print_help_option(print.to, context, kt_remove_short_created_s, kt_remove_long_created_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Remove by file created on date and time.");
+ fll_program_print_help_option(print.to, context, kt_remove_short_different_s, kt_remove_long_different_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Remove by file owner by a user different from the current calling user.");
+ fll_program_print_help_option(print.to, context, kt_remove_short_directory_s, kt_remove_long_directory_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Remove by file type of directory.");
+ fll_program_print_help_option(print.to, context, kt_remove_short_empty_s, kt_remove_long_empty_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Remove directory by a specific empty or not empty state.");
+ fll_program_print_help_option(print.to, context, kt_remove_short_fifo_s, kt_remove_long_fifo_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Remove by file type of FIFO.");
+ fll_program_print_help_option(print.to, context, kt_remove_short_follow_s, kt_remove_long_follow_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Remove the file being pointed to rather than the symbolic link itself.");
+ fll_program_print_help_option(print.to, context, kt_remove_short_force_s, kt_remove_long_force_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Forcibly perform remove.");
+ fll_program_print_help_option(print.to, context, kt_remove_short_group_s, kt_remove_long_group_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Remove by file group ID or name.");
+ fll_program_print_help_option(print.to, context, kt_remove_short_isolate_s, kt_remove_long_isolate_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Isolate remove based on filesystem.");
+ fll_program_print_help_option(print.to, context, kt_remove_short_link_s, kt_remove_long_link_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Remove by file type of link.");
+ fll_program_print_help_option(print.to, context, kt_remove_short_mode_s, kt_remove_long_mode_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Remove by file mode.");
+ fll_program_print_help_option(print.to, context, kt_remove_short_prompt_s, kt_remove_long_prompt_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Prompt before removing.");
+ fll_program_print_help_option(print.to, context, kt_remove_short_recurse_s, kt_remove_long_recurse_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Traverse into sub-directories when removing.");
+ fll_program_print_help_option(print.to, context, kt_remove_short_regular_s, kt_remove_long_regular_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Remove by file type of regular.");
+ fll_program_print_help_option(print.to, context, kt_remove_short_same_s, kt_remove_long_same_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Remove by file owner by the current calling user.");
+ fll_program_print_help_option(print.to, context, kt_remove_short_simulate_s, kt_remove_long_simulate_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Simulate removal rather than actually removing.");
+ fll_program_print_help_option(print.to, context, kt_remove_short_socket_s, kt_remove_long_socket_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Remove by file type of socket.");
+ fll_program_print_help_option(print.to, context, kt_remove_short_stay_s, kt_remove_long_stay_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Remove the symbolic link itself rather than the file being pointed to.");
+ fll_program_print_help_option(print.to, context, kt_remove_short_tree_s, kt_remove_long_tree_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Remove entire specified directory tree.");
+ fll_program_print_help_option(print.to, context, kt_remove_short_updated_s, kt_remove_long_updated_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Remove by file last updated date and time.");
+ fll_program_print_help_option(print.to, context, kt_remove_short_user_s, kt_remove_long_user_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Remove by file user ID or name.");
+
+ f_print_dynamic_raw(f_string_eol_s, print.to.stream);
+
+ fll_program_print_help_option_long(print.to, context, kt_remove_long_local_s, f_console_symbol_long_enable_s, "Designate dates are in local time.");
+ fll_program_print_help_option_long(print.to, context, kt_remove_long_utc_s, f_console_symbol_long_enable_s, " Designate dates are in UTC.");
+
+ fll_program_print_help_usage(print.to, context, kt_remove_program_name_s, kt_remove_program_help_parameters_s);
+
+ fl_print_format(" The parameters '%[%r%r%]', ", print.to.stream, context.set.notable, f_console_symbol_long_enable_s, kt_remove_long_accessed_s, context.set.notable);
+ fl_print_format("'%[%r%r%]', ", print.to.stream, context.set.notable, f_console_symbol_long_enable_s, kt_remove_long_created_s, context.set.notable);
+ fl_print_format("'%[%r%r%]', ", print.to.stream, context.set.notable, f_console_symbol_long_enable_s, kt_remove_long_group_s, context.set.notable);
+ fl_print_format("'%[%r%r%]', ", print.to.stream, context.set.notable, f_console_symbol_long_enable_s, kt_remove_long_mode_s, context.set.notable);
+ fl_print_format("'%[%r%r%]', and ", print.to.stream, context.set.notable, f_console_symbol_long_enable_s, kt_remove_long_updated_s, context.set.notable);
+ fl_print_format("'%[%r%r%]' may be specified multiple times.%r%r", print.to.stream, context.set.notable, f_console_symbol_long_enable_s, kt_remove_long_user_s, context.set.notable, f_string_eol_s, f_string_eol_s);
+
+ fl_print_format(" The value passed to the parameter '%[%r%r%]' may either be a ", print.to.stream, context.set.notable, f_console_symbol_long_enable_s, kt_remove_long_group_s, context.set.notable, f_string_eol_s);
+ fl_print_format("%[GID%]", print.to.stream, context.set.notable, context.set.notable);
+ fl_print_format(" or a %[group name%].%r%r", print.to.stream, context.set.notable, context.set.notable, f_string_eol_s, f_string_eol_s);
+
+ fl_print_format(" The value passed to the parameter '%[%r%r%]' may either be a ", print.to.stream, context.set.notable, f_console_symbol_long_enable_s, kt_remove_long_user_s, context.set.notable, f_string_eol_s);
+ fl_print_format("%[UID%]", print.to.stream, context.set.notable, context.set.notable);
+ fl_print_format(" or a %[user name%].%r%r", print.to.stream, context.set.notable, context.set.notable, f_string_eol_s, f_string_eol_s);
+
+ fl_print_format(" The parameter '%[%r%r%]' supports the following values:%r", print.to.stream, context.set.notable, f_console_symbol_long_enable_s, kt_remove_long_empty_s, context.set.notable, f_string_eol_s);
+ fl_print_format(" - '%[%r%]': Remove directories that are not empty.%r", print.to.stream, context.set.notable, kt_remove_not_s, context.set.notable, f_string_eol_s);
+ fl_print_format(" - '%[%r%]': Fail when attempting to remove directories that are not empty.%r", print.to.stream, context.set.notable, kt_remove_not_fail_s, context.set.notable, f_string_eol_s);
+ fl_print_format(" - '%[%r%]': Remove directories that are empty.%r", print.to.stream, context.set.notable, kt_remove_only_s, context.set.notable, f_string_eol_s);
+ fl_print_format(" - '%[%r%]': Fail when removing directoies that are empty.%r%r", print.to.stream, context.set.notable, kt_remove_only_fail_s, context.set.notable, f_string_eol_s, f_string_eol_s);
+
+ fl_print_format(" The parameter '%[%r%r%]' supports the following values:%r", print.to.stream, context.set.notable, f_console_symbol_long_enable_s, kt_remove_long_isolate_s, context.set.notable, f_string_eol_s);
+ fl_print_format(" - '%[%r%]': Isolate to a single file system, error on all files outside of the file system.%r", print.to.stream, context.set.notable, kt_remove_all_s, context.set.notable, f_string_eol_s);
+ fl_print_format(" - '%[%r%]': Ignore rather than erroring on problems outside the file system.%r", print.to.stream, context.set.notable, kt_remove_ignore_s, context.set.notable, f_string_eol_s);
+ fl_print_format(" - '%[%r%]': Isolate to a single file system, error on '/'.%r%r", print.to.stream, context.set.notable, kt_remove_root_s, context.set.notable, f_string_eol_s, f_string_eol_s);
+
+ // @todo "isolate" needs to optionally pass, ignoring when /proc is not available or fail when /proc is not available.
+ // @todo "/proc" needs to be configurable define macro and use that string here.
+
+ fl_print_format(" The parameter '%[%r%r%]' supports the following values:%r", print.to.stream, context.set.notable, f_console_symbol_long_enable_s, kt_remove_long_prompt_s, context.set.notable, f_string_eol_s);
+ fl_print_format(" - '%[%r%]': Operate in interactive mode, prompting for every file.%r", print.to.stream, context.set.notable, kt_remove_all_s, context.set.notable, f_string_eol_s);
+ fl_print_format(" - '%[%r%]': Operate in interactive mode, prompting for every link that is being followed.%r", print.to.stream, context.set.notable, kt_remove_follow_s, context.set.notable, f_string_eol_s);
+ fl_print_format(" - '%[%r%]': Do not operate in interactive mode.%r", print.to.stream, context.set.notable, kt_remove_never_s, context.set.notable, f_string_eol_s);
+ fl_print_format(" - '%[%r%]': Operate in interactive mode: prompting if removing 3 or more files.%r%r", print.to.stream, context.set.notable, kt_remove_once_s, context.set.notable, f_string_eol_s, f_string_eol_s);
+
+ fl_print_format(" The first value to the parameter '%[%r%r%]' must be any of:%r", print.to.stream, context.set.notable, f_console_symbol_long_enable_s, kt_remove_long_mode_s, context.set.notable, f_string_eol_s);
+ fl_print_format(" - '%[%r%]'", print.to.stream, context.set.notable, kt_remove_mode_symbol_different_s, context.set.notable);
+ fl_print_format(" or '%[%r%]': Mode matches different parts.%r", print.to.stream, context.set.notable, kt_remove_mode_word_different_s, context.set.notable, f_string_eol_s);
+
+ fl_print_format(" - '%[%r%]'", print.to.stream, context.set.notable, kt_remove_mode_symbol_same_s, context.set.notable);
+ fl_print_format(" or '%[%r%]': Mode matches exactly.%r", print.to.stream, context.set.notable, kt_remove_mode_word_same_s, context.set.notable, f_string_eol_s);
+
+ fl_print_format(" - '%[%r%]'", print.to.stream, context.set.notable, kt_remove_mode_symbol_similar_s, context.set.notable);
+ fl_print_format(" or '%[%r%]': Mode matches the same parts.%r", print.to.stream, context.set.notable, kt_remove_mode_word_similar_s, context.set.notable, f_string_eol_s);
+
+ fl_print_format(" - '%[%r%]'", print.to.stream, context.set.notable, kt_remove_mode_symbol_not_s, context.set.notable);
+ fl_print_format(" or '%[%r%]': Mode does not match exactly.%r%r", print.to.stream, context.set.notable, kt_remove_mode_word_not_s, context.set.notable, f_string_eol_s, f_string_eol_s);
+
+ fl_print_format(" The second value to the parameter '%[%r%r%]' may be either a mode octal or a mode string, such as: ", print.to.stream, context.set.notable, f_console_symbol_long_enable_s, kt_remove_long_mode_s, context.set.notable);
+ fl_print_format("'%[0751%]'", print.to.stream, context.set.notable, context.set.notable);
+ fl_print_format(" or '%[u+rwX,g+r%]'.%r%r", print.to.stream, context.set.notable, context.set.notable, f_string_eol_s, f_string_eol_s);
+
+ fl_print_format(" The date related parameters are: '%[%r%r%]', ", print.to.stream, context.set.notable, f_console_symbol_long_enable_s, kt_remove_long_accessed_s, context.set.notable);
+ fl_print_format("'%[%r%r%]', and ", print.to.stream, context.set.notable, f_console_symbol_long_enable_s, kt_remove_long_created_s, context.set.notable);
+ fl_print_format("'%[%r%r%]'.%r%r", print.to.stream, context.set.notable, f_console_symbol_long_enable_s, kt_remove_long_updated_s, context.set.notable, f_string_eol_s, f_string_eol_s);
+
+ fl_print_format(" The first value to the date related parameters must be any of the following comparison operators:%r", print.to.stream, f_string_eol_s);
+ fl_print_format(" - '%[%r%]'", print.to.stream, context.set.notable, kt_remove_date_symbol_equal_s, context.set.notable);
+ fl_print_format(" or '%[%r%]': Date match using an equal to operation.%r", print.to.stream, context.set.notable, kt_remove_date_word_equal_s, context.set.notable, f_string_eol_s);
+ fl_print_format(" - '%[%r%]'", print.to.stream, context.set.notable, kt_remove_date_symbol_less_s, context.set.notable);
+ fl_print_format(" or '%[%r%]': Date match using a less than operation.%r", print.to.stream, context.set.notable, kt_remove_date_word_less_s, context.set.notable, f_string_eol_s);
+ fl_print_format(" - '%[%r%]'", print.to.stream, context.set.notable, kt_remove_date_symbol_less_equal_s, context.set.notable);
+ fl_print_format(" or '%[%r%]': Date match using a less than or equal to operation.%r", print.to.stream, context.set.notable, kt_remove_date_word_less_equal_s, context.set.notable, f_string_eol_s);
+ fl_print_format(" - '%[%r%]'", print.to.stream, context.set.notable, kt_remove_date_symbol_more_s, context.set.notable);
+ fl_print_format(" or '%[%r%]': Date match using a more than operation.%r", print.to.stream, context.set.notable, kt_remove_date_word_more_s, context.set.notable, f_string_eol_s);
+ fl_print_format(" - '%[%r%]'", print.to.stream, context.set.notable, kt_remove_date_symbol_more_equal_s, context.set.notable);
+ fl_print_format(" or '%[%r%]': Date match using a more than or equal to operation.%r", print.to.stream, context.set.notable, kt_remove_date_word_more_equal_s, context.set.notable, f_string_eol_s);
+ fl_print_format(" - '%[%r%]'", print.to.stream, context.set.notable, kt_remove_date_symbol_not_s, context.set.notable);
+ fl_print_format(" or '%[%r%]': Date match using a not equal to operation.%r%r", print.to.stream, context.set.notable, kt_remove_date_word_not_s, context.set.notable, f_string_eol_s, f_string_eol_s);
+
+ fl_print_format(" When the second value to the date related parameters must be a date.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s);
+
+ fl_print_format(" Valid dates for the date related parameters must be any of the following:%r", print.to.stream, f_string_eol_s);
+ fl_print_format(" - '%[%r%]': Use the current day and time.%r", print.to.stream, context.set.notable, kt_remove_now_s, context.set.notable, f_string_eol_s);
+ fl_print_format(" - '%[Time%]': Use the Time format, such as ", print.to.stream, context.set.notable, context.set.notable);
+ fl_print_format("'%[1234:5678%]'.%r", print.to.stream, context.set.notable, context.set.notable, f_string_eol_s);
+ fl_print_format(" - '%[EpochTime%]': Use the EpochTime format, such as ", print.to.stream, context.set.notable, context.set.notable);
+ fl_print_format("'%[1234::5678%]'.%r", print.to.stream, context.set.notable, context.set.notable, f_string_eol_s);
+ fl_print_format(" - '%[%r%]': Use the current day.%r", print.to.stream, context.set.notable, kt_remove_today_s, context.set.notable, f_string_eol_s);
+ fl_print_format(" - '%[%r%]': Use the next day.%r", print.to.stream, context.set.notable, kt_remove_tomorrow_s, context.set.notable, f_string_eol_s);
+ fl_print_format(" - '%[Unix Epoch%]': Use the EpochTime format, such as ", print.to.stream, context.set.notable, context.set.notable);
+ fl_print_format("'%[1672639985%]'.%r", print.to.stream, context.set.notable, context.set.notable, f_string_eol_s);
+ fl_print_format(" - '%[%r%]': Use the previous day.%r%r", print.to.stream, context.set.notable, kt_remove_yesterday_s, context.set.notable, f_string_eol_s, f_string_eol_s);
+
+ // @todo add the additional date string formats once implemented.
+
+ fflush(print.to.stream);
+ funlockfile(print.to.stream);
+
+ return F_none;
+ }
+#endif // _di_kt_remove_print_help_
+
+#ifndef _di_kt_remove_print_warning_file_reason_
+ f_status_t remove_print_warning_file_reason(kt_remove_setting_t * const setting, const fl_print_t print, const f_string_static_t path, const f_string_static_t reason) {
+
+ if (print.verbosity == f_console_verbosity_quiet_e) return F_output_not;
+ if (print.verbosity < f_console_verbosity_verbose_e && !(setting->flag & kt_remove_flag_force_e)) {
+ if (setting) {
+ if (!(setting->flag & kt_remove_flag_print_warning_e)) return F_output_not;
+ }
+ else {
+ return F_output_not;
+ }
+ }
+
+ flockfile(print.to.stream);
+
+ fl_print_format("%[%QUnable to remove file '%]", print.to.stream, print.set->warning, print.prefix, print.set->warning);
+ fl_print_format("%[%Q%]", print.to.stream, print.set->notable, path, print.set->notable);
+ fl_print_format("%[', %Q.%]%r", print.to.stream, print.set->warning, reason, print.set->warning, f_string_eol_s);
+
+ funlockfile(print.to.stream);
+
+ return F_none;
+ }
+#endif // _di_kt_remove_print_warning_file_reason_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * Kevux Tools - Remove
+ *
+ * Project: Kevux Tools
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ */
+#ifndef _kt_remove_print_h
+#define _kt_remove_print_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Print generic error message regarding a function failing in some way.
+ *
+ * @param setting
+ * The main program settings.
+ *
+ * This does not alter setting.status.
+ * @param print
+ * Designates the how and where to print.
+ *
+ * @return
+ * F_none on success.
+ * F_output_not on success, but no printing is performed.
+ *
+ * @see fll_error_print()
+ */
+#ifndef _di_kt_remove_print_error_
+ extern f_status_t kt_remove_print_error(kt_remove_setting_t * const setting, const fl_print_t print, const f_string_t function);
+#endif // _di_kt_remove_print_error_
+
+/**
+ * Print file related error or warning messages.
+ *
+ * @param setting
+ * The main program settings.
+ *
+ * This does not alter setting.status.
+ * @param print
+ * Designates how printing is to be performed.
+ * @param function
+ * The name of the function where the error happened.
+ * Set to 0 to disable.
+ * @param name
+ * The name of the file or directory.
+ * @param operation
+ * The operation that fails, such as 'create' or 'access'.
+ * @param type
+ * A valid file type code from the fll_error_file_type enum.
+ *
+ * @return
+ * F_none on success.
+ * F_output_not on success, but no printing is performed.
+ *
+ * @see fll_error_file_print()
+ */
+#ifndef _di_kt_remove_print_error_file_
+ extern f_status_t kt_remove_print_error_file(kt_remove_setting_t * const setting, const fl_print_t print, const f_string_t function, const f_string_static_t name, const f_string_static_t operation, const uint8_t type);
+#endif // _di_kt_remove_print_error_file_
+
+/**
+ * Print message about parameter not have the required amount of values associated with this parameter.
+ *
+ * This is only printed when verbosity is not set to quiet.
+ *
+ * This uses the following:
+ * - print.set->error: For the error context.
+ * - print.set->strong: For the highlighting context
+ * - print.prefix: For the prefixing a string to the message (such as "ERROR:").
+ *
+ * @param print
+ * The output structure.
+ * This locks, uses, and unlocks the file stream.
+ * @param symbol
+ * The symbol string prepended to both parameters.
+ * This locks, uses, and unlocks the file stream.
+ * This is usually f_console_symbol_long_enable_s.
+ * @param parameter
+ * The parameter name.
+ * @param amount
+ * The number representing the amount of missing parameters.
+ *
+ * @return
+ * F_none on success.
+ * F_output_not on success, but no printing is performed.
+ */
+#ifndef _di_kt_remove_print_error_parameter_missing_value_requires_amount_
+ extern f_status_t kt_remove_print_error_parameter_missing_value_requires_amount(const fl_print_t print, const f_string_static_t symbol, const f_string_static_t parameter, const f_number_unsigned_t amount);
+#endif // _di_kt_remove_print_error_parameter_missing_value_requires_amount_
+
+/**
+ * Print message about no files being specified.
+ *
+ * This is only printed when verbosity is not set to quiet.
+ *
+ * This uses the following:
+ * - print.set->error: For the error context.
+ * - print.set->strong: For the highlighting context
+ * - print.prefix: For the prefixing a string to the message (such as "ERROR:").
+ *
+ * @param print
+ * The output structure.
+ * This locks, uses, and unlocks the file stream.
+ *
+ * @return
+ * F_none on success.
+ * F_output_not on success, but no printing is performed.
+ */
+#ifndef _di_kt_remove_print_error_parameter_no_files_
+ extern f_status_t kt_remove_print_error_parameter_no_files(const fl_print_t print);
+#endif // _di_kt_remove_print_error_parameter_no_files_
+
+/**
+ * Print message about parameter having an unknown value.
+ *
+ * This is only printed when verbosity is not set to quiet.
+ *
+ * This uses the following:
+ * - print.set->error: For the error context.
+ * - print.set->strong: For the highlighting context
+ * - print.prefix: For the prefixing a string to the message (such as "ERROR:").
+ *
+ * @param print
+ * The output structure.
+ * This locks, uses, and unlocks the file stream.
+ * @param symbol
+ * The symbol string prepended to both parameters.
+ * This locks, uses, and unlocks the file stream.
+ * This is usually f_console_symbol_long_enable_s.
+ * @param parameter
+ * The parameter name.
+ * @param value
+ * The unknown value.
+ *
+ * @return
+ * F_none on success.
+ * F_output_not on success, but no printing is performed.
+ */
+#ifndef _di_kt_remove_print_error_parameter_unknown_value_
+ extern f_status_t kt_remove_print_error_parameter_unknown_value(const fl_print_t print, const f_string_static_t symbol, const f_string_static_t parameter, const f_string_static_t value);
+#endif // _di_kt_remove_print_error_parameter_unknown_value_
+
+/**
+ * Print help.
+ *
+ * @param setting
+ * The main program settings.
+ *
+ * This does not alter setting.status.
+ * @param print
+ * Designates how printing is to be performed.
+ * @param context
+ * The color context settings.
+ *
+ * @return
+ * F_none on success.
+ */
+#ifndef _di_kt_remove_print_help_
+ extern f_status_t kt_remove_print_help(kt_remove_setting_t * const setting, const fl_print_t print, const f_color_context_t context);
+#endif // _di_kt_remove_print_help_
+
+/**
+ * Print warning message about file not being found.
+ *
+ * This is only printed when verbosity is less than verbose and kt_remove_flag_print_warning_e is not set.
+ * This is not printed when verbosity is set to quiet even when kt_remove_flag_print_warning_e is set.
+ * This is not printed when kt_remove_flag_force_e is set.
+ *
+ * This uses the following:
+ * - print.set->warning: For the warning context.
+ * - print.set->strong: For the highlighting context
+ * - print.prefix: For the prefixing a string to the message (such as "WARNING:").
+ *
+ * @param print
+ * The output structure.
+ * This locks, uses, and unlocks the file stream.
+ * @param path
+ * The path to the file.
+ * @param reason
+ * The reason for the failure.
+ *
+ * @return
+ * F_none on success.
+ * F_output_not on success, but no printing is performed.
+ */
+#ifndef _di_kt_remove_print_warning_file_reason_
+ extern f_status_t remove_print_warning_file_reason(kt_remove_setting_t * const setting, const fl_print_t print, const f_string_static_t path, const f_string_static_t reason);
+#endif // _di_kt_remove_print_warning_file_reason_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_remove_print_h
--- /dev/null
+#include "remove.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_remove_main_
+ void kt_remove_main(fll_program_data_t * const main, kt_remove_setting_t * const setting) {
+
+ if (!main || !setting || F_status_is_error(setting->status)) return;
+
+ setting->status = F_none;
+
+ if (setting->flag & kt_remove_flag_help_e) {
+ if (setting->process_help) {
+ setting->process_help(main, (void *) setting);
+ }
+
+ return;
+ }
+
+ if (setting->flag & kt_remove_flag_version_e) {
+ fll_print_format("%r%r", main->output.to.stream, kt_remove_program_version_s, f_string_eol_s);
+
+ return;
+ }
+
+ // This program ignores the input pipe.
+ if (setting->process_normal) {
+ setting->process_normal(main, (void *) setting);
+ if (F_status_is_error(setting->status)) return;
+ }
+
+ // Ensure a new line is always put at the end of the program execution.
+ f_print_dynamic_raw(f_string_eol_s, main->output.to.stream);
+
+ if (main->signal_received) {
+ setting->status = F_interrupt;
+ }
+ }
+#endif // _di_kt_remove_main_
+
+#ifndef _di_kt_remove_process_help_
+ f_status_t kt_remove_process_help(fll_program_data_t * const main, void * const void_setting) {
+
+ if (!main || !void_setting) return F_output_not;
+
+ return kt_remove_print_help(macro_kt_remove_setting(void_setting), main->output, main->context);
+ }
+#endif // _di_kt_remove_process_help_
+
+#ifndef _di_kt_remove_process_normal_
+ void kt_remove_process_normal(fll_program_data_t * const main, void * const void_setting) {
+
+ if (!main || !void_setting) return;
+
+ kt_remove_arguments_t arguments = macro_kt_remove_arguments_t_initialize(main, macro_kt_remove_setting(void_setting));
+
+ f_thread_id_t id_signal;
+
+ memset(&id_signal, 0, sizeof(f_thread_id_t));
+
+ macro_kt_remove_setting(void_setting)->status = f_thread_create(0, &id_signal, &kt_remove_thread_signal, (void *) &arguments);
+
+ if (F_status_is_error(macro_kt_remove_setting(void_setting)->status)) {
+ kt_remove_print_error(macro_kt_remove_setting(void_setting), main->error, macro_kt_remove_f(f_thread_create));
+
+ return;
+ }
+
+ kt_remove_process_normal_operate(main, macro_kt_remove_setting(void_setting));
+
+ f_thread_cancel(id_signal);
+ f_thread_join(id_signal, 0);
+ }
+#endif // _di_kt_remove_process_normal_
+
+#ifndef _di_kt_remove_process_normal_operate_
+ void kt_remove_process_normal_operate(fll_program_data_t * const main, kt_remove_setting_t * const setting) {
+
+ if (!main || !setting) return;
+
+ if (!setting->files.used) {
+ kt_remove_print_error_parameter_no_files(main->error);
+
+ return;
+ }
+
+ kt_remove_simulate_operate(main, setting);
+
+ setting->status = F_none;
+
+ for (f_array_length_t i = 0; i < setting->files.used; ++i) {
+
+ kt_remove_operate_file(main, setting, setting->files.array[i]);
+ if (F_status_is_error(setting->status)) break;
+
+ if ((setting->flag & kt_remove_flag_simulate_e) && i + 1 < setting->files.used) {
+ f_print_dynamic(f_string_eol_s, main->output.to.stream);
+ }
+
+ if (setting->status == F_interrupt) break;
+ } // for
+ }
+#endif // _di_kt_remove_process_normal_operate_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * Kevux Tools - Remove
+ *
+ * Project: Kevux Tools
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ *
+ * This program provides a program to perform file, directory, and symbolic link remove file removals.
+ */
+#ifndef _kt_remove_h
+#define _kt_remove_h
+
+// Libc includes.
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+// FLL-0 includes.
+#include <fll/level_0/type.h>
+#include <fll/level_0/status.h>
+#include <fll/level_0/memory.h>
+#include <fll/level_0/string.h>
+#include <fll/level_0/utf.h>
+#include <fll/level_0/account.h>
+#include <fll/level_0/color.h>
+#include <fll/level_0/console.h>
+#include <fll/level_0/conversion.h>
+#include <fll/level_0/file.h>
+#include <fll/level_0/fss.h>
+#include <fll/level_0/pipe.h>
+#include <fll/level_0/print.h>
+#include <fll/level_0/signal.h>
+#include <fll/level_0/thread.h>
+
+// FLL-1 includes.
+#include <fll/level_1/conversion.h>
+#include <fll/level_1/print.h>
+#include <fll/level_1/string.h>
+
+// FLL-2 includes.
+#include <fll/level_2/error.h>
+#include <fll/level_2/print.h>
+#include <fll/level_2/program.h>
+
+// Kevux Tools includes.
+#include <program/kevux/tools/remove/common.h>
+#include <program/kevux/tools/remove/common-print.h>
+#include <program/kevux/tools/remove/convert.h>
+#include <program/kevux/tools/remove/operate.h>
+#include <program/kevux/tools/remove/print.h>
+#include <program/kevux/tools/remove/signal.h>
+#include <program/kevux/tools/remove/simulate.h>
+#include <program/kevux/tools/remove/thread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Execute main program.
+ *
+ * If main.signal is non-zero, then this blocks and handles the following signals:
+ * - F_signal_abort
+ * - F_signal_broken_pipe
+ * - F_signal_hangup
+ * - F_signal_interrupt
+ * - F_signal_quit
+ * - F_signal_termination
+ *
+ * @param main
+ * The main program data.
+ * @param setting
+ * The main program settings.
+ *
+ * This alters setting.status:
+ * F_none on success.
+ * 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(fll_program_data_t * const main, kt_remove_setting_t * const setting);
+#endif // _di_kt_remove_main_
+
+/**
+ * Process printing help.
+ *
+ * @param main
+ * The main program data.
+ * @param setting
+ * The main program settings.
+ * Must be of type (kt_remove_setting_t *).
+ *
+ * This does not alter setting.status.
+ *
+ * @return
+ * F_none on success.
+ * F_output_not on success, but no printing is performed.
+ */
+#ifndef _di_kt_remove_process_help_
+ extern f_status_t kt_remove_process_help(fll_program_data_t * const main, void * const setting);
+#endif // _di_kt_remove_process_help_
+
+/**
+ * Process normally, writing to the output.
+ *
+ * @param main
+ * The main program data.
+ * @param setting
+ * The main program settings.
+ * Must be of type (kt_remove_setting_t *).
+ *
+ * This alters setting.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()
+ */
+#ifndef _di_kt_remove_process_normal_
+ extern void kt_remove_process_normal(fll_program_data_t * const main, void * const setting);
+#endif // _di_kt_remove_process_normal_
+
+/**
+ * Perform the normal processing.
+ *
+ * @param main
+ * The main program data.
+ * @param setting
+ * The main program settings.
+ * Must be of type (kt_remove_setting_t *).
+ *
+ * This alters setting.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(fll_program_data_t * const main, kt_remove_setting_t * const setting);
+#endif // _di_kt_remove_process_normal_operate_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_remove_h
--- /dev/null
+#include "remove.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(_di_kt_remove_signal_check_) && defined(_di_thread_support_)
+ f_status_t kt_remove_signal_check(fll_program_data_t * const main) {
+
+ if (main->signal.id == -1) return F_false;
+
+ if (!((++main->signal_check) % kt_remove_signal_check_d)) {
+ if (fll_program_standard_signal_received(main)) return F_true;
+
+ data->main->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(fll_program_data_t * const main) {
+
+ if (main->signal.id == -1) return F_false;
+ if (main->signal_received) return F_true;
+
+ return F_false;
+ }
+#endif // !defined(_di_kt_remove_signal_check_) && !defined(_di_thread_support_)
+
+#if !defined(_di_kt_remove_signal_handler_) && !defined(_di_thread_support_)
+ void kt_remove_signal_handler(fll_program_data_t * const main, kt_remove_setting_t * const setting) {
+
+ if (!main || !setting) return;
+
+ siginfo_t information;
+ f_array_length_t failsafe = 0;
+
+ memset(&information, 0, sizeof(siginfo_t));
+
+ main->signal_received = 0;
+
+ f_signal_set_empty(&main->signal.set);
+ f_signal_set_add(F_signal_abort, &main->signal.set);
+ f_signal_set_add(F_signal_broken_pipe, &main->signal.set);
+ f_signal_set_add(F_signal_hangup, &main->signal.set);
+ f_signal_set_add(F_signal_interrupt, &main->signal.set);
+ f_signal_set_add(F_signal_quit, &main->signal.set);
+ f_signal_set_add(F_signal_termination, &main->signal.set);
+
+ if (main->signal.id == -1) {
+ setting->status_thread = f_signal_open(&main->signal);
+
+ if (F_status_is_error(setting->status_thread)) {
+ main->signal_received = F_signal_abort;
+
+ return;
+ }
+ }
+
+ do {
+ memset(&information, 0, sizeof(siginfo_t));
+
+ setting->status_thread = f_signal_wait(&main->signal.set, &information);
+
+ if (F_status_is_error(setting->status_thread) && F_status_set_fine(setting->status_thread) != F_interrupt) {
+ if (++failsafe >= kt_remove_signal_check_failsafe_d) break;
+ }
+
+ switch (information.si_signo) {
+ case F_signal_abort:
+ case F_signal_broken_pipe:
+ case F_signal_hangup:
+ case F_signal_interrupt:
+ case F_signal_quit:
+ case F_signal_termination:
+ main->signal_received = information.si_signo;
+
+ break;
+ }
+
+ failsafe = 0;
+ setting->status_thread = F_none;
+
+ } while (!main->signal_received);
+
+ f_signal_close(&main->signal);
+
+ if (F_status_is_error(setting->status_thread)) {
+ main->signal_received = F_signal_abort;
+ }
+ }
+#endif // !defined(_di_kt_remove_signal_handler_) && !defined(_di_thread_support_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * Kevux Tools - Remove
+ *
+ * Project: Kevux Tools
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ */
+#ifndef _kt_remove_signal_h
+#define _kt_remove_signal_h
+
+#ifdef __cplusplus
+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 data.
+ *
+ * @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(fll_program_data_t * const main);
+#endif // _di_kt_remove_signal_check_
+
+/**
+ * Signal handler for signals/interrupts.
+ *
+ * This blocks until an expected signal is recieved.
+ * When an expected signal is received it then sets the
+ *
+ * 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
+ *
+ * @param main
+ * The main program data.
+ * @param setting
+ * The main program settings.
+ *
+ * This alters setting.signal_received, setting it to a received signal.
+ *
+ * This alters setting.status:
+ * Errors with (error bit set) from: f_signal_open()
+ * Errors with (error bit set) from: f_signal_wait()
+ *
+ * @see f_signal_close()
+ * @see f_signal_open()
+ * @see f_signal_wait()
+ */
+#if !defined(_di_kt_remove_signal_handler_) && !defined(_di_thread_support_)
+ extern void kt_remove_signal_handler(fll_program_data_t * const main, kt_remove_setting_t * const setting);
+#endif // !defined(_di_kt_remove_signal_handler_) && !defined(_di_thread_support_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_remove_signal_h
--- /dev/null
+#include "remove.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_remove_simulate_operate_
+ void kt_remove_simulate_operate(fll_program_data_t * const main, kt_remove_setting_t * const setting) {
+
+ if (!main || !setting) return;
+ if (!(setting->flag & kt_remove_flag_simulate_e)) return;
+
+ flockfile(main->output.to.stream);
+
+ fl_print_format("%r%[Files to Remove%]:%r", main->output.to.stream, f_string_eol_s, main->output.set->title, main->output.set->title, f_string_eol_s);
+
+ for (f_array_length_t i = 0; i < setting->files.used; ++i) {
+ fl_print_format(" %Q%r", main->output.to.stream, setting->files.array[i], f_string_eol_s);
+ } // for
+
+ f_print_dynamic(f_string_eol_s, main->output.to.stream);
+
+ funlockfile(main->output.to.stream);
+ }
+#endif // _di_kt_remove_simulate_operate_
+
+#ifndef _di_kt_remove_simulate_operate_file_
+ void kt_remove_simulate_operate_file(fll_program_data_t * const main, kt_remove_setting_t * const setting, const f_string_static_t path) {
+
+ if (!main || !setting) return;
+ if (!(setting->flag & kt_remove_flag_simulate_e)) return;
+
+ fll_print_format("%[Remove '%Q'%]:%r", main->output.to.stream, main->output.set->notable, path, main->output.set->notable, f_string_eol_s);
+ }
+#endif // _di_kt_remove_simulate_operate_file_
+
+#ifndef _di_kt_remove_simulate_operate_file_exists_
+ void kt_remove_simulate_operate_file_exists(fll_program_data_t * const main, kt_remove_setting_t * const setting, const f_string_static_t path) {
+
+ if (!main || !setting) return;
+ if (!(setting->flag & kt_remove_flag_simulate_e)) return;
+
+ if (F_status_is_error(setting->status)) {
+ fl_print_format(" file_access_failure %un%r", main->output.to.stream, (f_number_unsigned_t) F_status_set_fine(setting->status), f_string_eol_s);
+
+ return;
+ }
+
+ if (setting->status == F_true) {
+ f_status_t status = f_file_is(path, F_file_type_link_d, F_false);
+
+ if (F_status_is_error(status)) {
+ fl_print_format(" file_read_failure %un%r", main->output.to.stream, (f_number_unsigned_t) F_status_set_fine(status), f_string_eol_s);
+
+ return;
+ }
+
+ if (status == F_true) {
+ setting->buffer.used = 0;
+
+ status = f_file_link_read(path, F_false, &setting->buffer);
+
+ if (F_status_is_error(status)) {
+ fl_print_format(" link_read_failure %un%r", main->output.to.stream, (f_number_unsigned_t) F_status_set_fine(status), f_string_eol_s);
+
+ return;
+ }
+
+ flockfile(main->output.to.stream);
+
+ fl_print_format(" follow %Q%r", main->output.to.stream, (setting->flag & kt_remove_flag_follow_e) ? kt_remove_yes_s : kt_remove_no_s, f_string_eol_s);
+ fl_print_format(" to '%Q'%r", main->output.to.stream, setting->buffer, f_string_eol_s);
+
+ funlockfile(main->output.to.stream);
+ }
+ }
+
+ fll_print_format(" exists %Q%r", main->output.to.stream, setting->status == F_true ? kt_remove_yes_s : kt_remove_no_s, f_string_eol_s);
+ }
+#endif // _di_kt_remove_simulate_operate_file_exists_
+
+#ifndef _di_kt_remove_simulate_operate_file_stat_
+ void kt_remove_simulate_operate_file_stat(fll_program_data_t * const main, kt_remove_setting_t * const setting, struct stat statistics) {
+
+ if (!main || !setting) return;
+ if (!(setting->flag & kt_remove_flag_simulate_e)) return;
+
+ if (setting->flag & kt_remove_flag_block_e) {
+ fll_print_format(" block %Q%r", main->output.to.stream, (macro_f_file_type_get(statistics.st_mode) == F_file_type_block_d) ? kt_remove_yes_s : kt_remove_no_s, f_string_eol_s);
+ }
+
+ if (setting->flag & kt_remove_flag_character_e) {
+ fll_print_format(" character %Q%r", main->output.to.stream, (macro_f_file_type_get(statistics.st_mode) == F_file_type_character_d) ? kt_remove_yes_s : kt_remove_no_s, f_string_eol_s);
+ }
+
+ if (setting->flag & kt_remove_flag_directory_e) {
+ fll_print_format(" directory %Q%r", main->output.to.stream, (macro_f_file_type_get(statistics.st_mode) == F_file_type_directory_d) ? kt_remove_yes_s : kt_remove_no_s, f_string_eol_s);
+ }
+
+ if (setting->flag & kt_remove_flag_fifo_e) {
+ fll_print_format(" fifo %Q%r", main->output.to.stream, (macro_f_file_type_get(statistics.st_mode) == F_file_type_fifo_d) ? kt_remove_yes_s : kt_remove_no_s, f_string_eol_s);
+ }
+
+ if (setting->flag & kt_remove_flag_link_e) {
+ fll_print_format(" link %Q%r", main->output.to.stream, (macro_f_file_type_get(statistics.st_mode) == F_file_type_link_d) ? kt_remove_yes_s : kt_remove_no_s, f_string_eol_s);
+ }
+
+ if (setting->flag & kt_remove_flag_regular_e) {
+ fll_print_format(" regular %Q%r", main->output.to.stream, (macro_f_file_type_get(statistics.st_mode) == F_file_type_regular_d) ? kt_remove_yes_s : kt_remove_no_s, f_string_eol_s);
+ }
+
+ if (setting->flag & kt_remove_flag_socket_e) {
+ fll_print_format(" socket %Q%r", main->output.to.stream, (macro_f_file_type_get(statistics.st_mode) == F_file_type_socket_d) ? kt_remove_yes_s : kt_remove_no_s, f_string_eol_s);
+ }
+
+ f_array_length_t i = 0;
+
+ if (setting->flag & kt_remove_flag_user_e) {
+ for (; i < setting->users.used; ++i) {
+ if (statistics.st_uid == (uid_t) setting->users.array[i]) break;
+ } // for
+
+ if (i == setting->users.used) {
+ fll_print_format(" user%r", main->output.to.stream, f_string_eol_s);
+ }
+ else {
+ fll_print_format(" user %un%r", main->output.to.stream, (f_number_unsigned_t) statistics.st_uid, f_string_eol_s);
+ }
+ }
+
+ if (setting->flag & kt_remove_flag_same_e) {
+ fll_print_format(" same %Q%r", main->output.to.stream, (statistics.st_uid == geteuid()) ? kt_remove_yes_s : kt_remove_no_s, f_string_eol_s);
+ }
+
+ if (setting->flag & kt_remove_flag_different_e) {
+ fll_print_format(" different %Q%r", main->output.to.stream, (statistics.st_uid == geteuid()) ? kt_remove_no_s : kt_remove_yes_s, f_string_eol_s);
+ }
+
+ if (setting->flag & kt_remove_flag_group_e) {
+ for (i = 0; i < setting->groups.used; ++i) {
+ if (statistics.st_gid == (gid_t) setting->groups.array[i]) break;
+ } // for
+
+ if (i == setting->groups.used) {
+ fll_print_format(" group%r", main->output.to.stream, f_string_eol_s);
+ }
+ else {
+ fll_print_format(" group %un%r", main->output.to.stream, (f_number_unsigned_t) statistics.st_gid, f_string_eol_s);
+ }
+ }
+
+ if (setting->flag & kt_remove_flag_mode_e) {
+ const mode_t mode = statistics.st_mode & F_file_mode_all_d;
+
+ fll_print_format(" mode %@un%r", main->output.to.stream, (f_number_unsigned_t) mode, f_string_eol_s);
+
+ for (i = 0; i < setting->modes.used; ++i) {
+
+ if (setting->modes.array[i].type == kt_remove_flag_mode_different_e) {
+ if (setting->modes.array[i].mode & ~mode) break;
+ }
+ else if (setting->modes.array[i].type == kt_remove_flag_mode_same_e) {
+ if (setting->modes.array[i].mode == mode) break;
+ }
+ else if (setting->modes.array[i].type == kt_remove_flag_mode_similar_e) {
+ if (setting->modes.array[i].mode & mode) break;
+ }
+ else if (setting->modes.array[i].type == kt_remove_flag_mode_not_e) {
+ if (setting->modes.array[i].mode != mode) break;
+ }
+ } // for
+
+ if (i < setting->modes.used) {
+ uint8_t types[] = {
+ kt_remove_flag_mode_different_e,
+ kt_remove_flag_mode_same_e,
+ kt_remove_flag_mode_similar_e,
+ kt_remove_flag_mode_not_e,
+ };
+
+ f_string_static_t strings[] = {
+ kt_remove_mode_word_different_s,
+ kt_remove_mode_word_same_s,
+ kt_remove_mode_word_similar_s,
+ kt_remove_mode_word_not_s,
+ };
+
+ for (uint8_t j = 0; j < 4; ++j) {
+
+ if (setting->modes.array[i].type == types[j]) {
+ fll_print_format(" mode_matched %Q %@un%r", main->output.to.stream, strings[j], (f_number_unsigned_t) setting->modes.array[i].mode, f_string_eol_s);
+
+ break;
+ }
+ } // for
+ }
+ }
+
+ {
+ kt_remove_dates_t * const dates[] = {
+ &setting->accessed,
+ &setting->created,
+ &setting->updated,
+ };
+
+ struct timespec times[] = {
+ statistics.st_atim,
+ statistics.st_ctim,
+ statistics.st_mtim,
+ };
+
+ const f_string_static_t * const names[] = {
+ &kt_remove_long_accessed_s,
+ &kt_remove_long_created_s,
+ &kt_remove_long_updated_s,
+ };
+
+ f_string_static_t name_type = f_string_empty_s;
+ uint8_t p = 0;
+ f_status_t result = F_none;
+
+ // @todo: these are put drafted implementations, what needs to be done is consider the type as well (for example 'today' would allow anything at all in the day, this requires more complicated logic than what is below (break this into separte functions to simplify).
+ for (; p < 3; ++p) {
+
+ for (i = 0; i < dates[p]->used; ++i) {
+
+ name_type = f_string_empty_s;
+ result = F_none;
+
+ if (dates[p]->array[i].operation == kt_remove_flag_date_equal_e) {
+ if (times[p].tv_sec == dates[p]->array[i].seconds && times[p].tv_nsec == dates[p]->array[i].nanoseconds) {
+ name_type = kt_remove_date_symbol_equal_s;
+ result = F_true;
+ }
+ else {
+ result = F_false;
+ }
+ }
+ else if (dates[p]->array[i].operation == kt_remove_flag_date_less_e) {
+ if (times[p].tv_sec < dates[p]->array[i].seconds) {
+ name_type = kt_remove_date_symbol_less_s;
+ result = F_true;
+ }
+ else if (times[p].tv_sec == dates[p]->array[i].seconds && times[p].tv_nsec < dates[p]->array[i].nanoseconds) {
+ name_type = kt_remove_date_symbol_less_s;
+ result = F_true;
+ }
+ else {
+ result = F_false;
+ }
+ }
+ else if (dates[p]->array[i].operation == kt_remove_flag_date_less_equal_e) {
+ if (times[p].tv_sec < dates[p]->array[i].seconds) {
+ name_type = kt_remove_date_symbol_less_equal_s;
+ result = F_true;
+ }
+ else if (times[p].tv_sec == dates[p]->array[i].seconds && times[p].tv_nsec <= dates[p]->array[i].nanoseconds) {
+ name_type = kt_remove_date_symbol_less_equal_s;
+ result = F_true;
+ }
+ else {
+ result = F_false;
+ }
+ }
+ else if (dates[p]->array[i].operation == kt_remove_flag_date_more_e) {
+ if (times[p].tv_sec > dates[p]->array[i].seconds) {
+ name_type = kt_remove_date_symbol_more_s;
+ result = F_true;
+ }
+ else if (times[p].tv_sec == dates[p]->array[i].seconds && times[p].tv_nsec > dates[p]->array[i].nanoseconds) {
+ name_type = kt_remove_date_symbol_more_s;
+ result = F_true;
+ }
+ else {
+ result = F_false;
+ }
+ }
+ else if (dates[p]->array[i].operation == kt_remove_flag_date_more_equal_e) {
+ if (times[p].tv_sec > dates[p]->array[i].seconds) {
+ name_type = kt_remove_date_symbol_more_equal_s;
+ result = F_true;
+ }
+ else if (times[p].tv_sec == dates[p]->array[i].seconds && times[p].tv_nsec >= dates[p]->array[i].nanoseconds) {
+ name_type = kt_remove_date_symbol_more_equal_s;
+ result = F_true;
+ }
+ else {
+ result = F_false;
+ }
+ }
+ else if (dates[p]->array[i].operation == kt_remove_flag_date_not_e) {
+ if (times[p].tv_sec != dates[p]->array[i].seconds || times[p].tv_nsec != dates[p]->array[i].nanoseconds) {
+ name_type = kt_remove_date_symbol_not_s;
+ result = F_true;
+ }
+ else {
+ result = F_false;
+ }
+ }
+
+ if (name_type.used) {
+ fll_print_format(" %Q %Q ", main->output.to.stream, *names[p], result ? kt_remove_yes_s : kt_remove_no_s);
+ fll_print_format("%u::%un 0:%un %Q ", main->output.to.stream, kt_remove_time_year_unix_epoch_d, (f_number_unsigned_t) times[p].tv_sec, (f_number_unsigned_t) times[p].tv_nsec, name_type);
+ fll_print_format("%u::%un 0:%un%r", main->output.to.stream, kt_remove_time_year_unix_epoch_d, dates[p]->array[i].seconds, dates[p]->array[i].nanoseconds, f_string_eol_s);
+
+ break;
+ }
+ } // for
+ } // for
+ }
+ }
+#endif // _di_kt_remove_simulate_operate_file_stat_
+
+#ifndef _di_kt_remove_simulate_operate_remove_force_yes_
+ void kt_remove_simulate_operate_remove_force_yes(fll_program_data_t * const main, kt_remove_setting_t * const setting) {
+
+ if (!(setting->flag & kt_remove_flag_simulate_e)) return;
+
+ fll_print_format(" force yes%r", main->output.to.stream, f_string_eol_s);
+ }
+#endif // _di_kt_remove_simulate_operate_remove_force_yes_
+
+#ifndef _di_kt_remove_simulate_operate_remove_force_no_
+ void kt_remove_simulate_operate_remove_force_no(fll_program_data_t * const main, kt_remove_setting_t * const setting) {
+
+ if (!(setting->flag & kt_remove_flag_simulate_e)) return;
+
+ fll_print_format(" force no%r", main->output.to.stream, f_string_eol_s);
+ }
+#endif // _di_kt_remove_simulate_operate_remove_force_no_
+
+#ifndef _di_kt_remove_simulate_operate_remove_yes_
+ void kt_remove_simulate_operate_remove_yes(fll_program_data_t * const main, kt_remove_setting_t * const setting) {
+
+ if (!(setting->flag & kt_remove_flag_simulate_e)) return;
+
+ fll_print_format(" remove yes%r", main->output.to.stream, f_string_eol_s);
+ }
+#endif // _di_kt_remove_simulate_operate_remove_yes_
+
+#ifndef _di_kt_remove_simulate_operate_remove_no_
+ void kt_remove_simulate_operate_remove_no(fll_program_data_t * const main, kt_remove_setting_t * const setting) {
+
+ if (!(setting->flag & kt_remove_flag_simulate_e)) return;
+
+ fll_print_format(" remove no%r", main->output.to.stream, f_string_eol_s);
+ }
+#endif // _di_kt_remove_simulate_operate_remove_no_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * Kevux Tools - Remove
+ *
+ * Project: Kevux Tools
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ */
+#ifndef _kt_remove_simulate_h
+#define _kt_remove_simulate_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Simulate operate.
+ *
+ * This does nothing if the simulate flag (kt_remove_flag_simulate_e) is not set.
+ *
+ * @param main
+ * The main program data.
+ * @param setting
+ * The main program settings.
+ *
+ * This does not alter setting.status.
+ */
+#ifndef _di_kt_remove_simulate_operate_
+ extern void kt_remove_simulate_operate(fll_program_data_t * const main, kt_remove_setting_t * const setting);
+#endif // _di_kt_remove_simulate_operate_
+
+/**
+ * Simulate operate on a single file.
+ *
+ * This does nothing if the simulate flag (kt_remove_flag_simulate_e) is not set.
+ *
+ * @param main
+ * The main program data.
+ * @param setting
+ * The main program settings.
+ *
+ * This does not alter setting.status.
+ * @param path
+ * The path to the file to operate on.
+ */
+#ifndef _di_kt_remove_simulate_operate_file_
+ extern void kt_remove_simulate_operate_file(fll_program_data_t * const main, kt_remove_setting_t * const setting, const f_string_static_t path);
+#endif // _di_kt_remove_simulate_operate_file_
+
+/**
+ * Simulate operate on a single file, processing file existence.
+ *
+ * This does nothing if the simulate flag (kt_remove_flag_simulate_e) is not set.
+ *
+ * @param main
+ * The main program data.
+ * @param setting
+ * The main program settings.
+ *
+ * This does not alter setting.status.
+ * @param path
+ * The path to the file to operate on.
+ */
+#ifndef _di_kt_remove_simulate_operate_file_exists_
+ extern void kt_remove_simulate_operate_file_exists(fll_program_data_t * const main, kt_remove_setting_t * const setting, const f_string_static_t path);
+#endif // _di_kt_remove_simulate_operate_file_exists_
+
+/**
+ * Simulate operate on a single file, processing file statistics.
+ *
+ * This does nothing if the simulate flag (kt_remove_flag_simulate_e) is not set.
+ *
+ * @param main
+ * The main program data.
+ * @param setting
+ * The main program settings.
+ *
+ * This does not alter setting.status.
+ * @param statistics
+ * The file statistics.
+ */
+#ifndef _di_kt_remove_simulate_operate_file_stat_
+ extern void kt_remove_simulate_operate_file_stat(fll_program_data_t * const main, kt_remove_setting_t * const setting, struct stat statistics);
+#endif // _di_kt_remove_simulate_operate_file_stat_
+
+/**
+ * Simulate operate on a single file, designate that file is forcibly to be removed.
+ *
+ * This does nothing if the simulate flag (kt_remove_flag_simulate_e) is not set.
+ *
+ * @param main
+ * The main program data.
+ * @param setting
+ * The main program settings.
+ *
+ * This does not alter setting.status.
+ */
+#ifndef _di_kt_remove_simulate_operate_remove_force_yes_
+ extern void kt_remove_simulate_operate_remove_force_yes(fll_program_data_t * const main, kt_remove_setting_t * const setting);
+#endif // _di_kt_remove_simulate_operate_remove_force_yes_
+
+/**
+ * Simulate operate on a single file, designate that file is not forcibly to be removed.
+ *
+ * This does nothing if the simulate flag (kt_remove_flag_simulate_e) is not set.
+ *
+ * @param main
+ * The main program data.
+ * @param setting
+ * The main program settings.
+ *
+ * This does not alter setting.status.
+ */
+#ifndef _di_kt_remove_simulate_operate_remove_force_no_
+ extern void kt_remove_simulate_operate_remove_force_no(fll_program_data_t * const main, kt_remove_setting_t * const setting);
+#endif // _di_kt_remove_simulate_operate_remove_force_no_
+
+/**
+ * Simulate operate on a single file, designate that file is to be removed.
+ *
+ * This does nothing if the simulate flag (kt_remove_flag_simulate_e) is not set.
+ *
+ * @param main
+ * The main program data.
+ * @param setting
+ * The main program settings.
+ *
+ * This does not alter setting.status.
+ */
+#ifndef _di_kt_remove_simulate_operate_remove_yes_
+ extern void kt_remove_simulate_operate_remove_yes(fll_program_data_t * const main, kt_remove_setting_t * const setting);
+#endif // _di_kt_remove_simulate_operate_remove_yes_
+
+/**
+ * Simulate operate on a single file, designate that file is not to be removed.
+ *
+ * This does nothing if the simulate flag (kt_remove_flag_simulate_e) is not set.
+ *
+ * @param main
+ * The main program data.
+ * @param setting
+ * The main program settings.
+ *
+ * This does not alter setting.status.
+ */
+#ifndef _di_kt_remove_simulate_operate_remove_no_
+ extern void kt_remove_simulate_operate_remove_no(fll_program_data_t * const main, kt_remove_setting_t * const setting);
+#endif // _di_kt_remove_simulate_operate_remove_no_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_remove_simulate_h
--- /dev/null
+#include "remove.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_kt_remove_thread_signal_
+ void * kt_remove_thread_signal(void * const arguments) {
+
+ f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
+
+ kt_remove_signal_handler(macro_kt_remove_arguments(arguments)->main, macro_kt_remove_arguments(arguments)->setting);
+
+ return 0;
+ }
+#endif // _di_kt_remove_thread_signal_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * Kevux Tools - Remove
+ *
+ * Project: Kevux Tools
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ */
+#ifndef _kt_remove_thread_h
+#define _kt_remove_thread_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Thread handler for signals/interrupts.
+ *
+ * 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
+ *
+ * @param arguments
+ * The thread arguments.
+ * Must be of type kt_remove_arguments_t.
+ *
+ * @return
+ * 0, always.
+ *
+ * @see f_signal_mask()
+ * @see f_signal_wait()
+ */
+#if !defined(_di_kt_remove_thread_signal_) && !defined(_di_thread_support_)
+ extern void * kt_remove_thread_signal(void * const arguments);
+#endif // !defined(_di_kt_remove_thread_signal_) && !defined(_di_thread_support_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _kt_remove_thread_h
--- /dev/null
+# fss-0002 iki-0000
+#
+# license: open-standard-license-1.0
+#
+# This file (assumed to be named time.txt) can be more easily read using the following iki_read commands:
+# iki_read time.txt +Q -r UTC UTC -w -WW character "'" "'" code '"' '"'
+#
+# To read the "Time Specification" section of this file, use this command sequence:
+# fss_basic_list_read time.txt +Q -cn "Time Specification" | iki_read +Q -r UTC UTC -w -WW character "'" "'" code '"' '"'
+#
+
+Time Specification:
+ There are two units of bold:"Time", the first is simply called bold:"Time" and the second is called bold:"EpochTime".
+
+ Both bold:"Time" and bold:"EpochTime" are measured without the year but may contain a year to designate the point in the counting begins.
+ These are both represented by a single 64-bit (unsigned) integer.
+ The default timezone is always UTC:"Coordinated Universal Time".
+
+ The common form is intended as the non-technical form that is form common use.
+ This may have a negative value or be more than 64-bit digits long.
+ This is simply not expected to be interpreted as a unit of time on a computer (but nothing stops it from being interpreted).
+
+ The technical forms are limit to 64-bit unsigned for technical use but should technology advance to a point where larger bits are needed then this allows for that.
+ The systems should expect 64-bit and larger bits would have to become common before something larger than 64-bit is the expected or assumed default.
+ Negative signs can be allowed but they must not prevent the full use of the 64-bit.
+ The implementation of how this is done is left to the implementer except that the signs are immediately to the left of the digit.
+ For example code:"2022:-5" would be 5 units after the start of the year 2022.
+ Because the negative is allowed, so must the positive character (such as code:"2022:+5").
+ A positive value is the default interpretation when no sign is valid.
+
+ The unit of time called bold:"Time" is counted increments of a nanosecond, or 10^-9 seconds.
+ A unit of bold:"Time" is, therefore, equivalent to a nanosecond.
+ The default year for bold:"Time" is the current year.
+
+ The unit of time called bold:"EpochTime" is counted increments of a second, or 10^-9 seconds.
+ A unit of bold:"EpochTime" is, therefore, equivalent to a second.
+ The default year for bold:"EpochTime" is the bold:"UNIX Epoch", sometimes called bold:"Unix time".
+
+ The unit bold:"Time" has two technical forms and one common form, with the year and without the year.
+
+ Key\:
+ code:"\s" = White space.
+ code:"\d" = The digits used to represent time (a digit).
+ code:"*" = Zero or more occurrences.
+ code:"+" = One or more occurrences.
+ code:":" = A single colon character:":" (unicode:"U+003A").
+ code:'"' = A single double-quote character:'"' (unicode:"U+003A").
+
+ The common form of bold:"Time"\:
+
+ Before Structure\:
+ code:"".
+
+ Structure\:
+ code:"\s*\d+\s*\U*\s*".
+
+ After Structure\:
+ code:"".
+
+ Example\:
+ code:"86400".
+ code:"86400 T".
+ code:"86400 Time".
+
+ The first technical form of bold:"Time"\:
+
+ Before Structure\:
+ code:"".
+
+ Structure\:
+ code:"\s*\d+:\d+\s*\U*\s*".
+
+ After Structure\:
+ code:"".
+
+ Example\:
+ code:"2022:86400".
+ code:"2022:86400 T".
+ code:"2022:86400 Time".
+ code:"2022:86400 MT".
+ code:"2022:86400 MegaTime".
+
+ The second technical form of bold:"Time"\:
+
+ Before Structure\:
+ code:"".
+
+ Structure\:
+ code:"\s*:\d+\s*\U*\s*".
+
+ After Structure\:
+ code:"".
+
+ Example\:
+ code:":86400".
+ code:":86400 T".
+ code:":86400 Time".
+ code:":86400 MT".
+ code:":86400 MegaTime".
+
+ The unit bold:"EpochTime" has two technical forms and one common form, with the year and without the year.
+
+ The common form of bold:"Time"\:
+
+ Before Structure\:
+ code:"".
+
+ Structure\:
+ code:"\s*\d+\s*\U*\s*".
+
+ After Structure\:
+ code:"".
+
+ Example\:
+ code:"86400".
+ code:"86400 ET".
+ code:"86400 EpochTime".
+ code:"86400 MET".
+ code:"86400 MegaEpochTime".
+
+ The first technical form of bold:"EpochTime"\:
+
+ Before Structure\:
+ code:"".
+
+ Structure\:
+ code:"\s*\d+::\d+\s*\U*\s*".
+
+ After Structure\:
+ code:"".
+
+ Example\:
+ code:"2022::86400".
+ code:"2022::86400 ET".
+ code:"2022::86400 EpochTime".
+ code:"2022::86400 MET".
+ code:"2022::86400 MegaEpochTime".
+
+ The second technical form of bold:"Time"\:
+
+ Before Structure\:
+ code:"".
+
+ Structure\:
+ code:"\s*:\d+\s*\U*\s*".
+
+ After Structure\:
+ code:"".
+
+ Example\:
+ code:"::86400".
+ code:"::86400 ET".
+ code:"::86400 EpochTime".
+ code:"::86400 MET".
+ code:"::86400 MegaEpochTime".