]> Kevux Git Server - fll/commitdiff
Progress: get the change file mode functions in an acceptable state.
authorKevin Day <thekevinday@gmail.com>
Fri, 14 Aug 2020 02:11:20 +0000 (21:11 -0500)
committerKevin Day <thekevinday@gmail.com>
Fri, 14 Aug 2020 02:11:20 +0000 (21:11 -0500)
Finish writing the file change mode and related functions.
Due to significant gaps in development and the notable complexity of the ugo+rwxXst modes, this is implemented in what appears to be good enough for now.
There are likely hidden logic flaws or incomplete/missing logic.

This adds an @fixme to more thoroughly review this and possible fix this at a later date.
For now, this allows moving forward to avoid spending too much time on this one area.

level_0/f_file/c/file.c
level_0/f_file/c/file.h
level_3/fake/c/private-make.c
level_3/fake/data/build/fakefile

index 4b46545fa930ab613dd5b8afcf39a5b12568515a..b57f85a9bac9f8bae9a4fc3a53045be51800beaa 100644 (file)
@@ -525,7 +525,7 @@ 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, const mode_t umask, mode_t *mode) {
+  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) {
     #ifndef _di_level_0_parameter_checking_
       if (mode == 0) return F_status_set_error(F_parameter);
     #endif // _di_level_0_parameter_checking_
@@ -826,16 +826,12 @@ extern "C" {
       }
     }
 
-    if (mode_replace & f_file_mode_replace_umask) {
-      *mode -= *mode & umask;
-    }
-
     return F_none;
   }
 #endif // _di_f_file_mode_determine_
 
 #ifndef _di_f_file_mode_from_string_
