Last active
April 26, 2023 15:56
-
-
Save Dr-Emann/3d0f272d08c68a889fa368597a10cea7 to your computer and use it in GitHub Desktop.
Testing Apple File System Compression for RJVB/afsctool#62
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <assert.h> | |
#include <errno.h> | |
#include <fcntl.h> | |
#include <stdbool.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <sys/mman.h> | |
#include <sys/stat.h> | |
#include <sys/xattr.h> | |
#include <unistd.h> | |
const unsigned char rfork_data[] = { | |
0x08, | |
0x00, | |
0x00, | |
0x00, | |
0x56, | |
0x00, | |
0x00, | |
0x00, | |
0x62, | |
0x76, | |
0x78, | |
0x6e, | |
0x4c, | |
0x00, | |
0x00, | |
0x00, | |
0x3e, | |
0x00, | |
0x00, | |
0x00, | |
0xe8, | |
0x74, | |
0x65, | |
0x73, | |
0x74, | |
0x69, | |
0x6e, | |
0x67, | |
0x20, | |
0x08, | |
0x08, | |
0xe0, | |
0x12, | |
0x79, | |
0x20, | |
0x64, | |
0x61, | |
0x74, | |
0x61, | |
0x20, | |
0x77, | |
0x68, | |
0x69, | |
0x63, | |
0x68, | |
0x20, | |
0x73, | |
0x68, | |
0x6f, | |
0x75, | |
0x6c, | |
0x64, | |
0x20, | |
0x63, | |
0x6f, | |
0x6d, | |
0x70, | |
0x72, | |
0x65, | |
0x73, | |
0x73, | |
0x20, | |
0x77, | |
0x65, | |
0x6c, | |
0x6c, | |
0x2c, | |
0x10, | |
0x27, | |
0x38, | |
0x05, | |
0xfe, | |
0xe1, | |
0x74, | |
0x06, | |
0x00, | |
0x00, | |
0x00, | |
0x00, | |
0x00, | |
0x00, | |
0x00, | |
0x62, | |
0x76, | |
0x78, | |
0x24, | |
}; | |
const unsigned char decmpfs_rfork_data[] = { | |
0x66, | |
0x70, | |
0x6d, | |
0x63, | |
0x0c, | |
0x00, | |
0x00, | |
0x00, | |
0x4c, | |
0x00, | |
0x00, | |
0x00, | |
0x00, | |
0x00, | |
0x00, | |
0x00, | |
}; | |
const unsigned char decmpfs_embedded_data[] = { | |
0x66, | |
0x70, | |
0x6d, | |
0x63, | |
0x0b, | |
0x00, | |
0x00, | |
0x00, | |
0x4c, | |
0x00, | |
0x00, | |
0x00, | |
0x00, | |
0x00, | |
0x00, | |
0x00, | |
0x62, | |
0x76, | |
0x78, | |
0x6e, | |
0x4c, | |
0x00, | |
0x00, | |
0x00, | |
0x3e, | |
0x00, | |
0x00, | |
0x00, | |
0xe8, | |
0x74, | |
0x65, | |
0x73, | |
0x74, | |
0x69, | |
0x6e, | |
0x67, | |
0x20, | |
0x08, | |
0x08, | |
0xe0, | |
0x12, | |
0x79, | |
0x20, | |
0x64, | |
0x61, | |
0x74, | |
0x61, | |
0x20, | |
0x77, | |
0x68, | |
0x69, | |
0x63, | |
0x68, | |
0x20, | |
0x73, | |
0x68, | |
0x6f, | |
0x75, | |
0x6c, | |
0x64, | |
0x20, | |
0x63, | |
0x6f, | |
0x6d, | |
0x70, | |
0x72, | |
0x65, | |
0x73, | |
0x73, | |
0x20, | |
0x77, | |
0x65, | |
0x6c, | |
0x6c, | |
0x2c, | |
0x10, | |
0x27, | |
0x38, | |
0x05, | |
0xfe, | |
0xe1, | |
0x74, | |
0x06, | |
0x00, | |
0x00, | |
0x00, | |
0x00, | |
0x00, | |
0x00, | |
0x00, | |
0x62, | |
0x76, | |
0x78, | |
0x24, | |
}; | |
#define EXPECTED_BODY "testing testy data which should compress well, test test test test test test" | |
#define EXPECTED_BODY_LEN (sizeof(EXPECTED_BODY) - 1) | |
#define TEST_PATH "/tmp/test.txt" | |
void check_file_contains_body(int fd) { | |
lseek(fd, 0, SEEK_SET); | |
char buf[EXPECTED_BODY_LEN]; | |
ssize_t rc = read(fd, buf, sizeof(buf)); | |
assert(rc >= 0); | |
bool matches = rc == EXPECTED_BODY_LEN && (memcmp(buf, EXPECTED_BODY, EXPECTED_BODY_LEN) == 0); | |
printf("File contains expected body: %s\n", matches ? "TRUE" : "FALSE"); | |
} | |
void do_compression(const char *path, bool skip_rfork_compression_finish) { | |
printf("Removing %s\n", path); | |
unlink(path); | |
printf("Creating %s\n", path); | |
int fd = open(path, O_CREAT | O_RDWR, 0644); | |
assert(fd != -1); | |
printf("Writing decmpfs xattr using rfork\n"); | |
int rc = fsetxattr(fd, "com.apple.decmpfs", decmpfs_rfork_data, sizeof(decmpfs_rfork_data), 0, XATTR_SHOWCOMPRESSION); | |
assert(rc == 0); | |
printf("Writing resource fork\n"); | |
rc = fsetxattr(fd, "com.apple.ResourceFork", rfork_data, sizeof(rfork_data), 0, 0); | |
assert(rc == 0); | |
if (skip_rfork_compression_finish) { | |
printf("NOT setting compressed flag\n"); | |
} else { | |
printf("Setting compressed flag\n"); | |
rc = fchflags(fd, UF_COMPRESSED); | |
assert(rc == 0); | |
// Uncommenting this causes the later compression to work? | |
#if 0 | |
check_file_contains_body(fd); | |
#endif | |
// Performing ANY read seems to cause the later compression to work? | |
#if 0 | |
lseek(fd, 0, SEEK_SET); | |
char buf[1]; | |
read(fd, buf, 1); | |
#endif | |
// mmaping the file doesn't cause compression to work | |
char *map_result = mmap(NULL, EXPECTED_BODY_LEN, PROT_READ, MAP_SHARED | MAP_NOCACHE, fd, 0); | |
// But reading from the mmapped region DOES cause compression to work | |
#if 0 | |
bool equal = memcmp(map_result, EXPECTED_BODY, EXPECTED_BODY_LEN) == 0; | |
printf("mmap equal: %s\n", equal ? "TRUE" : "FALSE"); | |
#endif | |
munmap(map_result, EXPECTED_BODY_LEN); | |
printf("Unsetting compressed flag\n"); | |
rc = fchflags(fd, 0); | |
assert(rc == 0); | |
} | |
printf("Removing resource fork\n"); | |
rc = fremovexattr(fd, "com.apple.ResourceFork", XATTR_SHOWCOMPRESSION); | |
assert(rc == 0); | |
printf("Removing decmpfs xattr\n"); | |
rc = fremovexattr(fd, "com.apple.decmpfs", XATTR_SHOWCOMPRESSION); | |
assert(rc == 0); | |
printf("Writing decmpfs xattr using embedded data (no rfork)\n"); | |
rc = fsetxattr(fd, "com.apple.decmpfs", decmpfs_embedded_data, sizeof(decmpfs_embedded_data), 0, XATTR_SHOWCOMPRESSION); | |
assert(rc == 0); | |
printf("Setting compressed flag\n"); | |
rc = fchflags(fd, UF_COMPRESSED); | |
assert(rc == 0); | |
check_file_contains_body(fd); | |
} | |
int main() { | |
do_compression(TEST_PATH, false); | |
// do_compression(TEST_PATH, true); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment