10 #include <removefile.h>
12 #include <sys/fcntl.h>
15 #include "test_utils.h"
18 bool verify_st_flags(struct stat
*sb
, uint32_t flags_to_expect
) {
19 // Verify that sb's flags include flags_to_expect.
20 if (((sb
->st_flags
& flags_to_expect
)) != flags_to_expect
) {
21 printf("st_flags (%u) do not include expected flags (%u)\n",
22 sb
->st_flags
, flags_to_expect
);
29 bool verify_fd_contents(int orig_fd
, off_t orig_pos
, int copy_fd
, off_t copy_pos
, size_t length
) {
30 // Read *length* contents of the two fds and make sure they compare as equal.
31 // Don't alter the position of either fd.
32 char orig_contents
[length
], copy_contents
[length
];
35 assert(orig_fd
> 0 && copy_fd
> 0);
36 memset(orig_contents
, 0, length
);
37 memset(copy_contents
, 0, length
);
39 // Read the contents into our temporary buffers, and call memcmp().
41 ssize_t pread_res
= pread(orig_fd
, orig_contents
, length
, 0);
42 assert_with_errno(pread_res
== (off_t
) length
);
43 assert_with_errno(pread(copy_fd
, copy_contents
, length
, copy_pos
) >= 0);
44 equal
= (memcmp(orig_contents
, copy_contents
, length
) == 0);
46 printf("original fd (%lld - %lld) did not match copy (%lld - %lld)\n",
47 orig_pos
, orig_pos
+ length
, copy_pos
, copy_pos
+ length
);
49 // Find the first non-matching byte and print it out.
50 for (size_t bad_off
= 0; bad_off
< length
; bad_off
++) {
51 if (orig_contents
[bad_off
] != copy_contents
[bad_off
]) {
52 printf("first mismatch is at offset %zu, original 0x%llx COPY 0x%llx\n",
53 bad_off
, (unsigned long long)orig_contents
[bad_off
],
54 (unsigned long long)copy_contents
[bad_off
]);
63 bool verify_copy_contents(const char *orig_name
, const char *copy_name
) {
64 // Verify that the copy and the source have identical contents.
65 // Here, we just call out to 'diff' to do the work for us.
66 int rc
= systemx(DIFF_PATH
, orig_name
, copy_name
, SYSTEMX_QUIET
, SYSTEMX_QUIET_STDERR
, NULL
);
68 printf("%s and %s are not identical: diff returned %d\n", orig_name
, copy_name
, rc
);
75 bool verify_copy_sizes(struct stat
*orig_sb
, struct stat
*copy_sb
, copyfile_state_t cpf_state
,
76 bool do_sparse
, off_t src_start
) {
77 off_t cpf_bytes_copied
, blocks_offset
;
80 // If requested, verify that the copy is a sparse file.
82 if (orig_sb
->st_size
- src_start
!= copy_sb
->st_size
) {
83 printf("original size - offset (%lld) != copy size (%lld)\n",
84 orig_sb
->st_size
- src_start
, copy_sb
->st_size
);
88 blocks_offset
= src_start
/ S_BLKSIZE
;
89 if (orig_sb
->st_blocks
- blocks_offset
< copy_sb
->st_blocks
) {
90 printf("original blocks - offset (%lld) < copy blocks (%lld)\n",
91 orig_sb
->st_blocks
- blocks_offset
, copy_sb
->st_blocks
);
96 // Verify that the copyfile_state_t for the copy returns that all bytes were copied.
98 assert_no_err(copyfile_state_get(cpf_state
, COPYFILE_STATE_COPIED
, &cpf_bytes_copied
));
99 if (orig_sb
->st_size
- src_start
!= cpf_bytes_copied
) {
100 printf("original size - start (%lld) != copied bytes (%lld)\n",
101 orig_sb
->st_size
- src_start
, cpf_bytes_copied
);
109 int create_hole_in_fd(int fd
, off_t offset
, off_t length
) {
110 struct fpunchhole punchhole_args
= {
117 return fcntl(fd
, F_PUNCHHOLE
, &punchhole_args
);
121 void create_test_file_name(const char *dir
, const char *postfix
, int id
, char *string_out
) {
122 // Make a name for this new file and put it in out_name, which should be BSIZE_B bytes.
123 assert_with_errno(snprintf(string_out
, BSIZE_B
, "%s/testfile-%d.%s", dir
, id
, postfix
) > 0);
126 void disk_image_create(const char *fstype
, size_t size_in_mb
) {
129 // Set up good default values.
131 fstype
= DEFAULT_FSTYPE
;
133 if (size_in_mb
> MAX_DISK_IMAGE_SIZE_MB
) {
134 size_in_mb
= MAX_DISK_IMAGE_SIZE_MB
;
136 assert_with_errno(snprintf(size
, BSIZE_B
, "%zum", size_in_mb
) >= 3);
138 // Unmount and remove the sparseimage if it already exists.
139 disk_image_destroy(true);
140 if (removefile(DISK_IMAGE_PATH
, NULL
, REMOVEFILE_RECURSIVE
) < 0) {
141 assert_with_errno(errno
== ENOENT
);
144 // Make the disk image.
145 assert_no_err(systemx(HDIUTIL_PATH
, SYSTEMX_QUIET
, "create", "-fs", fstype
,
146 "-size", size
, "-type", "SPARSE", "-volname", "apfs_sparse",
147 DISK_IMAGE_PATH
, NULL
));
149 // Attach the disk image.
150 assert_no_err(systemx(HDIUTIL_PATH
, SYSTEMX_QUIET
, "attach", DISK_IMAGE_PATH
, NULL
));
153 void disk_image_destroy(bool allow_failure
) {
154 // If the caller allows, ignore any failures (also silence stderr).
156 systemx(HDIUTIL_PATH
, "eject", MOUNT_PATH
, SYSTEMX_QUIET
, SYSTEMX_QUIET_STDERR
, NULL
);
158 assert_no_err(systemx(HDIUTIL_PATH
, "eject", MOUNT_PATH
, SYSTEMX_QUIET
, NULL
));