#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <removefile.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <sys/xattr.h>
#include "../copyfile.h"
#include "identical_test.h"
#include "test_utils.h"
#define REGULAR_FILE_NAME "regular_file"
#define REGULAR_DIR_NAME "regular_dir"
#define DUMMY_XATTR_NAME "dummy_xattr"
#define DUMMY_XATTR_DATA "drell"
#define TEST_FILE_DATA "krogan"
static bool verify_src_dst_identical(const char *apfs_test_directory, __unused size_t block_size) {
char regular_file[BSIZE_B] = {0}, folder[BSIZE_B] = {0}, file_inside_folder[BSIZE_B] = {0};
int regular_file_fd, file_inside_folder_fd;
bool success = true;
assert_with_errno(snprintf(regular_file, BSIZE_B, "%s/" REGULAR_FILE_NAME, apfs_test_directory) > 0);
assert_with_errno(snprintf(folder, BSIZE_B, "%s/" REGULAR_DIR_NAME, apfs_test_directory) > 0);
assert_with_errno(snprintf(file_inside_folder, BSIZE_B, "%s/" REGULAR_FILE_NAME, folder) > 0);
regular_file_fd = open(regular_file, DEFAULT_OPEN_FLAGS, DEFAULT_OPEN_PERM);
assert_with_errno(regular_file_fd >= 0);
assert(write(regular_file_fd, TEST_FILE_DATA, sizeof(TEST_FILE_DATA)) > 0);
assert_no_err(copyfile(regular_file, regular_file, NULL, COPYFILE_ALL));
success = success && verify_contents_with_buf(regular_file_fd, 0, (const char *)TEST_FILE_DATA, sizeof(TEST_FILE_DATA));
assert(copyfile(regular_file, regular_file, NULL, COPYFILE_ALL|COPYFILE_EXCL) == -1);
assert(errno == EEXIST);
assert_no_err(fsetxattr(regular_file_fd, DUMMY_XATTR_NAME, DUMMY_XATTR_DATA, sizeof(DUMMY_XATTR_DATA), 0, XATTR_CREATE));
assert_no_err(copyfile(regular_file, regular_file, NULL, COPYFILE_CHECK) == COPYFILE_XATTR);
assert_no_err(mkdir(folder, DEFAULT_MKDIR_PERM));
file_inside_folder_fd = open(file_inside_folder, DEFAULT_OPEN_FLAGS, DEFAULT_OPEN_PERM);
assert_with_errno(file_inside_folder_fd >= 0);
assert(write(file_inside_folder_fd, (const char *)TEST_FILE_DATA, sizeof(TEST_FILE_DATA)) > 0);
assert_no_err(copyfile(folder, folder, NULL, COPYFILE_RECURSIVE));
success = success && verify_contents_with_buf(file_inside_folder_fd, 0, TEST_FILE_DATA, sizeof(TEST_FILE_DATA));
assert_no_err(close(file_inside_folder_fd));
assert_no_err(close(regular_file_fd));
(void)removefile(folder, NULL, REMOVEFILE_RECURSIVE);
(void)removefile(regular_file, NULL, 0);
return success;
}
bool do_src_dst_identical_test(const char *apfs_test_directory, __unused size_t block_size) {
char test_dir[BSIZE_B] = {0};
int test_folder_id;
bool success = true;
printf("START [identical]\n");
test_folder_id = rand() % DEFAULT_NAME_MOD;
create_test_file_name(apfs_test_directory, "identical", test_folder_id, test_dir);
assert_no_err(mkdir(test_dir, DEFAULT_MKDIR_PERM));
success = verify_src_dst_identical(test_dir, block_size);
if (success) {
printf("PASS [identical]\n");
} else {
printf("FAIL [identical]\n");
}
(void)removefile(test_dir, NULL, REMOVEFILE_RECURSIVE);
return success ? EXIT_SUCCESS : EXIT_FAILURE;
}