]> Kevux Git Server - fll/commitdiff
Update: add/update functions and refactor f_file_mode to f_file_mode_t and related.
authorKevin Day <thekevinday@gmail.com>
Thu, 3 Sep 2020 03:28:56 +0000 (22:28 -0500)
committerKevin Day <thekevinday@gmail.com>
Thu, 3 Sep 2020 03:28:56 +0000 (22:28 -0500)
Add functions f_environment_exists(), f_file_group_read(), and f_file_owner_read().

Update function f_file_mode_to_mode(), implementing it.

Refactor f_file_mode to f_file_mode_t and related.
This appears to have been missed in a previous refactor.

level_0/f_environment/c/environment.c
level_0/f_environment/c/environment.h
level_0/f_file/c/file.c
level_0/f_file/c/file.h

index 2a62111997fedcb30a0089698ffdf87f346836f7..c71007540d9b822bfe114e4e5cc70f64c3a2f5eb 100644 (file)
@@ -15,8 +15,26 @@ extern "C" {
   }
 #endif // _di_f_environment_clear_
 
+#ifndef _di_f_environment_exists_
+  f_return_status f_environment_exists(const f_string_t name) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!name) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    if (getenv(name)) {
+      return F_true;
+    }
+
+    return F_false;
+  }
+#endif // _di_f_environment_exists_
+
 #ifndef _di_f_environment_get_
   f_return_status f_environment_get(const f_string_t name, f_string_dynamic_t *value) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!name) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
     return private_f_environment_get(name, value);
   }
 #endif // _di_f_environment_get_
