The Pedigree Project 0.1
xattr-contract-test/main.c
1#define _GNU_SOURCE
2#include <signal.h>
3#include <stdlib.h>
4#include <string.h>
5#include <unistd.h>
6
7#include "contract.h"
8
9size_t xa_page;
10size_t xa_block;
11static const char *persist_base, *persist_token;
12static int persist_write;
13
14static int block_size(const char* text) {
15 char* end;
16 errno = 0;
17 unsigned long value = strtoul(text, &end, 10);
18 if (errno || !text[0] || *end || value < 1024 || value > 65536 || (value & (value - 1)))
19 return -1;
20 xa_block = value;
21 return 0;
22}
23
24static int run(const char* name, int (*function)(void)) {
25 printf("XATTR-CONTRACT: BEGIN %s\n", name);
26 fflush(stdout);
27 pid_t child = fork();
28 int result = -1;
29 if (!child) {
30 alarm(40);
31 result = function();
32 fflush(stdout);
33 fflush(stderr);
34 _exit(result ? 1 : 0);
35 }
36 if (child > 0)
37 result = xa_reap(child, 45000);
38 printf("XATTR-CONTRACT: %s %s status=%d\n", result ? "FAIL" : "PASS", name, result);
39 fflush(stdout);
40 return result;
41}
42
43static int persistence(void) {
44 return xa_persistence(persist_base, persist_token, persist_write);
45}
46
47int main(int argc, char** argv) {
48 xa_page = (size_t)sysconf(_SC_PAGESIZE);
49 if (xa_page < 512 || xa_page > 65536 || (xa_page & (xa_page - 1)))
50 return 2;
51 signal(SIGPIPE, SIG_IGN);
52 if (argc == 5 && (!strcmp(argv[1], "persist-write") || !strcmp(argv[1], "persist-read"))) {
53 if (block_size(argv[4]))
54 return 2;
55 persist_base = argv[2];
56 persist_token = argv[3];
57 persist_write = !strcmp(argv[1], "persist-write");
58 if (run(argv[1], persistence))
59 return 1;
60 printf("XATTR-PERSIST-CONTRACT: END %s PASS token=%s\n", persist_write ? "WRITE" : "READ",
61 persist_token);
62 return 0;
63 }
64 const char* selected = NULL;
65 for (int n = 1; n < argc; ++n) {
66 if (!strcmp(argv[n], "--block-size") && n + 1 < argc) {
67 if (block_size(argv[++n]))
68 return 2;
69 } else if (!selected)
70 selected = argv[n];
71 else
72 return 2;
73 }
74 if (!xa_block) {
75 fputs("XATTR-CONTRACT: verified Ext2 --block-size is required\n", stderr);
76 return 2;
77 }
78 static const struct {
79 const char* name;
80 int (*function)(void);
81 } suites[] = {
82 {"values", xa_values}, {"admission", xa_admission}, {"permissions", xa_permissions},
83 {"lifetime", xa_lifetime}, {"concurrency", xa_concurrency}, {"events", xa_events},
84 {"ext2", xa_ext2}};
85 int found = 0;
86 for (size_t n = 0; n < sizeof(suites) / sizeof(suites[0]); ++n) {
87 if (selected && strcmp(selected, "all") && strcmp(selected, suites[n].name))
88 continue;
89 found = 1;
90 if (run(suites[n].name, suites[n].function))
91 return 1;
92 }
93 if (!found)
94 return 2;
95 puts("XATTR-CONTRACT: END PASS");
96 return 0;
97}