]> Kevux Git Server - fll/commitdiff
Update: Improve the logic for the read link f_file functions.
authorKevin Day <thekevinday@gmail.com>
Sat, 16 Apr 2022 05:01:06 +0000 (00:01 -0500)
committerKevin Day <thekevinday@gmail.com>
Sat, 16 Apr 2022 05:01:06 +0000 (00:01 -0500)
The f_file_link_read() and f_file_link_read_at() functions have their dynamic allocation logic improved.
Use link_stat.st_size rather than target->used to pass to readlink() or readlinkat().

Initialize target->used to 0 and then update target->used on success while ensuring the string is always NULL terminated after the target->used.

The unit tests revealed that these can and should be improved.

level_0/f_file/c/file.h
level_0/f_file/c/private-file.c
level_0/f_file/c/private-file.h

index 80c314dfc63257eb0e079dc2279f2f91289f53ea..d1e20c36e1b8ba2b0a8fdf993e61c714cf222013 100644 (file)
@@ -979,7 +979,13 @@ extern "C" {
  *   F_string_too_large (with error bit) if link target path is too large for string buffer size.
  *   F_failure (with error bit) for any other error.
  *
+ *   Errors (with error bit) from: f_string_dynamic_increase_by()
+ *   Errors (with error bit) from: f_string_dynamic_terminate_after()
+ *
  * @see readlink()
+ *
+ * @see f_string_dynamic_increase_by()
+ * @see f_string_dynamic_terminate_after()
  */
 #ifndef _di_f_file_link_read_
   extern f_status_t f_file_link_read(const f_string_static_t path, const struct stat link_stat, f_string_dynamic_t * const target);
@@ -1018,7 +1024,13 @@ extern "C" {
  *   F_string_too_large (with error bit) if link target path is too large for string buffer size.
  *   F_failure (with error bit) for any other error.
  *
+ *   Errors (with error bit) from: f_string_dynamic_increase_by()
+ *   Errors (with error bit) from: f_string_dynamic_terminate_after()
+ *
  * @see readlinkat()
+ *
+ * @see f_string_dynamic_increase_by()
+ * @see f_string_dynamic_terminate_after()
  */
 #ifndef _di_f_file_link_read_at_
   extern f_status_t f_file_link_read_at(const int at_id, const f_string_static_t path, const struct stat link_stat, f_string_dynamic_t * const target);
index a4f3e49b0960ca8e95093bbb0781da022c551531..1850fc618b538c85e6ea9e2d1ca309c2b3053833 100644 (file)
@@ -404,21 +404,12 @@ extern "C" {
 #if !defined(_di_f_file_link_read_) || !defined(_di_f_file_copy_)
   f_status_t private_f_file_link_read(const f_string_static_t path, const struct stat link_stat, f_string_dynamic_t * const target) {
 
-    // Create a NULL terminated string based on file stat.
-    if (link_stat.st_size + 1 > target->size) {
-      if (link_stat.st_size + 1 > F_array_length_t_size_d) {
-        return F_status_set_error(F_string_too_large);
-      }
-
-      const f_status_t status = f_string_dynamic_resize(link_stat.st_size + 1, target);
-      if (F_status_is_error(status)) return status;
-    }
+    target->used = 0;
 
-    memset(target->string, 0, sizeof(f_char_t) * (target->used + 1));
-
-    target->used = link_stat.st_size;
+    f_status_t status = f_string_dynamic_increase_by(link_stat.st_size + 1, target);
+    if (F_status_is_error(status)) return status;
 
-    if (readlink(path.string, target->string, target->used) < 0) {
+    if (readlink(path.string, target->string, link_stat.st_size) < 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);
@@ -432,6 +423,11 @@ extern "C" {
       return F_status_set_error(F_failure);
     }
 
+    target->used = link_stat.st_size;
+
+    status = f_string_dynamic_terminate_after(target);
+    if (F_status_is_error(status)) return status;
+
     return F_none;
   }
 #endif // !defined(_di_f_file_link_read_) || !defined(_di_f_file_copy_)
@@ -439,21 +435,12 @@ extern "C" {
 #if !defined(_di_f_file_link_read_at_) || !defined(_di_f_file_copy_at_)
   f_status_t private_f_file_link_read_at(const int at_id, const f_string_static_t path, const struct stat link_stat, f_string_dynamic_t * const target) {
 
-    // Create a NULL terminated string based on file stat.
-    if (link_stat.st_size + 1 > target->size) {
-      if (link_stat.st_size + 1 > F_array_length_t_size_d) {
-        return F_status_set_error(F_string_too_large);
-      }
-
-      const f_status_t status = f_string_dynamic_resize(link_stat.st_size + 1, target);
-      if (F_status_is_error(status)) return status;
-    }
+    target->used = 0;
 
-    memset(target->string, 0, sizeof(f_char_t) * (target->used + 1));
-
-    target->used = link_stat.st_size;
+    f_status_t status = f_string_dynamic_increase_by(link_stat.st_size + 1, target);
+    if (F_status_is_error(status)) return status;
 
-    if (readlinkat(at_id, path.string, target->string, target->used) < 0) {
+    if (readlinkat(at_id, path.string, target->string, link_stat.st_size) < 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 == EFAULT) return F_status_set_error(F_buffer);
@@ -468,6 +455,11 @@ extern "C" {
       return F_status_set_error(F_failure);
     }
 
+    target->used = link_stat.st_size;
+
+    status = f_string_dynamic_terminate_after(target);
+    if (F_status_is_error(status)) return status;
+
     return F_none;
   }
 #endif // !defined(_di_f_file_link_read_at_) || !defined(_di_f_file_copy_at_)
index 59cf944c89bec77b2d4c6bfecd3da568c06fbc44..7e2b2481f2303f7b163f5aa2704247ee438fe332 100644 (file)
@@ -543,6 +543,8 @@ extern "C" {
  *
  * @see f_file_copy()
  * @see f_file_link_read()
+ * @see f_string_dynamic_increase_by()
+ * @see f_string_dynamic_terminate_after()
  */
 #if !defined(_di_f_file_link_read_) || !defined(_di_f_file_copy_)
   extern f_status_t private_f_file_link_read(const f_string_static_t path, const struct stat link_stat, f_string_dynamic_t * const target) F_attribute_visibility_internal_d;
@@ -581,6 +583,8 @@ extern "C" {
  *
  * @see f_file_copy_at()
  * @see f_file_link_read_at()
+ * @see f_string_dynamic_increase_by()
+ * @see f_string_dynamic_terminate_after()
  */
 #if !defined(_di_f_file_link_read_at_) || !defined(_di_f_file_copy_at_)
   extern f_status_t private_f_file_link_read_at(const int at_id, const f_string_static_t path, const struct stat link_stat, f_string_dynamic_t * const target) F_attribute_visibility_internal_d;