-  f_return_status f_file_mode_from_string(const f_string string, f_file_mode *mode, uint8_t *replace) {
+  f_return_status f_file_mode_from_string(const f_string string, const mode_t umask, f_file_mode *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);
@@ -904,60 +900,86 @@ extern "C" {
     if (syntax == 1) {
       uint8_t on = 0; // 1 = user, 2 = group, 4 = world/sticky, 7 = all.
       uint8_t how = 0; // 1 = add, 2 = replace, 3 = subtract.
-      bool active = F_false;
 
-      f_file_mode mask = f_file_mode_block_special;
+      f_file_mode mode_mask = 0;
+      f_file_mode mode_umask = 0;
       f_file_mode what = 0;
 
-      // @todo: this needs to record all of the possible combinations of add, subtract, and assignment (=).
-      for (f_string_length i = 0; syntax && i < string[i]; i++) {
+      // translate the umask into an f_file_mode umask equivalent.
+      if (umask & f_file_mode_special_set_user) {
+        mode_umask = f_file_mode_block_special & f_file_mode_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;
+      }
+
+      if (umask & f_file_mode_special_sticky) {
+        mode_umask |= f_file_mode_block_special & f_file_mode_mask_bit_sticky;
+      }
+
+      if (umask & f_file_mode_owner_r) {
+        mode_umask |= f_file_mode_block_owner & f_file_mode_mask_bit_read;
+      }
+
+      if (umask & f_file_mode_owner_w) {
+        mode_umask |= f_file_mode_block_owner & f_file_mode_mask_bit_write;
+      }
+
+      if (umask & f_file_mode_owner_x) {
+        mode_umask |= f_file_mode_block_owner & f_file_mode_mask_bit_execute;
+      }
+
+      if (umask & f_file_mode_group_r) {
+        mode_umask |= f_file_mode_block_group & f_file_mode_mask_bit_read;
+      }
+
+      if (umask & f_file_mode_group_w) {
+        mode_umask |= f_file_mode_block_group & f_file_mode_mask_bit_write;
+      }
+
+      if (umask & f_file_mode_group_x) {
+        mode_umask |= f_file_mode_block_group & f_file_mode_mask_bit_execute;
+      }
+
+      if (umask & f_file_mode_world_r) {
+        mode_umask |= f_file_mode_block_world & f_file_mode_mask_bit_read;
+      }
+
+      if (umask & f_file_mode_world_w) {
+        mode_umask |= f_file_mode_block_world & f_file_mode_mask_bit_write;
+      }
+
+      if (umask & f_file_mode_world_x) {
+        mode_umask |= f_file_mode_block_world & f_file_mode_mask_bit_execute;
+      }
+
+      for (f_string_length i = 0; syntax && string[i]; i++) {
 
         switch (string[i]) {
           case 'o':
-            if (active) {
-              syntax = 0;
-              break;
-            }
-
-            on = 1;
-            mask |= f_file_mode_block_world;
+            on |= 1;
+            mode_mask |= f_file_mode_block_world;
             break;
 
           case 'g':
-            if (active) {
-              syntax = 0;
-              break;
-            }
-
-            on = 2;
-            mask |= f_file_mode_block_group;
+            on |= 2;
+            mode_mask |= f_file_mode_block_group;
             break;
 
           case 'u':
-            if (active) {
-              syntax = 0;
-              break;
-            }
-
-            on = 4;
-            mask |= f_file_mode_block_owner;
+            on |= 4;
+            mode_mask |= f_file_mode_block_owner;
             break;
 
           case 'a':
-            if (active) {
-              syntax = 0;
-              break;
-            }
-
             on = 7;
-            mask = f_file_mode_block_all;
+            mode_mask = f_file_mode_block_standard;
             break;
 
           case '+':
           case '-':
           case '=':
-            active = F_true;
-
             if (string[i] == '+') {
               how = on ? 1 : 4;
             }
@@ -967,29 +989,31 @@ extern "C" {
             else {
               how = on ? 2 : 5;
 
-              // only the parts designated by the mask should be replaced.
-              *mode -= (*mode) & mask;
+              // clear by mask to prepare for replacement, which includes clearing the special block.
+              mode_mask |= f_file_mode_block_special;
+              *mode -= (*mode) & mode_mask;
 
-              if (mask == f_file_mode_block_all) {
-                *replace = f_file_mode_replace_all;
-              }
-              else if (mask & f_file_mode_block_world) {
-                *replace |= f_file_mode_block_special & f_file_mode_block_world;
+              *replace |= f_file_mode_replace_special;
+
+              if (mode_mask & f_file_mode_block_owner) {
+                *replace |= f_file_mode_replace_owner;
               }
-              else if (mask & f_file_mode_block_group) {
-                *replace |= f_file_mode_block_special & f_file_mode_block_group;
+
+              if (mode_mask & f_file_mode_block_group) {
+                *replace |= f_file_mode_replace_group;
               }
-              else if (mask & f_file_mode_block_owner) {
-                *replace |= f_file_mode_block_special & f_file_mode_block_owner;
+
+              if (mode_mask & f_file_mode_block_world) {
+                *replace |= f_file_mode_replace_world;
               }
             }
 
             if (!on) {
               on = 7;
-              mask = f_file_mode_block_all;
+              mode_mask = f_file_mode_block_all;
             }
 
-            for (i++; i < string[i]; i++) {
+            for (i++; string[i]; i++) {
 
               if (string[i] == 'r') {
                 what = f_file_mode_mask_bit_read;
@@ -1004,6 +1028,8 @@ extern "C" {
                 what = f_file_mode_mask_bit_execute_only;
               }
               else if (string[i] == 's') {
+                mode_mask |= f_file_mode_block_special;
+
                 if (on & 4) {
                   what = f_file_mode_mask_bit_set_owner;
                 }
@@ -1015,6 +1041,8 @@ extern "C" {
                 }
               }
               else if (string[i] == 't') {
+                mode_mask |= f_file_mode_block_special;
+
                 if (on & 1) {
                   what = f_file_mode_mask_bit_sticky;
                 }
@@ -1023,15 +1051,13 @@ extern "C" {
                 }
               }
               else if (string[i] == ',') {
-                active = F_false;
+                if (how > 3) {
+                  *mode -= *mode & mode_umask;
+                }
+
                 on = 0;
                 how = 0;
-                mask = f_file_mode_block_special;
-                break;
-              }
-              else if (string[i] == '+' || string[i] == '-' || string[i] == '=') {
-                // have the outer loop resume at this character after it increments.
-                i--;
+                mode_mask = 0;
                 break;
               }
               else {
@@ -1039,27 +1065,23 @@ extern "C" {
                 break;
               }
 
-              if (how == 1 || how == 2) {
-                *mode |= what & mask & f_file_mode_mask_how_add;
+              if (how == 1 || how == 2 || how == 4 || how == 5) {
+                *mode |= what & mode_mask & f_file_mode_mask_how_add;
               }
-              else if (how == 3) {
-                *mode |= what & mask & f_file_mode_mask_how_subtract;
-              }
-              else if (how == 4 || how == 5) {
-                *mode |= what & mask & f_file_mode_mask_how_add;
-                *replace |= f_file_mode_replace_umask;
-              }
-              else if (how == 6) {
-                *mode |= what & mask & f_file_mode_mask_how_subtract;
-                *replace |= f_file_mode_replace_umask;
+              else if (how == 3 || how == 6) {
+                *mode |= what & mode_mask & f_file_mode_mask_how_subtract;
               }
             } // for
 
+            if (how > 3) {
+              *mode -= *mode & mode_umask;
+            }
+
             break;
 
-        default:
-          syntax = 0;
-          break;
+          default:
+            syntax = 0;
+            break;
         }
       } // for
     }
@@ -1139,9 +1161,9 @@ extern "C" {
           syntax = 0;
         }
         else if (how == 2) {
-          // if there are only '0's then the setuid/setgid/sticky bits are to be replaced.
+          // 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;
+            *replace = f_file_mode_replace_standard | f_file_mode_replace_special;
           }
         }
       }
index 37c1fa24ce31539309eac2d815fd636b9fe637a6..d286e2b475d766fb075562bc9d9a1390a73e1446 100644 (file)
@@ -247,7 +247,6 @@ extern "C" {
  * File mode related functionality.
  *
  * The f_file_mode type properties are 8-bit types with the following structure:
- *   @todo finish documentation.
  *
  *   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.
@@ -257,20 +256,17 @@ extern "C" {
  *     'S' = set user bit (setuid).
  *     's' = set group bit (setgid).
  *     't' = sticky bit.
- *
- *   The mode replace codes are meant to be used for the user, group, and world modes.
- *   Generally "special" bits are preserved unless explicitly changed so there is also a "special" mode replace code as well.
- *   The "umask" equivalent specifies that the mask should allow for umask influence.
  */
 #ifndef _di_f_file_mode_
   typedef uint32_t f_file_mode;
 
-                                               // 0000 0000 0000 0111 0000 0101 0000 0101
-  #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_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
@@ -286,12 +282,11 @@ extern "C" {
   #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   0x7  // 0000 1000
-  #define f_file_mode_replace_umask     0x10 // 0001 0000
-  #define f_file_mode_replace_directory 0x20 // 0010 0000
+  #define f_file_mode_replace_special   0x8  // 0000 1000
+  #define f_file_mode_replace_directory 0x10 // 0001 0000
 
-  #define f_file_mode_replace_all      0x3f // 0011 1111
-  #define f_file_mode_replace_other    0x38 // 0011 1000
+  #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.
@@ -1146,6 +1141,8 @@ extern "C" {
 /**
  * Determine how the mode should be applied based on different file properties and the given mode properties.
  *
+ * This does not set mode based on umask(), which is already applied if f_file_mode_from_string() was used to create mode_change.
+ *
  * @param mode_file
  *   The mode_t value representing the file's current mode.
  *   This is expected to be populated from (struct stat).st_mode.
@@ -1155,8 +1152,6 @@ extern "C" {
  *   The mode modes that should be replaced instead of simply changed.
  * @param directory_is
  *   Set to TRUE if the file is a directory, FALSE otherwise.
- * @param umask
- *   The current umask, which will be used if necessary.
  * @param mode
  *   The determined mode.
  *
@@ -1167,7 +1162,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, const mode_t umask, mode_t *mode);
+  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);
 #endif // _di_f_file_mode_determine_
 
 /**
@@ -1231,8 +1226,12 @@ extern "C" {
  *
  * Considering the behavior, assume that when "=" or a leading "0" is provided, this will change the setuid/setgid/sticky bits, otherwise it preserves those bits for directories.
  *
+ * @fixme the possibilities are a bit extensive and this needs additional review; remove this fixme when this review is completed.
+ *
  * @param string
  *   A NULL terminated string designating the desired mode, following the above string syntax.
+ * @param umask
+ *   The umask to be applied to the file mode, when applicable.
  * @param mode
  *   The determined mode.
  *   This uses bitwise data.
@@ -1250,7 +1249,7 @@ 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 string, f_file_mode *mode, uint8_t *replace);
+  extern f_return_status f_file_mode_from_string(const f_string string, const mode_t umask, f_file_mode *mode, uint8_t *replace);
 #endif // _di_f_file_mode_from_string_
 
 /**
index 1a53e0fd2b2ae1489511e0694a4a55978f040bc3..1d1f515ae86ff4bd5610a459658088fd5ffd8d2d 100644 (file)
@@ -99,7 +99,7 @@ extern "C" {
       return F_status_set_error(F_parameter);
     }
 
-    f_status status = f_file_mode_from_string(buffer.string, mode, replace);
+    f_status status = f_file_mode_from_string(buffer.string, data.umask, mode, replace);
 
     if (F_status_is_error(status)) {
       if (data.verbosity != fake_verbosity_quiet) {
@@ -1539,7 +1539,7 @@ extern "C" {
           break;
         }
 
-        *status = f_file_mode_determine(stat_file.st_mode, mode_rule, replace, f_macro_file_type_is_directory(stat_file.st_mode), data.umask, &mode);
+        *status = f_file_mode_determine(stat_file.st_mode, mode_rule, replace, f_macro_file_type_is_directory(stat_file.st_mode), &mode);
         if (F_status_is_error(*status)) {
           fake_print_error_file(data, *status, "f_file_mode_determine", arguments.array[i].string, "change mode of", F_true, F_true);
           break;
index 0d95a1860af4e34cadcef68aa1291496e84e0b88..2ae12881c8800f5a32b29202956980779c305790 100644 (file)
@@ -9,6 +9,4 @@ settings:
 
 main:
 
-  #build
-  touch file b
-  mode =755 b
+  build