summaryrefslogtreecommitdiff
path: root/corrupt.c
diff options
context:
space:
mode:
authorLars Wirzenius <liw@achmed>2009-01-27 15:13:56 +0200
committerLars Wirzenius <liw@achmed>2009-01-27 15:13:56 +0200
commit4accd8958f01d7aac837c2fff716ba14ea2aa4b7 (patch)
tree5ae2bf12a759d29931e83bbc08d949eb86d3bed4 /corrupt.c
parented8aefcec6235b5c70bf014699ccc3c4c6a43d80 (diff)
downloadextrautils-4accd8958f01d7aac837c2fff716ba14ea2aa4b7.tar.gz
Added a --bits (-n) option to corrupt.
Diffstat (limited to 'corrupt.c')
-rw-r--r--corrupt.c109
1 files changed, 84 insertions, 25 deletions
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 <errno.h>
#include <limits.h>
@@ -28,6 +29,11 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
+#include <getopt.h>
+
+
+/* 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;