/* * Copyright (C) 2009 Lars Wirzenius * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #define _LARGEFILE64_SOURCE #include #include #include #include #include #include #include #include #include #include /* Choose a random integer in [0..n-1]. */ static long choose(long n) { if (n == 0) return 0; long buckets = (RAND_MAX + 1L) / n; long max = buckets * n; long r; do { r = random(); } while (r >= max); return r / buckets; } 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; } long offset = choose(st.st_size); long bit = choose(CHAR_BIT); printf("%s: offset=%ld bit=%ld\n", filename, offset, bit); if (lseek(fd, offset, SEEK_SET) == (off_t) -1) { fprintf(stderr, "Can't seek in %s: %s", filename, strerror(errno)); return -1; } unsigned char byte; if (read(fd, &byte, 1) == -1) { fprintf(stderr, "Can't read %s: %s", filename, strerror(errno)); return -1; } /* This is where we toggle the bit. */ unsigned mask = 1 << bit; // All zeroes, except for the interesting bit. unsigned interesting = byte & mask; // Only the interesting bit can be 1. unsigned toggled = interesting ^ mask; // Interesting bit has been toggled. unsigned others = byte & (~mask); // Interesting bit is 0. 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)); return -1; } if (write(fd, &byte, 1) != 1) { fprintf(stderr, "Can't write %s: %s", filename, strerror(errno)); return -1; } if (close(fd) == -1) { fprintf(stderr, "Can't close %s: %s", filename, strerror(errno)); return -1; } return 0; } int main(int argc, char **argv) { int exit_code; srandom(time(NULL) + getpid()); exit_code = 0; for (int i = 1; i < argc; ++i) if (corrupt(argv[i]) == -1) exit_code = 1; return exit_code; }