ref: 3bc9c2fe9c978cfbe371fac4eb4c7cd092bedeae
dir: /checkdisk.c/
#include <u.h> #include <libc.h> const uint PATTERNS[] = { 0xC0A11E5C, 0xDEADBEEF, 0xB16B00B5, 0x00000000 }; void usage(void) { fprint(2, "usage: %s [-s start] [-t threshold] disk\n", argv0); exits("usage"); } void* emalloc(ulong size) { void *buf = malloc(size); if(buf == nil) sysfatal("malloc: %r"); return buf; } void repeat(void *dbuf, uint pat, ulong size) { uchar *buf = (uchar*)dbuf; for(int c = 0; c < size; c++) buf[c] = (uchar)(pat >> c%sizeof(pat)); } int chkdsk(int fd, int bsize, vlong seek, int thr) { void *buf = emalloc(bsize), *pat = emalloc(bsize); int pos = seek, read, bad = 0; for(int c = 0; c < sizeof(PATTERNS); c++) { repeat(pat, PATTERNS[c], bsize); while((read = pread(fd, buf, bsize, pos)) != 0) { pwrite(fd, pat, read, pos); pread(fd, buf, read, pos); if(memcmp(buf, pat, read) != 0) { print("%d\n", pos); bad++; } if(thr > 0 && bad >= thr) { goto cleanup; /* Need the goto to break out of the outer loop */ } pos += read; } } cleanup: free(buf); free(pat); return bad; } void main(int argc, char **argv) { int thr = 0, bsize = 512, diskfd; vlong seek = 0; ARGBEGIN { case 's': seek = atoll(EARGF(usage())); break; case 't': thr = atoi(EARGF(usage())); if(thr < 0) usage(); break; default: usage(); break; } ARGEND; if(argc != 1) usage(); if((diskfd = open(argv[0], ORDWR)) < 0) sysfatal("open: %r"); chkdsk(diskfd, bsize, seek, thr); close(diskfd); exits(0); }