From 4accd8958f01d7aac837c2fff716ba14ea2aa4b7 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Tue, 27 Jan 2009 15:13:56 +0200 Subject: Added a --bits (-n) option to corrupt. --- corrupt.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 84 insertions(+), 25 deletions(-) (limited to 'corrupt.c') diff --git a/corrupt.c b/corrupt.c index f8c5cd2..0d29453 100644 --- a/corrupt.c +++ b/corrupt.c @@ -17,6 +17,7 @@ #define _LARGEFILE64_SOURCE +#define _GNU_SOURCE #include #include @@ -28,6 +29,11 @@ #include #include #include +#include + + +/* Number of bits to corrupt. */ +static int num_bits = 1; /* Choose a random integer in [0..n-1]. */ @@ -47,33 +53,27 @@ static long choose(long n) } -static int corrupt(const char *filename) +static int seek(const char *filename, int fd, off_t offset) { - int fd; - struct stat st; - - fd = open(filename, O_RDWR | O_LARGEFILE); - if (fd == -1) { - fprintf(stderr, "Can't open %s: %s\n", filename, strerror(errno)); + if (lseek(fd, offset, SEEK_SET) == (off_t) -1) { + fprintf(stderr, "Can't seek in %s: %s", filename, strerror(errno)); return -1; } + return 0; +} - if (fstat(fd, &st) == -1) { - fprintf(stderr, "Can't find length of %s: %s", filename, - strerror(errno)); - return -1; - } - long offset = choose(st.st_size); - long bit = choose(CHAR_BIT); - printf("%s: offset=%ld bit=%ld\n", filename, offset, bit); +static int corrupt_one_bit(const char *filename, int fd, struct stat st) +{ + long offset; + long bit; + unsigned char byte; + + offset = choose(st.st_size); + bit = choose(CHAR_BIT); - if (lseek(fd, offset, SEEK_SET) == (off_t) -1) { - fprintf(stderr, "Can't seek in %s: %s", filename, strerror(errno)); + if (seek(filename, fd, offset) == -1) return -1; - } - - unsigned char byte; if (read(fd, &byte, 1) == -1) { fprintf(stderr, "Can't read %s: %s", filename, strerror(errno)); return -1; @@ -87,14 +87,37 @@ static int corrupt(const char *filename) byte = others | toggled; /* Now write it back. */ - if (lseek(fd, offset, SEEK_SET) == (off_t) -1) { - fprintf(stderr, "Can't seek in %s: %s", filename, strerror(errno)); + if (seek(filename, fd, offset) == -1) return -1; - } if (write(fd, &byte, 1) != 1) { fprintf(stderr, "Can't write %s: %s", filename, strerror(errno)); return -1; } + + return 0; +} + + +static int corrupt(const char *filename) +{ + int fd; + struct stat st; + + fd = open(filename, O_RDWR | O_LARGEFILE); + if (fd == -1) { + fprintf(stderr, "Can't open %s: %s\n", filename, strerror(errno)); + return -1; + } + + if (fstat(fd, &st) == -1) { + fprintf(stderr, "Can't find length of %s: %s", filename, + strerror(errno)); + return -1; + } + + for (int i = 0; i < num_bits; ++i) + if (corrupt_one_bit(filename, fd, st) == -1) + return -1; if (close(fd) == -1) { fprintf(stderr, "Can't close %s: %s", filename, strerror(errno)); @@ -105,13 +128,49 @@ static int corrupt(const char *filename) } +static int parse_args(int argc, char **argv) +{ + const char optstring[] = "n:"; + const struct option longopts[] = { + { "bits", required_argument, NULL, 'n' }, + { 0 }, + }; + char *endptr; + + for (;;) { + int opt = getopt_long(argc, argv, optstring, longopts, NULL); + switch (opt) { + case -1: + return optind; + + case 'n': + num_bits = strtol(optarg, &endptr, 10); + if (*endptr != '\0') { + fprintf(stderr, "Invalid number of bits: %s\n", optarg); + exit(1); + } + break; + + default: + case '?': + exit(1); + } + } +} + + int main(int argc, char **argv) { int exit_code; - + int i; + + i = parse_args(argc, argv); + if (i == -1) + return 1; + srandom(time(NULL) + getpid()); exit_code = 0; - for (int i = 1; i < argc; ++i) + for (; i < argc; ++i) if (corrupt(argv[i]) == -1) exit_code = 1; return exit_code; -- cgit v1.2.1