dup-init.c (2836B)
1 #include <sys/types.h> 2 #include <sys/stat.h> 3 4 #include <err.h> 5 #include <errno.h> 6 #include <fcntl.h> 7 #include <limits.h> 8 #include <stdint.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <strings.h> 12 #include <unistd.h> 13 14 #include <sodium.h> 15 16 #include "arg.h" 17 #include "block.h" 18 #include "config.h" 19 #include "key.h" 20 #include "lock.h" 21 #include "misc.h" 22 #include "snap.h" 23 #include "state.h" 24 25 struct param param; 26 int verbose; 27 char *argv0; 28 29 static void 30 savestate(char *repo) 31 { 32 char path[PATH_MAX]; 33 int fd; 34 35 if (snprintf(path, sizeof(path), "%s/state", repo) >= sizeof(path)) 36 errx(1, "snprintf: %s: path too long", path); 37 fd = open(path, O_RDWR | O_CREAT | O_EXCL, 0600); 38 if (fd < 0) 39 err(1, "open: %s", path); 40 if (writestate(fd, ¶m) < 0) 41 printerr("writestate: %s", path); 42 if (close(fd) < 0) 43 err(1, "close: %s", path); 44 } 45 46 static void 47 loadkey(char *keyf) 48 { 49 int fd; 50 51 if (keyf == NULL) 52 return; 53 54 fd = open(keyf, O_RDONLY); 55 if (fd < 0) 56 err(1, "open: %s", keyf); 57 if (readkey(fd, param.key, sizeof(param.key)) < 0) 58 printerr("readkey: %s", keyf); 59 param.keyloaded = 1; 60 if (close(fd) < 0) 61 err(1, "close: %s", keyf); 62 } 63 64 static void 65 usage(void) 66 { 67 fprintf(stderr, "usage: %s [-v] [-E algo] [-Z algo] [-k keyfile] [repo]\n", argv0); 68 exit(1); 69 } 70 71 int 72 main(int argc, char *argv[]) 73 { 74 char spath[PATH_MAX]; 75 char bpath[PATH_MAX]; 76 struct bctx *bctx; 77 char *keyf = NULL; 78 char *repo; 79 int lfd; 80 81 param.calgo = "snappy"; 82 param.ealgo = "none"; 83 84 ARGBEGIN { 85 case 'k': 86 keyf = EARGF(usage()); 87 break; 88 case 'E': 89 param.ealgo = EARGF(usage()); 90 break; 91 case 'Z': 92 param.calgo = EARGF(usage()); 93 break; 94 case 'v': 95 verbose++; 96 break; 97 default: 98 usage(); 99 } ARGEND 100 101 switch (argc) { 102 case 0: 103 repo = "."; 104 break; 105 case 1: 106 repo = argv[0]; 107 break; 108 default: 109 usage(); 110 }; 111 112 if (sodium_init() < 0) 113 errx(1, "sodium_init: failed"); 114 115 if (strcasecmp(param.ealgo, "none") == 0) { 116 param.seed = 0; 117 } else if (strcasecmp(param.ealgo, "XChaCha20-Poly1305") == 0) { 118 if (keyf == NULL) 119 errx(1, "expected encryption key"); 120 param.seed = randombytes_uniform(0xffffffff); 121 } 122 123 if (snprintf(spath, sizeof(spath), "%s/%s", 124 repo, ARCHIVEPATH) >= sizeof(spath)) 125 errx(1, "snprintf: %s: path too long", spath); 126 if (snprintf(bpath, sizeof(bpath), "%s/%s", 127 repo, STORAGEPATH) >= sizeof(bpath)) 128 errx(1, "snprintf: %s: path too long", bpath); 129 130 if (mkdir(repo, 0700) < 0 && errno != EEXIST) 131 err(1, "mkdir: %s", repo); 132 133 if ((lfd = lockrepo(repo)) < 0) 134 errx(1, "failed to lock repository"); 135 136 if (mkdir(spath, 0700) < 0) 137 err(1, "mkdir: %s", spath); 138 139 loadkey(keyf); 140 savestate(repo); 141 142 if (bcreat(bpath, 0600, &bctx) < 0) 143 printerr("bcreat: %s", bpath); 144 if (bclose(bctx) < 0) 145 printerr("bclose: %s", bpath); 146 147 if (unlockrepo(lfd) < 0) 148 errx(1, "failed to unlock repository"); 149 return 0; 150 }