9 const struct option opts[] = {
10 { "seed", required_argument, 0, 's' },
11 { "verify", no_argument, 0, 'v' },
12 { "create", no_argument, 0, 'c' },
13 { "help", no_argument, 0, 'h' },
14 { "version", no_argument, 0, 'V' },
18 static void help(void) {
19 printf("vbig - create or verify a large but pseudo-random file\n"
22 " vbig [--seed SEED] --verify|--create PATH SIZE\n"
25 " --seed Specify random seed\n"
26 " --verify Verify that PATH contains the expected contents\n"
27 " --create Create PATH with psuedo-random contents\n"
28 " --help Display usage message\n"
29 " --version Display version string\n");
38 int main(int argc, char **argv) {
39 const char *seed = "hexapodia as the key insight";
40 mode_type mode = NONE;
42 while((n = getopt_long(argc, argv, "+s:vchV", opts, 0)) >= 0) {
44 case 's': seed = optarg; break;
45 case 'v': mode = VERIFY; break;
46 case 'c': mode = CREATE; break;
47 case 'h': help(); exit(0);
48 case 'V': puts(VERSION); exit(0);
50 fprintf(stderr, "ERROR: unknown option\n");
55 fprintf(stderr, "ERROR: must specify one of --verify or --create\n");
58 if(optind + 2 != argc) {
59 fprintf(stderr, "ERROR: must specify a path and size\n");
62 const char *path = argv[optind];
65 long long size = strtoll(argv[optind + 1], &end, 10);
67 fprintf(stderr, "ERROR: invalid size: %s\n", strerror(errno));
70 if(end == argv[optind + 1]) {
71 fprintf(stderr, "ERROR: invalid size\n");
76 else if(!strcmp(end, "M"))
78 else if(!strcmp(end, "G"))
79 size *= 1024 * 1024 * 1024;
81 fprintf(stderr, "ERROR: invalid size\n");
84 Arcfour rng(seed, strlen(seed));
85 FILE *fp = fopen(path, mode == VERIFY ? "rb" : "wb");
87 fprintf(stderr, "ERROR: %s: %s\n", path, strerror(errno));
90 char generated[4096], input[4096];
93 size_t bytesGenerated = (remain > sizeof generated
96 rng.stream(generated, bytesGenerated);
98 fwrite(generated, 1, bytesGenerated, fp);
100 fprintf(stderr, "ERROR: %s: %s\n", path, strerror(errno));
104 size_t bytesRead = fread(input, 1, bytesGenerated, fp);
106 fprintf(stderr, "ERROR: %s: %s\n", path, strerror(errno));
109 if(bytesRead < bytesGenerated) {
110 fprintf(stderr, "ERROR: %s: truncated at %lld/%lld bytes\n",
111 path, (size - remain + bytesRead), size);
114 if(memcmp(generated, input, bytesGenerated)) {
115 for(size_t n = 0; n < bytesGenerated; ++n)
116 if(generated[n] != input[n]){
117 fprintf(stderr, "ERROR: %s corrupted at %lld/%lld bytes (expected %d got %d)\n",
118 path, size - remain + n, size,
119 (unsigned char)generated[n], (unsigned char)input[n]);
124 remain -= bytesGenerated;
126 if(mode == VERIFY && getc(fp) != EOF) {
127 fprintf(stderr, "ERROR: %s: extended beyond %lld bytes\n",
132 fprintf(stderr, "ERROR: %s: %s\n", path, strerror(errno));