]> Kevux Git Server - fll/commitdiff
Bugfix: Fix problems in f_file exposed by unit tests.
authorKevin Day <thekevinday@gmail.com>
Tue, 19 Apr 2022 03:27:58 +0000 (22:27 -0500)
committerKevin Day <thekevinday@gmail.com>
Tue, 19 Apr 2022 03:27:58 +0000 (22:27 -0500)
Add _f_file_rename_use_renameat2_ to enable support for renameat2() for systems in which this is available.
Add flags parameter to rename function to automatically support this.

Add missing "!path.used" checks.
Add missing parameter checks.
Move parameter checks that should instead be file closed checks that process normally.
Consistently apply file closed checks.

The function private_f_file_role_change_at() needs to check that result is not an error before processing group.
Failure to do this may result in hiding an error.

Minor clean ups.

build/level_0/settings
build/monolithic/settings
level_0/f_file/c/file.c
level_0/f_file/c/file.h
level_0/f_file/c/private-file.c
level_0/f_file/data/build/defines
level_0/f_file/data/build/settings

index 888f0ab8607453457cbedfc95c4fd1227905ebd7..f8fbdde80f840c340d4e2f8f26f505523393226e 100644 (file)
@@ -100,6 +100,7 @@ search_shared yes
 search_static yes
 
 #defines -D_di_libcap_
+#defines -D_f_file_rename_use_renameat2_
 defines -D_libcap_legacy_only_ -D_pthread_attr_unsupported_ -D_pthread_sigqueue_unsupported_
 defines-clang -D_clang_not_a_compile_time_constant_workaround_
 defines-level_threadless -D_di_pthread_support_
index 0f804d108e6d4a9978762275f899fc02a5c9b797..b06e664e74260b9893fa78894c632a339ca5c5be 100644 (file)
@@ -151,6 +151,7 @@ search_shared yes
 search_static yes
 
 #defines -D_di_libcap_
+#defines -D_f_file_rename_use_renameat2_
 defines -D_libcap_legacy_only_ -D_pthread_attr_unsupported_ -D_pthread_sigqueue_unsupported_
 defines-clang -D_clang_not_a_compile_time_constant_workaround_
 defines-monolithic_threadless -D_di_pthread_support_
