From d8c9028de72c577f413730cc6b18370349456a09 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Wed, 22 Jul 2020 20:57:02 -0500 Subject: [PATCH] Update: provide fll_path and fl_environment while providing an alternative to f_path_real. The realpath() function does not work on non-existent paths. Provide an alternative, fll_path_canonical(), that works on paths without concern for some paths existence. The f_environment_path* functions need f_path, so move them to a new fl_environment project. --- build/level_1/settings | 4 +- build/level_2/settings | 4 +- build/monolithic/settings | 4 +- build/scripts/bootstrap-example.sh | 2 +- level_0/f_environment/c/environment.c | 342 ------------------------ level_0/f_environment/c/environment.h | 100 ------- level_0/f_path/c/path.h | 8 +- level_1/fl_environment/c/environment.c | 351 +++++++++++++++++++++++++ level_1/fl_environment/c/environment.h | 132 ++++++++++ level_1/fl_environment/data/build/defines | 2 + level_1/fl_environment/data/build/dependencies | 9 + level_1/fl_environment/data/build/settings | 52 ++++ level_2/fll_execute/c/execute.c | 2 +- level_2/fll_execute/c/execute.h | 1 + level_2/fll_execute/data/build/dependencies | 1 + level_2/fll_execute/data/build/settings | 2 +- level_2/fll_path/c/path.c | 140 ++++++++++ level_2/fll_path/c/path.h | 57 ++++ level_2/fll_path/data/build/defines | 2 + level_2/fll_path/data/build/dependencies | 8 + level_2/fll_path/data/build/settings | 52 ++++ level_3/fake/c/fake.h | 1 + level_3/fake/c/private-make.c | 33 ++- level_3/fake/c/private-make.h | 6 +- level_3/fake/data/build/dependencies | 1 + level_3/fake/data/build/settings | 2 +- 26 files changed, 854 insertions(+), 464 deletions(-) create mode 100644 level_1/fl_environment/c/environment.c create mode 100644 level_1/fl_environment/c/environment.h create mode 100644 level_1/fl_environment/data/build/defines create mode 100644 level_1/fl_environment/data/build/dependencies create mode 100644 level_1/fl_environment/data/build/settings create mode 100644 level_2/fll_path/c/path.c create mode 100644 level_2/fll_path/c/path.h create mode 100644 level_2/fll_path/data/build/defines create mode 100644 level_2/fll_path/data/build/dependencies create mode 100644 level_2/fll_path/data/build/settings diff --git a/build/level_1/settings b/build/level_1/settings index f62e845..dfda425 100644 --- a/build/level_1/settings +++ b/build/level_1/settings @@ -20,9 +20,9 @@ build_language c build_linker ar build_libraries -lc build_libraries-level -lfll_0 -build_sources_library color.c console.c conversion.c directory.c private-directory.c private-fss.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c iki.c print.c status.c string.c private-string.c utf.c private-utf.c utf_file.c private-utf_file.c +build_sources_library color.c console.c conversion.c directory.c private-directory.c environment.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c private-fss.c iki.c print.c status.c string.c private-string.c utf.c private-utf.c utf_file.c private-utf_file.c build_sources_program -build_sources_headers color.h console.h conversion.h directory.h fss.h fss_basic.h fss_basic_list.h fss_extended.h fss_extended_list.h fss_macro.h fss_status.h iki.h print.h status.h string.h utf.h utf_file.h +build_sources_headers color.h console.h conversion.h directory.h environment.h fss.h fss_basic.h fss_basic_list.h fss_extended.h fss_extended_list.h fss_macro.h fss_status.h iki.h print.h status.h string.h utf.h utf_file.h build_sources_script build_sources_setting build_script yes diff --git a/build/level_2/settings b/build/level_2/settings index a77c00c..6c3f83c 100644 --- a/build/level_2/settings +++ b/build/level_2/settings @@ -20,9 +20,9 @@ build_language c build_linker ar build_libraries -lc build_libraries-level -lfll_1 -lfll_0 -build_sources_library execute.c private-execute.c file.c fss.c private-fss.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c fss_status.c program.c status.c +build_sources_library execute.c private-execute.c file.c fss.c private-fss.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c fss_status.c path.c program.c status.c build_sources_program -build_sources_headers execute.h file.h fss.h fss_basic.h fss_basic_list.h fss_extended.h fss_extended_list.h fss_status.h program.h status.h +build_sources_headers execute.h file.h fss.h fss_basic.h fss_basic_list.h fss_extended.h fss_extended_list.h fss_status.h path.c program.h status.h build_sources_script build_sources_setting build_script yes diff --git a/build/monolithic/settings b/build/monolithic/settings index 94c8196..06c63be 100644 --- a/build/monolithic/settings +++ b/build/monolithic/settings @@ -20,9 +20,9 @@ build_language c build_linker ar build_libraries -lc build_libraries-monolithic -build_sources_library level_0/console.c level_0/conversion.c level_0/directory.c level_0/private-directory.c level_0/environment.c level_0/private-environment.c level_0/file.c level_0/private-file.c level_0/fss.c level_0/iki.c level_0/memory.c level_0/path.c level_0/private-path.c level_0/pipe.c level_0/print.c level_0/serialize.c level_0/private-serialize.c level_0/socket.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/conversion.c level_1/directory.c level_1/private-directory.c level_1/private-fss.c level_1/fss_basic.c level_1/fss_basic_list.c level_1/fss_extended.c level_1/fss_extended_list.c level_1/iki.c level_1/print.c level_1/status.c level_1/string.c level_1/private-string.c level_1/utf.c level_1/private-utf.c level_1/utf_file.c level_1/private-utf_file.c level_2/execute.c level_2/private-execute.c level_2/file.c level_2/fss.c level_2/private-fss.c level_2/fss_basic.c level_2/fss_basic_list.c level_2/fss_extended.c level_2/fss_extended_list.c level_2/fss_status.c level_2/program.c level_2/status.c +build_sources_library level_0/console.c level_0/conversion.c level_0/directory.c level_0/private-directory.c level_0/environment.c level_0/private-environment.c level_0/file.c level_0/private-file.c level_0/fss.c level_0/iki.c level_0/memory.c level_0/path.c level_0/private-path.c level_0/pipe.c level_0/print.c level_0/serialize.c level_0/private-serialize.c level_0/socket.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/conversion.c level_1/directory.c level_1/private-directory.c level_1/private-fss.c level_1/environment.c level_1/fss_basic.c level_1/fss_basic_list.c level_1/fss_extended.c level_1/fss_extended_list.c level_1/iki.c level_1/print.c level_1/status.c level_1/string.c level_1/private-string.c level_1/utf.c level_1/private-utf.c level_1/utf_file.c level_1/private-utf_file.c level_2/execute.c level_2/private-execute.c level_2/file.c level_2/fss.c level_2/private-fss.c level_2/fss_basic.c level_2/fss_basic_list.c level_2/fss_extended.c level_2/fss_extended_list.c level_2/fss_status.c level_2/path.c level_2/program.c level_2/status.c build_sources_program -build_sources_headers level_0/color.h level_0/console.h level_0/conversion.h level_0/directory.h level_0/directory_type.h level_0/environment.h level_0/file.h level_0/fss.h level_0/fss-common.h level_0/fss-named.h level_0/fss-nest.h level_0/fss-quoted.h level_0/fss-set.h level_0/iki.h level_0/iki-common.h level_0/memory.h level_0/memory-structure.h level_0/path.h level_0/pipe.h level_0/print.h level_0/serialize.h level_0/socket.h level_0/status.h level_0/status_array.h level_0/string.h level_0/string_common.h level_0/string_dynamic.h level_0/string_map.h level_0/string_quantity.h level_0/string_range.h level_0/type.h level_0/type_array.h level_0/utf.h level_0/utf-common.h level_1/color.h level_1/console.h level_1/conversion.h level_1/directory.h level_1/fss.h level_1/fss_basic.h level_1/fss_basic_list.h level_1/fss_extended.h level_1/fss_extended_list.h level_1/fss_macro.h level_1/fss_status.h level_1/iki.h level_1/print.h level_1/status.h level_1/string.h level_1/utf.h level_1/utf_file.h level_2/execute.h level_2/file.h level_2/fss.h level_2/fss_basic.h level_2/fss_basic_list.h level_2/fss_extended.h level_2/fss_extended_list.h level_2/fss_status.h level_2/program.h level_2/status.h +build_sources_headers level_0/color.h level_0/console.h level_0/conversion.h level_0/directory.h level_0/directory_type.h level_0/environment.h level_0/file.h level_0/fss.h level_0/fss-common.h level_0/fss-named.h level_0/fss-nest.h level_0/fss-quoted.h level_0/fss-set.h level_0/iki.h level_0/iki-common.h level_0/memory.h level_0/memory-structure.h level_0/path.h level_0/pipe.h level_0/print.h level_0/serialize.h level_0/socket.h level_0/status.h level_0/status_array.h level_0/string.h level_0/string_common.h level_0/string_dynamic.h level_0/string_map.h level_0/string_quantity.h level_0/string_range.h level_0/type.h level_0/type_array.h level_0/utf.h level_0/utf-common.h level_1/color.h level_1/console.h level_1/conversion.h level_1/directory.h level_1/environment.h level_1/fss.h level_1/fss_basic.h level_1/fss_basic_list.h level_1/fss_extended.h level_1/fss_extended_list.h level_1/fss_macro.h level_1/fss_status.h level_1/iki.h level_1/print.h level_1/status.h level_1/string.h level_1/utf.h level_1/utf_file.h level_2/execute.h level_2/file.h level_2/fss.h level_2/fss_basic.h level_2/fss_basic_list.h level_2/fss_extended.h level_2/fss_extended_list.h level_2/fss_status.h level_2/path.h level_2/program.h level_2/status.h build_sources_script build_sources_setting build_script yes diff --git a/build/scripts/bootstrap-example.sh b/build/scripts/bootstrap-example.sh index abd4f96..7b66ff1 100644 --- a/build/scripts/bootstrap-example.sh +++ b/build/scripts/bootstrap-example.sh @@ -23,7 +23,7 @@ if [[ $1 == "individual" ]] ; then bash build/scripts/package.sh build -i if [[ $? -eq 0 ]] ; then - for i in f_type f_status f_memory f_string f_utf f_color f_console f_conversion f_directory f_environment f_file f_fss f_iki f_path f_pipe f_print f_serialize f_socket fl_color fl_console fl_conversion fl_directory fl_fss fl_iki fl_print fl_status fl_string fl_utf fl_utf_file fll_execute fll_file fll_fss fll_program fll_status ; do + for i in f_type f_status f_memory f_string f_utf f_color f_console f_conversion f_directory f_environment f_file f_fss f_iki f_path f_pipe f_print f_serialize f_socket fl_color fl_console fl_conversion fl_directory fl_environment fl_fss fl_iki fl_print fl_status fl_string fl_utf fl_utf_file fll_execute fll_file fll_fss fll_path fll_program fll_status ; do echo && echo "Processing $i." && cd package/individual/$i-$2/ && diff --git a/level_0/f_environment/c/environment.c b/level_0/f_environment/c/environment.c index 2bc1522..ccca086 100644 --- a/level_0/f_environment/c/environment.c +++ b/level_0/f_environment/c/environment.c @@ -43,348 +43,6 @@ extern "C" { } #endif // _di_f_environment_get_dynamic_ -#ifndef _di_f_environment_path_explode_ - f_return_status f_environment_path_explode(const f_string path, f_string_dynamics *paths) { - #ifndef _di_level_0_parameter_checking_ - if (paths == 0) return F_status_set_error(F_parameter); - if (paths->used > paths->size) return F_status_set_error(F_parameter); - #endif // _di_level_0_parameter_checking_ - - f_status status = F_none; - const f_string_length length = strnlen(path, PATH_MAX); - - if (length == 0) { - // When PATH is "", this is actually a valid search path for PWD. - // Therefore append an equivalent representation of PWD (string used length is 0). - f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); - if (F_status_is_error(status)) return status; - - f_macro_string_dynamic_clear(paths->array[paths->used]); - paths->used++; - - return F_none; - } - - f_string_length i = length; - f_string_length first = 0; - f_string_length total = 0; - - for (i = 0; i <= length; i++) { - if (i == length || path[i] == f_path_separator_variable[0]) { - f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); - if (F_status_is_error(status)) return status; - - if (i == 0) { - f_macro_string_dynamic_clear(paths->array[paths->used]); - paths->used++; - - first = 1; - continue; - } - - f_string_dynamic part = f_string_dynamic_initialize; - - total = i - first; - - if (total > 0) { - if (path[i - 1] == f_path_separator[0]) { - f_macro_string_dynamic_new(status, part, total); - if (F_status_is_error(status)) return status; - - part.used = total; - } - else { - f_macro_string_dynamic_new(status, part, total + 1); - if (F_status_is_error(status)) return status; - - part.string[total] = f_path_separator[0]; - part.used = total + 1; - } - - memcpy(part.string, path + first, total); - } - - paths->array[paths->used].string = part.string; - paths->array[paths->used].used = part.used; - paths->array[paths->used].size = part.size; - paths->used++; - - first = i + 1; - } - } // for - - return F_none; - } -#endif // _di_f_environment_path_explode_ - -#ifndef _di_f_environment_path_explode_dynamic_ - f_return_status f_environment_path_explode_dynamic(const f_string_static path, f_string_dynamics *paths) { - #ifndef _di_level_0_parameter_checking_ - if (path.used > path.size) return F_status_set_error(F_parameter); - if (paths == 0) return F_status_set_error(F_parameter); - if (paths->used > paths->size) return F_status_set_error(F_parameter); - #endif // _di_level_0_parameter_checking_ - - f_status status = F_none; - - if (path.used == 0) { - // When PATH is "", this is actually a valid search path for PWD. - // Therefore append an equivalent representation of PWD (string used length is 0). - f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); - if (F_status_is_error(status)) return status; - - f_macro_string_dynamic_clear(paths->array[paths->used]); - paths->used++; - - return F_none; - } - - f_string_length i = 0; - f_string_length j = 0; - f_string_length first = 0; - f_string_length total = 0; - - f_string_dynamic part = f_string_dynamic_initialize; - - for (i = 0; i <= path.used; i++) { - if (i == path.used || path.string[i] == f_path_separator_variable[0]) { - f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); - if (F_status_is_error(status)) return status; - - if (i == 0) { - f_macro_string_dynamic_clear(paths->array[paths->used]); - paths->used++; - - first = 1; - continue; - } - - total = i - first; - - if (total > 0) { - f_macro_string_dynamic_new(status, part, total); - if (F_status_is_error(status)) return status; - - for (j = 0; j < total; j++) { - if (path.string[first + j] == 0) continue; - - part.string[part.used] = path.string[first + j]; - part.used++; - } // for - - if (part.string[part.used - 1] != f_path_separator[0]) { - f_macro_string_dynamic_resize(status, part, total + 1); - if (F_status_is_error(status)) return status; - - part.string[part.used] = f_path_separator[0]; - part.used++; - } - } - - paths->array[paths->used].string = part.string; - paths->array[paths->used].used = part.used; - paths->array[paths->used].size = part.size; - paths->used++; - - first = i + 1; - } - } // for - - return F_none; - } -#endif // _di_f_environment_path_explode_dynamic_ - -#ifndef _di_f_environment_path_explode_reverse_ - f_return_status f_environment_path_explode_reverse(const f_string path, f_string_dynamics *paths) { - #ifndef _di_level_0_parameter_checking_ - if (paths == 0) return F_status_set_error(F_parameter); - if (paths->used > paths->size) return F_status_set_error(F_parameter); - #endif // _di_level_0_parameter_checking_ - - f_status status = F_none; - const f_string_length length = strnlen(path, PATH_MAX); - - if (length == 0) { - // When PATH is "", this is actually a valid search path for PWD. - // Therefore append an equivalent representation of PWD (string used length is 0). - f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); - if (F_status_is_error(status)) return status; - - paths->array[paths->used].string = 0; - paths->array[paths->used].used = 0; - paths->array[paths->used].size = 0; - paths->used++; - - return F_none; - } - - f_string_length i = length; - f_string_length j = length; - f_string_length last = length; - f_string_length total = 0; - - f_string_dynamic part = f_string_dynamic_initialize; - - for (; i > 0; i--) { - j--; - - if (j == 0 || path[j] == f_path_separator_variable[0]) { - f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); - if (F_status_is_error(status)) return status; - - if (path[j] == f_path_separator_variable[0]) { - total = last - i; - - if (total > 0) { - if (path[j + total] == f_path_separator[0]) { - f_macro_string_dynamic_new(status, part, total); - if (F_status_is_error(status)) return status; - - part.used = total; - } - else { - f_macro_string_dynamic_new(status, part, total + 1); - if (F_status_is_error(status)) return status; - - part.string[total] = f_path_separator[0]; - part.used = total + 1; - } - - memcpy(part.string, path + i, total); - } - - last = j; - } - else if (j == 0) { - // when j = 0, the total is actually the entire length to max. - total = last - j; - - if (total > 0) { - if (path[last - 1] == f_path_separator[0]) { - f_macro_string_dynamic_new(status, part, total); - if (F_status_is_error(status)) return status; - - part.used = total; - } - else { - f_macro_string_dynamic_new(status, part, total + 1); - if (F_status_is_error(status)) return status; - - part.used = total + 1; - part.string[total] = f_path_separator[0]; - } - - memcpy(part.string, path, total); - } - } - - paths->array[paths->used].string = part.string; - paths->array[paths->used].used = part.used; - paths->array[paths->used].size = part.size; - paths->used++; - } - } // for - - return F_none; - } -#endif // _di_f_environment_path_explode_reverse_ - -#ifndef _di_f_environment_path_explode_reverse_dynamic_ - f_return_status f_environment_path_explode_reverse_dynamic(const f_string_static path, f_string_dynamics *paths) { - #ifndef _di_level_0_parameter_checking_ - if (path.used > path.size) return F_status_set_error(F_parameter); - if (paths == 0) return F_status_set_error(F_parameter); - if (paths->used > paths->size) return F_status_set_error(F_parameter); - #endif // _di_level_0_parameter_checking_ - - f_status status = F_none; - - if (path.used == 0) { - // When PATH is "", this is actually a valid search path for PWD. - // Therefore append an equivalent representation of PWD (string used length is 0). - f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); - if (F_status_is_error(status)) return status; - - f_macro_string_dynamic_clear(paths->array[paths->used]); - paths->used++; - - return F_none; - } - - f_string_length i = path.used; - f_string_length j = path.used; - f_string_length k = 0; - f_string_length last = path.used; - f_string_length total = 0; - - f_string_dynamic part = f_string_dynamic_initialize; - - for (; i > 0; i--) { - j--; - - if (j == 0 || path.string[j] == f_path_separator_variable[0]) { - f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); - if (F_status_is_error(status)) return status; - - if (path.string[j] == f_path_separator_variable[0]) { - total = last - i; - - if (total > 0) { - f_macro_string_dynamic_new(status, part, total); - if (F_status_is_error(status)) return status; - - for (k = 0; k < total; k++) { - if (path.string[i + k] == 0) continue; - - part.string[part.used] = path.string[i + k]; - part.used++; - } // for - - if (part.string[part.used - 1] != f_path_separator[0]) { - f_macro_string_dynamic_resize(status, part, total + 1); - if (F_status_is_error(status)) return status; - - part.string[part.used] = f_path_separator[0]; - part.used++; - } - } - - last = j; - } - else if (j == 0) { - // when j = 0, the total is actually the entire length to max. - total = last - j; - - f_macro_string_dynamic_new(status, part, total); - if (F_status_is_error(status)) return status; - - for (k = 0; k < total; k++) { - if (path.string[i + k] == 0) continue; - - part.string[part.used] = path.string[i + k]; - part.used++; - } // for - - if (part.string[part.used - 1] != f_path_separator[0]) { - f_macro_string_dynamic_resize(status, part, total + 1); - if (F_status_is_error(status)) return status; - - part.string[part.used - 1] = f_path_separator[0]; - part.used++; - } - } - - paths->array[paths->used].string = part.string; - paths->array[paths->used].used = part.used; - paths->array[paths->used].size = part.size; - paths->used++; - } - } // for - - return F_none; - } -#endif // _di_f_environment_path_explode_reverse_dynamic_ - #ifndef _di_f_environment_set_ f_return_status f_environment_set(const f_string name, const f_string value, const bool replace) { return private_f_environment_set(name, value, replace); diff --git a/level_0/f_environment/c/environment.h b/level_0/f_environment/c/environment.h index 19a10f8..be12382 100644 --- a/level_0/f_environment/c/environment.h +++ b/level_0/f_environment/c/environment.h @@ -99,106 +99,6 @@ extern "C" { #endif // _di_f_environment_get_dynamic_ /** - * Separate a given PATH-style string into multiple separate paths. - * - * @param path - * The string to process that is expected to follow the traditional Linux standard PATH environment variable. - * Each seperate path is separated by a single ':'. - * Must not contain NULLs except for the terminating NULL. - * Must be NULL terminated. - * @param paths - * All of the strings exploded from PATH. - * Each exploded path, when not empty, is guaranteed to have a trailing '/'. - * Each exploded path is not NULL terminated. - * - * @return - * F_none on success. - * F_buffer_too_large (with error bit) if paths array is too large for further addressing. - * F_memory_reallocation (with error bit) on reallocation error. - * F_memory_allocation (with error bit) on allocation error. - * F_parameter (with error bit) if a parameter is invalid. - */ -#ifndef _di_f_environment_path_explode_ - extern f_return_status f_environment_path_explode(const f_string path, f_string_dynamics *paths); -#endif // _di_f_environment_path_explode_ - -/** - * Separate a given PATH-style string into multiple separate paths. - * - * @param path - * The string to process that is expected to follow the traditional Linux standard PATH environment variable. - * Each seperate path is separated by a single ':'. - * Need not be NULL terminated. - * NULLs are ignored and are not copied into the exploded paths. - * @param paths - * All of the strings exploded from PATH. - * Each exploded path, when not empty, is guaranteed to have a trailing '/'. - * Each exploded path is not NULL terminated. - * - * @return - * F_none on success. - * F_buffer_too_large (with error bit) if paths array is too large for further addressing. - * F_memory_reallocation (with error bit) on reallocation error. - * F_memory_allocation (with error bit) on allocation error. - * F_parameter (with error bit) if a parameter is invalid. - */ -#ifndef _di_f_environment_path_explode_dynamic_ - extern f_return_status f_environment_path_explode_dynamic(const f_string_static path, f_string_dynamics *paths); -#endif // _di_f_environment_path_explode_dynamic_ - -/** - * Separate a given PATH-style string into multiple separate paths. - * - * The paths are created in reverse order. - * - * @param path - * The string to process that is expected to follow the traditional Linux standard PATH environment variable. - * Each seperate path is separated by a single ':'. - * Must not contain NULLs except for the terminating NULL. - * Must be NULL terminated. - * @param paths - * All of the strings exploded from PATH. - * Each exploded path, when not empty, is guaranteed to have a trailing '/'. - * Each exploded path is not NULL terminated. - * - * @return - * F_none on success. - * F_buffer_too_large (with error bit) if paths array is too large for further addressing. - * F_memory_reallocation (with error bit) on reallocation error. - * F_memory_allocation (with error bit) on allocation error. - * F_parameter (with error bit) if a parameter is invalid. - */ -#ifndef _di_f_environment_path_explode_reverse_ - extern f_return_status f_environment_path_explode_reverse(const f_string path, f_string_dynamics *paths); -#endif // _di_f_environment_path_explode_reverse_ - -/** - * Separate a given PATH-style string into multiple separate paths. - * - * The paths are created in reverse order. - * - * @param path - * The string to process that is expected to follow the traditional Linux standard PATH environment variable. - * Each seperate path is separated by a single ':'. - * Need not be NULL terminated. - * NULLs are ignored and are not copied into the exploded paths. - * @param paths - * All of the strings exploded from PATH. - * Each exploded path, when not empty, is guaranteed to have a trailing '/'. - * Each exploded path is not NULL terminated. - * - * @return - * F_none on success. - * F_buffer_too_large (with error bit) if paths array is too large for further addressing. - * F_memory_reallocation (with error bit) on reallocation error. - * F_memory_allocation (with error bit) on allocation error. - * F_parameter (with error bit) if a parameter is invalid. - */ -#ifndef _di_f_environment_path_explode_reverse_dynamic_ - extern f_return_status f_environment_path_explode_reverse_dynamic(const f_string_static path, f_string_dynamics *paths); -#endif // _di_f_environment_path_explode_reverse_dynamic_ - -/** * Assign the given value to the named environment variable. * * If the name does not exist, then it is created. diff --git a/level_0/f_path/c/path.h b/level_0/f_path/c/path.h index 5160fd7..1490d6b 100644 --- a/level_0/f_path/c/path.h +++ b/level_0/f_path/c/path.h @@ -146,12 +146,16 @@ extern "C" { #endif // _di_f_path_current_ /** - * Get the real path for some path. + * Get the real path for the given path. * - * All symbolic links and relative path parts are expanded to yield the real full path. + * This does check to see if the path exists or not (path must exist). + * This processes all relative parts. + * This processes all symbolic links. + * This has a max size of f_path_max + 1. * * @param path * The source path to determine what the real path is. + * This is a NULL terminated string. * @param real * The (allocated) real file path. * This will have a max size of f_path_max + 1. diff --git a/level_1/fl_environment/c/environment.c b/level_1/fl_environment/c/environment.c new file mode 100644 index 0000000..15430d9 --- /dev/null +++ b/level_1/fl_environment/c/environment.c @@ -0,0 +1,351 @@ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_fl_environment_path_explode_ + f_return_status fl_environment_path_explode(const f_string path, f_string_dynamics *paths) { + #ifndef _di_level_0_parameter_checking_ + if (paths == 0) return F_status_set_error(F_parameter); + if (paths->used > paths->size) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + f_status status = F_none; + const f_string_length length = strnlen(path, PATH_MAX); + + if (length == 0) { + // When PATH is "", this is actually a valid search path for PWD. + // Append an equivalent representation of PWD (string used length is 0). + f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); + if (F_status_is_error(status)) return status; + + f_macro_string_dynamic_clear(paths->array[paths->used]); + paths->used++; + + return F_none; + } + + f_string_length i = length; + f_string_length first = 0; + f_string_length total = 0; + + for (i = 0; i <= length; i++) { + if (i == length || path[i] == f_path_separator_variable[0]) { + f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); + if (F_status_is_error(status)) return status; + + if (i == 0) { + f_macro_string_dynamic_clear(paths->array[paths->used]); + paths->used++; + + first = 1; + continue; + } + + f_string_dynamic part = f_string_dynamic_initialize; + + total = i - first; + + if (total > 0) { + if (path[i - 1] == f_path_separator[0]) { + f_macro_string_dynamic_new(status, part, total); + if (F_status_is_error(status)) return status; + + part.used = total; + } + else { + f_macro_string_dynamic_new(status, part, total + 1); + if (F_status_is_error(status)) return status; + + part.string[total] = f_path_separator[0]; + part.used = total + 1; + } + + memcpy(part.string, path + first, total); + } + + paths->array[paths->used].string = part.string; + paths->array[paths->used].used = part.used; + paths->array[paths->used].size = part.size; + paths->used++; + + first = i + 1; + } + } // for + + return F_none; + } +#endif // _di_fl_environment_path_explode_ + +#ifndef _di_fl_environment_path_explode_dynamic_ + f_return_status fl_environment_path_explode_dynamic(const f_string_static path, f_string_dynamics *paths) { + #ifndef _di_level_0_parameter_checking_ + if (path.used > path.size) return F_status_set_error(F_parameter); + if (paths == 0) return F_status_set_error(F_parameter); + if (paths->used > paths->size) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + f_status status = F_none; + + if (path.used == 0) { + // When PATH is "", this is actually a valid search path for PWD. + // Therefore append an equivalent representation of PWD (string used length is 0). + f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); + if (F_status_is_error(status)) return status; + + f_macro_string_dynamic_clear(paths->array[paths->used]); + paths->used++; + + return F_none; + } + + f_string_length i = 0; + f_string_length j = 0; + f_string_length first = 0; + f_string_length total = 0; + + f_string_dynamic part = f_string_dynamic_initialize; + + for (i = 0; i <= path.used; i++) { + if (i == path.used || path.string[i] == f_path_separator_variable[0]) { + f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); + if (F_status_is_error(status)) return status; + + if (i == 0) { + f_macro_string_dynamic_clear(paths->array[paths->used]); + paths->used++; + + first = 1; + continue; + } + + total = i - first; + + if (total > 0) { + f_macro_string_dynamic_new(status, part, total); + if (F_status_is_error(status)) return status; + + for (j = 0; j < total; j++) { + if (path.string[first + j] == 0) continue; + + part.string[part.used] = path.string[first + j]; + part.used++; + } // for + + if (part.string[part.used - 1] != f_path_separator[0]) { + f_macro_string_dynamic_resize(status, part, total + 1); + if (F_status_is_error(status)) return status; + + part.string[part.used] = f_path_separator[0]; + part.used++; + } + } + + paths->array[paths->used].string = part.string; + paths->array[paths->used].used = part.used; + paths->array[paths->used].size = part.size; + paths->used++; + + first = i + 1; + } + } // for + + return F_none; + } +#endif // _di_fl_environment_path_explode_dynamic_ + +#ifndef _di_fl_environment_path_explode_reverse_ + f_return_status fl_environment_path_explode_reverse(const f_string path, f_string_dynamics *paths) { + #ifndef _di_level_0_parameter_checking_ + if (paths == 0) return F_status_set_error(F_parameter); + if (paths->used > paths->size) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + f_status status = F_none; + const f_string_length length = strnlen(path, PATH_MAX); + + if (length == 0) { + // When PATH is "", this is actually a valid search path for PWD. + // Therefore append an equivalent representation of PWD (string used length is 0). + f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); + if (F_status_is_error(status)) return status; + + paths->array[paths->used].string = 0; + paths->array[paths->used].used = 0; + paths->array[paths->used].size = 0; + paths->used++; + + return F_none; + } + + f_string_length i = length; + f_string_length j = length; + f_string_length last = length; + f_string_length total = 0; + + f_string_dynamic part = f_string_dynamic_initialize; + + for (; i > 0; i--) { + j--; + + if (j == 0 || path[j] == f_path_separator_variable[0]) { + f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); + if (F_status_is_error(status)) return status; + + if (path[j] == f_path_separator_variable[0]) { + total = last - i; + + if (total > 0) { + if (path[j + total] == f_path_separator[0]) { + f_macro_string_dynamic_new(status, part, total); + if (F_status_is_error(status)) return status; + + part.used = total; + } + else { + f_macro_string_dynamic_new(status, part, total + 1); + if (F_status_is_error(status)) return status; + + part.string[total] = f_path_separator[0]; + part.used = total + 1; + } + + memcpy(part.string, path + i, total); + } + + last = j; + } + else if (j == 0) { + // when j = 0, the total is actually the entire length to max. + total = last - j; + + if (total > 0) { + if (path[last - 1] == f_path_separator[0]) { + f_macro_string_dynamic_new(status, part, total); + if (F_status_is_error(status)) return status; + + part.used = total; + } + else { + f_macro_string_dynamic_new(status, part, total + 1); + if (F_status_is_error(status)) return status; + + part.used = total + 1; + part.string[total] = f_path_separator[0]; + } + + memcpy(part.string, path, total); + } + } + + paths->array[paths->used].string = part.string; + paths->array[paths->used].used = part.used; + paths->array[paths->used].size = part.size; + paths->used++; + } + } // for + + return F_none; + } +#endif // _di_fl_environment_path_explode_reverse_ + +#ifndef _di_fl_environment_path_explode_reverse_dynamic_ + f_return_status fl_environment_path_explode_reverse_dynamic(const f_string_static path, f_string_dynamics *paths) { + #ifndef _di_level_0_parameter_checking_ + if (path.used > path.size) return F_status_set_error(F_parameter); + if (paths == 0) return F_status_set_error(F_parameter); + if (paths->used > paths->size) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + f_status status = F_none; + + if (path.used == 0) { + // When PATH is "", this is actually a valid search path for PWD. + // Therefore append an equivalent representation of PWD (string used length is 0). + f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); + if (F_status_is_error(status)) return status; + + f_macro_string_dynamic_clear(paths->array[paths->used]); + paths->used++; + + return F_none; + } + + f_string_length i = path.used; + f_string_length j = path.used; + f_string_length k = 0; + f_string_length last = path.used; + f_string_length total = 0; + + f_string_dynamic part = f_string_dynamic_initialize; + + for (; i > 0; i--) { + j--; + + if (j == 0 || path.string[j] == f_path_separator_variable[0]) { + f_macro_memory_structure_macro_increment(status, (*paths), 1, f_memory_default_allocation_step, f_macro_string_dynamics_resize, F_buffer_too_large); + if (F_status_is_error(status)) return status; + + if (path.string[j] == f_path_separator_variable[0]) { + total = last - i; + + if (total > 0) { + f_macro_string_dynamic_new(status, part, total); + if (F_status_is_error(status)) return status; + + for (k = 0; k < total; k++) { + if (path.string[i + k] == 0) continue; + + part.string[part.used] = path.string[i + k]; + part.used++; + } // for + + if (part.string[part.used - 1] != f_path_separator[0]) { + f_macro_string_dynamic_resize(status, part, total + 1); + if (F_status_is_error(status)) return status; + + part.string[part.used] = f_path_separator[0]; + part.used++; + } + } + + last = j; + } + else if (j == 0) { + // when j = 0, the total is actually the entire length to max. + total = last - j; + + f_macro_string_dynamic_new(status, part, total); + if (F_status_is_error(status)) return status; + + for (k = 0; k < total; k++) { + if (path.string[i + k] == 0) continue; + + part.string[part.used] = path.string[i + k]; + part.used++; + } // for + + if (part.string[part.used - 1] != f_path_separator[0]) { + f_macro_string_dynamic_resize(status, part, total + 1); + if (F_status_is_error(status)) return status; + + part.string[part.used - 1] = f_path_separator[0]; + part.used++; + } + } + + paths->array[paths->used].string = part.string; + paths->array[paths->used].used = part.used; + paths->array[paths->used].size = part.size; + paths->used++; + } + } // for + + return F_none; + } +#endif // _di_fl_environment_path_explode_reverse_dynamic_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_1/fl_environment/c/environment.h b/level_1/fl_environment/c/environment.h new file mode 100644 index 0000000..c3e49b6 --- /dev/null +++ b/level_1/fl_environment/c/environment.h @@ -0,0 +1,132 @@ +/** + * FLL - Level 1 + * + * Project: Environment + * API Version: 0.5 + * Licenses: lgplv2.1 + * + * Provides environment processing functionality, such as environment variable handling. + */ +#ifndef _FL_environment_h +#define _FL_environment_h + +#include +#include + +// fll-0 includes +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Separate a given PATH-style string into multiple separate paths. + * + * @param path + * The string to process that is expected to follow the traditional Linux standard PATH environment variable. + * Each seperate path is separated by a single ':'. + * Must not contain NULLs except for the terminating NULL. + * Must be NULL terminated. + * @param paths + * All of the strings exploded from PATH. + * Each exploded path, when not empty, is guaranteed to have a trailing '/'. + * Each exploded path is not NULL terminated. + * + * @return + * F_none on success. + * F_buffer_too_large (with error bit) if paths array is too large for further addressing. + * F_memory_reallocation (with error bit) on reallocation error. + * F_memory_allocation (with error bit) on allocation error. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fl_environment_path_explode_ + extern f_return_status fl_environment_path_explode(const f_string path, f_string_dynamics *paths); +#endif // _di_fl_environment_path_explode_ + +/** + * Separate a given PATH-style string into multiple separate paths. + * + * @param path + * The string to process that is expected to follow the traditional Linux standard PATH environment variable. + * Each seperate path is separated by a single ':'. + * Need not be NULL terminated. + * NULLs are ignored and are not copied into the exploded paths. + * @param paths + * All of the strings exploded from PATH. + * Each exploded path, when not empty, is guaranteed to have a trailing '/'. + * Each exploded path is not NULL terminated. + * + * @return + * F_none on success. + * F_buffer_too_large (with error bit) if paths array is too large for further addressing. + * F_memory_reallocation (with error bit) on reallocation error. + * F_memory_allocation (with error bit) on allocation error. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fl_environment_path_explode_dynamic_ + extern f_return_status fl_environment_path_explode_dynamic(const f_string_static path, f_string_dynamics *paths); +#endif // _di_fl_environment_path_explode_dynamic_ + +/** + * Separate a given PATH-style string into multiple separate paths. + * + * The paths are created in reverse order. + * + * @param path + * The string to process that is expected to follow the traditional Linux standard PATH environment variable. + * Each seperate path is separated by a single ':'. + * Must not contain NULLs except for the terminating NULL. + * Must be NULL terminated. + * @param paths + * All of the strings exploded from PATH. + * Each exploded path, when not empty, is guaranteed to have a trailing '/'. + * Each exploded path is not NULL terminated. + * + * @return + * F_none on success. + * F_buffer_too_large (with error bit) if paths array is too large for further addressing. + * F_memory_reallocation (with error bit) on reallocation error. + * F_memory_allocation (with error bit) on allocation error. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fl_environment_path_explode_reverse_ + extern f_return_status fl_environment_path_explode_reverse(const f_string path, f_string_dynamics *paths); +#endif // _di_fl_environment_path_explode_reverse_ + +/** + * Separate a given PATH-style string into multiple separate paths. + * + * The paths are created in reverse order. + * + * @param path + * The string to process that is expected to follow the traditional Linux standard PATH environment variable. + * Each seperate path is separated by a single ':'. + * Need not be NULL terminated. + * NULLs are ignored and are not copied into the exploded paths. + * @param paths + * All of the strings exploded from PATH. + * Each exploded path, when not empty, is guaranteed to have a trailing '/'. + * Each exploded path is not NULL terminated. + * + * @return + * F_none on success. + * F_buffer_too_large (with error bit) if paths array is too large for further addressing. + * F_memory_reallocation (with error bit) on reallocation error. + * F_memory_allocation (with error bit) on allocation error. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fl_environment_path_explode_reverse_dynamic_ + extern f_return_status fl_environment_path_explode_reverse_dynamic(const f_string_static path, f_string_dynamics *paths); +#endif // _di_fl_environment_path_explode_reverse_dynamic_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _FL_environment_h diff --git a/level_1/fl_environment/data/build/defines b/level_1/fl_environment/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_1/fl_environment/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_1/fl_environment/data/build/dependencies b/level_1/fl_environment/data/build/dependencies new file mode 100644 index 0000000..2e9e9f3 --- /dev/null +++ b/level_1/fl_environment/data/build/dependencies @@ -0,0 +1,9 @@ +# fss-0000 + +f_type +f_status +f_memory +f_string +f_utf +f_environment +f_path diff --git a/level_1/fl_environment/data/build/settings b/level_1/fl_environment/data/build/settings new file mode 100644 index 0000000..9a42638 --- /dev/null +++ b/level_1/fl_environment/data/build/settings @@ -0,0 +1,52 @@ +# fss-0001 + +project_name fl_environment + +version_major 0 +version_minor 5 +version_micro 0 +version_target major + +environment + +process_pre +process_post + +modes individual +modes_default individual + +build_compiler gcc +build_language c +build_linker ar +build_libraries -lc +build_libraries-individual -lf_environment -lf_path -lf_utf -lf_memory +build_sources_library environment.c +build_sources_program +build_sources_headers environment.h +build_sources_script +build_sources_setting +build_script yes +build_shared yes +build_static yes + +path_headers level_1 +path_library_script script +path_library_shared shared +path_library_static static +path_program_script script +path_program_shared shared +path_program_static static + +search_exclusive yes +search_shared yes +search_static yes + +defines_all +defines_static +defines_shared + +flags_all -z now -g +flags_shared +flags_static +flags_library -fPIC +flags_program -fPIE diff --git a/level_2/fll_execute/c/execute.c b/level_2/fll_execute/c/execute.c index eb323a4..413edb5 100644 --- a/level_2/fll_execute/c/execute.c +++ b/level_2/fll_execute/c/execute.c @@ -587,7 +587,7 @@ extern "C" { } } else { - status = f_environment_path_explode_dynamic(path, &paths); + status = fl_environment_path_explode_dynamic(path, &paths); } if (F_status_is_error(status)) { diff --git a/level_2/fll_execute/c/execute.h b/level_2/fll_execute/c/execute.h index dd97c37..16e22a3 100644 --- a/level_2/fll_execute/c/execute.h +++ b/level_2/fll_execute/c/execute.h @@ -28,6 +28,7 @@ #include // fll-1 includes +#include #include #ifdef __cplusplus diff --git a/level_2/fll_execute/data/build/dependencies b/level_2/fll_execute/data/build/dependencies index f2299d5..6c62d3b 100644 --- a/level_2/fll_execute/data/build/dependencies +++ b/level_2/fll_execute/data/build/dependencies @@ -7,4 +7,5 @@ f_string f_environment f_file f_path +fl_environment fl_string diff --git a/level_2/fll_execute/data/build/settings b/level_2/fll_execute/data/build/settings index 70484c8..27468a9 100644 --- a/level_2/fll_execute/data/build/settings +++ b/level_2/fll_execute/data/build/settings @@ -19,7 +19,7 @@ build_compiler gcc build_language c build_linker ar build_libraries -lc -build_libraries-individual -lfl_string -lf_utf -lf_path -lf_file -lf_environment -lf_memory +build_libraries-individual -lfl_environment -lfl_string -lf_utf -lf_path -lf_file -lf_environment -lf_memory build_sources_library execute.c private-execute.c build_sources_program build_sources_headers execute.h diff --git a/level_2/fll_path/c/path.c b/level_2/fll_path/c/path.c new file mode 100644 index 0000000..57177c7 --- /dev/null +++ b/level_2/fll_path/c/path.c @@ -0,0 +1,140 @@ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_fll_path_canonical_ + f_return_status fll_path_canonical(const f_string path, f_string_dynamic *canonical) { + #ifndef _di_level_2_parameter_checking_ + if (canonical == 0) return F_status_set_error(F_parameter); + #endif // _di_level_2_parameter_checking_ + + f_status status = F_none; + f_string_length at = 0; + + uint8_t previous_1 = 0; + uint8_t previous_2 = 0; + + f_string_length size_chunk = 0; + f_string_length position = 0; + + canonical->used = 0; + + if (path[0] == '/') { + previous_1 = '/'; + at = 1; + } + else { + status = f_path_current(F_true, canonical); + if (F_status_is_error(status)) return status; + + if (!path[0]) { + return F_none; + } + } + + status = fl_string_append_assure("/", 1, canonical); + if (F_status_is_error(status)) return status; + + for (; path[at]; at++) { + + if (!size_chunk && path[at] == '.') { + if (!previous_1 || previous_1 == '/') { + previous_1 = '.'; + previous_2 = 0; + continue; + } + + if (previous_1 == '.') { + if (previous_2) { + previous_1 = 0; + previous_2 = 0; + size_chunk = 3; + position = at - 2; + } + else { + previous_2 = '.'; + } + } + } + else if (path[at] == '/') { + if (previous_1 == '/') { + size_chunk = 0; + position = 0; + continue; + } + + if (previous_1 == '.') { + if (previous_2 == '.') { + if (canonical->used > 1) { + for (canonical->used--; canonical->used > 0; canonical->used--) { + if (canonical->string[canonical->used - 1] == '/') break; + } // for + } + } + } + else { + size_chunk++; + + status = fl_string_append(path + position, size_chunk, canonical); + if (F_status_is_error(status)) return status; + } + + previous_1 = '/'; + previous_2 = 0; + size_chunk = 0; + position = 0; + } + else { + if (!size_chunk) { + position = at; + + if (previous_2) { + position -= 2; + size_chunk = 2; + } + else if (previous_1) { + position--; + size_chunk = 1; + } + } + + if (previous_1) { + previous_1 = 0; + previous_2 = 0; + } + + size_chunk++; + } + } // for + + if (previous_2 == '.') { + if (canonical->used > 1) { + for (canonical->used--; canonical->used > 0; canonical->used--) { + if (canonical->string[canonical->used - 1] == '/') break; + } // for + } + } + else if (!(previous_1 == '.' || previous_1 == '/')) { + if (size_chunk) { + status = fl_string_append(path + position, size_chunk, canonical); + if (F_status_is_error(status)) return status; + } + } + + // assure there is no trailing forward slash, unless it is the first slash. + if (canonical->used > 1 && canonical->string[canonical->used - 1] == '/') { + canonical->used--; + } + + status = fl_string_dynamic_terminate_after(canonical); + if (F_status_is_error(status)) return status; + + return F_none; + } +#endif // _di_fll_path_canonical_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_2/fll_path/c/path.h b/level_2/fll_path/c/path.h new file mode 100644 index 0000000..9672772 --- /dev/null +++ b/level_2/fll_path/c/path.h @@ -0,0 +1,57 @@ +/** + * FLL - Level 2 + * + * Project: Path + * API Version: 0.5 + * Licenses: lgplv2.1 + * + * Provides path-related functionality. + */ +#ifndef _FLL_path_h +#define _FLL_path_h + +// libc includes +#include + +// fll-0 includes +#include +#include +#include +#include +#include + +// fll-1 includes +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Get the canonical (real) path for some path. + * + * This does not check if the path exists or not. + * This processes the relative parts: './', '../', and extra '/'. + * This does not process symbolic links. + * This has a max size of f_string_length_size. + * + * @param path + * The source path to determine what the canonical path is. + * This is a NULL terminated string. + * @param canonical + * The (allocated) canonical file path. + * The canonical->used is reset to 0 before processing. + * This will be NULL terminated at canonical->used + 1. + * + * @return + * F_none on success. + */ +#ifndef _di_fll_path_canonical_ + extern f_return_status fll_path_canonical(const f_string path, f_string_dynamic *canonical); +#endif // _di_fll_path_canonical_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _FLL_path_h diff --git a/level_2/fll_path/data/build/defines b/level_2/fll_path/data/build/defines new file mode 100644 index 0000000..c665317 --- /dev/null +++ b/level_2/fll_path/data/build/defines @@ -0,0 +1,2 @@ +# fss-0000 + diff --git a/level_2/fll_path/data/build/dependencies b/level_2/fll_path/data/build/dependencies new file mode 100644 index 0000000..2815ad2 --- /dev/null +++ b/level_2/fll_path/data/build/dependencies @@ -0,0 +1,8 @@ +# fss-0000 + +f_type +f_status +f_memory +f_string +f_path +fl_string diff --git a/level_2/fll_path/data/build/settings b/level_2/fll_path/data/build/settings new file mode 100644 index 0000000..41800b3 --- /dev/null +++ b/level_2/fll_path/data/build/settings @@ -0,0 +1,52 @@ +# fss-0001 + +project_name fll_path + +version_major 0 +version_minor 5 +version_micro 0 +version_target major + +environment + +process_pre +process_post + +modes individual +modes_default individual + +build_compiler gcc +build_language c +build_linker ar +build_libraries -lc +build_libraries-individual -lfl_string -lf_path -lf_memory +build_sources_library path.c +build_sources_program +build_sources_headers path.h +build_sources_script +build_sources_setting +build_script yes +build_shared yes +build_static yes + +path_headers level_2 +path_library_script script +path_library_shared shared +path_library_static static +path_program_script script +path_program_shared shared +path_program_static static + +search_exclusive yes +search_shared yes +search_static yes + +defines_all +defines_static +defines_shared + +flags_all -z now -g +flags_shared +flags_static +flags_library -fPIC +flags_program -fPIE diff --git a/level_3/fake/c/fake.h b/level_3/fake/c/fake.h index f115eb2..ec9ce24 100644 --- a/level_3/fake/c/fake.h +++ b/level_3/fake/c/fake.h @@ -75,6 +75,7 @@ #include #include #include +#include #include #ifdef __cplusplus diff --git a/level_3/fake/c/private-make.c b/level_3/fake/c/private-make.c index 04c2913..e8a2cfe 100644 --- a/level_3/fake/c/private-make.c +++ b/level_3/fake/c/private-make.c @@ -15,7 +15,7 @@ extern "C" { data_make->path_cache.used = 0; - f_status status = f_path_real(path.string, &data_make->path_cache); + f_status status = fll_path_canonical(path.string, &data_make->path_cache); if (F_status_is_error(status)) return status; if (data_make->path_cache.used < data_make->path.stack.array[0].used) { @@ -1235,7 +1235,7 @@ extern "C" { fake_make_operate_expand(data, section->name, operation, *operation_name, section->contents.array[i], section->quotedss.array[i], data_make, &arguments[i], status); if (F_status_is_error(*status)) break; - fake_make_operate_validate(data, section->name, operation, *operation_name, *data_make, arguments[i], operation_if, status); + fake_make_operate_validate(data, section->name, operation, *operation_name, arguments[i], operation_if, data_make, status); if (operation_if) { if (operation_if == fake_make_operation_if_type_if) { @@ -1547,7 +1547,13 @@ extern "C" { *status = f_file_touch(arguments.array[1].string, mode.regular, F_false); if (F_status_is_error(*status)) { - fake_print_error(data, F_status_set_fine(*status), "f_file_touch", F_true); + if (F_status_is_fine(fll_path_canonical(arguments.array[1].string, &data_make->path_cache))) { + fake_print_error_file(data, F_status_set_fine(*status), "f_file_touch", data_make->path_cache.string, "touch", F_true, F_true); + } + else { + fake_print_error_file(data, F_status_set_fine(*status), "f_file_touch", arguments.array[1].string, "touch", F_true, F_true); + } + return; } } @@ -1555,7 +1561,13 @@ extern "C" { *status = f_directory_touch(arguments.array[1].string, mode.directory); if (F_status_is_error(*status)) { - fake_print_error(data, F_status_set_fine(*status), "f_directory_touch", F_true); + if (F_status_is_fine(fll_path_canonical(arguments.array[1].string, &data_make->path_cache))) { + fake_print_error_file(data, F_status_set_fine(*status), "f_directory_touch", data_make->path_cache.string, "touch", F_false, F_true); + } + else { + fake_print_error_file(data, F_status_set_fine(*status), "f_directory_touch", arguments.array[1].string, "touch", F_false, F_true); + } + return; } } @@ -1734,7 +1746,7 @@ extern "C" { #endif // _di_fake_make_operate_process_run_ #ifndef _di_fake_make_operate_validate_ - void fake_make_operate_validate(const fake_data data, const f_string_range section_name, const f_array_length operation, const f_string_static operation_name, const fake_make_data data_make, const f_string_dynamics arguments, const uint8_t operation_if, f_status *status) { + void fake_make_operate_validate(const fake_data data, const f_string_range section_name, const f_array_length operation, const f_string_static operation_name, const f_string_dynamics arguments, const uint8_t operation_if, fake_make_data *data_make, f_status *status) { if (F_status_is_error(*status)) return; if (operation == fake_make_operation_type_archive || operation == fake_make_operation_type_run || operation == fake_make_operation_type_shell) { @@ -1790,7 +1802,7 @@ extern "C" { *status = F_status_set_error(F_failure); } else if (operation == fake_make_operation_type_pop) { - if (data_make.path.stack.used == 1) { + if (data_make->path.stack.used == 1) { printf("%c", f_string_eol[0]); fl_color_print_line(f_type_error, data.context.error, data.context.reset, "ERROR: Must not attempt to pop project root off of path stack."); @@ -2082,7 +2094,14 @@ extern "C" { } } - // @todo: fake_make_assure_inside_project + *status = fake_make_assure_inside_project(data, arguments.array[1], data_make); + if (F_status_is_error(*status)) { + fake_print_error_fakefile_section_operation_path_outside(data, F_status_set_fine(*status), "fake_make_assure_inside_project", arguments.array[1].string); + + if (F_status_set_fine(*status) == F_false) { + *status = F_status_set_error(F_failure); + } + } } else { printf("%c", f_string_eol[0]); diff --git a/level_3/fake/c/private-make.h b/level_3/fake/c/private-make.h index 73e2038..f9ea2c9 100644 --- a/level_3/fake/c/private-make.h +++ b/level_3/fake/c/private-make.h @@ -559,19 +559,19 @@ extern "C" { * The operation being performed. * @param operation_name * The operation name. - * @param data_make - * All make related setting data, including data from the fakefile and optionally build settings file. * @param arguments * The expanded arguments. * @param operation_if * The if-condition status for the current operation. + * @param data_make + * All make related setting data, including data from the fakefile and optionally build settings file. * @param status * The return status. * * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_make_operate_validate_ - extern void fake_make_operate_validate(const fake_data data, const f_string_range section_name, const f_array_length operation, const f_string_static operation_name, const fake_make_data data_make, const f_string_dynamics arguments, const uint8_t operation_if, f_status *status) f_gcc_attribute_visibility_internal; + extern void fake_make_operate_validate(const fake_data data, const f_string_range section_name, const f_array_length operation, const f_string_static operation_name, const f_string_dynamics arguments, const uint8_t operation_if, fake_make_data *data_make, f_status *status) f_gcc_attribute_visibility_internal; #endif // _di_fake_make_operate_validate_ /** diff --git a/level_3/fake/data/build/dependencies b/level_3/fake/data/build/dependencies index e114de7..2a05f08 100644 --- a/level_3/fake/data/build/dependencies +++ b/level_3/fake/data/build/dependencies @@ -26,4 +26,5 @@ fl_string fl_utf fll_fss fll_execute +fll_path fll_program diff --git a/level_3/fake/data/build/settings b/level_3/fake/data/build/settings index ba781b9..09e5000 100644 --- a/level_3/fake/data/build/settings +++ b/level_3/fake/data/build/settings @@ -19,7 +19,7 @@ build_compiler gcc build_language c build_linker ar build_libraries -lc -build_libraries-individual -lfll_program -lfll_execute -lfll_fss -lfl_utf -lfl_string -lfl_status -lfl_iki -lfl_fss -lfl_directory -lfl_conversion -lfl_console -lfl_color -lf_print -lf_path -lf_iki -lf_file -lf_fss -lf_environment -lf_directory -lf_conversion -lf_console -lf_utf -lf_memory +build_libraries-individual -lfll_execute -lfll_fss -lfll_path -lfll_program -lfl_utf -lfl_string -lfl_status -lfl_iki -lfl_fss -lfl_directory -lfl_conversion -lfl_console -lfl_color -lf_print -lf_path -lf_iki -lf_file -lf_fss -lf_environment -lf_directory -lf_conversion -lf_console -lf_utf -lf_memory build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll build_sources_library fake.c private-fake.c private-clean.c private-build.c private-make.c private-print.c private-skeleton.c -- 1.8.3.1