#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_
}
}
- 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);
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;
}
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;
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;
}
}
}
else if (string[i] == 't') {
+ mode_mask |= f_file_mode_block_special;
+
if (on & 1) {
what = f_file_mode_mask_bit_sticky;
}
}
}
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 {
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
}
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;
}
}
}
* 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.
* '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
#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.
/**
* 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.
* 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.
*
* @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_
/**
*
* 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.
* @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_
/**