commit 8ef5e9d6666a818d610e1e1b1ffefa552f2c76f6
parent a54afccf81b4152c8767ea4eaee2f93e39ac9eba
Author: sin <sin@2f30.org>
Date: Wed, 8 May 2019 01:14:33 +0100
Implement state file
Diffstat:
M | Makefile | | | 2 | ++ |
A | state.c | | | 140 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | state.h | | | 4 | ++++ |
3 files changed, 146 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile
@@ -13,6 +13,7 @@ HDR = \
misc.h \
queue.h \
snap.h \
+ state.h \
tree.h \
COMMOBJ = \
@@ -27,6 +28,7 @@ COMMOBJ = \
misc.o \
pack.o \
snap.o \
+ state.o \
unpack.o \
DCHECKOBJ = $(COMMOBJ) dup-check.o
diff --git a/state.c b/state.c
@@ -0,0 +1,140 @@
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+
+#include "misc.h"
+#include "state.h"
+
+#define VMIN 0
+#define VMAJ 1
+#define VMINMASK 0xff
+#define VMAJSHIFT 8
+#define VMAJMASK 0xff
+
+#define CALGOSHIFT 16
+#define CALGOMASK 0x7
+#define CNONETYPE 0
+#define CSNAPPYTYPE 1
+#define CLZ4TYPE 2
+
+#define EALGOSHIFT 19
+#define EALGOMASK 0x7
+#define ENONETYPE 0
+#define ECHACHATYPE 1
+
+#define SHDRSIZE 8
+
+/* misc helpers */
+extern int pack(unsigned char *, char *, ...);
+extern int unpack(unsigned char *, char *, ...);
+
+struct shdr {
+ uint64_t flags;
+};
+
+/* Read state header */
+static int
+unpackshdr(int fd, struct shdr *shdr)
+{
+ unsigned char buf[SHDRSIZE];
+ int n;
+
+ if (xread(fd, buf, sizeof(buf)) != sizeof(buf))
+ return -1;
+
+ n = unpack(buf, "q", &shdr->flags);
+ assert(n == sizeof(buf));
+ return n;
+}
+
+/* Write state header */
+static int
+packshdr(int fd, struct shdr *shdr)
+{
+ unsigned char buf[SHDRSIZE];
+ int n;
+
+ n = pack(buf, "q", shdr->flags);
+ assert(n == SHDRSIZE);
+ if (xwrite(fd, buf, n) != n)
+ return -1;
+ return n;
+}
+
+int
+savestate(int fd, struct param *par)
+{
+ struct shdr shdr;
+
+ /* Set version */
+ shdr.flags = (VMAJ << VMAJSHIFT) | VMIN;
+
+ /* Set compression type */
+ if (strcasecmp(par->calgo, "none") == 0)
+ shdr.flags |= CNONETYPE << CALGOSHIFT;
+ else if (strcasecmp(par->calgo, "snappy") == 0)
+ shdr.flags |= CSNAPPYTYPE << CALGOSHIFT;
+ else if (strcasecmp(par->calgo, "lz4") == 0)
+ shdr.flags |= CLZ4TYPE << CALGOSHIFT;
+ else
+ return -1;
+
+ /* Set encryption type */
+ if (strcasecmp(par->ealgo, "none") == 0)
+ shdr.flags |= ENONETYPE << EALGOSHIFT;
+ else if (strcasecmp(par->ealgo, "XChaCha20-Poly1305") == 0)
+ shdr.flags |= ECHACHATYPE << EALGOSHIFT;
+ else
+ return -1;
+
+ if (packshdr(fd, &shdr) < 0)
+ return -1;
+ return 0;
+}
+
+int
+loadstate(int fd, struct param *par)
+{
+ struct shdr shdr;
+ int algo;
+
+ if (unpackshdr(fd, &shdr) < 0)
+ return -1;
+
+ /* If the major version is different, the format is incompatible */
+ if (((shdr.flags >> VMAJSHIFT) & VMAJMASK) != VMAJ)
+ return -1;
+
+ /* Populate param compression algo */
+ algo = (shdr.flags >> CALGOSHIFT) & CALGOMASK;
+ switch (algo) {
+ case CNONETYPE:
+ par->calgo = "none";
+ break;
+ case CSNAPPYTYPE:
+ par->calgo = "snappy";
+ break;
+ case CLZ4TYPE:
+ par->calgo = "lz4";
+ break;
+ default:
+ return -1;
+ }
+
+ /* Populate param encryption algo */
+ algo = (shdr.flags >> EALGOSHIFT) & EALGOMASK;
+ switch (algo) {
+ case ENONETYPE:
+ par->ealgo = "none";
+ break;
+ case ECHACHATYPE:
+ par->ealgo = "XChaCha20-Poly1305";
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/state.h b/state.h
@@ -0,0 +1,4 @@
+struct param {
+ char *calgo;
+ char *ealgo;
+};