From 34bc06a116e38ef7059e03c1016b02260cd9e33b Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Wed, 12 Aug 2020 22:41:31 -0500 Subject: [PATCH] Progress: continue work on mode changes The functions were renamed and re-organized to be more consistent with the project practices. This changeset focused on getting the number-only changes done within the time allowed. This adds a new function for converting the f_file_mode into a mode_t for the libc chmod compatibility. --- level_0/f_file/c/file.c | 504 +++++++++++++++++++++++------ level_0/f_file/c/file.h | 389 ++++++++++++---------- level_0/f_file/c/private-file.c | 258 +++++++-------- level_0/f_file/c/private-file.h | 288 +++++++++-------- level_1/fl_directory/c/directory.c | 6 +- level_1/fl_directory/c/directory.h | 8 +- level_1/fl_directory/c/private-directory.c | 6 +- level_3/fake/c/private-make.c | 46 +-- level_3/fake/data/build/fakefile | 3 +- 9 files changed, 943 insertions(+), 565 deletions(-) diff --git a/level_0/f_file/c/file.c b/level_0/f_file/c/file.c index 03efa95..4b46545 100644 --- a/level_0/f_file/c/file.c +++ b/level_0/f_file/c/file.c @@ -28,50 +28,6 @@ extern "C" { } #endif // _di_f_file_access_ -#ifndef _di_f_file_change_mode_ - f_return_status f_file_change_mode(const f_string path, const mode_t mode) { - #ifndef _di_level_0_parameter_checking_ - if (path == 0) return F_status_set_error(F_parameter); - #endif // _di_level_0_parameter_checking_ - - return private_f_file_change_mode(path, mode); - } -#endif // _di_f_file_change_mode_ - -#ifndef _di_f_file_change_mode_at_ - f_return_status f_file_change_mode_at(const int at_id, const f_string path, const mode_t mode) { - #ifndef _di_level_0_parameter_checking_ - if (path == 0) return F_status_set_error(F_parameter); - #endif // _di_level_0_parameter_checking_ - - return private_f_file_change_mode_at(at_id, path, mode); - } -#endif // _di_f_file_change_mode_at_ - -#ifndef _di_f_file_change_role_ - f_return_status f_file_change_role(const f_string path, const uid_t uid, const gid_t gid, const bool dereference) { - #ifndef _di_level_0_parameter_checking_ - if (path == 0) return F_status_set_error(F_parameter); - if (uid < 0 && gid < 0) return F_status_set_error(F_parameter); - if (uid < -1 || gid < -1) return F_status_set_error(F_parameter); - #endif // _di_level_0_parameter_checking_ - - return private_f_file_change_role(path, uid, gid, dereference); - } -#endif // _di_f_file_change_role_ - -#ifndef _di_f_file_change_role_at_ - f_return_status f_file_change_role_at(const int at_id, const f_string path, const uid_t uid, const gid_t gid, const int flag) { - #ifndef _di_level_0_parameter_checking_ - if (path == 0) return F_status_set_error(F_parameter); - if (uid < 0 && gid < 0) return F_status_set_error(F_parameter); - if (uid < -1 || gid < -1) return F_status_set_error(F_parameter); - #endif // _di_level_0_parameter_checking_ - - return private_f_file_change_role_at(at_id, path, uid, gid, flag); - } -#endif // _di_f_file_change_role_at_ - #ifndef _di_f_file_clone_ f_return_status f_file_clone(const f_string source, const f_string destination, const bool role, const f_number_unsigned size_block, const bool exclusive) { #ifndef _di_level_0_parameter_checking_ @@ -92,12 +48,12 @@ extern "C" { if (F_status_is_error(status)) return status; if (!exclusive) { - status = private_f_file_change_mode(destination, source_stat.st_mode); + status = private_f_file_mode_set(destination, source_stat.st_mode); if (F_status_is_error(status)) return status; } if (role) { - status = private_f_file_change_role(destination, source_stat.st_uid, source_stat.st_gid, F_false); + status = private_f_file_role_change(destination, source_stat.st_uid, source_stat.st_gid, F_false); if (F_status_is_error(status)) return status; } @@ -112,11 +68,11 @@ extern "C" { return status; } - status = private_f_file_change_mode(destination, source_stat.st_mode); + status = private_f_file_mode_set(destination, source_stat.st_mode); if (F_status_is_error(status)) return status; if (role) { - status = private_f_file_change_role(destination, source_stat.st_uid, source_stat.st_gid, F_false); + status = private_f_file_role_change(destination, source_stat.st_uid, source_stat.st_gid, F_false); if (F_status_is_error(status)) return status; } @@ -158,7 +114,7 @@ extern "C" { if (F_status_is_error(status)) return status; if (!exclusive) { - status = private_f_file_change_mode(destination, (~f_file_type_mask) & mode.regular); + status = private_f_file_mode_set(destination, (~f_file_type_mask) & mode.regular); if (F_status_is_error(status)) return status; } @@ -173,7 +129,7 @@ extern "C" { } } - status = private_f_file_change_mode(destination, (~f_file_type_mask) & mode.directory); + status = private_f_file_mode_set(destination, (~f_file_type_mask) & mode.directory); if (F_status_is_error(status)) return status; return F_none; @@ -208,7 +164,7 @@ extern "C" { } } - status = private_f_file_change_mode(destination, (~f_file_type_mask) & mode.fifo); + status = private_f_file_mode_set(destination, (~f_file_type_mask) & mode.fifo); if (F_status_is_error(status)) return status; return F_none; @@ -222,7 +178,7 @@ extern "C" { } } - status = private_f_file_change_mode(destination, (~f_file_type_mask) & mode.socket); + status = private_f_file_mode_set(destination, (~f_file_type_mask) & mode.socket); if (F_status_is_error(status)) return status; return F_none; @@ -236,7 +192,7 @@ extern "C" { } } - status = private_f_file_change_mode(destination, (~f_file_type_mask) & mode.block); + status = private_f_file_mode_set(destination, (~f_file_type_mask) & mode.block); if (F_status_is_error(status)) return status; return F_none; @@ -568,6 +524,316 @@ 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) { + #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; + + *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) { + *mode = f_file_mode_special_set_user; + } + + if (change & f_file_mode_mask_bit_set_group & f_file_mode_mask_how_add) { + *mode |= f_file_mode_special_set_group; + } + + if (change & f_file_mode_mask_bit_sticky & f_file_mode_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 & 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) { + 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 (*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) { + 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 (*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) { + if (!(*mode & f_file_mode_special_sticky)) { + *mode |= f_file_mode_special_sticky; + } + } + } + } + + change = mode_change & f_file_mode_block_owner; + + if (mode_replace & f_file_mode_replace_owner) { + if (change & f_file_mode_mask_bit_read & f_file_mode_mask_how_add) { + *mode |= f_file_mode_owner_r; + } + + if (change & f_file_mode_mask_bit_write & f_file_mode_mask_how_add) { + *mode |= f_file_mode_owner_w; + } + + if (change & f_file_mode_mask_bit_execute & f_file_mode_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) { + if (directory_is || (mode_file & f_file_mode_owner_x)) { + *mode |= f_file_mode_owner_x; + } + } + } + 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 & 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) { + 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 (*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) { + 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_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) { + 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; + + if (directory_is || (mode_file & f_file_mode_owner_x)) { + if (change & f_file_mode_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) { + if (!(*mode & f_file_mode_owner_x)) { + *mode |= f_file_mode_owner_x; + } + } + } + } + } + } + + change = mode_change & f_file_mode_block_group; + + if (mode_replace & f_file_mode_replace_group) { + if (change & f_file_mode_mask_bit_read & f_file_mode_mask_how_add) { + *mode |= f_file_mode_group_r; + } + + if (change & f_file_mode_mask_bit_write & f_file_mode_mask_how_add) { + *mode |= f_file_mode_group_w; + } + + if (change & f_file_mode_mask_bit_execute & f_file_mode_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) { + if (directory_is || (mode_file & f_file_mode_group_x)) { + *mode |= f_file_mode_group_x; + } + } + } + else { + *mode |= mode_file & f_file_mode_group_rwx; + + if (mode_change & f_file_mode_block_group) { + + if (change & f_file_mode_mask_bit_read & f_file_mode_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) { + 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 (*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) { + 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_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) { + 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; + + if (directory_is || (mode_file & f_file_mode_group_x)) { + if (change & f_file_mode_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) { + if (!(*mode & f_file_mode_group_x)) { + *mode |= f_file_mode_group_x; + } + } + } + } + } + } + + change = mode_change & f_file_mode_block_world; + + if (mode_replace & f_file_mode_replace_world) { + + if (change & f_file_mode_mask_bit_read & f_file_mode_mask_how_add) { + *mode |= f_file_mode_world_r; + } + + if (change & f_file_mode_mask_bit_write & f_file_mode_mask_how_add) { + *mode |= f_file_mode_world_w; + } + + if (change & f_file_mode_mask_bit_execute & f_file_mode_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) { + if (directory_is || (mode_file & f_file_mode_world_x)) { + *mode |= f_file_mode_world_x; + } + } + } + else { + *mode |= mode_file & f_file_mode_world_rwx; + + if (mode_change & f_file_mode_block_world) { + + if (change & f_file_mode_mask_bit_read & f_file_mode_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) { + 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 (*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) { + 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_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) { + 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; + + if (directory_is || (mode_file & f_file_mode_world_x)) { + if (change & f_file_mode_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) { + if (!(*mode & f_file_mode_world_x)) { + *mode |= f_file_mode_world_x; + } + } + } + } + } + } + + 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) { #ifndef _di_level_0_parameter_checking_ @@ -583,12 +849,10 @@ extern "C" { *replace = 0; switch (string[0]) { - case '+': case '-': case '=': switch (string[1]) { - case 'r': case 'w': case 'x': @@ -613,7 +877,6 @@ extern "C" { return F_status_set_error(F_syntax); } - syntax = 1; break; case 'u': @@ -640,12 +903,13 @@ 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, 4 = umask add, 5 = umask replace, 6 = umask subtract. + uint8_t how = 0; // 1 = add, 2 = replace, 3 = subtract. bool active = F_false; - f_file_mode mask = 0; + f_file_mode mask = f_file_mode_block_special; 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++) { switch (string[i]) { @@ -686,7 +950,7 @@ extern "C" { } on = 7; - mask = f_file_mode_block_owner | f_file_mode_block_group | f_file_mode_block_world; + mask = f_file_mode_block_all; break; case '+': @@ -705,11 +969,24 @@ extern "C" { // only the parts designated by the mask should be replaced. *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; + } + else if (mask & f_file_mode_block_group) { + *replace |= f_file_mode_block_special & f_file_mode_block_group; + } + else if (mask & f_file_mode_block_owner) { + *replace |= f_file_mode_block_special & f_file_mode_block_owner; + } } if (!on) { on = 7; - mask = f_file_mode_block_owner | f_file_mode_block_group | f_file_mode_block_world; + mask = f_file_mode_block_all; } for (i++; i < string[i]; i++) { @@ -749,7 +1026,7 @@ extern "C" { active = F_false; on = 0; how = 0; - mask = 0; + mask = f_file_mode_block_special; break; } else if (string[i] == '+' || string[i] == '-' || string[i] == '=') { @@ -769,10 +1046,12 @@ extern "C" { *mode |= what & mask & f_file_mode_mask_how_subtract; } else if (how == 4 || how == 5) { - *mode |= what & mask & f_file_mode_mask_how_umask_add; + *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_umask_subtract; + *mode |= what & mask & f_file_mode_mask_how_subtract; + *replace |= f_file_mode_replace_umask; } } // for @@ -785,13 +1064,13 @@ extern "C" { } // for } else if (syntax == 2) { - // 1 = add, 2 = replace, 3 = subtract, 4 = umask add, 5 = umask replace, 6 = umask subtract. + // 1 = add, 2 = replace, 3 = subtract. uint8_t how = 0; - mode_t classic = 0; - f_string_length i = 0; + *replace = 0; + if (string[0] == '+') { how = 1; i = 1; @@ -800,17 +1079,23 @@ extern "C" { how = 3; i = 1; } - else if (string[0] == '=' || string[0] == '0') { + else if (string[0] == '=') { how = 2; i = 1; + + *replace = f_file_mode_replace_standard; } else { - how = 5; + how = 2; + + *replace = f_file_mode_replace_standard | f_file_mode_replace_directory; } - for (; string[i] == '0'; i++) { - // seek past leading '0's. - } // for + if (string[i] == '0') { + for (; string[i] == '0'; i++) { + // seek past leading '0's. + } // for + } if (string[i]) { f_string_length j = 0; @@ -818,7 +1103,7 @@ extern "C" { for (; string[i + j] && j < 4; j++) { if (j) { - classic <<= 3; + *mode <<= 8; } switch (string[i]) { @@ -834,11 +1119,17 @@ extern "C" { case '6': case '7': // this assumes ASCII/UTF-8. - classic |= string[i] - 0x30; + if (how == 3) { + *mode |= (string[i + j] - 0x30) << 4; + } + else { + *mode |= string[i + j] - 0x30; + } break; default: + // designate that this is invalid. j = 4; break; } @@ -847,28 +1138,13 @@ extern "C" { if (j == 4) { syntax = 0; } - - // @fixme: classic is a different structure than mode masks, properly expand. (maybe just use f_file_mode instead of classic and shift by 6 instead of 3.) - if (syntax) { - if (how == 1) { - *mode = classic & f_file_mode_mask_how_add; - } - else if (how == 2) { - *mode = classic & f_file_mode_mask_how_add; - *replace = f_file_mode_replace_all; - } - else if (how == 3) { - *mode = classic & f_file_mode_mask_how_subtract; - } - else if (how == 5) { - *mode = classic & f_file_mode_mask_how_add; - *replace = f_file_mode_replace_umask_all; + else if (how == 2) { + // if there are only '0's then the setuid/setgid/sticky bits are to be replaced. + if (*mode == 0) { + *replace = f_file_mode_replace_standard; } } } - else { - *replace = f_file_mode_replace_all; - } } if (syntax) { @@ -882,7 +1158,25 @@ extern "C" { } #endif // _di_f_file_mode_from_string_ -// @todo: needs f_file_mode_to_mode_t() to convert f_file_mode to a mode_t (requires f_file_mode, a source mode_t, and a destination mode_t). +#ifndef _di_f_file_mode_set_ + f_return_status f_file_mode_set(const f_string path, const mode_t mode) { + #ifndef _di_level_0_parameter_checking_ + if (path == 0) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_file_mode_set(path, mode); + } +#endif // _di_f_file_mode_set_ + +#ifndef _di_f_file_mode_set_at_ + f_return_status f_file_mode_set_at(const int at_id, const f_string path, const mode_t mode) { + #ifndef _di_level_0_parameter_checking_ + if (path == 0) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_file_mode_set_at(at_id, path, mode); + } +#endif // _di_f_file_mode_set_at_ #ifndef _di_f_file_name_base_ f_return_status f_file_name_base(const f_string path, const f_string_length length, f_string_dynamic *name_base) { @@ -1193,6 +1487,30 @@ extern "C" { } #endif // _di_f_file_remove_at_ +#ifndef _di_f_file_role_change_ + f_return_status f_file_role_change(const f_string path, const uid_t uid, const gid_t gid, const bool dereference) { + #ifndef _di_level_0_parameter_checking_ + if (path == 0) return F_status_set_error(F_parameter); + if (uid < 0 && gid < 0) return F_status_set_error(F_parameter); + if (uid < -1 || gid < -1) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_file_role_change(path, uid, gid, dereference); + } +#endif // _di_f_file_role_change_ + +#ifndef _di_f_file_role_change_at_ + f_return_status f_file_role_change_at(const int at_id, const f_string path, const uid_t uid, const gid_t gid, const int flag) { + #ifndef _di_level_0_parameter_checking_ + if (path == 0) return F_status_set_error(F_parameter); + if (uid < 0 && gid < 0) return F_status_set_error(F_parameter); + if (uid < -1 || gid < -1) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_file_role_change_at(at_id, path, uid, gid, flag); + } +#endif // _di_f_file_role_change_at_ + #ifndef _di_f_file_seek_ f_return_status f_file_seek(const int id, const int whence, const f_string_length offset, f_string_length *seeked) { #ifndef _di_level_0_parameter_checking_ diff --git a/level_0/f_file/c/file.h b/level_0/f_file/c/file.h index c0a8479..37c1fa2 100644 --- a/level_0/f_file/c/file.h +++ b/level_0/f_file/c/file.h @@ -257,20 +257,23 @@ 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_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_how_umask_add 0x0f0f0f0f // 0000 1111 0000 1111 0000 1111 0000 1111 - #define f_file_mode_mask_how_umask_subtract 0x78f0f0f0 // 0111 1000 1111 0000 1111 0000 1111 0000 + #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 @@ -280,15 +283,16 @@ extern "C" { #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_umask_owner 0x8 // 0000 1000 - #define f_file_mode_replace_umask_group 0x10 // 0001 0000 - #define f_file_mode_replace_umask_world 0x20 // 0010 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_all 0x7 // 0000 0111 - #define f_file_mode_replace_umask_all 0x38 // 0011 1000 + #define f_file_mode_replace_all 0x3f // 0011 1111 + #define f_file_mode_replace_other 0x38 // 0011 1000 + #define f_file_mode_replace_standard 0x7 // 0000 0111 // file permission modes. #define f_file_mode_owner_rwx S_IRWXU @@ -321,11 +325,14 @@ 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 sticky-bits and all bits. - #define f_file_mode_special_user S_ISUID - #define f_file_mode_special_group S_ISGID - #define f_file_mode_special_world S_ISVTX - #define f_file_mode_special_all (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO) + // file mode set-uid/set-gid/sticky-bits and all bits. + #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. + #define f_file_mode_all (f_file_mode_special_all | f_file_mode_all_rwx) // special file mode combinations. #define f_file_mode_user_access (f_file_mode_owner_rwx | f_file_mode_group_rwx | f_file_mode_world_x) @@ -360,151 +367,6 @@ extern "C" { #endif // _di_f_file_access_ /** - * Change mode of a given file at the specified path. - * - * This does not set mode based on umask(), be sure to apply umask if so desired. - * (such as: mode & ~mask). - * - * @param path - * The path file name. - * @param mode - * The new mode to use. - * - * @return - * F_none on success. - * F_access_denied (with error bit) on access denied. - * F_access_mode (with error bit) if the current user does not have access to assign the file mode. - * F_directory (with error bit) on invalid directory. - * F_file_found_not (with error bit) if file at path was not found. - * F_input_output (with error bit) on I/O error. - * 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_parameter (with error bit) if a parameter is invalid. - * F_read_only (with error bit) if file is read-only. - * F_failure (with error bit) for any other error. - * - * @see chmod() - */ -#ifndef _di_f_file_change_mode_ - extern f_return_status f_file_change_mode(const f_string path, const mode_t mode); -#endif // _di_f_file_change_mode_ - -/** - * Change mode of a given file at the specified path. - * - * This does not set mode based on umask(), be sure to apply umask if so desired. - * (such as: mode & ~mask). - * - * @param at_id - * The parent directory, as an open directory file descriptor, in which path is relative to. - * @param path - * The path file name. - * @param mode - * The new mode to use. - * - * @return - * F_none on success. - * F_access_denied (with error bit) on access denied. - * F_access_mode (with error bit) if the current user does not have access to assign the file mode. - * F_file_found_not (with error bit) if file at path was not found. - * F_directory (with error bit) on invalid directory. - * F_input_output (with error bit) on I/O error. - * 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_parameter (with error bit) if a parameter is invalid. - * F_read_only (with error bit) if file is read-only. - * F_failure (with error bit) for any other error. - * - * @see fchmodat() - */ -#ifndef _di_f_file_change_mode_at_ - extern f_return_status f_file_change_mode_at(const int at_id, const f_string path, const mode_t mode); -#endif // _di_f_file_change_mode_at_ - -/** - * Change owner and/or group of a given file at the specified path. - * - * At least one of uid or gid must not be -1. - * - * @param path - * The path file name. - * @param uid - * The new user id to use. - * Set to -1 to not change. - * @param gid - * The new group id to use. - * Set to -1 to not change. - * @param dereference - * Set to TRUE to dereferenc symlinks (often is what is desired). - * Set to FALSE to operate on the symlink itself. - * - * @return - * F_none on success. - * F_access_denied (with error bit) on access denied. - * F_access_group (with error bit) if the current user does not have access to assign the specified group. - * F_access_owner (with error bit) if the current user does not have access to assign the specified owner. - * F_buffer (with error bit) if the buffer is invalid. - * F_directory (with error bit) on invalid directory. - * F_file_found_not (with error bit) if file at path was not found. - * F_input_output (with error bit) on I/O error. - * 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_parameter (with error bit) if a parameter is invalid. - * F_read_only (with error bit) if file is read-only. - * F_failure (with error bit) for any other error. - * - * @see chown() - * @see lchown() - */ -#ifndef _di_f_file_change_role_ - extern f_return_status f_file_change_role(const f_string path, const uid_t uid, const gid_t gid, const bool dereference); -#endif // _di_f_file_change_role_ - -/** - * Change owner and/or group of a given file at the specified path. - * - * At least one of uid or gid must not be -1. - * - * @param at_id - * The parent directory, as an open directory file descriptor, in which path is relative to. - * @param path - * The path file name. - * @param uid - * The new user id to use. - * Set to -1 to not change. - * @param gid - * The new group id to use. - * Set to -1 to not change. - * @param flag - * Any valid flag, such as f_file_at_path_empty, f_file_at_automount_no, or f_file_at_symlink_follow_no. - * - * @return - * F_none on success. - * F_access_denied (with error bit) on access denied. - * F_access_group (with error bit) if the current user does not have access to assign the specified group. - * F_access_owner (with error bit) if the current user does not have access to assign the specified owner. - * F_buffer (with error bit) if the buffer is invalid. - * F_directory (with error bit) on invalid directory. - * F_directory_descriptor (with error bit) for bad directory descriptor for at_id. - * F_file_found_not (with error bit) if file at path was not found. - * F_input_output (with error bit) on I/O error. - * 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_parameter (with error bit) if a parameter is invalid. - * F_read_only (with error bit) if file is read-only. - * F_failure (with error bit) for any other error. - * - * @see fchownat() - */ -#ifndef _di_f_file_change_role_at_ - extern f_return_status f_file_change_role_at(const int at_id, const f_string path, const uid_t uid, const gid_t gid, const int flag); -#endif // _di_f_file_change_role_at_ - -/** * Copy a file, as well as its file mode and possibly the owner and group. * * The paths must not contain NULL except for the terminating NULL. @@ -1282,10 +1144,37 @@ extern "C" { #endif // _di_f_file_link_read_at_ /** + * Determine how the mode should be applied based on different file properties and the given mode properties. + * + * @param mode_file + * The mode_t value representing the file's current mode. + * This is expected to be populated from (struct stat).st_mode. + * @param mode_change + * The file mode values to change. + * @param mode_replace + * 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. + * + * @return + * F_none on success. + * F_parameter (with error bit) if a parameter is invalid. + * + * @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); +#endif // _di_f_file_mode_determine_ + +/** * Get the file mode id from a string syntax. * * The string syntax is defined as follows: - * '([ugoa]*[-+=]{0,1}([rwxXst]|[ugo])+([,][ugoa]*[-+=]{0,1}([rwxXst]|[ugo])+)*)|([-+=]0*[0-7]{1,4})'. + * '([ugoa]*[-+=]{0,1}([rwxXst]|[ugo])+([,][ugoa]*[-+=]{0,1}([rwxXst]|[ugo])+)*)|([-+=]{0,1}0*[0-7]{1,4})'. * * Such that: * 'u' = apply to user. @@ -1298,7 +1187,7 @@ extern "C" { * 'r' = read mode. * 'w' = write mode. * 'x' = execute mode. - * 'X' = execute mode, only if already executable. + * 'X' = execute mode, only if already executable directory or is file with owner already has executable bit. * 's' = set-gid/set-uid mode. * 't' = sticky-bit mode. * '0' = no mode. @@ -1320,17 +1209,28 @@ extern "C" { * '7' = sticky-bit, set-uid, and set-gid mode. * * When using digits, each set of 0-7 represents the following: - * [1-7] = apply to other/world. - * [1-7][0-7] = first ([1-7]) to group and second ([0-7]) to other/world. - * [1-7][0-7][0-7] = first ([1-7]) to owner, second ([0-7]) to group, and third ([0-7]) to other/world. - * [1-7][0-7][0-7][0-7] = first ([1-7]) to stick/set-uid/set-gid, second ([0-7]) to owner, third ([0-7]) to owner, and fourth ([0-7]) to other/world. + * [0]+ = set all bits to 0. + * [0-7] = apply to other/world. + * [0-7][0-7] = first ([1-7]) to group and second ([0-7]) to other/world. + * [0-7][0-7][0-7] = first ([1-7]) to owner, second ([0-7]) to group, and third ([0-7]) to other/world. + * [0-7][0-7][0-7][0-7] = first ([1-7]) to stick/set-uid/set-gid, second ([0-7]) to owner, third ([0-7]) to owner, and fourth ([0-7]) to other/world. * - * When there is a leading 0 when using digits, then this mask will ignore the current umask settings. - * Otherwise, the current umask is intended to be respected. + * 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). * - * When '+', '-', or '=' are specified without a leading 'a', 'u', 'g', or 'o', then the mode operations should be performed against the current umask. + * 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. * + * There are problems with the chmod documentation (as of GNU coreutils 8.30): + * 1) "The operator + causes the selected file mode bits to be added to the existing file mode bits of each file; - causes them to be removed; and = causes them to be added and causes unmentioned bits to be re‐moved except that a directory's unmentioned set user and group ID bits are not affected." + * - This means that "chmod =1 some_directory" would not change the setuid/setgid/sticky bits, however, in practice it does change it! + * 2) "For directories chmod preserves set-user-ID and set-group-ID bits unless you explicitly specify other‐wise. You can set or clear the bits with symbolic modes like u+s and g-s. To clear these bits for directories with a numeric mode requires an additional leading zero, or leading = like 00755, or =755" + * - This directly contradicts quote "1" above, which effectively states "=755" would preserve the bits while quote "2" states that it clears the bits. + * - This means that "chmod 1 some_directory" would not change the setuid/setgid/sticky bits, however, in practice it does change it! + * + * 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. + * * @param string * A NULL terminated string designating the desired mode, following the above string syntax. * @param mode @@ -1346,12 +1246,78 @@ extern "C" { * F_syntax (with error bit) if the string fails to follow the syntax rules. * * The parameters how, mode_normal, and mode_executable are all set to 0 on error. + * + * @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); #endif // _di_f_file_mode_from_string_ /** + * Change mode of a given file at the specified path. + * + * This does not set mode based on umask(), be sure to apply umask if so desired. + * (such as: mode & ~mask). + * + * @param path + * The path file name. + * @param mode + * The new mode to use. + * + * @return + * F_none on success. + * F_access_denied (with error bit) on access denied. + * F_access_mode (with error bit) if the current user does not have access to assign the file mode. + * F_directory (with error bit) on invalid directory. + * F_file_found_not (with error bit) if file at path was not found. + * F_input_output (with error bit) on I/O error. + * 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_parameter (with error bit) if a parameter is invalid. + * F_read_only (with error bit) if file is read-only. + * F_failure (with error bit) for any other error. + * + * @see chmod() + */ +#ifndef _di_f_file_mode_set_ + extern f_return_status f_file_mode_set(const f_string path, const mode_t mode); +#endif // _di_f_file_mode_set_ + +/** + * Change mode of a given file at the specified path. + * + * This does not set mode based on umask(), be sure to apply umask if so desired. + * (such as: mode & ~mask). + * + * @param at_id + * The parent directory, as an open directory file descriptor, in which path is relative to. + * @param path + * The path file name. + * @param mode + * The new mode to use. + * + * @return + * F_none on success. + * F_access_denied (with error bit) on access denied. + * F_access_mode (with error bit) if the current user does not have access to assign the file mode. + * F_file_found_not (with error bit) if file at path was not found. + * F_directory (with error bit) on invalid directory. + * F_input_output (with error bit) on I/O error. + * 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_parameter (with error bit) if a parameter is invalid. + * F_read_only (with error bit) if file is read-only. + * F_failure (with error bit) for any other error. + * + * @see fchmodat() + */ +#ifndef _di_f_file_mode_set_at_ + extern f_return_status f_file_mode_set_at(const int at_id, const f_string path, const mode_t mode); +#endif // _di_f_file_mode_set_at_ + +/** * Get the base name of a file path. * * @param path @@ -1610,6 +1576,87 @@ extern "C" { #endif // _di_f_file_remove_at_ /** + * Change owner and/or group of a given file at the specified path. + * + * At least one of uid or gid must not be -1. + * + * @param path + * The path file name. + * @param uid + * The new user id to use. + * Set to -1 to not change. + * @param gid + * The new group id to use. + * Set to -1 to not change. + * @param dereference + * Set to TRUE to dereferenc symlinks (often is what is desired). + * Set to FALSE to operate on the symlink itself. + * + * @return + * F_none on success. + * F_access_denied (with error bit) on access denied. + * F_access_group (with error bit) if the current user does not have access to assign the specified group. + * F_access_owner (with error bit) if the current user does not have access to assign the specified owner. + * F_buffer (with error bit) if the buffer is invalid. + * F_directory (with error bit) on invalid directory. + * F_file_found_not (with error bit) if file at path was not found. + * F_input_output (with error bit) on I/O error. + * 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_parameter (with error bit) if a parameter is invalid. + * F_read_only (with error bit) if file is read-only. + * F_failure (with error bit) for any other error. + * + * @see chown() + * @see lchown() + */ +#ifndef _di_f_file_role_change_ + extern f_return_status f_file_role_change(const f_string path, const uid_t uid, const gid_t gid, const bool dereference); +#endif // _di_f_file_role_change_ + +/** + * Change owner and/or group of a given file at the specified path. + * + * At least one of uid or gid must not be -1. + * + * @param at_id + * The parent directory, as an open directory file descriptor, in which path is relative to. + * @param path + * The path file name. + * @param uid + * The new user id to use. + * Set to -1 to not change. + * @param gid + * The new group id to use. + * Set to -1 to not change. + * @param flag + * Any valid flag, such as f_file_at_path_empty, f_file_at_automount_no, or f_file_at_symlink_follow_no. + * + * @return + * F_none on success. + * F_access_denied (with error bit) on access denied. + * F_access_group (with error bit) if the current user does not have access to assign the specified group. + * F_access_owner (with error bit) if the current user does not have access to assign the specified owner. + * F_buffer (with error bit) if the buffer is invalid. + * F_directory (with error bit) on invalid directory. + * F_directory_descriptor (with error bit) for bad directory descriptor for at_id. + * F_file_found_not (with error bit) if file at path was not found. + * F_input_output (with error bit) on I/O error. + * 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_parameter (with error bit) if a parameter is invalid. + * F_read_only (with error bit) if file is read-only. + * F_failure (with error bit) for any other error. + * + * @see fchownat() + */ +#ifndef _di_f_file_role_change_at_ + extern f_return_status f_file_role_change_at(const int at_id, const f_string path, const uid_t uid, const gid_t gid, const int flag); +#endif // _di_f_file_role_change_at_ + +/** * Given an open file descriptor, seek to a given location. * * @param id diff --git a/level_0/f_file/c/private-file.c b/level_0/f_file/c/private-file.c index b592f3f..6b15ee6 100644 --- a/level_0/f_file/c/private-file.c +++ b/level_0/f_file/c/private-file.c @@ -5,135 +5,6 @@ extern "C" { #endif -#if !defined(_di_f_file_change_mode_) || !defined(_di_f_file_copy_) - f_return_status private_f_file_change_mode(const f_string path, const mode_t mode) { - - if (chmod(path, mode) < 0) { - if (errno == EACCES) return F_status_set_error(F_access_denied); - if (errno == ENAMETOOLONG) return F_status_set_error(F_name); - if (errno == EFAULT) return F_status_set_error(F_buffer); - if (errno == ELOOP) return F_status_set_error(F_loop); - if (errno == ENOENT) return F_status_set_error(F_file_found_not); - if (errno == ENOMEM) return F_status_set_error(F_memory_out); - if (errno == ENOTDIR) return F_status_set_error(F_directory); - if (errno == EPERM) return F_status_set_error(F_access_mode); - if (errno == EROFS) return F_status_set_error(F_read_only); - if (errno == EIO) return F_status_set_error(F_input_output); - - return F_status_set_error(F_failure); - } - - return F_none; - } -#endif // !defined(_di_f_file_change_mode_) || !defined(_di_f_file_copy_) - -#if !defined(_di_f_file_change_mode_at_) || !defined(_di_f_file_copy_at_) - f_return_status private_f_file_change_mode_at(const int at_id, const f_string path, const mode_t mode) { - - if (fchmodat(at_id, path, mode, 0) < 0) { - if (errno == EACCES) return F_status_set_error(F_access_denied); - if (errno == ENAMETOOLONG) return F_status_set_error(F_name); - if (errno == EFAULT) return F_status_set_error(F_buffer); - if (errno == ELOOP) return F_status_set_error(F_loop); - if (errno == ENOENT) return F_status_set_error(F_file_found_not); - if (errno == ENOMEM) return F_status_set_error(F_memory_out); - if (errno == ENOTDIR) return F_status_set_error(F_directory); - if (errno == EBADF) return F_status_set_error(F_directory_descriptor); - if (errno == EPERM) return F_status_set_error(F_access_mode); - if (errno == EROFS) return F_status_set_error(F_read_only); - if (errno == EIO) return F_status_set_error(F_input_output); - - return F_status_set_error(F_failure); - } - - return F_none; - } -#endif // !defined(_di_f_file_change_mode_at_) || !defined(_di_f_file_copy_at_) - -#if !defined(_di_f_file_change_role_) || !defined(_di_f_file_copy_) - f_return_status private_f_file_change_role(const f_string path, const uid_t uid, const gid_t gid, const bool dereference) { - int result = 0; - - if (dereference) { - if (uid != -1) { - result = chown(path, uid, -1); - - if (result < 0 && errno == EPERM) return F_status_set_error(F_access_owner); - } - - if (result == 0 && gid != -1) { - result = chown(path, -1, gid); - - if (result < 0 && errno == EPERM) return F_status_set_error(F_access_group); - } - } - else { - if (uid != -1) { - result = lchown(path, uid, -1); - - if (result < 0 && errno == EPERM) return F_status_set_error(F_access_owner); - } - - if (gid != -1) { - result = lchown(path, -1, gid); - - if (result < 0 && errno == EPERM) return F_status_set_error(F_access_group); - } - } - - if (result < 0) { - if (errno == EACCES) return F_status_set_error(F_access_denied); - if (errno == ENAMETOOLONG) return F_status_set_error(F_name); - if (errno == EFAULT) return F_status_set_error(F_buffer); - if (errno == ELOOP) return F_status_set_error(F_loop); - if (errno == ENOENT) return F_status_set_error(F_file_found_not); - if (errno == ENOMEM) return F_status_set_error(F_memory_out); - if (errno == ENOTDIR) return F_status_set_error(F_directory); - if (errno == EROFS) return F_status_set_error(F_read_only); - if (errno == EIO) return F_status_set_error(F_input_output); - - return F_status_set_error(F_failure); - } - - return F_none; - } -#endif // !defined(_di_f_file_change_role_) || !defined(_di_f_file_copy_) - -#if !defined(_di_f_file_change_role_at_) || !defined(_di_f_file_copy_at_) - f_return_status private_f_file_change_role_at(const int at_id, const f_string path, const uid_t uid, const gid_t gid, const int flag) { - int result = 0; - - if (uid != -1) { - result = fchownat(at_id, path, uid, -1, flag); - - if (result < 0 && errno == EPERM) return F_status_set_error(F_access_owner); - } - - if (gid != -1) { - result = fchownat(at_id, path, -1, gid, flag); - - if (result < 0 && errno == EPERM) return F_status_set_error(F_access_group); - } - - if (result < 0) { - if (errno == EACCES) return F_status_set_error(F_access_denied); - if (errno == ENAMETOOLONG) return F_status_set_error(F_name); - if (errno == EFAULT) return F_status_set_error(F_buffer); - if (errno == ELOOP) return F_status_set_error(F_loop); - if (errno == ENOENT) return F_status_set_error(F_file_found_not); - if (errno == ENOMEM) return F_status_set_error(F_memory_out); - if (errno == ENOTDIR) return F_status_set_error(F_directory); - if (errno == EBADF) return F_status_set_error(F_directory_descriptor); - if (errno == EROFS) return F_status_set_error(F_read_only); - if (errno == EIO) return F_status_set_error(F_input_output); - - return F_status_set_error(F_failure); - } - - return F_none; - } -#endif // !defined(_di_f_file_change_role_at_) || !defined(_di_f_file_copy_at_) - #if !defined(_di_f_file_close_) || !defined(_di_f_file_copy_) f_return_status private_f_file_close(int *id) { if (F_status_is_error(private_f_file_flush(*id))) return F_status_set_error(F_file_synchronize); @@ -575,6 +446,51 @@ extern "C" { } #endif // !defined(_di_f_file_link_read_at_) || !defined(_di_f_file_copy_at_) +#if !defined(_di_f_file_mode_set_) || !defined(_di_f_file_copy_) + f_return_status private_f_file_mode_set(const f_string path, const mode_t mode) { + + if (chmod(path, mode) < 0) { + if (errno == EACCES) return F_status_set_error(F_access_denied); + if (errno == ENAMETOOLONG) return F_status_set_error(F_name); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == ELOOP) return F_status_set_error(F_loop); + if (errno == ENOENT) return F_status_set_error(F_file_found_not); + if (errno == ENOMEM) return F_status_set_error(F_memory_out); + if (errno == ENOTDIR) return F_status_set_error(F_directory); + if (errno == EPERM) return F_status_set_error(F_access_mode); + if (errno == EROFS) return F_status_set_error(F_read_only); + if (errno == EIO) return F_status_set_error(F_input_output); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // !defined(_di_f_file_mode_set_) || !defined(_di_f_file_copy_) + +#if !defined(_di_f_file_mode_set_at_) || !defined(_di_f_file_copy_at_) + f_return_status private_f_file_mode_set_at(const int at_id, const f_string path, const mode_t mode) { + + if (fchmodat(at_id, path, mode, 0) < 0) { + if (errno == EACCES) return F_status_set_error(F_access_denied); + if (errno == ENAMETOOLONG) return F_status_set_error(F_name); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == ELOOP) return F_status_set_error(F_loop); + if (errno == ENOENT) return F_status_set_error(F_file_found_not); + if (errno == ENOMEM) return F_status_set_error(F_memory_out); + if (errno == ENOTDIR) return F_status_set_error(F_directory); + if (errno == EBADF) return F_status_set_error(F_directory_descriptor); + if (errno == EPERM) return F_status_set_error(F_access_mode); + if (errno == EROFS) return F_status_set_error(F_read_only); + if (errno == EIO) return F_status_set_error(F_input_output); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // !defined(_di_f_file_mode_set_at_) || !defined(_di_f_file_copy_at_) + #if !defined(_di_f_file_open_) || !defined(_di_f_file_copy_) f_return_status private_f_file_open(const f_string path, const mode_t mode, f_file *file) { if (mode == 0) { @@ -650,6 +566,90 @@ extern "C" { } #endif // !defined(_di_f_file_open_at_) || !defined(_di_f_file_copy_at_) +#if !defined(_di_f_file_role_change_) || !defined(_di_f_file_copy_) + f_return_status private_f_file_role_change(const f_string path, const uid_t uid, const gid_t gid, const bool dereference) { + int result = 0; + + if (dereference) { + if (uid != -1) { + result = chown(path, uid, -1); + + if (result < 0 && errno == EPERM) return F_status_set_error(F_access_owner); + } + + if (result == 0 && gid != -1) { + result = chown(path, -1, gid); + + if (result < 0 && errno == EPERM) return F_status_set_error(F_access_group); + } + } + else { + if (uid != -1) { + result = lchown(path, uid, -1); + + if (result < 0 && errno == EPERM) return F_status_set_error(F_access_owner); + } + + if (gid != -1) { + result = lchown(path, -1, gid); + + if (result < 0 && errno == EPERM) return F_status_set_error(F_access_group); + } + } + + if (result < 0) { + if (errno == EACCES) return F_status_set_error(F_access_denied); + if (errno == ENAMETOOLONG) return F_status_set_error(F_name); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == ELOOP) return F_status_set_error(F_loop); + if (errno == ENOENT) return F_status_set_error(F_file_found_not); + if (errno == ENOMEM) return F_status_set_error(F_memory_out); + if (errno == ENOTDIR) return F_status_set_error(F_directory); + if (errno == EROFS) return F_status_set_error(F_read_only); + if (errno == EIO) return F_status_set_error(F_input_output); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // !defined(_di_f_file_role_change_) || !defined(_di_f_file_copy_) + +#if !defined(_di_f_file_role_change_at_) || !defined(_di_f_file_copy_at_) + f_return_status private_f_file_role_change_at(const int at_id, const f_string path, const uid_t uid, const gid_t gid, const int flag) { + int result = 0; + + if (uid != -1) { + result = fchownat(at_id, path, uid, -1, flag); + + if (result < 0 && errno == EPERM) return F_status_set_error(F_access_owner); + } + + if (gid != -1) { + result = fchownat(at_id, path, -1, gid, flag); + + if (result < 0 && errno == EPERM) return F_status_set_error(F_access_group); + } + + if (result < 0) { + if (errno == EACCES) return F_status_set_error(F_access_denied); + if (errno == ENAMETOOLONG) return F_status_set_error(F_name); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == ELOOP) return F_status_set_error(F_loop); + if (errno == ENOENT) return F_status_set_error(F_file_found_not); + if (errno == ENOMEM) return F_status_set_error(F_memory_out); + if (errno == ENOTDIR) return F_status_set_error(F_directory); + if (errno == EBADF) return F_status_set_error(F_directory_descriptor); + if (errno == EROFS) return F_status_set_error(F_read_only); + if (errno == EIO) return F_status_set_error(F_input_output); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // !defined(_di_f_file_role_change_at_) || !defined(_di_f_file_copy_at_) + #if !defined(_di_f_file_stat_) || !defined(_di_f_file_copy_) f_return_status private_f_file_stat(const f_string path, const bool dereference, struct stat *file_stat) { diff --git a/level_0/f_file/c/private-file.h b/level_0/f_file/c/private-file.h index 7d045a5..0ebfba2 100644 --- a/level_0/f_file/c/private-file.h +++ b/level_0/f_file/c/private-file.h @@ -16,146 +16,6 @@ extern "C" { #endif /** - * Private implementation of f_file_change_mode(). - * - * Intended to be shared to each of the different implementation variations. - * - * @param path - * The path file name. - * @param mode - * The new mode to use. - * - * @return - * F_none on success. - * F_access_denied (with error bit) on access denied. - * F_access_mode (with error bit) if the current user does not have access to assign the file mode. - * F_directory (with error bit) on invalid directory. - * F_file_found_not (with error bit) if file at path was not found. - * F_input_output (with error bit) on I/O error. - * 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_parameter (with error bit) if a parameter is invalid. - * F_read_only (with error bit) if file is read-only. - * F_failure (with error bit) for any other error. - * - * @see f_file_change_mode() - * @see f_file_copy() - */ -#if !defined(_di_f_file_change_mode_) || !defined(_di_f_file_copy_) - extern f_return_status private_f_file_change_mode(const f_string path, const mode_t mode) f_gcc_attribute_visibility_internal; -#endif // !defined(_di_f_file_change_mode_) || !defined(_di_f_file_copy_) - -/** - * Private implementation of f_file_change_mode_at(). - * - * Intended to be shared to each of the different implementation variations. - * - * @param at_id - * The parent directory, as an open directory file descriptor, in which path is relative to. - * @param path - * The path file name. - * @param mode - * The new mode to use. - * - * @return - * F_none on success. - * F_access_denied (with error bit) on access denied. - * F_access_mode (with error bit) if the current user does not have access to assign the file mode. - * F_file_found_not (with error bit) if file at path was not found. - * F_directory (with error bit) on invalid directory. - * F_input_output (with error bit) on I/O error. - * 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_parameter (with error bit) if a parameter is invalid. - * F_read_only (with error bit) if file is read-only. - * F_failure (with error bit) for any other error. - * - * @see f_file_change_mode_at() - */ -#if !defined(_di_f_file_change_mode_at_) - extern f_return_status private_f_file_change_mode_at(const int at_id, const f_string path, const mode_t mode) f_gcc_attribute_visibility_internal; -#endif // !defined(_di_f_file_change_mode_at_) - -/** - * Private implementation of f_file_change_role(). - * - * Intended to be shared to each of the different implementation variations. - * - * @param path - * The path file name. - * @param uid - * The new user id to use. - * @param gid - * The new group id to use. - * @param dereference - * Set to TRUE to dereference symlinks (often is what is desired). - * Set to FALSE to operate on the symlink itself. - * - * @return - * F_none on success. - * F_access_denied (with error bit) on access denied. - * F_access_group (with error bit) if the current user does not have access to assign the specified group. - * F_access_owner (with error bit) if the current user does not have access to assign the specified owner. - * F_buffer (with error bit) if the buffer is invalid. - * F_directory (with error bit) on invalid directory. - * F_file_found_not (with error bit) if file at path was not found. - * F_input_output (with error bit) on I/O error. - * 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_parameter (with error bit) if a parameter is invalid. - * F_read_only (with error bit) if file is read-only. - * F_failure (with error bit) for any other error. - * - * @see f_file_change_role() - * @see f_file_copy() - */ -#if !defined(_di_f_file_change_role_) || !defined(_di_f_file_copy_) - extern f_return_status private_f_file_change_role(const f_string path, const uid_t uid, const gid_t gid, const bool dereference) f_gcc_attribute_visibility_internal; -#endif // !defined(_di_f_file_change_role_) || !defined(_di_f_file_copy_) - -/** - * Private implementation of f_file_change_role_at(). - * - * Intended to be shared to each of the different implementation variations. - * - * @param at_id - * The parent directory, as an open directory file descriptor, in which path is relative to. - * @param path - * The path file name. - * @param uid - * The new user id to use. - * @param gid - * The new group id to use. - * @param flag - * Any valid flag, such as f_file_at_path_empty, f_file_at_automount_no, or f_file_at_symlink_follow_no. - * - * @return - * F_none on success. - * F_access_denied (with error bit) on access denied. - * F_access_group (with error bit) if the current user does not have access to assign the specified group. - * F_access_owner (with error bit) if the current user does not have access to assign the specified owner. - * F_buffer (with error bit) if the buffer is invalid. - * F_directory (with error bit) on invalid directory. - * F_directory_descriptor (with error bit) for bad directory descriptor for at_id. - * F_file_found_not (with error bit) if file at path was not found. - * F_input_output (with error bit) on I/O error. - * 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_parameter (with error bit) if a parameter is invalid. - * F_read_only (with error bit) if file is read-only. - * F_failure (with error bit) for any other error. - * - * @see f_file_change_role_at() - */ -#if !defined(_di_f_file_change_role_at_) - extern f_return_status private_f_file_change_role_at(const int at_id, const f_string path, const uid_t uid, const gid_t gid, const int flag) f_gcc_attribute_visibility_internal; -#endif // !defined(_di_f_file_change_role_at_) - -/** * Private implementation of f_file_close(). * * Intended to be shared to each of the different implementation variations. @@ -389,7 +249,9 @@ extern "C" { #endif // !defined(_di_f_file_copy_at_) /** - * Create a fifo based on the given path and file mode. + * Private implementation of private_f_file_create_fifo(). + * + * Intended to be shared to each of the different implementation variations. * * @param path * The path file name. @@ -418,7 +280,9 @@ extern "C" { #endif // !defined(_di_f_file_create_fifo_) || !defined(_di_f_file_copy_) /** - * Create a fifo based on the given path and file mode. + * Private implementation of private_f_file_create_fifo_at(). + * + * Intended to be shared to each of the different implementation variations. * * @param at_id * The parent directory, as an open directory file descriptor, in which path is relative to. @@ -698,6 +562,69 @@ extern "C" { #endif // !defined(_di_f_file_link_read_at_) || !defined(_di_f_file_copy_at_) /** + * Private implementation of f_file_mode_set(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param path + * The path file name. + * @param mode + * The new mode to use. + * + * @return + * F_none on success. + * F_access_denied (with error bit) on access denied. + * F_access_mode (with error bit) if the current user does not have access to assign the file mode. + * F_directory (with error bit) on invalid directory. + * F_file_found_not (with error bit) if file at path was not found. + * F_input_output (with error bit) on I/O error. + * 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_parameter (with error bit) if a parameter is invalid. + * F_read_only (with error bit) if file is read-only. + * F_failure (with error bit) for any other error. + * + * @see f_file_mode_set() + * @see f_file_copy() + */ +#if !defined(_di_f_file_mode_set_) || !defined(_di_f_file_copy_) + extern f_return_status private_f_file_mode_set(const f_string path, const mode_t mode) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_file_mode_set_) || !defined(_di_f_file_copy_) + +/** + * Private implementation of f_file_mode_set_at(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param at_id + * The parent directory, as an open directory file descriptor, in which path is relative to. + * @param path + * The path file name. + * @param mode + * The new mode to use. + * + * @return + * F_none on success. + * F_access_denied (with error bit) on access denied. + * F_access_mode (with error bit) if the current user does not have access to assign the file mode. + * F_file_found_not (with error bit) if file at path was not found. + * F_directory (with error bit) on invalid directory. + * F_input_output (with error bit) on I/O error. + * 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_parameter (with error bit) if a parameter is invalid. + * F_read_only (with error bit) if file is read-only. + * F_failure (with error bit) for any other error. + * + * @see f_file_mode_set_at() + */ +#if !defined(_di_f_file_mode_set_at_) + extern f_return_status private_f_file_mode_set_at(const int at_id, const f_string path, const mode_t mode) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_file_mode_set_at_) + +/** * Private implementation of f_file_open(). * * Intended to be shared to each of the different implementation variations. @@ -755,6 +682,83 @@ extern "C" { #endif // !defined(_di_f_file_open_at_) /** + * Private implementation of f_file_role_change(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param path + * The path file name. + * @param uid + * The new user id to use. + * @param gid + * The new group id to use. + * @param dereference + * Set to TRUE to dereference symlinks (often is what is desired). + * Set to FALSE to operate on the symlink itself. + * + * @return + * F_none on success. + * F_access_denied (with error bit) on access denied. + * F_access_group (with error bit) if the current user does not have access to assign the specified group. + * F_access_owner (with error bit) if the current user does not have access to assign the specified owner. + * F_buffer (with error bit) if the buffer is invalid. + * F_directory (with error bit) on invalid directory. + * F_file_found_not (with error bit) if file at path was not found. + * F_input_output (with error bit) on I/O error. + * 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_parameter (with error bit) if a parameter is invalid. + * F_read_only (with error bit) if file is read-only. + * F_failure (with error bit) for any other error. + * + * @see f_file_role_change() + * @see f_file_copy() + */ +#if !defined(_di_f_file_role_change_) || !defined(_di_f_file_copy_) + extern f_return_status private_f_file_role_change(const f_string path, const uid_t uid, const gid_t gid, const bool dereference) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_file_role_change_) || !defined(_di_f_file_copy_) + +/** + * Private implementation of f_file_role_change_at(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param at_id + * The parent directory, as an open directory file descriptor, in which path is relative to. + * @param path + * The path file name. + * @param uid + * The new user id to use. + * @param gid + * The new group id to use. + * @param flag + * Any valid flag, such as f_file_at_path_empty, f_file_at_automount_no, or f_file_at_symlink_follow_no. + * + * @return + * F_none on success. + * F_access_denied (with error bit) on access denied. + * F_access_group (with error bit) if the current user does not have access to assign the specified group. + * F_access_owner (with error bit) if the current user does not have access to assign the specified owner. + * F_buffer (with error bit) if the buffer is invalid. + * F_directory (with error bit) on invalid directory. + * F_directory_descriptor (with error bit) for bad directory descriptor for at_id. + * F_file_found_not (with error bit) if file at path was not found. + * F_input_output (with error bit) on I/O error. + * 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_parameter (with error bit) if a parameter is invalid. + * F_read_only (with error bit) if file is read-only. + * F_failure (with error bit) for any other error. + * + * @see f_file_role_change_at() + */ +#if !defined(_di_f_file_role_change_at_) + extern f_return_status private_f_file_role_change_at(const int at_id, const f_string path, const uid_t uid, const gid_t gid, const int flag) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_file_role_change_at_) + +/** * Private implementation of f_file_stat(). * * Intended to be shared to each of the different implementation variations. diff --git a/level_1/fl_directory/c/directory.c b/level_1/fl_directory/c/directory.c index e268c86..0313d5a 100644 --- a/level_1/fl_directory/c/directory.c +++ b/level_1/fl_directory/c/directory.c @@ -32,7 +32,7 @@ extern "C" { return F_status_set_error(F_directory_found); } - status = f_file_change_mode(destination, source_stat.st_mode); + status = f_file_mode_set(destination, source_stat.st_mode); if (F_status_is_error(status)) return status; } else { @@ -41,7 +41,7 @@ extern "C" { } if (role) { - status = f_file_change_role(destination, source_stat.st_uid, source_stat.st_gid, F_true); + status = f_file_role_change(destination, source_stat.st_uid, source_stat.st_gid, F_true); if (F_status_is_error(status)) return status; } @@ -137,7 +137,7 @@ extern "C" { return F_status_set_error(F_directory_found); } - status = f_file_change_mode(destination, mode.directory); + status = f_file_mode_set(destination, mode.directory); if (F_status_is_error(status)) return status; } else { diff --git a/level_1/fl_directory/c/directory.h b/level_1/fl_directory/c/directory.h index c584a46..71d0176 100644 --- a/level_1/fl_directory/c/directory.h +++ b/level_1/fl_directory/c/directory.h @@ -97,8 +97,8 @@ extern "C" { * * Errors from (with error bit): f_directory_create(). * Errors from (with error bit): f_directory_exists(). - * Errors from (with error bit): f_file_change_mode(). - * Errors from (with error bit): f_file_change_role(). + * Errors from (with error bit): f_file_mode_set(). + * Errors from (with error bit): f_file_role_change(). * Errors from (with error bit): f_file_stat(). * * @see f_file_clone() @@ -219,8 +219,8 @@ extern "C" { * * Errors from (with error bit): f_directory_create(). * Errors from (with error bit): f_directory_exists(). - * Errors from (with error bit): f_file_change_mode(). - * Errors from (with error bit): f_file_change_role(). + * Errors from (with error bit): f_file_mode_set(). + * Errors from (with error bit): f_file_role_change(). * Errors from (with error bit): f_file_stat(). * * @see f_file_copy() diff --git a/level_1/fl_directory/c/private-directory.c b/level_1/fl_directory/c/private-directory.c index d42bae9..77c5124 100644 --- a/level_1/fl_directory/c/private-directory.c +++ b/level_1/fl_directory/c/private-directory.c @@ -112,7 +112,7 @@ extern "C" { break; } - status = f_file_change_mode(destination_sub.string, source_stat.st_mode); + status = f_file_mode_set(destination_sub.string, source_stat.st_mode); if (F_status_is_error(status)) break; } else { @@ -121,7 +121,7 @@ extern "C" { } if (role) { - status = f_file_change_role(destination_sub.string, source_stat.st_uid, source_stat.st_gid, F_true); + status = f_file_role_change(destination_sub.string, source_stat.st_uid, source_stat.st_gid, F_true); if (F_status_is_error(status)) break; } } @@ -328,7 +328,7 @@ extern "C" { break; } - status = f_file_change_mode(destination_sub.string, mode.directory); + status = f_file_mode_set(destination_sub.string, mode.directory); if (F_status_is_error(status)) break; } else { diff --git a/level_3/fake/c/private-make.c b/level_3/fake/c/private-make.c index 598fe1c..1a53e0f 100644 --- a/level_3/fake/c/private-make.c +++ b/level_3/fake/c/private-make.c @@ -1479,9 +1479,9 @@ extern "C" { if (F_status_is_error(*status)) return; for (f_array_length i = 1; i < arguments.used; i++) { - *status = f_file_change_role(arguments.array[i].string, -1, id, F_false); + *status = f_file_role_change(arguments.array[i].string, -1, id, F_false); if (F_status_is_error(*status)) { - fake_print_error_file(data, *status, "f_file_change_role", arguments.array[i].string, "change group of", F_true, F_true); + fake_print_error_file(data, *status, "f_file_role_change", arguments.array[i].string, "change group of", F_true, F_true); } } // for @@ -1496,9 +1496,9 @@ extern "C" { for (f_array_length i = 1; i < arguments.used; i++) { // @todo: recursive. - *status = f_file_change_role(arguments.array[i].string, -1, id, F_false); + *status = f_file_role_change(arguments.array[i].string, -1, id, F_false); if (F_status_is_error(*status)) { - fake_print_error_file(data, *status, "f_file_change_role", arguments.array[i].string, "change group of", F_true, F_true); + fake_print_error_file(data, *status, "f_file_role_change", arguments.array[i].string, "change group of", F_true, F_true); } } // for @@ -1527,18 +1527,29 @@ extern "C" { mode_t mode = 0; + struct stat stat_file; + for (f_array_length i = 1; i < arguments.used; i++) { - // @todo: get the file mode. + mode = 0; + memset(&stat_file, 0, sizeof(struct stat)); - if (replace) { - // @todo when replace is specified, then determine what is to be replaced when converting to mode_t. + *status = f_file_stat(arguments.array[i].string, F_true, &stat_file); + if (F_status_is_error(*status)) { + fake_print_error_file(data, *status, "f_file_stat", arguments.array[i].string, "change mode of", F_true, F_true); + break; } - // @todo: check the zeroing logic, read each file's mode, and updat accordingly. - //*status = f_file_change_mode(arguments.array[i].string, mode); - //if (F_status_is_error(*status)) { - // fake_print_error_file(data, *status, "f_file_change_mode", arguments.array[i].string, "change mode of", F_true, F_true); - //} + *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); + 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; + } + + *status = f_file_mode_set(arguments.array[i].string, mode); + if (F_status_is_error(*status)) { + fake_print_error_file(data, *status, "f_file_mode_set", arguments.array[i].string, "change mode of", F_true, F_true); + break; + } } // for return; @@ -1561,9 +1572,9 @@ extern "C" { if (F_status_is_error(*status)) return; for (f_array_length i = 1; i < arguments.used; i++) { - *status = f_file_change_role(arguments.array[i].string, id, -1, F_false); + *status = f_file_role_change(arguments.array[i].string, id, -1, F_false); if (F_status_is_error(*status)) { - fake_print_error_file(data, *status, "f_file_change_role", arguments.array[i].string, "change owner of", F_true, F_true); + fake_print_error_file(data, *status, "f_file_role_change", arguments.array[i].string, "change owner of", F_true, F_true); } } // for @@ -1578,9 +1589,9 @@ extern "C" { for (f_array_length i = 1; i < arguments.used; i++) { // @todo recursive. - *status = f_file_change_role(arguments.array[i].string, id, -1, F_false); + *status = f_file_role_change(arguments.array[i].string, id, -1, F_false); if (F_status_is_error(*status)) { - fake_print_error_file(data, *status, "f_file_change_role", arguments.array[i].string, "change owner of", F_true, F_true); + fake_print_error_file(data, *status, "f_file_role_change", arguments.array[i].string, "change owner of", F_true, F_true); } } // for @@ -2124,15 +2135,12 @@ extern "C" { } } else if (operation == fake_make_operation_type_group || operation == fake_make_operation_type_groups || operation == fake_make_operation_type_mode || operation == fake_make_operation_type_modes || operation == fake_make_operation_type_owner || operation == fake_make_operation_type_owners) { - printf("DEBUG: arguments.used = %llu\n"); if (arguments.used > 1) { f_status status_file = F_none; for (f_array_length i = 1; i < arguments.used; i++) { status_file = f_file_is(arguments.array[i].string, f_file_type_regular); - printf("DEBUG: at %llu, looking at '%s', %llu\n", i, arguments.array[i].string, F_status_set_fine(status_file)); - if (status_file == F_file_found_not) { printf("%c", f_string_eol[0]); fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: Failed to find file '"); diff --git a/level_3/fake/data/build/fakefile b/level_3/fake/data/build/fakefile index 1128fed..0d95a18 100644 --- a/level_3/fake/data/build/fakefile +++ b/level_3/fake/data/build/fakefile @@ -10,4 +10,5 @@ settings: main: #build - owner a b + touch file b + mode =755 b -- 1.8.3.1