From bbfb3dfa8cf1811ad27750a6cd156d84fee364c7 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Mon, 7 Sep 2020 21:33:51 -0500 Subject: [PATCH] Update: recursive functions, fix 'const const', don't error on max recurse depth. Rewrite the fl_directory_* recursive functions, simplifying their design. Add a max recursion depth. I have a toleration limit on the number of arguments in a function and this just reached a limit. Given that many of the parameters can be logically grouped and are also are also passed to other functions, implement a new structure. While this simply changes where the complexity/problems happen, this does alleviate the number of arguments concerns. Fix an accidental 'const const' declaration. Don't error on max recurse depth. This should just stop recursing for that directory and not generated an error. --- level_0/f_utf/c/utf.c | 2 +- level_1/fl_directory/c/directory.c | 44 ++++--- level_1/fl_directory/c/directory.h | 98 +++++++-------- level_1/fl_directory/c/private-directory.c | 192 ++++++++++++----------------- level_1/fl_directory/c/private-directory.h | 68 +++------- level_2/fll_file/c/file.h | 2 - level_2/fll_file/c/private-file.c | 18 ++- level_3/fake/c/private-build.c | 10 +- 8 files changed, 190 insertions(+), 244 deletions(-) diff --git a/level_0/f_utf/c/utf.c b/level_0/f_utf/c/utf.c index b103fd6..653f9c0 100644 --- a/level_0/f_utf/c/utf.c +++ b/level_0/f_utf/c/utf.c @@ -1128,7 +1128,7 @@ extern "C" { if (width_max < 1) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - const const uint8_t width = f_macro_utf_byte_width_is(*character); + const uint8_t width = f_macro_utf_byte_width_is(*character); if (width == 0) { // There are no ASCII private characters. diff --git a/level_1/fl_directory/c/directory.c b/level_1/fl_directory/c/directory.c index aeac554..fb323c6 100644 --- a/level_1/fl_directory/c/directory.c +++ b/level_1/fl_directory/c/directory.c @@ -6,7 +6,7 @@ extern "C" { #endif #ifndef _di_fl_directory_clone_ - f_return_status fl_directory_clone(const f_string_t source, const f_string_t destination, const f_string_length_t source_length, const f_string_length_t destination_length, const bool role, const f_number_unsigned_t size_block, const bool exclusive, FILE *verbose, f_directory_statuss_t *failures) { + f_return_status fl_directory_clone(const f_string_t source, const f_string_t destination, const f_string_length_t source_length, const f_string_length_t destination_length, const bool role, const fl_directory_recurse_t recurse) { #ifndef _di_level_1_parameter_checking_ if (source) return F_status_set_error(F_parameter); if (destination) return F_status_set_error(F_parameter); @@ -28,7 +28,7 @@ extern "C" { if (F_status_is_error(status)) return status; if (status == F_true) { - if (exclusive) { + if (recurse.exclusive) { return F_status_set_error(F_directory_found); } @@ -45,8 +45,8 @@ extern "C" { if (F_status_is_error(status)) return status; } - if (verbose) { - fprintf(verbose, "Cloned '%s' to '%s'.%c", source, destination, f_string_eol[0]); + if (recurse.verbose) { + fprintf(recurse.verbose, "Cloned '%s' to '%s'.%c", source, destination, f_string_eol[0]); } f_string_static_t static_source = { source, source_length, source_length }; @@ -71,12 +71,16 @@ extern "C" { } // for } - return private_fl_directory_clone(static_source, static_destination, role, size_block, exclusive, verbose, failures); + if (recurse.depth_max == 0) { + return status; + } + + return private_fl_directory_clone(static_source, static_destination, role, recurse, 1); } #endif // _di_fl_directory_clone_ #ifndef _di_fl_directory_clone_content_ - f_return_status fl_directory_clone_content(const f_string_t source, const f_string_t destination, const f_string_length_t source_length, const f_string_length_t destination_length, const bool role, const f_number_unsigned_t size_block, const bool exclusive, FILE *verbose, f_directory_statuss_t *failures) { + f_return_status fl_directory_clone_content(const f_string_t source, const f_string_t destination, const f_string_length_t source_length, const f_string_length_t destination_length, const bool role, const fl_directory_recurse_t recurse) { #ifndef _di_level_1_parameter_checking_ if (source) return F_status_set_error(F_parameter); if (destination) return F_status_set_error(F_parameter); @@ -113,12 +117,16 @@ extern "C" { } // for } - return private_fl_directory_clone(static_source, static_destination, role, size_block, exclusive, verbose, failures); + if (recurse.depth_max == 0) { + return status; + } + + return private_fl_directory_clone(static_source, static_destination, role, recurse, 1); } #endif // _di_fl_directory_clone_content_ #ifndef _di_fl_directory_copy_ - f_return_status fl_directory_copy(const f_string_t source, const f_string_t destination, const f_string_length_t source_length, const f_string_length_t destination_length, const f_mode_t mode, const f_number_unsigned_t size_block, const bool exclusive, FILE *verbose, f_directory_statuss_t *failures) { + f_return_status fl_directory_copy(const f_string_t source, const f_string_t destination, const f_string_length_t source_length, const f_string_length_t destination_length, const f_mode_t mode, const fl_directory_recurse_t recurse) { #ifndef _di_level_1_parameter_checking_ if (source) return F_status_set_error(F_parameter); if (destination) return F_status_set_error(F_parameter); @@ -133,7 +141,7 @@ extern "C" { if (F_status_is_error(status)) return status; if (status == F_true) { - if (exclusive) { + if (recurse.exclusive) { return F_status_set_error(F_directory_found); } @@ -145,8 +153,8 @@ extern "C" { if (F_status_is_error(status)) return status; } - if (verbose) { - fprintf(verbose, "Copied '%s' to '%s'.%c", source, destination, f_string_eol[0]); + if (recurse.verbose) { + fprintf(recurse.verbose, "Copied '%s' to '%s'.%c", source, destination, f_string_eol[0]); } f_string_static_t static_source = { source, source_length, source_length }; @@ -171,12 +179,16 @@ extern "C" { } // for } - return private_fl_directory_copy(static_source, static_destination, mode, size_block, exclusive, verbose, failures); + if (recurse.depth_max == 0) { + return status; + } + + return private_fl_directory_copy(static_source, static_destination, mode, recurse, 1); } #endif // _di_fl_directory_copy_ #ifndef _di_fl_directory_copy_content_ - f_return_status fl_directory_copy_content(const f_string_t source, const f_string_t destination, const f_string_length_t source_length, const f_string_length_t destination_length, const f_mode_t mode, const f_number_unsigned_t size_block, const bool exclusive, FILE *verbose, f_directory_statuss_t *failures) { + f_return_status fl_directory_copy_content(const f_string_t source, const f_string_t destination, const f_string_length_t source_length, const f_string_length_t destination_length, const f_mode_t mode, const fl_directory_recurse_t recurse) { #ifndef _di_level_1_parameter_checking_ if (source) return F_status_set_error(F_parameter); if (destination) return F_status_set_error(F_parameter); @@ -213,7 +225,11 @@ extern "C" { } // for } - return private_fl_directory_copy(static_source, static_destination, mode, size_block, exclusive, verbose, failures); + if (recurse.depth_max == 0) { + return status; + } + + return private_fl_directory_copy(static_source, static_destination, mode, recurse, 1); } #endif // _di_fl_directory_copy_content_ diff --git a/level_1/fl_directory/c/directory.h b/level_1/fl_directory/c/directory.h index dbb2e56..d4b09df 100644 --- a/level_1/fl_directory/c/directory.h +++ b/level_1/fl_directory/c/directory.h @@ -45,6 +45,40 @@ extern "C" { #endif /** + * An association of a path and a status code. + * + * The allocation macros apply to the path. + * + * depth_max: + * The max recursion depth. + * size_block: + * The default number of chunks to read at a time with each chunk being 1-byte. + * Must be greater than 0. + * exclusive: + * If TRUE, will fail when file already exists. + * If FALSE, will not fail if file already exists (existing file will be replaced). + * verbose: + * Set to 0 to not print copy operation values on successful copy. + * Set to a valid file pointer, such as f_type_output (stdout), to print on successful copy. + * failures: + * A list of paths and their respective status codes for clone failures. + * If 0, then this and statuses are ignored. + */ +#ifndef _di_fl_directory_recurse_t_ + #define fl_directory_recurse_depth_max 65535 + + typedef struct { + f_number_unsigned_t depth_max; + f_number_unsigned_t size_block; + bool exclusive; + FILE *verbose; + f_directory_statuss_t *failures; + } fl_directory_recurse_t; + + #define fl_directory_recurse_t_initialize { fl_directory_recurse_depth_max, f_file_default_read_size, F_false, 0, 0 } +#endif // _di_fl_directory_recurse_t_ + +/** * Copy a directory and its contents, as well as its file mode and possibly the owner and group.. * * The paths must not contain NULL except for the terminating NULL. @@ -68,18 +102,8 @@ extern "C" { * If TRUE, will copy the owner and group ids. * If FALSE, will not copy the owner and group ids. * (In both cases the file mode is copied.) - * @param size_block - * The default number of chunks to read at a time with each chunk being 1-byte. - * Must be greater than 0. - * @param exclusive - * If TRUE, will fail when file already exists. - * If FALSE, will not fail if file already exists (existing file will be replaced). - * @param verbose - * Set to 0 to not print copy operation values on successful copy. - * Set to a valid file pointer, such as f_type_output (stdout), to print on successful copy. - * @param failures - * A list of paths and their respective status codes for clone failures. - * If 0, then this and statuses is ignored. + * @param recurse + * The directory recurse data. * * @return * F_none on success. @@ -104,7 +128,7 @@ extern "C" { * @see f_file_clone() */ #ifndef _di_fl_directory_clone_ - extern f_return_status fl_directory_clone(const f_string_t source, const f_string_t destination, const f_string_length_t source_length, const f_string_length_t destination_length, const bool role, const f_number_unsigned_t size_block, const bool exclusive, FILE *verbose, f_directory_statuss_t *failures); + extern f_return_status fl_directory_clone(const f_string_t source, const f_string_t destination, const f_string_length_t source_length, const f_string_length_t destination_length, const bool role, const fl_directory_recurse_t recurse); #endif // _di_fl_directory_clone_ /** @@ -133,18 +157,8 @@ extern "C" { * If TRUE, will copy the owner and group ids. * If FALSE, will not copy the owner and group ids. * (In both cases the file mode is copied.) - * @param size_block - * The default number of chunks to read at a time with each chunk being 1-byte. - * Must be greater than 0. - * @param exclusive - * If TRUE, will fail when file already exists. - * If FALSE, will not fail if file already exists (existing file will be replaced). - * @param verbose - * Set to 0 to not print copy operation values on successful copy. - * Set to a valid file pointer, such as f_type_output (stdout), to print on successful copy. - * @param failures - * A list of paths and their respective status codes for clone failures. - * If 0, then this and statuses is ignored. + * @param recurse + * The directory recurse data. * * @return * F_none on success. @@ -165,7 +179,7 @@ extern "C" { * @see f_file_clone() */ #ifndef _di_fl_directory_clone_content_ - extern f_return_status fl_directory_clone_content(const f_string_t source, const f_string_t destination, const f_string_length_t source_length, const f_string_length_t destination_length, const bool role, const f_number_unsigned_t size_block, const bool exclusive, FILE *verbose, f_directory_statuss_t *failures); + extern f_return_status fl_directory_clone_content(const f_string_t source, const f_string_t destination, const f_string_length_t source_length, const f_string_length_t destination_length, const bool role, const fl_directory_recurse_t recurse); #endif // _di_fl_directory_clone_content_ /** @@ -190,18 +204,8 @@ extern "C" { * The length of the destination path. * @param mode * The directory modes. - * @param size_block - * The default number of chunks to read at a time with each chunk being 1-byte. - * Set to 0 to use default block read size. - * @param exclusive - * If TRUE, will fail when file already exists. - * If FALSE, will not fail if file already exists (existing file will be replaced). - * @param verbose - * Set to 0 to not print copy operation values on successful copy. - * Set to a valid file pointer, such as f_type_output (stdout), to print on successful copy. - * @param failures - * A list of paths and their respective status codes for copy failures. - * If 0, then this and statuses is ignored. + * @param recurse + * The directory recurse data. * * @return * F_none on success. @@ -226,7 +230,7 @@ extern "C" { * @see f_file_copy() */ #ifndef _di_fl_directory_copy_ - extern f_return_status fl_directory_copy(const f_string_t source, const f_string_t destination, const f_string_length_t source_length, const f_string_length_t destination_length, const f_mode_t mode, const f_number_unsigned_t size_block, const bool exclusive, FILE *verbose, f_directory_statuss_t *failures); + extern f_return_status fl_directory_copy(const f_string_t source, const f_string_t destination, const f_string_length_t source_length, const f_string_length_t destination_length, const f_mode_t mode, const fl_directory_recurse_t recurse); #endif // _di_fl_directory_copy_ /** @@ -253,18 +257,8 @@ extern "C" { * The length of the destination path. * @param mode * The directory modes. - * @param size_block - * The default number of chunks to read at a time with each chunk being 1-byte. - * Set to 0 to use default block read size. - * @param exclusive - * If TRUE, will fail when file already exists. - * If FALSE, will not fail if file already exists (existing file will be replaced). - * @param verbose - * Set to 0 to not print copy operation values on successful copy. - * Set to a valid file pointer, such as f_type_output (stdout), to print on successful copy. - * @param failures - * A list of paths and their respective status codes for copy failures. - * If 0, then this and statuses is ignored. + * @param recurse + * The directory recurse data. * * @return * F_none on success. @@ -285,7 +279,7 @@ extern "C" { * @see f_file_copy() */ #ifndef _di_fl_directory_copy_content_ - extern f_return_status fl_directory_copy_content(const f_string_t source, const f_string_t destination, const f_string_length_t source_length, const f_string_length_t destination_length, const f_mode_t mode, const f_number_unsigned_t size_block, const bool exclusive, FILE *verbose, f_directory_statuss_t *failures); + extern f_return_status fl_directory_copy_content(const f_string_t source, const f_string_t destination, const f_string_length_t source_length, const f_string_length_t destination_length, const f_mode_t mode, const fl_directory_recurse_t recurse); #endif // _di_fl_directory_copy_content_ /** diff --git a/level_1/fl_directory/c/private-directory.c b/level_1/fl_directory/c/private-directory.c index b921a32..e79e45e 100644 --- a/level_1/fl_directory/c/private-directory.c +++ b/level_1/fl_directory/c/private-directory.c @@ -6,7 +6,7 @@ extern "C" { #endif #if !defined(_di_fl_directory_clone_) - f_return_status private_fl_directory_clone(const f_string_static_t source, const f_string_static_t destination, const bool role, const f_number_unsigned_t size_block, const bool exclusive, FILE *verbose, f_directory_statuss_t *failures) { + f_return_status private_fl_directory_clone(const f_string_static_t source, const f_string_static_t destination, const bool role, const fl_directory_recurse_t recurse, const f_number_unsigned_t depth) { f_status_t status = F_none; f_directory_listing_t listing = f_directory_listing_t_initialize; @@ -18,48 +18,33 @@ extern "C" { status = F_none; - f_array_length_t i = 0; - int directory_fd = 0; - f_string_length_t failures_used = failures ? failures->used : 0; - - for (; F_status_is_fine(status) && i < listing.block.used; i++) { - status = private_fl_directory_clone_file(listing.block.array[i], source, destination, role, size_block, exclusive, verbose, failures); - } // for - - f_macro_string_dynamics_t_delete_simple(listing.block); - - for (i = 0; F_status_is_fine(status) && i < listing.character.used; i++) { - status = private_fl_directory_clone_file(listing.character.array[i], source, destination, role, size_block, exclusive, verbose, failures); - } // for - - f_macro_string_dynamics_t_delete_simple(listing.character); - - for (i = 0; F_status_is_fine(status) && i < listing.regular.used; i++) { - status = private_fl_directory_clone_file(listing.regular.array[i], source, destination, role, size_block, exclusive, verbose, failures); - } // for - - f_macro_string_dynamics_t_delete_simple(listing.regular); - - for (i = 0; F_status_is_fine(status) && i < listing.link.used; i++) { - status = private_fl_directory_clone_file(listing.link.array[i], source, destination, role, size_block, exclusive, verbose, failures); - } // for + f_string_length_t failures_used = recurse.failures ? recurse.failures->used : 0; - f_macro_string_dynamics_t_delete_simple(listing.link); - - for (i = 0; F_status_is_fine(status) && i < listing.socket.used; i++) { - status = private_fl_directory_clone_file(listing.socket.array[i], source, destination, role, size_block, exclusive, verbose, failures); - } // for - - f_macro_string_dynamics_t_delete_simple(listing.socket); - - for (i = 0; F_status_is_fine(status) && i < listing.unknown.used; i++) { - status = private_fl_directory_clone_file(listing.unknown.array[i], source, destination, role, size_block, exclusive, verbose, failures); - } // for + { + f_string_dynamics_t *list[] = { + &listing.block, + &listing.character, + &listing.regular, + &listing.link, + &listing.fifo, + &listing.socket, + &listing.unknown, + }; + + uint8_t i = 0; + f_array_length_t j = 0; + + for (; i < 7; i++) { + for (j = 0; F_status_is_fine(status) && j < list[i]->used; j++) { + status = private_fl_directory_clone_file(list[i]->array[i], source, destination, role, recurse); + } // for - f_macro_string_dynamics_t_delete_simple(listing.unknown); + f_macro_string_dynamics_t_delete_simple((*list[i])); + } // for + } - for (i = 0; F_status_is_fine(status) && i < listing.directory.used; i++) { + for (f_array_length_t i = 0; F_status_is_fine(status) && i < listing.directory.used; i++) { f_string_static_t source_sub = f_string_static_t_initialize; f_string_static_t destination_sub = f_string_static_t_initialize; @@ -107,7 +92,7 @@ extern "C" { if (F_status_is_error(status)) break; if (status == F_true) { - if (exclusive) { + if (recurse.exclusive) { status = F_status_set_error(F_directory_found); break; } @@ -126,21 +111,23 @@ extern "C" { } } - status = private_fl_directory_clone(source_sub, destination_sub, role, size_block, exclusive, verbose, failures); + if (depth < recurse.depth_max) { + status = private_fl_directory_clone(source_sub, destination_sub, role, recurse, depth + 1); + } } // for f_macro_string_dynamics_t_delete_simple(listing.directory); if (F_status_is_error(status)) return status; - if (failures && failures_used < failures->used) return F_failure; + if (recurse.failures && failures_used < recurse.failures->used) return F_failure; return F_none; } #endif // !defined(_di_fl_directory_clone_) #if !defined(_di_fl_directory_clone_file_) - f_return_status private_fl_directory_clone_file(const f_string_static_t file, const f_string_static_t source, const f_string_static_t destination, const bool role, const f_number_unsigned_t size_block, const bool exclusive, FILE *verbose, f_directory_statuss_t *failures) { + f_return_status private_fl_directory_clone_file(const f_string_static_t file, const f_string_static_t source, const f_string_static_t destination, const bool role, const fl_directory_recurse_t recurse) { char path_source[source.used + file.used + 2]; char path_destination[destination.used + file.used + 2]; @@ -154,18 +141,18 @@ extern "C" { path_destination[destination.used] = f_path_separator[0]; path_destination[destination.used + file.used + 1] = 0; - f_status_t status = f_file_clone(path_source, path_destination, role, size_block, exclusive); + f_status_t status = f_file_clone(path_source, path_destination, role, recurse.size_block, recurse.exclusive); if (F_status_is_error(status) || status == F_unsupported) { if (status == F_status_set_error(F_memory_allocation) || status == F_status_set_error(F_memory_reallocation)) { return F_status_set_error(status); } - if (!failures) return F_failure; + if (!recurse.failures) return F_failure; const f_status_t status_failure = status; - f_macro_memory_structure_macro_increment(status, (*failures), 1, f_memory_default_allocation_step, f_macro_directory_statuss_t_resize, F_buffer_too_large); + f_macro_memory_structure_macro_increment(status, (*recurse.failures), 1, f_memory_default_allocation_step, f_macro_directory_statuss_t_resize, F_buffer_too_large); if (F_status_is_error(status)) return status; f_directory_status_t failure = f_directory_status_t_initialize; @@ -206,17 +193,17 @@ extern "C" { failure.path.string[size] = 0; } - failures->array[failures->used].path.string = failure.path.string; - failures->array[failures->used].path.used = size; - failures->array[failures->used].path.size = size + 1; - failures->array[failures->used].status = status_failure; - failures->used++; + recurse.failures->array[recurse.failures->used].path.string = failure.path.string; + recurse.failures->array[recurse.failures->used].path.used = size; + recurse.failures->array[recurse.failures->used].path.size = size + 1; + recurse.failures->array[recurse.failures->used].status = status_failure; + recurse.failures->used++; return F_failure; } - if (verbose) { - fprintf(verbose, "Cloned '%s' to '%s'.%c", source.string, destination.string, f_string_eol[0]); + if (recurse.verbose) { + fprintf(recurse.verbose, "Cloned '%s' to '%s'.%c", source.string, destination.string, f_string_eol[0]); } return F_none; @@ -224,7 +211,7 @@ extern "C" { #endif // !defined(_di_fl_directory_clone_file_) #if !defined(_di_fl_directory_copy_) - f_return_status private_fl_directory_copy(const f_string_static_t source, const f_string_static_t destination, const f_mode_t mode, const f_number_unsigned_t size_block, const bool exclusive, FILE *verbose, f_directory_statuss_t *failures) { + f_return_status private_fl_directory_copy(const f_string_static_t source, const f_string_static_t destination, const f_mode_t mode, const fl_directory_recurse_t recurse, const f_number_unsigned_t depth) { f_status_t status = F_none; f_directory_listing_t listing = f_directory_listing_t_initialize; @@ -236,54 +223,33 @@ extern "C" { status = F_none; - f_array_length_t i = 0; - int directory_fd = 0; - f_string_length_t failures_used = failures ? failures->used : 0; + f_string_length_t failures_used = recurse.failures ? recurse.failures->used : 0; - for (; F_status_is_fine(status) && i < listing.block.used; i++) { - status = private_fl_directory_copy_file(listing.block.array[i], source, destination, mode, size_block, exclusive, verbose, failures); - } // for - - f_macro_string_dynamics_t_delete_simple(listing.block); - - for (i = 0; F_status_is_fine(status) && i < listing.character.used; i++) { - status = private_fl_directory_copy_file(listing.character.array[i], source, destination, mode, size_block, exclusive, verbose, failures); - } // for - - f_macro_string_dynamics_t_delete_simple(listing.character); - - for (i = 0; F_status_is_fine(status) && i < listing.fifo.used; i++) { - status = private_fl_directory_copy_file(listing.fifo.array[i], source, destination, mode, size_block, exclusive, verbose, failures); - } // for - - f_macro_string_dynamics_t_delete_simple(listing.fifo); - - for (i = 0; F_status_is_fine(status) && i < listing.regular.used; i++) { - status = private_fl_directory_copy_file(listing.regular.array[i], source, destination, mode, size_block, exclusive, verbose, failures); - } // for - - f_macro_string_dynamics_t_delete_simple(listing.regular); - - for (i = 0; F_status_is_fine(status) && i < listing.link.used; i++) { - status = private_fl_directory_copy_file(listing.link.array[i], source, destination, mode, size_block, exclusive, verbose, failures); - } // for - - f_macro_string_dynamics_t_delete_simple(listing.link); - - for (i = 0; F_status_is_fine(status) && i < listing.socket.used; i++) { - status = private_fl_directory_copy_file(listing.socket.array[i], source, destination, mode, size_block, exclusive, verbose, failures); - } // for - - f_macro_string_dynamics_t_delete_simple(listing.socket); - - for (i = 0; F_status_is_fine(status) && i < listing.unknown.used; i++) { - status = private_fl_directory_copy_file(listing.unknown.array[i], source, destination, mode, size_block, exclusive, verbose, failures); - } // for + { + f_string_dynamics_t *list[] = { + &listing.block, + &listing.character, + &listing.regular, + &listing.link, + &listing.fifo, + &listing.socket, + &listing.unknown, + }; + + uint8_t i = 0; + f_array_length_t j = 0; + + for (; i < 7; i++) { + for (j = 0; F_status_is_fine(status) && j < list[i]->used; j++) { + status = private_fl_directory_copy_file(list[i]->array[i], source, destination, mode, recurse); + } // for - f_macro_string_dynamics_t_delete_simple(listing.unknown); + f_macro_string_dynamics_t_delete_simple((*list[i])); + } // for + } - for (i = 0; F_status_is_fine(status) && i < listing.directory.used; i++) { + for (f_array_length_t i = 0; F_status_is_fine(status) && i < listing.directory.used; i++) { f_string_static_t source_sub = f_string_static_t_initialize; f_string_static_t destination_sub = f_string_static_t_initialize; @@ -323,7 +289,7 @@ extern "C" { if (F_status_is_error(status)) break; if (status == F_true) { - if (exclusive) { + if (recurse.exclusive) { status = F_status_set_error(F_directory_found); break; } @@ -336,21 +302,23 @@ extern "C" { if (F_status_is_error(status)) break; } - status = private_fl_directory_copy(source_sub, destination_sub, mode, size_block, exclusive, verbose, failures); + if (depth < recurse.depth_max) { + status = private_fl_directory_copy(source_sub, destination_sub, mode, recurse, depth + 1); + } } // for f_macro_string_dynamics_t_delete_simple(listing.directory); if (F_status_is_error(status)) return status; - if (failures && failures_used < failures->used) return F_failure; + if (recurse.failures && failures_used < recurse.failures->used) return F_failure; return F_none; } #endif // !defined(_di_fl_directory_copy_) #if !defined(_di_fl_directory_copy_file_) - f_return_status private_fl_directory_copy_file(const f_string_static_t file, const f_string_static_t source, const f_string_static_t destination, const f_mode_t mode, const f_number_unsigned_t size_block, const bool exclusive, FILE *verbose, f_directory_statuss_t *failures) { + f_return_status private_fl_directory_copy_file(const f_string_static_t file, const f_string_static_t source, const f_string_static_t destination, const f_mode_t mode, const fl_directory_recurse_t recurse) { char path_source[source.used + file.used + 2]; char path_destination[destination.used + file.used + 2]; @@ -364,18 +332,18 @@ extern "C" { path_destination[destination.used] = f_path_separator[0]; path_destination[destination.used + file.used + 1] = 0; - f_status_t status = f_file_copy(path_source, path_destination, mode, size_block, exclusive); + f_status_t status = f_file_copy(path_source, path_destination, mode, recurse.size_block, recurse.exclusive); if (F_status_is_error(status) || status == F_unsupported) { if (status == F_status_set_error(F_memory_allocation) || status == F_status_set_error(F_memory_reallocation)) { return F_status_set_error(status); } - if (!failures) return F_failure; + if (!recurse.failures) return F_failure; const f_status_t status_failure = status; - f_macro_memory_structure_macro_increment(status, (*failures), 1, f_memory_default_allocation_step, f_macro_directory_statuss_t_resize, F_buffer_too_large); + f_macro_memory_structure_macro_increment(status, (*recurse.failures), 1, f_memory_default_allocation_step, f_macro_directory_statuss_t_resize, F_buffer_too_large); if (F_status_is_error(status)) return status; f_directory_status_t failure = f_directory_status_t_initialize; @@ -416,17 +384,17 @@ extern "C" { failure.path.string[size] = 0; } - failures->array[failures->used].path.string = failure.path.string; - failures->array[failures->used].path.used = size; - failures->array[failures->used].path.size = size + 1; - failures->array[failures->used].status = status_failure; - failures->used++; + recurse.failures->array[recurse.failures->used].path.string = failure.path.string; + recurse.failures->array[recurse.failures->used].path.used = size; + recurse.failures->array[recurse.failures->used].path.size = size + 1; + recurse.failures->array[recurse.failures->used].status = status_failure; + recurse.failures->used++; return F_failure; } - if (verbose) { - fprintf(verbose, "Copied '%s' to '%s'.%c", source.string, destination.string, f_string_eol[0]); + if (recurse.verbose) { + fprintf(recurse.verbose, "Copied '%s' to '%s'.%c", source.string, destination.string, f_string_eol[0]); } return F_none; diff --git a/level_1/fl_directory/c/private-directory.h b/level_1/fl_directory/c/private-directory.h index b8a3128..c76154b 100644 --- a/level_1/fl_directory/c/private-directory.h +++ b/level_1/fl_directory/c/private-directory.h @@ -29,18 +29,10 @@ extern "C" { * If TRUE, will copy the owner and group ids. * If FALSE, will not copy the owner and group ids. * (In both cases the file mode is copied.) - * @param size_block - * The default number of chunks to read at a time with each chunk being 1-byte. - * Must be greater than 0. - * @param exclusive - * If TRUE, will fail when file already exists. - * If FALSE, will not fail if file already exists (existing file will be replaced). - * @param verbose - * Set to 0 to not print copy operation values on successful copy. - * Set to a valid file pointer, such as f_type_output (stdout), to print on successful copy. - * @param failures - * A list of paths and their respective status codes for clone failures. - * If 0, then this and statuses is ignored. + * @param recurse + * The directory recurse data. + * @param depth + * The current depth. * * @return * F_none on success. @@ -59,7 +51,7 @@ extern "C" { * @see fl_directory_clone() */ #if !defined(_di_fl_directory_clone_) - extern f_return_status private_fl_directory_clone(const f_string_static_t source, const f_string_static_t destination, const bool role, const f_number_unsigned_t size_block, const bool exclusive, FILE *verbose, f_directory_statuss_t *failures) f_gcc_attribute_visibility_internal; + extern f_return_status private_fl_directory_clone(const f_string_static_t source, const f_string_static_t destination, const bool role, const fl_directory_recurse_t recurse, const f_number_unsigned_t depth) f_gcc_attribute_visibility_internal; #endif // !defined(_di_fl_directory_clone_) /** @@ -80,18 +72,8 @@ extern "C" { * If TRUE, will copy the owner and group ids. * If FALSE, will not copy the owner and group ids. * (In both cases the file mode is copied.) - * @param size_block - * The default number of chunks to read at a time with each chunk being 1-byte. - * Must be greater than 0. - * @param exclusive - * If TRUE, will fail when file already exists. - * If FALSE, will not fail if file already exists (existing file will be replaced). - * @param verbose - * Set to 0 to not print copy operation values on successful copy. - * Set to a valid file pointer, such as f_type_output (stdout), to print on successful copy. - * @param failures - * A list of paths and their respective status codes for clone failures. - * If 0, then this and statuses is ignored. + * @param recurse + * The directory recurse data. * * @return * F_none on success. @@ -111,7 +93,7 @@ extern "C" { * @see fl_directory_clone() */ #if !defined(_di_fl_directory_clone_file_) - extern f_return_status private_fl_directory_clone_file(const f_string_static_t file, const f_string_static_t source, const f_string_static_t destination, const bool role, const f_number_unsigned_t size_block, const bool exclusive, FILE *verbose, f_directory_statuss_t *failures) f_gcc_attribute_visibility_internal; + extern f_return_status private_fl_directory_clone_file(const f_string_static_t file, const f_string_static_t source, const f_string_static_t destination, const bool role, const fl_directory_recurse_t recurse) f_gcc_attribute_visibility_internal; #endif // !defined(_di_fl_directory_clone_file_) /** @@ -127,18 +109,10 @@ extern "C" { * Must be NULL terminated. * @param mode * The mode for each file type. - * @param size_block - * The default number of chunks to read at a time with each chunk being 1-byte. - * Must be greater than 0. - * @param exclusive - * If TRUE, will fail when file already exists. - * If FALSE, will not fail if file already exists (existing file will be replaced). - * @param verbose - * Set to 0 to not print copy operation values on successful copy. - * Set to a valid file pointer, such as f_type_output (stdout), to print on successful copy. - * @param failures - * A list of paths and their respective status codes for copy failures. - * If 0, then this and statuses is ignored. + * @param recurse + * The directory recurse data. + * @param depth + * The current depth. * * @return * F_none on success. @@ -157,7 +131,7 @@ extern "C" { * @see fl_directory_copy() */ #if !defined(_di_fl_directory_copy_) - extern f_return_status private_fl_directory_copy(const f_string_static_t source, const f_string_static_t destination, const f_mode_t mode, const f_number_unsigned_t size_block, const bool exclusive, FILE *verbose, f_directory_statuss_t *failures) f_gcc_attribute_visibility_internal; + extern f_return_status private_fl_directory_copy(const f_string_static_t source, const f_string_static_t destination, const f_mode_t mode, const fl_directory_recurse_t recurse, const f_number_unsigned_t depth) f_gcc_attribute_visibility_internal; #endif // !defined(_di_fl_directory_copy_) /** @@ -176,18 +150,8 @@ extern "C" { * Must be NULL terminated. * @param mode * The mode for each file type. - * @param size_block - * The default number of chunks to read at a time with each chunk being 1-byte. - * Must be greater than 0. - * @param exclusive - * If TRUE, will fail when file already exists. - * If FALSE, will not fail if file already exists (existing file will be replaced). - * @param verbose - * Set to 0 to not print copy operation values on successful copy. - * Set to a valid file pointer, such as f_type_output (stdout), to print on successful copy. - * @param failures - * A list of paths and their respective status codes for copy failures. - * If 0, then this and statuses is ignored. + * @param recurse + * The directory recurse data. * * @return * F_none on success. @@ -206,7 +170,7 @@ extern "C" { * @see fl_directory_copy() */ #if !defined(_di_fl_directory_copy_file_) - extern f_return_status private_fl_directory_copy_file(const f_string_static_t file, const f_string_static_t source, const f_string_static_t destination, const f_mode_t mode, const f_number_unsigned_t size_block, const bool exclusive, FILE *verbose, f_directory_statuss_t *failures) f_gcc_attribute_visibility_internal; + extern f_return_status private_fl_directory_copy_file(const f_string_static_t file, const f_string_static_t source, const f_string_static_t destination, const f_mode_t mode, const fl_directory_recurse_t recurse) f_gcc_attribute_visibility_internal; #endif // !defined(_di_fl_directory_copy_file_) /** diff --git a/level_2/fll_file/c/file.h b/level_2/fll_file/c/file.h index dbc4cae..c3b068f 100644 --- a/level_2/fll_file/c/file.h +++ b/level_2/fll_file/c/file.h @@ -79,7 +79,6 @@ extern "C" { * F_name (with error bit) on path name error. * F_parameter (with error bit) if a parameter is invalid. * F_read_only (with error bit) if file is read-only. - * F_recurse (with error bit) if recursion failed, due to max depth reached. * F_failure (with error bit) for any other error. */ #ifndef _di_fll_file_mode_set_all_ @@ -121,7 +120,6 @@ extern "C" { * F_name (with error bit) on path name error. * F_parameter (with error bit) if a parameter is invalid. * F_read_only (with error bit) if file is read-only. - * F_recurse (with error bit) if recursion failed, due to max depth reached. * F_failure (with error bit) for any other error. */ #ifndef _di_fll_file_role_change_all_ diff --git a/level_2/fll_file/c/private-file.c b/level_2/fll_file/c/private-file.c index d8106ae..7a3bf78 100644 --- a/level_2/fll_file/c/private-file.c +++ b/level_2/fll_file/c/private-file.c @@ -7,9 +7,6 @@ extern "C" { #if !defined(_di_fll_file_mode_set_all_) f_return_status private_fll_file_mode_set_all(const f_string_t path, const mode_t mode, const f_number_unsigned_t depth_max, const f_number_unsigned_t depth) { - - if (depth >= depth_max) return F_status_set_error(F_recurse); - f_status_t status = F_none; status = f_directory_is(path); @@ -86,8 +83,10 @@ extern "C" { break; } - status = private_fll_file_mode_set_all(path_sub, mode, depth_max, depth + 1); - if (F_status_is_error(status)) break; + if (depth < depth_max) { + status = private_fll_file_mode_set_all(path_sub, mode, depth_max, depth + 1); + if (F_status_is_error(status)) break; + } } // for f_macro_string_dynamics_t_delete_simple(listing.directory); @@ -100,9 +99,6 @@ extern "C" { #if !defined(_di_fll_file_role_change_all_) f_return_status private_fll_file_role_change_all(const f_string_t path, const uid_t uid, const gid_t gid, const bool dereference, const f_number_unsigned_t depth_max, const f_number_unsigned_t depth) { - - if (depth >= depth_max) return F_status_set_error(F_recurse); - f_status_t status = F_none; status = f_directory_is(path); @@ -177,8 +173,10 @@ extern "C" { break; } - status = private_fll_file_role_change_all(path_sub, uid, gid, dereference, depth_max, depth + 1); - if (F_status_is_error(status)) break; + if (depth < depth_max) { + status = private_fll_file_role_change_all(path_sub, uid, gid, dereference, depth_max, depth + 1); + if (F_status_is_error(status)) break; + } } // for f_macro_string_dynamics_t_delete_simple(listing.directory); diff --git a/level_3/fake/c/private-build.c b/level_3/fake/c/private-build.c index 55ed70e..26683d3 100644 --- a/level_3/fake/c/private-build.c +++ b/level_3/fake/c/private-build.c @@ -177,6 +177,14 @@ extern "C" { memcpy(path_source.string, source.string, source.used); + fl_directory_recurse_t recurse = fl_directory_recurse_t_initialize; + + if (data.verbosity == fake_verbosity_verbose) { + recurse.verbose = f_type_output; + } + + recurse.failures = &failures; + for (f_array_length_t i = 0; i < files.used; i++) { if (files.array[i].used == 0) continue; @@ -195,7 +203,7 @@ extern "C" { } if ((*status = f_directory_is(path_source.string)) == F_true) { - *status = fl_directory_copy_content(path_source.string, destination.string, path_source.used, destination.used, mode, f_file_default_read_size, F_false, (data.verbosity == fake_verbosity_verbose) ? f_type_output : 0, &failures); + *status = fl_directory_copy_content(path_source.string, destination.string, path_source.used, destination.used, mode, recurse); if (F_status_is_error(*status)) { if (data.verbosity == fake_verbosity_verbose) { -- 1.8.3.1