]> git.saurik.com Git - apple/copyfile.git/blob - copyfile_test/identical_test.c
copyfile-173.40.2.tar.gz
[apple/copyfile.git] / copyfile_test / identical_test.c
1 //
2 // identical_test.c
3 // copyfile_test
4 //
5
6 #include <errno.h>
7 #include <stdbool.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <removefile.h>
12 #include <sys/fcntl.h>
13 #include <sys/stat.h>
14 #include <sys/xattr.h>
15
16 #include "../copyfile.h"
17 #include "identical_test.h"
18 #include "test_utils.h"
19
20 #define REGULAR_FILE_NAME "regular_file"
21 #define REGULAR_DIR_NAME "regular_dir"
22 #define DUMMY_XATTR_NAME "dummy_xattr"
23 #define DUMMY_XATTR_DATA "drell"
24 #define TEST_FILE_DATA "krogan"
25
26 static bool verify_src_dst_identical(const char *apfs_test_directory, __unused size_t block_size) {
27 char regular_file[BSIZE_B] = {0}, folder[BSIZE_B] = {0}, file_inside_folder[BSIZE_B] = {0};
28 int regular_file_fd, file_inside_folder_fd;
29 bool success = true;
30
31 // The idea here is to verify that copyfile(file1, file1) returns success
32 // without doing anything.
33 // There are a few wrinkles - COPYFILE_CHECK still needs to work on these files,
34 // and we need to make sure that our identity check works on filesystems without
35 // persistent object identifiers. The first we can easily verify but the second
36 // is not tested here. Nor are negative tests included (there are an infinite
37 // number of those, so we rely on the other tests to verify that behavior).
38
39 // Create path names.
40 assert_with_errno(snprintf(regular_file, BSIZE_B, "%s/" REGULAR_FILE_NAME, apfs_test_directory) > 0);
41 assert_with_errno(snprintf(folder, BSIZE_B, "%s/" REGULAR_DIR_NAME, apfs_test_directory) > 0);
42 assert_with_errno(snprintf(file_inside_folder, BSIZE_B, "%s/" REGULAR_FILE_NAME, folder) > 0);
43
44 // First, verify copyfile(file1, file1),
45 // where file1 is a regular file.
46
47 // Create our regular file.
48 regular_file_fd = open(regular_file, DEFAULT_OPEN_FLAGS, DEFAULT_OPEN_PERM);
49 assert_with_errno(regular_file_fd >= 0);
50
51 // Write some data to the test file so that we can verify it is not empty.
52 assert(write(regular_file_fd, TEST_FILE_DATA, sizeof(TEST_FILE_DATA)) > 0);
53
54 // Verify copyfile(file1, file1) does nothing.
55 assert_no_err(copyfile(regular_file, regular_file, NULL, COPYFILE_ALL));
56 success = success && verify_contents_with_buf(regular_file_fd, 0, (const char *)TEST_FILE_DATA, sizeof(TEST_FILE_DATA));
57
58 // Verify copyfile(file1, file1, COPYFILE_EXCL) returns an error.
59 assert(copyfile(regular_file, regular_file, NULL, COPYFILE_ALL|COPYFILE_EXCL) == -1);
60 assert(errno == EEXIST);
61
62 // Write an dummy xattr to the file to verify COPYFILE_CHECK.
63 assert_no_err(fsetxattr(regular_file_fd, DUMMY_XATTR_NAME, DUMMY_XATTR_DATA, sizeof(DUMMY_XATTR_DATA), 0, XATTR_CREATE));
64
65 // Verify copyfile(file1, file1, ..., COPYFILE_CHECK) works.
66 assert_no_err(copyfile(regular_file, regular_file, NULL, COPYFILE_CHECK) == COPYFILE_XATTR);
67
68 // Now, verify that copyfile(dir1, dir1, COPYFILE_RECURSIVE)
69 // also returns early. Do this by making sure the contents of a file inside the directory
70 // do not change after copyfile(COPYFILE_RECURSIVE).
71
72 // Create our directory.
73 assert_no_err(mkdir(folder, DEFAULT_MKDIR_PERM));
74
75 // Create a regular file inside that directory.
76
77 file_inside_folder_fd = open(file_inside_folder, DEFAULT_OPEN_FLAGS, DEFAULT_OPEN_PERM);
78 assert_with_errno(file_inside_folder_fd >= 0);
79
80 // Write some data to the interior file so that we can verify it is not empty.
81 assert(write(file_inside_folder_fd, (const char *)TEST_FILE_DATA, sizeof(TEST_FILE_DATA)) > 0);
82
83 // Verify copyfile(dir1, dir1, ... COPYFILE_RECURSIVE).
84 assert_no_err(copyfile(folder, folder, NULL, COPYFILE_RECURSIVE));
85 success = success && verify_contents_with_buf(file_inside_folder_fd, 0, TEST_FILE_DATA, sizeof(TEST_FILE_DATA));
86
87 // Post-test cleanup.
88 assert_no_err(close(file_inside_folder_fd));
89 assert_no_err(close(regular_file_fd));
90 (void)removefile(folder, NULL, REMOVEFILE_RECURSIVE);
91 (void)removefile(regular_file, NULL, 0);
92
93 return success;
94 }
95
96 bool do_src_dst_identical_test(const char *apfs_test_directory, __unused size_t block_size) {
97 char test_dir[BSIZE_B] = {0};
98 int test_folder_id;
99 bool success = true;
100
101 printf("START [identical]\n");
102
103 // Get ready for the test.
104 test_folder_id = rand() % DEFAULT_NAME_MOD;
105 create_test_file_name(apfs_test_directory, "identical", test_folder_id, test_dir);
106 assert_no_err(mkdir(test_dir, DEFAULT_MKDIR_PERM));
107
108 success = verify_src_dst_identical(test_dir, block_size);
109
110 if (success) {
111 printf("PASS [identical]\n");
112 } else {
113 printf("FAIL [identical]\n");
114 }
115
116 (void)removefile(test_dir, NULL, REMOVEFILE_RECURSIVE);
117
118 return success ? EXIT_SUCCESS : EXIT_FAILURE;
119 }