/* * bd-test.c * Copyright (C) 2010 Krzysztof Mazur * * 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 2 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, write to the Free Software Fundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include static char *device = NULL; #define SECTOR_SIZE 4096 #define SECTORS 1024 static unsigned char mirror[SECTORS * SECTOR_SIZE]; static int fd; static void show_info(void) { fprintf(stderr, "lsbd-fsck "PACKAGE_VERSION"\n" "Copyright (C) 2011 " "Krzysztof Mazur \n\n"); } static void show_usage(char *name) { show_info(); fprintf(stderr, "usage: %s [options] (file)\n" "Options:\n" " -b, --start set partition start\n" " -h, --help show this help\n" " -p, --partition partition number\n" " -s, --size set partition size\n" " -m, --mirror use mirroring\n" " -V, --version show version\n", (name == NULL) ? "lsbd-fsck" : name); exit(0); } static void parse_command_line(int argc, char **args) { int c; int option_index = 0; static struct option long_options[] = { {"help", 0, 0, 'h'}, {"version", 0, 0, 'V'}, {0, 0, 0, 0}, }; while (1) { c = getopt_long(argc, args, "hV", long_options, &option_index); if (c == -1) break; switch (c) { case 'h': show_usage(args[0]); break; case 'V': exit(0); break; default: fprintf(stderr, "Unknown option.\n"); exit(1); } } if (optind < argc) { device = args[optind++]; } } static void swrite(unsigned long id, void *buf) { lseek(fd, id * SECTOR_SIZE, SEEK_SET); write(fd, buf, SECTOR_SIZE); memcpy(mirror + id * SECTOR_SIZE, buf, SECTOR_SIZE); } static void sread(unsigned long id, void *buf) { lseek(fd, id * SECTOR_SIZE, SEEK_SET); read(fd, buf, SECTOR_SIZE); if (memcmp(mirror + id * SECTOR_SIZE, buf, SECTOR_SIZE)) fprintf(stderr, "sector %ld: read error\n", id); } int write_zeros(void) { unsigned int i; unsigned char buf[SECTOR_SIZE]; memset(buf, 0, sizeof(buf)); for (i = 0; i < SECTORS; i++) { swrite(i, buf); sread(i, buf); } for (i = 0; i < SECTORS; i++) sread(i, buf); return 0; } int write_random(void) { unsigned int i; unsigned char buf[SECTOR_SIZE]; unsigned long s; for (i = 0; i < 1000000; i++) { if (i % 1000 == 999) { fprintf(stderr, "."); } s = (unsigned long) (SECTORS * drand48()); if (s >= SECTORS) s = SECTORS - 1; sread(s, buf); memset(buf, 0, sizeof(buf)); buf[0] = (i >> 0) & 0xff; buf[1] = (i >> 8) & 0xff; buf[2] = (i >> 16) & 0xff; buf[3] = (i >> 24) & 0xff; swrite(s, buf); sread(s, buf); } for (i = 0; i < SECTORS; i++) sread(i, buf); return 0; } int main(int argc, char **argv) { parse_command_line(argc, argv); if (device == NULL) { fprintf(stderr, "error: device option is required\n"); exit(EXIT_FAILURE); } fd = open(device, O_RDWR); if (fd == -1) { perror("open"); exit(EXIT_FAILURE); } write_zeros(); write_random(); exit(EXIT_SUCCESS); }