// 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' },
// Possible modes of operation
enum mode_type {
- NONE,
VERIFY,
- CREATE
+ CREATE,
+ BOTH
};
// Report an error and exit
#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;
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;
}
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");
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)
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
if(ferror(stdout) || fflush(stdout))
fatal(errno, "flush stdout");
}
+ return done;
}