isnap.c - dedup - deduplicating backup program Err bitreich.org 70 hgit clone git://bitreich.org/dedup/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/dedup/ URL:git://bitreich.org/dedup/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/dedup/ bitreich.org 70 1Log /scm/dedup/log.gph bitreich.org 70 1Files /scm/dedup/files.gph bitreich.org 70 1Refs /scm/dedup/refs.gph bitreich.org 70 1Tags /scm/dedup/tag bitreich.org 70 1README /scm/dedup/file/README.gph bitreich.org 70 1LICENSE /scm/dedup/file/LICENSE.gph bitreich.org 70 i--- Err bitreich.org 70 isnap.c (10918B) Err bitreich.org 70 i--- Err bitreich.org 70 i 1 /* Snapshot archive implementation */ Err bitreich.org 70 i 2 #include Err bitreich.org 70 i 3 #include Err bitreich.org 70 i 4 Err bitreich.org 70 i 5 #include Err bitreich.org 70 i 6 #include Err bitreich.org 70 i 7 #include Err bitreich.org 70 i 8 #include Err bitreich.org 70 i 9 #include Err bitreich.org 70 i 10 #include Err bitreich.org 70 i 11 #include Err bitreich.org 70 i 12 #include Err bitreich.org 70 i 13 #include Err bitreich.org 70 i 14 #include Err bitreich.org 70 i 15 Err bitreich.org 70 i 16 #include Err bitreich.org 70 i 17 Err bitreich.org 70 i 18 #include "config.h" Err bitreich.org 70 i 19 #include "misc.h" Err bitreich.org 70 i 20 #include "queue.h" Err bitreich.org 70 i 21 #include "snap.h" Err bitreich.org 70 i 22 #include "state.h" Err bitreich.org 70 i 23 Err bitreich.org 70 i 24 /* snapshot encryption algorithms */ Err bitreich.org 70 i 25 #define SNONETYPE 0x400 Err bitreich.org 70 i 26 #define SCHACHATYPE 0x401 Err bitreich.org 70 i 27 Err bitreich.org 70 i 28 /* snapshot header constants */ Err bitreich.org 70 i 29 #define SHDRMAGIC "SNAPSNAPPYSNOOP" Err bitreich.org 70 i 30 #define NSHDRMAGIC 16 Err bitreich.org 70 i 31 Err bitreich.org 70 i 32 #define VMIN 0 Err bitreich.org 70 i 33 #define VMAJ 1 Err bitreich.org 70 i 34 #define VMINMASK 0xff Err bitreich.org 70 i 35 #define VMAJSHIFT 8 Err bitreich.org 70 i 36 #define VMAJMASK 0xff Err bitreich.org 70 i 37 Err bitreich.org 70 i 38 #define CRYPTOHDRSIZE crypto_secretstream_xchacha20poly1305_HEADERBYTES Err bitreich.org 70 i 39 #define SHDRSIZE (NSHDRMAGIC + CRYPTOHDRSIZE + 8 + 8) Err bitreich.org 70 i 40 Err bitreich.org 70 i 41 extern struct param param; Err bitreich.org 70 i 42 Err bitreich.org 70 i 43 /* misc helpers */ Err bitreich.org 70 i 44 extern int pack(unsigned char *, char *, ...); Err bitreich.org 70 i 45 extern int unpack(unsigned char *, char *, ...); Err bitreich.org 70 i 46 Err bitreich.org 70 i 47 /* Snapshot header structure */ Err bitreich.org 70 i 48 struct shdr { Err bitreich.org 70 i 49 char magic[NSHDRMAGIC]; /* magic number for file(1) */ Err bitreich.org 70 i 50 unsigned char header[CRYPTOHDRSIZE]; /* xchacha20-poly1305 crypto header */ Err bitreich.org 70 i 51 uint64_t flags; /* version number */ Err bitreich.org 70 i 52 uint64_t nbd; /* number of block hashes */ Err bitreich.org 70 i 53 }; Err bitreich.org 70 i 54 Err bitreich.org 70 i 55 struct mdnode { Err bitreich.org 70 i 56 unsigned char md[MDSIZE]; /* hash of block */ Err bitreich.org 70 i 57 TAILQ_ENTRY(mdnode) e; /* mdhead link node */ Err bitreich.org 70 i 58 }; Err bitreich.org 70 i 59 Err bitreich.org 70 i 60 struct sctx { Err bitreich.org 70 i 61 TAILQ_HEAD(mdhead, mdnode) mdhead; /* list of hashes contained in snapshot */ Err bitreich.org 70 i 62 struct mdnode *mdnext; /* next hash to be returned via sget() */ Err bitreich.org 70 i 63 int type; /* encryption algorithm */ Err bitreich.org 70 i 64 int fd; /* underlying snapshot file descriptor */ Err bitreich.org 70 i 65 int rdonly; /* when set, ssync() is a no-op */ Err bitreich.org 70 i 66 struct shdr shdr; /* snapshot header */ Err bitreich.org 70 i 67 }; Err bitreich.org 70 i 68 Err bitreich.org 70 i 69 /* Unpack snapshot header */ Err bitreich.org 70 i 70 static int Err bitreich.org 70 i 71 unpackshdr(unsigned char *buf, struct shdr *shdr) Err bitreich.org 70 i 72 { Err bitreich.org 70 i 73 char fmt[BUFSIZ]; Err bitreich.org 70 i 74 int n; Err bitreich.org 70 i 75 Err bitreich.org 70 i 76 snprintf(fmt, sizeof(fmt), "'%d'%dqq", NSHDRMAGIC, CRYPTOHDRSIZE); Err bitreich.org 70 i 77 n = unpack(buf, fmt, Err bitreich.org 70 i 78 shdr->magic, Err bitreich.org 70 i 79 shdr->header, Err bitreich.org 70 i 80 &shdr->flags, Err bitreich.org 70 i 81 &shdr->nbd); Err bitreich.org 70 i 82 Err bitreich.org 70 i 83 assert(n == SHDRSIZE); Err bitreich.org 70 i 84 return n; Err bitreich.org 70 i 85 } Err bitreich.org 70 i 86 Err bitreich.org 70 i 87 /* Pack snapshot header */ Err bitreich.org 70 i 88 static int Err bitreich.org 70 i 89 packshdr(unsigned char *buf, struct shdr *shdr) Err bitreich.org 70 i 90 { Err bitreich.org 70 i 91 char fmt[BUFSIZ]; Err bitreich.org 70 i 92 int n; Err bitreich.org 70 i 93 Err bitreich.org 70 i 94 snprintf(fmt, sizeof(fmt), "'%d'%dqq", NSHDRMAGIC, CRYPTOHDRSIZE); Err bitreich.org 70 i 95 n = pack(buf, fmt, Err bitreich.org 70 i 96 shdr->magic, Err bitreich.org 70 i 97 shdr->header, Err bitreich.org 70 i 98 shdr->flags, Err bitreich.org 70 i 99 shdr->nbd); Err bitreich.org 70 i 100 Err bitreich.org 70 i 101 assert(n == SHDRSIZE); Err bitreich.org 70 i 102 return n; Err bitreich.org 70 i 103 } Err bitreich.org 70 i 104 Err bitreich.org 70 i 105 static int Err bitreich.org 70 i 106 loadmdnone(struct sctx *sctx, int first) Err bitreich.org 70 i 107 { Err bitreich.org 70 i 108 struct mdnode *mdnode; Err bitreich.org 70 i 109 Err bitreich.org 70 i 110 mdnode = calloc(1, sizeof(*mdnode)); Err bitreich.org 70 i 111 if (mdnode == NULL) { Err bitreich.org 70 i 112 seterr("calloc: out of memory"); Err bitreich.org 70 i 113 return -1; Err bitreich.org 70 i 114 } Err bitreich.org 70 i 115 Err bitreich.org 70 i 116 if (xread(sctx->fd, mdnode->md, MDSIZE) != MDSIZE) { Err bitreich.org 70 i 117 seterr("failed to read block hash: %s", strerror(errno)); Err bitreich.org 70 i 118 return -1; Err bitreich.org 70 i 119 } Err bitreich.org 70 i 120 Err bitreich.org 70 i 121 TAILQ_INSERT_TAIL(&sctx->mdhead, mdnode, e); Err bitreich.org 70 i 122 return 0; Err bitreich.org 70 i 123 } Err bitreich.org 70 i 124 Err bitreich.org 70 i 125 static int Err bitreich.org 70 i 126 loadmdchacha(struct sctx *sctx, int first) Err bitreich.org 70 i 127 { Err bitreich.org 70 i 128 unsigned char buf[MDSIZE + crypto_secretstream_xchacha20poly1305_ABYTES]; Err bitreich.org 70 i 129 unsigned char hdr[SHDRSIZE]; Err bitreich.org 70 i 130 static crypto_secretstream_xchacha20poly1305_state state; Err bitreich.org 70 i 131 struct mdnode *mdnode; Err bitreich.org 70 i 132 struct shdr *shdr; Err bitreich.org 70 i 133 Err bitreich.org 70 i 134 shdr = &sctx->shdr; Err bitreich.org 70 i 135 packshdr(hdr, shdr); Err bitreich.org 70 i 136 if (first && crypto_secretstream_xchacha20poly1305_init_pull(&state, Err bitreich.org 70 i 137 shdr->header, Err bitreich.org 70 i 138 param.key) < 0) { Err bitreich.org 70 i 139 seterr("invalid crypto header"); Err bitreich.org 70 i 140 return -1; Err bitreich.org 70 i 141 } Err bitreich.org 70 i 142 Err bitreich.org 70 i 143 if (xread(sctx->fd, buf, sizeof(buf)) != sizeof(buf)) { Err bitreich.org 70 i 144 seterr("failed to read block hash: %s", strerror(errno)); Err bitreich.org 70 i 145 return -1; Err bitreich.org 70 i 146 } Err bitreich.org 70 i 147 Err bitreich.org 70 i 148 mdnode = calloc(1, sizeof(*mdnode)); Err bitreich.org 70 i 149 if (mdnode == NULL) { Err bitreich.org 70 i 150 seterr("calloc: out of memory"); Err bitreich.org 70 i 151 return -1; Err bitreich.org 70 i 152 } Err bitreich.org 70 i 153 Err bitreich.org 70 i 154 if (crypto_secretstream_xchacha20poly1305_pull(&state, mdnode->md, NULL, Err bitreich.org 70 i 155 NULL, buf, sizeof(buf), Err bitreich.org 70 i 156 hdr, sizeof(hdr)) < 0) { Err bitreich.org 70 i 157 free(mdnode); Err bitreich.org 70 i 158 seterr("authentication failed"); Err bitreich.org 70 i 159 return -1; Err bitreich.org 70 i 160 } Err bitreich.org 70 i 161 Err bitreich.org 70 i 162 TAILQ_INSERT_TAIL(&sctx->mdhead, mdnode, e); Err bitreich.org 70 i 163 return 0; Err bitreich.org 70 i 164 } Err bitreich.org 70 i 165 Err bitreich.org 70 i 166 static int Err bitreich.org 70 i 167 initmdhead(struct sctx *sctx) Err bitreich.org 70 i 168 { Err bitreich.org 70 i 169 struct shdr *shdr; Err bitreich.org 70 i 170 int (*loadmd)(struct sctx *, int); Err bitreich.org 70 i 171 uint64_t i; Err bitreich.org 70 i 172 Err bitreich.org 70 i 173 if (sctx->type == SNONETYPE) Err bitreich.org 70 i 174 loadmd = loadmdnone; Err bitreich.org 70 i 175 else Err bitreich.org 70 i 176 loadmd = loadmdchacha; Err bitreich.org 70 i 177 Err bitreich.org 70 i 178 shdr = &sctx->shdr; Err bitreich.org 70 i 179 for (i = 0; i < shdr->nbd; i++) { Err bitreich.org 70 i 180 if ((*loadmd)(sctx, i == 0) == 0) Err bitreich.org 70 i 181 continue; Err bitreich.org 70 i 182 Err bitreich.org 70 i 183 while (!TAILQ_EMPTY(&sctx->mdhead)) { Err bitreich.org 70 i 184 struct mdnode *mdnode; Err bitreich.org 70 i 185 Err bitreich.org 70 i 186 mdnode = TAILQ_FIRST(&sctx->mdhead); Err bitreich.org 70 i 187 TAILQ_REMOVE(&sctx->mdhead, mdnode, e); Err bitreich.org 70 i 188 free(mdnode); Err bitreich.org 70 i 189 } Err bitreich.org 70 i 190 return -1; Err bitreich.org 70 i 191 } Err bitreich.org 70 i 192 return 0; Err bitreich.org 70 i 193 } Err bitreich.org 70 i 194 Err bitreich.org 70 i 195 int Err bitreich.org 70 i 196 screat(char *path, int mode, struct sctx **sctx) Err bitreich.org 70 i 197 { Err bitreich.org 70 i 198 unsigned char buf[SHDRSIZE]; Err bitreich.org 70 i 199 struct shdr *shdr; Err bitreich.org 70 i 200 int type; Err bitreich.org 70 i 201 int fd; Err bitreich.org 70 i 202 Err bitreich.org 70 i 203 if (path == NULL || sctx == NULL) { Err bitreich.org 70 i 204 seterr("invalid params"); Err bitreich.org 70 i 205 return -1; Err bitreich.org 70 i 206 } Err bitreich.org 70 i 207 Err bitreich.org 70 i 208 /* Determine algorithm type */ Err bitreich.org 70 i 209 if (strcasecmp(param.ealgo, "none") == 0) { Err bitreich.org 70 i 210 type = SNONETYPE; Err bitreich.org 70 i 211 } else if (strcasecmp(param.ealgo, "XChaCha20-Poly1305") == 0) { Err bitreich.org 70 i 212 type = SCHACHATYPE; Err bitreich.org 70 i 213 } else { Err bitreich.org 70 i 214 seterr("invalid encryption type: %s", param.ealgo); Err bitreich.org 70 i 215 return -1; Err bitreich.org 70 i 216 } Err bitreich.org 70 i 217 Err bitreich.org 70 i 218 /* Ensure a key has been provided if caller requested encryption */ Err bitreich.org 70 i 219 if (type != SNONETYPE && !param.keyloaded) { Err bitreich.org 70 i 220 seterr("expected encryption key"); Err bitreich.org 70 i 221 return -1; Err bitreich.org 70 i 222 } Err bitreich.org 70 i 223 Err bitreich.org 70 i 224 if (sodium_init() < 0) { Err bitreich.org 70 i 225 seterr("sodium_init: failed"); Err bitreich.org 70 i 226 return -1; Err bitreich.org 70 i 227 } Err bitreich.org 70 i 228 Err bitreich.org 70 i 229 fd = open(path, O_RDWR | O_CREAT | O_EXCL, mode); Err bitreich.org 70 i 230 if (fd < 0) { Err bitreich.org 70 i 231 seterr("open: %s", strerror(errno)); Err bitreich.org 70 i 232 return -1; Err bitreich.org 70 i 233 } Err bitreich.org 70 i 234 Err bitreich.org 70 i 235 *sctx = calloc(1, sizeof(**sctx)); Err bitreich.org 70 i 236 if (*sctx == NULL) { Err bitreich.org 70 i 237 close(fd); Err bitreich.org 70 i 238 seterr("calloc: out of memory"); Err bitreich.org 70 i 239 return -1; Err bitreich.org 70 i 240 } Err bitreich.org 70 i 241 Err bitreich.org 70 i 242 TAILQ_INIT(&(*sctx)->mdhead); Err bitreich.org 70 i 243 (*sctx)->mdnext = NULL; Err bitreich.org 70 i 244 (*sctx)->type = type; Err bitreich.org 70 i 245 (*sctx)->fd = fd; Err bitreich.org 70 i 246 Err bitreich.org 70 i 247 shdr = &(*sctx)->shdr; Err bitreich.org 70 i 248 memcpy(shdr->magic, SHDRMAGIC, NSHDRMAGIC); Err bitreich.org 70 i 249 shdr->flags = (VMAJ << VMAJSHIFT) | VMIN; Err bitreich.org 70 i 250 shdr->nbd = 0; Err bitreich.org 70 i 251 Err bitreich.org 70 i 252 packshdr(buf, shdr); Err bitreich.org 70 i 253 if (xwrite(fd, buf, SHDRSIZE) != SHDRSIZE) { Err bitreich.org 70 i 254 free(*sctx); Err bitreich.org 70 i 255 close(fd); Err bitreich.org 70 i 256 seterr("failed to write snapshot header: %s", strerror(errno)); Err bitreich.org 70 i 257 return -1; Err bitreich.org 70 i 258 } Err bitreich.org 70 i 259 return 0; Err bitreich.org 70 i 260 } Err bitreich.org 70 i 261 Err bitreich.org 70 i 262 int Err bitreich.org 70 i 263 sopen(char *path, int flags, int mode, struct sctx **sctx) Err bitreich.org 70 i 264 { Err bitreich.org 70 i 265 unsigned char buf[SHDRSIZE]; Err bitreich.org 70 i 266 struct shdr *shdr; Err bitreich.org 70 i 267 int type; Err bitreich.org 70 i 268 int fd; Err bitreich.org 70 i 269 Err bitreich.org 70 i 270 if (path == NULL || sctx == NULL) { Err bitreich.org 70 i 271 seterr("invalid params"); Err bitreich.org 70 i 272 return -1; Err bitreich.org 70 i 273 } Err bitreich.org 70 i 274 Err bitreich.org 70 i 275 /* Existing snapshots are immutable */ Err bitreich.org 70 i 276 if (flags != S_READ) { Err bitreich.org 70 i 277 seterr("invalid params"); Err bitreich.org 70 i 278 return -1; Err bitreich.org 70 i 279 } Err bitreich.org 70 i 280 Err bitreich.org 70 i 281 /* Determine algorithm type */ Err bitreich.org 70 i 282 if (strcasecmp(param.ealgo, "none") == 0) { Err bitreich.org 70 i 283 type = SNONETYPE; Err bitreich.org 70 i 284 } else if (strcasecmp(param.ealgo, "XChaCha20-Poly1305") == 0) { Err bitreich.org 70 i 285 type = SCHACHATYPE; Err bitreich.org 70 i 286 } else { Err bitreich.org 70 i 287 seterr("invalid encryption type: %s", param.ealgo); Err bitreich.org 70 i 288 return -1; Err bitreich.org 70 i 289 } Err bitreich.org 70 i 290 Err bitreich.org 70 i 291 /* Ensure a key has been provided if caller requested encryption */ Err bitreich.org 70 i 292 if (type != SNONETYPE && !param.keyloaded) { Err bitreich.org 70 i 293 seterr("expected encryption key"); Err bitreich.org 70 i 294 return -1; Err bitreich.org 70 i 295 } Err bitreich.org 70 i 296 Err bitreich.org 70 i 297 if (sodium_init() < 0) { Err bitreich.org 70 i 298 seterr("sodium_init: failed"); Err bitreich.org 70 i 299 return -1; Err bitreich.org 70 i 300 } Err bitreich.org 70 i 301 Err bitreich.org 70 i 302 fd = open(path, O_RDONLY, mode); Err bitreich.org 70 i 303 if (fd < 0) { Err bitreich.org 70 i 304 seterr("open: %s", strerror(errno)); Err bitreich.org 70 i 305 return -1; Err bitreich.org 70 i 306 } Err bitreich.org 70 i 307 Err bitreich.org 70 i 308 *sctx = calloc(1, sizeof(**sctx)); Err bitreich.org 70 i 309 if (*sctx == NULL) { Err bitreich.org 70 i 310 close(fd); Err bitreich.org 70 i 311 seterr("calloc: out of memory"); Err bitreich.org 70 i 312 return -1; Err bitreich.org 70 i 313 } Err bitreich.org 70 i 314 Err bitreich.org 70 i 315 TAILQ_INIT(&(*sctx)->mdhead); Err bitreich.org 70 i 316 (*sctx)->mdnext = NULL; Err bitreich.org 70 i 317 (*sctx)->type = type; Err bitreich.org 70 i 318 (*sctx)->fd = fd; Err bitreich.org 70 i 319 (*sctx)->rdonly = 1; Err bitreich.org 70 i 320 Err bitreich.org 70 i 321 shdr = &(*sctx)->shdr; Err bitreich.org 70 i 322 Err bitreich.org 70 i 323 if (xread(fd, buf, SHDRSIZE) != SHDRSIZE) { Err bitreich.org 70 i 324 free(sctx); Err bitreich.org 70 i 325 close(fd); Err bitreich.org 70 i 326 seterr("failed to read snapshot header: %s", strerror(errno)); Err bitreich.org 70 i 327 return -1; Err bitreich.org 70 i 328 } Err bitreich.org 70 i 329 unpackshdr(buf, shdr); Err bitreich.org 70 i 330 Err bitreich.org 70 i 331 if (memcmp(shdr->magic, SHDRMAGIC, NSHDRMAGIC) != 0) { Err bitreich.org 70 i 332 free(sctx); Err bitreich.org 70 i 333 close(fd); Err bitreich.org 70 i 334 seterr("unknown snapshot header magic"); Err bitreich.org 70 i 335 return -1; Err bitreich.org 70 i 336 } Err bitreich.org 70 i 337 Err bitreich.org 70 i 338 /* If the major version is different, the format is incompatible */ Err bitreich.org 70 i 339 if (((shdr->flags >> VMAJSHIFT) & VMAJMASK) != VMAJ) { Err bitreich.org 70 i 340 free(sctx); Err bitreich.org 70 i 341 close(fd); Err bitreich.org 70 i 342 seterr("snapshot header version mismatch"); Err bitreich.org 70 i 343 return -1; Err bitreich.org 70 i 344 } Err bitreich.org 70 i 345 Err bitreich.org 70 i 346 if (initmdhead(*sctx) < 0) { Err bitreich.org 70 i 347 free(*sctx); Err bitreich.org 70 i 348 close(fd); Err bitreich.org 70 i 349 return -1; Err bitreich.org 70 i 350 } Err bitreich.org 70 i 351 return 0; Err bitreich.org 70 i 352 } Err bitreich.org 70 i 353 Err bitreich.org 70 i 354 int Err bitreich.org 70 i 355 sput(struct sctx *sctx, unsigned char *md) Err bitreich.org 70 i 356 { Err bitreich.org 70 i 357 struct shdr *shdr; Err bitreich.org 70 i 358 struct mdnode *mdnode; Err bitreich.org 70 i 359 Err bitreich.org 70 i 360 if (sctx == NULL || md == NULL) { Err bitreich.org 70 i 361 seterr("invalid params"); Err bitreich.org 70 i 362 return -1; Err bitreich.org 70 i 363 } Err bitreich.org 70 i 364 Err bitreich.org 70 i 365 mdnode = calloc(1, sizeof(*mdnode)); Err bitreich.org 70 i 366 if (mdnode == NULL) { Err bitreich.org 70 i 367 seterr("calloc: out of memory"); Err bitreich.org 70 i 368 return -1; Err bitreich.org 70 i 369 } Err bitreich.org 70 i 370 shdr = &sctx->shdr; Err bitreich.org 70 i 371 shdr->nbd++; Err bitreich.org 70 i 372 memcpy(mdnode->md, md, MDSIZE); Err bitreich.org 70 i 373 TAILQ_INSERT_TAIL(&sctx->mdhead, mdnode, e); Err bitreich.org 70 i 374 return 0; Err bitreich.org 70 i 375 } Err bitreich.org 70 i 376 Err bitreich.org 70 i 377 int Err bitreich.org 70 i 378 sget(struct sctx *sctx, unsigned char *md) Err bitreich.org 70 i 379 { Err bitreich.org 70 i 380 struct mdnode *mdnode; Err bitreich.org 70 i 381 Err bitreich.org 70 i 382 if (sctx == NULL || md == NULL) { Err bitreich.org 70 i 383 seterr("invalid params"); Err bitreich.org 70 i 384 return -1; Err bitreich.org 70 i 385 } Err bitreich.org 70 i 386 Err bitreich.org 70 i 387 mdnode = sctx->mdnext; Err bitreich.org 70 i 388 if (mdnode == NULL) Err bitreich.org 70 i 389 mdnode = TAILQ_FIRST(&sctx->mdhead); Err bitreich.org 70 i 390 else Err bitreich.org 70 i 391 mdnode = TAILQ_NEXT(mdnode, e); Err bitreich.org 70 i 392 sctx->mdnext = mdnode; Err bitreich.org 70 i 393 if (mdnode != NULL) { Err bitreich.org 70 i 394 memcpy(md, mdnode->md, MDSIZE); Err bitreich.org 70 i 395 return MDSIZE; Err bitreich.org 70 i 396 } Err bitreich.org 70 i 397 return 0; Err bitreich.org 70 i 398 } Err bitreich.org 70 i 399 Err bitreich.org 70 i 400 static int Err bitreich.org 70 i 401 syncnone(struct sctx *sctx) Err bitreich.org 70 i 402 { Err bitreich.org 70 i 403 unsigned char hdr[SHDRSIZE]; Err bitreich.org 70 i 404 struct mdnode *mdnode; Err bitreich.org 70 i 405 struct shdr *shdr; Err bitreich.org 70 i 406 Err bitreich.org 70 i 407 shdr = &sctx->shdr; Err bitreich.org 70 i 408 packshdr(hdr, shdr); Err bitreich.org 70 i 409 if (xwrite(sctx->fd, hdr, SHDRSIZE) != SHDRSIZE) { Err bitreich.org 70 i 410 seterr("failed to write snapshot header: %s", strerror(errno)); Err bitreich.org 70 i 411 return -1; Err bitreich.org 70 i 412 } Err bitreich.org 70 i 413 Err bitreich.org 70 i 414 TAILQ_FOREACH(mdnode, &sctx->mdhead, e) { Err bitreich.org 70 i 415 if (xwrite(sctx->fd, mdnode->md, MDSIZE) != MDSIZE) { Err bitreich.org 70 i 416 seterr("failed to write block hash: %s", Err bitreich.org 70 i 417 strerror(errno)); Err bitreich.org 70 i 418 return -1; Err bitreich.org 70 i 419 } Err bitreich.org 70 i 420 } Err bitreich.org 70 i 421 return 0; Err bitreich.org 70 i 422 } Err bitreich.org 70 i 423 Err bitreich.org 70 i 424 static int Err bitreich.org 70 i 425 syncchacha(struct sctx *sctx) Err bitreich.org 70 i 426 { Err bitreich.org 70 i 427 unsigned char hdr[SHDRSIZE]; Err bitreich.org 70 i 428 crypto_secretstream_xchacha20poly1305_state state; Err bitreich.org 70 i 429 struct mdnode *mdnode; Err bitreich.org 70 i 430 struct shdr *shdr; Err bitreich.org 70 i 431 Err bitreich.org 70 i 432 shdr = &sctx->shdr; Err bitreich.org 70 i 433 crypto_secretstream_xchacha20poly1305_init_push(&state, Err bitreich.org 70 i 434 shdr->header, Err bitreich.org 70 i 435 param.key); Err bitreich.org 70 i 436 Err bitreich.org 70 i 437 packshdr(hdr, shdr); Err bitreich.org 70 i 438 if (xwrite(sctx->fd, hdr, SHDRSIZE) != SHDRSIZE) { Err bitreich.org 70 i 439 seterr("failed to write snapshot header: %s", strerror(errno)); Err bitreich.org 70 i 440 return -1; Err bitreich.org 70 i 441 } Err bitreich.org 70 i 442 Err bitreich.org 70 i 443 TAILQ_FOREACH(mdnode, &sctx->mdhead, e) { Err bitreich.org 70 i 444 unsigned char buf[MDSIZE + crypto_secretstream_xchacha20poly1305_ABYTES]; Err bitreich.org 70 i 445 unsigned char tag; Err bitreich.org 70 i 446 Err bitreich.org 70 i 447 if (TAILQ_LAST(&sctx->mdhead, mdhead) == mdnode) Err bitreich.org 70 i 448 tag = crypto_secretstream_xchacha20poly1305_TAG_FINAL; Err bitreich.org 70 i 449 else Err bitreich.org 70 i 450 tag = 0; Err bitreich.org 70 i 451 Err bitreich.org 70 i 452 crypto_secretstream_xchacha20poly1305_push(&state, Err bitreich.org 70 i 453 buf, NULL, Err bitreich.org 70 i 454 mdnode->md, MDSIZE, Err bitreich.org 70 i 455 hdr, SHDRSIZE, tag); Err bitreich.org 70 i 456 if (xwrite(sctx->fd, buf, sizeof(buf)) != sizeof(buf)) { Err bitreich.org 70 i 457 seterr("failed to write block hash: %s", Err bitreich.org 70 i 458 strerror(errno)); Err bitreich.org 70 i 459 return -1; Err bitreich.org 70 i 460 } Err bitreich.org 70 i 461 } Err bitreich.org 70 i 462 return 0; Err bitreich.org 70 i 463 } Err bitreich.org 70 i 464 Err bitreich.org 70 i 465 int Err bitreich.org 70 i 466 ssync(struct sctx *sctx) Err bitreich.org 70 i 467 { Err bitreich.org 70 i 468 if (sctx == NULL) { Err bitreich.org 70 i 469 seterr("invalid params"); Err bitreich.org 70 i 470 return -1; Err bitreich.org 70 i 471 } Err bitreich.org 70 i 472 Err bitreich.org 70 i 473 if (sctx->rdonly) Err bitreich.org 70 i 474 return 0; Err bitreich.org 70 i 475 Err bitreich.org 70 i 476 if (lseek(sctx->fd, 0, SEEK_SET) < 0) { Err bitreich.org 70 i 477 seterr("lseek: %s", strerror(errno)); Err bitreich.org 70 i 478 return -1; Err bitreich.org 70 i 479 } Err bitreich.org 70 i 480 Err bitreich.org 70 i 481 if (sctx->type == SNONETYPE) Err bitreich.org 70 i 482 syncnone(sctx); Err bitreich.org 70 i 483 else Err bitreich.org 70 i 484 syncchacha(sctx); Err bitreich.org 70 i 485 Err bitreich.org 70 i 486 fsync(sctx->fd); Err bitreich.org 70 i 487 return 0; Err bitreich.org 70 i 488 } Err bitreich.org 70 i 489 Err bitreich.org 70 i 490 int Err bitreich.org 70 i 491 sclose(struct sctx *sctx) Err bitreich.org 70 i 492 { Err bitreich.org 70 i 493 int r; Err bitreich.org 70 i 494 Err bitreich.org 70 i 495 if (sctx == NULL) Err bitreich.org 70 i 496 return -1; Err bitreich.org 70 i 497 Err bitreich.org 70 i 498 if (ssync(sctx) < 0) Err bitreich.org 70 i 499 return -1; Err bitreich.org 70 i 500 Err bitreich.org 70 i 501 /* Free block hash list */ Err bitreich.org 70 i 502 while (!TAILQ_EMPTY(&sctx->mdhead)) { Err bitreich.org 70 i 503 struct mdnode *mdnode; Err bitreich.org 70 i 504 Err bitreich.org 70 i 505 mdnode = TAILQ_FIRST(&sctx->mdhead); Err bitreich.org 70 i 506 TAILQ_REMOVE(&sctx->mdhead, mdnode, e); Err bitreich.org 70 i 507 free(mdnode); Err bitreich.org 70 i 508 } Err bitreich.org 70 i 509 Err bitreich.org 70 i 510 r = close(sctx->fd); Err bitreich.org 70 i 511 free(sctx); Err bitreich.org 70 i 512 if (r < 0) Err bitreich.org 70 i 513 seterr("close: %s", strerror(errno)); Err bitreich.org 70 i 514 return r; Err bitreich.org 70 i 515 } Err bitreich.org 70 .