==> tests/durable.c <==1/* Writes are whole under their name (no .tmp left), links share the inode, a link whose source went is
2 * written instead, and directories sync. */
3#include "mesh/blobs/durable.h"
4#include "mesh/check.h"
5#include "mesh/strbuf.h"
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <sys/stat.h>
11#include <unistd.h>
12
13static char *slurp(const char *p, size_t *n) {
14 FILE *f = fopen(p, "rb");
15 if (!f) return NULL;
16 char *b = mxalloc(4096);
17 *n = fread(b, 1, 4096, f);
18 fclose(f);
19 return b;
20}
21
22int main(void) {
23 char *root = mfmt("%s/mesh-blobs-durable-%d", getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp", (int)getpid());
24 mb_remove_tree(root);
25 char *a = mfmt("%s/1.1", root), *b = mfmt("%s/2.1", root);
26 char *err = NULL;
27 CHECK(mb_make_durable(a, "h1", NULL, "pass sums", 9, &err));
28 CHECK(mb_sync_dir(a, &err));
29 char *pa = mfmt("%s/h1", a), *ta = mfmt("%s/h1.tmp", a);
30 size_t n;
31 char *got = slurp(pa, &n);
32 CHECK(got && n == 9 && memcmp(got, "pass sums", 9) == 0);
33 free(got);
34 struct stat st, st2;
35 CHECK(stat(ta, &st) != 0);
36 /* Another job's copy: a hard link, the same inode. */
37 CHECK(mb_make_durable(b, "h1", pa, "pass sums", 9, &err));
38 char *pb = mfmt("%s/h1", b);
39 CHECK(stat(pa, &st) == 0 && stat(pb, &st2) == 0 && st.st_ino == st2.st_ino);
40 /* Linking again over an existing name replaces it. */
41 CHECK(mb_make_durable(b, "h1", pa, "pass sums", 9, &err));
42 /* A link whose source went: the bytes are written. */
43 char *c = mfmt("%s/3.1", root);
44 CHECK(mb_make_durable(c, "h2", "/nonexistent/file", "late", 4, &err));
45 char *pc = mfmt("%s/h2", c);
46 got = slurp(pc, &n);
47 CHECK(got && n == 4 && memcmp(got, "late", 4) == 0);
48 free(got);
49 CHECK(!mb_sync_dir("/nonexistent/dir", &err));
50 CHECK(err && strstr(err, "/nonexistent/dir") != NULL);
51 free(err);
52 mb_remove_tree(root);
53 CHECK(stat(root, &st) != 0);
54 for (char *p[] = {root, a, b, pa, ta, pb, c, pc}, **q = p; q < p + 8; q++) free(*q);
55 return mesh_check_done();
56}