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
));