]> Kevux Git Server - fll/commitdiff
Update: rename f_file_move to f_file_rename, add fll_file_move, and address printf().
authorKevin Day <thekevinday@gmail.com>
Thu, 10 Sep 2020 02:39:03 +0000 (21:39 -0500)
committerKevin Day <thekevinday@gmail.com>
Thu, 10 Sep 2020 02:39:03 +0000 (21:39 -0500)
The move function should operate as a move would expect, which includes cross-filesystem.
Rename the f_file_move() to f_file_rename() and ensure the limitations are documented.

The fll_file_move()  calls f_file_rename() and if that fails due to being across filesystems, then call the appropriate clone and remove functions depending on whether or not the source is a file or directory.

I try to avoid having any output strings in the project that is below level 3 (but level 2 may have exceptions).
Rewrite parts of the directory copy and clone functions to use passed functions instead of directly printing.

Cleanup some function's documentation.

14 files changed:
level_0/f_directory/c/directory.c
level_0/f_directory/c/directory.h
level_0/f_file/c/file.c
level_0/f_file/c/file.h
level_1/fl_directory/c/directory.c
level_1/fl_directory/c/directory.h
level_1/fl_directory/c/private-directory.c
level_1/fl_directory/c/private-directory.h
level_2/fll_file/c/file.c
level_2/fll_file/c/file.h
level_3/fake/c/private-build.c
level_3/fake/c/private-fake.c
level_3/fake/c/private-fake.h
level_3/fake/c/private-make.c

