libroot/posix/stdio: Remove unused portions.
[haiku.git] / src / bin / badblocks.cpp
blobe8227b62cac2c8328b97c6027396f35fa1c7cb0c
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>
9 // for R5:
10 //#define pread(fd, buf, count, pos) read_pos(fd, pos, buf, count)
12 int blockSize = 1024;
13 int group = 64;
14 int progress = 1;
15 int verbose = 0;
16 FILE *outputFile = NULL;
18 int scan_device(const char *dev, off_t startBlock, off_t endBlock)
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;
27 buffer = (char *)malloc(len);
28 if (buffer == NULL)
29 return 1;
32 fd = open(dev, O_RDONLY);
33 if (fd < 0) {
34 perror("open");
35 goto err1;
37 // Check size
39 if (verbose)
40 fprintf(stderr, "Scanning '%s', %d * %d bytes at once\n",
41 dev, group, blockSize);
43 if (progress)
44 fprintf(stderr, "\n");
46 for (; block <= endBlock; block += group, at += len) {
47 int got;
48 if (progress)
49 fprintf(stderr, "checking block %Ld\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 %Ld (offset %Ld): got %d < %zd\n",
56 block, at, got, len);
57 break;
59 if (got < 0) {
60 fprintf(stderr, "block %Ld: error: %s\n", block, strerror(errno));
62 if (errno != EIO && errno != ENXIO) {
63 perror("pread");
64 goto err2;
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 %Ld: error: %s\n", block + i, strerror(errno));
76 else
77 fprintf(stderr, "block %Ld: read %d bytes\n", block + i, got);
78 fprintf(outputFile, "%Ld\n", block + i);
79 fflush(stdout);
83 close(fd);
84 free(buffer);
85 return 0;
87 close(fd);
88 err1:
89 free(buffer);
90 return 1;
93 int usage(int ret)
95 fprintf(stderr, "badblocks [-sv] [-b block-size] [-c block-at-once] "
96 "/dev/disk/... [end-block [start-block]]\n");
97 return ret;
100 int main(int argc, char **argv)
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);
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);
132 argc -= optind;
133 argv += optind;
135 if (argc > 2)
136 startBlock = atoll(argv[2]);
137 if (argc > 1)
138 endBlock = atoll(argv[1]);
140 return scan_device(argv[0], startBlock, endBlock);