X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=vbig.cc;h=1823dd316aaacba1cc7d1efb7bea0d6d4e300e29;hb=f5cf02c54821c02adcdaa5c88a33050fab5fea01;hp=4bad93029254361c95c03855124b30f8d9eabea4;hpb=14a4470dc78d8d6554bca3a3b9c52af1443f96bf;p=vbig.git diff --git a/vbig.cc b/vbig.cc index 4bad930..1823dd3 100644 --- a/vbig.cc +++ b/vbig.cc @@ -32,6 +32,7 @@ // Command line options const struct option opts[] = { { "seed", required_argument, 0, 's' }, + { "both", no_argument, 0, 'b' }, { "verify", no_argument, 0, 'v' }, { "create", no_argument, 0, 'c' }, { "flush", no_argument, 0, 'f' }, @@ -60,9 +61,9 @@ static void help(void) { // Possible modes of operation enum mode_type { - NONE, VERIFY, - CREATE + CREATE, + BOTH }; // Report an error and exit @@ -107,7 +108,7 @@ static void flushCache(FILE *fp) { #endif } -static void execute(mode_type mode, bool entire, const char *show); +static long long execute(mode_type mode, bool entire, const char *show); static const char *seed = "hexapodia as the key insight"; static const char *path; @@ -116,11 +117,12 @@ static bool flush = false; static long long size; int main(int argc, char **argv) { - mode_type mode = NONE; + mode_type mode = BOTH; int n; while((n = getopt_long(argc, argv, "+s:vcefhV", opts, 0)) >= 0) { switch(n) { case 's': seed = optarg; break; + case 'b': mode = BOTH; break; case 'v': mode = VERIFY; break; case 'c': mode = CREATE; break; case 'e': entireopt = true; break; @@ -133,10 +135,10 @@ int main(int argc, char **argv) { } argc -= optind; argv += optind; - if(mode == NONE) - fatal(0, "must specify one of --verify or --create"); if(argc > 2) fatal(0, "excess arguments"); + if(argc == 1 && mode == BOTH) + entireopt = true; if(entireopt) { if(argc != 1) fatal(0, "with --entire, size should not be specified"); @@ -170,11 +172,16 @@ int main(int argc, char **argv) { size = sb.st_size; } const char *show = entireopt ? (mode == CREATE ? "written" : "verified") : 0; - execute(mode, entireopt, show); + if(mode == BOTH) { + size = execute(CREATE, entireopt, 0); + execute(VERIFY, false, show); + } else { + execute(mode, entireopt, show); + } return 0; } -static void execute(mode_type mode, bool entire, const char *show) { +static long long execute(mode_type mode, bool entire, const char *show) { Arcfour rng(seed, strlen(seed)); FILE *fp = fopen(path, mode == VERIFY ? "rb" : "wb"); if(!fp) @@ -185,6 +192,9 @@ static void execute(mode_type mode, bool entire, const char *show) { setvbuf(fp, 0, _IONBF, 0); char generated[4096], input[4096]; long long remain = size; + static const size_t rc4drop = 3072; // en.wikipedia.org/wiki/RC4#Security + assert(rc4drop <= sizeof(generated)); + rng.stream(generated, rc4drop); while(remain > 0) { size_t bytesGenerated = (remain > (ssize_t)sizeof generated ? sizeof generated @@ -240,4 +250,5 @@ static void execute(mode_type mode, bool entire, const char *show) { if(ferror(stdout) || fflush(stdout)) fatal(errno, "flush stdout"); } + return done; }