index 0e34916b59ecb542d4158c4d9ee0633224509565..a141a1e5bcb90c53ca21ebdce5dd008f464523f5 100644 (file)
@@ -255,15 +255,15 @@ extern "C" {
 #endif // _di_f_directory_open_at_
 
 #ifndef _di_f_directory_remove_
-  f_return_status f_directory_remove(const f_string_t path, const int recursion_max, const bool preserve) {
+  f_return_status f_directory_remove(const f_string_t path, const int depth_max, const bool preserve) {
     #ifndef _di_level_0_parameter_checking_
-      if (recursion_max < 0) return F_status_set_error(F_parameter);
+      if (depth_max < 0) return F_status_set_error(F_parameter);
     #endif // _di_level_0_parameter_checking_
 
     int result = 0;
 
-    if (recursion_max) {
-      result = nftw(path, private_f_directory_remove_recursively, recursion_max, FTW_DEPTH | FTW_PHYS);
+    if (depth_max) {
+      result = nftw(path, private_f_directory_remove_recursively, depth_max, FTW_DEPTH | FTW_PHYS);
 
       if (result == 0 && !preserve) {
         result = remove(path);
@@ -302,15 +302,15 @@ extern "C" {
 #endif // _di_f_directory_remove_
 
 #ifndef _di_f_directory_remove_custom_
-  f_return_status f_directory_remove_custom(const f_string_t path, const int recursion_max, const bool preserve, int (*custom) (const char *, const struct stat *, int, struct FTW *)) {
+  f_return_status f_directory_remove_custom(const f_string_t path, const int depth_max, const bool preserve, int (*custom) (const char *, const struct stat *, int, struct FTW *)) {
     #ifndef _di_level_0_parameter_checking_
-      if (recursion_max < 0) return F_status_set_error(F_parameter);
+      if (depth_max < 0) return F_status_set_error(F_parameter);
     #endif // _di_level_0_parameter_checking_
 
     int result = 0;
 
-    if (recursion_max) {
-      result = nftw(path, custom, recursion_max, FTW_DEPTH | FTW_PHYS);
+    if (depth_max) {
+      result = nftw(path, custom, depth_max, FTW_DEPTH | FTW_PHYS);
 
       if (result == 0 && !preserve) {
         result = remove(path);
index d22f6bb47b74cd17685f82e3d3a93b3fe8a0150d..5af8a0beba9929ff0db70e8f11a0d0c8075ad041 100644 (file)
@@ -381,13 +381,13 @@ extern "C" {
  *
  * @param path
  *   The file path to the directory.
- * @param recursion_max
+ * @param depth_max
  *   Represents the max recursion depth, set to 0 to disable recursive delete.
  * @param preserve
- *   When recursion_max > 0, this designates whether or not to preserve the directory at path.
+ *   When depth_max > 0, this designates whether or not to preserve the directory at path.
  *   If TRUE, then only the content within the directory is deleted.
  *   If FALSE, then the directory at path and its content are deleted.
- *   When recursion_max is 0, then this should only be FALSE (setting this to TRUE would be a no-op).
+ *   When depth_max is 0, then this should only be FALSE (setting this to TRUE would be a no-op).
  *
  * @return
  *   F_none on success.
@@ -412,7 +412,7 @@ extern "C" {
  * @see remove()
  */
 #ifndef _di_f_directory_remove_
-  extern f_return_status f_directory_remove(const f_string_t path, const int recursion_max, const bool preserve);
+  extern f_return_status f_directory_remove(const f_string_t path, const int depth_max, const bool preserve);
 #endif // _di_f_directory_remove_
 
 /**
@@ -420,13 +420,13 @@ extern "C" {
  *
  * @param path
  *   The file path to the directory.
- * @param recursion_max
+ * @param depth_max
  *   Represents the max recursion depth, set to 0 to disable recursive delete.
  * @param preserve
- *   When recursion_max > 0, this designates whether or not to preserve the directory at path.
+ *   When depth_max > 0, this designates whether or not to preserve the directory at path.
  *   If TRUE, then only the content within the directory is deleted.
  *   If FALSE, then the directory at path and its content are deleted.
- *   When recursion_max is 0, then this should only be FALSE (setting this to TRUE would be a no-op).
+ *   When depth_max is 0, then this should only be FALSE (setting this to TRUE would be a no-op).
  * @param custom
  *   A custom function to pass to nftw() instead of using the internal one.
  *   Such as a custom function for verbose printing of removed files.
@@ -454,7 +454,7 @@ extern "C" {
  * @see remove()
  */
 #ifndef _di_f_directory_remove_custom_
-  extern f_return_status f_directory_remove_custom(const f_string_t path, const int recursion_max, const bool preserve, int (*custom) (const char *, const struct stat *, int, struct FTW *));
+  extern f_return_status f_directory_remove_custom(const f_string_t path, const int depth_max, const bool preserve, int (*custom) (const char *, const struct stat *, int, struct FTW *));
 #endif // _di_f_directory_remove_custom_
 
 /**
index cf422f8319cffdcf1fdd39b1e006e6a933ff40de..ddd834b457505e62e20b5a8857c547279f92d023 100644 (file)
@@ -1318,8 +1318,8 @@ extern "C" {
   }
 #endif // _di_f_file_mode_to_mode_
 
-#ifndef _di_f_file_move_
-  f_return_status f_file_move(const f_string_t source, const f_string_t destination) {
+#ifndef _di_f_file_rename_
+  f_return_status f_file_rename(const f_string_t source, const f_string_t destination) {
     #ifndef _di_level_0_parameter_checking_
       if (source == 0) return F_status_set_error(F_parameter);
       if (destination == 0) return F_status_set_error(F_parameter);
@@ -1350,10 +1350,10 @@ extern "C" {
 
     return F_none;
   }
-#endif // _di_f_file_move_
+#endif // _di_f_file_rename_
 
-#ifndef _di_f_file_move_at_
-  f_return_status f_file_move_at(const int at_id, const int to_id, const f_string_t source, const f_string_t destination) {
+#ifndef _di_f_file_rename_at_
+  f_return_status f_file_rename_at(const int at_id, const int to_id, const f_string_t source, const f_string_t destination) {
     #ifndef _di_level_0_parameter_checking_
       if (source == 0) return F_status_set_error(F_parameter);
       if (destination == 0) return F_status_set_error(F_parameter);
@@ -1385,7 +1385,7 @@ extern "C" {
 
     return F_none;
   }
-#endif // _di_f_file_move_at_
+#endif // _di_f_file_rename_at_
 
 #ifndef _di_f_file_name_base_
   f_return_status f_file_name_base(const f_string_t path, const f_string_length_t length, f_string_dynamic_t *name_base) {
index dafef8868baeb290780bbdd982324389e8109f20..2ffe9ea499d324aa699e1d24c40f63d8f99456e5 100644 (file)
@@ -1446,19 +1446,16 @@ extern "C" {
 #endif // _di_f_file_mode_to_mode_
 
 /**
- * Move a file.
+ * Rename a file.
  *
  * The paths must not contain NULL except for the terminating NULL.
  * The paths must be NULL terminated.
  *
- * This essentially renames a file but can also change the file's path, which is therefore a move.
+ * This essentially renames a file but can also change the file's path, which is identical to a move.
+ * However, renames only work within a filesystem and cannot be moved to another filesystem.
  *
  * If destination already exists, then according to rename(), destination will be atomically replaced.
- * Which, if destination is a directory must either not exist or be empty.
- *
- * It is recommended to perform an existence test on destination to not have to consider the details on how rename() operates with an existing destination.
- *
- * @todo consider handling F_mount error internally, copying across filesystem and then removing file on success.
+ * Which, if destination is a directory, then that directory must either not exist or be empty.
  *
  * @param source
  *   The path to the file to copy from.
@@ -1488,24 +1485,21 @@ extern "C" {
  *
  * @see rename()
  */
-#ifndef _di_f_file_move_
-  extern f_return_status f_file_move(const f_string_t source, const f_string_t destination);
-#endif // _di_f_file_move_
+#ifndef _di_f_file_rename_
+  extern f_return_status f_file_rename(const f_string_t source, const f_string_t destination);
+#endif // _di_f_file_rename_
 
 /**
- * Move a file.
+ * Rename a file.
  *
  * The paths must not contain NULL except for the terminating NULL.
  * The paths must be NULL terminated.
  *
- * This essentially renames a file but can also change the file's path, which is therefore a move.
+ * This essentially renames a file but can also change the file's path, which is identical to a move.
+ * However, renames only work within a filesystem and cannot be moved to another filesystem.
  *
  * If destination already exists, then according to rename(), destination will be atomically replaced.
- * Which, if destination is a directory must either not exist or be empty.
- *
- * It is recommended to perform an existence test on destination to not have to consider the details on how rename() operates with an existing destination.
- *
- * @todo consider handling F_mount error internally, copying across filesystem and then removing file on success.
+ * Which, if destination is a directory, then that directory must either not exist or be empty.
  *
  * @param at_id
  *   The parent directory, as an open directory file descriptor, in which the source is relative to.
@@ -1540,9 +1534,9 @@ extern "C" {
  *
  * @see renameat()
  */
-#ifndef _di_f_file_move_at_
-  extern f_return_status f_file_move_at(const int at_id, const int to_id, const f_string_t source, const f_string_t destination);
-#endif // _di_f_file_move_at_
+#ifndef _di_f_file_rename_at_
+  extern f_return_status f_file_rename_at(const int at_id, const int to_id, const f_string_t source, const f_string_t destination);
+#endif // _di_f_file_rename_at_
 
 /**
  * Get the base name of a file path.
index 49864e9c9d5518457f5d216c75bd98402d562f04..18572b934025b5c4568fc72952fa21ea70ad753a 100644 (file)
@@ -45,10 +45,6 @@ extern "C" {
       if (F_status_is_error(status)) return status;
     }
 
-    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 };
     f_string_static_t static_destination = { destination, destination_length, destination_length };
 
@@ -71,11 +67,15 @@ extern "C" {
       } // for
     }
 
-    if (recurse.depth_max == 0) {
-      return status;
+    if (recurse.depth_max) {
+      status = private_fl_directory_clone(static_source, static_destination, role, recurse, 1);
+    }
+
+    if (status == F_none && recurse.output && recurse.verbose) {
+      recurse.verbose(recurse.output, source, destination);
     }
 
-    return private_fl_directory_clone(static_source, static_destination, role, recurse, 1);
+    return status;
   }
 #endif // _di_fl_directory_clone_
 
@@ -121,7 +121,15 @@ extern "C" {
       return status;
     }
 
-    return private_fl_directory_clone(static_source, static_destination, role, recurse, 1);
+    if (recurse.depth_max) {
+      status = private_fl_directory_clone(static_source, static_destination, role, recurse, 1);
+    }
+
+    if (status == F_none && recurse.output && recurse.verbose) {
+      recurse.verbose(recurse.output, source, destination);
+    }
+
+    return status;
   }
 #endif // _di_fl_directory_clone_content_
 
@@ -153,10 +161,6 @@ extern "C" {
       if (F_status_is_error(status)) return status;
     }
 
-    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 };
     f_string_static_t static_destination = { destination, destination_length, destination_length };
 
@@ -179,11 +183,15 @@ extern "C" {
       } // for
     }
 
-    if (recurse.depth_max == 0) {
-      return status;
+    if (recurse.depth_max) {
+      status = private_fl_directory_copy(static_source, static_destination, mode, recurse, 1);
+    }
+
+    if (status == F_none && recurse.output && recurse.verbose) {
+      recurse.verbose(recurse.output, source, destination);
     }
 
-    return private_fl_directory_copy(static_source, static_destination, mode, recurse, 1);
+    return status;
   }
 #endif // _di_fl_directory_copy_
 
@@ -225,11 +233,15 @@ extern "C" {
       } // for
     }
 
-    if (recurse.depth_max == 0) {
-      return status;
+    if (recurse.depth_max) {
+      status = private_fl_directory_copy(static_source, static_destination, mode, recurse, 1);
+    }
+
+    if (status == F_none && recurse.output && recurse.verbose) {
+      recurse.verbose(recurse.output, source, destination);
     }
 
-    return private_fl_directory_copy(static_source, static_destination, mode, recurse, 1);
+    return status;
   }
 #endif // _di_fl_directory_copy_content_
 
index 924add598bdb418bd3fa0a104554232c826f4187..0fe6b09f24690035cd79d03462cd43e2a80fa02f 100644 (file)
@@ -57,9 +57,16 @@ extern "C" {
  * exclusive:
  *   If TRUE, will fail when file already exists.
  *   If FALSE, will not fail if file already exists (existing file will be replaced).
+ * output:
+ *   Set to 0 to not print on successful operation.
+ *   Set to a valid file pointer to print to on successful operation.
+ *   This is passed to the verbose function if that function pointer is not 0.
  * 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.
+ *   Set to 0 to not print on successful operation.
+ *   Set to address of a function to be called for printing such that:
+ *     - The first parameter represents the file pointer from the output variable.
+ *     - The second parameter represents the source string.
+ *     - The third parameter represents the destination string.
  * failures:
  *   A list of paths and their respective status codes for clone failures.
  *   If 0, then this and statuses are ignored.
@@ -71,11 +78,12 @@ extern "C" {
     f_number_unsigned_t depth_max;
     f_number_unsigned_t size_block;
     bool exclusive;
-    FILE *verbose;
+    FILE *output;
+    void (*verbose)(FILE *, const f_string_t, const f_string_t);
     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 }
+  #define fl_directory_recurse_t_initialize { fl_directory_recurse_depth_max, f_file_default_read_size, F_false, 0, 0, 0 }
 #endif // _di_fl_directory_recurse_t_
 
 /**
@@ -107,16 +115,6 @@ extern "C" {
  *
  * @return
  *   F_none on success.
- *   F_data_not if directory is empty.
- *   F_directory_descriptor (with error bit) on directory file descriptor error.
- *   F_directory_open (with error bit) on directory open 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_memory_reallocation (with error bit) on memory reallocation error.
- *   F_parameter (with error bit) if a parameter is invalid.
- *   F_string_too_large (with error bit) if appended string length is too large to store in the buffer.
  *   F_failure (with error bit) for any other failure, failures might be populated with individual status codes.
  *
  *   Errors from (with error bit): f_directory_create().
@@ -162,16 +160,6 @@ extern "C" {
  *
  * @return
  *   F_none on success.
- *   F_data_not if directory is empty.
- *   F_directory_descriptor (with error bit) on directory file descriptor error.
- *   F_directory_open (with error bit) on directory open 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_memory_reallocation (with error bit) on memory reallocation error.
- *   F_parameter (with error bit) if a parameter is invalid.
- *   F_string_too_large (with error bit) if appended string length is too large to store in the buffer.
  *   F_failure (with error bit) for any other failure, failures might be populated with individual status codes.
  *
  *   Errors from (with error bit): f_directory_exists().
@@ -209,16 +197,6 @@ extern "C" {
  *
  * @return
  *   F_none on success.
- *   F_data_not if directory is empty.
- *   F_directory_descriptor (with error bit) on directory file descriptor error.
- *   F_directory_open (with error bit) on directory open 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_memory_reallocation (with error bit) on memory reallocation error.
- *   F_parameter (with error bit) if a parameter is invalid.
- *   F_string_too_large (with error bit) if appended string length is too large to store in the buffer.
  *   F_failure (with error bit) for any other failure, failures might be populated with individual status codes.
  *
  *   Errors from (with error bit): f_directory_create().
@@ -262,16 +240,6 @@ extern "C" {
  *
  * @return
  *   F_none on success.
- *   F_data_not if directory is empty.
- *   F_directory_descriptor (with error bit) on directory file descriptor error.
- *   F_directory_open (with error bit) on directory open 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_memory_reallocation (with error bit) on memory reallocation error.
- *   F_parameter (with error bit) if a parameter is invalid.
- *   F_string_too_large (with error bit) if appended string length is too large to store in the buffer.
  *   F_failure (with error bit) for any other failure, failures might be populated with individual status codes.
  *
  *   Errors from (with error bit): f_directory_exists().
index 775bad8fde54b51d270dee051e16ec5f03db9da7..0a75acf3dabca9e846bb8cf70e0428e4e6eb9f1a 100644 (file)
@@ -113,6 +113,10 @@ extern "C" {
 
       if (depth < recurse.depth_max) {
         status = private_fl_directory_clone(source_sub, destination_sub, role, recurse, depth + 1);
+
+        if (status == F_none && recurse.output && recurse.verbose) {
+          recurse.verbose(recurse.output, source_sub.string, destination_sub.string);
+        }
       }
     } // for
 
@@ -202,8 +206,8 @@ extern "C" {
       return F_failure;
     }
 
-    if (recurse.verbose) {
-      fprintf(recurse.verbose, "Cloned '%s' to '%s'.%c", path_source, path_destination, f_string_eol[0]);
+    if (recurse.output && recurse.verbose) {
+      recurse.verbose(recurse.output, path_source, path_destination);
     }
 
     return F_none;
@@ -304,6 +308,10 @@ extern "C" {
 
       if (depth < recurse.depth_max) {
         status = private_fl_directory_copy(source_sub, destination_sub, mode, recurse, depth + 1);
+
+        if (status == F_none && recurse.output && recurse.verbose) {
+          recurse.verbose(recurse.output, source_sub.string, destination_sub.string);
+        }
       }
     } // for
 
@@ -393,8 +401,8 @@ extern "C" {
       return F_failure;
     }
 
-    if (recurse.verbose) {
-      fprintf(recurse.verbose, "Copied '%s' to '%s'.%c", path_source, path_destination, f_string_eol[0]);
+    if (recurse.output && recurse.verbose) {
+      recurse.verbose(recurse.output, path_source, path_destination);
     }
 
     return F_none;
index c76154b91e2a326d5dd66b9c7e59d5decfec967c..ef6fdcfda32be9ea09a419fad915f1a9fdafa839 100644 (file)
@@ -36,16 +36,6 @@ extern "C" {
  *
  * @return
  *   F_none on success.
- *   F_data_not if directory is empty.
- *   F_directory_descriptor (with error bit) on directory file descriptor error.
- *   F_directory_open (with error bit) on directory open 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_memory_reallocation (with error bit) on memory reallocation error.
- *   F_parameter (with error bit) if a parameter is invalid.
- *   F_string_too_large (with error bit) if appended string length is too large to store in the buffer.
  *   F_failure (with error bit) for any other failure, failures might be populated with individual status codes.
  *
  * @see fl_directory_clone()
@@ -77,17 +67,6 @@ extern "C" {
  *
  * @return
  *   F_none on success.
- *   F_data_not if directory is empty.
- *   F_buffer_too_large (with error bit) if a buffer would exceed max length.
- *   F_directory_descriptor (with error bit) on directory file descriptor error.
- *   F_directory_open (with error bit) on directory open 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_memory_reallocation (with error bit) on memory reallocation error.
- *   F_parameter (with error bit) if a parameter is invalid.
- *   F_string_too_large (with error bit) if appended string length is too large to store in the buffer.
  *   F_failure (with error bit) for any other failure, failures might be populated with individual status codes.
  *
  * @see fl_directory_clone()
@@ -116,16 +95,6 @@ extern "C" {
  *
  * @return
  *   F_none on success.
- *   F_data_not if directory is empty.
- *   F_directory_descriptor (with error bit) on directory file descriptor error.
- *   F_directory_open (with error bit) on directory open 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_memory_reallocation (with error bit) on memory reallocation error.
- *   F_parameter (with error bit) if a parameter is invalid.
- *   F_string_too_large (with error bit) if appended string length is too large to store in the buffer.
  *   F_failure (with error bit) for any other failure, failures might be populated with individual status codes.
  *
  * @see fl_directory_copy()
@@ -155,16 +124,6 @@ extern "C" {
  *
  * @return
  *   F_none on success.
- *   F_data_not if directory is empty.
- *   F_directory_descriptor (with error bit) on directory file descriptor error.
- *   F_directory_open (with error bit) on directory open 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_memory_reallocation (with error bit) on memory reallocation error.
- *   F_parameter (with error bit) if a parameter is invalid.
- *   F_string_too_large (with error bit) if appended string length is too large to store in the buffer.
  *   F_failure (with error bit) for any other failure, failures might be populated with individual status codes.
  *
  * @see fl_directory_copy()
index 2bbb6cf27248ec2a37984b02b64f7a52693c0aff..bde11f13d88a6b1c75dec5e0fd789c5ed1e264b8 100644 (file)
@@ -66,20 +66,78 @@ extern "C" {
 
 #ifndef _di_fll_file_mode_set_all_
   f_return_status fll_file_mode_set_all(const f_string_t path, const mode_t mode, const f_number_unsigned_t depth_max) {
-    #ifndef _di_level_0_parameter_checking_
-      if (path == 0) return F_status_set_error(F_parameter);
-    #endif // _di_level_0_parameter_checking_
+    #ifndef _di_level_2_parameter_checking_
+      if (!path) return F_status_set_error(F_parameter);
+    #endif // _di_level_2_parameter_checking_
 
     return private_fll_file_mode_set_all(path, mode, depth_max, 0);
   }
-#endif // _di_fll_file_mode_set_all__
+#endif // _di_fll_file_mode_set_all_
+
+#ifndef _di_fll_file_move_
+  f_return_status fll_file_move(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 fl_directory_recurse_t recurse) {
+    #ifndef _di_level_2_parameter_checking_
+      if (!source) return F_status_set_error(F_parameter);
+      if (!destination) return F_status_set_error(F_parameter);
+    #endif // _di_level_2_parameter_checking_
+
+    f_status_t status = f_file_rename(source, destination);
+
+    if (F_status_set_fine(status) != F_mount) {
+      if (status == F_none && recurse.output && recurse.verbose) {
+        recurse.verbose(recurse.output, source, destination);
+      }
+
+      return status;
+    }
+
+    status = f_file_is(source, f_file_type_directory, F_false);
+
+    if (status == F_file_found_not) {
+      return F_status_set_error(status);
+    }
+
+    if (F_status_is_error(status)) {
+      return status;
+    }
+
+    if (status == F_true) {
+      status = fl_directory_clone(source, destination, source_length, destination_length, F_true, recurse);
+
+      if (F_status_is_error(status)) {
+        return status;
+      }
+
+      status = f_directory_remove(source, recurse.depth_max, F_false);
+
+      if (status == F_none && recurse.output && recurse.verbose) {
+        recurse.verbose(recurse.output, source, destination);
+      }
+    }
+    else {
+      status = f_file_clone(source, destination, F_true, recurse.size_block, recurse.exclusive);
+
+      if (F_status_is_error(status)) {
+        return status;
+      }
+
+      status = f_file_remove(source);
+
+      if (status == F_none && recurse.output && recurse.verbose) {
+        recurse.verbose(recurse.output, source, destination);
+      }
+    }
+
+    return status;
+  }
+#endif // _di_fll_file_move_
 
 #ifndef _di_fll_file_role_change_all_
   f_return_status 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) {
-    #ifndef _di_level_0_parameter_checking_
-      if (path == 0) return F_status_set_error(F_parameter);
+    #ifndef _di_level_2_parameter_checking_
+      if (!path) return F_status_set_error(F_parameter);
       if (uid == -1 && gid == -1) return F_status_set_error(F_parameter);
-    #endif // _di_level_0_parameter_checking_
+    #endif // _di_level_2_parameter_checking_
 
     return private_fll_file_role_change_all(path, uid, gid, dereference, depth_max, 0);
   }
index c3b068fad68cf9f2c68bf7b38cfecf91aa08b53a..66d70c82b27ba68b850eb37b675614d1d8cbcdb4 100644 (file)
@@ -86,6 +86,66 @@ extern "C" {
 #endif // _di_fll_file_mode_set_all_
 
 /**
+ * Move a file.
+ *
+ * The paths must not contain NULL except for the terminating NULL.
+ * The paths must be NULL terminated.
+ *
+ * This attempts to rename a file but if the file is on another filesystem then it tries to clone the file or directory.
+ * If the file or directory is cloned, then the original is deleted after a successful copy.
+ *
+ * When this calls the additional functions, if the clone succeeds but the remove fails the source may exist.
+ * Therefore, if there is an error during remove, then the file should be checked for existence and possibly be manually removed.
+ *
+ * @param source
+ *   The path to the file to copy from.
+ * @param destination
+ *   The path to copy to.
+ * @param source_length
+ *   The length of the source path.
+ * @param destination_length
+ *   The length of the destination path.
+ * @param recurse
+ *   The directory recurse data.
+ *
+ * @return
+ *   F_none on success.
+ *   F_access_denied (with error bit) on access denied.
+ *   F_buffer (with error bit) if the buffer is invalid.
+ *   F_busy (with error bit) if filesystem is too busy to perform write.
+ *   F_directory (with error bit) if a supposed directory in path is not actually a directory.
+ *   F_directory_empty_not (with error bit) if the destination is a non-empty directory.
+ *   F_file_found_not (with error bit) if file at path was not found.
+ *   F_file_type_directory (with error bit) if destination is a directory but source is not.
+ *   F_filesystem_quota_block (with error bit) if filesystem's disk blocks or inodes are exhausted.
+ *   F_link (with error bit) if source or destination has the maxiumum associated links.
+ *   F_loop (with error bit) on loop error.
+ *   F_memory_out (with error bit) if out of memory.
+ *   F_name (with error bit) on path name error.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_prohibited (with error bit) if filesystem does not allow for making changes.
+ *   F_read_only (with error bit) if file is read-only.
+ *   F_space_not (with error bit) if filesystem is out of space (or filesystem quota is reached).
+ *   F_failure (with error bit) for any other error, failures might be populated with individual status codes.
+ *
+ *   Errors from (with error bit): f_directory_remove_custom().
+ *   Errors from (with error bit): f_file_is().
+ *   Errors from (with error bit): f_file_remove().
+ *   Errors from (with error bit): f_file_rename().
+ *   Errors from (with error bit): fl_directory_clone().
+ *
+ * @see f_directory_remove()
+ * @see f_directory_remove_custom()
+ * @see f_file_is()
+ * @see f_file_remove()
+ * @see f_file_rename()
+ * @see fl_directory_clone()
+ */
+#ifndef _di_fll_file_move_
+  extern f_return_status fll_file_move(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 fl_directory_recurse_t recurse);
+#endif // _di_fll_file_move_
+
+/**
  * Change owner and/or group of a given file at the specified path.
  *
  * At least one of uid or gid must not be -1.
index 26683d30b02602793efd6252b8895e5fcd39d654..172b679006d35b7952ba531627cc4c16e90231fd 100644 (file)
@@ -180,7 +180,8 @@ extern "C" {
     fl_directory_recurse_t recurse = fl_directory_recurse_t_initialize;
 
     if (data.verbosity == fake_verbosity_verbose) {
-      recurse.verbose = f_type_output;
+      recurse.output = f_type_output;
+      recurse.verbose = fake_verbose_print_copy;
     }
 
     recurse.failures = &failures;
index 07dbb43a4eab62381ea50cd875b460dd0cd9be43..db4a6946d85daa2141b7992c87520a62fb00dccd 100644 (file)
@@ -954,6 +954,24 @@ extern "C" {
   }
 #endif // _di_fake_validate_parameter_directories_
 
+#ifndef _di_fake_verbose_print_clone_
+  void fake_verbose_print_clone(FILE *output, const f_string_t source, const f_string_t destination) {
+    fprintf(output, "Cloned '%s' to '%s'.%c", source, destination, f_string_eol[0]);
+  }
+#endif // _di_fake_verbose_print_clone_
+
+#ifndef _di_fake_verbose_print_copy_
+  void fake_verbose_print_copy(FILE *output, const f_string_t source, const f_string_t destination) {
+    fprintf(output, "Copied '%s' to '%s'.%c", source, destination, f_string_eol[0]);
+  }
+#endif // _di_fake_verbose_print_copy_
+
+#ifndef _di_fake_verbose_print_move_
+  void fake_verbose_print_move(FILE *output, const f_string_t source, const f_string_t destination) {
+    fprintf(output, "Moved '%s' to '%s'.%c", source, destination, f_string_eol[0]);
+  }
+#endif // _di_fake_verbose_print_move_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index a768078421ddd13498ce91a7d9e80932f8cd2049..eed761fc57b42f0905500710c9afe55961b55645 100644 (file)
@@ -153,6 +153,48 @@ extern "C" {
   extern f_return_status fake_validate_parameter_directories(const f_console_arguments_t arguments, const fake_data_t data) f_gcc_attribute_visibility_internal;
 #endif // _di_fake_validate_parameter_directories_
 
+/**
+ * Helper function for performing a verbose print for a file clone operation.
+ *
+ * @param output
+ *   A file pointer to print to, such as stdout.
+ * @param source
+ *   The source string.
+ * @param destination
+ *   The destination string.
+ */
+#ifndef _di_fake_verbose_print_clone_
+  extern void fake_verbose_print_clone(FILE *output, const f_string_t source, const f_string_t destination) f_gcc_attribute_visibility_internal;
+#endif // _di_fake_verbose_print_clone_
+
+/**
+ * Helper function for performing a verbose print for a file copy operation.
+ *
+ * @param output
+ *   A file pointer to print to, such as stdout.
+ * @param source
+ *   The source string.
+ * @param destination
+ *   The destination string.
+ */
+#ifndef _di_fake_verbose_print_copy_
+  extern void fake_verbose_print_copy(FILE *output, const f_string_t source, const f_string_t destination) f_gcc_attribute_visibility_internal;
+#endif // _di_fake_verbose_print_copy_
+
+/**
+ * Helper function for performing a verbose print for a file move operation.
+ *
+ * @param output
+ *   A file pointer to print to, such as stdout.
+ * @param source
+ *   The source string.
+ * @param destination
+ *   The destination string.
+ */
+#ifndef _di_fake_verbose_print_move_
+  extern void fake_verbose_print_move(FILE *output, const f_string_t source, const f_string_t destination) f_gcc_attribute_visibility_internal;
+#endif // _di_fake_verbose_print_move_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index aa292bf2a6ced0783e1d53cf164fc150975e87de..64a7bf0f2ba2197b3400d69e17080c8c18dffd7c 100644 (file)
@@ -1798,7 +1798,8 @@ extern "C" {
       f_string_length_t destination_length = 0;
 
       if (data.verbosity == fake_verbosity_verbose) {
-        recurse.verbose = f_type_output;
+        recurse.output = f_type_output;
+        recurse.verbose = fake_verbose_print_clone;
       }
 
       bool existing = F_true;
@@ -1893,7 +1894,8 @@ extern "C" {
       f_macro_mode_t_set_default_umask(mode, data.umask);
 
       if (data.verbosity == fake_verbosity_verbose) {
-        recurse.verbose = f_type_output;
+        recurse.output = f_type_output;
+        recurse.verbose = fake_verbose_print_copy;
       }
 
       bool existing = F_true;
@@ -2755,8 +2757,15 @@ extern "C" {
       const f_array_length_t total = arguments.used -1;
       f_status_t status_file = F_none;
 
+      fl_directory_recurse_t recurse = fl_directory_recurse_t_initialize;
+
       f_string_length_t destination_length = 0;
 
+      if (data.verbosity == fake_verbosity_verbose) {
+        recurse.output = f_type_output;
+        recurse.verbose = fake_verbose_print_move;
+      }
+
       bool existing = F_true;
 
       // in this case, the destination could be a file, so confirm this.
@@ -2792,15 +2801,12 @@ extern "C" {
 
         destination[destination_length] = 0;
 
-        status_file = f_file_move(arguments.array[i].string, destination);
+        status_file = fll_file_move(arguments.array[i].string, destination, arguments.array[i].used, destination_length, recurse);
 
         if (F_status_is_error(status_file)) {
-          fake_print_message_file(data, F_status_set_fine(status_file), "f_file_move", arguments.array[i].string, "move", F_false, F_true, data_make->print);
+          fake_print_message_file(data, F_status_set_fine(status_file), "fll_file_move", arguments.array[i].string, "move", F_false, F_true, data_make->print);
           *status = F_status_set_error(F_failure);
         }
-        else if (data.verbosity == fake_verbosity_verbose) {
-          printf("Moved '%s' to '%s'.%c", arguments.array[i].string, destination, f_string_eol[0]);
-        }
       } // for
 
       return;