dup-unpack.c (2723B)
1 #include <sys/types.h> 2 #include <sys/stat.h> 3 4 #include <err.h> 5 #include <fcntl.h> 6 #include <limits.h> 7 #include <stdint.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <unistd.h> 11 12 #include "arg.h" 13 #include "block.h" 14 #include "config.h" 15 #include "key.h" 16 #include "lock.h" 17 #include "misc.h" 18 #include "snap.h" 19 #include "state.h" 20 21 struct param param; 22 int verbose; 23 char *argv0; 24 25 static void 26 loadstate(char *repo) 27 { 28 char path[PATH_MAX]; 29 int fd; 30 31 if (snprintf(path, sizeof(path), "%s/state", repo) >= sizeof(path)) 32 errx(1, "snprintf: %s: path too long", path); 33 fd = open(path, O_RDONLY); 34 if (fd < 0) 35 err(1, "open: %s", path); 36 if (readstate(fd, ¶m) < 0) 37 printerr("readstate: %s", path); 38 if (close(fd) < 0) 39 err(1, "close: %s", path); 40 } 41 42 static void 43 loadkey(char *keyfile) 44 { 45 int fd; 46 47 if (keyfile == NULL) 48 return; 49 50 fd = open(keyfile, O_RDONLY); 51 if (fd < 0) 52 err(1, "open: %s", keyfile); 53 if (readkey(fd, param.key, sizeof(param.key)) < 0) 54 printerr("readkey: %s", keyfile); 55 param.keyloaded = 1; 56 if (close(fd) < 0) 57 err(1, "close: %s", keyfile); 58 } 59 60 static void 61 unpack(struct sctx *sctx, struct bctx *bctx) 62 { 63 unsigned char md[MDSIZE]; 64 void *buf; 65 int sn; 66 67 buf = malloc(BSIZEMAX); 68 if (buf == NULL) 69 err(1, "malloc"); 70 while ((sn = sget(sctx, md)) == MDSIZE) { 71 size_t bn = BSIZEMAX; 72 73 if (bget(bctx, md, buf, &bn) < 0) 74 printerr("bget"); 75 if (xwrite(1, buf, bn) != bn) 76 err(1, "xwrite"); 77 } 78 if (sn < 0) 79 printerr("sget"); 80 free(buf); 81 } 82 83 static void 84 usage(void) 85 { 86 fprintf(stderr, "usage: %s [-v] [-k keyfile] [-r repo] name\n", argv0); 87 exit(1); 88 } 89 90 int 91 main(int argc, char *argv[]) 92 { 93 char spath[PATH_MAX]; 94 char bpath[PATH_MAX]; 95 struct sctx *sctx; 96 struct bctx *bctx; 97 char *keyfile = NULL; 98 char *repo = "."; 99 int lfd; 100 101 ARGBEGIN { 102 case 'k': 103 keyfile = EARGF(usage()); 104 break; 105 case 'r': 106 repo = EARGF(usage()); 107 break; 108 case 'v': 109 verbose++; 110 break; 111 default: 112 usage(); 113 } ARGEND 114 115 if (argc != 1) 116 usage(); 117 118 if (snprintf(spath, sizeof(spath), "%s/archive/%s", 119 repo, argv[0]) >= sizeof(spath)) 120 errx(1, "snprintf: %s: path too long", spath); 121 if (snprintf(bpath, sizeof(bpath), "%s/storage", 122 repo) >= sizeof(bpath)) 123 errx(1, "snprintf: %s: path too long", bpath); 124 125 if ((lfd = lockrepo(repo)) < 0) 126 errx(1, "failed to lock repository"); 127 128 loadkey(keyfile); 129 loadstate(repo); 130 131 if (sopen(spath, S_READ, 0600, &sctx) < 0) 132 printerr("sopen: %s", spath); 133 if (bopen(bpath, B_READ, 0600, &bctx) < 0) 134 printerr("bopen: %s", bpath); 135 136 unpack(sctx, bctx); 137 138 if (bclose(bctx) < 0) 139 printerr("bclose: %s", bpath); 140 if (sclose(sctx) < 0) 141 printerr("sclose: %s", spath); 142 143 if (unlockrepo(lfd) < 0) 144 errx(1, "failed to unlock repository"); 145 146 return 0; 147 }