13#define CHECK(condition) \
16 fprintf(stderr, "FILESYSTEM-ALLOCATION-CONTRACT: line=%d errno=%d\n", __LINE__, errno); \
21int main(
int argc,
char** argv) {
22 const char* directory = argc > 1 ? argv[1] :
"/tmp";
24 snprintf(path,
sizeof(path),
"%s/allocation-%ld", directory, (
long)getpid());
25 int fd = -1, readonly = -1, pathfd = -1, pipes[2] = {-1, -1};
27 const long page = sysconf(_SC_PAGESIZE);
28 const unsigned char prefix[] = {13, 29, 47, 61, 83};
29 unsigned char* mapping = MAP_FAILED;
30 unsigned char* bytes = NULL;
31 struct stat before, reserved, after;
33 const off_t offset = 5 * page + 11, length = 2 * page + 17, end = offset + length;
34 bytes = malloc((
size_t)end);
36 fd = open(path, O_CREAT | O_EXCL | O_RDWR, 0600);
38 CHECK(write(fd, prefix,
sizeof(prefix)) ==
sizeof(prefix));
39 CHECK(lseek(fd, 37, SEEK_SET) == 37);
40 CHECK(fstat(fd, &before) == 0);
42 CHECK(fallocate(fd, FALLOC_FL_KEEP_SIZE, offset, length) == 0);
43 CHECK(fstat(fd, &reserved) == 0 && reserved.st_size ==
sizeof(prefix));
44 CHECK(reserved.st_blocks >= before.st_blocks + 2 * page / 512);
45 CHECK(lseek(fd, 0, SEEK_CUR) == 37);
46 CHECK(close(fd) == 0);
47 fd = open(path, O_RDWR);
48 CHECK(fd >= 0 && fstat(fd, &after) == 0);
49 CHECK(after.st_blocks == reserved.st_blocks && after.st_size ==
sizeof(prefix));
50 CHECK(fallocate(fd, FALLOC_FL_KEEP_SIZE, offset, length) == 0);
51 CHECK(fstat(fd, &after) == 0 && after.st_blocks == reserved.st_blocks);
53 mapping = mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
54 CHECK(mapping != MAP_FAILED);
56 memset(mapping +
sizeof(prefix), 0xe7, (
size_t)page -
sizeof(prefix));
57 CHECK(fallocate(fd, 0, offset, length) == 0);
58 CHECK(fstat(fd, &after) == 0 && after.st_size == end);
59 CHECK(after.st_blocks == reserved.st_blocks);
60 CHECK(memcmp(mapping, prefix,
sizeof(prefix)) == 0);
61 for (
size_t i =
sizeof(prefix); i < (size_t)page; ++i)
62 CHECK(mapping[i] == 0);
63 CHECK(munmap(mapping, page) == 0);
65 memset(bytes, 0xcc, (
size_t)end);
66 CHECK(pread(fd, bytes, (
size_t)end, 0) == end);
67 CHECK(memcmp(bytes, prefix,
sizeof(prefix)) == 0);
68 for (
size_t i =
sizeof(prefix); i < (size_t)end; ++i)
72 CHECK(posix_fallocate(fd, offset, length) == 0 && errno == EDOM);
73 CHECK(fstat(fd, &before) == 0);
74 CHECK(pwrite(fd, prefix,
sizeof(prefix), offset) ==
sizeof(prefix));
75 CHECK(fstat(fd, &after) == 0 && after.st_blocks == before.st_blocks);
76 CHECK(fsync(fd) == 0);
77 CHECK(pread(fd, bytes,
sizeof(prefix), offset) ==
sizeof(prefix));
78 CHECK(memcmp(bytes, prefix,
sizeof(prefix)) == 0);
80 readonly = open(path, O_RDONLY);
81 pathfd = open(path, O_PATH);
82 CHECK(readonly >= 0 && pathfd >= 0);
84 CHECK(fallocate(readonly, 0, 0, 1) == -1 && errno == EBADF);
86 CHECK(fallocate(pathfd, 0, 0, 1) == -1 && errno == EBADF);
88 CHECK(fallocate(-1, 0, 0, 1) == -1 && errno == EBADF);
90 CHECK(fallocate(fd, 0, -1, 1) == -1 && errno == EINVAL);
92 CHECK(fallocate(fd, 0, 0, 0) == -1 && errno == EINVAL);
94 CHECK(fallocate(fd, 0, INT64_MAX, 1) == -1 && errno == EFBIG);
96 CHECK(fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, page) == -1 &&
98 CHECK(pipe(pipes) == 0);
100 CHECK(fallocate(pipes[1], 0, 0, 1) == -1 && errno == ESPIPE);
102 CHECK(posix_fallocate(fd, 0, -1) == EINVAL && errno == EDOM);
104 CHECK(ftruncate(fd, 0) == 0);
105 CHECK(fstat(fd, &after) == 0 && after.st_blocks == 0);
106 CHECK(fallocate(fd, FALLOC_FL_KEEP_SIZE, offset, length) == 0);
107 CHECK(fstat(fd, &after) == 0 && after.st_size == 0 && after.st_blocks > 0);
108 CHECK(ftruncate(fd, 0) == 0);
109 CHECK(fstat(fd, &after) == 0 && after.st_blocks == 0);
110 CHECK(unlink(path) == 0);
111 CHECK(fallocate(fd, 0, 0, page) == 0);
112 CHECK(fstat(fd, &after) == 0 && after.st_size == page);
116 if (mapping != MAP_FAILED)
117 munmap(mapping, page);
131 puts(
"FILESYSTEM-ALLOCATION-CONTRACT: PASS");