index 3226d922e5dc5ff98dd7d591ee21dea7f3eed816..ecdd1eee60e63a6a9c4f8a70264a2e83a0c3dc47 100644 (file)
@@ -1742,11 +1742,11 @@ extern "C" {
     if (unlink(path.string) < 0) {
       if (errno == EACCES) return F_status_set_error(F_access_denied);
       if (errno == EBUSY) return F_status_set_error(F_busy);
+      if (errno == EFAULT) return F_status_set_error(F_buffer);
       if (errno == EIO) return F_status_set_error(F_input_output);
       if (errno == EISDIR) return F_status_set_error(F_file_type_directory);
       if (errno == ELOOP) return F_status_set_error(F_loop);
       if (errno == ENAMETOOLONG) return F_status_set_error(F_name);
-      if (errno == EFAULT) return F_status_set_error(F_buffer);
       if (errno == ENOENT) return F_status_set_error(F_file_found_not);
       if (errno == ENOMEM) return F_status_set_error(F_memory_not);
       if (errno == ENOTDIR) return F_status_set_error(F_directory_not);
@@ -1824,35 +1824,39 @@ extern "C" {
 #endif // _di_f_file_rename_
 
 #ifndef _di_f_file_rename_at_
-  f_status_t f_file_rename_at(const int at_id, const int to_id, const f_string_static_t source, const f_string_static_t destination) {
+  f_status_t f_file_rename_at(const int at_id, const int to_id, const f_string_static_t source, const f_string_static_t destination, const unsigned int flag) {
 
     if (!source.used || !destination.used) {
       return F_data_not;
     }
 
-    if (renameat(at_id, source.string, to_id, destination.string) < 0) {
-      if (errno == EACCES) return F_status_set_error(F_access_denied);
-      if (errno == EBADF) return F_status_set_error(F_directory_descriptor);
-      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_not);
-      if (errno == ENOSPC) return F_status_set_error(F_space_not);
-      if (errno == ENOTDIR) return F_status_set_error(F_directory_not);
-      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);
+    #ifdef _f_file_rename_use_renameat2_
+      if (renameat2(at_id, source.string, to_id, destination.string, flag) < 0) {
+    #else
+      if (renameat(at_id, source.string, to_id, destination.string) < 0) {
+    #endif // _f_file_rename_use_renameat2_
+        if (errno == EACCES) return F_status_set_error(F_access_denied);
+        if (errno == EBADF) return F_status_set_error(F_directory_descriptor);
+        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_not);
+        if (errno == ENOSPC) return F_status_set_error(F_space_not);
+        if (errno == ENOTDIR) return F_status_set_error(F_directory_not);
+        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_status_set_error(F_failure);
+      }
 
     return F_none;
   }
@@ -1872,7 +1876,7 @@ extern "C" {
 #ifndef _di_f_file_role_change_at_
   f_status_t f_file_role_change_at(const int at_id, const f_string_static_t path, const uid_t uid, const gid_t gid, const int flag) {
 
-    if (uid == -1 && gid == -1) {
+    if (uid == -1 && gid == -1 || !path.used) {
       return F_data_not;
     }
 
@@ -1883,8 +1887,8 @@ extern "C" {
 #ifndef _di_f_file_seek_
   f_status_t f_file_seek(const int id, const int whence, const off_t offset, off_t * const seeked) {
     #ifndef _di_level_0_parameter_checking_
-      if (id <= 0) return F_status_set_error(F_parameter);
       if (whence < 0) return F_status_set_error(F_parameter);
+      if (!seeked) return F_status_set_error(F_parameter);
     #endif // _di_level_0_parameter_checking_
 
     *seeked = lseek(id, offset, whence);
@@ -1956,10 +1960,13 @@ extern "C" {
 #ifndef _di_f_file_size_by_id_
   f_status_t f_file_size_by_id(const int id, off_t * const size) {
     #ifndef _di_level_0_parameter_checking_
-      if (id <= 0) return F_status_set_error(F_parameter);
       if (!size) return F_status_set_error(F_parameter);
     #endif // _di_level_0_parameter_checking_
 
+    if (id == -1) {
+      return F_status_set_error(F_file_closed);
+    }
+
     struct stat stat_file;
 
     memset(&stat_file, 0, sizeof(struct stat));
@@ -2006,10 +2013,13 @@ extern "C" {
 #ifndef _di_f_file_stat_by_id_
   f_status_t f_file_stat_by_id(const int id, struct stat * const stat_file) {
     #ifndef _di_level_0_parameter_checking_
-      if (id <= 0) return F_status_set_error(F_parameter);
       if (!stat_file) return F_status_set_error(F_parameter);
     #endif // _di_level_0_parameter_checking_
 
+    if (id == -1) {
+      return F_status_set_error(F_file_closed);
+    }
+
     return private_f_file_stat_by_id(id, stat_file);
   }
 #endif // _di_f_file_stat_by_id_
@@ -2066,9 +2076,12 @@ extern "C" {
   f_status_t f_file_stream_descriptor(const f_string_static_t mode, f_file_t * const file) {
     #ifndef _di_level_0_parameter_checking_
       if (!file) return F_status_set_error(F_parameter);
-      if (file->id == -1) return F_status_set_error(F_parameter);
     #endif // _di_level_0_parameter_checking_
 
+    if (file->id == -1) {
+      return F_status_set_error(F_file_closed);
+    }
+
     if (mode.string) {
       file->stream = fdopen(file->id, mode.string);
     }
@@ -2214,7 +2227,9 @@ extern "C" {
       if (!buffer) return F_status_set_error(F_parameter);
     #endif // _di_level_0_parameter_checking_
 
-    if (!file.stream) return F_status_set_error(F_file_closed);
+    if (!file.stream) {
+      return F_status_set_error(F_file_closed);
+    }
 
     flockfile(file.stream);
 
@@ -2279,7 +2294,9 @@ extern "C" {
       if (!buffer) return F_status_set_error(F_parameter);
     #endif // _di_level_0_parameter_checking_
 
-    if (!file.stream) return F_status_set_error(F_file_closed);
+    if (!file.stream) {
+      return F_status_set_error(F_file_closed);
+    }
 
     flockfile(file.stream);
 
index 3db20e924086805abbb57c0f1508f420d961d83a..7bdcc098384c81c2970a9474d88fa9a9809843d8 100644 (file)
@@ -1722,6 +1722,10 @@ extern "C" {
  *   The path to the file to copy from.
  * @param destination
  *   The path to copy to.
+ * @param flag
+ *   Any valid flag, such as F_file_at_path_empty_d, F_file_at_automount_no_d, or F_file_at_symlink_follow_no_d.
+ *   The POSIX renameat() doesn't support flag but Linux has a renameat2() that does.
+ *   If this is compiled with renameat2 support (), then flag is used otherwise flag is always 0 regardless of this property.
  *
  * @return
  *   F_none on success.
@@ -1749,7 +1753,7 @@ extern "C" {
  * @see renameat()
  */
 #ifndef _di_f_file_rename_at_
-  extern f_status_t f_file_rename_at(const int at_id, const int to_id, const f_string_static_t source, const f_string_static_t destination);
+  extern f_status_t f_file_rename_at(const int at_id, const int to_id, const f_string_static_t source, const f_string_static_t destination, const unsigned int flag);
 #endif // _di_f_file_rename_at_
 
 /**
@@ -1936,6 +1940,8 @@ extern "C" {
  *
  *   F_access_denied (with error bit) if access to the file was denied.
  *   F_directory_not (with error bit) on invalid directory.
+ *   F_file_closed (with error bit) if file is not open.
+ *   F_file_descriptor (with error bit) if the file descriptor is invalid.
  *   F_file_found_not (with error bit) if the file was not found.
  *   F_loop (with error bit) on loop error.
  *   F_memory_not (with error bit) if out of memory.
@@ -2093,6 +2099,7 @@ extern "C" {
  *   F_access_denied (with error bit) on access denied.
  *   F_buffer (with error bit) if the buffer is invalid.
  *   F_deadlock (with error bit) if operation would cause a deadlock.
+ *   F_file_closed (with error bit) if file is not open.
  *   F_file_descriptor (with error bit) if file descriptor is invalid.
  *   F_file_descriptor_max (with error bit) if max file descriptors is reached.
  *   F_file_type_not_directory (with error bit) if F_NOTIFY was specified and file.id is not a directory.
index fa2ee956027690aedb66210574444d1b1e168042..00e2183ed5b10efc55371c2ff0af29dab1635f29 100644 (file)
@@ -642,7 +642,7 @@ extern "C" {
       }
     }
 
-    if (gid != -1) {
+    if (result == 0 && gid != -1) {
       result = fchownat(at_id, path.string, -1, gid, flag);
 
       if (result < 0 && errno == EPERM) {
@@ -675,6 +675,7 @@ extern "C" {
     if ((dereference ? stat(path.string, file_stat) : lstat(path.string, file_stat)) < 0) {
       if (errno == EACCES) return F_status_set_error(F_access_denied);
       if (errno == EFAULT) return F_status_set_error(F_buffer);
+      if (errno == EINVAL) return F_status_set_error(F_parameter);
       if (errno == ELOOP) return F_status_set_error(F_loop);
       if (errno == ENAMETOOLONG) return F_status_set_error(F_name);
       if (errno == ENOENT) return F_status_set_error(F_file_found_not);
@@ -696,6 +697,7 @@ extern "C" {
       if (errno == EACCES) return F_status_set_error(F_access_denied);
       if (errno == EBADF) return F_status_set_error(F_directory_descriptor);
       if (errno == EFAULT) return F_status_set_error(F_buffer);
+      if (errno == EINVAL) return F_status_set_error(F_parameter);
       if (errno == ELOOP) return F_status_set_error(F_loop);
       if (errno == ENAMETOOLONG) return F_status_set_error(F_name);
       if (errno == ENOENT) return F_status_set_error(F_file_found_not);
@@ -715,10 +717,12 @@ extern "C" {
 
     if (fstat(id, file_stat) < 0) {
       if (errno == EACCES) return F_status_set_error(F_access_denied);
+      if (errno == EBADF) return F_status_set_error(F_file_descriptor);
       if (errno == EFAULT) return F_status_set_error(F_buffer);
+      if (errno == EINVAL) return F_status_set_error(F_parameter);
       if (errno == ELOOP) return F_status_set_error(F_loop);
       if (errno == ENAMETOOLONG) return F_status_set_error(F_name);
-      if (errno == ENOENT) return F_file_found_not;
+      if (errno == ENOENT) return F_status_set_error(F_file_found_not);
       if (errno == ENOMEM) return F_status_set_error(F_memory_not);
       if (errno == ENOTDIR) return F_status_set_error(F_directory_not);
       if (errno == EOVERFLOW) return F_status_set_error(F_number_overflow);
index 4f130804d83cb5bf412c3e349a4ac790b2b825ca..04d7dfd40121a88c00b42e9f9e4f5443a051495e 100644 (file)
@@ -1 +1,2 @@
 # fss-0000
+_f_file_rename_use_renameat2_ Use renameat2() instead of rename(), which allows for a flag value other than 0.
index a32b56adb8df626b551f11ee8660b7d7ca895ff7..2bb01c530492372c735b69a249f38d20b0e04dfa 100644 (file)
@@ -50,6 +50,8 @@ flags -O2 -z now -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno
 flags-clang -Wno-logical-op-parentheses
 flags-test -fstack-protector
 
+#defines -D_f_file_rename_use_renameat2_
+
 flags_library -fPIC
 flags_object -fPIC
 flags_program -fPIE