Update the todo.txt documentation.
There needs to be directory copy and clone functions for copy the contents of a source directory and not the directory itself.
To that end, add new *_contents() copy functions.
The comment documentation for clone was never updated and is incorrect.
In which case, the language can be hardcoded in as a single language.
Later versions after this first locale support will then consider supporting multiple languages not necessarily compiled in.
-- Create an fss simple content type (such that data->contents.array[at].start can be used instead of data->contents.array[at].array[0].start).
+- Consider creating an fss simple content type (such that data->contents.array[at].start can be used instead of data->contents.array[at].array[0].start).
- FSS needs to allow escaping of comments, "\# " would escape a comment, every backslash after that would be literal.
- implement the "data" unit that using the metric system more appropriately, such that a data is a single byte.
1 megadata in base 10 is (10^6)*8 = # of bits, and 1 megadata in base 16 s (16^6)*8 = # of bits.
-- console processing code needs to ignore unknown codes (namely, negative/positive numbes like: -3 or +4) (do not consider these parameters).
+- console processing code needs to ignore unknown codes (namely, negative/positive numbers like: -3 or +4) (do not consider these parameters).
-- rename f_not_equal_to to f_equal_to_not (and do similar changes).
-
-- Research/Implement optimizaton by using pointers to reduce the complecity of processing multi-depth structures, such as fss_nest:
+- Research/Implement optimizaton by using pointers to reduce the complexity of processing multi-depth structures, such as fss_nest:
this:
nests->array[nests->used].array[index].array[0] = xxx;
could become:
Then document this behavior.
The status code processing code are all out of alphabetic order and need cleanup.
+
+Go back through all existing f_file and f_directory code, updating return codes and respective documentation.
+Update f_utf_file and create a f_utf_directory?
+
+Remove empty projects and cleanup private functions.
#ifndef _di_fl_directory_clone_
f_return_status fl_directory_clone(const f_string source, const f_string destination, const f_string_length source_length, const f_string_length destination_length, const bool role, const f_number_unsigned size_block, const bool exclusive, f_directory_statuss *failures) {
- f_status status = F_none;
+ f_status status = f_directory_exists(source);
- status = f_directory_exists(source);
if (F_status_is_error(status)) return status;
if (status == F_false) return F_status_set_error(F_directory);
- const f_string_static static_source = { source, source_length, source_length };
- const f_string_static static_destination = { destination, destination_length, destination_length };
+ struct stat source_stat;
- status = private_fl_directory_clone(static_source, static_destination, role, size_block, exclusive, failures);
+ memset(&source_stat, 0, sizeof(struct stat));
- return F_none;
+ status = f_file_stat(source, F_false, &source_stat);
+ if (F_status_is_error(status)) return status;
+
+ status = f_directory_exists(destination);
+ if (F_status_is_error(status)) return status;
+
+ if (status == F_true) {
+ if (exclusive) {
+ return F_status_set_error(F_directory_found);
+ }
+
+ status = f_file_change_mode(destination, source_stat.st_mode);
+ if (F_status_is_error(status)) return status;
+ }
+ else {
+ status = f_directory_create(destination, source_stat.st_mode);
+ if (F_status_is_error(status)) return status;
+ }
+
+ if (role) {
+ status = f_file_change_owner(destination, source_stat.st_uid, source_stat.st_gid, F_true);
+ if (F_status_is_error(status)) return status;
+ }
+
+ f_string_static static_source = { source, source_length, source_length };
+ f_string_static static_destination = { destination, destination_length, destination_length };
+
+ // do not allow null termination or trailing path separators in the string's length calculation.
+ {
+ f_string_length i = source_length;
+
+ for (; i > 0; i--, static_source.used--) {
+ if (source[i - 1] == 0) continue;
+ if (source[i - 1] == f_path_separator[0]) continue;
+ break;
+ } // for
+
+ i = destination_length;
+
+ for (; i > 0; i--, static_destination.used--) {
+ if (destination[i - 1] == 0) continue;
+ if (destination[i - 1] == f_path_separator[0]) continue;
+ break;
+ } // for
+ }
+
+ return private_fl_directory_clone(static_source, static_destination, role, size_block, exclusive, failures);
}
#endif // _di_fl_directory_clone_
+#ifndef _di_fl_directory_clone_content_
+ f_return_status fl_directory_clone_content(const f_string source, const f_string destination, const f_string_length source_length, const f_string_length destination_length, const bool role, const f_number_unsigned size_block, const bool exclusive, f_directory_statuss *failures) {
+ f_status status = f_directory_exists(source);
+
+ if (F_status_is_error(status)) return status;
+ if (status == F_false) return F_status_set_error(F_directory);
+
+ status = f_directory_exists(destination);
+ if (F_status_is_error(status)) return status;
+ if (status == F_false) return F_status_set_error(F_directory);
+
+ f_string_static static_source = { source, source_length, source_length };
+ f_string_static static_destination = { destination, destination_length, destination_length };
+
+ // do not allow null termination or trailing path separators in the string's length calculation.
+ {
+ f_string_length i = source_length;
+
+ for (; i > 0; i--, static_source.used--) {
+ if (source[i - 1] == 0) continue;
+ if (source[i - 1] == f_path_separator[0]) continue;
+ break;
+ } // for
+
+ i = destination_length;
+
+ for (; i > 0; i--, static_destination.used--) {
+ if (destination[i - 1] == 0) continue;
+ if (destination[i - 1] == f_path_separator[0]) continue;
+ break;
+ } // for
+ }
+
+ return private_fl_directory_clone(static_source, static_destination, role, size_block, exclusive, failures);
+ }
+#endif // _di_fl_directory_clone_content_
+
#ifndef _di_fl_directory_copy_
f_return_status fl_directory_copy(const f_string source, const f_string destination, const f_string_length source_length, const f_string_length destination_length, const f_directory_mode mode, const f_number_unsigned size_block, const bool exclusive, f_directory_statuss *failures) {
- f_status status = F_none;
+ f_status status = f_directory_exists(source);
- status = f_directory_exists(source);
if (F_status_is_error(status)) return status;
if (status == F_false) return F_status_set_error(F_directory);
- const f_string_static static_source = { source, source_length, source_length };
- const f_string_static static_destination = { destination, destination_length, destination_length };
+ status = f_directory_exists(destination);
+ if (F_status_is_error(status)) return status;
- status = private_fl_directory_copy(static_source, static_destination, mode, size_block, exclusive, failures);
+ if (status == F_true) {
+ if (exclusive) {
+ return F_status_set_error(F_directory_found);
+ }
- return F_none;
+ status = f_file_change_mode(destination, mode.directory);
+ if (F_status_is_error(status)) return status;
+ }
+ else {
+ status = f_directory_create(destination, mode.directory);
+ if (F_status_is_error(status)) return status;
+ }
+
+ f_string_static static_source = { source, source_length, source_length };
+ f_string_static static_destination = { destination, destination_length, destination_length };
+
+ // do not allow null termination or trailing path separators in the string's length calculation.
+ {
+ f_string_length i = source_length;
+
+ for (; i > 0; i--, static_source.used--) {
+ if (source[i - 1] == 0) continue;
+ if (source[i - 1] == f_path_separator[0]) continue;
+ break;
+ } // for
+
+ i = destination_length;
+
+ for (; i > 0; i--, static_destination.used--) {
+ if (destination[i - 1] == 0) continue;
+ if (destination[i - 1] == f_path_separator[0]) continue;
+ break;
+ } // for
+ }
+
+ return private_fl_directory_copy(static_source, static_destination, mode, size_block, exclusive, failures);
}
#endif // _di_fl_directory_copy_
-#ifndef _di_fl_directory_list_
- f_return_status fl_directory_list(const f_string path, int (*filter)(const struct dirent *), int (*sort)(const struct dirent **, const struct dirent **), const bool dereference, f_directory_listing *listing) {
- #ifndef _di_level_2_parameter_checking_
- if (listing == 0) return F_status_set_error(F_parameter);
- #endif // _di_level_2_parameter_checking_
+#ifndef _di_fl_directory_copy_content_
+ f_return_status fl_directory_copy_content(const f_string source, const f_string destination, const f_string_length source_length, const f_string_length destination_length, const f_directory_mode mode, const f_number_unsigned size_block, const bool exclusive, f_directory_statuss *failures) {
+ f_status status = f_directory_exists(source);
- return private_fl_directory_list(path, filter, sort, dereference, listing);
+ if (F_status_is_error(status)) return status;
+ if (status == F_false) return F_status_set_error(F_directory);
+
+ status = f_directory_exists(destination);
+ if (F_status_is_error(status)) return status;
+ if (status == F_false) return F_status_set_error(F_directory);
+
+ f_string_static static_source = { source, source_length, source_length };
+ f_string_static static_destination = { destination, destination_length, destination_length };
+
+ // do not allow null termination or trailing path separators in the string's length calculation.
+ {
+ f_string_length i = source_length;
+
+ for (; i > 0; i--, static_source.used--) {
+ if (source[i - 1] == 0) continue;
+ if (source[i - 1] == f_path_separator[0]) continue;
+ break;
+ } // for
+
+ i = destination_length;
+
+ for (; i > 0; i--, static_destination.used--) {
+ if (destination[i - 1] == 0) continue;
+ if (destination[i - 1] == f_path_separator[0]) continue;
+ break;
+ } // for
+ }
+
+ return private_fl_directory_copy(static_source, static_destination, mode, size_block, exclusive, failures);
}
-#endif // _di_fl_directory_list_
+#endif // _di_fl_directory_copy_content_
-#ifndef _di_fl_directory_list_at_
- f_return_status fl_directory_list_at(const int at_id, const f_string path, int (*filter)(const struct dirent *), int (*sort)(const struct dirent **, const struct dirent **), const bool dereference, f_directory_listing *listing) {
+#ifndef _di_fl_directory_list_
+ f_return_status fl_directory_list(const f_string path, int (*filter)(const struct dirent *), int (*sort)(const struct dirent **, const struct dirent **), const bool dereference, f_directory_listing *listing) {
#ifndef _di_level_2_parameter_checking_
if (listing == 0) return F_status_set_error(F_parameter);
#endif // _di_level_2_parameter_checking_
- // @todo implement a directoy list that passes at_id to scandirat().
- // but... DIR * appears to be needed, can I just instead pass the path string instead? (char *).
-
return private_fl_directory_list(path, filter, sort, dereference, listing);
}
-#endif // _di_fl_directory_list_at_
+#endif // _di_fl_directory_list_
#ifndef _di_fl_directory_path_pop_
f_return_status fl_directory_path_pop(f_string_static *path) {
#endif
/**
- * Copy a file, as well as its file mode and possibly the owner and group.
+ * 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.
* The paths must be NULL terminated.
*
- * @todo provide a return status for when owner/role cannot be assigned.
- *
* Symbolic links are not followed, they are copied as the symbolic link itself.
*
* This does not copy unknown file types.
* 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 parent directory already exists.
- * If FALSE, will not fail if parent directory already exists (existing directory will be updated).
+ * If TRUE, will fail when file already exists.
+ * If FALSE, will not fail if file already exists (existing file will be replaced).
+ * @param failures
+ * A list of paths and their respective status codes for clone failures.
+ * If 0, then this and statuses is ignored.
*
* @return
* F_none on success.
* F_busy (with error bit) if filesystem is too busy to perforrm write.
* F_file_read (with error bit) on file read error.
* F_file_write (with error bit) on file write error.
- * F_directory_descriptor (with error bit) for bad directory descriptor for at_id.
*
- * @see f_directory_create()
* @see f_file_clone()
- * @see read()
*/
#ifndef _di_fl_directory_clone_
extern f_return_status fl_directory_clone(const f_string source, const f_string destination, const f_string_length source_length, const f_string_length destination_length, const bool role, const f_number_unsigned size_block, const bool exclusive, f_directory_statuss *failures);
#endif // _di_fl_directory_clone_
/**
+ * Copy a directory contents, as well as its file mode and possibly the owner and group.
+ *
+ * When cloning the contents of a directory, both the source and the destination paths must already exist and be directories, regardless of exclusive boolean.
+ *
+ * The paths must not contain NULL except for the terminating NULL.
+ * The paths must be NULL terminated.
+ *
+ * Symbolic links are not followed, they are copied as the symbolic link itself.
+ *
+ * This does not copy unknown file types.
+ *
+ * @param source
+ * The source file path.
+ * Must be NULL terminated.
+ * @param destination
+ * The destination file path.
+ * Must be NULL terminated.
+ * @param source_length
+ * The length of the source path.
+ * @param destination_length
+ * The length of the destination path.
+ * @param role
+ * 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 failures
+ * A list of paths and their respective status codes for clone failures.
+ * If 0, then this and statuses is ignored.
+ *
+ * @return
+ * F_none on success.
+ * F_parameter (with error bit) if a parameter is invalid.
+ * F_access_denied (with error bit) on access denied.
+ * F_loop (with error bit) on loop error.
+ * F_file_found (with error bit) if a file was found while exclusive is TRUE.
+ * F_memory_out (with error bit) if out of memory.
+ * F_memory_allocation (with error bit) on memory allocation error.
+ * F_memory_reallocation (with error bit) on memory re-allocation error.
+ * F_prohibited (with error bit) if filesystem does not allow for removing.
+ * F_read_only (with error bit) if file is read-only.
+ * F_failure (with error bit) for any other (mkdir()) error.
+ * F_filesystem_quota_block (with error bit) if filesystem's disk blocks or inodes are exhausted.
+ * F_filesystem_quota_reached (with error bit) quota reached of filesystem is out of space.
+ * F_file_found (with error bit) of a directory aleady exists at the path.
+ * F_name (with error bit) on path name error.
+ * F_directory (with error bit) if a supposed directory in path is not actually a directory.
+ * F_number_overflow (with error bit) on overflow error.
+ * F_interrupted (with error bit) when program received an interrupt signal, halting create.
+ * F_file_open_max (with error bit) when system-wide max open files is reached.
+ * F_busy (with error bit) if filesystem is too busy to perforrm write.
+ * F_file_read (with error bit) on file read error.
+ * F_file_write (with error bit) on file write error.
+ *
+ * @see f_file_clone()
+ */
+#ifndef _di_fl_directory_clone_content_
+ extern f_return_status fl_directory_clone_content(const f_string source, const f_string destination, const f_string_length source_length, const f_string_length destination_length, const bool role, const f_number_unsigned size_block, const bool exclusive, f_directory_statuss *failures);
+#endif // _di_fl_directory_clone_content_
+
+/**
* Copy a directory and its contents.
*
* The paths must not contain NULL except for the terminating NULL.
* @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 exclusive
+ * If TRUE, will fail when file already exists.
+ * If FALSE, will not fail if file already exists (existing file will be replaced).
* @param failures
* A list of paths and their respective status codes for copy failures.
* If 0, then this and statuses is ignored.
* F_busy (with error bit) if filesystem is too busy to perforrm write.
* F_file_read (with error bit) on file read error.
* F_file_write (with error bit) on file write error.
- * F_directory_descriptor (with error bit) for bad directory descriptor for at_id.
*
* @see f_file_copy()
- * @see read()
*/
#ifndef _di_fl_directory_copy_
extern f_return_status fl_directory_copy(const f_string source, const f_string destination, const f_string_length source_length, const f_string_length destination_length, const f_directory_mode mode, const f_number_unsigned size_block, const bool exclusive, f_directory_statuss *failures);
#endif // _di_fl_directory_copy_
/**
- * For some given path, print the names of each file and/or directory inside the directory, stored as a directory listing.
+ * Copy a directory contents.
*
- * Allows specifying a custom filter and custom sort.
+ * When copying the contents of a directory, both the source and the destination paths must already exist and be directories, regardless of exclusive boolean.
*
- * @param path
- * Filesystem path to the directory.
- * @param filter
- * A filter function of the form: int xxx(const struct direct *).
- * Set to 0 to not use (NULL).
- * @param sort
- * A sort function of the form: int xxx(const struct direct *, const struct direct *).
- * Set to 0 to not use (NULL).
- * There are two pre-made libc functions available for this: alphasort() and versionsort().
- * @param dereference
- * Set to TRUE to dereferenc symlinks (often is what is desired).
- * Set to FALSE to operate on the symlink itself.
- * @param listing
- * Will be populated with the names of all top-level paths found within the given directory.
+ * The paths must not contain NULL except for the terminating NULL.
+ * The paths must be NULL terminated.
+ *
+ * Symbolic links are not followed, they are copied as the symbolic link itself.
+ *
+ * This does not copy unknown file types.
+ *
+ * @param source
+ * The source file path.
+ * Must be NULL terminated.
+ * @param destination
+ * The destination file path.
+ * Must be NULL terminated.
+ * @param source_length
+ * The length of the source path.
+ * @param destination_length
+ * 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 failures
+ * A list of paths and their respective status codes for copy failures.
+ * If 0, then this and statuses is ignored.
*
* @return
* F_none on success.
- * F_data_not if directory is empty (@fixme: unlikely due to '.' and '..' probably always being returned.).
- * F_failure (with error bit) if failed to read directory information.
* F_parameter (with error bit) if a parameter is invalid.
- * F_memory_reallocation (with error bit) on memory reallocation error.
- * F_directory_open (with error bit) on directory open error.
- * F_directory_descriptor (with error bit) on directory file descriptor error.
- * F_directory_stream (with error bit) on directory stream error.
- * F_directory_unsupported (with error bit) on directory file descriptor not supported.
- * F_file_descriptor_max (with error bit) if max file descriptors was reached.
- * F_file_open_max (with error bit) too many open files.
+ * F_access_denied (with error bit) on access denied.
+ * F_loop (with error bit) on loop error.
+ * F_file_found (with error bit) if a file was found while exclusive is TRUE.
+ * F_memory_out (with error bit) if out of memory.
+ * F_memory_allocation (with error bit) on memory allocation error.
+ * F_memory_reallocation (with error bit) on memory re-allocation error.
+ * F_prohibited (with error bit) if filesystem does not allow for removing.
+ * F_read_only (with error bit) if file is read-only.
+ * F_failure (with error bit) for any other (mkdir()) error.
+ * F_filesystem_quota_block (with error bit) if filesystem's disk blocks or inodes are exhausted.
+ * F_filesystem_quota_reached (with error bit) quota reached of filesystem is out of space.
+ * F_file_found (with error bit) of a directory aleady exists at the path.
+ * F_name (with error bit) on path name error.
+ * F_directory (with error bit) if a supposed directory in path is not actually a directory.
+ * F_number_overflow (with error bit) on overflow error.
+ * F_interrupted (with error bit) when program received an interrupt signal, halting create.
+ * F_file_open_max (with error bit) when system-wide max open files is reached.
+ * F_busy (with error bit) if filesystem is too busy to perforrm write.
+ * F_file_read (with error bit) on file read error.
+ * F_file_write (with error bit) on file write error.
*
- * @see alphasort()
- * @see opendir()
- * @see scandir()
- * @see versionsort()
+ * @see f_file_copy()
*/
-#ifndef _di_fl_directory_list_
- extern f_return_status fl_directory_list(const f_string path, int (*filter)(const struct dirent *), int (*sort)(const struct dirent **, const struct dirent **), const bool dereference, f_directory_listing *listing);
-#endif // _di_fl_directory_list_
+#ifndef _di_fl_directory_copy_content_
+ extern f_return_status fl_directory_copy_content(const f_string source, const f_string destination, const f_string_length source_length, const f_string_length destination_length, const f_directory_mode mode, const f_number_unsigned size_block, const bool exclusive, f_directory_statuss *failures);
+#endif // _di_fl_directory_copy_content_
/**
* For some given path, print the names of each file and/or directory inside the directory, stored as a directory listing.
* @see scandir()
* @see versionsort()
*/
-#ifndef _di_fl_directory_list_at_
- extern f_return_status fl_directory_list_at(const int at_id, const f_string path, int (*filter)(const struct dirent *), int (*sort)(const struct dirent **, const struct dirent **), const bool dereference, f_directory_listing *listing);
-#endif // _di_fl_directory_list_at_
+#ifndef _di_fl_directory_list_
+ extern f_return_status fl_directory_list(const f_string path, int (*filter)(const struct dirent *), int (*sort)(const struct dirent **, const struct dirent **), const bool dereference, f_directory_listing *listing);
+#endif // _di_fl_directory_list_
/**
* Append a path string onto the destination path.
#if !defined(_di_fl_directory_clone_)
f_return_status private_fl_directory_clone(const f_string_static source, const f_string_static destination, const bool role, const f_number_unsigned size_block, const bool exclusive, f_directory_statuss *failures) {
- f_status status = f_directory_exists(source.string);
-
- if (F_status_is_error(status)) return status;
- if (status == F_false) return F_status_set_error(F_directory);
-
- struct stat source_stat;
-
- memset(&source_stat, 0, sizeof(struct stat));
-
- status = f_file_stat(source.string, F_false, &source_stat);
- if (F_status_is_error(status)) return status;
-
- status = f_directory_exists(destination.string);
- if (F_status_is_error(status)) return status;
-
- if (status == F_true) {
- if (exclusive) {
- return F_status_set_error(F_directory_found);
- }
-
- status = f_file_change_mode(destination.string, source_stat.st_mode);
- if (F_status_is_error(status)) return status;
- }
- else {
- status = f_directory_create(destination.string, source_stat.st_mode);
- if (F_status_is_error(status)) return status;
- }
-
- if (role) {
- status = f_file_change_owner(destination.string, source_stat.st_uid, source_stat.st_gid, F_true);
- if (F_status_is_error(status)) return status;
- }
-
+ f_status status = F_none;
f_directory_listing listing = f_directory_listing_initialize;
status = private_fl_directory_list(source.string, 0, 0, F_false, &listing);
source_sub.string = path_source_sub;
destination_sub.string = path_destination_sub;
+ status = f_directory_exists(source_sub.string);
+ if (F_status_is_error(status)) break;
+
+ if (status == F_false) {
+ status = F_status_set_error(F_directory);
+ break;
+ }
+
+ {
+ struct stat source_stat;
+
+ memset(&source_stat, 0, sizeof(struct stat));
+
+ status = f_file_stat(source_sub.string, F_false, &source_stat);
+ if (F_status_is_error(status)) break;
+
+ status = f_directory_exists(destination_sub.string);
+ if (F_status_is_error(status)) break;
+
+ if (status == F_true) {
+ if (exclusive) {
+ status = F_status_set_error(F_directory_found);
+ break;
+ }
+
+ status = f_file_change_mode(destination_sub.string, source_stat.st_mode);
+ if (F_status_is_error(status)) break;
+ }
+ else {
+ status = f_directory_create(destination_sub.string, source_stat.st_mode);
+ if (F_status_is_error(status)) break;
+ }
+
+ if (role) {
+ status = f_file_change_owner(destination_sub.string, source_stat.st_uid, source_stat.st_gid, F_true);
+ if (F_status_is_error(status)) break;
+ }
+ }
+
status = private_fl_directory_clone(source_sub, destination_sub, role, size_block, exclusive, failures);
} // for
#if !defined(_di_fl_directory_copy_)
f_return_status private_fl_directory_copy(const f_string_static source, const f_string_static destination, const f_directory_mode mode, const f_number_unsigned size_block, const bool exclusive, f_directory_statuss *failures) {
- f_status status = f_directory_exists(source.string);
-
- if (F_status_is_error(status)) return status;
- if (status == F_false) return F_status_set_error(F_directory);
-
- status = f_directory_exists(destination.string);
- if (F_status_is_error(status)) return status;
-
- if (status == F_true) {
- if (exclusive) {
- return F_status_set_error(F_directory_found);
- }
-
- status = f_file_change_mode(destination.string, mode.directory);
- if (F_status_is_error(status)) return status;
- }
- else {
- status = f_directory_create(destination.string, mode.directory);
- if (F_status_is_error(status)) return status;
- }
-
+ f_status status = F_none;
f_directory_listing listing = f_directory_listing_initialize;
status = private_fl_directory_list(source.string, 0, 0, F_false, &listing);
source_sub.string = path_source_sub;
destination_sub.string = path_destination_sub;
+ status = f_directory_exists(source_sub.string);
+ if (F_status_is_error(status)) break;
+
+ if (status == F_false) {
+ status = F_status_set_error(F_directory);
+ break;
+ }
+
+ status = f_directory_exists(destination_sub.string);
+ if (F_status_is_error(status)) break;
+
+ if (status == F_true) {
+ if (exclusive) {
+ status = F_status_set_error(F_directory_found);
+ break;
+ }
+
+ status = f_file_change_mode(destination_sub.string, mode.directory);
+ if (F_status_is_error(status)) break;
+ }
+ else {
+ status = f_directory_create(destination_sub.string, mode.directory);
+ if (F_status_is_error(status)) break;
+ }
+
status = private_fl_directory_copy(source_sub, destination_sub, mode, size_block, exclusive, failures);
} // for
* F_busy (with error bit) if filesystem is too busy to perforrm write.
* F_file_read (with error bit) on file read error.
* F_file_write (with error bit) on file write error.
- * F_directory_descriptor (with error bit) for bad directory descriptor for at_id.
*
* @see fl_directory_clone()
*/
* F_busy (with error bit) if filesystem is too busy to perforrm write.
* F_file_read (with error bit) on file read error.
* F_file_write (with error bit) on file write error.
- * F_directory_descriptor (with error bit) for bad directory descriptor for at_id.
*
* @see fl_directory_clone()
*/
* F_busy (with error bit) if filesystem is too busy to perforrm write.
* F_file_read (with error bit) on file read error.
* F_file_write (with error bit) on file write error.
- * F_directory_descriptor (with error bit) for bad directory descriptor for at_id.
*
* @see fl_directory_copy()
*/
* F_busy (with error bit) if filesystem is too busy to perforrm write.
* F_file_read (with error bit) on file read error.
* F_file_write (with error bit) on file write error.
- * F_directory_descriptor (with error bit) for bad directory descriptor for at_id.
*
* @see fl_directory_copy()
*/
}
#endif // _di_fl_string_dynamic_terminate_
+#ifndef _di_fl_string_dynamic_terminate_after_
+ f_return_status fl_string_dynamic_terminate_after(f_string_dynamic *destination) {
+ #ifndef _di_level_1_parameter_checking_
+ if (destination == 0) return F_status_set_error(F_parameter);
+ if (destination->used > destination->size) return F_status_set_error(F_parameter);
+ #endif // _di_level_1_parameter_checking_
+
+ if (destination->used > 0) {
+ for (f_string_length i = destination->used; i > 0; i--, destination->used--) {
+ if (destination->string[i] == 0) continue;
+ break;
+ } // for
+ }
+
+ if (destination->used + 1 > f_string_length_size) return F_status_set_error(F_string_too_large);
+
+ const f_string_length total = destination->used + 1;
+
+ if (total > destination->size) {
+ f_status status = F_none;
+
+ f_macro_string_dynamic_resize(status, (*destination), total);
+ if (F_status_is_error(status)) return status;
+ }
+
+ destination->string[destination->used] = 0;
+ destination->used = total - 1;
+
+ return F_none;
+ }
+#endif // _di_fl_string_dynamic_terminate_after_
+
#ifndef _di_fl_string_mash_
f_return_status fl_string_mash(const f_string glue, const f_string_length glue_length, const f_string source, const f_string_length length, f_string_dynamic *destination) {
#ifndef _di_level_1_parameter_checking_
#endif // _di_fl_string_dynamic_terminate_
/**
+ * Guarantee that an end of string (NULL) exists at the end of the string.
+ *
+ * This ensures that the terminating NULL not only exists but is not counted in destination.used.
+ *
+ * This is intended to be used for anything requiring NULL terminated strings whose used length cannot be counted.
+ * This will reallocate more space if necessary.
+ *
+ * If destination size is 0, then it will be reallocated and have the NULL assigned at index 0.
+ *
+ * @param destination
+ * The new string, which will be allocated or reallocated as necessary.
+ *
+ * @return
+ * F_none on success.
+ * F_parameter (with error bit) if a parameter is invalid.
+ * F_memory_reallocation (with error bit) on memory reallocation error.
+ * F_string_too_large (with error bit) if string is too large to fit into the buffer.
+ */
+#ifndef _di_fl_string_dynamic_terminate_after_
+ extern f_return_status fl_string_dynamic_terminate_after(f_string_dynamic *destination);
+#endif // _di_fl_string_dynamic_terminate_after_
+
+/**
* Append the source string onto the destination with the glue in between.
*
* If the destination string is empty, then no glue is appended.