index ff104d2c8633c30104029014912c83c87f00b34a..597f2e3c12cadfdc8885a9d45ba699e7a8943bc3 100644 (file)
@@ -59,9 +59,35 @@ extern "C" {
  *   The value will be appended (set value->used to 0 to replace).
  *
  * @return
+ *   F_true on success and environment variable exists.
+ *   F_false on success and environment variable does not exist.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ * @see getenv()
+ */
+#ifndef _di_f_environment_exists_
+  extern f_return_status f_environment_exists(const f_string_t name);
+#endif // _di_f_environment_exists_
+
+/**
+ * Get a single environment variable.
+ *
+ * The variable is copied into a new dynamically allocated string and is safe to alter.
+ *
+ * @param name
+ *   The name of the environment variable to get.
+ *   The name string must not contain the '=' character.
+ *   The name must be NULL terminated.
+ * @param value
+ *   The value associated with name.
+ *   The value will not be null terminated.
+ *   The value will be appended (set value->used to 0 to replace).
+ *
+ * @return
  *   F_none on success.
  *   F_exist_not if name does not exist.
  *   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.
  *
  * @see getenv()
index f61e07dede54db1b1f225cacb938fdcf88d053e2..924e27ae7a4b9efbc6697253ddd67f15e8d68b22 100644 (file)
@@ -355,6 +355,28 @@ extern "C" {
   }
 #endif // _di_f_file_flush_
 
+#ifndef _di_f_file_group_read_
+  f_return_status f_file_group_read(const f_string_t path, gid_t *group) {
+    #ifndef _di_level_0_parameter_checking_
+      if (path == 0) return F_status_set_error(F_parameter);
+      if (group == 0) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    struct stat stat_file;
+
+    memset(&stat_file, 0, sizeof(struct stat));
+
+    f_status_t status = private_f_file_stat(path, F_true, &stat_file);
+    if (F_status_is_error(status)) {
+      return status;
+    }
+
+    *group = stat_file.st_gid;
+
+    return F_none;
+  }
+#endif // _di_f_file_group_read_
+
 #ifndef _di_f_file_is_
   f_return_status f_file_is(const f_string_t path, const int type) {
     #ifndef _di_level_0_parameter_checking_
@@ -525,60 +547,60 @@ extern "C" {
 #endif // _di_f_file_link_read_at_
 
 #ifndef _di_f_file_mode_determine_
-  f_return_status f_file_mode_determine(const mode_t mode_file, const f_file_mode mode_change, const uint8_t mode_replace, const bool directory_is, mode_t *mode) {
+  f_return_status f_file_mode_determine(const mode_t mode_file, const f_file_mode_t mode_change, const uint8_t mode_replace, const bool directory_is, mode_t *mode) {
     #ifndef _di_level_0_parameter_checking_
       if (mode == 0) return F_status_set_error(F_parameter);
     #endif // _di_level_0_parameter_checking_
 
-    f_file_mode change = mode_change & f_file_mode_block_special;
+    f_file_mode_t change = mode_change & f_file_mode_t_block_special;
 
     *mode = 0;
 
-    if (mode_replace & f_file_mode_replace_special) {
-      if (change & f_file_mode_mask_bit_set_owner & f_file_mode_mask_how_add) {
+    if (mode_replace & f_file_mode_t_replace_special) {
+      if (change & f_file_mode_t_mask_bit_set_owner & f_file_mode_t_mask_how_add) {
         *mode = f_file_mode_special_set_user;
       }
 
-      if (change & f_file_mode_mask_bit_set_group & f_file_mode_mask_how_add) {
+      if (change & f_file_mode_t_mask_bit_set_group & f_file_mode_t_mask_how_add) {
         *mode |= f_file_mode_special_set_group;
       }
 
-      if (change & f_file_mode_mask_bit_sticky & f_file_mode_mask_how_add) {
+      if (change & f_file_mode_t_mask_bit_sticky & f_file_mode_t_mask_how_add) {
         *mode |= f_file_mode_special_sticky;
       }
     }
     else {
       *mode = mode_file & f_file_mode_special_all;
 
-      if (mode_change & f_file_mode_block_special) {
-        if (change & f_file_mode_mask_bit_set_owner & f_file_mode_mask_how_subtract) {
+      if (mode_change & f_file_mode_t_block_special) {
+        if (change & f_file_mode_t_mask_bit_set_owner & f_file_mode_t_mask_how_subtract) {
           if (*mode & f_file_mode_special_set_user) {
             *mode -= f_file_mode_special_set_user;
           }
         }
-        else if (change & f_file_mode_mask_bit_set_owner & f_file_mode_mask_how_add) {
+        else if (change & f_file_mode_t_mask_bit_set_owner & f_file_mode_t_mask_how_add) {
           if (!(*mode & f_file_mode_special_set_user)) {
             *mode |= f_file_mode_special_set_user;
           }
         }
 
-        if (change & f_file_mode_mask_bit_set_group & f_file_mode_mask_how_subtract) {
+        if (change & f_file_mode_t_mask_bit_set_group & f_file_mode_t_mask_how_subtract) {
           if (*mode & f_file_mode_special_set_group) {
             *mode -= f_file_mode_special_set_group;
           }
         }
-        else if (change & f_file_mode_mask_bit_set_group & f_file_mode_mask_how_add) {
+        else if (change & f_file_mode_t_mask_bit_set_group & f_file_mode_t_mask_how_add) {
           if (!(*mode & f_file_mode_special_set_group)) {
             *mode |= f_file_mode_special_set_group;
           }
         }
 
-        if (change & f_file_mode_mask_bit_sticky & f_file_mode_mask_how_subtract) {
+        if (change & f_file_mode_t_mask_bit_sticky & f_file_mode_t_mask_how_subtract) {
           if (*mode & f_file_mode_special_sticky) {
             *mode -= f_file_mode_special_sticky;
           }
         }
-        else if (change & f_file_mode_mask_bit_sticky & f_file_mode_mask_how_add) {
+        else if (change & f_file_mode_t_mask_bit_sticky & f_file_mode_t_mask_how_add) {
           if (!(*mode & f_file_mode_special_sticky)) {
             *mode |= f_file_mode_special_sticky;
           }
@@ -586,21 +608,21 @@ extern "C" {
       }
     }
 
-    change = mode_change & f_file_mode_block_owner;
+    change = mode_change & f_file_mode_t_block_owner;
 
-    if (mode_replace & f_file_mode_replace_owner) {
-      if (change & f_file_mode_mask_bit_read & f_file_mode_mask_how_add) {
+    if (mode_replace & f_file_mode_t_replace_owner) {
+      if (change & f_file_mode_t_mask_bit_read & f_file_mode_t_mask_how_add) {
         *mode |= f_file_mode_owner_r;
       }
 
-      if (change & f_file_mode_mask_bit_write & f_file_mode_mask_how_add) {
+      if (change & f_file_mode_t_mask_bit_write & f_file_mode_t_mask_how_add) {
         *mode |= f_file_mode_owner_w;
       }
 
-      if (change & f_file_mode_mask_bit_execute & f_file_mode_mask_how_add) {
+      if (change & f_file_mode_t_mask_bit_execute & f_file_mode_t_mask_how_add) {
         *mode |= f_file_mode_owner_x;
       }
-      else if (change & f_file_mode_mask_bit_execute_only & f_file_mode_mask_how_add) {
+      else if (change & f_file_mode_t_mask_bit_execute_only & f_file_mode_t_mask_how_add) {
         if (directory_is || (mode_file & f_file_mode_owner_x)) {
           *mode |= f_file_mode_owner_x;
         }
@@ -609,53 +631,53 @@ extern "C" {
     else {
       *mode |= mode_file & f_file_mode_owner_rwx;
 
-      if (mode_change & f_file_mode_block_owner) {
-        if (change & f_file_mode_mask_bit_read & f_file_mode_mask_how_subtract) {
+      if (mode_change & f_file_mode_t_block_owner) {
+        if (change & f_file_mode_t_mask_bit_read & f_file_mode_t_mask_how_subtract) {
           if (*mode & f_file_mode_owner_r) {
             *mode -= f_file_mode_owner_r;
           }
         }
-        else if (change & f_file_mode_mask_bit_read & f_file_mode_mask_how_add) {
+        else if (change & f_file_mode_t_mask_bit_read & f_file_mode_t_mask_how_add) {
           if (!(*mode & f_file_mode_owner_r)) {
             *mode |= f_file_mode_owner_r;
           }
         }
 
-        if (change & f_file_mode_mask_bit_write & f_file_mode_mask_how_subtract) {
+        if (change & f_file_mode_t_mask_bit_write & f_file_mode_t_mask_how_subtract) {
           if (*mode & f_file_mode_owner_w) {
             *mode -= f_file_mode_owner_w;
           }
         }
-        else if (change & f_file_mode_mask_bit_write & f_file_mode_mask_how_add) {
+        else if (change & f_file_mode_t_mask_bit_write & f_file_mode_t_mask_how_add) {
           if (!(*mode & f_file_mode_owner_w)) {
             *mode |= f_file_mode_owner_w;
           }
         }
 
-        if (change & f_file_mode_mask_bit_execute) {
-          change &= f_file_mode_mask_bit_execute;
+        if (change & f_file_mode_t_mask_bit_execute) {
+          change &= f_file_mode_t_mask_bit_execute;
 
-          if (change & f_file_mode_mask_how_subtract) {
+          if (change & f_file_mode_t_mask_how_subtract) {
             if (*mode & f_file_mode_owner_x) {
               *mode -= f_file_mode_owner_x;
             }
           }
-          else if (change & f_file_mode_mask_how_add) {
+          else if (change & f_file_mode_t_mask_how_add) {
             if (!(*mode & f_file_mode_owner_x)) {
               *mode |= f_file_mode_owner_x;
             }
           }
         }
-        else if (change & f_file_mode_mask_bit_execute_only) {
-          change &= f_file_mode_mask_bit_execute_only;
+        else if (change & f_file_mode_t_mask_bit_execute_only) {
+          change &= f_file_mode_t_mask_bit_execute_only;
 
           if (directory_is || (mode_file & f_file_mode_owner_x)) {
-            if (change & f_file_mode_mask_how_subtract) {
+            if (change & f_file_mode_t_mask_how_subtract) {
               if (*mode & f_file_mode_owner_x) {
                 *mode -= f_file_mode_owner_x;
               }
             }
-            else if (change & f_file_mode_mask_how_add) {
+            else if (change & f_file_mode_t_mask_how_add) {
               if (!(*mode & f_file_mode_owner_x)) {
                 *mode |= f_file_mode_owner_x;
               }
@@ -665,21 +687,21 @@ extern "C" {
       }
     }
 
-    change = mode_change & f_file_mode_block_group;
+    change = mode_change & f_file_mode_t_block_group;
 
-    if (mode_replace & f_file_mode_replace_group) {
-      if (change & f_file_mode_mask_bit_read & f_file_mode_mask_how_add) {
+    if (mode_replace & f_file_mode_t_replace_group) {
+      if (change & f_file_mode_t_mask_bit_read & f_file_mode_t_mask_how_add) {
         *mode |= f_file_mode_group_r;
       }
 
-      if (change & f_file_mode_mask_bit_write & f_file_mode_mask_how_add) {
+      if (change & f_file_mode_t_mask_bit_write & f_file_mode_t_mask_how_add) {
         *mode |= f_file_mode_group_w;
       }
 
-      if (change & f_file_mode_mask_bit_execute & f_file_mode_mask_how_add) {
+      if (change & f_file_mode_t_mask_bit_execute & f_file_mode_t_mask_how_add) {
         *mode |= f_file_mode_group_x;
       }
-      else if (change & f_file_mode_mask_bit_execute_only & f_file_mode_mask_how_add) {
+      else if (change & f_file_mode_t_mask_bit_execute_only & f_file_mode_t_mask_how_add) {
         if (directory_is || (mode_file & f_file_mode_group_x)) {
           *mode |= f_file_mode_group_x;
         }
@@ -688,54 +710,54 @@ extern "C" {
     else {
       *mode |= mode_file & f_file_mode_group_rwx;
 
-      if (mode_change & f_file_mode_block_group) {
+      if (mode_change & f_file_mode_t_block_group) {
 
-        if (change & f_file_mode_mask_bit_read & f_file_mode_mask_how_subtract) {
+        if (change & f_file_mode_t_mask_bit_read & f_file_mode_t_mask_how_subtract) {
           if (*mode & f_file_mode_group_r) {
             *mode -= f_file_mode_group_r;
           }
         }
-        else if (change & f_file_mode_mask_bit_read & f_file_mode_mask_how_add) {
+        else if (change & f_file_mode_t_mask_bit_read & f_file_mode_t_mask_how_add) {
           if (!(*mode & f_file_mode_group_r)) {
             *mode |= f_file_mode_group_r;
           }
         }
 
-        if (change & f_file_mode_mask_bit_write & f_file_mode_mask_how_subtract) {
+        if (change & f_file_mode_t_mask_bit_write & f_file_mode_t_mask_how_subtract) {
           if (*mode & f_file_mode_group_w) {
             *mode -= f_file_mode_group_w;
           }
         }
-        else if (change & f_file_mode_mask_bit_write & f_file_mode_mask_how_add) {
+        else if (change & f_file_mode_t_mask_bit_write & f_file_mode_t_mask_how_add) {
           if (!(*mode & f_file_mode_group_w)) {
             *mode |= f_file_mode_group_w;
           }
         }
 
-        if (change & f_file_mode_mask_bit_execute) {
-          change &= f_file_mode_mask_bit_execute;
+        if (change & f_file_mode_t_mask_bit_execute) {
+          change &= f_file_mode_t_mask_bit_execute;
 
-          if (change & f_file_mode_mask_how_subtract) {
+          if (change & f_file_mode_t_mask_how_subtract) {
             if (*mode & f_file_mode_group_x) {
               *mode -= f_file_mode_group_x;
             }
           }
-          else if (change & f_file_mode_mask_how_add) {
+          else if (change & f_file_mode_t_mask_how_add) {
             if (!(*mode & f_file_mode_group_x)) {
               *mode |= f_file_mode_group_x;
             }
           }
         }
-        else if (change & f_file_mode_mask_bit_execute_only) {
-          change &= f_file_mode_mask_bit_execute_only;
+        else if (change & f_file_mode_t_mask_bit_execute_only) {
+          change &= f_file_mode_t_mask_bit_execute_only;
 
           if (directory_is || (mode_file & f_file_mode_group_x)) {
-            if (change & f_file_mode_mask_how_subtract) {
+            if (change & f_file_mode_t_mask_how_subtract) {
               if (*mode & f_file_mode_group_x) {
                 *mode -= f_file_mode_group_x;
               }
             }
-            else if (change & f_file_mode_mask_how_add) {
+            else if (change & f_file_mode_t_mask_how_add) {
               if (!(*mode & f_file_mode_group_x)) {
                 *mode |= f_file_mode_group_x;
               }
@@ -745,22 +767,22 @@ extern "C" {
       }
     }
 
-    change = mode_change & f_file_mode_block_world;
+    change = mode_change & f_file_mode_t_block_world;
 
-    if (mode_replace & f_file_mode_replace_world) {
+    if (mode_replace & f_file_mode_t_replace_world) {
 
-      if (change & f_file_mode_mask_bit_read & f_file_mode_mask_how_add) {
+      if (change & f_file_mode_t_mask_bit_read & f_file_mode_t_mask_how_add) {
         *mode |= f_file_mode_world_r;
       }
 
-      if (change & f_file_mode_mask_bit_write & f_file_mode_mask_how_add) {
+      if (change & f_file_mode_t_mask_bit_write & f_file_mode_t_mask_how_add) {
         *mode |= f_file_mode_world_w;
       }
 
-      if (change & f_file_mode_mask_bit_execute & f_file_mode_mask_how_add) {
+      if (change & f_file_mode_t_mask_bit_execute & f_file_mode_t_mask_how_add) {
         *mode |= f_file_mode_world_x;
       }
-      else if (change & f_file_mode_mask_bit_execute_only & f_file_mode_mask_how_add) {
+      else if (change & f_file_mode_t_mask_bit_execute_only & f_file_mode_t_mask_how_add) {
         if (directory_is || (mode_file & f_file_mode_world_x)) {
           *mode |= f_file_mode_world_x;
         }
@@ -769,54 +791,54 @@ extern "C" {
     else {
       *mode |= mode_file & f_file_mode_world_rwx;
 
-      if (mode_change & f_file_mode_block_world) {
+      if (mode_change & f_file_mode_t_block_world) {
 
-        if (change & f_file_mode_mask_bit_read & f_file_mode_mask_how_subtract) {
+        if (change & f_file_mode_t_mask_bit_read & f_file_mode_t_mask_how_subtract) {
           if (*mode & f_file_mode_world_r) {
             *mode -= f_file_mode_world_r;
           }
         }
-        else if (change & f_file_mode_mask_bit_read & f_file_mode_mask_how_add) {
+        else if (change & f_file_mode_t_mask_bit_read & f_file_mode_t_mask_how_add) {
           if (!(*mode & f_file_mode_world_r)) {
             *mode |= f_file_mode_world_r;
           }
         }
 
-        if (change & f_file_mode_mask_bit_write & f_file_mode_mask_how_subtract) {
+        if (change & f_file_mode_t_mask_bit_write & f_file_mode_t_mask_how_subtract) {
           if (*mode & f_file_mode_world_w) {
             *mode -= f_file_mode_world_w;
           }
         }
-        else if (change & f_file_mode_mask_bit_write & f_file_mode_mask_how_add) {
+        else if (change & f_file_mode_t_mask_bit_write & f_file_mode_t_mask_how_add) {
           if (!(*mode & f_file_mode_world_w)) {
             *mode |= f_file_mode_world_w;
           }
         }
 
-        if (change & f_file_mode_mask_bit_execute) {
-          change &= f_file_mode_mask_bit_execute;
+        if (change & f_file_mode_t_mask_bit_execute) {
+          change &= f_file_mode_t_mask_bit_execute;
 
-          if (change & f_file_mode_mask_how_subtract) {
+          if (change & f_file_mode_t_mask_how_subtract) {
             if (*mode & f_file_mode_world_x) {
               *mode -= f_file_mode_world_x;
             }
           }
-          else if (change & f_file_mode_mask_how_add) {
+          else if (change & f_file_mode_t_mask_how_add) {
             if (!(*mode & f_file_mode_world_x)) {
               *mode |= f_file_mode_world_x;
             }
           }
         }
-        else if (change & f_file_mode_mask_bit_execute_only) {
-          change &= f_file_mode_mask_bit_execute_only;
+        else if (change & f_file_mode_t_mask_bit_execute_only) {
+          change &= f_file_mode_t_mask_bit_execute_only;
 
           if (directory_is || (mode_file & f_file_mode_world_x)) {
-            if (change & f_file_mode_mask_how_subtract) {
+            if (change & f_file_mode_t_mask_how_subtract) {
               if (*mode & f_file_mode_world_x) {
                 *mode -= f_file_mode_world_x;
               }
             }
-            else if (change & f_file_mode_mask_how_add) {
+            else if (change & f_file_mode_t_mask_how_add) {
               if (!(*mode & f_file_mode_world_x)) {
                 *mode |= f_file_mode_world_x;
               }
@@ -831,7 +853,7 @@ extern "C" {
 #endif // _di_f_file_mode_determine_
 
 #ifndef _di_f_file_mode_from_string_
-  f_return_status f_file_mode_from_string(const f_string_t string, const mode_t umask, f_file_mode *mode, uint8_t *replace) {
+  f_return_status f_file_mode_from_string(const f_string_t string, const mode_t umask, f_file_mode_t *mode, uint8_t *replace) {
     #ifndef _di_level_0_parameter_checking_
       if (string == 0) return F_status_set_error(F_parameter);
       if (string[0] == 0) return F_status_set_error(F_parameter);
@@ -901,57 +923,57 @@ extern "C" {
       uint8_t on = 0; // 1 = user, 2 = group, 4 = world/sticky, 7 = all.
       uint8_t how = 0; // 1 = add, 2 = replace, 3 = subtract.
 
-      f_file_mode mode_mask = 0;
-      f_file_mode mode_umask = 0;
-      f_file_mode what = 0;
+      f_file_mode_t mode_mask = 0;
+      f_file_mode_t mode_umask = 0;
+      f_file_mode_t what = 0;
 
-      // translate the umask into an f_file_mode umask equivalent.
+      // translate the umask into an f_file_mode_t umask equivalent.
       if (umask & f_file_mode_special_set_user) {
-        mode_umask = f_file_mode_block_special & f_file_mode_mask_bit_set_owner;
+        mode_umask = f_file_mode_t_block_special & f_file_mode_t_mask_bit_set_owner;
       }
 
       if (umask & f_file_mode_special_set_group) {
-        mode_umask |= f_file_mode_block_special & f_file_mode_mask_bit_set_group;
+        mode_umask |= f_file_mode_t_block_special & f_file_mode_t_mask_bit_set_group;
       }
 
       if (umask & f_file_mode_special_sticky) {
-        mode_umask |= f_file_mode_block_special & f_file_mode_mask_bit_sticky;
+        mode_umask |= f_file_mode_t_block_special & f_file_mode_t_mask_bit_sticky;
       }
 
       if (umask & f_file_mode_owner_r) {
-        mode_umask |= f_file_mode_block_owner & f_file_mode_mask_bit_read;
+        mode_umask |= f_file_mode_t_block_owner & f_file_mode_t_mask_bit_read;
       }
 
       if (umask & f_file_mode_owner_w) {
-        mode_umask |= f_file_mode_block_owner & f_file_mode_mask_bit_write;
+        mode_umask |= f_file_mode_t_block_owner & f_file_mode_t_mask_bit_write;
       }
 
       if (umask & f_file_mode_owner_x) {
-        mode_umask |= f_file_mode_block_owner & f_file_mode_mask_bit_execute;
+        mode_umask |= f_file_mode_t_block_owner & f_file_mode_t_mask_bit_execute;
       }
 
       if (umask & f_file_mode_group_r) {
-        mode_umask |= f_file_mode_block_group & f_file_mode_mask_bit_read;
+        mode_umask |= f_file_mode_t_block_group & f_file_mode_t_mask_bit_read;
       }
 
       if (umask & f_file_mode_group_w) {
-        mode_umask |= f_file_mode_block_group & f_file_mode_mask_bit_write;
+        mode_umask |= f_file_mode_t_block_group & f_file_mode_t_mask_bit_write;
       }
 
       if (umask & f_file_mode_group_x) {
-        mode_umask |= f_file_mode_block_group & f_file_mode_mask_bit_execute;
+        mode_umask |= f_file_mode_t_block_group & f_file_mode_t_mask_bit_execute;
       }
 
       if (umask & f_file_mode_world_r) {
-        mode_umask |= f_file_mode_block_world & f_file_mode_mask_bit_read;
+        mode_umask |= f_file_mode_t_block_world & f_file_mode_t_mask_bit_read;
       }
 
       if (umask & f_file_mode_world_w) {
-        mode_umask |= f_file_mode_block_world & f_file_mode_mask_bit_write;
+        mode_umask |= f_file_mode_t_block_world & f_file_mode_t_mask_bit_write;
       }
 
       if (umask & f_file_mode_world_x) {
-        mode_umask |= f_file_mode_block_world & f_file_mode_mask_bit_execute;
+        mode_umask |= f_file_mode_t_block_world & f_file_mode_t_mask_bit_execute;
       }
 
       for (f_string_length_t i = 0; syntax && string[i]; i++) {
@@ -959,22 +981,22 @@ extern "C" {
         switch (string[i]) {
           case 'o':
             on |= 1;
-            mode_mask |= f_file_mode_block_world;
+            mode_mask |= f_file_mode_t_block_world;
             break;
 
           case 'g':
             on |= 2;
-            mode_mask |= f_file_mode_block_group;
+            mode_mask |= f_file_mode_t_block_group;
             break;
 
           case 'u':
             on |= 4;
-            mode_mask |= f_file_mode_block_owner;
+            mode_mask |= f_file_mode_t_block_owner;
             break;
 
           case 'a':
             on = 7;
-            mode_mask = f_file_mode_block_standard;
+            mode_mask = f_file_mode_t_block_standard;
             break;
 
           case '+':
@@ -990,61 +1012,61 @@ extern "C" {
               how = on ? 2 : 5;
 
               // clear by mask to prepare for replacement, which includes clearing the special block.
-              mode_mask |= f_file_mode_block_special;
+              mode_mask |= f_file_mode_t_block_special;
               *mode -= (*mode) & mode_mask;
 
-              *replace |= f_file_mode_replace_special;
+              *replace |= f_file_mode_t_replace_special;
 
-              if (mode_mask & f_file_mode_block_owner) {
-                *replace |= f_file_mode_replace_owner;
+              if (mode_mask & f_file_mode_t_block_owner) {
+                *replace |= f_file_mode_t_replace_owner;
               }
 
-              if (mode_mask & f_file_mode_block_group) {
-                *replace |= f_file_mode_replace_group;
+              if (mode_mask & f_file_mode_t_block_group) {
+                *replace |= f_file_mode_t_replace_group;
               }
 
-              if (mode_mask & f_file_mode_block_world) {
-                *replace |= f_file_mode_replace_world;
+              if (mode_mask & f_file_mode_t_block_world) {
+                *replace |= f_file_mode_t_replace_world;
               }
             }
 
             if (!on) {
               on = 7;
-              mode_mask = f_file_mode_block_all;
+              mode_mask = f_file_mode_t_block_all;
             }
 
             for (i++; string[i]; i++) {
 
               if (string[i] == 'r') {
-                what = f_file_mode_mask_bit_read;
+                what = f_file_mode_t_mask_bit_read;
               }
               else if (string[i] == 'w') {
-                what = f_file_mode_mask_bit_write;
+                what = f_file_mode_t_mask_bit_write;
               }
               else if (string[i] == 'x') {
-                what = f_file_mode_mask_bit_execute;
+                what = f_file_mode_t_mask_bit_execute;
               }
               else if (string[i] == 'X') {
-                what = f_file_mode_mask_bit_execute_only;
+                what = f_file_mode_t_mask_bit_execute_only;
               }
               else if (string[i] == 's') {
-                mode_mask |= f_file_mode_block_special;
+                mode_mask |= f_file_mode_t_block_special;
 
                 if (on & 4) {
-                  what = f_file_mode_mask_bit_set_owner;
+                  what = f_file_mode_t_mask_bit_set_owner;
                 }
                 else if (on & 2) {
-                  what = f_file_mode_mask_bit_set_group;
+                  what = f_file_mode_t_mask_bit_set_group;
                 }
                 else {
                   what = 0;
                 }
               }
               else if (string[i] == 't') {
-                mode_mask |= f_file_mode_block_special;
+                mode_mask |= f_file_mode_t_block_special;
 
                 if (on & 1) {
-                  what = f_file_mode_mask_bit_sticky;
+                  what = f_file_mode_t_mask_bit_sticky;
                 }
                 else {
                   what = 0;
@@ -1066,10 +1088,10 @@ extern "C" {
               }
 
               if (how == 1 || how == 2 || how == 4 || how == 5) {
-                *mode |= what & mode_mask & f_file_mode_mask_how_add;
+                *mode |= what & mode_mask & f_file_mode_t_mask_how_add;
               }
               else if (how == 3 || how == 6) {
-                *mode |= what & mode_mask & f_file_mode_mask_how_subtract;
+                *mode |= what & mode_mask & f_file_mode_t_mask_how_subtract;
               }
             } // for
 
@@ -1105,12 +1127,12 @@ extern "C" {
         how = 2;
         i = 1;
 
-        *replace = f_file_mode_replace_standard;
+        *replace = f_file_mode_t_replace_standard;
       }
       else {
         how = 2;
 
-        *replace = f_file_mode_replace_standard | f_file_mode_replace_directory;
+        *replace = f_file_mode_t_replace_standard | f_file_mode_t_replace_directory;
       }
 
       if (string[i] == '0') {
@@ -1163,7 +1185,7 @@ extern "C" {
         else if (how == 2) {
           // if there are only '0's then the standard and setuid/setgid/sticky bits are to be replaced.
           if (*mode == 0) {
-            *replace = f_file_mode_replace_standard | f_file_mode_replace_special;
+            *replace = f_file_mode_t_replace_standard | f_file_mode_t_replace_special;
           }
         }
       }
@@ -1244,17 +1266,67 @@ extern "C" {
   }
 #endif // _di_f_file_mode_set_at_
 
-#ifndef _di_f_file_mode_determine_
-  f_return_status f_file_mode_to_mode(const f_file_mode mode_from, const uint8_t mode_replace, mode_t *mode_to) {
+#ifndef _di_f_file_mode_to_mode_
+  f_return_status f_file_mode_to_mode(const f_file_mode_t from, mode_t *to) {
     #ifndef _di_level_0_parameter_checking_
-      if (mode_to == 0) return F_status_set_error(F_parameter);
+      if (to == 0) return F_status_set_error(F_parameter);
     #endif // _di_level_0_parameter_checking_
 
-    // @todo
+    const f_file_mode_t add = from & f_file_mode_t_mask_how_add;
+
+    *to = 0;
+
+    if (add & f_file_mode_t_mask_bit_set_owner) {
+      *to |= f_file_mode_special_set_user;
+    }
+
+    if (add & f_file_mode_t_mask_bit_set_group) {
+      *to |= f_file_mode_special_set_group;
+    }
+
+    if (add & f_file_mode_t_mask_bit_sticky) {
+      *to |= f_file_mode_special_sticky;
+    }
+
+    if (add & f_file_mode_t_block_owner & f_file_mode_t_mask_bit_read) {
+      *to |= f_file_mode_owner_r;
+    }
+
+    if (add & f_file_mode_t_block_group & f_file_mode_t_mask_bit_read) {
+      *to |= f_file_mode_group_r;
+    }
+
+    if (add & f_file_mode_t_block_world & f_file_mode_t_mask_bit_write) {
+      *to |= f_file_mode_world_r;
+    }
+
+    if (add & f_file_mode_t_block_owner & f_file_mode_t_mask_bit_write) {
+      *to |= f_file_mode_owner_w;
+    }
+
+    if (add & f_file_mode_t_block_group & f_file_mode_t_mask_bit_write) {
+      *to |= f_file_mode_group_w;
+    }
+
+    if (add & f_file_mode_t_block_world & f_file_mode_t_mask_bit_write) {
+      *to |= f_file_mode_world_w;
+    }
+
+    if (add & f_file_mode_t_block_owner & (f_file_mode_t_mask_bit_execute | f_file_mode_t_mask_bit_execute_only)) {
+      *to |= f_file_mode_owner_x;
+    }
+
+    if (add & f_file_mode_t_block_group & (f_file_mode_t_mask_bit_execute | f_file_mode_t_mask_bit_execute_only)) {
+      *to |= f_file_mode_group_x;
+    }
+
+    if (add & f_file_mode_t_block_world & (f_file_mode_t_mask_bit_execute | f_file_mode_t_mask_bit_execute_only)) {
+      *to |= f_file_mode_world_x;
+    }
 
     return F_none;
   }
-#endif // _di_f_file_mode_determine_
+#endif // _di_f_file_mode_to_mode_
 
 #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) {
@@ -1349,6 +1421,28 @@ extern "C" {
   }
 #endif // _di_f_file_open_at_
 
+#ifndef _di_f_file_owner_read_
+  f_return_status f_file_owner_read(const f_string_t path, uid_t *owner) {
+    #ifndef _di_level_0_parameter_checking_
+      if (path == 0) return F_status_set_error(F_parameter);
+      if (owner == 0) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    struct stat stat_file;
+
+    memset(&stat_file, 0, sizeof(struct stat));
+
+    f_status_t status = private_f_file_stat(path, F_true, &stat_file);
+    if (F_status_is_error(status)) {
+      return status;
+    }
+
+    *owner = stat_file.st_uid;
+
+    return F_none;
+  }
+#endif // _di_f_file_owner_read_
+
 #ifndef _di_f_file_read_
   f_return_status f_file_read(const f_file_t file, f_string_dynamic_t *buffer) {
     #ifndef _di_level_0_parameter_checking_
index e764c50af7d8b2652e8f2349d9af07c17cadef19..58245ada3661b2ab4c619177be1c48ec21151066 100644 (file)
@@ -264,7 +264,11 @@ extern "C" {
 /**
  * File mode related functionality.
  *
- * The f_file_mode type properties are 8-bit types with the following structure:
+ * There are two types of file modes the f_file_mode_t macros associate with.
+ *
+ * The first type is the traditional mode type, associated with mode_t.
+ *
+ * The second type is f_file_mode_t, which utilizes 8-bit types with the following structure:
  *
  *   There should only be a single bit for each 'r', 'w', 'x', and 'X' bit (as well as 'S', 's', and 't'):
  *     'r' = read bit.
@@ -274,40 +278,43 @@ extern "C" {
  *     'S' = set user bit (setuid).
  *     's' = set group bit (setgid).
  *     't' = sticky bit.
+ *
+ * The file mode macros with "f_file_mode_" prefix (has no "_t") refer to the first type (mode_t).
+ * The file mode macros with "f_file_mode_t" prefix refer to the second type (f_file_mode_t).
  */
 #ifndef _di_f_file_mode_
-  typedef uint32_t f_file_mode;
-
-  #define f_file_mode_block_special  0x77000000 // 0111 0111 0000 0000 0000 0000 0000 0000
-  #define f_file_mode_block_owner    0x00ff0000 // 0000 0000 1111 1111 0000 0000 0000 0000
-  #define f_file_mode_block_group    0x0000ff00 // 0000 0000 0000 0000 1111 1111 0000 0000
-  #define f_file_mode_block_world    0x000000ff // 0000 0000 0000 0000 0000 0000 1111 1111
-
-  #define f_file_mode_block_all      0x77ffffff // 0111 0111 1111 1111 1111 1111 1111 1111
-  #define f_file_mode_block_standard 0x00ffffff // 0000 0000 1111 1111 1111 1111 1111 1111
-
-  #define f_file_mode_mask_how_add      0x070f0f0f // 0000 0111 0000 1111 0000 1111 0000 1111
-  #define f_file_mode_mask_how_subtract 0x70f0f0f0 // 0111 0000 1111 0000 1111 0000 1111 0000
-
-  #define f_file_mode_mask_bit_execute      0x00111111 // 0000 0000 0001 0001 0001 0001 0001 0001
-  #define f_file_mode_mask_bit_execute_only 0x00888888 // 0000 0000 1000 1000 1000 1000 1000 1000
-  #define f_file_mode_mask_bit_read         0x00444444 // 0000 0000 0100 0100 0100 0100 0100 0100
-  #define f_file_mode_mask_bit_set_group    0x22000000 // 0010 0010 0000 0000 0000 0000 0000 0000
-  #define f_file_mode_mask_bit_set_owner    0x44000000 // 0100 0100 0000 0000 0000 0000 0000 0000
-  #define f_file_mode_mask_bit_sticky       0x11000000 // 0001 0001 0000 0000 0000 0000 0000 0000
-  #define f_file_mode_mask_bit_write        0x00222222 // 0000 0000 0010 0010 0010 0010 0010 0010
-
-  #define f_file_mode_replace_owner     0x1  // 0000 0001
-  #define f_file_mode_replace_group     0x2  // 0000 0010
-  #define f_file_mode_replace_world     0x4  // 0000 0100
-  #define f_file_mode_replace_special   0x8  // 0000 1000
-  #define f_file_mode_replace_directory 0x10 // 0001 0000
-
-  #define f_file_mode_replace_all      0x1f // 0001 1111
-  #define f_file_mode_replace_other    0x18 // 0001 1000
-  #define f_file_mode_replace_standard 0x7  // 0000 0111
-
-  // file permission modes.
+  typedef uint32_t f_file_mode_t;
+
+  #define f_file_mode_t_block_special 0x77000000 // 0111 0111 0000 0000 0000 0000 0000 0000
+  #define f_file_mode_t_block_owner   0x00ff0000 // 0000 0000 1111 1111 0000 0000 0000 0000
+  #define f_file_mode_t_block_group   0x0000ff00 // 0000 0000 0000 0000 1111 1111 0000 0000
+  #define f_file_mode_t_block_world   0x000000ff // 0000 0000 0000 0000 0000 0000 1111 1111
+
+  #define f_file_mode_t_block_all      0x77ffffff // 0111 0111 1111 1111 1111 1111 1111 1111
+  #define f_file_mode_t_block_standard 0x00ffffff // 0000 0000 1111 1111 1111 1111 1111 1111
+
+  #define f_file_mode_t_mask_how_add      0x070f0f0f // 0000 0111 0000 1111 0000 1111 0000 1111
+  #define f_file_mode_t_mask_how_subtract 0x70f0f0f0 // 0111 0000 1111 0000 1111 0000 1111 0000
+
+  #define f_file_mode_t_mask_bit_execute      0x00111111 // 0000 0000 0001 0001 0001 0001 0001 0001
+  #define f_file_mode_t_mask_bit_execute_only 0x00888888 // 0000 0000 1000 1000 1000 1000 1000 1000
+  #define f_file_mode_t_mask_bit_read         0x00444444 // 0000 0000 0100 0100 0100 0100 0100 0100
+  #define f_file_mode_t_mask_bit_set_group    0x22000000 // 0010 0010 0000 0000 0000 0000 0000 0000
+  #define f_file_mode_t_mask_bit_set_owner    0x44000000 // 0100 0100 0000 0000 0000 0000 0000 0000
+  #define f_file_mode_t_mask_bit_sticky       0x11000000 // 0001 0001 0000 0000 0000 0000 0000 0000
+  #define f_file_mode_t_mask_bit_write        0x00222222 // 0000 0000 0010 0010 0010 0010 0010 0010
+
+  #define f_file_mode_t_replace_owner     0x1  // 0000 0001
+  #define f_file_mode_t_replace_group     0x2  // 0000 0010
+  #define f_file_mode_t_replace_world     0x4  // 0000 0100
+  #define f_file_mode_t_replace_special   0x8  // 0000 1000
+  #define f_file_mode_t_replace_directory 0x10 // 0001 0000
+
+  #define f_file_mode_t_replace_all      0x1f // 0001 1111
+  #define f_file_mode_t_replace_other    0x18 // 0001 1000
+  #define f_file_mode_t_replace_standard 0x7  // 0000 0111
+
+  // file permission modes (mode_t).
   #define f_file_mode_owner_rwx S_IRWXU
   #define f_file_mode_owner_r   S_IRUSR
   #define f_file_mode_owner_w   S_IWUSR
@@ -338,16 +345,16 @@ extern "C" {
   #define f_file_mode_all_w   (f_file_mode_owner_w | f_file_mode_group_w | f_file_mode_world_w)
   #define f_file_mode_all_x   (f_file_mode_owner_x | f_file_mode_group_x | f_file_mode_world_x)
 
-  // file mode set-uid/set-gid/sticky-bits and all bits.
+  // file mode set-uid/set-gid/sticky-bits and all bits (mode_t).
   #define f_file_mode_special_set_user  S_ISUID
   #define f_file_mode_special_set_group S_ISGID
   #define f_file_mode_special_sticky    S_ISVTX
   #define f_file_mode_special_all       (S_ISUID | S_ISGID | S_ISVTX)
 
-  // all permissions modes and special modes.
+  // all permissions modes and special modes (mode_t).
   #define f_file_mode_all (f_file_mode_special_all | f_file_mode_all_rwx)
 
-  // special file mode combinations.
+  // special file mode combinations (mode_t).
   #define f_file_mode_user_access    (f_file_mode_owner_rwx | f_file_mode_group_rwx | f_file_mode_world_x)
   #define f_file_mode_user_directory (f_file_mode_owner_rwx | f_file_mode_group_rwx)
   #define f_file_mode_user_file      (f_file_mode_owner_rw | f_file_mode_group_rw)
@@ -875,6 +882,31 @@ extern "C" {
 #endif // _di_f_file_flush_
 
 /**
+ * Get the current group of a file.
+ *
+ * @param path
+ *   The path file name.
+ * @param group
+ *   The id of the file's group.
+ *
+ * @return
+ *   F_none on success.
+ *   F_access_denied (with error bit) if access to the file was denied.
+ *   F_directory (with error bit) on invalid directory.
+ *   F_file_found_not (with error bit) if the file was not found.
+ *   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_number_overflow (with error bit) on overflow error.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ * @see fstat()
+ */
+#ifndef _di_f_file_group_read_
+  extern f_return_status f_file_group_read(const f_string_t path, uid_t *group);
+#endif // _di_f_file_group_read_
+
+/**
  * Identify whether or not a file exists at the given path and if that file is a specific type.
  *
  * This does not require access on the file itself.
@@ -1182,7 +1214,7 @@ extern "C" {
  * @see f_file_mode_from_string()
  */
 #ifndef _di_f_file_mode_determine_
-  extern f_return_status f_file_mode_determine(const mode_t mode_file, const f_file_mode mode_change, const uint8_t mode_replace, const bool directory_is, mode_t *mode);
+  extern f_return_status f_file_mode_determine(const mode_t mode_file, const f_file_mode_t mode_change, const uint8_t mode_replace, const bool directory_is, mode_t *mode);
 #endif // _di_f_file_mode_determine_
 
 /**
@@ -1232,7 +1264,7 @@ extern "C" {
  *
  * When using digits, the umask is always ignored.
  * When there is a leading '0' or '=' when using digits, then the special bits should be replaced.
- * Otherwise, the current special bits are intended to be respected (designated by f_file_mode_replace_directory).
+ * Otherwise, the current special bits are intended to be respected (designated by f_file_mode_t_replace_directory).
  *
  * When using non-digits and '+', '-', or '=' are specified without a leading 'a', 'u', 'g', or 'o', then the mode operations should be performed against the current umask.
  * These are designated with the umask hows, such as f_file_mode_how_umask_replace.
@@ -1258,7 +1290,7 @@ extern "C" {
  *   The determined mode.
  *   This uses bitwise data.
  * @param replace
- *   The determined modes that are to be replaced, such as: f_file_mode_replace_owner.
+ *   The determined modes that are to be replaced, such as: f_file_mode_t_replace_owner.
  *   This uses bitwise data.
  *
  * @return
@@ -1271,11 +1303,11 @@ extern "C" {
  * @see private_f_file_mode_determine()
  */
 #ifndef _di_f_file_mode_from_string_
-  extern f_return_status f_file_mode_from_string(const f_string_t string, const mode_t umask, f_file_mode *mode, uint8_t *replace);
+  extern f_return_status f_file_mode_from_string(const f_string_t string, const mode_t umask, f_file_mode_t *mode, uint8_t *replace);
 #endif // _di_f_file_mode_from_string_
 
 /**
- * Get the current file mode as an f_file_mode.
+ * Get the current file mode as an f_file_mode_t.
  *
  * @param path
  *   The path file name.
@@ -1300,7 +1332,7 @@ extern "C" {
 #endif // _di_f_file_mode_read_
 
 /**
- * Get the current file mode as an f_file_mode.
+ * Get the current file mode as an f_file_mode_t.
  *
  * @param at_id
  *   The parent directory, as an open directory file descriptor, in which path is relative to.
@@ -1391,13 +1423,13 @@ extern "C" {
 #endif // _di_f_file_mode_set_at_
 
 /**
- * Convert an f_file_mode type to a mode_t type.
+ * Convert an f_file_mode_t type to a mode_t type.
+ *
+ * This essentially converts all "add" codes from an f_file_mode_t to a mode_t, ignoring the "subtract" codes.
  *
- * @param mode_from
+ * @param from
  *   The file mode to convert from.
- * @param mode_replace
- *   The modes designated to be replaced instead of simply changed.
- * @param mode_to
+ * @param to
  *   The determined mode.
  *
  * @return
@@ -1406,9 +1438,9 @@ extern "C" {
  *
  * @see f_file_mode_from_string()
  */
-#ifndef _di_f_file_mode_determine_
-  extern f_return_status f_file_mode_to_mode(const f_file_mode mode_from, const uint8_t mode_replace, mode_t *mode_to);
-#endif // _di_f_file_mode_determine_
+#ifndef _di_f_file_mode_to_mode_
+  extern f_return_status f_file_mode_to_mode(const f_file_mode_t from, mode_t *to);
+#endif // _di_f_file_mode_to_mode_
 
 /**
  * Get the base name of a file path.
@@ -1515,6 +1547,31 @@ extern "C" {
 #endif // _di_f_file_open_at_
 
 /**
+ * Get the current owner of a file.
+ *
+ * @param path
+ *   The path file name.
+ * @param owner
+ *   The id of the file's owner.
+ *
+ * @return
+ *   F_none on success.
+ *   F_access_denied (with error bit) if access to the file was denied.
+ *   F_directory (with error bit) on invalid directory.
+ *   F_file_found_not (with error bit) if the file was not found.
+ *   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_number_overflow (with error bit) on overflow error.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ * @see fstat()
+ */
+#ifndef _di_f_file_owner_read_
+  extern f_return_status f_file_owner_read(const f_string_t path, uid_t *owner);
+#endif // _di_f_file_owner_read_
+
+/**
  * Read until EOF is reached.
  *
  * To check how much was read into the buffer, record buffer->used before execution and compare to buffer->used after execution.