Skip to content

Instantly share code, notes, and snippets.

@Dr-Emann
Last active April 26, 2023 15:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Dr-Emann/3d0f272d08c68a889fa368597a10cea7 to your computer and use it in GitHub Desktop.
Save Dr-Emann/3d0f272d08c68a889fa368597a10cea7 to your computer and use it in GitHub Desktop.
Testing Apple File System Compression for RJVB/afsctool#62
#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