#include #include #include #include #include #include #include // for R5: //#define pread(fd, buf, count, pos) read_pos(fd, pos, buf, count) int blockSize = 1024; int group = 64; int progress = 1; int verbose = 0; FILE *outputFile = NULL; int scan_device(const char *dev, off_t startBlock, off_t endBlock) { char *buffer = NULL; size_t len = group * blockSize; off_t block = startBlock; off_t at = block * blockSize; int i; int fd; buffer = (char *)malloc(len); if (buffer == NULL) return 1; fd = open(dev, O_RDONLY); if (fd < 0) { perror("open"); goto err1; } // Check size if (verbose) fprintf(stderr, "Scanning '%s', %d * %d bytes at once\n", dev, group, blockSize); if (progress) fprintf(stderr, "\n"); for (; block <= endBlock; block += group, at += len) { int got; if (progress) fprintf(stderr, "checking block %lld\x1b[1A\n", block); got = pread(fd, buffer, len, at); if (got == len) continue; if (got >= 0) { if (verbose) fprintf(stderr, "block %lld (offset %lld): got %d < %zd\n", block, at, got, len); break; } if (got < 0) { fprintf(stderr, "block %lld: error: %s\n", block, strerror(errno)); /* if (errno != EIO && errno != ENXIO) { perror("pread"); goto err2; } */ } // try each block separately for (i = 0; i < group; i++) { got = pread(fd, buffer, blockSize, at + blockSize * i); if (got == blockSize) continue; if (got < blockSize) { if (got < 0) fprintf(stderr, "block %lld: error: %s\n", block + i, strerror(errno)); else fprintf(stderr, "block %lld: read %d bytes\n", block + i, got); fprintf(outputFile, "%lld\n", block + i); fflush(stdout); } } } close(fd); free(buffer); return 0; close(fd); err1: free(buffer); return 1; } int usage(int ret) { fprintf(stderr, "badblocks [-sv] [-b block-size] [-c block-at-once] " "/dev/disk/... [end-block [start-block]]\n"); return ret; } int main(int argc, char **argv) { int ch; off_t startBlock = 0LL; off_t endBlock = INT64_MAX; outputFile = stdout; if (argc < 2) return usage(1); while ((ch = getopt(argc, argv, "b:c:hsv?")) != -1) { switch (ch) { case 'b': blockSize = atoi(optarg); //fprintf(stderr, "bs %d\n", blockSize); break; case 'c': group = atoi(optarg); //fprintf(stderr, "g %d\n", group); break; case 's': progress = 1; break; case 'v': verbose = 1; break; case 'h': case '?': return usage(0); default: return usage(1); } } argc -= optind; argv += optind; if (argc > 2) startBlock = atoll(argv[2]); if (argc > 1) endBlock = atoll(argv[1]); return scan_device(argv[0], startBlock, endBlock); }