ref: 3bc9c2fe9c978cfbe371fac4eb4c7cd092bedeae
author: Tevo <estevan.cps@gmail.com>
date: Tue Sep 1 21:25:23 EDT 2020
Initial commit
--- /dev/null
+++ b/TODO
@@ -1,0 +1,5 @@
+- Cleanup code
+- Non-destructive read/write and read-only tests
+- Verbosity level and progress/error messages
+- `aux/statusbar`-compatible output
+- Write man page
\ No newline at end of file
--- /dev/null
+++ b/checkdisk.c
@@ -1,0 +1,92 @@
+#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);
+}
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,18 @@
+</$objtype/mkfile
+
+SRC=checkdisk.c
+
+%.$O: %.c
+ $CC $CFLAGS -o $target $prereq
+
+$O.out: ${SRC:%.c=%.$O}
+ $LD $LFLAGS -o $target $prereq
+
+clean nuke:V:
+ rm -f [$OS].out *.[$OS]
+
+install:V: $O.out
+ cp $O.out /$objtype/bin/disk/check
+
+uninstall:V:
+ rm -f /$objtype/bin/disk/check