├── .gitignore
├── README.md
├── asm
├── .gitignore
├── Makefile
├── arrrrgs.c
└── hello.s
├── btree
├── .gitignore
├── Makefile
├── btree.c
├── btree.h
└── run
├── chash
├── .gitignore
├── Makefile
├── README.md
├── dist.c
├── dist.h
├── genkeys
├── hash.c
├── murmur.c
└── ring.c
├── errno
├── .gitignore
├── Makefile
├── elist
├── errno.c
└── mklist
├── fifos
├── .gitignore
├── Makefile
├── fuzz.pl
├── fuzz2.pl
├── io.c
├── io2.c
└── size.c
├── flags
├── .gitignore
└── flags.c
├── fork
└── fork.c
├── fuse
└── nullfs
│ ├── .gitignore
│ ├── Makefile
│ └── nullfs.c
├── insist
├── .gitignore
├── Makefile
├── insist.h
├── main.c
├── modern.c
├── modern.s
└── traditional.c
├── knave
├── .gitignore
├── Makefile
└── knave.c
├── lexer-ll
├── NOTES
├── bql.ll
├── bql.ll.c
├── bql.ll.h
├── bql.regex
├── ll.pl
├── ll1.pl
└── main.c
├── malloc
├── .gitignore
├── Makefile
├── fmalloc1.c
└── victim.c
├── matrix
├── matrix.pl
└── sets
├── mlock
├── .gitignore
└── mlock.c
├── nacl
├── .gitignore
├── Makefile
├── common.h
├── decrypt.c
├── decrypt2.c
├── decrypt3.c
├── encrypt.c
├── tweetnacl.c
└── tweetnacl.h
├── openssl
└── spin
├── rcu
├── .gitignore
├── Makefile
├── api.h
├── lock
│ └── main.c
├── plot
├── qs
│ └── main.c
└── report
├── regm
├── .gitignore
├── Makefile
├── README.md
├── asm.c
├── file.p
├── gencode
├── opcodes.h
├── opcodes.yml
├── pn
│ ├── fibonacci.pn
│ ├── hello.pn
│ ├── numbers.pn
│ └── string.pn
├── regm.c
└── regm.h
├── ringer
├── Makefile
├── ring.c
├── ring.h
├── ringer.c
├── test
└── test.c
├── sedge
└── TODO
├── smaps
├── .gitignore
├── Makefile
├── README.md
├── buf.c
├── data
│ └── 256k
├── diag
├── fork.c
├── heap.c
├── huge.c
├── lib.c
├── mmap.c
├── null.c
└── stack.c
├── zig
├── .gitignore
├── Makefile
├── example.out
├── find-r.c
├── find-r.scm
├── run
└── solver.c
└── zmq
├── .gitignore
├── Makefile
└── req.c
/.gitignore:
--------------------------------------------------------------------------------
1 | *.sw[a-p]
2 | *.o
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | jameshunt(.us) Research
2 | =======================
3 |
4 | What is this?
5 |
6 | It's research, yo
7 |
8 | smaps/
9 | ------
10 |
11 | Research into the /proc/$PID/smaps file format, what it can tell
12 | us, and how to use it as a component in monitoring and a general
13 | troubleshooting aid.
14 |
15 | [http://jameshunt.us/writings/dist-rrd.html](http://jameshunt.us/writings/dist-rrd.html)
16 |
17 | malloc/
18 | -------
19 |
20 | A custom malloc implementation, with an eye towrads stress-testing
21 | software for edge-case failures around memory allocation.
22 |
23 | (article forthcoming...)
24 |
25 | Further Reading
26 | ---------------
27 |
28 | [http://jameshunt.us](http://jameshunt.us)
29 |
30 |
31 |
--------------------------------------------------------------------------------
/asm/.gitignore:
--------------------------------------------------------------------------------
1 | /hello
2 |
--------------------------------------------------------------------------------
/asm/Makefile:
--------------------------------------------------------------------------------
1 | hello: hello.o
2 | ld -o $@ $+
3 |
4 | %.o: %.s
5 | nasm -f elf64 -g -F stabs $+
6 |
--------------------------------------------------------------------------------
/asm/arrrrgs.c:
--------------------------------------------------------------------------------
1 | /*
2 | arrrrgs.c - Seeing what functions with long arg lists look like
3 |
4 | This is not meant to be compiled into an executable, just object
5 | code. Try `make arrrrgs.o`.
6 |
7 | To see the assembler code, run `objdump -M intel -d arrrrgs.o`
8 |
9 | 0000000000000000 :
10 | 0: 55 push rbp
11 | 1: 48 89 e5 mov rbp,rsp
12 | 4: 89 7d fc mov DWORD PTR [rbp-0x4],edi
13 | 7: 89 75 f8 mov DWORD PTR [rbp-0x8],esi
14 | a: 89 55 f4 mov DWORD PTR [rbp-0xc],edx
15 | d: 89 4d f0 mov DWORD PTR [rbp-0x10],ecx
16 | 10: 44 89 45 ec mov DWORD PTR [rbp-0x14],r8d
17 | 14: 44 89 4d e8 mov DWORD PTR [rbp-0x18],r9d
18 | 18: 83 45 fc 01 add DWORD PTR [rbp-0x4],0x1
19 | 1c: 83 45 f8 01 add DWORD PTR [rbp-0x8],0x1
20 | 20: 83 45 f4 01 add DWORD PTR [rbp-0xc],0x1
21 | 24: 83 45 f0 01 add DWORD PTR [rbp-0x10],0x1
22 | 28: 83 45 ec 01 add DWORD PTR [rbp-0x14],0x1
23 | 2c: 83 45 e8 01 add DWORD PTR [rbp-0x18],0x1
24 | 30: 83 45 10 01 add DWORD PTR [rbp+0x10],0x1
25 | 34: 83 45 18 01 add DWORD PTR [rbp+0x18],0x1
26 | 38: 83 45 20 01 add DWORD PTR [rbp+0x20],0x1
27 | 3c: 83 45 28 01 add DWORD PTR [rbp+0x28],0x1
28 | 40: 83 45 30 01 add DWORD PTR [rbp+0x30],0x1
29 | 44: 83 45 38 01 add DWORD PTR [rbp+0x38],0x1
30 | 48: b8 00 00 00 00 mov eax,0x0
31 | 4d: 5d pop rbp
32 | 4e: c3 ret
33 |
34 | */
35 |
36 | int fnargs(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l)
37 | {
38 | a++; b++; c++; d++; e++; f++; g++; h++; i++; j++; k++; l++;
39 | return 0;
40 | }
41 |
--------------------------------------------------------------------------------
/asm/hello.s:
--------------------------------------------------------------------------------
1 | ; hello.s
2 | ; 21 Aug 2017 - jrh
3 | ;
4 | ; A simple Hello, World! in Intel x86-64 assembly
5 | ;
6 | ; Compile with:
7 | ; nasm -f elf -g -F stabs hello.s
8 | ; ld -o hello hello.o
9 | ;
10 |
11 | section .bss
12 |
13 | section .data
14 | hello_str db "Hello, World!",10
15 | hello_len equ $-hello_str
16 |
17 | section .text
18 | global _start
19 |
20 | _start:
21 | nop ; hi gdb!
22 |
23 | ; write(0, hello_str, hello_len)
24 | mov rax,1 ; system call number
25 | mov rdi,1 ; standard output
26 | mov rsi,hello_str ; buffer to print
27 | mov rdx,hello_len ; bytes to print
28 | syscall
29 |
30 | ; exit(1)
31 | mov rax,60 ; system call number
32 | mov rdi,0 ; exit code
33 | syscall ; trap into kernel mode
34 |
--------------------------------------------------------------------------------
/btree/.gitignore:
--------------------------------------------------------------------------------
1 | /btree
2 |
--------------------------------------------------------------------------------
/btree/Makefile:
--------------------------------------------------------------------------------
1 | CFLAGS := -g -Wall -Wpedantic
2 |
3 | btree: btree.o
4 |
5 | clean:
6 | rm -fr btree btree.o btree.dSYM
7 |
--------------------------------------------------------------------------------
/btree/btree.c:
--------------------------------------------------------------------------------
1 | #include "btree.h"
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #ifndef YEARS
9 | # define YEARS 2
10 | #endif
11 | #ifndef SPAN
12 | # define SPAN 30
13 | #endif
14 |
15 | static int
16 | _find(struct btree *bt, uint32_t k)
17 | {
18 | assert(bt != NULL);
19 |
20 | int lo, mid, hi;
21 |
22 | lo = -1;
23 | hi = bt->nkeys;
24 | while (lo + 1 < hi) {
25 | mid = (lo + hi) / 2;
26 | if (bt->keys[mid] == k) return mid;
27 | if (bt->keys[mid] > k) hi = mid;
28 | else lo = mid;
29 | }
30 | return hi;
31 | }
32 |
33 | static int
34 | _isfull(struct btree *bt)
35 | {
36 | assert(bt != NULL);
37 | return bt->nkeys == BTREE_N;
38 | }
39 |
40 | static void
41 | _print(struct btree *bt, int indent)
42 | {
43 | int i;
44 |
45 | assert(bt != NULL);
46 | assert(indent >= 0);
47 |
48 | fprintf(stderr, "%*s[btree %p // %d keys]\n",
49 | indent, "", (void *)bt, bt->nkeys);
50 |
51 | for (i = 0; i < bt->nkeys; i++) {
52 | if (bt->leaf) {
53 | fprintf(stderr, "%*s[%03d] % 10d (= %lu)\n",
54 | indent + 2, "", i, bt->keys[i], bt->vals[i].data);
55 | } else {
56 | fprintf(stderr, "%*s[%03d] % 10d (%p) -->\n",
57 | indent + 2, "", i, bt->keys[i], (void *)bt->vals[i].child);
58 | _print(bt->vals[i].child, indent + 8);
59 | }
60 |
61 | }
62 | if (bt->leaf) {
63 | fprintf(stderr, "%*s[%03d] ~ (= %lu)\n",
64 | indent + 2, "", i, bt->vals[bt->nkeys].data);
65 | } else {
66 | fprintf(stderr, "%*s[%03d] ~ (%p) -->\n",
67 | indent + 2, "", i, (void *)bt->vals[bt->nkeys].child);
68 | _print(bt->vals[bt->nkeys].child, indent + 8);
69 | }
70 | }
71 |
72 | void
73 | btree_print(struct btree *bt)
74 | {
75 | _print(bt, 0);
76 | }
77 |
78 | struct btree *
79 | btree_new()
80 | {
81 | struct btree * bt = calloc(1, sizeof(struct btree));
82 | assert(bt != NULL);
83 |
84 | bt->leaf = 1;
85 | return bt;
86 | }
87 |
88 | static void
89 | _divide(struct btree *l, struct btree *r, int mid)
90 | {
91 | assert(l != NULL);
92 | assert(r != NULL);
93 | assert(mid != 0);
94 | assert(l->nkeys >= mid);
95 |
96 | r->nkeys = l->nkeys - mid - 1;
97 | l->nkeys = mid;
98 |
99 | memmove(r->keys, &l->keys[mid + 1], sizeof(uint32_t) * r->nkeys );
100 | memmove(r->vals, &l->vals[mid + 1], sizeof(void *) * (r->nkeys + 1));
101 |
102 | return;
103 | /* optional */
104 | memset(&r->keys[r->nkeys], 0, BTREE_N - r->nkeys );
105 | memset(&r->vals[r->nkeys], 0, BTREE_N - r->nkeys + 1);
106 | }
107 |
108 | static void
109 | _shiftr(struct btree *b, int n)
110 | {
111 | memmove(&b->keys[n + 1], &b->keys[n], sizeof(uint32_t) * (b->nkeys - n));
112 | memmove(&b->vals[n + 2], &b->vals[n + 1], sizeof(void *) * (b->nkeys - n));
113 | }
114 |
115 | static struct btree *
116 | _clone(struct btree *bt)
117 | {
118 | struct btree *r;
119 |
120 | r = btree_new();
121 | assert(r);
122 |
123 | r->leaf = bt->leaf;
124 | return r;
125 | }
126 |
127 | static struct btree *
128 | _insert(struct btree *bt, uint32_t key, uint64_t val, uint32_t *median)
129 | {
130 | int i, mid;
131 | struct btree *r;
132 |
133 | i = _find(bt, key);
134 |
135 | if (i < bt->nkeys && bt->keys[i] == key) {
136 | bt->vals[i].data = val;
137 | return NULL;
138 | }
139 |
140 | if (bt->leaf) {
141 | _shiftr(bt, i);
142 | bt->nkeys++;
143 | bt->keys[i] = key;
144 | bt->vals[i].data = val;
145 |
146 | } else { /* insert in child */
147 | r = _insert(bt->vals[i].child, key, val, median);
148 |
149 | if (r) {
150 | _shiftr(bt, i);
151 | bt->nkeys++;
152 | bt->keys[i] = *median;
153 | bt->vals[i+1].child = r;
154 | }
155 | }
156 |
157 | /* split the node now, if it is full, to save complexity */
158 | if (_isfull(bt)) {
159 | mid = bt->nkeys * BTREE_S / 100;
160 | *median = bt->keys[mid];
161 |
162 | r = _clone(bt);
163 | _divide(bt, r, mid);
164 | return r;
165 | }
166 |
167 | return NULL;
168 | }
169 |
170 | int
171 | btree_insert(struct btree *bt, uint32_t key, uint64_t val)
172 | {
173 | struct btree *l, *r;
174 | uint32_t m;
175 |
176 | assert(bt != NULL);
177 |
178 | r = _insert(bt, key, val, &m);
179 | if (r) {
180 | /* "pivot" root to the left */
181 | l = btree_new();
182 | memmove(l, bt, sizeof(*bt));
183 |
184 | /* re-initialize root as [ l . m . r ] */
185 | bt->nkeys = 1;
186 | bt->leaf = 0;
187 | bt->vals[0].child = l;
188 | bt->keys[0] = m;
189 | bt->vals[1].child = r;
190 | }
191 |
192 | return 0;
193 | }
194 |
195 | struct analysis {
196 | int nodes;
197 | int set;
198 | int depth;
199 | };
200 |
201 | static void
202 | _analyze(struct btree *bt, struct analysis *a)
203 | {
204 | int i;
205 |
206 | assert(bt != NULL);
207 | assert(a != NULL);
208 |
209 | a->nodes += 1;
210 | a->set += bt->nkeys + 1;
211 |
212 | if (!bt->leaf) {
213 | for (i = 0; i <= bt->nkeys; i++)
214 | _analyze(bt->vals[i].child, a);
215 | }
216 | }
217 |
218 | static void
219 | btree_analyze(struct btree *bt)
220 | {
221 | struct analysis a;
222 | double size;
223 | const char *unit;
224 |
225 | assert(bt != NULL);
226 |
227 | a.nodes = a.set = 0;
228 | _analyze(bt, &a);
229 |
230 | assert(a.nodes > 0);
231 | assert(a.set >= 0);
232 |
233 | a.depth = 0;
234 | while (bt && !bt->leaf) {
235 | a.depth++;
236 | bt = bt->vals[0].child;
237 | }
238 |
239 | fprintf(stderr, "N=%d, SFF=%0.2f, YEARS=%d, MIN=%d\n", BTREE_N, BTREE_S / 100.0, YEARS, SPAN);
240 | fprintf(stderr, "%d keys / %d nodes / %d levels\n", a.set, a.nodes, a.depth);
241 | fprintf(stderr, "%lu bytes per node\n", sizeof(struct btree));
242 | fprintf(stderr, "%0.3f%% slots filled\n", a.set * 100.0 / (a.nodes * BTREE_N));
243 |
244 | size = a.nodes * sizeof(struct btree);
245 | unit = "";
246 |
247 | fprintf(stderr, "%0.1f bytes (overhead) per key\n", size / a.set);
248 |
249 | if (size > 1024 * 1024 * 1024) {
250 | size /= 1024 * 1024 * 1024;
251 | unit = "G";
252 | }
253 | if (size > 1024 * 1024) {
254 | size /= 1024 * 1024;
255 | unit = "M";
256 | }
257 | if (size > 1024) {
258 | size /= 1024;
259 | unit = "K";
260 | }
261 |
262 | fprintf(stderr, "%0.1lf %sB\n", size, unit);
263 | fprintf(stderr, "\n");
264 | }
265 |
266 |
267 |
268 | #include
269 |
270 | int
271 | main(int argc, char **argv)
272 | {
273 | uint32_t ts;
274 | unsigned int i;
275 | struct btree *bt;
276 |
277 | bt = btree_new();
278 |
279 | for (i = 0; i < YEARS * 365U * 86400U; i += SPAN * 60) {
280 | ts = 1234567890 + i;
281 | if (ts % 1000000 == 0) fprintf(stderr, "%d\n", ts);
282 | btree_insert(bt, ts, ts);
283 | }
284 | btree_analyze(bt);
285 |
286 | return 0;
287 | }
288 |
--------------------------------------------------------------------------------
/btree/btree.h:
--------------------------------------------------------------------------------
1 | #ifndef BTREE_H
2 | #define BTREE_H
3 |
4 | #include
5 |
6 | #ifndef BTREE_N
7 | # define BTREE_N 340
8 | #endif
9 |
10 | #ifndef BTREE_S
11 | # define BTREE_S 75
12 | #endif
13 |
14 | /* NOTE: this btree structure is not suitable
15 | for writing to disk and then mmap()-ing
16 | back in; it is just for exploration.
17 | */
18 | struct btree {
19 | int nkeys;
20 | int leaf;
21 | uint32_t keys[BTREE_N];
22 | union {
23 | uint64_t data;
24 | struct btree *child;
25 | } vals[BTREE_N + 1];
26 | };
27 |
28 | struct btree *
29 | btree_new();
30 |
31 | int
32 | btree_insert(struct btree *bt, uint32_t key, uint64_t val);
33 |
34 | void *
35 | btree_lookup(struct btree *bt, uint32_t key);
36 |
37 | #endif
38 |
--------------------------------------------------------------------------------
/btree/run:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | while [[ $# != 0 ]]; do
4 | make CFLAGS="-DBTREE_S=$1 -DYEARS=${YEARS:-2} -DSPAN=${SPAN:-30}" clean btree && ./btree
5 | shift
6 | done
7 |
--------------------------------------------------------------------------------
/chash/.gitignore:
--------------------------------------------------------------------------------
1 | hash
2 | ring
3 |
--------------------------------------------------------------------------------
/chash/Makefile:
--------------------------------------------------------------------------------
1 | CFLAGS := -g -Wall
2 | LDLIBS := -lvigor
3 |
4 | all: hash ring
5 | hash: hash.o
6 | ring: ring.o dist.o murmur.o
7 |
8 | example: hash
9 | @./hash $$(/bin/bash -c 'echo host0{1,2}.example.com:{cpu,memory,load} www.example.com:requests_per_second')
10 |
--------------------------------------------------------------------------------
/chash/README.md:
--------------------------------------------------------------------------------
1 | chash - jameshunt(.us) Research
2 | ===============================
3 |
4 | This is **DRAFT** research. The blog post is published (but not
5 | syndicated). Send comments to [feedback@jameshunt.us](mailto:feedback@jameshunt.us)
6 |
7 | Research into (consistent) hashing techniques and methodologies.
8 |
9 | [http://jameshunt.us/writings/dist-rrd.html](http://jameshunt.us/writings/dist-rrd.html)
10 |
11 | Further Reading
12 | ---------------
13 |
14 | [http://jameshunt.us](http://jameshunt.us)
15 |
16 |
17 |
--------------------------------------------------------------------------------
/chash/dist.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "dist.h"
5 |
6 | static uint64_t s_node_key(node_t *n, unsigned int i)
7 | {
8 | char *k = string("%lu-%s", i, n);
9 | uint64_t h = murmur64a(k, strlen(k), 0);
10 | free(k);
11 | return h;
12 | }
13 |
14 | static int s_sort_vnodes(const void *a_, const void *b_)
15 | {
16 | uint64_t a = ((const vnode_t *)a_)->key;
17 | uint64_t b = ((const vnode_t *)b_)->key;
18 | return a == b ? 0 : a > b ? 1 : -1;
19 | }
20 |
21 | int ring_init(ring_t* ring, node_t *nodes, unsigned int n)
22 | {
23 | assert(ring != NULL);
24 | assert(nodes != NULL);
25 | assert(n != 0);
26 |
27 | unsigned int i, j, k;
28 |
29 | ring->len = 0;
30 | for (i = 0; i < n; i++)
31 | ring->len += ring->spread * nodes[i].weight;
32 |
33 | ring->vnodes = calloc(ring->len, sizeof(vnode_t));
34 | assert(ring->vnodes != NULL);
35 | for (i = k = 0; i < n && k < ring->len; i++) {
36 | nodes[i].u = 0;
37 | for (j = 0; j < ring->spread * nodes[i].weight; j++, k++) {
38 | ring->vnodes[k].node = &nodes[i];
39 | ring->vnodes[k].key = s_node_key(&nodes[i], j);
40 | }
41 | }
42 |
43 | qsort(ring->vnodes, ring->len, sizeof(vnode_t), s_sort_vnodes);
44 |
45 | return 0;
46 | }
47 |
48 | node_t* lookup(ring_t *ring, const char *key)
49 | {
50 | uint64_t h = murmur64a(key, strlen(key), 0);
51 | if (h > ring->vnodes[ring->len - 1].key)
52 | return ring->vnodes[0].node;
53 |
54 | unsigned int i;
55 | for (i = 0; i < ring->len; i++)
56 | if (h <= ring->vnodes[i].key)
57 | return ring->vnodes[i].node;
58 |
59 | return NULL;
60 | }
61 |
--------------------------------------------------------------------------------
/chash/dist.h:
--------------------------------------------------------------------------------
1 | #ifndef DIST_H
2 | #define DIST_H
3 |
4 | #include
5 |
6 | typedef struct {
7 | const char *name;
8 | uint8_t weight;
9 |
10 | uint32_t u; /* only used for analysis */
11 | } node_t;
12 |
13 | typedef struct {
14 | node_t *node;
15 | uint64_t key;
16 | } vnode_t;
17 |
18 | typedef struct {
19 | unsigned int spread; /* how many vnodes per weighting? */
20 | unsigned int len;
21 | vnode_t *vnodes;
22 | } ring_t;
23 |
24 | uint64_t murmur64a(const void *key, unsigned int len, unsigned int seed);
25 | uint64_t murmur64b(const void *key, unsigned int len, unsigned int seed);
26 |
27 | int ring_init(ring_t* ring, node_t *nodes, unsigned int n);
28 | node_t* lookup(ring_t *ring, const char *key);
29 |
30 | #endif
31 |
--------------------------------------------------------------------------------
/chash/genkeys:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 |
3 | my @types = qw/web db asset cache mon/;
4 | my @checks = qw/memory load cpu disk procs forks swap syslog ntp ssh logs authlog dmesg/;
5 |
6 | my $MAX = shift @ARGV || 16;
7 |
8 | my $n = 0;
9 | for (;;) {
10 | $n++;
11 | for my $t (@types) {
12 | for my $c (@checks) {
13 | printf "%s%02i.example.com:%s\n", $t, $n, $c;
14 | exit 0 unless --$MAX;
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/chash/hash.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | unsigned long
4 | hash(unsigned char *str)
5 | {
6 | unsigned long hash = 5381;
7 | int c;
8 |
9 | while ((c = *str++))
10 | hash = ((hash << 5) + hash) + c;
11 |
12 | return hash;
13 | }
14 |
15 | int main(int argc, char **argv)
16 | {
17 | int i;
18 | for (i = 1; i < argc; i++)
19 | printf(" \"%s\" = %lu\n", argv[i], hash((unsigned char*)argv[i]) & 0xff);
20 | printf("\n\n");
21 | for (i = 1; i < argc; i++)
22 | printf(" L(%s) = %lu mod %i = %lu\n", argv[i],
23 | hash((unsigned char*)argv[i]) & 0xff, 3,
24 | (hash((unsigned char*)argv[i]) & 0xff) % 3);
25 | printf("\n\n");
26 | for (i = 1; i < argc; i++)
27 | printf(" L(%s) = %lu mod %i = %lu\n", argv[i],
28 | hash((unsigned char*)argv[i]) & 0xff, 4,
29 | (hash((unsigned char*)argv[i]) & 0xff) % 4);
30 | printf("\n\n");
31 | return 0;
32 | }
33 |
--------------------------------------------------------------------------------
/chash/murmur.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | /* 64-bit optimized */
4 | uint64_t murmur64a(const void *key, unsigned int len, unsigned int seed)
5 | {
6 | const uint64_t m = 0xc6a4a7935bd1e995;
7 | const int r = 47;
8 |
9 | uint64_t h = seed ^ len;
10 |
11 | const uint64_t *data = (const uint64_t *)key;
12 | const uint64_t *end = data + (len/8);
13 |
14 | while(data != end) {
15 | uint64_t k = *data++;
16 |
17 | k *= m;
18 | k ^= k >> r;
19 | k *= m;
20 |
21 | h ^= k;
22 | h *= m;
23 | }
24 |
25 | const unsigned char *data2 = (const unsigned char *)data;
26 |
27 | switch(len & 7) {
28 | case 7: h ^= (uint64_t)(data2[6]) << 48;
29 | case 6: h ^= (uint64_t)(data2[5]) << 40;
30 | case 5: h ^= (uint64_t)(data2[4]) << 32;
31 | case 4: h ^= (uint64_t)(data2[3]) << 24;
32 | case 3: h ^= (uint64_t)(data2[2]) << 16;
33 | case 2: h ^= (uint64_t)(data2[1]) << 8;
34 | case 1: h ^= (uint64_t)(data2[0]);
35 | h *= m;
36 | };
37 |
38 | h ^= h >> r;
39 | h *= m;
40 | h ^= h >> r;
41 |
42 | return h;
43 | }
44 |
45 | /* 32-bit optimized */
46 | uint64_t murmur64b(const void *key, unsigned int len, unsigned int seed)
47 | {
48 | const unsigned int m = 0x5bd1e995;
49 | const int r = 24;
50 |
51 | unsigned int h1 = seed ^ len;
52 | unsigned int h2 = 0;
53 |
54 | const unsigned int *data = (const unsigned int *)key;
55 |
56 | while(len >= 8) {
57 | unsigned int k1 = *data++;
58 | k1 *= m; k1 ^= k1 >> r; k1 *= m;
59 | h1 *= m; h1 ^= k1;
60 | len -= 4;
61 |
62 | unsigned int k2 = *data++;
63 | k2 *= m; k2 ^= k2 >> r; k2 *= m;
64 | h2 *= m; h2 ^= k2;
65 | len -= 4;
66 | }
67 |
68 | if(len >= 4) {
69 | unsigned int k1 = *data++;
70 | k1 *= m; k1 ^= k1 >> r; k1 *= m;
71 | h1 *= m; h1 ^= k1;
72 | len -= 4;
73 | }
74 |
75 | switch(len) {
76 | case 3: h2 ^= ((unsigned char *)data)[2] << 16;
77 | case 2: h2 ^= ((unsigned char *)data)[1] << 8;
78 | case 1: h2 ^= ((unsigned char *)data)[0];
79 | h2 *= m;
80 | };
81 |
82 | h1 ^= h2 >> 18; h1 *= m;
83 | h2 ^= h1 >> 22; h2 *= m;
84 | h1 ^= h2 >> 17; h1 *= m;
85 |
86 | uint64_t h = h1;
87 | h = (h << 32) | h2;
88 |
89 | return h;
90 | }
91 |
--------------------------------------------------------------------------------
/chash/ring.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include "dist.h"
7 |
8 | int main(int argc, char **argv)
9 | {
10 | int spread;
11 | int quiet;
12 |
13 | int opt;
14 | while ((opt = getopt(argc, argv, "qs:")) != -1) {
15 | switch (opt) {
16 | case 'q': quiet = 1; break;
17 | case 's': spread = atoi(optarg); break;
18 | default:
19 | fprintf(stderr, "USAGE: %s [-q] [-s spread]\n", argv[0]);
20 | return 1;
21 | }
22 | }
23 |
24 | ring_t ring = { .spread = spread ? spread : 16 };
25 | node_t nodes[4] = {
26 | { .name = "node01.ring.example.com", .weight = 1 },
27 | { .name = "node02.ring.example.com", .weight = 2 },
28 | { .name = "node03.ring.example.com", .weight = 1 },
29 | { .name = "node04.ring.example.com", .weight = 1 }
30 | };
31 |
32 | int rc = ring_init(&ring, nodes, 4);
33 | assert(rc == 0);
34 |
35 | int i;
36 | for (i = 0; !quiet && i < ring.len; i++)
37 | printf("%#018lx %i %s\n", ring.vnodes[i].key,
38 | ring.vnodes[i].node->weight, ring.vnodes[i].node->name);
39 |
40 | int count = 0;
41 | char buf[8192];
42 | while ((fgets(buf, 8192, stdin))) {
43 | char *nl = strchr(buf, '\n');
44 | if (nl) *nl = '\0';
45 |
46 | node_t *n = lookup(&ring, buf);
47 | if (n) {
48 | count++;
49 | n->u++;
50 | if (!quiet)
51 | printf("key %-30s (%#018lx) is at %s (%i)\n",
52 | buf, murmur64a(buf, strlen(buf), 0),
53 | n ? n->name : "(nil)",
54 | n ? n->weight : 0);
55 | } else {
56 | printf("key %s not found in ring!\n", buf);
57 | }
58 | }
59 |
60 | if (!quiet) printf("\n\n");
61 | for (i = 0; i < 4; i++) {
62 | printf("node %s (%i) accounts for % 5i/%i keys (%5.2lf%%)\n",
63 | nodes[i].name, nodes[i].weight, nodes[i].u, count, nodes[i].u * 100.0 / count);
64 | }
65 | return 0;
66 | }
67 |
--------------------------------------------------------------------------------
/errno/.gitignore:
--------------------------------------------------------------------------------
1 | errno
2 | elist.h
3 |
--------------------------------------------------------------------------------
/errno/Makefile:
--------------------------------------------------------------------------------
1 | CFLAGS := -Wall -g2 -O0 -Wno-unused
2 |
3 | BINARIES :=
4 | BINARIES += errno
5 |
6 | all: $(BINARIES)
7 | clean:
8 | rm -f *.o $(BINARIES)
9 | errno.o: errno.c elist.h
10 | elist.h: elist
11 | ./mklist elist > $@
12 |
--------------------------------------------------------------------------------
/errno/elist:
--------------------------------------------------------------------------------
1 | E2BIG
2 | EACCES
3 | EADDRINUSE
4 | EADDRNOTAVAIL
5 | EAFNOSUPPORT
6 | EAGAIN
7 | EALREADY
8 | EBADE
9 | EBADF
10 | EBADFD
11 | EBADMSG
12 | EBADR
13 | EBADRQC
14 | EBADSLT
15 | EBUSY
16 | ECANCELED
17 | ECHILD
18 | ECHRNG
19 | ECOMM
20 | ECONNABORTED
21 | ECONNREFUSED
22 | ECONNRESET
23 | EDEADLK
24 | EDEADLOCK
25 | EDESTADDRREQ
26 | EDOM
27 | EDQUOT
28 | EEXIST
29 | EFAULT
30 | EFBIG
31 | EHOSTDOWN
32 | EHOSTUNREACH
33 | EIDRM
34 | EILSEQ
35 | EINPROGRESS
36 | EINTR
37 | EINVAL
38 | EIO
39 | EISCONN
40 | EISDIR
41 | EISNAM
42 | EKEYEXPIRED
43 | EKEYREJECTED
44 | EKEYREVOKED
45 | EL2HLT
46 | EL2NSYNC
47 | EL3HLT
48 | EL3RST
49 | ELIBACC
50 | ELIBBAD
51 | ELIBMAX
52 | ELIBSCN
53 | ELIBEXEC
54 | ELOOP
55 | EMEDIUMTYPE
56 | EMFILE
57 | EMLINK
58 | EMSGSIZE
59 | EMULTIHOP
60 | ENAMETOOLONG
61 | ENETDOWN
62 | ENETRESET
63 | ENETUNREACH
64 | ENFILE
65 | ENOBUFS
66 | ENODATA
67 | ENODEV
68 | ENOENT
69 | ENOEXEC
70 | ENOKEY
71 | ENOLCK
72 | ENOLINK
73 | ENOMEDIUM
74 | ENOMEM
75 | ENOMSG
76 | ENONET
77 | ENOPKG
78 | ENOPROTOOPT
79 | ENOSPC
80 | ENOSR
81 | ENOSTR
82 | ENOSYS
83 | ENOTBLK
84 | ENOTCONN
85 | ENOTDIR
86 | ENOTEMPTY
87 | ENOTSOCK
88 | ENOTSUP
89 | ENOTTY
90 | ENOTUNIQ
91 | ENXIO
92 | EOPNOTSUPP
93 | EOVERFLOW
94 | EPERM
95 | EPFNOSUPPORT
96 | EPIPE
97 | EPROTO
98 | EPROTONOSUPPORT
99 | EPROTOTYPE
100 | ERANGE
101 | EREMCHG
102 | EREMOTE
103 | EREMOTEIO
104 | ERESTART
105 | EROFS
106 | ESHUTDOWN
107 | ESPIPE
108 | ESOCKTNOSUPPORT
109 | ESRCH
110 | ESTALE
111 | ESTRPIPE
112 | ETIME
113 | ETIMEDOUT
114 | ETXTBSY
115 | EUCLEAN
116 | EUNATCH
117 | EUSERS
118 | EWOULDBLOCK
119 | EXDEV
120 | EXFULL
121 |
--------------------------------------------------------------------------------
/errno/errno.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include "elist.h"
7 |
8 | int main (int argc, char **argv)
9 | {
10 | elist_init();
11 | int i;
12 | for (i = 1; argv[i]; i++) {
13 | char *x = NULL;
14 | int err = strtoul(argv[i], &x, 10);
15 | if (x && *x) {
16 | fprintf(stderr, "'%s': unrecognized errno value\n", argv[i]);
17 | continue;
18 | }
19 | if (err < 0 || err > 255) {
20 | fprintf(stderr, "%i: out-of-range for an errno value\n", err);
21 | continue;
22 | }
23 |
24 | fprintf(stderr, "% 4i %-16s %s\n",
25 | err, CONST[err] ? CONST[err] : "-", strerror(err));
26 | }
27 | return 0;
28 | }
29 |
--------------------------------------------------------------------------------
/errno/mklist:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 | # elist can be generated with:
3 | # `man errno | grep '^ * E' | awk '{print $1}' > elist`
4 |
5 | print <= 0 && (x) <= 255) CONST[(x)] = #x; } while (0)
10 |
11 | static void elist_init(void)
12 | {
13 | EOF
14 |
15 | for (<>) {
16 | chomp;
17 | print <", "io.fifo" or die "io.fifo: $!\n";
5 | print $fh $_[0];
6 | close $fh;
7 | }
8 | submit "[$ts] SCHEDULE_SERVICE_CHECK;host.example.com;foo$_;$ts\n" for 1 .. 963;
9 | submit "[$ts] SCHEDULE_SERVICE_CHECK;host;service;$ts\n";
10 |
--------------------------------------------------------------------------------
/fifos/io.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #define MAX_LEN 2048
10 |
11 | static int total;
12 | static int i = 0;
13 |
14 | void exec_command(const char *cmd)
15 | {
16 | i++; total += strlen(cmd);
17 |
18 | fprintf(stderr, ".");
19 | if (cmd[strlen(cmd) - 1] != '\n' || cmd[0] != '[')
20 | fprintf(stderr, "<< (%i) read %i bytes (%i total): '%s'>>", i, (int)strlen(cmd), total, cmd);
21 | }
22 |
23 | void process_command_file(FILE *io)
24 | {
25 | char buf[MAX_LEN];
26 | int fd = fileno(io);
27 |
28 | struct pollfd pfd;
29 |
30 | for (;;) {
31 | pfd.fd = fd;
32 | pfd.events = POLLIN;
33 |
34 | int pollval = poll(&pfd, 1, 500);
35 | assert(pollval != -1);
36 |
37 | if (pollval == 0)
38 | continue;
39 |
40 | //clearerr(io);
41 | while (fgets(buf, MAX_LEN, io) != NULL)
42 | exec_command(buf);
43 | fprintf(stderr, "\nEOF!\n");
44 | }
45 | }
46 |
47 | int main(int argc, char **argv)
48 | {
49 | unlink("io.fifo");
50 | system("mkfifo io.fifo");
51 |
52 | int fd = open("io.fifo", O_RDWR | O_NONBLOCK);
53 | assert(fd >= 0);
54 |
55 | FILE *fp = fdopen(fd, "r");
56 | assert(fp != NULL);
57 |
58 | process_command_file(fp);
59 |
60 | close(fd);
61 | fclose(fp);
62 | return 0;
63 | }
64 |
--------------------------------------------------------------------------------
/fifos/io2.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | #define MAX_LEN 2048
11 |
12 | static int total;
13 | static int i = 0;
14 |
15 | void exec_command(const char *cmd)
16 | {
17 | i++; total += strlen(cmd);
18 |
19 | fprintf(stderr, ".");
20 | if (cmd[strlen(cmd) - 1] != '\n' || cmd[0] != '[')
21 | fprintf(stderr, "<< (%i) read %i bytes (%i total): '%s'>>", i, (int)strlen(cmd), total, cmd);
22 | }
23 |
24 | void process_command_file(int fd)
25 | {
26 | char command[MAX_LEN];
27 | static char buf[MAX_LEN];
28 | static size_t offset = 0;
29 |
30 | struct pollfd pfd;
31 |
32 | for (;;) {
33 | pfd.fd = fd;
34 | pfd.events = POLLIN;
35 |
36 | int pollval = poll(&pfd, 1, 500);
37 | assert(pollval != -1);
38 |
39 | if (pollval == 0)
40 | continue;
41 |
42 | ssize_t n = read(fd, buf + offset, MAX_LEN - offset - 1);
43 | if (n == 0) {
44 | fprintf(stderr, "EOF!\n");
45 | break;
46 | }
47 | if (n == -1) {
48 | if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
49 | continue;
50 | perror("read");
51 | break;
52 | }
53 | buf[offset + n] = '\0';
54 |
55 | char *a;
56 | for (;;) {
57 | a = buf;
58 | while (*a && *a != '\n') a++;
59 | if (!*a) break;
60 | a++;
61 |
62 | memset(command, 0, MAX_LEN);
63 | memcpy(command, buf, a - buf);
64 | memmove(buf, a, MAX_LEN - (a - buf));
65 |
66 | exec_command(command);
67 | }
68 | offset = a - buf;
69 | }
70 | fprintf(stderr, "\nEOF!\n");
71 | }
72 |
73 | int main(int argc, char **argv)
74 | {
75 | unlink("io.fifo");
76 | system("mkfifo io.fifo");
77 |
78 | int fd = open("io.fifo", O_RDWR | O_NONBLOCK);
79 | assert(fd >= 0);
80 |
81 | process_command_file(fd);
82 | fprintf(stderr, "\n\nprocessed %i items / %i bytes\n", i, total);
83 |
84 | close(fd);
85 | return 0;
86 | }
87 |
--------------------------------------------------------------------------------
/fifos/size.c:
--------------------------------------------------------------------------------
1 | #define _GNU_SOURCE
2 | #include
3 | #include
4 | #include
5 |
6 | int main(int argc, char **argv)
7 | {
8 | int pfd[2];
9 | if (pipe(pfd) != 0) {
10 | perror("pipe()");
11 | return 1;
12 | }
13 |
14 | printf("pipe buffer is %i bytes\n", fcntl(pfd[0], F_GETPIPE_SZ));
15 | return 0;
16 | }
17 |
--------------------------------------------------------------------------------
/flags/.gitignore:
--------------------------------------------------------------------------------
1 | *.o
2 | flags
3 |
--------------------------------------------------------------------------------
/flags/flags.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #define FLAG_A 1
5 | #define FLAG_B 2
6 | #define FLAG_C 4
7 |
8 | int main(int argc, char **argv)
9 | {
10 | int i;
11 |
12 | srand(99); /* need arbitrary numbers */
13 | for (i = 0; i < 40; i++) {
14 | int v = (int)(rand() * 1.0 / RAND_MAX * 8);
15 |
16 | fprintf(stderr, "% 2d: ", v);
17 | /* this doesn't work:
18 | switch (1) {
19 | case v & FLAG_A: fprintf(stderr, "A "); break;
20 | case v & FLAG_B: fprintf(stderr, "B "); break;
21 | case v & FLAG_C: fprintf(stderr, "C "); break;
22 | }
23 | */
24 | /* but this does: */
25 | if (v & FLAG_A) fprintf(stderr, "A ");
26 | if (v & FLAG_B) fprintf(stderr, "B ");
27 | if (v & FLAG_C) fprintf(stderr, "C ");
28 | fprintf(stderr, "\n");
29 | }
30 | return 0;
31 | }
32 |
--------------------------------------------------------------------------------
/fork/fork.c:
--------------------------------------------------------------------------------
1 | /* public domain */
2 | #include
3 | #include
4 | #include
5 |
6 | int main (int argc, char **argv)
7 | {
8 | if (argc == 1) {
9 | fprintf(stderr, "USAGE: %s command --to --run -forked\n", argv[0]);
10 | return 1;
11 | }
12 |
13 | pid_t pid = fork();
14 | if (pid < 0) {
15 | perror("fork() failed");
16 | return 1;
17 | }
18 |
19 | if (pid > 0) return 0;
20 | if (!freopen("/dev/null", "r", stdin)) perror("/dev/null");
22 | if (!freopen("/dev/null", "w", stderr)) perror("2>/dev/null");
23 |
24 | execvp(argv[1], argv + 1);
25 | perror("exec() failed");
26 | return 1;
27 | }
28 |
--------------------------------------------------------------------------------
/fuse/nullfs/.gitignore:
--------------------------------------------------------------------------------
1 | nullfs
2 | *.o
3 |
--------------------------------------------------------------------------------
/fuse/nullfs/Makefile:
--------------------------------------------------------------------------------
1 | CFLAGS := $(shell pkg-config fuse --cflags)
2 | LDLIBS := $(shell pkg-config fuse --libs)
3 |
4 | nullfs: nullfs.o
5 |
6 | clean:
7 | rm -f nullfs *.o
8 |
--------------------------------------------------------------------------------
/fuse/nullfs/nullfs.c:
--------------------------------------------------------------------------------
1 | #define FUSE_USE_VERSION 26
2 |
3 | #include
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 |
20 |
21 | int nullfs_getattr(const char *path, struct stat *st)
22 | {
23 | return 0;
24 | }
25 |
26 | int nullfs_readlink(const char *path, char *target, size_t len)
27 | {
28 | return 1;
29 | }
30 |
31 | int nullfs_mknod(const char *path, mode_t mode, dev_t dev)
32 | {
33 | return 0;
34 | }
35 |
36 | int nullfs_mkdir(const char *path, mode_t mode)
37 | {
38 | return 0;
39 | }
40 |
41 | int nullfs_unlink(const char *path)
42 | {
43 | return 0;
44 | }
45 |
46 | int nullfs_rmdir(const char *path)
47 | {
48 | return 0;
49 | }
50 |
51 | int nullfs_symlink(const char *path, const char *target)
52 | {
53 | return 0;
54 | }
55 |
56 | int nullfs_rename(const char *oldpath, const char *newpath)
57 | {
58 | return 0;
59 | }
60 |
61 | int nullfs_link(const char *oldpath, const char *newpath)
62 | {
63 | return 0;
64 | }
65 |
66 | int nullfs_chmod(const char *path, mode_t mode)
67 | {
68 | return 0;
69 | }
70 |
71 | int nullfs_chown(const char *path, uid_t uid, gid_t gid)
72 | {
73 | return 0;
74 | }
75 |
76 | int nullfs_truncate(const char *path, off_t newsize)
77 | {
78 | return 0;
79 | }
80 |
81 | int nullfs_utimens(const char *path, const struct timespec tv[2])
82 | {
83 | return 0;
84 | }
85 |
86 | int nullfs_open(const char *path, struct fuse_file_info *info)
87 | {
88 | return 0;
89 | }
90 |
91 | int nullfs_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *info)
92 | {
93 | return 0;
94 | }
95 |
96 | int nullfs_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *info)
97 | {
98 | return 0;
99 | }
100 |
101 | int nullfs_statfs(const char *path, struct statvfs *st)
102 | {
103 | return -EINVAL;
104 | }
105 |
106 | int nullfs_flush(const char *path, struct fuse_file_info *info)
107 | {
108 | return 0;
109 | }
110 |
111 | int nullfs_release(const char *path, struct fuse_file_info *info)
112 | {
113 | return 0;
114 | }
115 |
116 | int nullfs_fsync(const char *path, int datasync, struct fuse_file_info *info)
117 | {
118 | return 0;
119 | }
120 |
121 | int nullfs_setxattr(const char *path, const char *name, const char *value, size_t size, int flags)
122 | {
123 | return 0;
124 | }
125 |
126 | int nullfs_getxattr(const char *path, const char *name, char *value, size_t size)
127 | {
128 | return 1;
129 | }
130 |
131 | int nullfs_listxattr(const char *path, char *list, size_t size)
132 | {
133 | return 1;
134 | }
135 |
136 | int nullfs_removexattr(const char *path, const char *name)
137 | {
138 | return 0;
139 | }
140 |
141 | int nullfs_opendir(const char *path, struct fuse_file_info *info)
142 | {
143 | return 0;
144 | }
145 |
146 | int nullfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *info)
147 | {
148 | return 0;
149 | }
150 |
151 | int nullfs_releasedir(const char *path, struct fuse_file_info *info)
152 | {
153 | return 0;
154 | }
155 |
156 | int nullfs_fsyncdir(const char *path, int datasync, struct fuse_file_info *info)
157 | {
158 | return 0;
159 | }
160 |
161 | void *nullfs_init(struct fuse_conn_info *conn)
162 | {
163 | return NULL;
164 | }
165 |
166 | void nullfs_destroy(void *userdata)
167 | {
168 | }
169 |
170 | int nullfs_access(const char *path, int mask)
171 | {
172 | return 0;
173 | }
174 |
175 | int nullfs_create(const char *path, mode_t mode, struct fuse_file_info *info)
176 | {
177 | return 0;
178 | }
179 |
180 | int nullfs_ftruncate(const char *path, off_t offset, struct fuse_file_info *info)
181 | {
182 | return 0;
183 | }
184 |
185 | int nullfs_fgetattr(const char *path, struct stat *statbuf, struct fuse_file_info *info)
186 | {
187 | return 0;
188 | }
189 |
190 | struct fuse_operations nullfs_oper = {
191 | .getattr = nullfs_getattr,
192 | .readlink = nullfs_readlink,
193 | .getdir = NULL, /* deprecated */
194 | .mknod = nullfs_mknod,
195 | .mkdir = nullfs_mkdir,
196 | .unlink = nullfs_unlink,
197 | .rmdir = nullfs_rmdir,
198 | .symlink = nullfs_symlink,
199 | .rename = nullfs_rename,
200 | .link = nullfs_link,
201 | .chmod = nullfs_chmod,
202 | .chown = nullfs_chown,
203 | .truncate = nullfs_truncate,
204 |
205 | .utime = NULL,
206 | .utimens = nullfs_utimens,
207 | .open = nullfs_open,
208 | .read = nullfs_read,
209 | .write = nullfs_write,
210 | .statfs = nullfs_statfs,
211 | .flush = nullfs_flush,
212 | .release = nullfs_release,
213 | .fsync = nullfs_fsync,
214 | .setxattr = nullfs_setxattr,
215 | .getxattr = nullfs_getxattr,
216 | .listxattr = nullfs_listxattr,
217 | .removexattr = nullfs_removexattr,
218 | .opendir = nullfs_opendir,
219 | .readdir = nullfs_readdir,
220 | .releasedir = nullfs_releasedir,
221 | .fsyncdir = nullfs_fsyncdir,
222 | .init = nullfs_init,
223 | .destroy = nullfs_destroy,
224 | .access = nullfs_access,
225 | .create = nullfs_create,
226 | .ftruncate = nullfs_ftruncate,
227 | .fgetattr = nullfs_fgetattr,
228 | };
229 |
230 | int main(int argc, char **argv)
231 | {
232 | int rc = fuse_main(argc, argv, &nullfs_oper, NULL);
233 | return rc;
234 | }
235 |
--------------------------------------------------------------------------------
/insist/.gitignore:
--------------------------------------------------------------------------------
1 | main
2 | traditional
3 | modern
4 |
--------------------------------------------------------------------------------
/insist/Makefile:
--------------------------------------------------------------------------------
1 | all: main
2 | clean:
3 | rm -f main traditional modern *.o
4 |
5 | main: main.o
6 |
7 | .PHONY: all clean
8 |
--------------------------------------------------------------------------------
/insist/insist.h:
--------------------------------------------------------------------------------
1 | #ifndef INSIST_DOT_H
2 | #define INSIST_DOT_H
3 |
4 | /*
5 | Copyright (c) 2016, James Hunt
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in
15 | all copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | */
25 |
26 | #include
27 | #include
28 | #include
29 |
30 | /* ASSERTION_OUTPUT_STREAM defines the FILE* that the `insist()` macro will
31 | print error messages to, before exiting. If ASSERTION_PRINT_ALWAYS is also
32 | defined, this stream will be used to print successes as well. */
33 | #ifndef ASSERTION_OUTPUT_STREAM
34 | #define ASSERTION_OUTPUT_STREAM stderr
35 | #endif
36 |
37 | /* ASSERTION_FAIL_EXIT_CODE defines the exit code value that the `insist()`
38 | macro will exit with, in the event of an assertion failure. */
39 | #ifndef ASSERTION_FAIL_EXIT_CODE
40 | #define ASSERTION_FAIL_EXIT_CODE 7
41 | #endif
42 |
43 | /* Two (2) #define's control the behavior of the `insist()` macro:
44 |
45 | ASSERTION_DEBUGGING causes the function (__func__), file (__FILE__) and
46 | line number (__LINE__) of the assertion call to be printed with the
47 | failure message, which can be useful for tracking down flaky assertions.
48 |
49 | ASSERTION_PRINT_ALWAYS causes `insist()` to *always* print a diagnostic
50 | (to ASSERTION_OUTPUT_STREAM), regardless of success / failure. The
51 | program will not abort on success, of course, but the messages may prove
52 | useful for output verification during testing.
53 |
54 | Note that ASSERTION_PRINT_ALWAYS is only checked if ASSERTION_DEBUGGING
55 | is defined. That is, you cannot get the "print always" behavior without
56 | the "debugging" behavior.
57 | */
58 | #if !defined(ASSERTION_DEBUGGING)
59 | # define insist(test,msg) ({ \
60 | if (!(test)) { \
61 | fprintf((ASSERTION_OUTPUT_STREAM), "ASSERTION FAILED: " msg " (`" #test "` was false)\n"); \
62 | exit((ASSERTION_FAIL_EXIT_CODE)); \
63 | } \
64 | })
65 | #elif !defined(ASSERTION_PRINT_ALWAYS)
66 | # define insist(test,msg) ({ \
67 | if (!(test)) { \
68 | void *buffer[128]; int size; \
69 | fprintf((ASSERTION_OUTPUT_STREAM), "ASSERTION FAILED: " msg " (`" #test "` was false, in %s(), at %s:%i)\n", __func__, __FILE__, __LINE__); \
70 | size = backtrace(buffer, size); \
71 | fprintf((ASSERTION_OUTPUT_STREAM), "%i frames\n", size); \
72 | backtrace_symbols_fd(buffer, size, fileno(ASSERTION_OUTPUT_STREAM)); \
73 | fprintf((ASSERTION_OUTPUT_STREAM), "done\n"); \
74 | exit((ASSERTION_FAIL_EXIT_CODE)); \
75 | } \
76 | })
77 | #else
78 | # define insist(test,msg) ({ \
79 | if (!(test)) { \
80 | void *buffer[128]; int size; \
81 | fprintf((ASSERTION_OUTPUT_STREAM), "ASSERTION FAILED: " msg " (`" #test "` was false, in %s(), at %s:%i)\n", __func__, __FILE__, __LINE__); \
82 | size = backtrace(buffer, size); \
83 | backtrace_symbols_fd(buffer, size, fileno(ASSERTION_OUTPUT_STREAM)); \
84 | fprintf((ASSERTION_OUTPUT_STREAM), "done\n"); \
85 | exit((ASSERTION_FAIL_EXIT_CODE)); \
86 | } else { \
87 | fprintf((ASSERTION_OUTPUT_STREAM), "assertion succeeded: " msg " (`" #test "` was true, in %s(), at %s:%i)\n", __func__, __FILE__, __LINE__); \
88 | } \
89 | })
90 | #endif
91 |
92 | #endif
93 |
--------------------------------------------------------------------------------
/insist/main.c:
--------------------------------------------------------------------------------
1 | #define ASSERTION_OUTPUT_STREAM stdout
2 | #define ASSERTION_FAIL_EXIT_CODE 23
3 | #define ASSERTION_DEBUGGING
4 | #define ASSERTION_PRINT_ALWAYS
5 | #include "insist.h"
6 | #include
7 |
8 | int main(int argc, char **argv) {
9 | int x = 421;
10 | insist(x == 42, "x should be the answer to life, the universe, and everything");
11 | return 0;
12 | }
13 |
--------------------------------------------------------------------------------
/insist/modern.c:
--------------------------------------------------------------------------------
1 | #define ASSERTION_DEBUGGING
2 | #include "insist.h"
3 | #include
4 |
5 | int _strlen(const char *s)
6 | {
7 | insist(s != NULL, "_strlen(NULL) is undefined");
8 |
9 | int n = 0;
10 | while (*s++)
11 | n++;
12 |
13 | return n;
14 | }
15 |
16 | void thunk() {
17 | _strlen(NULL); /* should fail */
18 | }
19 |
20 | int main(int argc, char **argv)
21 | {
22 | thunk();
23 | thunk();
24 | thunk();
25 | return 0;
26 | }
27 |
--------------------------------------------------------------------------------
/insist/modern.s:
--------------------------------------------------------------------------------
1 | .section __TEXT,__text,regular,pure_instructions
2 | .macosx_version_min 10, 11
3 | .globl __strlen
4 | .align 4, 0x90
5 | __strlen: ## @_strlen
6 | .cfi_startproc
7 | ## BB#0:
8 | pushq %rbp
9 | Ltmp0:
10 | .cfi_def_cfa_offset 16
11 | Ltmp1:
12 | .cfi_offset %rbp, -16
13 | movq %rsp, %rbp
14 | Ltmp2:
15 | .cfi_def_cfa_register %rbp
16 | subq $1088, %rsp ## imm = 0x440
17 | movq ___stack_chk_guard@GOTPCREL(%rip), %rax
18 | movq (%rax), %rax
19 | movq %rax, -8(%rbp)
20 | movq %rdi, -1048(%rbp)
21 | cmpq $0, -1048(%rbp)
22 | jne LBB0_2
23 | ## BB#1:
24 | leaq L_.str(%rip), %rsi
25 | leaq L___func__._strlen(%rip), %rdx
26 | leaq L_.str.1(%rip), %rcx
27 | movl $7, %r8d
28 | movq ___stderrp@GOTPCREL(%rip), %rax
29 | movq (%rax), %rdi
30 | movb $0, %al
31 | callq _fprintf
32 | leaq -1040(%rbp), %rdi
33 | movl -1052(%rbp), %esi
34 | movl %eax, -1060(%rbp) ## 4-byte Spill
35 | callq _backtrace
36 | leaq L_.str.2(%rip), %rsi
37 | movq ___stderrp@GOTPCREL(%rip), %rcx
38 | movl %eax, -1052(%rbp)
39 | movq (%rcx), %rdi
40 | movl -1052(%rbp), %edx
41 | movb $0, %al
42 | callq _fprintf
43 | movq ___stderrp@GOTPCREL(%rip), %rcx
44 | leaq -1040(%rbp), %rdi
45 | movl -1052(%rbp), %esi
46 | movq (%rcx), %rcx
47 | movq %rdi, -1072(%rbp) ## 8-byte Spill
48 | movq %rcx, %rdi
49 | movl %eax, -1076(%rbp) ## 4-byte Spill
50 | movl %esi, -1080(%rbp) ## 4-byte Spill
51 | callq _fileno
52 | movq -1072(%rbp), %rdi ## 8-byte Reload
53 | movl -1080(%rbp), %esi ## 4-byte Reload
54 | movl %eax, %edx
55 | callq _backtrace_symbols_fd
56 | leaq L_.str.3(%rip), %rsi
57 | movq ___stderrp@GOTPCREL(%rip), %rcx
58 | movq (%rcx), %rdi
59 | movb $0, %al
60 | callq _fprintf
61 | movl $7, %edi
62 | movl %eax, -1084(%rbp) ## 4-byte Spill
63 | callq _exit
64 | LBB0_2:
65 | movl $0, -1056(%rbp)
66 | LBB0_3: ## =>This Inner Loop Header: Depth=1
67 | movq -1048(%rbp), %rax
68 | movq %rax, %rcx
69 | addq $1, %rcx
70 | movq %rcx, -1048(%rbp)
71 | cmpb $0, (%rax)
72 | je LBB0_5
73 | ## BB#4: ## in Loop: Header=BB0_3 Depth=1
74 | movl -1056(%rbp), %eax
75 | addl $1, %eax
76 | movl %eax, -1056(%rbp)
77 | jmp LBB0_3
78 | LBB0_5:
79 | movq ___stack_chk_guard@GOTPCREL(%rip), %rax
80 | movl -1056(%rbp), %ecx
81 | movq (%rax), %rax
82 | cmpq -8(%rbp), %rax
83 | movl %ecx, -1088(%rbp) ## 4-byte Spill
84 | jne LBB0_7
85 | ## BB#6:
86 | movl -1088(%rbp), %eax ## 4-byte Reload
87 | addq $1088, %rsp ## imm = 0x440
88 | popq %rbp
89 | retq
90 | LBB0_7:
91 | callq ___stack_chk_fail
92 | .cfi_endproc
93 |
94 | .globl _thunk
95 | .align 4, 0x90
96 | _thunk: ## @thunk
97 | .cfi_startproc
98 | ## BB#0:
99 | pushq %rbp
100 | Ltmp3:
101 | .cfi_def_cfa_offset 16
102 | Ltmp4:
103 | .cfi_offset %rbp, -16
104 | movq %rsp, %rbp
105 | Ltmp5:
106 | .cfi_def_cfa_register %rbp
107 | subq $16, %rsp
108 | xorl %eax, %eax
109 | movl %eax, %edi
110 | callq __strlen
111 | movl %eax, -4(%rbp) ## 4-byte Spill
112 | addq $16, %rsp
113 | popq %rbp
114 | retq
115 | .cfi_endproc
116 |
117 | .globl _main
118 | .align 4, 0x90
119 | _main: ## @main
120 | .cfi_startproc
121 | ## BB#0:
122 | pushq %rbp
123 | Ltmp6:
124 | .cfi_def_cfa_offset 16
125 | Ltmp7:
126 | .cfi_offset %rbp, -16
127 | movq %rsp, %rbp
128 | Ltmp8:
129 | .cfi_def_cfa_register %rbp
130 | subq $16, %rsp
131 | movl $0, -4(%rbp)
132 | movl %edi, -8(%rbp)
133 | movq %rsi, -16(%rbp)
134 | callq _thunk
135 | callq _thunk
136 | callq _thunk
137 | xorl %eax, %eax
138 | addq $16, %rsp
139 | popq %rbp
140 | retq
141 | .cfi_endproc
142 |
143 | .section __TEXT,__cstring,cstring_literals
144 | L_.str: ## @.str
145 | .asciz "ASSERTION FAILED: _strlen(NULL) is undefined (`s != NULL` was false, in %s(), at %s:%i)\n"
146 |
147 | L___func__._strlen: ## @__func__._strlen
148 | .asciz "_strlen"
149 |
150 | L_.str.1: ## @.str.1
151 | .asciz "modern.c"
152 |
153 | L_.str.2: ## @.str.2
154 | .asciz "%i frames\n"
155 |
156 | L_.str.3: ## @.str.3
157 | .asciz "done\n"
158 |
159 |
160 | .subsections_via_symbols
161 |
--------------------------------------------------------------------------------
/insist/traditional.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | int _strlen(const char *s)
5 | {
6 | assert(s != NULL);
7 |
8 | int n = 0;
9 | while (*s++)
10 | n++;
11 |
12 | return n;
13 | }
14 |
15 | int main(int argc, char **argv)
16 | {
17 | _strlen(NULL); /* should fail */
18 | return 0;
19 | }
20 |
--------------------------------------------------------------------------------
/knave/.gitignore:
--------------------------------------------------------------------------------
1 | knave
2 | wastrel
3 |
--------------------------------------------------------------------------------
/knave/Makefile:
--------------------------------------------------------------------------------
1 | CFLAGS := -Wall -g2 -O0 -Wno-unused
2 |
3 | BINARIES :=
4 | BINARIES += knave
5 |
6 | all: $(BINARIES)
7 | ln -sf knave wastrel
8 | clean:
9 | rm -f *.o $(BINARIES)
10 |
--------------------------------------------------------------------------------
/knave/knave.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | int main(int argc, char **argv)
6 | {
7 | char *bin = strrchr(argv[0], '/');
8 | if (!bin) bin = argv[0];
9 | else bin++;
10 |
11 | if (strcmp(bin, "wastrel") == 0) {
12 | fprintf(stderr, "wastrel\n");
13 | int n = (argc < 2 ? 1024 : atoi(argv[1])) * 1024;
14 | char **m = calloc(n / 64, sizeof(char **));
15 |
16 | fprintf(stderr, "allocating %u 64k blocks (%uM)\n", n / 64, n / 1024);
17 | int i;
18 | for (i = 0; i < n / 64; i++) {
19 | m[i] = calloc(64 * 1024, sizeof(char));
20 | memset(m, rand(), 64 * 1024);
21 | }
22 |
23 | // FIXME: can we just use a single sbrk() call to extend the heap?
24 |
25 | } else {
26 | fprintf(stderr, "unknown tool '%s'\n", bin);
27 | return 1;
28 | }
29 | return 0;
30 | }
31 |
--------------------------------------------------------------------------------
/lexer-ll/NOTES:
--------------------------------------------------------------------------------
1 | The L parser works kind of like lex, but doesn't support a lot of things, and it aims to be simple to parse and reason about.
2 |
3 | The language is basically:
4 |
5 |
6 | spec: [preamble] '^----$' rules '^----$' [postamble]
7 | rules:
8 | | rules rule;
9 | rule: regex
10 |
11 | preamble and postamble are copied verbatim, with no introspection.
12 |
13 |
--------------------------------------------------------------------------------
/lexer-ll/bql.ll:
--------------------------------------------------------------------------------
1 | /* c pre-amble */
2 | #define TOKEN_VAR 1
3 | #define TOKEN_QSTRING 2
4 | ----
5 | a|b|c|x|y|z
6 | recognize(TOKEN_VAR, NULL, NULL);
7 |
8 | ".*"
9 | recognize(TOKEN_QSTRING,
10 | lexeme(1, ll.lexeme.len - 1),
11 | ll.lexeme.len - 2);
12 | ----
13 | /* c post-amble */
14 | #include
15 | void done() {
16 | printf("all done!\n");
17 | }
18 |
--------------------------------------------------------------------------------
/lexer-ll/bql.ll.c:
--------------------------------------------------------------------------------
1 | /* c pre-amble */
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | void * lex_open(const char *);
11 | void lex_close(void *);
12 | int lex_token(void *);
13 |
14 | typedef struct {
15 | const char *file;
16 |
17 | char *source;
18 | size_t len;
19 |
20 | size_t line;
21 | size_t column;
22 |
23 | size_t dot;
24 | } lexer;
25 |
26 | #define LEXER(v) ((lexer *)(v))
27 |
28 | void *
29 | lex_open(const char *file)
30 | {
31 | int fd = -1;
32 | void *lx = NULL;
33 |
34 | off_t size;
35 | ssize_t nread;
36 |
37 | assert(file != NULL);
38 |
39 | lx = malloc(sizeof(lexer));
40 | if (!lx) goto failed;
41 |
42 | fd = open(file, O_RDONLY);
43 | if (fd < 0) goto failed;
44 |
45 | size = lseek(fd, 0, SEEK_END);
46 | if (size < 0) goto failed;
47 |
48 | if (lseek(fd, 0, SEEK_SET) < 0)
49 | goto failed;
50 |
51 | LEXER(lx)->len = size;
52 | LEXER(lx)->source = malloc(LEXER(lx)->len);
53 | if (!LEXER(lx)->source) goto failed;
54 |
55 | nread = read(fd, LEXER(lx)->source, LEXER(lx)->len);
56 | if (nread < 0) goto failed;
57 | if ((size_t)nread != LEXER(lx)->len) {
58 | errno = EIO;
59 | goto failed;
60 | }
61 |
62 | LEXER(lx)->line = LEXER(lx)->column = 1;
63 | LEXER(lx)->dot = 0;
64 |
65 | close(fd);
66 | return LEXER(lx);
67 |
68 | failed:
69 | if (fd >= 0) close(fd);
70 | lex_close(lx);
71 | return NULL;
72 | }
73 |
74 | void
75 | lex_close(void *lx) {
76 | if (!lx) return;
77 | free(LEXER(lx)->source);
78 | free(LEXER(lx));
79 | }
80 |
81 | const char *
82 | lex_lexeme(void *lx)
83 | {
84 | }
85 |
86 | int
87 | lex_token(void *lx)
88 | {
89 | }
90 |
91 | int
92 | lex(void *lx)
93 | {
94 | if (LEXER(lx)->dot == LEXER(lx)->len)
95 | return 0;
96 | #define recognize(t,l,u)
97 | #undef recognize
98 |
99 | LEXER(lx)->dot++;
100 | return 1;
101 | }
102 |
103 | /* c post-amble */
104 |
--------------------------------------------------------------------------------
/lexer-ll/bql.ll.h:
--------------------------------------------------------------------------------
1 | #ifndef REALLY_LONG_IDENTIFIER_FIXME
2 | #define REALLY_LONG_IDENTIFIER_FIXME
3 |
4 | void * lex_open(const char *);
5 | void lex_close(void *);
6 | int lex(void *);
7 |
8 | const char * lex_lexeme(void *);
9 | int lex_token(void *);
10 |
11 | #endif
12 |
--------------------------------------------------------------------------------
/lexer-ll/bql.regex:
--------------------------------------------------------------------------------
1 | select|from|where|=|(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z)(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|0|1|2|3|4|5|6|7|8|9)*
2 |
--------------------------------------------------------------------------------
/lexer-ll/ll.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 | use strict;
3 | use warnings;
4 |
5 | my (@pre, @post, @rules);
6 | my $rule = undef;
7 | my $section = 1;
8 | while (<>) {
9 | chomp;
10 | if (m/^----+$/) {
11 | $section++;
12 | die "syntax error (too many sections)\n" if $section > 3;
13 | next;
14 | }
15 | if ($section == 1) {
16 | push @pre, "$_\n";
17 |
18 | } elsif ($section == 3) {
19 | push @rules, $rule if $rule;
20 | $rule = undef;
21 | push @post, "$_\n";
22 |
23 | } else {
24 | if (m/^\S/) {
25 | push @rules, $rule if $rule;
26 | $rule = { regex => $_, body => [] };
27 |
28 | } else {
29 | push @{$rule->{body}}, "$_\n";
30 | }
31 | }
32 | }
33 | die "syntax error (no preamble)" if $section == 1;
34 | die "syntax error (no postamble)" if $section == 2;
35 |
36 | my $spec = {
37 | pre => join('', @pre),
38 | post => join('', @post),
39 | rules => [ map {
40 | $_->{body} = join('', @{$_->{body}});
41 | $_;
42 | } @rules ]
43 | };
44 |
45 | use Data::Dumper;
46 | print Dumper($spec);
47 |
48 | my (@starts, @states);
49 |
50 | for my $rule (@rules) {
51 | my $state = @states;
52 |
53 | $states[$state] = {};
54 | }
55 |
56 | print Dumper(\@starts, \@states);
57 |
58 |
--------------------------------------------------------------------------------
/lexer-ll/ll1.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 | use strict;
3 | use warnings;
4 |
5 | my (@pre, @post, @rules);
6 | my $rule = undef;
7 | my $section = 1;
8 | while (<>) {
9 | chomp;
10 | if (m/^----+$/) {
11 | $section++;
12 | die "syntax error (too many sections)\n" if $section > 3;
13 | next;
14 | }
15 | if ($section == 1) {
16 | push @pre, "$_\n";
17 |
18 | } elsif ($section == 3) {
19 | push @rules, $rule if $rule;
20 | $rule = undef;
21 | push @post, "$_\n";
22 |
23 | } else {
24 | if (m/^\S/) {
25 | push @rules, $rule if $rule;
26 | $rule = { regex => $_, body => [] };
27 |
28 | } else {
29 | push @{$rule->{body}}, "$_\n";
30 | }
31 | }
32 | }
33 | die "syntax error (no preamble)" if $section == 1;
34 | die "syntax error (no postamble)" if $section == 2;
35 |
36 | my $spec = {
37 | pre => join('', @pre),
38 | post => join('', @post),
39 | rules => [ map {
40 | $_->{body} = join('', @{$_->{body}});
41 | $_;
42 | } @rules ]
43 | };
44 |
45 | use Data::Dumper;
46 | print Dumper($spec);
47 |
--------------------------------------------------------------------------------
/lexer-ll/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include "bql.ll.h"
3 |
4 | int main(int argc, char **argv) {
5 | void *state;
6 |
7 | state = lex_open("l/bql.ll");
8 | if (!state) {
9 | perror("lex_open");
10 | return 1;
11 | }
12 |
13 | while (lex(state)) {
14 | // ...
15 | }
16 |
17 | lex_close(state);
18 | return 0;
19 | }
20 |
--------------------------------------------------------------------------------
/malloc/.gitignore:
--------------------------------------------------------------------------------
1 | *.o
2 | *.so
3 | victim
4 |
--------------------------------------------------------------------------------
/malloc/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # fmalloc -
3 | #
4 |
5 | all: victim libfmalloc1.so
6 |
7 | victim: victim.c
8 | $(CC) -o $@ $+
9 |
10 | libfmalloc1.so: fmalloc1.o
11 | $(CC) -shared -Wl,-soname,fmalloc1 -o $@ $+
12 |
13 | %.o: %.c
14 | $(CC) -fPIC -c -o $@ $+
15 |
16 | clean:
17 | rm -f fmalloc1.o
18 | rm -f victim
19 | rm -f libfmalloc.so
20 |
--------------------------------------------------------------------------------
/malloc/fmalloc1.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #define puts(x) write(2, (x), strlen(x))
9 |
10 | static struct {
11 | int init;
12 | int left;
13 | } FMALLOC = {0};
14 | static int N = -1;
15 |
16 | static inline void __init(void)
17 | {
18 | if (!FMALLOC.init) {
19 | char *s = getenv("MALLOC_OK");
20 | FMALLOC.left = atoi(s ? s : "-1");
21 |
22 | FMALLOC.init = 1;
23 | }
24 | }
25 |
26 | static inline int __check(void)
27 | {
28 | if (FMALLOC.left == 0) {
29 | char *sigil = getenv("MALLOC_FS_SIGIL");
30 | if (sigil)
31 | unlink(sigil);
32 | return 0;
33 | }
34 |
35 | FMALLOC.left--;
36 | return 1;
37 | }
38 |
39 | static inline void* __malloc(size_t n)
40 | {
41 | if (!n)
42 | return NULL;
43 |
44 | void *p = sbrk(0);
45 | void *r = sbrk(n);
46 | if (r == (void*) -1)
47 | return NULL;
48 |
49 | assert(p == r); /* not thread-safe */
50 | return p;
51 | }
52 |
53 | void* malloc(size_t n)
54 | {
55 | __init();
56 | return __check() ? __malloc(n) : NULL;
57 | }
58 |
59 | void* calloc(size_t n, size_t each)
60 | {
61 | void *m = malloc(n * each);
62 | if (m)
63 | memset(m, 0, n * each);
64 | return m;
65 | }
66 |
67 | void *realloc(void *p, size_t n)
68 | {
69 | return NULL;
70 | }
71 |
--------------------------------------------------------------------------------
/malloc/victim.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | int main (int argc, char **argv)
5 | {
6 | if (malloc(24) == NULL)
7 | fprintf(stderr, "first malloc failed\n");
8 | if (malloc(24) == NULL)
9 | fprintf(stderr, "second malloc failed\n");
10 | if (malloc(24) == NULL)
11 | fprintf(stderr, "third malloc failed\n");
12 |
13 | if (calloc(48, sizeof(char)) == NULL)
14 | fprintf(stderr, "first calloc failed\n");
15 | if (calloc(48, sizeof(char)) == NULL)
16 | fprintf(stderr, "second calloc failed\n");
17 | if (calloc(48, sizeof(char)) == NULL)
18 | fprintf(stderr, "third calloc failed\n");
19 | return 0;
20 | }
21 |
--------------------------------------------------------------------------------
/matrix/matrix.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 | use strict;
3 | use warnings;
4 | sub max {
5 | return $_[0] > $_[1] ? $_[0] : $_[1];
6 | }
7 |
8 | sub similarity {
9 | my ($a, $b, $n) = (0, 0, 0);
10 | my %a = map { $_ => 1 } @{$_[0]};
11 | delete $a{$_} for keys %{$_[2]};
12 | $a = scalar keys %a;
13 | for (@{$_[1]}) {
14 | next if $_[2]->{$_};
15 | $b++;
16 | $n++ if $a{$_};
17 | }
18 | return $n / max($a, $b);
19 | }
20 |
21 | my %D;
22 | while (<>) {
23 | chomp;
24 | my ($name, @releases) = split /\s+/, $_;
25 | $D{$name} = \@releases;
26 | }
27 |
28 | my $addons = { 'os-conf' => 1 };
29 | my @names = sort keys %D;
30 | for (my $i = 0; $i < @names; $i++) {
31 | next unless $names[$i];
32 | my $set = [$names[$i]];
33 | for (my $j = $i + 1; $j < @names; $j++) {
34 | if (similarity($D{$names[$i]}, $D{$names[$j]}, $addons) > 0.66) {
35 | push @$set, $names[$j];
36 | $names[$j] = undef;
37 | }
38 | }
39 | print "SET:\n";
40 | print " - $_\n" for @$set;
41 | print "\n\n";
42 | }
43 |
--------------------------------------------------------------------------------
/matrix/sets:
--------------------------------------------------------------------------------
1 | scs1 os-conf spring-cloud-broker
2 | ops-metrics1 os-conf cf-metrics
3 | gemfire1 os-conf GemFire GemFire-Broker GemFire-Broker-Registrar
4 | gemfire2 os-conf GemFire GemFire-Broker GemFire-Broker-Registrar
5 | gemfire3 os-conf GemFire GemFire-Broker GemFire-Broker-Registrar
6 | bind1 os-conf bind9
7 | cf1 os-conf cf cf-mysql cflinuxfs2-rootfs diego notifications-ui garden-runc mysql-backup mysql-monitoring service-backup etcd notifications cf-autoscaling push-apps-manager-release consul
8 | cf2 os-conf cf cf-mysql cflinuxfs2-rootfs diego notifications-ui garden-runc mysql-backup mysql-monitoring service-backup etcd notifications cf-autoscaling push-apps-manager-release
9 | concourse1 os-conf concourse garden-runc os-conf
10 | concourse2 os-conf concourse garden-runc os-conf
11 | concourse3 os-conf concourse garden-runc os-conf
12 |
--------------------------------------------------------------------------------
/mlock/.gitignore:
--------------------------------------------------------------------------------
1 | /mlock
2 |
--------------------------------------------------------------------------------
/mlock/mlock.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | int main(int argc, char **argv)
4 | {
5 | return (mlockall(MCL_CURRENT | MCL_FUTURE) == 0) ? 0 : 1;
6 | }
7 |
--------------------------------------------------------------------------------
/nacl/.gitignore:
--------------------------------------------------------------------------------
1 | /encrypt
2 | /decrypt
3 | /decrypt2
4 | /decrypt3
5 |
--------------------------------------------------------------------------------
/nacl/Makefile:
--------------------------------------------------------------------------------
1 | BINS :=
2 | BINS += encrypt
3 | BINS += decrypt
4 | BINS += decrypt2
5 | BINS += decrypt3
6 |
7 | default: $(BINS)
8 | clean:
9 | rm -f tweetnacl.o $(BINS:=.o) $(BINS)
10 |
11 | encrypt: encrypt.o tweetnacl.o
12 | decrypt: decrypt.o tweetnacl.o
13 | decrypt2: decrypt2.o tweetnacl.o
14 | decrypt3: decrypt3.o tweetnacl.o
15 |
--------------------------------------------------------------------------------
/nacl/common.h:
--------------------------------------------------------------------------------
1 | #ifndef COMMON_H
2 | #define COMMON_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include "tweetnacl.h"
10 |
11 | #define MESSAGE "There are strange things done in the midnight sun\n" \
12 | "By the men who toil for gold;\n" \
13 | "The Arctic trails have their secret tales\n" \
14 | "That would make your blood run cold;\n" \
15 | "The Northern Lights have seen queer sights,\n" \
16 | "But the queerest they ever did see\n" \
17 | "Was that night on the marge of Lake Lebarge\n" \
18 | "I cremated Sam McGee.\n"
19 | /* - Robert W. Service */
20 |
21 | #define MESSAGE_LEN 304 /* I counted */
22 |
23 | /* generated by crypto_box_keypair() */
24 | #define CLIENT_PUB "\xbc\x07\x9f\xfe\xf5\x09\x6b\x2b" \
25 | "\xfe\xd3\x8e\xdb\xe5\x26\xc0\xd3" \
26 | "\x57\xba\x79\x88\xbf\xff\x9e\x8e" \
27 | "\xea\x85\xcf\xd4\xcb\xb0\x7b\x3d"
28 |
29 | #define CLIENT_SEC "\x53\xb7\xab\xca\x19\x81\xca\xd7" \
30 | "\x6a\x87\x9d\xe3\xa3\x93\xd5\x73" \
31 | "\x84\x39\xa5\x10\x3e\x4d\xdf\xde" \
32 | "\xea\x19\x25\x01\xc9\xf3\x06\xf6"
33 |
34 |
35 | /* also generated by crypto_box_keypair() */
36 | #define SERVER_PUB "\xb0\x5c\x49\xda\xc9\xf6\xbc\x86" \
37 | "\xcf\x76\xe5\xbd\xca\xe8\x0e\x14" \
38 | "\x50\x03\xba\xbb\xa9\x4d\xfc\x6c" \
39 | "\x4c\x0a\xeb\xff\x9a\x5c\xba\x31"
40 |
41 | #define SERVER_SEC "\x22\x1b\x3e\x9c\xf7\xb0\x94\xdd" \
42 | "\xec\xdb\x58\x02\x4f\x54\xa6\xfa" \
43 | "\xc9\x0f\xa4\x86\x90\x80\xe7\xf5" \
44 | "\xec\xb9\x4d\x87\xdb\xb9\x1e\xfc"
45 |
46 | static void
47 | dump(const char *prefix, const uint8_t *buf, size_t len)
48 | {
49 | size_t i;
50 | printf("%s\n------------------------------------------------\n", prefix);
51 | for (i = 0; i < len; i++) {
52 | printf(" %02x%s", buf[i], (i+1) % 16 == 0 ? "\n" : "");
53 | }
54 | if (len % 16 != 0) printf("\n");
55 | printf("------------------------------------------------\n");
56 | }
57 |
58 | /* tweetnacl is a bring-your-own-randomness kinda lib */
59 | int
60 | randombytes(uint8_t *buf, size_t len)
61 | {
62 | FILE *in;
63 | int rc;
64 | in = fopen("/dev/urandom", "r");
65 | if (!in) return 1;
66 | rc = fread(buf, len, 1, in) == 1 ? 0 : 1;
67 | fclose(in);
68 | return rc;
69 | }
70 |
71 | #endif
72 |
--------------------------------------------------------------------------------
/nacl/decrypt.c:
--------------------------------------------------------------------------------
1 | #include "common.h"
2 |
3 | /* NOTE: this example is expected to fail, because I screwed up
4 | the padding. On purpose. Read the blog post for more:
5 |
6 | http://jameshunt.us/writings/nacl-padding.html
7 | */
8 | int main(int argc, char **argv)
9 | {
10 | int rc;
11 | uint8_t client_pub[32], client_sec[32];
12 | uint8_t server_pub[32], server_sec[32];
13 | uint8_t cipher[512], plain[512];
14 | uint8_t nonce[24];
15 |
16 | /* initialize memory */
17 | memset(cipher, 0, 512);
18 | memset(plain, 0, 512);
19 |
20 | /* "generate" nonce */
21 | memset(nonce, 0, 24);
22 |
23 | /* "generate" keys */
24 | memcpy(client_pub, CLIENT_PUB, 32);
25 | memcpy(client_sec, CLIENT_SEC, 32);
26 | memcpy(server_pub, SERVER_PUB, 32);
27 | memcpy(server_sec, SERVER_SEC, 32);
28 |
29 | /* assemble plaintext */
30 | memcpy(plain, MESSAGE, MESSAGE_LEN);
31 | dump("plaintext, before encryption", plain, MESSAGE_LEN);
32 |
33 | /* encipher message from client to server */
34 | rc = crypto_box(cipher, plain, MESSAGE_LEN,
35 | nonce, server_pub, client_sec);
36 | dump("ciphertext", cipher, MESSAGE_LEN);
37 | assert(rc == 0);
38 |
39 | /* erase all trace of plaintext */
40 | memset(plain, 0, 512);
41 |
42 | /* decipher message as server, using client's public key */
43 | rc = crypto_box_open(plain, cipher, MESSAGE_LEN,
44 | nonce, client_pub, server_sec);
45 | dump("plaintext, after decryption", plain, MESSAGE_LEN);
46 | assert(rc == 0);
47 |
48 | return 0;
49 | }
50 |
--------------------------------------------------------------------------------
/nacl/decrypt2.c:
--------------------------------------------------------------------------------
1 | #include "common.h"
2 |
3 | /* NOTE: this example is expected to fail, because I screwed up
4 | the padding. On purpose. Read the blog post for more:
5 |
6 | http://jameshunt.us/writings/nacl-padding.html
7 | */
8 |
9 | int main(int argc, char **argv)
10 | {
11 | int rc;
12 | uint8_t client_pub[32], client_sec[32];
13 | uint8_t server_pub[32], server_sec[32];
14 | uint8_t cipher[512], plain[512];
15 | uint8_t nonce[24];
16 |
17 | /* initialize memory */
18 | memset(cipher, 0, 512);
19 | memset(plain, 0, 512);
20 |
21 | /* "generate" nonce */
22 | memset(nonce, 0, 24);
23 |
24 | /* "generate" keys */
25 | memcpy(client_pub, CLIENT_PUB, 32);
26 | memcpy(client_sec, CLIENT_SEC, 32);
27 | memcpy(server_pub, SERVER_PUB, 32);
28 | memcpy(server_sec, SERVER_SEC, 32);
29 |
30 | /* assemble plaintext */
31 | memset(plain, 0, 32); /* first 32 octest are ZERO */
32 | memcpy(plain+32, MESSAGE, MESSAGE_LEN); /* then comes the real data */
33 | dump("plaintext, before encryption", plain, MESSAGE_LEN+32);
34 |
35 | /* encipher message from client to server */
36 | rc = crypto_box(cipher, plain, MESSAGE_LEN+32,
37 | nonce, server_pub, client_sec);
38 | dump("ciphertext", cipher, MESSAGE_LEN);
39 | assert(rc == 0);
40 |
41 | /* erase all trace of plaintext */
42 | memset(plain, 0, 512);
43 |
44 | /* decipher message as server, using client's public key */
45 | rc = crypto_box_open(plain, cipher, MESSAGE_LEN+32,
46 | nonce, client_pub, server_sec);
47 | dump("plaintext, after decryption", plain, MESSAGE_LEN+32);
48 | assert(rc == 0);
49 | assert(memcmp(MESSAGE, plain, MESSAGE_LEN) == 0);
50 |
51 | plain[MESSAGE_LEN+1] = '\0';
52 | printf("%s\n", plain);
53 |
54 | return 0;
55 | }
56 |
--------------------------------------------------------------------------------
/nacl/decrypt3.c:
--------------------------------------------------------------------------------
1 | #include "common.h"
2 |
3 | /* NOTE: this example will work! Read the blog post for more:
4 |
5 | http://jameshunt.us/writings/nacl-padding.html
6 | */
7 |
8 | int main(int argc, char **argv)
9 | {
10 | int rc;
11 | uint8_t client_pub[32], client_sec[32];
12 | uint8_t server_pub[32], server_sec[32];
13 | uint8_t cipher[512], plain[512];
14 | uint8_t nonce[24];
15 |
16 | /* initialize memory */
17 | memset(cipher, 0, 512);
18 | memset(plain, 0, 512);
19 |
20 | /* "generate" nonce */
21 | memset(nonce, 0, 24);
22 |
23 | /* "generate" keys */
24 | memcpy(client_pub, CLIENT_PUB, 32);
25 | memcpy(client_sec, CLIENT_SEC, 32);
26 | memcpy(server_pub, SERVER_PUB, 32);
27 | memcpy(server_sec, SERVER_SEC, 32);
28 |
29 | /* assemble plaintext */
30 | memset(plain, 0, 32); /* first 32 octest are ZERO */
31 | memcpy(plain+32, MESSAGE, MESSAGE_LEN); /* then comes the real data */
32 | dump("plaintext, before encryption", plain, MESSAGE_LEN+32);
33 |
34 | /* encipher message from client to server */
35 | rc = crypto_box(cipher, plain, MESSAGE_LEN+32,
36 | nonce, server_pub, client_sec);
37 | dump("ciphertext", cipher, MESSAGE_LEN+32);
38 | assert(rc == 0);
39 |
40 | /* erase all trace of plaintext */
41 | memset(plain, 0, 512);
42 |
43 | /* decipher message as server, using client's public key */
44 | rc = crypto_box_open(plain, cipher, MESSAGE_LEN+32,
45 | nonce, client_pub, server_sec);
46 | assert(rc == 0);
47 | memmove(plain, plain+32, MESSAGE_LEN);
48 | dump("plaintext, after decryption", plain, MESSAGE_LEN);
49 | assert(memcmp(MESSAGE, plain, MESSAGE_LEN) == 0);
50 |
51 | plain[MESSAGE_LEN] = '\0';
52 | printf("\n%s\n", plain);
53 |
54 | return 0;
55 | }
56 |
--------------------------------------------------------------------------------
/nacl/encrypt.c:
--------------------------------------------------------------------------------
1 | #include "common.h"
2 |
3 | /* NOTE: this example is expected "succeeds", but without attempting
4 | to decrypt the resulting ciphertext, we can't quite count it
5 | a success just yet. Read the blog post for more:
6 |
7 | http://jameshunt.us/writings/nacl-padding.html
8 | */
9 |
10 | int main(int argc, char **argv)
11 | {
12 | int rc;
13 | uint8_t client_pub[32], client_sec[32];
14 | uint8_t server_pub[32], server_sec[32];
15 | uint8_t cipher[512], plain[512];
16 | uint8_t nonce[24];
17 |
18 | /* initialize memory */
19 | memset(cipher, 0, 512);
20 | memset(plain, 0, 512);
21 |
22 | /* "generate" nonce */
23 | memset(nonce, 0, 24);
24 |
25 | /* "generate" keys */
26 | memcpy(client_pub, CLIENT_PUB, 32);
27 | memcpy(client_sec, CLIENT_SEC, 32);
28 | memcpy(server_pub, SERVER_PUB, 32);
29 | memcpy(server_sec, SERVER_SEC, 32);
30 |
31 | /* assemble plaintext */
32 | memcpy(plain, MESSAGE, MESSAGE_LEN);
33 | dump("plaintext, before encryption", plain, MESSAGE_LEN);
34 |
35 | /* encipher message from client to server */
36 | rc = crypto_box(cipher, plain, MESSAGE_LEN,
37 | nonce, server_pub, client_sec);
38 | dump("ciphertext", cipher, MESSAGE_LEN);
39 | assert(rc == 0);
40 |
41 | return 0;
42 | }
43 |
--------------------------------------------------------------------------------
/nacl/tweetnacl.c:
--------------------------------------------------------------------------------
1 | #include "tweetnacl.h"
2 | #define FOR(i,n) for (i = 0;i < n;++i)
3 | #define sv static void
4 |
5 | typedef unsigned char u8;
6 | typedef unsigned long u32;
7 | typedef unsigned long long u64;
8 | typedef long long i64;
9 | typedef i64 gf[16];
10 | extern void randombytes(u8 *,u64);
11 |
12 | static const u8
13 | _0[16],
14 | _9[32] = {9};
15 | static const gf
16 | gf0,
17 | gf1 = {1},
18 | _121665 = {0xDB41,1},
19 | D = {0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203},
20 | D2 = {0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406},
21 | X = {0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169},
22 | Y = {0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666},
23 | I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83};
24 |
25 | static u32 L32(u32 x,int c) { return (x << c) | ((x&0xffffffff) >> (32 - c)); }
26 |
27 | static u32 ld32(const u8 *x)
28 | {
29 | u32 u = x[3];
30 | u = (u<<8)|x[2];
31 | u = (u<<8)|x[1];
32 | return (u<<8)|x[0];
33 | }
34 |
35 | static u64 dl64(const u8 *x)
36 | {
37 | u64 i,u=0;
38 | FOR(i,8) u=(u<<8)|x[i];
39 | return u;
40 | }
41 |
42 | sv st32(u8 *x,u32 u)
43 | {
44 | int i;
45 | FOR(i,4) { x[i] = u; u >>= 8; }
46 | }
47 |
48 | sv ts64(u8 *x,u64 u)
49 | {
50 | int i;
51 | for (i = 7;i >= 0;--i) { x[i] = u; u >>= 8; }
52 | }
53 |
54 | static int vn(const u8 *x,const u8 *y,int n)
55 | {
56 | u32 i,d = 0;
57 | FOR(i,n) d |= x[i]^y[i];
58 | return (1 & ((d - 1) >> 8)) - 1;
59 | }
60 |
61 | int crypto_verify_16(const u8 *x,const u8 *y)
62 | {
63 | return vn(x,y,16);
64 | }
65 |
66 | int crypto_verify_32(const u8 *x,const u8 *y)
67 | {
68 | return vn(x,y,32);
69 | }
70 |
71 | sv core(u8 *out,const u8 *in,const u8 *k,const u8 *c,int h)
72 | {
73 | u32 w[16],x[16],y[16],t[4];
74 | int i,j,m;
75 |
76 | FOR(i,4) {
77 | x[5*i] = ld32(c+4*i);
78 | x[1+i] = ld32(k+4*i);
79 | x[6+i] = ld32(in+4*i);
80 | x[11+i] = ld32(k+16+4*i);
81 | }
82 |
83 | FOR(i,16) y[i] = x[i];
84 |
85 | FOR(i,20) {
86 | FOR(j,4) {
87 | FOR(m,4) t[m] = x[(5*j+4*m)%16];
88 | t[1] ^= L32(t[0]+t[3], 7);
89 | t[2] ^= L32(t[1]+t[0], 9);
90 | t[3] ^= L32(t[2]+t[1],13);
91 | t[0] ^= L32(t[3]+t[2],18);
92 | FOR(m,4) w[4*j+(j+m)%4] = t[m];
93 | }
94 | FOR(m,16) x[m] = w[m];
95 | }
96 |
97 | if (h) {
98 | FOR(i,16) x[i] += y[i];
99 | FOR(i,4) {
100 | x[5*i] -= ld32(c+4*i);
101 | x[6+i] -= ld32(in+4*i);
102 | }
103 | FOR(i,4) {
104 | st32(out+4*i,x[5*i]);
105 | st32(out+16+4*i,x[6+i]);
106 | }
107 | } else
108 | FOR(i,16) st32(out + 4 * i,x[i] + y[i]);
109 | }
110 |
111 | int crypto_core_salsa20(u8 *out,const u8 *in,const u8 *k,const u8 *c)
112 | {
113 | core(out,in,k,c,0);
114 | return 0;
115 | }
116 |
117 | int crypto_core_hsalsa20(u8 *out,const u8 *in,const u8 *k,const u8 *c)
118 | {
119 | core(out,in,k,c,1);
120 | return 0;
121 | }
122 |
123 | static const u8 sigma[16] = "expand 32-byte k";
124 |
125 | int crypto_stream_salsa20_xor(u8 *c,const u8 *m,u64 b,const u8 *n,const u8 *k)
126 | {
127 | u8 z[16],x[64];
128 | u32 u,i;
129 | if (!b) return 0;
130 | FOR(i,16) z[i] = 0;
131 | FOR(i,8) z[i] = n[i];
132 | while (b >= 64) {
133 | crypto_core_salsa20(x,z,k,sigma);
134 | FOR(i,64) c[i] = (m?m[i]:0) ^ x[i];
135 | u = 1;
136 | for (i = 8;i < 16;++i) {
137 | u += (u32) z[i];
138 | z[i] = u;
139 | u >>= 8;
140 | }
141 | b -= 64;
142 | c += 64;
143 | if (m) m += 64;
144 | }
145 | if (b) {
146 | crypto_core_salsa20(x,z,k,sigma);
147 | FOR(i,b) c[i] = (m?m[i]:0) ^ x[i];
148 | }
149 | return 0;
150 | }
151 |
152 | int crypto_stream_salsa20(u8 *c,u64 d,const u8 *n,const u8 *k)
153 | {
154 | return crypto_stream_salsa20_xor(c,0,d,n,k);
155 | }
156 |
157 | int crypto_stream(u8 *c,u64 d,const u8 *n,const u8 *k)
158 | {
159 | u8 s[32];
160 | crypto_core_hsalsa20(s,n,k,sigma);
161 | return crypto_stream_salsa20(c,d,n+16,s);
162 | }
163 |
164 | int crypto_stream_xor(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k)
165 | {
166 | u8 s[32];
167 | crypto_core_hsalsa20(s,n,k,sigma);
168 | return crypto_stream_salsa20_xor(c,m,d,n+16,s);
169 | }
170 |
171 | sv add1305(u32 *h,const u32 *c)
172 | {
173 | u32 j,u = 0;
174 | FOR(j,17) {
175 | u += h[j] + c[j];
176 | h[j] = u & 255;
177 | u >>= 8;
178 | }
179 | }
180 |
181 | static const u32 minusp[17] = {
182 | 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252
183 | } ;
184 |
185 | int crypto_onetimeauth(u8 *out,const u8 *m,u64 n,const u8 *k)
186 | {
187 | u32 s,i,j,u,x[17],r[17],h[17],c[17],g[17];
188 |
189 | FOR(j,17) r[j]=h[j]=0;
190 | FOR(j,16) r[j]=k[j];
191 | r[3]&=15;
192 | r[4]&=252;
193 | r[7]&=15;
194 | r[8]&=252;
195 | r[11]&=15;
196 | r[12]&=252;
197 | r[15]&=15;
198 |
199 | while (n > 0) {
200 | FOR(j,17) c[j] = 0;
201 | for (j = 0;(j < 16) && (j < n);++j) c[j] = m[j];
202 | c[j] = 1;
203 | m += j; n -= j;
204 | add1305(h,c);
205 | FOR(i,17) {
206 | x[i] = 0;
207 | FOR(j,17) x[i] += h[j] * ((j <= i) ? r[i - j] : 320 * r[i + 17 - j]);
208 | }
209 | FOR(i,17) h[i] = x[i];
210 | u = 0;
211 | FOR(j,16) {
212 | u += h[j];
213 | h[j] = u & 255;
214 | u >>= 8;
215 | }
216 | u += h[16]; h[16] = u & 3;
217 | u = 5 * (u >> 2);
218 | FOR(j,16) {
219 | u += h[j];
220 | h[j] = u & 255;
221 | u >>= 8;
222 | }
223 | u += h[16]; h[16] = u;
224 | }
225 |
226 | FOR(j,17) g[j] = h[j];
227 | add1305(h,minusp);
228 | s = -(h[16] >> 7);
229 | FOR(j,17) h[j] ^= s & (g[j] ^ h[j]);
230 |
231 | FOR(j,16) c[j] = k[j + 16];
232 | c[16] = 0;
233 | add1305(h,c);
234 | FOR(j,16) out[j] = h[j];
235 | return 0;
236 | }
237 |
238 | int crypto_onetimeauth_verify(const u8 *h,const u8 *m,u64 n,const u8 *k)
239 | {
240 | u8 x[16];
241 | crypto_onetimeauth(x,m,n,k);
242 | return crypto_verify_16(h,x);
243 | }
244 |
245 | int crypto_secretbox(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k)
246 | {
247 | int i;
248 | if (d < 32) return -1;
249 | crypto_stream_xor(c,m,d,n,k);
250 | crypto_onetimeauth(c + 16,c + 32,d - 32,c);
251 | FOR(i,16) c[i] = 0;
252 | return 0;
253 | }
254 |
255 | int crypto_secretbox_open(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *k)
256 | {
257 | int i;
258 | u8 x[32];
259 | if (d < 32) return -1;
260 | crypto_stream(x,32,n,k);
261 | if (crypto_onetimeauth_verify(c + 16,c + 32,d - 32,x) != 0) return -1;
262 | crypto_stream_xor(m,c,d,n,k);
263 | FOR(i,32) m[i] = 0;
264 | return 0;
265 | }
266 |
267 | sv set25519(gf r, const gf a)
268 | {
269 | int i;
270 | FOR(i,16) r[i]=a[i];
271 | }
272 |
273 | sv car25519(gf o)
274 | {
275 | int i;
276 | i64 c;
277 | FOR(i,16) {
278 | o[i]+=(1LL<<16);
279 | c=o[i]>>16;
280 | o[(i+1)*(i<15)]+=c-1+37*(c-1)*(i==15);
281 | o[i]-=c<<16;
282 | }
283 | }
284 |
285 | sv sel25519(gf p,gf q,int b)
286 | {
287 | i64 t,i,c=~(b-1);
288 | FOR(i,16) {
289 | t= c&(p[i]^q[i]);
290 | p[i]^=t;
291 | q[i]^=t;
292 | }
293 | }
294 |
295 | sv pack25519(u8 *o,const gf n)
296 | {
297 | int i,j,b;
298 | gf m,t;
299 | FOR(i,16) t[i]=n[i];
300 | car25519(t);
301 | car25519(t);
302 | car25519(t);
303 | FOR(j,2) {
304 | m[0]=t[0]-0xffed;
305 | for(i=1;i<15;i++) {
306 | m[i]=t[i]-0xffff-((m[i-1]>>16)&1);
307 | m[i-1]&=0xffff;
308 | }
309 | m[15]=t[15]-0x7fff-((m[14]>>16)&1);
310 | b=(m[15]>>16)&1;
311 | m[14]&=0xffff;
312 | sel25519(t,m,1-b);
313 | }
314 | FOR(i,16) {
315 | o[2*i]=t[i]&0xff;
316 | o[2*i+1]=t[i]>>8;
317 | }
318 | }
319 |
320 | static int neq25519(const gf a, const gf b)
321 | {
322 | u8 c[32],d[32];
323 | pack25519(c,a);
324 | pack25519(d,b);
325 | return crypto_verify_32(c,d);
326 | }
327 |
328 | static u8 par25519(const gf a)
329 | {
330 | u8 d[32];
331 | pack25519(d,a);
332 | return d[0]&1;
333 | }
334 |
335 | sv unpack25519(gf o, const u8 *n)
336 | {
337 | int i;
338 | FOR(i,16) o[i]=n[2*i]+((i64)n[2*i+1]<<8);
339 | o[15]&=0x7fff;
340 | }
341 |
342 | sv A(gf o,const gf a,const gf b)
343 | {
344 | int i;
345 | FOR(i,16) o[i]=a[i]+b[i];
346 | }
347 |
348 | sv Z(gf o,const gf a,const gf b)
349 | {
350 | int i;
351 | FOR(i,16) o[i]=a[i]-b[i];
352 | }
353 |
354 | sv M(gf o,const gf a,const gf b)
355 | {
356 | i64 i,j,t[31];
357 | FOR(i,31) t[i]=0;
358 | FOR(i,16) FOR(j,16) t[i+j]+=a[i]*b[j];
359 | FOR(i,15) t[i]+=38*t[i+16];
360 | FOR(i,16) o[i]=t[i];
361 | car25519(o);
362 | car25519(o);
363 | }
364 |
365 | sv S(gf o,const gf a)
366 | {
367 | M(o,a,a);
368 | }
369 |
370 | sv inv25519(gf o,const gf i)
371 | {
372 | gf c;
373 | int a;
374 | FOR(a,16) c[a]=i[a];
375 | for(a=253;a>=0;a--) {
376 | S(c,c);
377 | if(a!=2&&a!=4) M(c,c,i);
378 | }
379 | FOR(a,16) o[a]=c[a];
380 | }
381 |
382 | sv pow2523(gf o,const gf i)
383 | {
384 | gf c;
385 | int a;
386 | FOR(a,16) c[a]=i[a];
387 | for(a=250;a>=0;a--) {
388 | S(c,c);
389 | if(a!=1) M(c,c,i);
390 | }
391 | FOR(a,16) o[a]=c[a];
392 | }
393 |
394 | int crypto_scalarmult(u8 *q,const u8 *n,const u8 *p)
395 | {
396 | u8 z[32];
397 | i64 x[80],r,i;
398 | gf a,b,c,d,e,f;
399 | FOR(i,31) z[i]=n[i];
400 | z[31]=(n[31]&127)|64;
401 | z[0]&=248;
402 | unpack25519(x,p);
403 | FOR(i,16) {
404 | b[i]=x[i];
405 | d[i]=a[i]=c[i]=0;
406 | }
407 | a[0]=d[0]=1;
408 | for(i=254;i>=0;--i) {
409 | r=(z[i>>3]>>(i&7))&1;
410 | sel25519(a,b,r);
411 | sel25519(c,d,r);
412 | A(e,a,c);
413 | Z(a,a,c);
414 | A(c,b,d);
415 | Z(b,b,d);
416 | S(d,e);
417 | S(f,a);
418 | M(a,c,a);
419 | M(c,b,e);
420 | A(e,a,c);
421 | Z(a,a,c);
422 | S(b,a);
423 | Z(c,d,f);
424 | M(a,c,_121665);
425 | A(a,a,d);
426 | M(c,c,a);
427 | M(a,d,f);
428 | M(d,b,x);
429 | S(b,e);
430 | sel25519(a,b,r);
431 | sel25519(c,d,r);
432 | }
433 | FOR(i,16) {
434 | x[i+16]=a[i];
435 | x[i+32]=c[i];
436 | x[i+48]=b[i];
437 | x[i+64]=d[i];
438 | }
439 | inv25519(x+32,x+32);
440 | M(x+16,x+16,x+32);
441 | pack25519(q,x+16);
442 | return 0;
443 | }
444 |
445 | int crypto_scalarmult_base(u8 *q,const u8 *n)
446 | {
447 | return crypto_scalarmult(q,n,_9);
448 | }
449 |
450 | int crypto_box_keypair(u8 *y,u8 *x)
451 | {
452 | randombytes(x,32);
453 | return crypto_scalarmult_base(y,x);
454 | }
455 |
456 | int crypto_box_beforenm(u8 *k,const u8 *y,const u8 *x)
457 | {
458 | u8 s[32];
459 | crypto_scalarmult(s,x,y);
460 | return crypto_core_hsalsa20(k,_0,s,sigma);
461 | }
462 |
463 | int crypto_box_afternm(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k)
464 | {
465 | return crypto_secretbox(c,m,d,n,k);
466 | }
467 |
468 | int crypto_box_open_afternm(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *k)
469 | {
470 | return crypto_secretbox_open(m,c,d,n,k);
471 | }
472 |
473 | int crypto_box(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *y,const u8 *x)
474 | {
475 | u8 k[32];
476 | crypto_box_beforenm(k,y,x);
477 | return crypto_box_afternm(c,m,d,n,k);
478 | }
479 |
480 | int crypto_box_open(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *y,const u8 *x)
481 | {
482 | u8 k[32];
483 | crypto_box_beforenm(k,y,x);
484 | return crypto_box_open_afternm(m,c,d,n,k);
485 | }
486 |
487 | static u64 R(u64 x,int c) { return (x >> c) | (x << (64 - c)); }
488 | static u64 Ch(u64 x,u64 y,u64 z) { return (x & y) ^ (~x & z); }
489 | static u64 Maj(u64 x,u64 y,u64 z) { return (x & y) ^ (x & z) ^ (y & z); }
490 | static u64 Sigma0(u64 x) { return R(x,28) ^ R(x,34) ^ R(x,39); }
491 | static u64 Sigma1(u64 x) { return R(x,14) ^ R(x,18) ^ R(x,41); }
492 | static u64 sigma0(u64 x) { return R(x, 1) ^ R(x, 8) ^ (x >> 7); }
493 | static u64 sigma1(u64 x) { return R(x,19) ^ R(x,61) ^ (x >> 6); }
494 |
495 | static const u64 K[80] =
496 | {
497 | 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
498 | 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
499 | 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
500 | 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
501 | 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
502 | 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
503 | 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
504 | 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
505 | 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
506 | 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
507 | 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
508 | 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
509 | 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
510 | 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
511 | 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
512 | 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
513 | 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
514 | 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
515 | 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
516 | 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
517 | };
518 |
519 | int crypto_hashblocks(u8 *x,const u8 *m,u64 n)
520 | {
521 | u64 z[8],b[8],a[8],w[16],t;
522 | int i,j;
523 |
524 | FOR(i,8) z[i] = a[i] = dl64(x + 8 * i);
525 |
526 | while (n >= 128) {
527 | FOR(i,16) w[i] = dl64(m + 8 * i);
528 |
529 | FOR(i,80) {
530 | FOR(j,8) b[j] = a[j];
531 | t = a[7] + Sigma1(a[4]) + Ch(a[4],a[5],a[6]) + K[i] + w[i%16];
532 | b[7] = t + Sigma0(a[0]) + Maj(a[0],a[1],a[2]);
533 | b[3] += t;
534 | FOR(j,8) a[(j+1)%8] = b[j];
535 | if (i%16 == 15)
536 | FOR(j,16)
537 | w[j] += w[(j+9)%16] + sigma0(w[(j+1)%16]) + sigma1(w[(j+14)%16]);
538 | }
539 |
540 | FOR(i,8) { a[i] += z[i]; z[i] = a[i]; }
541 |
542 | m += 128;
543 | n -= 128;
544 | }
545 |
546 | FOR(i,8) ts64(x+8*i,z[i]);
547 |
548 | return n;
549 | }
550 |
551 | static const u8 iv[64] = {
552 | 0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08,
553 | 0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b,
554 | 0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b,
555 | 0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1,
556 | 0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1,
557 | 0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f,
558 | 0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b,
559 | 0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79
560 | } ;
561 |
562 | int crypto_hash(u8 *out,const u8 *m,u64 n)
563 | {
564 | u8 h[64],x[256];
565 | u64 i,b = n;
566 |
567 | FOR(i,64) h[i] = iv[i];
568 |
569 | crypto_hashblocks(h,m,n);
570 | m += n;
571 | n &= 127;
572 | m -= n;
573 |
574 | FOR(i,256) x[i] = 0;
575 | FOR(i,n) x[i] = m[i];
576 | x[n] = 128;
577 |
578 | n = 256-128*(n<112);
579 | x[n-9] = b >> 61;
580 | ts64(x+n-8,b<<3);
581 | crypto_hashblocks(h,x,n);
582 |
583 | FOR(i,64) out[i] = h[i];
584 |
585 | return 0;
586 | }
587 |
588 | sv add(gf p[4],gf q[4])
589 | {
590 | gf a,b,c,d,t,e,f,g,h;
591 |
592 | Z(a, p[1], p[0]);
593 | Z(t, q[1], q[0]);
594 | M(a, a, t);
595 | A(b, p[0], p[1]);
596 | A(t, q[0], q[1]);
597 | M(b, b, t);
598 | M(c, p[3], q[3]);
599 | M(c, c, D2);
600 | M(d, p[2], q[2]);
601 | A(d, d, d);
602 | Z(e, b, a);
603 | Z(f, d, c);
604 | A(g, d, c);
605 | A(h, b, a);
606 |
607 | M(p[0], e, f);
608 | M(p[1], h, g);
609 | M(p[2], g, f);
610 | M(p[3], e, h);
611 | }
612 |
613 | sv cswap(gf p[4],gf q[4],u8 b)
614 | {
615 | int i;
616 | FOR(i,4)
617 | sel25519(p[i],q[i],b);
618 | }
619 |
620 | sv pack(u8 *r,gf p[4])
621 | {
622 | gf tx, ty, zi;
623 | inv25519(zi, p[2]);
624 | M(tx, p[0], zi);
625 | M(ty, p[1], zi);
626 | pack25519(r, ty);
627 | r[31] ^= par25519(tx) << 7;
628 | }
629 |
630 | sv scalarmult(gf p[4],gf q[4],const u8 *s)
631 | {
632 | int i;
633 | set25519(p[0],gf0);
634 | set25519(p[1],gf1);
635 | set25519(p[2],gf1);
636 | set25519(p[3],gf0);
637 | for (i = 255;i >= 0;--i) {
638 | u8 b = (s[i/8]>>(i&7))&1;
639 | cswap(p,q,b);
640 | add(q,p);
641 | add(p,p);
642 | cswap(p,q,b);
643 | }
644 | }
645 |
646 | sv scalarbase(gf p[4],const u8 *s)
647 | {
648 | gf q[4];
649 | set25519(q[0],X);
650 | set25519(q[1],Y);
651 | set25519(q[2],gf1);
652 | M(q[3],X,Y);
653 | scalarmult(p,q,s);
654 | }
655 |
656 | int crypto_sign_keypair(u8 *pk, u8 *sk)
657 | {
658 | u8 d[64];
659 | gf p[4];
660 | int i;
661 |
662 | randombytes(sk, 32);
663 | crypto_hash(d, sk, 32);
664 | d[0] &= 248;
665 | d[31] &= 127;
666 | d[31] |= 64;
667 |
668 | scalarbase(p,d);
669 | pack(pk,p);
670 |
671 | FOR(i,32) sk[32 + i] = pk[i];
672 | return 0;
673 | }
674 |
675 | static const u64 L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10};
676 |
677 | sv modL(u8 *r,i64 x[64])
678 | {
679 | i64 carry,i,j;
680 | for (i = 63;i >= 32;--i) {
681 | carry = 0;
682 | for (j = i - 32;j < i - 12;++j) {
683 | x[j] += carry - 16 * x[i] * L[j - (i - 32)];
684 | carry = (x[j] + 128) >> 8;
685 | x[j] -= carry << 8;
686 | }
687 | x[j] += carry;
688 | x[i] = 0;
689 | }
690 | carry = 0;
691 | FOR(j,32) {
692 | x[j] += carry - (x[31] >> 4) * L[j];
693 | carry = x[j] >> 8;
694 | x[j] &= 255;
695 | }
696 | FOR(j,32) x[j] -= carry * L[j];
697 | FOR(i,32) {
698 | x[i+1] += x[i] >> 8;
699 | r[i] = x[i] & 255;
700 | }
701 | }
702 |
703 | sv reduce(u8 *r)
704 | {
705 | i64 x[64],i;
706 | FOR(i,64) x[i] = (u64) r[i];
707 | FOR(i,64) r[i] = 0;
708 | modL(r,x);
709 | }
710 |
711 | int crypto_sign(u8 *sm,u64 *smlen,const u8 *m,u64 n,const u8 *sk)
712 | {
713 | u8 d[64],h[64],r[64];
714 | i64 i,j,x[64];
715 | gf p[4];
716 |
717 | crypto_hash(d, sk, 32);
718 | d[0] &= 248;
719 | d[31] &= 127;
720 | d[31] |= 64;
721 |
722 | *smlen = n+64;
723 | FOR(i,n) sm[64 + i] = m[i];
724 | FOR(i,32) sm[32 + i] = d[32 + i];
725 |
726 | crypto_hash(r, sm+32, n+32);
727 | reduce(r);
728 | scalarbase(p,r);
729 | pack(sm,p);
730 |
731 | FOR(i,32) sm[i+32] = sk[i+32];
732 | crypto_hash(h,sm,n + 64);
733 | reduce(h);
734 |
735 | FOR(i,64) x[i] = 0;
736 | FOR(i,32) x[i] = (u64) r[i];
737 | FOR(i,32) FOR(j,32) x[i+j] += h[i] * (u64) d[j];
738 | modL(sm + 32,x);
739 |
740 | return 0;
741 | }
742 |
743 | static int unpackneg(gf r[4],const u8 p[32])
744 | {
745 | gf t, chk, num, den, den2, den4, den6;
746 | set25519(r[2],gf1);
747 | unpack25519(r[1],p);
748 | S(num,r[1]);
749 | M(den,num,D);
750 | Z(num,num,r[2]);
751 | A(den,r[2],den);
752 |
753 | S(den2,den);
754 | S(den4,den2);
755 | M(den6,den4,den2);
756 | M(t,den6,num);
757 | M(t,t,den);
758 |
759 | pow2523(t,t);
760 | M(t,t,num);
761 | M(t,t,den);
762 | M(t,t,den);
763 | M(r[0],t,den);
764 |
765 | S(chk,r[0]);
766 | M(chk,chk,den);
767 | if (neq25519(chk, num)) M(r[0],r[0],I);
768 |
769 | S(chk,r[0]);
770 | M(chk,chk,den);
771 | if (neq25519(chk, num)) return -1;
772 |
773 | if (par25519(r[0]) == (p[31]>>7)) Z(r[0],gf0,r[0]);
774 |
775 | M(r[3],r[0],r[1]);
776 | return 0;
777 | }
778 |
779 | int crypto_sign_open(u8 *m,u64 *mlen,const u8 *sm,u64 n,const u8 *pk)
780 | {
781 | int i;
782 | u8 t[32],h[64];
783 | gf p[4],q[4];
784 |
785 | *mlen = -1;
786 | if (n < 64) return -1;
787 |
788 | if (unpackneg(q,pk)) return -1;
789 |
790 | FOR(i,n) m[i] = sm[i];
791 | FOR(i,32) m[i+32] = pk[i];
792 | crypto_hash(h,m,n);
793 | reduce(h);
794 | scalarmult(p,q,h);
795 |
796 | scalarbase(q,sm + 32);
797 | add(p,q);
798 | pack(t,p);
799 |
800 | n -= 64;
801 | if (crypto_verify_32(sm, t)) {
802 | FOR(i,n) m[i] = 0;
803 | return -1;
804 | }
805 |
806 | FOR(i,n) m[i] = sm[i + 64];
807 | *mlen = n;
808 | return 0;
809 | }
810 |
--------------------------------------------------------------------------------
/nacl/tweetnacl.h:
--------------------------------------------------------------------------------
1 | #ifndef TWEETNACL_H
2 | #define TWEETNACL_H
3 | #define crypto_auth_PRIMITIVE "hmacsha512256"
4 | #define crypto_auth crypto_auth_hmacsha512256
5 | #define crypto_auth_verify crypto_auth_hmacsha512256_verify
6 | #define crypto_auth_BYTES crypto_auth_hmacsha512256_BYTES
7 | #define crypto_auth_KEYBYTES crypto_auth_hmacsha512256_KEYBYTES
8 | #define crypto_auth_IMPLEMENTATION crypto_auth_hmacsha512256_IMPLEMENTATION
9 | #define crypto_auth_VERSION crypto_auth_hmacsha512256_VERSION
10 | #define crypto_auth_hmacsha512256_tweet_BYTES 32
11 | #define crypto_auth_hmacsha512256_tweet_KEYBYTES 32
12 | extern int crypto_auth_hmacsha512256_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *);
13 | extern int crypto_auth_hmacsha512256_tweet_verify(const unsigned char *,const unsigned char *,unsigned long long,const unsigned char *);
14 | #define crypto_auth_hmacsha512256_tweet_VERSION "-"
15 | #define crypto_auth_hmacsha512256 crypto_auth_hmacsha512256_tweet
16 | #define crypto_auth_hmacsha512256_verify crypto_auth_hmacsha512256_tweet_verify
17 | #define crypto_auth_hmacsha512256_BYTES crypto_auth_hmacsha512256_tweet_BYTES
18 | #define crypto_auth_hmacsha512256_KEYBYTES crypto_auth_hmacsha512256_tweet_KEYBYTES
19 | #define crypto_auth_hmacsha512256_VERSION crypto_auth_hmacsha512256_tweet_VERSION
20 | #define crypto_auth_hmacsha512256_IMPLEMENTATION "crypto_auth/hmacsha512256/tweet"
21 | #define crypto_box_PRIMITIVE "curve25519xsalsa20poly1305"
22 | #define crypto_box crypto_box_curve25519xsalsa20poly1305
23 | #define crypto_box_open crypto_box_curve25519xsalsa20poly1305_open
24 | #define crypto_box_keypair crypto_box_curve25519xsalsa20poly1305_keypair
25 | #define crypto_box_beforenm crypto_box_curve25519xsalsa20poly1305_beforenm
26 | #define crypto_box_afternm crypto_box_curve25519xsalsa20poly1305_afternm
27 | #define crypto_box_open_afternm crypto_box_curve25519xsalsa20poly1305_open_afternm
28 | #define crypto_box_PUBLICKEYBYTES crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
29 | #define crypto_box_SECRETKEYBYTES crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES
30 | #define crypto_box_BEFORENMBYTES crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES
31 | #define crypto_box_NONCEBYTES crypto_box_curve25519xsalsa20poly1305_NONCEBYTES
32 | #define crypto_box_ZEROBYTES crypto_box_curve25519xsalsa20poly1305_ZEROBYTES
33 | #define crypto_box_BOXZEROBYTES crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES
34 | #define crypto_box_IMPLEMENTATION crypto_box_curve25519xsalsa20poly1305_IMPLEMENTATION
35 | #define crypto_box_VERSION crypto_box_curve25519xsalsa20poly1305_VERSION
36 | #define crypto_box_curve25519xsalsa20poly1305_tweet_PUBLICKEYBYTES 32
37 | #define crypto_box_curve25519xsalsa20poly1305_tweet_SECRETKEYBYTES 32
38 | #define crypto_box_curve25519xsalsa20poly1305_tweet_BEFORENMBYTES 32
39 | #define crypto_box_curve25519xsalsa20poly1305_tweet_NONCEBYTES 24
40 | #define crypto_box_curve25519xsalsa20poly1305_tweet_ZEROBYTES 32
41 | #define crypto_box_curve25519xsalsa20poly1305_tweet_BOXZEROBYTES 16
42 | extern int crypto_box_curve25519xsalsa20poly1305_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *,const unsigned char *);
43 | extern int crypto_box_curve25519xsalsa20poly1305_tweet_open(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *,const unsigned char *);
44 | extern int crypto_box_curve25519xsalsa20poly1305_tweet_keypair(unsigned char *,unsigned char *);
45 | extern int crypto_box_curve25519xsalsa20poly1305_tweet_beforenm(unsigned char *,const unsigned char *,const unsigned char *);
46 | extern int crypto_box_curve25519xsalsa20poly1305_tweet_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
47 | extern int crypto_box_curve25519xsalsa20poly1305_tweet_open_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
48 | #define crypto_box_curve25519xsalsa20poly1305_tweet_VERSION "-"
49 | #define crypto_box_curve25519xsalsa20poly1305 crypto_box_curve25519xsalsa20poly1305_tweet
50 | #define crypto_box_curve25519xsalsa20poly1305_open crypto_box_curve25519xsalsa20poly1305_tweet_open
51 | #define crypto_box_curve25519xsalsa20poly1305_keypair crypto_box_curve25519xsalsa20poly1305_tweet_keypair
52 | #define crypto_box_curve25519xsalsa20poly1305_beforenm crypto_box_curve25519xsalsa20poly1305_tweet_beforenm
53 | #define crypto_box_curve25519xsalsa20poly1305_afternm crypto_box_curve25519xsalsa20poly1305_tweet_afternm
54 | #define crypto_box_curve25519xsalsa20poly1305_open_afternm crypto_box_curve25519xsalsa20poly1305_tweet_open_afternm
55 | #define crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES crypto_box_curve25519xsalsa20poly1305_tweet_PUBLICKEYBYTES
56 | #define crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES crypto_box_curve25519xsalsa20poly1305_tweet_SECRETKEYBYTES
57 | #define crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES crypto_box_curve25519xsalsa20poly1305_tweet_BEFORENMBYTES
58 | #define crypto_box_curve25519xsalsa20poly1305_NONCEBYTES crypto_box_curve25519xsalsa20poly1305_tweet_NONCEBYTES
59 | #define crypto_box_curve25519xsalsa20poly1305_ZEROBYTES crypto_box_curve25519xsalsa20poly1305_tweet_ZEROBYTES
60 | #define crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES crypto_box_curve25519xsalsa20poly1305_tweet_BOXZEROBYTES
61 | #define crypto_box_curve25519xsalsa20poly1305_VERSION crypto_box_curve25519xsalsa20poly1305_tweet_VERSION
62 | #define crypto_box_curve25519xsalsa20poly1305_IMPLEMENTATION "crypto_box/curve25519xsalsa20poly1305/tweet"
63 | #define crypto_core_PRIMITIVE "salsa20"
64 | #define crypto_core crypto_core_salsa20
65 | #define crypto_core_OUTPUTBYTES crypto_core_salsa20_OUTPUTBYTES
66 | #define crypto_core_INPUTBYTES crypto_core_salsa20_INPUTBYTES
67 | #define crypto_core_KEYBYTES crypto_core_salsa20_KEYBYTES
68 | #define crypto_core_CONSTBYTES crypto_core_salsa20_CONSTBYTES
69 | #define crypto_core_IMPLEMENTATION crypto_core_salsa20_IMPLEMENTATION
70 | #define crypto_core_VERSION crypto_core_salsa20_VERSION
71 | #define crypto_core_salsa20_tweet_OUTPUTBYTES 64
72 | #define crypto_core_salsa20_tweet_INPUTBYTES 16
73 | #define crypto_core_salsa20_tweet_KEYBYTES 32
74 | #define crypto_core_salsa20_tweet_CONSTBYTES 16
75 | extern int crypto_core_salsa20_tweet(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *);
76 | #define crypto_core_salsa20_tweet_VERSION "-"
77 | #define crypto_core_salsa20 crypto_core_salsa20_tweet
78 | #define crypto_core_salsa20_OUTPUTBYTES crypto_core_salsa20_tweet_OUTPUTBYTES
79 | #define crypto_core_salsa20_INPUTBYTES crypto_core_salsa20_tweet_INPUTBYTES
80 | #define crypto_core_salsa20_KEYBYTES crypto_core_salsa20_tweet_KEYBYTES
81 | #define crypto_core_salsa20_CONSTBYTES crypto_core_salsa20_tweet_CONSTBYTES
82 | #define crypto_core_salsa20_VERSION crypto_core_salsa20_tweet_VERSION
83 | #define crypto_core_salsa20_IMPLEMENTATION "crypto_core/salsa20/tweet"
84 | #define crypto_core_hsalsa20_tweet_OUTPUTBYTES 32
85 | #define crypto_core_hsalsa20_tweet_INPUTBYTES 16
86 | #define crypto_core_hsalsa20_tweet_KEYBYTES 32
87 | #define crypto_core_hsalsa20_tweet_CONSTBYTES 16
88 | extern int crypto_core_hsalsa20_tweet(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *);
89 | #define crypto_core_hsalsa20_tweet_VERSION "-"
90 | #define crypto_core_hsalsa20 crypto_core_hsalsa20_tweet
91 | #define crypto_core_hsalsa20_OUTPUTBYTES crypto_core_hsalsa20_tweet_OUTPUTBYTES
92 | #define crypto_core_hsalsa20_INPUTBYTES crypto_core_hsalsa20_tweet_INPUTBYTES
93 | #define crypto_core_hsalsa20_KEYBYTES crypto_core_hsalsa20_tweet_KEYBYTES
94 | #define crypto_core_hsalsa20_CONSTBYTES crypto_core_hsalsa20_tweet_CONSTBYTES
95 | #define crypto_core_hsalsa20_VERSION crypto_core_hsalsa20_tweet_VERSION
96 | #define crypto_core_hsalsa20_IMPLEMENTATION "crypto_core/hsalsa20/tweet"
97 | #define crypto_hashblocks_PRIMITIVE "sha512"
98 | #define crypto_hashblocks crypto_hashblocks_sha512
99 | #define crypto_hashblocks_STATEBYTES crypto_hashblocks_sha512_STATEBYTES
100 | #define crypto_hashblocks_BLOCKBYTES crypto_hashblocks_sha512_BLOCKBYTES
101 | #define crypto_hashblocks_IMPLEMENTATION crypto_hashblocks_sha512_IMPLEMENTATION
102 | #define crypto_hashblocks_VERSION crypto_hashblocks_sha512_VERSION
103 | #define crypto_hashblocks_sha512_tweet_STATEBYTES 64
104 | #define crypto_hashblocks_sha512_tweet_BLOCKBYTES 128
105 | extern int crypto_hashblocks_sha512_tweet(unsigned char *,const unsigned char *,unsigned long long);
106 | #define crypto_hashblocks_sha512_tweet_VERSION "-"
107 | #define crypto_hashblocks_sha512 crypto_hashblocks_sha512_tweet
108 | #define crypto_hashblocks_sha512_STATEBYTES crypto_hashblocks_sha512_tweet_STATEBYTES
109 | #define crypto_hashblocks_sha512_BLOCKBYTES crypto_hashblocks_sha512_tweet_BLOCKBYTES
110 | #define crypto_hashblocks_sha512_VERSION crypto_hashblocks_sha512_tweet_VERSION
111 | #define crypto_hashblocks_sha512_IMPLEMENTATION "crypto_hashblocks/sha512/tweet"
112 | #define crypto_hashblocks_sha256_tweet_STATEBYTES 32
113 | #define crypto_hashblocks_sha256_tweet_BLOCKBYTES 64
114 | extern int crypto_hashblocks_sha256_tweet(unsigned char *,const unsigned char *,unsigned long long);
115 | #define crypto_hashblocks_sha256_tweet_VERSION "-"
116 | #define crypto_hashblocks_sha256 crypto_hashblocks_sha256_tweet
117 | #define crypto_hashblocks_sha256_STATEBYTES crypto_hashblocks_sha256_tweet_STATEBYTES
118 | #define crypto_hashblocks_sha256_BLOCKBYTES crypto_hashblocks_sha256_tweet_BLOCKBYTES
119 | #define crypto_hashblocks_sha256_VERSION crypto_hashblocks_sha256_tweet_VERSION
120 | #define crypto_hashblocks_sha256_IMPLEMENTATION "crypto_hashblocks/sha256/tweet"
121 | #define crypto_hash_PRIMITIVE "sha512"
122 | #define crypto_hash crypto_hash_sha512
123 | #define crypto_hash_BYTES crypto_hash_sha512_BYTES
124 | #define crypto_hash_IMPLEMENTATION crypto_hash_sha512_IMPLEMENTATION
125 | #define crypto_hash_VERSION crypto_hash_sha512_VERSION
126 | #define crypto_hash_sha512_tweet_BYTES 64
127 | extern int crypto_hash_sha512_tweet(unsigned char *,const unsigned char *,unsigned long long);
128 | #define crypto_hash_sha512_tweet_VERSION "-"
129 | #define crypto_hash_sha512 crypto_hash_sha512_tweet
130 | #define crypto_hash_sha512_BYTES crypto_hash_sha512_tweet_BYTES
131 | #define crypto_hash_sha512_VERSION crypto_hash_sha512_tweet_VERSION
132 | #define crypto_hash_sha512_IMPLEMENTATION "crypto_hash/sha512/tweet"
133 | #define crypto_hash_sha256_tweet_BYTES 32
134 | extern int crypto_hash_sha256_tweet(unsigned char *,const unsigned char *,unsigned long long);
135 | #define crypto_hash_sha256_tweet_VERSION "-"
136 | #define crypto_hash_sha256 crypto_hash_sha256_tweet
137 | #define crypto_hash_sha256_BYTES crypto_hash_sha256_tweet_BYTES
138 | #define crypto_hash_sha256_VERSION crypto_hash_sha256_tweet_VERSION
139 | #define crypto_hash_sha256_IMPLEMENTATION "crypto_hash/sha256/tweet"
140 | #define crypto_onetimeauth_PRIMITIVE "poly1305"
141 | #define crypto_onetimeauth crypto_onetimeauth_poly1305
142 | #define crypto_onetimeauth_verify crypto_onetimeauth_poly1305_verify
143 | #define crypto_onetimeauth_BYTES crypto_onetimeauth_poly1305_BYTES
144 | #define crypto_onetimeauth_KEYBYTES crypto_onetimeauth_poly1305_KEYBYTES
145 | #define crypto_onetimeauth_IMPLEMENTATION crypto_onetimeauth_poly1305_IMPLEMENTATION
146 | #define crypto_onetimeauth_VERSION crypto_onetimeauth_poly1305_VERSION
147 | #define crypto_onetimeauth_poly1305_tweet_BYTES 16
148 | #define crypto_onetimeauth_poly1305_tweet_KEYBYTES 32
149 | extern int crypto_onetimeauth_poly1305_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *);
150 | extern int crypto_onetimeauth_poly1305_tweet_verify(const unsigned char *,const unsigned char *,unsigned long long,const unsigned char *);
151 | #define crypto_onetimeauth_poly1305_tweet_VERSION "-"
152 | #define crypto_onetimeauth_poly1305 crypto_onetimeauth_poly1305_tweet
153 | #define crypto_onetimeauth_poly1305_verify crypto_onetimeauth_poly1305_tweet_verify
154 | #define crypto_onetimeauth_poly1305_BYTES crypto_onetimeauth_poly1305_tweet_BYTES
155 | #define crypto_onetimeauth_poly1305_KEYBYTES crypto_onetimeauth_poly1305_tweet_KEYBYTES
156 | #define crypto_onetimeauth_poly1305_VERSION crypto_onetimeauth_poly1305_tweet_VERSION
157 | #define crypto_onetimeauth_poly1305_IMPLEMENTATION "crypto_onetimeauth/poly1305/tweet"
158 | #define crypto_scalarmult_PRIMITIVE "curve25519"
159 | #define crypto_scalarmult crypto_scalarmult_curve25519
160 | #define crypto_scalarmult_base crypto_scalarmult_curve25519_base
161 | #define crypto_scalarmult_BYTES crypto_scalarmult_curve25519_BYTES
162 | #define crypto_scalarmult_SCALARBYTES crypto_scalarmult_curve25519_SCALARBYTES
163 | #define crypto_scalarmult_IMPLEMENTATION crypto_scalarmult_curve25519_IMPLEMENTATION
164 | #define crypto_scalarmult_VERSION crypto_scalarmult_curve25519_VERSION
165 | #define crypto_scalarmult_curve25519_tweet_BYTES 32
166 | #define crypto_scalarmult_curve25519_tweet_SCALARBYTES 32
167 | extern int crypto_scalarmult_curve25519_tweet(unsigned char *,const unsigned char *,const unsigned char *);
168 | extern int crypto_scalarmult_curve25519_tweet_base(unsigned char *,const unsigned char *);
169 | #define crypto_scalarmult_curve25519_tweet_VERSION "-"
170 | #define crypto_scalarmult_curve25519 crypto_scalarmult_curve25519_tweet
171 | #define crypto_scalarmult_curve25519_base crypto_scalarmult_curve25519_tweet_base
172 | #define crypto_scalarmult_curve25519_BYTES crypto_scalarmult_curve25519_tweet_BYTES
173 | #define crypto_scalarmult_curve25519_SCALARBYTES crypto_scalarmult_curve25519_tweet_SCALARBYTES
174 | #define crypto_scalarmult_curve25519_VERSION crypto_scalarmult_curve25519_tweet_VERSION
175 | #define crypto_scalarmult_curve25519_IMPLEMENTATION "crypto_scalarmult/curve25519/tweet"
176 | #define crypto_secretbox_PRIMITIVE "xsalsa20poly1305"
177 | #define crypto_secretbox crypto_secretbox_xsalsa20poly1305
178 | #define crypto_secretbox_open crypto_secretbox_xsalsa20poly1305_open
179 | #define crypto_secretbox_KEYBYTES crypto_secretbox_xsalsa20poly1305_KEYBYTES
180 | #define crypto_secretbox_NONCEBYTES crypto_secretbox_xsalsa20poly1305_NONCEBYTES
181 | #define crypto_secretbox_ZEROBYTES crypto_secretbox_xsalsa20poly1305_ZEROBYTES
182 | #define crypto_secretbox_BOXZEROBYTES crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES
183 | #define crypto_secretbox_IMPLEMENTATION crypto_secretbox_xsalsa20poly1305_IMPLEMENTATION
184 | #define crypto_secretbox_VERSION crypto_secretbox_xsalsa20poly1305_VERSION
185 | #define crypto_secretbox_xsalsa20poly1305_tweet_KEYBYTES 32
186 | #define crypto_secretbox_xsalsa20poly1305_tweet_NONCEBYTES 24
187 | #define crypto_secretbox_xsalsa20poly1305_tweet_ZEROBYTES 32
188 | #define crypto_secretbox_xsalsa20poly1305_tweet_BOXZEROBYTES 16
189 | extern int crypto_secretbox_xsalsa20poly1305_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
190 | extern int crypto_secretbox_xsalsa20poly1305_tweet_open(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
191 | #define crypto_secretbox_xsalsa20poly1305_tweet_VERSION "-"
192 | #define crypto_secretbox_xsalsa20poly1305 crypto_secretbox_xsalsa20poly1305_tweet
193 | #define crypto_secretbox_xsalsa20poly1305_open crypto_secretbox_xsalsa20poly1305_tweet_open
194 | #define crypto_secretbox_xsalsa20poly1305_KEYBYTES crypto_secretbox_xsalsa20poly1305_tweet_KEYBYTES
195 | #define crypto_secretbox_xsalsa20poly1305_NONCEBYTES crypto_secretbox_xsalsa20poly1305_tweet_NONCEBYTES
196 | #define crypto_secretbox_xsalsa20poly1305_ZEROBYTES crypto_secretbox_xsalsa20poly1305_tweet_ZEROBYTES
197 | #define crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES crypto_secretbox_xsalsa20poly1305_tweet_BOXZEROBYTES
198 | #define crypto_secretbox_xsalsa20poly1305_VERSION crypto_secretbox_xsalsa20poly1305_tweet_VERSION
199 | #define crypto_secretbox_xsalsa20poly1305_IMPLEMENTATION "crypto_secretbox/xsalsa20poly1305/tweet"
200 | #define crypto_sign_PRIMITIVE "ed25519"
201 | #define crypto_sign crypto_sign_ed25519
202 | #define crypto_sign_open crypto_sign_ed25519_open
203 | #define crypto_sign_keypair crypto_sign_ed25519_keypair
204 | #define crypto_sign_BYTES crypto_sign_ed25519_BYTES
205 | #define crypto_sign_PUBLICKEYBYTES crypto_sign_ed25519_PUBLICKEYBYTES
206 | #define crypto_sign_SECRETKEYBYTES crypto_sign_ed25519_SECRETKEYBYTES
207 | #define crypto_sign_IMPLEMENTATION crypto_sign_ed25519_IMPLEMENTATION
208 | #define crypto_sign_VERSION crypto_sign_ed25519_VERSION
209 | #define crypto_sign_ed25519_tweet_BYTES 64
210 | #define crypto_sign_ed25519_tweet_PUBLICKEYBYTES 32
211 | #define crypto_sign_ed25519_tweet_SECRETKEYBYTES 64
212 | extern int crypto_sign_ed25519_tweet(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *);
213 | extern int crypto_sign_ed25519_tweet_open(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *);
214 | extern int crypto_sign_ed25519_tweet_keypair(unsigned char *,unsigned char *);
215 | #define crypto_sign_ed25519_tweet_VERSION "-"
216 | #define crypto_sign_ed25519 crypto_sign_ed25519_tweet
217 | #define crypto_sign_ed25519_open crypto_sign_ed25519_tweet_open
218 | #define crypto_sign_ed25519_keypair crypto_sign_ed25519_tweet_keypair
219 | #define crypto_sign_ed25519_BYTES crypto_sign_ed25519_tweet_BYTES
220 | #define crypto_sign_ed25519_PUBLICKEYBYTES crypto_sign_ed25519_tweet_PUBLICKEYBYTES
221 | #define crypto_sign_ed25519_SECRETKEYBYTES crypto_sign_ed25519_tweet_SECRETKEYBYTES
222 | #define crypto_sign_ed25519_VERSION crypto_sign_ed25519_tweet_VERSION
223 | #define crypto_sign_ed25519_IMPLEMENTATION "crypto_sign/ed25519/tweet"
224 | #define crypto_stream_PRIMITIVE "xsalsa20"
225 | #define crypto_stream crypto_stream_xsalsa20
226 | #define crypto_stream_xor crypto_stream_xsalsa20_xor
227 | #define crypto_stream_KEYBYTES crypto_stream_xsalsa20_KEYBYTES
228 | #define crypto_stream_NONCEBYTES crypto_stream_xsalsa20_NONCEBYTES
229 | #define crypto_stream_IMPLEMENTATION crypto_stream_xsalsa20_IMPLEMENTATION
230 | #define crypto_stream_VERSION crypto_stream_xsalsa20_VERSION
231 | #define crypto_stream_xsalsa20_tweet_KEYBYTES 32
232 | #define crypto_stream_xsalsa20_tweet_NONCEBYTES 24
233 | extern int crypto_stream_xsalsa20_tweet(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
234 | extern int crypto_stream_xsalsa20_tweet_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
235 | #define crypto_stream_xsalsa20_tweet_VERSION "-"
236 | #define crypto_stream_xsalsa20 crypto_stream_xsalsa20_tweet
237 | #define crypto_stream_xsalsa20_xor crypto_stream_xsalsa20_tweet_xor
238 | #define crypto_stream_xsalsa20_KEYBYTES crypto_stream_xsalsa20_tweet_KEYBYTES
239 | #define crypto_stream_xsalsa20_NONCEBYTES crypto_stream_xsalsa20_tweet_NONCEBYTES
240 | #define crypto_stream_xsalsa20_VERSION crypto_stream_xsalsa20_tweet_VERSION
241 | #define crypto_stream_xsalsa20_IMPLEMENTATION "crypto_stream/xsalsa20/tweet"
242 | #define crypto_stream_salsa20_tweet_KEYBYTES 32
243 | #define crypto_stream_salsa20_tweet_NONCEBYTES 8
244 | extern int crypto_stream_salsa20_tweet(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
245 | extern int crypto_stream_salsa20_tweet_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
246 | #define crypto_stream_salsa20_tweet_VERSION "-"
247 | #define crypto_stream_salsa20 crypto_stream_salsa20_tweet
248 | #define crypto_stream_salsa20_xor crypto_stream_salsa20_tweet_xor
249 | #define crypto_stream_salsa20_KEYBYTES crypto_stream_salsa20_tweet_KEYBYTES
250 | #define crypto_stream_salsa20_NONCEBYTES crypto_stream_salsa20_tweet_NONCEBYTES
251 | #define crypto_stream_salsa20_VERSION crypto_stream_salsa20_tweet_VERSION
252 | #define crypto_stream_salsa20_IMPLEMENTATION "crypto_stream/salsa20/tweet"
253 | #define crypto_verify_PRIMITIVE "16"
254 | #define crypto_verify crypto_verify_16
255 | #define crypto_verify_BYTES crypto_verify_16_BYTES
256 | #define crypto_verify_IMPLEMENTATION crypto_verify_16_IMPLEMENTATION
257 | #define crypto_verify_VERSION crypto_verify_16_VERSION
258 | #define crypto_verify_16_tweet_BYTES 16
259 | extern int crypto_verify_16_tweet(const unsigned char *,const unsigned char *);
260 | #define crypto_verify_16_tweet_VERSION "-"
261 | #define crypto_verify_16 crypto_verify_16_tweet
262 | #define crypto_verify_16_BYTES crypto_verify_16_tweet_BYTES
263 | #define crypto_verify_16_VERSION crypto_verify_16_tweet_VERSION
264 | #define crypto_verify_16_IMPLEMENTATION "crypto_verify/16/tweet"
265 | #define crypto_verify_32_tweet_BYTES 32
266 | extern int crypto_verify_32_tweet(const unsigned char *,const unsigned char *);
267 | #define crypto_verify_32_tweet_VERSION "-"
268 | #define crypto_verify_32 crypto_verify_32_tweet
269 | #define crypto_verify_32_BYTES crypto_verify_32_tweet_BYTES
270 | #define crypto_verify_32_VERSION crypto_verify_32_tweet_VERSION
271 | #define crypto_verify_32_IMPLEMENTATION "crypto_verify/32/tweet"
272 | #endif
273 |
--------------------------------------------------------------------------------
/openssl/spin:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | VERSION=$1
3 | if [[ -z $VERSION ]]; then
4 | echo "USAGE: $0 0.9.xy"
5 | exit 1
6 | fi
7 |
8 | mkdir -p $HOME/ssl/build
9 | cd $HOME/ssl/build
10 |
11 | set -ex
12 | [ -f openssl-$VERSION.tar.gz ] || wget ftp://ftp.openssl.org/source/old/0.9.x/openssl-$VERSION.tar.gz
13 | tar -xzvf openssl-$VERSION.tar.gz
14 | cd openssl-$VERSION
15 |
16 | egrep -ril '^=item [0-9]+$' doc/ | xargs sed -i -e 's/=item \(.*\)/=item C<\1>/'
17 | ./config --prefix=$HOME/ssl/$VERSION --shared
18 | make
19 | make test
20 | make install
21 | find . -name '*.so'
22 |
--------------------------------------------------------------------------------
/rcu/.gitignore:
--------------------------------------------------------------------------------
1 | /run-*
2 | /*.data
3 | /trial.png
4 | /tmp
5 |
--------------------------------------------------------------------------------
/rcu/Makefile:
--------------------------------------------------------------------------------
1 | all: run-lock run-qs
2 | clean:
3 | rm -f run-*
4 | rm -f */*.o
5 |
6 | run-lock: lock/main.o
7 | $(CC) -o $@ -I. $+
8 |
9 | run-qs: qs/main.o
10 | $(CC) -o $@ -I. $+
11 |
12 | data: trial.png
13 | trial.png: out.data
14 | ./plot > $@
15 | [[ -z "$$(command -v open)" ]] || open $@
16 | out.data: run-lock run-qs report
17 | ./report > out.data
18 |
--------------------------------------------------------------------------------
/rcu/api.h:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | static inline void
4 | spin_up(void *(*fn)(void *), void *restrict arg)
5 | {
6 | pthread_t tid;
7 | if (pthread_create(&tid, NULL, fn, arg) != 0) {
8 | perror("pthread_create");
9 | exit(3);
10 | }
11 | }
12 |
13 | static inline void
14 | make_lock(pthread_mutex_t *lck)
15 | {
16 | if (pthread_mutex_init(lck, NULL) != 0) {
17 | perror("pthread_mutex_init");
18 | exit(3);
19 | }
20 | }
21 |
22 | static inline void
23 | lock(pthread_mutex_t *lck) {
24 | if (pthread_mutex_lock(lck) != 0) { \
25 | perror("pthread_mutex_lock"); \
26 | exit(3); \
27 | } \
28 | }
29 |
30 | static inline void
31 | unlock(pthread_mutex_t *lck) {
32 | if (pthread_mutex_unlock(lck) != 0) {
33 | perror("pthread_mutex_unlock");
34 | exit(3);
35 | }
36 | }
37 |
38 | #define xmalloc(n) xcalloc(1,(n))
39 | static inline void*
40 | xcalloc(size_t n, size_t len)
41 | {
42 | void *p = calloc(n, len);
43 | if (!p) {
44 | perror("calloc");
45 | exit(3);
46 | }
47 | return p;
48 | }
49 |
--------------------------------------------------------------------------------
/rcu/lock/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include "../api.h"
6 |
7 | /*
8 |
9 | rcu/lock
10 |
11 | This is a naïve implementation of concurrent data sharing
12 | across multiple threads that utilized mutex locks to ensure
13 | that threads see a consistent set of data.
14 |
15 | If my understanding of RCU read-side primitive overhead is
16 | correct, this program should execute the slowest, given the
17 | same starting parameters (number of threads, write cycles,
18 | and reads per write cycle).
19 |
20 | */
21 |
22 |
23 | static unsigned char
24 | hashit(const char *s)
25 | {
26 | unsigned int h = 81;
27 | unsigned char c;
28 |
29 | while ((c = *s++))
30 | h = ((h << 5) + h) + c;
31 |
32 | return h & ~0xc0;
33 | }
34 |
35 | struct hlist {
36 | struct hlist *next;
37 | char *key;
38 | void *value;
39 | };
40 | typedef struct {
41 | struct hlist h[64];
42 | } hash_t;
43 |
44 | static void*
45 | hash_get(hash_t *h, const char *k)
46 | {
47 | struct hlist *hl;
48 | for (hl = h->hlist[hashit(k)]; hl, hl = hl->next) {
49 | if (strcmp(hl->key, k) == 0) {
50 | return hl->value;
51 | }
52 | }
53 | return NULL;
54 | }
55 |
56 | static void
57 | hash_set(hash_t *h, const char *k, void *v)
58 | {
59 | return;
60 | }
61 |
62 | pthread_mutex_t LOCK;
63 | unsigned long long *COUNTER;
64 |
65 | void writer(int cycles)
66 | {
67 | while (cycles--) {
68 | lock(&LOCK);
69 | *COUNTER += 1;
70 | fprintf(stderr, "[writer] incremented COUNTER to %llu\n", *COUNTER);
71 | unlock(&LOCK);
72 | }
73 | }
74 |
75 | void* reader(void *_)
76 | {
77 | int id = *(int *)_;
78 |
79 | for (;;) {
80 | lock(&LOCK);
81 | fprintf(stderr, "[t%d] read COUNTER at %llu\n", id, *COUNTER);
82 | unlock(&LOCK);
83 | }
84 |
85 | return _;
86 | }
87 |
88 | int main(int argc, char **argv)
89 | {
90 | struct timeval start, end;
91 | pthread_t tid;
92 | int rc, i, nthreads, cycles, *ids;
93 | void *status;
94 |
95 | if (argc != 3) {
96 | fprintf(stderr, "USAGE: %s THREADS CYCLES READS\n", argv[0]);
97 | exit(2);
98 | }
99 |
100 | nthreads = atoi(argv[1]);
101 | cycles = atoi(argv[2]);
102 | if (nthreads < 1) {
103 | fprintf(stderr, "Invalid THREADS value %s (must be > 0)\n", argv[1]);
104 | fprintf(stderr, "USAGE: %s THREADS CYCLES READS\n", argv[0]);
105 | exit(2);
106 | }
107 | if (cycles < 1) {
108 | fprintf(stderr, "Invalid WRITE_CYCLES value %s (must be > 0)\n", argv[2]);
109 | fprintf(stderr, "USAGE: %s THREADS CYCLES READS\n", argv[0]);
110 | exit(2);
111 | }
112 |
113 | make_lock(&LOCK);
114 | ids = xcalloc(nthreads, sizeof(int));
115 | COUNTER = xmalloc(sizeof(unsigned long long));
116 |
117 | for (i = 0; i < nthreads; i++) {
118 | pthread_t tid;
119 | ids[i] = i+1;
120 |
121 | rc = pthread_create(&tid, NULL, reader, &ids[i]);
122 | if (rc != 0) {
123 | perror("pthread_create");
124 | exit(3);
125 | }
126 | }
127 |
128 | gettimeofday(&start, NULL);
129 | writer(cycles);
130 | gettimeofday(&end, NULL);
131 |
132 | if (end.tv_usec < start.tv_usec) {
133 | end.tv_sec--;
134 | end.tv_usec += 1000000;
135 | }
136 |
137 | fprintf(stdout, "%i %li\n", nthreads,
138 | ((end.tv_sec - start.tv_sec) * 1000000) + (end.tv_usec - start.tv_usec));
139 |
140 | return 0;
141 | }
142 |
--------------------------------------------------------------------------------
/rcu/plot:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env gnuplot
2 |
3 | set terminal png
4 | datafile = 'out.data'
5 |
6 | plot datafile using 1:2 with lines, \
7 | datafile using 1:3 with lines
8 |
--------------------------------------------------------------------------------
/rcu/qs/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include "../api.h"
7 |
8 | /*
9 |
10 | rcu/qs
11 |
12 | This is the _Quiescent State_ implementation of RCU for
13 | concurrent data sharing across multiple threads. Under
14 | QS, the threads are responsible for identifying their
15 | quiescent states (when they are no longer able to update
16 | the old copy of shared data).
17 |
18 | I could very well have gotten the implementation horribly
19 | wrong. Please bear with me here...
20 |
21 | */
22 |
23 | /* NUM_THREADS puts a fixed limit on the number of threads
24 | that can be spun up, such that we can use static arrays
25 | to imitate "weak" thread-local storage.
26 |
27 | This is one of many concessions that an application
28 | wishing to take advantage of quiescent state-based RCU
29 | needs to make, and why QSBR may not be universally
30 | applicable (i.e. via a library) */
31 | #define NUM_THREADS 128
32 |
33 | /* NO_THREAD is a _sigil value_ that identifies if a slot
34 | in a per-thread variable is available (set to NO_THREAD)
35 | or occupied (set to anything else). */
36 | #define NO_THREAD ((pthread_t)(0UL))
37 |
38 | /* Define a per-thread variable, for the calling thread.
39 |
40 | We imitate a weaker form of true thread-local storage by
41 | using an array of things, with enough elements
42 | to store a distinct value for up to NUM_THREADS.
43 |
44 | The "weak" adjective refers to the ability for other
45 | threads to peer into the variable scope of other threads,
46 | which is impossible with POSIX pthreads thead-local
47 | implementations. */
48 | #define DEFINE_PER_THREAD(type,name) static type __per_thread_ ## name[NUM_THREADS]
49 | #define for_each_thread(t) for (t = 0; t < NUM_THREADS; t++)
50 |
51 | pthread_mutex_t tid_lock;
52 | DEFINE_PER_THREAD(pthread_t, tid) = {0};
53 |
54 | /* Retrieve a per-thread variable, for the calling thread. */
55 | #define MY(var) THEIR(_thread_index(pthread_self()), var)
56 |
57 | /* Retrieve a per-thread variable, for some other thread. */
58 | #define THEIR(idx,var) __per_thread_##var[idx]
59 |
60 | static inline
61 | int _thread_index(pthread_t tid)
62 | {
63 | int t;
64 | for_each_thread(t) {
65 | if (__per_thread_tid[t] == tid) {
66 | return t;
67 | }
68 | }
69 | fprintf(stderr, "unrecognized thread %p\n", tid);
70 | exit(1);
71 | }
72 |
73 | static inline
74 | void register_thread()
75 | {
76 | int t;
77 |
78 | lock(&tid_lock);
79 | for_each_thread(t) {
80 | if (__per_thread_tid[t] == NO_THREAD) {
81 | __per_thread_tid[t] = pthread_self();
82 | unlock(&tid_lock);
83 | return;
84 | }
85 | }
86 | fprintf(stderr, "self-destruct: unable to register %p - out of thread slots\n", pthread_self());
87 | exit(1);
88 | }
89 |
90 | static inline
91 | void deregister_thread()
92 | {
93 | MY(tid) = NO_THREAD;
94 | }
95 |
96 | /* Prevent compiler optimizations for memory access */
97 | /* (use of `volatile' keyword stops most sane compilers
98 | from duplicating de-duplicating variable / register access) */
99 | #define ONCE(x) (*(volatile typeof(x) *)&(x))
100 |
101 | /* Prevent compiler optimizations for memory reordering
102 | (this is a compile-time barrier to ensure that the optimizer
103 | doesn't try to "improve" how we access memory, and thereby
104 | ruin our carefully crafted concurrent code) */
105 | #define barrier() asm volatile("" ::: "memory")
106 |
107 | pthread_mutex_t rcu_gp_lock;
108 | long rcu_gp_ctr = 0;
109 | DEFINE_PER_THREAD(long, rcu_reader_qs_gp);
110 |
111 | static inline void rcu_read_lock(void)
112 | {
113 | }
114 |
115 | static inline void rcu_read_unlock(void)
116 | {
117 | }
118 |
119 | static inline void rcu_quiescent_state(void)
120 | {
121 | barrier();
122 | MY(rcu_reader_qs_gp) = ONCE(rcu_gp_ctr) + 1;
123 | barrier();
124 | }
125 |
126 | static inline void rcu_thread_offline(void)
127 | {
128 | barrier();
129 | MY(rcu_reader_qs_gp) = ONCE(rcu_gp_ctr);
130 | }
131 | static inline void rcu_thread_online(void)
132 | {
133 | MY(rcu_reader_qs_gp) = ONCE(rcu_gp_ctr) + 1;
134 | barrier();
135 | }
136 |
137 | static inline int rcu_gp_ongoing(int idx)
138 | {
139 | return THEIR(idx, rcu_reader_qs_gp) & 1;
140 | }
141 |
142 | void synchronize_rcu(void)
143 | {
144 | int t;
145 |
146 | barrier();
147 | lock(&rcu_gp_lock);
148 | rcu_gp_ctr += 2;
149 | for_each_thread(t) {
150 | while (rcu_gp_ongoing(t) &&
151 | ((THEIR(t, rcu_reader_qs_gp) - rcu_gp_ctr) < 0)) {
152 | poll(NULL, 0, 10);
153 | barrier();
154 | }
155 | }
156 | unlock(&rcu_gp_lock);
157 | barrier();
158 | }
159 |
160 | /***********************************************************/
161 |
162 | pthread_mutex_t LOCK;
163 | unsigned long long *COUNTER;
164 |
165 | static inline
166 | void writer(int cycles)
167 | {
168 | unsigned long long *OLD, *NEW;
169 |
170 | while (cycles--) {
171 |
172 | NEW = xmalloc(sizeof(*NEW));
173 |
174 | lock(&LOCK);
175 | OLD = COUNTER;
176 | *NEW = *OLD + 1;
177 | COUNTER = NEW;
178 | unlock(&LOCK);
179 |
180 | fprintf(stderr, "[writer] incremented COUNTER to %llu\n", *NEW);
181 |
182 | synchronize_rcu();
183 | free(OLD);
184 | }
185 | }
186 |
187 | static inline
188 | void sleep_ms(int ms)
189 | {
190 | struct timespec tv;
191 | tv.tv_sec = 0;
192 | tv.tv_nsec = ms * 1000000;
193 | nanosleep(&tv, NULL);
194 | }
195 |
196 | void* reader(void *_)
197 | {
198 | int id = *(int *)_;
199 |
200 | register_thread();
201 |
202 | for (;;) {
203 | rcu_read_lock();
204 | fprintf(stderr, "[t%d] read COUNTER at %llu\n", id, *(ONCE(COUNTER)));
205 | // sleep_ms(10);
206 | rcu_read_unlock();
207 | rcu_quiescent_state();
208 | }
209 |
210 | return _;
211 | }
212 |
213 | static void rcu_init()
214 | {
215 | int rc;
216 |
217 | make_lock(&rcu_gp_lock);
218 | make_lock(&tid_lock);
219 | }
220 |
221 | int main(int argc, char **argv)
222 | {
223 | struct timeval start, end;
224 | pthread_t tid;
225 | int rc, i, nthreads, cycles, *ids;
226 | void *status;
227 |
228 | if (argc != 3) {
229 | fprintf(stderr, "USAGE: %s THREADS CYCLES\n", argv[0]);
230 | exit(2);
231 | }
232 |
233 | nthreads = atoi(argv[1]);
234 | cycles = atoi(argv[2]);
235 | if (nthreads < 1) {
236 | fprintf(stderr, "Invalid THREADS value %s (must be > 0)\n", argv[1]);
237 | fprintf(stderr, "USAGE: %s THREADS CYCLES\n", argv[0]);
238 | exit(2);
239 | }
240 | if (cycles < 1) {
241 | fprintf(stderr, "Invalid WRITE_CYCLES value %s (must be > 0)\n", argv[2]);
242 | fprintf(stderr, "USAGE: %s THREADS CYCLES\n", argv[0]);
243 | exit(2);
244 | }
245 |
246 | rcu_init();
247 |
248 | make_lock(&LOCK);
249 | ids = xcalloc(nthreads, sizeof(int));
250 | COUNTER = xcalloc(1, sizeof(unsigned long long));
251 |
252 | for (i = 0; i < nthreads; i++) {
253 | ids[i] = i+1;
254 | spin_up(reader, &ids[i]);
255 | }
256 |
257 | //sleep_ms(9);
258 | gettimeofday(&start, NULL);
259 | writer(cycles);
260 | gettimeofday(&end, NULL);
261 |
262 | if (end.tv_usec < start.tv_usec) {
263 | end.tv_sec--;
264 | end.tv_usec += 1000000;
265 | }
266 |
267 | fprintf(stdout, "%i %li\n", nthreads,
268 | ((end.tv_sec - start.tv_sec) * 1000000) + (end.tv_usec - start.tv_usec));
269 |
270 | return 0;
271 | }
272 |
--------------------------------------------------------------------------------
/rcu/report:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -ex
3 |
4 | rm -fr tmp/ && mkdir -p tmp/
5 | for x in 1 2 4 8 12 16 20 24 32 40 48 64 96 128; do ./run-lock $x 10000 2>/dev/null >> tmp/lock.data; done
6 | for x in 1 2 4 8 12 16 20 24 32 40 48 64 96 128; do ./run-qs $x 10000 2>/dev/null >> tmp/qs.data; done
7 | join tmp/lock.data tmp/qs.data
8 | rm -fr tmp/
9 |
--------------------------------------------------------------------------------
/regm/.gitignore:
--------------------------------------------------------------------------------
1 | regm
2 | asm
3 | *.o
4 | *.b
5 | *.s
6 |
--------------------------------------------------------------------------------
/regm/Makefile:
--------------------------------------------------------------------------------
1 | CFLAGS := -g -Wall
2 | LDLIBS := -lvigor
3 |
4 | BINARIES :=
5 | BINARIES += regm
6 | BINARIES += asm
7 |
8 | EXAMPLES_SRC := $(shell ls -1 pn/*.pn)
9 | EXAMPLES_BIN := $(shell ls -1 pn/*.pn | sed -e 's/\.pn/.b/')
10 |
11 | ################################################
12 | # DUMMY TARGETS
13 |
14 | default: $(BINARIES)
15 | clean:
16 | rm -f *.o asm regm
17 | rm -f $(EXAMPLES_BIN)
18 |
19 | test: default
20 | ./regm
21 |
22 | examples: $(EXAMPLES_BIN)
23 |
24 |
25 | ################################################
26 | # BINARY targets
27 |
28 | regm: regm.o
29 | asm: asm.o
30 |
31 | ################################################
32 | # SUPPORTING targets
33 |
34 | opcodes.h: opcodes.yml gencode
35 | ./gencode opcodes > $@
36 |
37 | pn/%.b: pn/%.pn asm
38 | ./asm <$< >$@
39 |
--------------------------------------------------------------------------------
/regm/README.md:
--------------------------------------------------------------------------------
1 | regm - jameshunt(.us) Research
2 | ==============================
3 |
4 | Research into register machine design and implementation, for PN.2, the
5 | second iteration of the [Clockwork][clockwork] Pendulum Virtual Machine.
6 |
7 | [clockwork]: https://github.com/filefrog/clockwork
8 |
--------------------------------------------------------------------------------
/regm/asm.c:
--------------------------------------------------------------------------------
1 | #define _POSIX_C_SOURCE 200809L
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include "regm.h"
8 |
9 | #define OPCODES_EXTENDED
10 | #include "opcodes.h"
11 |
12 | static const char * VTYPES[] = {
13 | "NONE",
14 | "register",
15 | "number",
16 | "string",
17 | "address",
18 | "label",
19 | "offset",
20 | "fnlabel",
21 | NULL,
22 | };
23 |
24 | #define VALUE_NONE 0x0
25 | #define VALUE_REGISTER 0x1
26 | #define VALUE_NUMBER 0x2
27 | #define VALUE_STRING 0x3
28 | #define VALUE_ADDRESS 0x4
29 | #define VALUE_LABEL 0x5
30 | #define VALUE_FNLABEL 0x6
31 | #define VALUE_OFFSET 0x7
32 |
33 | #define TYPE_LITERAL 0x1
34 | #define TYPE_REGISTER 0x2
35 | #define TYPE_ADDRESS 0x3
36 |
37 | typedef struct {
38 | byte_t type;
39 | byte_t bintype;
40 | union {
41 | char regname; /* register (a, c, etc.) */
42 | dword_t literal; /* literal value */
43 | char *string; /* string value */
44 | dword_t address; /* memory address */
45 | char *label; /* for labelled jumps */
46 | char *fnlabel; /* for labelled jumps */
47 | dword_t offset; /* for relative jumps */
48 | } _;
49 | } value_t;
50 |
51 | #define SPECIAL_LABEL 1
52 | #define SPECIAL_FUNC 2
53 | typedef struct {
54 | byte_t special; /* identify special, non-code markers */
55 | char *label; /* special label */
56 | void *fn; /* link to the FN that starts scope */
57 |
58 | byte_t op; /* opcode number, for final encoding */
59 | value_t args[2]; /* operands */
60 |
61 | dword_t offset; /* byte offset in opcode binary stream */
62 | list_t l;
63 | } op_t;
64 |
65 | typedef struct {
66 | const char *name; /* name of the flag (for source correlation) */
67 | dword_t idx; /* index into heap array (address) */
68 | list_t l;
69 | } flag_t;
70 |
71 | typedef struct {
72 | byte_t *mem;
73 | size_t total;
74 | size_t used;
75 | size_t burst;
76 | dword_t offset;
77 | } static_t;
78 |
79 | list_t OPS;
80 | static_t STATIC;
81 | byte_t *CODE;
82 |
83 |
84 | #define LINE_BUF_SIZE 8192
85 | typedef struct {
86 | FILE *io;
87 | const char *file;
88 | int line;
89 | int token;
90 | char value[LINE_BUF_SIZE];
91 | char buffer[LINE_BUF_SIZE];
92 | char raw[LINE_BUF_SIZE];
93 | } parser_t;
94 |
95 | #define T_REGISTER 0x01
96 | #define T_LABEL 0x02
97 | #define T_IDENTIFIER 0x03
98 | #define T_OFFSET 0x04
99 | #define T_NUMBER 0x05
100 | #define T_STRING 0x06
101 | #define T_OPCODE 0x07
102 | #define T_FUNCTION 0x08
103 | #define T_TOPIC 0x09
104 |
105 | static const char * T_names[] = {
106 | "(NONE)",
107 | "T_REGISTER",
108 | "T_LABEL",
109 | "T_IDENTIFIER",
110 | "T_OFFSET",
111 | "T_NUMBER",
112 | "T_STRING",
113 | "T_OPCODE",
114 | "T_FUNCTION",
115 | "T_TOPIC",
116 | NULL,
117 | };
118 |
119 | static int lex(parser_t *p)
120 | {
121 | char *a, *b;
122 | if (!*p->buffer || *p->buffer == ';') {
123 | getline:
124 | if (!fgets(p->raw, LINE_BUF_SIZE, p->io))
125 | return 0;
126 | p->line++;
127 |
128 | a = p->raw;
129 | while (*a && isspace(*a)) a++;
130 | if (*a == ';')
131 | while (*a && *a != '\n') a++;
132 | while (*a && isspace(*a)) a++;
133 | if (!*a)
134 | goto getline;
135 |
136 | b = p->buffer;
137 | while ((*b++ = *a++));
138 | }
139 | p->token = 0;
140 | p->value[0] = '\0';
141 |
142 | b = p->buffer;
143 | while (*b && isspace(*b)) b++;
144 | a = b;
145 |
146 | if (*b == '%') { /* register */
147 | while (!isspace(*b)) b++;
148 | if (!*b || isspace(*b)) {
149 | *b = '\0';
150 | char reg = 0;
151 | if (b - a == 2)
152 | reg = *(a + 1);
153 | if (reg < 'a' || reg >= 'a'+NREGS) {
154 | logger(LOG_ERR, "%s:%i: unrecognized register address %s (%i)", p->file, p->line, a, reg);
155 | return 0;
156 | }
157 |
158 | p->token = T_REGISTER;
159 | p->value[0] = reg;
160 | p->value[1] = '\0';
161 |
162 | b++; while (*b && isspace(*b)) b++;
163 | memmove(p->buffer, b, strlen(b)+1);
164 | return 1;
165 | }
166 | b = a;
167 | }
168 |
169 | if (*b == '+' || *b == '-') {
170 | b++;
171 | while (*b && isdigit(*b)) b++;
172 | if (!*b || isspace(*b)) {
173 | *b++ = '\0';
174 |
175 | p->token = T_OFFSET;
176 | memcpy(p->value, p->buffer, b-p->buffer);
177 |
178 | while (*b && isspace(*b)) b++;
179 | memmove(p->buffer, b, strlen(b)+1);
180 | return 1;
181 | }
182 | b = a;
183 | }
184 |
185 | if (isdigit(*b)) {
186 | if (*b == '0' && *(b+1) == 'x') {
187 | b += 2;
188 | while (*b && isxdigit(*b)) b++;
189 | } else {
190 | while (*b && isdigit(*b)) b++;
191 | }
192 | if (!*b || isspace(*b)) {
193 | *b++ = '\0';
194 |
195 | p->token = T_NUMBER;
196 | memcpy(p->value, p->buffer, b-p->buffer);
197 |
198 | while (*b && isspace(*b)) b++;
199 | memmove(p->buffer, b, strlen(b)+1);
200 | return 1;
201 | }
202 | b = a;
203 | }
204 |
205 | if (isalpha(*b)) {
206 | while (*b && !isspace(*b) && *b != ':')
207 | b++;
208 | if (*b == ':') {
209 | *b++ = '\0';
210 | p->token = T_LABEL;
211 | memcpy(p->value, p->buffer, b-p->buffer);
212 | while (*b && isspace(*b)) b++;
213 | memmove(p->buffer, b, strlen(b)+1);
214 | return 1;
215 | }
216 | b = a;
217 |
218 | while (*b && (isalnum(*b) || *b == '.' || *b == '_' || *b == '?'))
219 | b++;
220 | *b++ = '\0';
221 |
222 | int i;
223 | for (i = 0; ASM[i]; i++) {
224 | if (strcmp(a, ASM[i]) != 0) continue;
225 | p->token = T_OPCODE;
226 | p->value[0] = T_OPCODE_NOOP + i;
227 | p->value[1] = '\0';
228 | break;
229 | }
230 |
231 | if (strcmp(a, "fn") == 0) p->token = T_FUNCTION;
232 |
233 | if (!p->token) {
234 | p->token = T_IDENTIFIER;
235 | memcpy(p->value, p->buffer, b-p->buffer);
236 | }
237 |
238 | while (*b && isspace(*b)) b++;
239 | memmove(p->buffer, b, strlen(b)+1);
240 | return 1;
241 | }
242 |
243 | if (*b == '"') {
244 | b++; a = p->value;
245 | while (*b && *b != '"' && *b != '\r' && *b != '\n') {
246 | if (*b == '\\') {
247 | b++;
248 | switch (*b) {
249 | case 'n': *a = '\n'; break;
250 | case 'r': *a = '\r'; break;
251 | case 't': *a = '\t'; break;
252 | default: *a = *b;
253 | }
254 | a++; b++;
255 | } else *a++ = *b++;
256 | }
257 | *a = '\0';
258 | if (*b == '"') b++;
259 | else logger(LOG_WARNING, "%s:%i: unterminated string literal", p->file, p->line);
260 |
261 | p->token = T_STRING;
262 | while (*b && isspace(*b)) b++;
263 | memmove(p->buffer, b, strlen(b)+1);
264 | return 1;
265 | }
266 |
267 | if (*b == '@') {
268 | int n = 0;
269 | while (*b == '@') { n++; b++; }
270 | if (n > 2) {
271 | p->token = T_TOPIC;
272 | while (*b && isspace(*b)) b++;
273 | a = b;
274 | while (*b && !isspace(*b)) b++;
275 | *b++ = '\0';
276 | memcpy(p->value, a, b-a);
277 |
278 | while (*b && isspace(*b)) b++;
279 | memmove(p->buffer, b, strlen(b)+1);
280 | return 1;
281 | }
282 | b = a;
283 | }
284 |
285 |
286 | logger(LOG_ERR, "%s:%i: failed to parse '%s'", p->file, p->line, p->buffer);
287 | return 0;
288 | }
289 |
290 | static int parse(void)
291 | {
292 | parser_t p;
293 | memset(&p, 0, sizeof(p));
294 | p.file = strdup("");
295 | p.io = stdin;
296 |
297 | op_t *FN = NULL;
298 | list_init(&OPS);
299 |
300 | #define NEXT if (!lex(&p)) { logger(LOG_CRIT, "%s:%i: unexpected end of configuration\n", p.file, p.line); goto bail; }
301 | #define ERROR(s) do { logger(LOG_CRIT, "%s:%i: syntax error: %s", p.file, p.line, s); goto bail; } while (0)
302 |
303 | int i, j;
304 | op_t *op;
305 | while (lex(&p)) {
306 |
307 | if (!p.value[0])
308 | fprintf(stderr, "%02x %-14s\n", p.token, T_names[p.token]);
309 | else if (p.token == T_OPCODE)
310 | fprintf(stderr, "%02x %-14s : %#04x (%s)\n", p.token, T_names[p.token],
311 | p.value[0] & 0xff, ASM[(p.value[0] & 0xff) - T_OPCODE_NOOP]);
312 | else
313 | fprintf(stderr, "%02x %-14s : %s\n", p.token, T_names[p.token], p.value);
314 |
315 | op = calloc(1, sizeof(op_t));
316 | op->fn = FN;
317 |
318 | switch (p.token) {
319 | case T_TOPIC:
320 | break;
321 |
322 | case T_FUNCTION:
323 | if (FN && list_tail(&OPS, op_t, l)->op != RET) {
324 | op->op = RET;
325 | list_push(&OPS, &op->l);
326 | op = calloc(1, sizeof(op_t));
327 | }
328 | FN = op;
329 | op->special = SPECIAL_FUNC;
330 | NEXT;
331 | if (p.token != T_IDENTIFIER)
332 | ERROR("unacceptable name for function");
333 | op->label = strdup(p.value);
334 | break;
335 |
336 | case T_LABEL:
337 | op->special = SPECIAL_LABEL;
338 | op->label = strdup(p.value);
339 | break;
340 |
341 | case T_OPCODE:
342 | for (i = 0; ASM_SYNTAX[i].token; i++) {
343 | if (p.value[0] != ASM_SYNTAX[i].token) continue;
344 | op->op = ASM_SYNTAX[i].opcode;
345 |
346 | for (j = 0; j < 2; j++) {
347 | if (ASM_SYNTAX[i].args[j] == ARG_NONE) break;
348 | NEXT;
349 |
350 | if (p.token == T_REGISTER && ASM_SYNTAX[i].args[j] & ARG_REGISTER) {
351 | op->args[j].type = VALUE_REGISTER;
352 | op->args[j]._.regname = p.value[0];
353 |
354 | } else if (p.token == T_NUMBER && ASM_SYNTAX[i].args[j] & ARG_NUMBER) {
355 | op->args[j].type = VALUE_NUMBER;
356 | op->args[j]._.literal = strtol(p.value, NULL, 0);
357 |
358 | } else if (p.token == T_STRING && ASM_SYNTAX[i].args[j] & ARG_STRING) {
359 | op->args[j].type = VALUE_STRING;
360 | op->args[j]._.string = strdup(p.value);
361 |
362 | } else if (p.token == T_IDENTIFIER && ASM_SYNTAX[i].args[j] & ARG_LABEL) {
363 | op->args[j].type = VALUE_LABEL;
364 | op->args[j]._.label = strdup(p.value);
365 |
366 | } else if (p.token == T_IDENTIFIER && ASM_SYNTAX[i].args[j] & ARG_FUNCTION) {
367 | op->args[j].type = VALUE_FNLABEL;
368 | op->args[j]._.fnlabel = strdup(p.value);
369 |
370 | } else if (p.token == T_OFFSET && ASM_SYNTAX[i].args[j] & ARG_LABEL) {
371 | op->args[j].type = VALUE_OFFSET;
372 | op->args[j]._.offset = strtol(p.value, NULL, 10);
373 |
374 | } else {
375 | logger(LOG_CRIT, "%s: %i: invalid form; expected `%s`",
376 | p.file, p.line, ASM_SYNTAX[i].usage);
377 | goto bail;
378 | }
379 | }
380 | break;
381 | }
382 | break;
383 |
384 | case T_REGISTER: ERROR("unexpected register reference found at top-level");
385 | case T_IDENTIFIER: ERROR("unexpected identifier found at top-level");
386 | case T_OFFSET: ERROR("unexpected offset found at top-level");
387 | case T_NUMBER: ERROR("unexpected numeric literal found at top-level");
388 | case T_STRING: ERROR("unexpected string literal found at top-level");
389 |
390 | default:
391 | ERROR("unhandled token type");
392 | }
393 |
394 | list_push(&OPS, &op->l);
395 | }
396 |
397 | if (FN && list_tail(&OPS, op_t, l)->op != RET) {
398 | op = calloc(1, sizeof(op_t));
399 | op->op = RET;
400 | list_push(&OPS, &op->l);
401 | }
402 | return 0;
403 |
404 | bail:
405 | return 1;
406 | }
407 |
408 | hash_t strings;
409 | static int s_resolve(value_t *v, op_t *me)
410 | {
411 | byte_t *addr;
412 | size_t len;
413 | op_t *op, *fn;
414 |
415 | switch (v->type) {
416 | case VALUE_REGISTER:
417 | v->bintype = TYPE_REGISTER;
418 | v->_.literal -= 'a';
419 | return 0;
420 |
421 | case VALUE_NUMBER:
422 | v->bintype = TYPE_LITERAL;
423 | return 0;
424 |
425 | case VALUE_STRING:
426 | addr = hash_get(&strings, v->_.string);
427 | if (!addr) {
428 | len = strlen(v->_.string) + 1;
429 | if (STATIC.total - STATIC.used < len) {
430 | /* FIXME: only works for strings < STATIC.burst */
431 | byte_t *mem = realloc(STATIC.mem, STATIC.total + STATIC.burst);
432 | if (!mem) perror("realloc");
433 |
434 | STATIC.mem = mem;
435 | STATIC.total += STATIC.burst;
436 | }
437 | memcpy(STATIC.mem + STATIC.used, v->_.string, len);
438 | fprintf(stderr, "s_resolve: relocated string %s to %#010x\n",
439 | v->_.string, (unsigned)(STATIC.offset + STATIC.used));
440 |
441 | addr = STATIC.mem + STATIC.used;
442 | hash_set(&strings, v->_.string, addr);
443 | STATIC.used += len;
444 | }
445 |
446 | free(v->_.string);
447 |
448 | v->type = VALUE_ADDRESS;
449 | v->bintype = TYPE_ADDRESS;
450 | v->_.address = STATIC.offset + (addr - STATIC.mem);
451 | return 0;
452 |
453 | case VALUE_ADDRESS:
454 | v->bintype = TYPE_ADDRESS;
455 | return 0;
456 |
457 | case VALUE_LABEL:
458 | fn = (op_t*)me->fn;
459 | for_each_object(op, &fn->l, l) {
460 | if (op->special == SPECIAL_FUNC) break;
461 | if (op->special != SPECIAL_LABEL) continue;
462 | if (strcmp(v->_.label, op->label) != 0) continue;
463 |
464 | free(v->_.label);
465 | v->type = VALUE_ADDRESS;
466 | v->bintype = TYPE_ADDRESS;
467 | v->_.address = op->offset;
468 | return 0;
469 | }
470 | logger(LOG_ERR, "label %s not found in scope!", v->_.label);
471 | return 1;
472 |
473 | case VALUE_FNLABEL:
474 | for_each_object(op, &me->l, l) {
475 | if (op->special != SPECIAL_FUNC) continue;
476 | if (strcmp(v->_.fnlabel, op->label) != 0) continue;
477 |
478 | free(v->_.fnlabel);
479 | v->type = VALUE_ADDRESS;
480 | v->bintype = TYPE_ADDRESS;
481 | v->_.address = op->offset;
482 | return 0;
483 | }
484 | logger(LOG_ERR, "fnlabel %s not found globally!", v->_.fnlabel);
485 | return 1;
486 |
487 | case VALUE_OFFSET:
488 | for_each_object(op, &me->l, l) {
489 | if (op->special) continue;
490 | if (v->_.offset--) continue;
491 |
492 | v->type = VALUE_ADDRESS;
493 | v->bintype = TYPE_ADDRESS;
494 | v->_.address = op->offset;
495 | return 0;
496 | }
497 | return 1;
498 | }
499 | return 0;
500 | }
501 |
502 | static int compile(void)
503 | {
504 | /* phases of compilation:
505 |
506 | I. insert runtime at addr 0
507 | II. determine offset of each opcode
508 | III. resolve labels / relative addresses
509 | IV. pack 'external memory' data
510 | V. encode
511 | */
512 |
513 | memset(&STATIC, 0, sizeof(STATIC));
514 | STATIC.burst = 256 * 1024;
515 |
516 | op_t *op;
517 | int rc;
518 |
519 | /* phase I: runtime insertion */
520 | op = calloc(1, sizeof(op_t));
521 | op->op = JMP; /* JMP, don't CALL */
522 | op->args[0].type = VALUE_FNLABEL;
523 | op->args[0]._.label = strdup("main");
524 | list_unshift(&OPS, &op->l);
525 |
526 | /* phase II: calculate offsets */
527 | dword_t offset = 0;
528 | for_each_object(op, &OPS, l) {
529 | op->offset = offset;
530 | if (op->special) continue;
531 | offset += 2; /* 2-byte opcode */
532 | if (op->args[0].type != VALUE_NONE) offset += 4; /* 4-byte operand */
533 | if (op->args[1].type != VALUE_NONE) offset += 4; /* 4-byte operand */
534 | }
535 | STATIC.offset = offset;
536 | CODE = calloc(offset, sizeof(byte_t));
537 | byte_t *c = CODE;
538 |
539 | for_each_object(op, &OPS, l) {
540 | if (op->special) continue;
541 |
542 | /* phase II/III: resolve labels / pack strings */
543 | rc = s_resolve(&op->args[0], op);
544 | assert(rc == 0);
545 | rc = s_resolve(&op->args[1], op);
546 | assert(rc == 0);
547 |
548 | /* phase IV: encode */
549 | *c++ = op->op;
550 | *c++ = ((op->args[0].bintype & 0xff) << 4)
551 | | ((op->args[1].bintype & 0xff));
552 |
553 | if (op->args[0].type) {
554 | *c++ = ((op->args[0]._.literal >> 24) & 0xff);
555 | *c++ = ((op->args[0]._.literal >> 16) & 0xff);
556 | *c++ = ((op->args[0]._.literal >> 8) & 0xff);
557 | *c++ = ((op->args[0]._.literal >> 0) & 0xff);
558 | }
559 | if (op->args[1].type) {
560 | *c++ = ((op->args[1]._.literal >> 24) & 0xff);
561 | *c++ = ((op->args[1]._.literal >> 16) & 0xff);
562 | *c++ = ((op->args[1]._.literal >> 8) & 0xff);
563 | *c++ = ((op->args[1]._.literal >> 0) & 0xff);
564 | }
565 | }
566 |
567 | return 0;
568 | }
569 |
570 | int main(int argc, char **argv)
571 | {
572 | log_open("asm", "console");
573 |
574 | int rc = parse();
575 | assert(rc == 0);
576 |
577 | rc = compile();
578 | assert(rc == 0);
579 |
580 | op_t *op;
581 | for_each_object(op, &OPS, l) {
582 | fprintf(stderr, "%08x [%04x] %s\n", op->offset, op->op, OPCODES[op->op]);
583 | if (op->args[0].type != VALUE_NONE) {
584 | fprintf(stderr, "%8s 1: %s (%i)\n", " ", VTYPES[op->args[0].type], op->args[0].type);
585 | switch (op->args[0].type) {
586 | case VALUE_NUMBER: fprintf(stderr, "%11s= %i\n", " ", op->args[0]._.literal); break;
587 | case VALUE_LABEL: fprintf(stderr, "%11s @%s\n", " ", op->args[0]._.label); break;
588 | case VALUE_STRING: fprintf(stderr, "%11s \"%s\"\n", " ", op->args[0]._.string); break;
589 | case VALUE_ADDRESS: fprintf(stderr, "%11s %#010x\n", " ", op->args[0]._.address); break;
590 | }
591 | }
592 | if (op->args[1].type != VALUE_NONE) {
593 | fprintf(stderr, "%8s 2: %s (%i)\n", " ", VTYPES[op->args[1].type], op->args[1].type);
594 | switch (op->args[1].type) {
595 | case VALUE_NUMBER: fprintf(stderr, "%11s= %i\n", " ", op->args[1]._.literal); break;
596 | case VALUE_LABEL: fprintf(stderr, "%11s @%s\n", " ", op->args[1]._.label); break;
597 | case VALUE_STRING: fprintf(stderr, "%11s \"%s\"\n", " ", op->args[1]._.string); break;
598 | case VALUE_ADDRESS: fprintf(stderr, "%11s %0#10x\n", " ", op->args[1]._.address); break;
599 | }
600 | }
601 | fprintf(stderr, "\n");
602 | }
603 |
604 | write(1, CODE, STATIC.offset);
605 | write(1, STATIC.mem, STATIC.used);
606 |
607 | return 0;
608 | }
609 |
--------------------------------------------------------------------------------
/regm/file.p:
--------------------------------------------------------------------------------
1 | ; these are comments
2 |
3 | fn res.file.absent
4 | fs.stat %a
5 | jz +1
6 | retv 0
7 |
8 | fs.file? %a
9 | jz rm
10 |
11 | fs.symlink? %a
12 | jz rm
13 |
14 | err "%s exists, but is not a regular file"
15 | bail
16 |
17 | rm:
18 | fs.unlink %a
19 | jnz +2
20 | mark
21 | retv 0
22 |
23 | perror "failed to remove %s"
24 | bail
25 |
26 | fn res.file.present
27 | fs.stat %a
28 | jnz create
29 |
30 | fs.symlink? %a
31 | jz remove
32 |
33 | err "%s exists, but is not a regular file"
34 | bail
35 |
36 | remove:
37 | fs.unlink %a
38 | jz create
39 |
40 | perror "failed to replace %s with a regular file"
41 | bail
42 |
43 | create:
44 | fs.touch %a
45 | jnz +2
46 | mark
47 | retv 0
48 |
49 | perror "failed to create regular file %s"
50 | bail
51 |
52 | fn res.file.chown
53 | getuid %b %c
54 | jz ok
55 |
56 | ; re-arrange registers for err call
57 | set %a %b ; %a is now the username, too
58 | err "failed to find user %s"
59 | bail
60 |
61 | ok:
62 | fs.chown %a %c
63 | jnz +2
64 | mark
65 | retv 0
66 |
67 | perror "failed to change ownership of %s to %s"
68 | bail
69 |
70 | fn res.file.chgrp
71 | getgid %b %c
72 | jz ok
73 |
74 | ; re-arrange registers for err call
75 | set %a %b ; %a is now the group name, too
76 | err "failed to find group %s"
77 | bail
78 |
79 | ok:
80 | fs.chgrp %a %c
81 | jnz +2
82 | mark
83 | retv 0
84 |
85 | perror "failed to change group ownership of %s to %s: %s"
86 | bail
87 |
88 | fn res.file.chmod
89 | fs.chmod %a %b
90 | jnz +2
91 | mark
92 | retv 0
93 |
94 | perror "failed to set mode of %s to %04o: %s"
95 | bail
96 |
97 | fn res.file.diff
98 | ; %a is path
99 | ; %b is remote sha1
100 |
101 | fs.sha1 %a %p
102 | jz +2
103 | perror "failed to calculate SHA1 for local copy of %s"
104 | bail
105 |
106 | strcmp %b %p
107 | ret
108 |
109 | fn res.file.update
110 | ; %a is path
111 | ; %b is remote sha1
112 | ; %c is cached/not
113 |
114 | getfile %b %a
115 | jnz +1
116 | ret
117 |
118 | err "failed to update contents of %s"
119 | bail
120 |
121 | fn res.file.verify
122 | ; %a is temp path
123 | ; %b is real path
124 | ; %c is verify command
125 | ; %d is expected rc
126 |
127 | push %b
128 | push %a
129 |
130 | set %a 0 ; run as user root
131 | set %b 0 ; run as group root
132 |
133 | exec %c %e
134 | cmp %d %e
135 | jz +1
136 | ret
137 |
138 | pop %a
139 | pop %b
140 | fs.rename %a %b
141 | jnz +1
142 | retv 0
143 |
144 | fs.unlink %a
145 | perror "failed to rename %s to %s"
146 | bail
147 |
148 | fn res.file.contents
149 | ; %a is path
150 | ; %b is remote sha1
151 | ; %c is cached/not
152 | ; %d is verify/not
153 | ; %e is verify command
154 | ; %f is expected rc
155 | ; %g is tempfile
156 |
157 | call res.file.diff
158 | jnz +1
159 | ret
160 |
161 | ;; files differ
162 | cmp %d 1 ; should we use %g (tempfile)
163 | jnz update ; in place of %a (real path)?
164 |
165 | swap %g %a ; yes. update the contents of
166 | ; the tempfile first, so we can
167 | ; run the verify (%e) command
168 |
169 | update:
170 | call res.file.update ; no need to check return value
171 | ; res.file.update will bail if
172 | ; there were any problems
173 |
174 | cmp %d 1 ; run the verification?
175 | jz verify
176 | mark
177 | ret
178 |
179 | verify:
180 | set %b %g ; real path
181 | set %c %e ; verify command
182 | set %d %f ; expected rc
183 |
184 | call res.file.verify ; no need to check return value
185 | ; res.file.verify will bail if
186 | ; there are any problems
187 | mark
188 | retv 0
189 |
190 | fn main
191 | @@@ file:/path/to/delete
192 | set %a "/path/to/delete"
193 | call res.file.absent
194 |
195 | @@@ file:/etc/sudoers
196 | set %a "/etc/sudoers"
197 | call res.file.present
198 |
199 | ;;udbopen
200 | set %b "root"
201 | call res.file.chown
202 | set %b "root"
203 | call res.file.chgrp
204 | ;;udbclose
205 |
206 | set %b 0755
207 | call res.file.chmod
208 |
209 | set %b "decafbadcafe" ; rsha1
210 | set %c 1 ; cached
211 | set %d 1 ; do verify
212 | set %e "/bin/test-it -c /tmp/file"
213 | set %f 0
214 | set %g "/tmp/file"
215 | call res.file.contents
216 |
--------------------------------------------------------------------------------
/regm/gencode:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 |
3 | use strict;
4 | use warnings;
5 |
6 | use YAML::XS qw/LoadFile/;
7 | use List::Util qw/max/;
8 |
9 | my @cols = ();
10 | my @widths = ();
11 | sub column
12 | {
13 | @_ = map { "$_," } @_;
14 | if (!@cols) {
15 | @widths = map { 0 } @_;
16 | } else {
17 | for (my $i = 0; $i < @_; $i++) {
18 | $widths[$i] = max($widths[$i], length $_[$i]);
19 | }
20 | }
21 |
22 | push @cols, [@_];
23 | }
24 |
25 | sub table
26 | {
27 | my ($fmt) = @_;
28 | $fmt =~ s/%s/%-${_}s/ for @widths;
29 | printf $fmt, @$_ for @cols;
30 | }
31 |
32 | sub arg
33 | {
34 | my ($list, $reg) = @_;
35 | return ("", "ARG_NONE") if !$list || !@$list;
36 |
37 | my (@names, @flags);
38 | for (@$list) {
39 | if (m/register/) {
40 | push @names, $reg;
41 | push @flags, "ARG_REGISTER";
42 | } elsif (m/(number|string|function|label)/) {
43 | push @names, "<$1>";
44 | push @flags, uc("ARG_$1");
45 | } else {
46 | die "Unhandled arg type $_\n";
47 | }
48 | }
49 |
50 | return ((@names == 1 ? " $names[0]" : " (".join('|', @names).")"), join('|', @flags));
51 | }
52 |
53 | my $lst = eval { LoadFile "opcodes.yml" }
54 | or die "Failed to load opcoes.yml: $!\n";
55 |
56 | for my $op (@$lst) {
57 | my ($key, $o) = %$op;
58 | if (!$o->{constant}) {
59 | $o->{constant} = uc($key);
60 | $o->{constant} =~ s/\./_/g;
61 | $o->{constant} =~ s/\?$/_P/g;
62 | }
63 |
64 | $o->{opcode} = uc($o->{alias} || $o->{constant});
65 |
66 | my ($name, $flags);
67 | my $usage;
68 |
69 | $usage = $key;
70 | ($name, $flags) = arg($o->{args}[0], "%a");
71 | $usage .= $name; $o->{args}[0] = $flags;
72 |
73 | ($name, $flags) = arg($o->{args}[1], "%b");
74 | $usage .= $name; $o->{args}[1] = $flags;
75 |
76 | $o->{usage} = $usage if !$o->{usage};
77 | }
78 |
79 | my $n = 0;
80 | my $len = 0;
81 | for my $op (@$lst) {
82 | my ($key, $o) = %$op;
83 | $len = max($len, length($o->{constant}));
84 | $n++;
85 | }
86 |
87 | $n = 0;
88 | print "/* opcodes.h - generated by gencode */\n\n";
89 | print "/** OPCODE CONSTANTS **/\n";
90 | for my $op (@$lst) {
91 | my ($key, $o) = %$op;
92 | next if $o->{alias};
93 | printf "#define %-${len}s %#04x /* %s */\n", $o->{constant}, $n++, $o->{help};
94 | }
95 |
96 | print "\n\n";
97 | print "#ifdef OPCODES_EXTENDED\n";
98 | print "/** OPCODE MNEMONIC NAMES **/\n";
99 | print "static const char * OPCODES[] = {\n";
100 | $n = 0;
101 | for my $op (@$lst) {
102 | my ($key, $o) = %$op;
103 | next if $o->{alias};
104 | printf qq(\t%-@{[$len+3]}s /* %-${len}s %2i %#04x */\n), qq("$key",), $o->{constant}, $n, $n;
105 | $n++;
106 | }
107 | print "\tNULL,\n";
108 | print "};\n";
109 |
110 | print "\n\n";
111 | print "/** ASM TOKENS **/\n";
112 | $n = 0x40;
113 | for my $op (@$lst) {
114 | my ($key, $o) = %$op;
115 | printf "#define T_OPCODE_%-${len}s %#04x /* %s */\n", $o->{constant}, $n++, $o->{help};
116 | }
117 |
118 | print "\n\n";
119 | print "static const char * ASM[] = {\n";
120 | $n = 0;
121 | for my $op (@$lst) {
122 | my ($key, $o) = %$op;
123 | printf qq(\t%-@{[$len+3]}s /* T_OPCODE_%-${len}s %2i %#04x */\n), qq("$key",), $o->{constant}, $n, $n;
124 | $n++;
125 | }
126 | print "\tNULL,\n";
127 | print "};\n\n";
128 |
129 | print <{constant}", qq("$o->{usage}"), $o->{opcode}, $o->{args}[0], $o->{args}[1];
148 | }
149 | table "\t{ %s %s %s { %s %s } },\n";
150 | print "\t{ 0, 0, 0, { 0, 0 } },\n";
151 | print "};\n\n";
152 |
153 | print "#endif\n";
154 |
--------------------------------------------------------------------------------
/regm/opcodes.h:
--------------------------------------------------------------------------------
1 | /* opcodes.h - generated by gencode */
2 |
3 | /** OPCODE CONSTANTS **/
4 | #define NOOP 0000 /* does nothing */
5 | #define PUSH 0x01 /* push a register onto data stack */
6 | #define POP 0x02 /* pop data stack top into a register */
7 | #define SET 0x03 /* set register value */
8 | #define SWAP 0x04 /* swap two register values */
9 | #define ADD 0x05 /* add the second operand to the first */
10 | #define SUB 0x06 /* subtract the second operand from the first */
11 | #define MULT 0x07 /* multiply the first operand by the second */
12 | #define DIV 0x08 /* divide the first operand by the second */
13 | #define MOD 0x09 /* modulo the first operand by the second */
14 | #define CALL 0x0a /* call a user-defined function */
15 | #define RET 0x0b /* return to caller */
16 | #define CMP 0x0c /* compare two integers */
17 | #define STRCMP 0x0d /* compare two strings */
18 | #define JMP 0x0e /* unconditional jump */
19 | #define JZ 0x0f /* jump if accumulator is 0 */
20 | #define JNZ 0x10 /* jump if accumulator is not 0 */
21 | #define JE 0x11 /* jump if accumulator is equal to first operand */
22 | #define JNE 0x12 /* jump if accumulator is not equal to first operand */
23 | #define JGT 0x13 /* jump if accumulator is greater than first operand */
24 | #define JGTE 0x14 /* jump if accumulator is greater than or equal to first operand */
25 | #define JLT 0x15 /* jump if accumulator is less than first operand */
26 | #define JLTE 0x16 /* jump if accumulator is less than or equal to first operand */
27 | #define STRING 0x17 /* format a (heap-allocated) string */
28 | #define PRINT 0x18 /* print a message to standard output */
29 | #define DUMP 0x19 /* dump virtual machine state for debugging */
30 | #define HALT 0x1a /* halt the virtual machine */
31 |
32 |
33 | #ifdef OPCODES_EXTENDED
34 | /** OPCODE MNEMONIC NAMES **/
35 | static const char * OPCODES[] = {
36 | "noop", /* NOOP 0 0000 */
37 | "push", /* PUSH 1 0x01 */
38 | "pop", /* POP 2 0x02 */
39 | "set", /* SET 3 0x03 */
40 | "swap", /* SWAP 4 0x04 */
41 | "add", /* ADD 5 0x05 */
42 | "sub", /* SUB 6 0x06 */
43 | "mult", /* MULT 7 0x07 */
44 | "div", /* DIV 8 0x08 */
45 | "mod", /* MOD 9 0x09 */
46 | "call", /* CALL 10 0x0a */
47 | "ret", /* RET 11 0x0b */
48 | "cmp", /* CMP 12 0x0c */
49 | "strcmp", /* STRCMP 13 0x0d */
50 | "jmp", /* JMP 14 0x0e */
51 | "jz", /* JZ 15 0x0f */
52 | "jnz", /* JNZ 16 0x10 */
53 | "je", /* JE 17 0x11 */
54 | "jne", /* JNE 18 0x12 */
55 | "jgt", /* JGT 19 0x13 */
56 | "jgte", /* JGTE 20 0x14 */
57 | "jlt", /* JLT 21 0x15 */
58 | "jlte", /* JLTE 22 0x16 */
59 | "string", /* STRING 23 0x17 */
60 | "print", /* PRINT 24 0x18 */
61 | "dump", /* DUMP 25 0x19 */
62 | "halt", /* HALT 26 0x1a */
63 | NULL,
64 | };
65 |
66 |
67 | /** ASM TOKENS **/
68 | #define T_OPCODE_NOOP 0x40 /* does nothing */
69 | #define T_OPCODE_PUSH 0x41 /* push a register onto data stack */
70 | #define T_OPCODE_POP 0x42 /* pop data stack top into a register */
71 | #define T_OPCODE_SET 0x43 /* set register value */
72 | #define T_OPCODE_SWAP 0x44 /* swap two register values */
73 | #define T_OPCODE_ADD 0x45 /* add the second operand to the first */
74 | #define T_OPCODE_SUB 0x46 /* subtract the second operand from the first */
75 | #define T_OPCODE_MULT 0x47 /* multiply the first operand by the second */
76 | #define T_OPCODE_DIV 0x48 /* divide the first operand by the second */
77 | #define T_OPCODE_MOD 0x49 /* modulo the first operand by the second */
78 | #define T_OPCODE_CALL 0x4a /* call a user-defined function */
79 | #define T_OPCODE_RET 0x4b /* return to caller */
80 | #define T_OPCODE_RETV 0x4c /* return to caller (with value) */
81 | #define T_OPCODE_CMP 0x4d /* compare two integers */
82 | #define T_OPCODE_STRCMP 0x4e /* compare two strings */
83 | #define T_OPCODE_JMP 0x4f /* unconditional jump */
84 | #define T_OPCODE_JZ 0x50 /* jump if accumulator is 0 */
85 | #define T_OPCODE_JNZ 0x51 /* jump if accumulator is not 0 */
86 | #define T_OPCODE_JE 0x52 /* jump if accumulator is equal to first operand */
87 | #define T_OPCODE_JNE 0x53 /* jump if accumulator is not equal to first operand */
88 | #define T_OPCODE_JGT 0x54 /* jump if accumulator is greater than first operand */
89 | #define T_OPCODE_JGTE 0x55 /* jump if accumulator is greater than or equal to first operand */
90 | #define T_OPCODE_JLT 0x56 /* jump if accumulator is less than first operand */
91 | #define T_OPCODE_JLTE 0x57 /* jump if accumulator is less than or equal to first operand */
92 | #define T_OPCODE_STRING 0x58 /* format a (heap-allocated) string */
93 | #define T_OPCODE_PRINT 0x59 /* print a message to standard output */
94 | #define T_OPCODE_DUMP 0x5a /* dump virtual machine state for debugging */
95 | #define T_OPCODE_HALT 0x5b /* halt the virtual machine */
96 |
97 |
98 | static const char * ASM[] = {
99 | "noop", /* T_OPCODE_NOOP 0 0000 */
100 | "push", /* T_OPCODE_PUSH 1 0x01 */
101 | "pop", /* T_OPCODE_POP 2 0x02 */
102 | "set", /* T_OPCODE_SET 3 0x03 */
103 | "swap", /* T_OPCODE_SWAP 4 0x04 */
104 | "add", /* T_OPCODE_ADD 5 0x05 */
105 | "sub", /* T_OPCODE_SUB 6 0x06 */
106 | "mult", /* T_OPCODE_MULT 7 0x07 */
107 | "div", /* T_OPCODE_DIV 8 0x08 */
108 | "mod", /* T_OPCODE_MOD 9 0x09 */
109 | "call", /* T_OPCODE_CALL 10 0x0a */
110 | "ret", /* T_OPCODE_RET 11 0x0b */
111 | "retv", /* T_OPCODE_RETV 12 0x0c */
112 | "cmp", /* T_OPCODE_CMP 13 0x0d */
113 | "strcmp", /* T_OPCODE_STRCMP 14 0x0e */
114 | "jmp", /* T_OPCODE_JMP 15 0x0f */
115 | "jz", /* T_OPCODE_JZ 16 0x10 */
116 | "jnz", /* T_OPCODE_JNZ 17 0x11 */
117 | "je", /* T_OPCODE_JE 18 0x12 */
118 | "jne", /* T_OPCODE_JNE 19 0x13 */
119 | "jgt", /* T_OPCODE_JGT 20 0x14 */
120 | "jgte", /* T_OPCODE_JGTE 21 0x15 */
121 | "jlt", /* T_OPCODE_JLT 22 0x16 */
122 | "jlte", /* T_OPCODE_JLTE 23 0x17 */
123 | "string", /* T_OPCODE_STRING 24 0x18 */
124 | "print", /* T_OPCODE_PRINT 25 0x19 */
125 | "dump", /* T_OPCODE_DUMP 26 0x1a */
126 | "halt", /* T_OPCODE_HALT 27 0x1b */
127 | NULL,
128 | };
129 |
130 | #define ARG_NONE 0x00
131 | #define ARG_REGISTER 0x01
132 | #define ARG_NUMBER 0x02
133 | #define ARG_STRING 0x04
134 | #define ARG_LABEL 0x08
135 | #define ARG_FUNCTION 0x10
136 |
137 | static struct {
138 | byte_t token;
139 | const char *usage;
140 | byte_t opcode;
141 | byte_t args[2];
142 | } ASM_SYNTAX[] = {
143 | { T_OPCODE_NOOP, "noop", NOOP, { ARG_NONE, ARG_NONE, } },
144 | { T_OPCODE_PUSH, "push %a", PUSH, { ARG_REGISTER, ARG_NONE, } },
145 | { T_OPCODE_POP, "pop %a", POP, { ARG_REGISTER, ARG_NONE, } },
146 | { T_OPCODE_SET, "set %a (%b||)", SET, { ARG_REGISTER, ARG_REGISTER|ARG_STRING|ARG_NUMBER, } },
147 | { T_OPCODE_SWAP, "swap %a %b", SWAP, { ARG_REGISTER, ARG_REGISTER, } },
148 | { T_OPCODE_ADD, "add %a (%b|)", ADD, { ARG_REGISTER, ARG_REGISTER|ARG_NUMBER, } },
149 | { T_OPCODE_SUB, "sub %a (%b|)", SUB, { ARG_REGISTER, ARG_REGISTER|ARG_NUMBER, } },
150 | { T_OPCODE_MULT, "mult %a (%b|)", MULT, { ARG_REGISTER, ARG_REGISTER|ARG_NUMBER, } },
151 | { T_OPCODE_DIV, "div %a (%b|)", DIV, { ARG_REGISTER, ARG_REGISTER|ARG_NUMBER, } },
152 | { T_OPCODE_MOD, "mod %a (%b|)", MOD, { ARG_REGISTER, ARG_REGISTER|ARG_NUMBER, } },
153 | { T_OPCODE_CALL, "call ", CALL, { ARG_FUNCTION, ARG_NONE, } },
154 | { T_OPCODE_RET, "ret", RET, { ARG_NONE, ARG_NONE, } },
155 | { T_OPCODE_RETV, "retv (%a||)", RET, { ARG_REGISTER|ARG_STRING|ARG_NUMBER, ARG_NONE, } },
156 | { T_OPCODE_CMP, "cmp (%a|) (%b|)", CMP, { ARG_REGISTER|ARG_NUMBER, ARG_REGISTER|ARG_NUMBER, } },
157 | { T_OPCODE_STRCMP, "strcmp (%a|) (%b|)", STRCMP, { ARG_REGISTER|ARG_STRING, ARG_REGISTER|ARG_STRING, } },
158 | { T_OPCODE_JMP, "jmp