]> Kevux Git Server - fll/commitdiff
Progress: featureless make.
authorKevin Day <thekevinday@gmail.com>
Wed, 9 Sep 2020 04:09:06 +0000 (23:09 -0500)
committerKevin Day <thekevinday@gmail.com>
Wed, 9 Sep 2020 04:09:06 +0000 (23:09 -0500)
Implement file move functions.
- There will need to be future changes to allow for moving across filesystems.
- This move across filesystems may need to be an fll_file_move() so that it can either do a directory clone or a file clone.

Fix a typo 'perforrm', which should instead be 'perform'.

Add 'F_mount' status code.

Implement the move section operation.

level_0/f_directory/c/directory.h
level_0/f_file/c/file.c
level_0/f_file/c/file.h
level_0/f_file/c/private-file.h
level_0/f_status/c/status.h
level_1/fl_status/c/status.c
level_1/fl_status/c/status.h
level_2/fll_status/c/status.c
level_3/fake/c/private-make.c

index 19f998a4bca06ca8b3b197c819a62db875739e2d..d22f6bb47b74cd17685f82e3d3a93b3fe8a0150d 100644 (file)
@@ -471,7 +471,7 @@ extern "C" {
  *   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 perforrm write.
+ *   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_descriptor (with error bit) for bad directory descriptor for at_id.
  *   F_file_found (with error bit) if a file aleady exists at the path.
@@ -513,7 +513,7 @@ extern "C" {
  *   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 perforrm write.
+ *   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_descriptor (with error bit) for bad directory descriptor for at_id.
  *   F_file_found (with error bit) if a file aleady exists at the path (when calling utimensat()).
index 79bb6e2a180f3ca1a7a646ad02d9103e3fd8bfb9..cf422f8319cffdcf1fdd39b1e006e6a933ff40de 100644 (file)
@@ -1318,6 +1318,75 @@ 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_level_0_parameter_checking_
+      if (source == 0) return F_status_set_error(F_parameter);
+      if (destination == 0) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    if (rename(source, destination) < 0) {
+      if (errno == EACCES) return F_status_set_error(F_access_denied);
+      if (errno == EBUSY) return F_status_set_error(F_busy);
+      if (errno == EDQUOT) return F_status_set_error(F_filesystem_quota_block);
+      if (errno == EFAULT) return F_status_set_error(F_buffer);
+      if (errno == EINVAL) return F_status_set_error(F_parameter);
+      if (errno == EISDIR) return F_status_set_error(F_file_type_directory);
+      if (errno == ELOOP) return F_status_set_error(F_loop);
+      if (errno == EMLINK) return F_status_set_error(F_link);
+      if (errno == ENAMETOOLONG) return F_status_set_error(F_name);
+      if (errno == ENOENT) return F_status_set_error(F_file_found_not);
+      if (errno == ENOMEM) return F_status_set_error(F_memory_out);
+      if (errno == ENOSPC) return F_status_set_error(F_space_not);
+      if (errno == ENOTDIR) return F_status_set_error(F_directory);
+      if (errno == ENOTEMPTY) return F_status_set_error(F_directory_empty_not);
+      if (errno == EEXIST) return F_status_set_error(F_directory_empty_not);
+      if (errno == EPERM) return F_status_set_error(F_prohibited);
+      if (errno == EROFS) return F_status_set_error(F_read_only);
+      if (errno == EXDEV) return F_status_set_error(F_mount);
+
+      return F_status_set_error(F_failure);
+    }
+
+    return F_none;
+  }
+#endif // _di_f_file_move_
+
+#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_level_0_parameter_checking_
+      if (source == 0) return F_status_set_error(F_parameter);
+      if (destination == 0) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    if (renameat(at_id, source, to_id, destination) < 0) {
+      if (errno == EACCES) return F_status_set_error(F_access_denied);
+      if (errno == EBUSY) return F_status_set_error(F_busy);
+      if (errno == EDQUOT) return F_status_set_error(F_filesystem_quota_block);
+      if (errno == EFAULT) return F_status_set_error(F_buffer);
+      if (errno == EINVAL) return F_status_set_error(F_parameter);
+      if (errno == EISDIR) return F_status_set_error(F_file_type_directory);
+      if (errno == ELOOP) return F_status_set_error(F_loop);
+      if (errno == EMLINK) return F_status_set_error(F_link);
+      if (errno == ENAMETOOLONG) return F_status_set_error(F_name);
+      if (errno == ENOENT) return F_status_set_error(F_file_found_not);
+      if (errno == ENOMEM) return F_status_set_error(F_memory_out);
+      if (errno == ENOSPC) return F_status_set_error(F_space_not);
+      if (errno == ENOTDIR) return F_status_set_error(F_directory);
+      if (errno == ENOTEMPTY) return F_status_set_error(F_directory_empty_not);
+      if (errno == EEXIST) return F_status_set_error(F_directory_empty_not);
+      if (errno == EPERM) return F_status_set_error(F_prohibited);
+      if (errno == EROFS) return F_status_set_error(F_read_only);
+      if (errno == EXDEV) return F_status_set_error(F_mount);
+      if (errno == EBADF) return F_status_set_error(F_directory_descriptor);
+
+      return F_status_set_error(F_failure);
+    }
+
+    return F_none;
+  }
+#endif // _di_f_file_move_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) {
     #ifndef _di_level_0_parameter_checking_
