test-raw-dev-unaligned.c [plain text]
#include <sys/fcntl.h>
#include <unistd.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/param.h>
#include <sys/mount.h>
#include "hfs-tests.h"
#include "test-utils.h"
#include "disk-image.h"
TEST(raw_dev_unaligned, .run_as_root = 1);
int run_raw_dev_unaligned(__unused test_ctx_t *ctx)
{
struct statfs sfs;
assert(statfs("/tmp", &sfs) == 0);
if (strcmp(sfs.f_fstypename, "hfs")) {
printf("raw_dev_aligned needs hfs as root file system - skipping.\n");
return 0;
}
int fd = open("/tmp/raw-dev-unaligned", O_CREAT | O_RDWR | O_TRUNC, 0666);
assert_with_errno(fd >= 0);
assert_no_err(ftruncate(fd, 4096));
assert_no_err(fcntl(fd, F_FULLFSYNC));
struct log2phys l2p = {};
assert_no_err(fcntl(fd, F_LOG2PHYS_EXT, &l2p));
assert(!strncmp(sfs.f_mntfromname, "/dev/disk", 9));
char *rdev;
asprintf(&rdev, "/dev/rdisk%s", sfs.f_mntfromname + 9);
int raw_fd;
assert_with_errno((raw_fd = open(rdev, O_RDWR)) >= 0);
void *buf = malloc(16384);
off_t offset = l2p.l2p_devoffset;
char *p = (char *)((((uintptr_t)buf + 64) & ~63) + 8);
unsigned bs = 4096;
if (bs < sfs.f_bsize)
bs = sfs.f_bsize;
check_io(pread(raw_fd, p, bs, offset), bs);
check_io(pwrite(fd, &fd, 4, 0), 4);
assert_no_err(fcntl(fd, F_FULLFSYNC));
char *state = malloc(bs);
check_io(pread(raw_fd, state, bs, offset), bs);
assert(memcmp(state, p, bs));
assert_no_err(close(fd));
for (int i = 0; i < 3000; ++i) {
for (unsigned i = 0; i < bs; ++i)
state[i] ^= 0xff;
memcpy(p, state, bs);
check_io(pwrite(raw_fd, p, bs, offset), bs);
check_io(pread(raw_fd, p, bs, offset), bs);
assert(!memcmp(p, state, bs));
}
assert_no_err(close(raw_fd));
assert_no_err(unlink("/tmp/raw-dev-unaligned"));
free(buf);
free(state);
return 0;
}