1 #include <stdio.h> 2 #include <errno.h> 3 #include <fcntl.h> 4 #include <stdint.h> 5 #include <stdlib.h> 6 #include <string.h> 7 #include <unistd.h> 8 9 // for R5: 10 //#define pread(fd, buf, count, pos) read_pos(fd, pos, buf, count) 11 12 int blockSize = 1024; 13 int group = 64; 14 int progress = 1; 15 int verbose = 0; 16 FILE *outputFile = NULL; 17 18 int scan_device(const char *dev, off_t startBlock, off_t endBlock) 19 { 20 char *buffer = NULL; 21 size_t len = group * blockSize; 22 off_t block = startBlock; 23 off_t at = block * blockSize; 24 int i; 25 int fd; 26 27 buffer = (char *)malloc(len); 28 if (buffer == NULL) 29 return 1; 30 31 32 fd = open(dev, O_RDONLY); 33 if (fd < 0) { 34 perror("open"); 35 goto err1; 36 } 37 // Check size 38 39 if (verbose) 40 fprintf(stderr, "Scanning '%s', %d * %d bytes at once\n", 41 dev, group, blockSize); 42 43 if (progress) 44 fprintf(stderr, "\n"); 45 46 for (; block <= endBlock; block += group, at += len) { 47 int got; 48 if (progress) 49 fprintf(stderr, "checking block %lld\x1b[1A\n", block); 50 got = pread(fd, buffer, len, at); 51 if (got == len) 52 continue; 53 if (got >= 0) { 54 if (verbose) 55 fprintf(stderr, "block %lld (offset %lld): got %d < %zd\n", 56 block, at, got, len); 57 break; 58 } 59 if (got < 0) { 60 fprintf(stderr, "block %lld: error: %s\n", block, strerror(errno)); 61 /* 62 if (errno != EIO && errno != ENXIO) { 63 perror("pread"); 64 goto err2; 65 } 66 */ 67 } 68 // try each block separately 69 for (i = 0; i < group; i++) { 70 got = pread(fd, buffer, blockSize, at + blockSize * i); 71 if (got == blockSize) 72 continue; 73 if (got < blockSize) { 74 if (got < 0) 75 fprintf(stderr, "block %lld: error: %s\n", block + i, strerror(errno)); 76 else 77 fprintf(stderr, "block %lld: read %d bytes\n", block + i, got); 78 fprintf(outputFile, "%lld\n", block + i); 79 fflush(stdout); 80 } 81 } 82 } 83 close(fd); 84 free(buffer); 85 return 0; 86 87 close(fd); 88 err1: 89 free(buffer); 90 return 1; 91 } 92 93 int usage(int ret) 94 { 95 fprintf(stderr, "badblocks [-sv] [-b block-size] [-c block-at-once] " 96 "/dev/disk/... [end-block [start-block]]\n"); 97 return ret; 98 } 99 100 int main(int argc, char **argv) 101 { 102 int ch; 103 off_t startBlock = 0LL; 104 off_t endBlock = INT64_MAX; 105 outputFile = stdout; 106 if (argc < 2) 107 return usage(1); 108 109 while ((ch = getopt(argc, argv, "b:c:hsv?")) != -1) { 110 switch (ch) { 111 case 'b': 112 blockSize = atoi(optarg); 113 //fprintf(stderr, "bs %d\n", blockSize); 114 break; 115 case 'c': 116 group = atoi(optarg); 117 //fprintf(stderr, "g %d\n", group); 118 break; 119 case 's': 120 progress = 1; 121 break; 122 case 'v': 123 verbose = 1; 124 break; 125 case 'h': 126 case '?': 127 return usage(0); 128 default: 129 return usage(1); 130 } 131 } 132 argc -= optind; 133 argv += optind; 134 135 if (argc > 2) 136 startBlock = atoll(argv[2]); 137 if (argc > 1) 138 endBlock = atoll(argv[1]); 139 140 return scan_device(argv[0], startBlock, endBlock); 141 } 142