index b14f4abb9ccef76fcf70e101dce274d60529fc71..dafef8868baeb290780bbdd982324389e8109f20 100644 (file)
@@ -417,7 +417,7 @@ extern "C" {
  *   F_access_group (with error bit) if the current user does not have access to assign the specified group.
  *   F_access_mode (with error bit) if the current user does not have access to assign the file mode.
  *   F_access_owner (with error bit) if the current user does not have access to assign the specified owner.
- *   F_busy (with error bit) if filesystem is too busy to perforrm write.
+ *   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_file_found (with error bit) if a file was found while exclusive is TRUE.
  *   F_file_open_max (with error bit) when system-wide max open files is reached.
@@ -494,7 +494,7 @@ extern "C" {
  * @return
  *   F_none on success.
  *   F_access_denied (with error bit) on access denied.
- *   F_busy (with error bit) if filesystem is too busy to perforrm write.
+ *   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_file_found (with error bit) if a file was found while exclusive is TRUE.
  *   F_file_open_max (with error bit) when system-wide max open files is reached.
@@ -533,7 +533,7 @@ extern "C" {
  * @return
  *   F_none on success.
  *   F_access_denied (with error bit) on access denied.
- *   F_busy (with error bit) if filesystem is too busy to perforrm write.
+ *   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_file_found (with error bit) if a file was found while exclusive is TRUE.
  *   F_file_open_max (with error bit) when system-wide max open files is reached.
@@ -573,7 +573,7 @@ extern "C" {
  * @return
  *   F_none on success.
  *   F_access_denied (with error bit) on access denied.
- *   F_busy (with error bit) if filesystem is too busy to perforrm write.
+ *   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_file_found (with error bit) if a file was found while exclusive is TRUE.
  *   F_file_open_max (with error bit) when system-wide max open files is reached.
@@ -983,7 +983,7 @@ extern "C" {
  *   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 perforrm write.
+ *   F_busy (with error bit) if filesystem is too busy to perform write.
  *   F_file_found (with error bit) if a file aleady exists at the path.
  *   F_file_found_not (with error bit) if a parent path in point does not exist or is a broken symlink.
  *   F_filesystem_quota_block (with error bit) if filesystem's disk blocks or inodes are exhausted.
@@ -1020,7 +1020,7 @@ extern "C" {
  * @return
  *   F_none on success.
  *   F_access_denied (with error bit) on access denied.
- *   F_busy (with error bit) if filesystem is too busy to perforrm write.
+ *   F_busy (with error bit) if filesystem is too busy to perform write.
  *   F_buffer (with error bit) if the buffer is invalid.
  *   F_directory (with error bit) if a supposed directory in path is not actually a directory.
  *   F_directory_descriptor (with error bit) for bad directory descriptor for at_id.
@@ -1057,7 +1057,7 @@ extern "C" {
  *   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 perforrm write.
+ *   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_file_found (with error bit) if a file aleady exists at the path.
  *   F_file_found_not (with error bit) if a parent path in point does not exist or is a broken symlink.
@@ -1098,7 +1098,7 @@ extern "C" {
  *   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 perforrm write.
+ *   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_descriptor (with error bit) for bad directory descriptor for at_id.
  *   F_file_found (with error bit) if a file aleady exists at the path.
@@ -1446,6 +1446,105 @@ extern "C" {
 #endif // _di_f_file_mode_to_mode_
 
 /**
+ * Move 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.
+ *
+ * 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.
+ *
+ * @param source
+ *   The path to the file to copy from.
+ * @param destination
+ *   The path to copy to.
+ *
+ * @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_mount (with error bit) if source and destination are not within the same mounted filesystems.
+ *   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.
+ *
+ * @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_
+
+/**
+ * Move 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.
+ *
+ * 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.
+ *
+ * @param at_id
+ *   The parent directory, as an open directory file descriptor, in which the source is relative to.
+ * @param to_id
+ *   The parent directory, as an open directory file descriptor, in which the destination is relative to.
+ * @param source
+ *   The path to the file to copy from.
+ * @param destination
+ *   The path to copy to.
+ *
+ * @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_descriptor (with error bit) for bad directory descriptor for at_id or to_id.
+ *   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_mount (with error bit) if source and destination are not within the same mounted filesystems.
+ *   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.
+ *
+ * @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_
+
+/**
  * Get the base name of a file path.
  *
  * @param path
@@ -2019,7 +2118,7 @@ extern "C" {
  *   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 perforrm write.
+ *   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_descriptor (with error bit) for bad directory descriptor for at_id.
  *   F_file_found (with error bit) if a file aleady exists at the path.
@@ -2061,7 +2160,7 @@ extern "C" {
  *   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 perforrm write.
+ *   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_descriptor (with error bit) for bad directory descriptor for at_id.
  *   F_file_found (with error bit) if a file aleady exists at the path (when calling utimensat()).
index 05ce890f2028fd5809c8d40f31c7dae687cae24e..0f649c07891582a73fe68247eb4ca8cf229e5f5c 100644 (file)
@@ -63,7 +63,7 @@ extern "C" {
  * @return
  *   F_none on success.
  *   F_access_denied (with error bit) on access denied.
- *   F_busy (with error bit) if filesystem is too busy to perforrm write.
+ *   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_file_found (with error bit) if a file was found while exclusive is TRUE.
  *   F_file_open_max (with error bit) when system-wide max open files is reached.
@@ -109,7 +109,7 @@ extern "C" {
  * @return
  *   F_none on success.
  *   F_access_denied (with error bit) on access denied.
- *   F_busy (with error bit) if filesystem is too busy to perforrm write.
+ *   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_file_found (with error bit) if a file was found while exclusive is TRUE.
  *   F_file_open_max (with error bit) when system-wide max open files is reached.
@@ -154,7 +154,7 @@ extern "C" {
  * @return
  *   F_none on success.
  *   F_access_denied (with error bit) on access denied.
- *   F_busy (with error bit) if filesystem is too busy to perforrm write.
+ *   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_file_found (with error bit) if a file was found while exclusive is TRUE.
  *   F_file_open_max (with error bit) when system-wide max open files is reached.
@@ -432,7 +432,7 @@ extern "C" {
  *   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 perforrm write.
+ *   F_busy (with error bit) if filesystem is too busy to perform write.
  *   F_file_found (with error bit) if a file aleady exists at the path.
  *   F_file_found_not (with error bit) if a parent path in point does not exist or is a broken symlink.
  *   F_filesystem_quota_block (with error bit) if filesystem's disk blocks or inodes are exhausted.
@@ -469,7 +469,7 @@ extern "C" {
  * @return
  *   F_none on success.
  *   F_access_denied (with error bit) on access denied.
- *   F_busy (with error bit) if filesystem is too busy to perforrm write.
+ *   F_busy (with error bit) if filesystem is too busy to perform write.
  *   F_buffer (with error bit) if the buffer is invalid.
  *   F_directory (with error bit) if a supposed directory in path is not actually a directory.
  *   F_directory_descriptor (with error bit) for bad directory descriptor for at_id.
index 2ddb67eaa88e6e2fcedf13dcc058fdadb67aed22..325d537a778acf6b94aea6f0638ab3e496fcf74c 100644 (file)
@@ -171,6 +171,7 @@ extern "C" {
       F_loop,
       F_maybe,
       F_memory_out,
+      F_mount,
       F_name,
       F_parameter,
       F_pipe,
index c3bba9ac49a0596f8dd5583fe79cfeda346e3143..f65cd3cc004e62963c7580932d21a4ad7238b581 100644 (file)
@@ -299,6 +299,9 @@ extern "C" {
         case F_memory_out:
           *string = FL_status_string_memory_out;
           break;
+        case F_mount:
+          *string = FL_status_string_mount;
+          break;
         case F_name:
           *string = FL_status_string_name;
           break;
index da1356c16f702c7f0adb29c0238160b5111f434f..7678d1a096b7b8718cb03d511840b343155b81b2 100644 (file)
@@ -191,6 +191,7 @@ extern "C" {
     #define FL_status_string_loop             "F_loop"
     #define FL_status_string_maybe            "F_maybe"
     #define FL_status_string_memory_out       "F_memory_out"
+    #define FL_status_string_mount            "F_mount"
     #define FL_status_string_name             "F_name"
     #define FL_status_string_parameter        "F_parameter"
     #define FL_status_string_pipe             "F_pipe"
@@ -241,6 +242,7 @@ extern "C" {
     #define FL_status_string_loop_length             6
     #define FL_status_string_maybe_length            7
     #define FL_status_string_memory_out_length       12
+    #define FL_status_string_mount_length            7
     #define FL_status_string_name_length             6
     #define FL_status_string_parameter_length        11
     #define FL_status_string_pipe_length             6
index 414be02a0ab611444aa51026348aac7202f017c9..63d17bfd150a98b0726ee0a8e1dc4f3775c12412 100644 (file)
@@ -501,6 +501,11 @@ extern "C" {
         return F_none;
       }
 
+      if (fl_string_compare(string, FL_status_string_mount, length, FL_status_string_mount_length) == F_equal_to) {
+        *code = F_mount;
+        return F_none;
+      }
+
       if (fl_string_compare(string, FL_status_string_name, length, FL_status_string_name_length) == F_equal_to) {
         *code = F_name;
         return F_none;
index e521d40285120f478001a4526ad03699c78038d9..aa292bf2a6ced0783e1d53cf164fc150975e87de 100644 (file)
@@ -1888,7 +1888,9 @@ extern "C" {
 
       f_string_length_t destination_length = 0;
 
-      f_mode_t mode = f_mode_t_initialize;f_macro_mode_t_set_default_umask(mode, data.umask);
+      f_mode_t mode = f_mode_t_initialize;
+
+      f_macro_mode_t_set_default_umask(mode, data.umask);
 
       if (data.verbosity == fake_verbosity_verbose) {
         recurse.verbose = f_type_output;
@@ -2753,19 +2755,51 @@ extern "C" {
       const f_array_length_t total = arguments.used -1;
       f_status_t status_file = F_none;
 
+      f_string_length_t destination_length = 0;
+
+      bool existing = F_true;
+
+      // in this case, the destination could be a file, so confirm this.
+      if (arguments.used == 2) {
+        status_file = f_directory_is(arguments.array[total].string);
+
+        if (F_status_is_error(status_file)) {
+          fake_print_message_file(data, F_status_set_fine(status_file), "f_directory_is", arguments.array[1].string, "identify", F_false, F_true, data_make->print);
+          *status = F_status_set_error(F_failure);
+          return;
+        }
+
+        if (status_file == F_false || status_file == F_file_found_not) {
+          existing = F_false;
+        }
+      }
+
       for (f_array_length_t i = 0; i < total; i++) {
-        status_file = f_directory_is(arguments.array[i].string);
+        destination_length = arguments.array[total].used;
 
-        if (status_file == F_true) {
-          // @todo: *status = fl_directory_copy();
+        if (existing) {
+          destination_length += arguments.array[i].used + 1;
         }
-        else if (status_file == F_true) {
-          // @todo: *status = f_file_copy();
+
+        char destination[destination_length + 1];
+
+        memcpy(destination, arguments.array[total].string, arguments.array[total].used);
+
+        if (existing) {
+          memcpy(destination + arguments.array[total].used + 1, arguments.array[i].string, arguments.array[i].used);
+          destination[arguments.array[total].used] = f_path_separator[0];
         }
-        else if (F_status_is_error(status_file)) {
-          // @todo
+
+        destination[destination_length] = 0;
+
+        status_file = f_file_move(arguments.array[i].string, destination);
+
+        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);
           *status = F_status_set_error(F_failure);
-          break;
+        }
+        else if (data.verbosity == fake_verbosity_verbose) {
+          printf("Moved '%s' to '%s'.%c", arguments.array[i].string, destination, f_string_eol[0]);
         }
       } // for