|
|
#include "../../unity/unity.h" |
|
|
|
|
|
#include <sys/stat.h> |
|
|
#include <fcntl.h> |
|
|
#include <unistd.h> |
|
|
#include <stdlib.h> |
|
|
#include <string.h> |
|
|
#include <errno.h> |
|
|
#include <stdio.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
extern bool force_silent; |
|
|
|
|
|
|
|
|
static mode_t get_mode(const char *path) { |
|
|
struct stat st; |
|
|
TEST_ASSERT_EQUAL_INT_MESSAGE(0, stat(path, &st), "stat on temp file failed"); |
|
|
return st.st_mode; |
|
|
} |
|
|
|
|
|
static void make_temp_path(char *buf, size_t buflen) { |
|
|
|
|
|
snprintf(buf, buflen, "/tmp/chmod_mode_changed_%ld_XXXXXX", (long)getpid()); |
|
|
} |
|
|
|
|
|
static void create_temp_file(char *path_buf, size_t buflen) { |
|
|
make_temp_path(path_buf, buflen); |
|
|
int fd = mkstemp(path_buf); |
|
|
TEST_ASSERT_MESSAGE(fd >= 0, "mkstemp failed"); |
|
|
|
|
|
close(fd); |
|
|
} |
|
|
|
|
|
static void remove_temp_file(const char *path) { |
|
|
|
|
|
unlink(path); |
|
|
} |
|
|
|
|
|
void setUp(void) { |
|
|
|
|
|
} |
|
|
|
|
|
void tearDown(void) { |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void test_mode_changed_no_special_no_change(void) { |
|
|
char path[256]; |
|
|
create_temp_file(path, sizeof(path)); |
|
|
|
|
|
mode_t old_mode = get_mode(path); |
|
|
mode_t new_mode = old_mode; |
|
|
|
|
|
bool changed = mode_changed(AT_FDCWD, path, path, old_mode, new_mode); |
|
|
TEST_ASSERT_FALSE(changed); |
|
|
|
|
|
remove_temp_file(path); |
|
|
} |
|
|
|
|
|
|
|
|
void test_mode_changed_no_special_with_change(void) { |
|
|
char path[256]; |
|
|
create_temp_file(path, sizeof(path)); |
|
|
|
|
|
mode_t old_mode = get_mode(path); |
|
|
|
|
|
mode_t new_mode = old_mode ^ S_IXUSR; |
|
|
|
|
|
bool changed = mode_changed(AT_FDCWD, path, path, old_mode, new_mode); |
|
|
TEST_ASSERT_TRUE(changed); |
|
|
|
|
|
remove_temp_file(path); |
|
|
} |
|
|
|
|
|
|
|
|
void test_mode_changed_special_fstatat_failure(void) { |
|
|
|
|
|
bool prev_silent = force_silent; |
|
|
force_silent = true; |
|
|
|
|
|
const char *missing = "/this/path/does/not/exist/___definitely___"; |
|
|
mode_t old_mode = 0; |
|
|
|
|
|
mode_t new_mode = old_mode | S_ISUID; |
|
|
|
|
|
bool changed = mode_changed(AT_FDCWD, missing, missing, old_mode, new_mode); |
|
|
TEST_ASSERT_FALSE(changed); |
|
|
|
|
|
force_silent = prev_silent; |
|
|
} |
|
|
|
|
|
|
|
|
void test_mode_changed_special_no_actual_change(void) { |
|
|
char path[256]; |
|
|
create_temp_file(path, sizeof(path)); |
|
|
|
|
|
mode_t old_mode = get_mode(path); |
|
|
|
|
|
mode_t new_mode = old_mode | S_ISUID; |
|
|
|
|
|
bool changed = mode_changed(AT_FDCWD, path, path, old_mode, new_mode); |
|
|
TEST_ASSERT_FALSE(changed); |
|
|
|
|
|
remove_temp_file(path); |
|
|
} |
|
|
|
|
|
|
|
|
void test_mode_changed_special_actual_change(void) { |
|
|
char path[256]; |
|
|
create_temp_file(path, sizeof(path)); |
|
|
|
|
|
mode_t old_mode = get_mode(path); |
|
|
|
|
|
mode_t changed_perm = (old_mode ^ S_IXUSR) & 07777; |
|
|
int rc = chmod(path, changed_perm); |
|
|
TEST_ASSERT_EQUAL_INT_MESSAGE(0, rc, "chmod to alter file mode failed"); |
|
|
|
|
|
|
|
|
mode_t new_mode_param = old_mode | S_ISUID; |
|
|
|
|
|
bool changed = mode_changed(AT_FDCWD, path, path, old_mode, new_mode_param); |
|
|
TEST_ASSERT_TRUE(changed); |
|
|
|
|
|
|
|
|
chmod(path, old_mode & 07777); |
|
|
remove_temp_file(path); |
|
|
} |
|
|
|
|
|
|
|
|
void test_mode_changed_ignores_file_type_bits(void) { |
|
|
|
|
|
mode_t old_mode = S_IFREG | 0644; |
|
|
mode_t new_mode = S_IFDIR | 0644; |
|
|
|
|
|
bool changed = mode_changed(AT_FDCWD, "unused", "unused", old_mode, new_mode); |
|
|
TEST_ASSERT_FALSE(changed); |
|
|
} |
|
|
|
|
|
int main(void) { |
|
|
UNITY_BEGIN(); |
|
|
|
|
|
RUN_TEST(test_mode_changed_no_special_no_change); |
|
|
RUN_TEST(test_mode_changed_no_special_with_change); |
|
|
RUN_TEST(test_mode_changed_special_fstatat_failure); |
|
|
RUN_TEST(test_mode_changed_special_no_actual_change); |
|
|
RUN_TEST(test_mode_changed_special_actual_change); |
|
|
RUN_TEST(test_mode_changed_ignores_file_type_bits); |
|
|
|
|
|
return UNITY_END(); |
|
|
} |