home *** CD-ROM | disk | FTP | other *** search
- static char sccsid[] = "@(#)lmdd.c 1.7";
-
- /*
- * lmdd, lm@sun.com (Larry McVoy)
- *
- * Uncopyrighted, do whatever you want with it.
- *
- * defaults:
- * bs=8k
- * count=forever
- * if=stdin
- * of=stdout
- * ipat=0
- * opat=0
- * mismatch=0
- * rusage=0
- * flush=0
- * shorthands:
- * recognizes 'k' or 'm' at the end of a number for 1024 & 1024^2
- * recognizes "internal" as an internal /dev/zero /dev/null file.
- */
- #include <signal.h>
- #include <sys/types.h>
- #include <sys/time.h>
- #ifndef SVR4
- #include <sys/resource.h>
- #endif
- #define FLUSH
- #ifdef FLUSH
- #include <unistd.h>
- #include <sys/mman.h>
- #include <sys/stat.h>
- #endif
- #define STARTUP (.11) /* XXX - about how long before it starts
- * working. So time matches w/ rusage. This is
- * close on a 20Mhz SS. */
- #define uchar unsigned char
-
- int out, Fsync, Sync, Flush, ru, c;/* done needs it */
- char *cmds[] = {
- "if", /* input file */
- "of", /* output file */
- "ipat", /* check input for pattern */
- "opat", /* generate pattern on output */
- "mismatch", /* stop at first mismatch */
- "bs", /* block size */
- "count", /* number of blocks */
- "skip", /* skip this number of blocks on input */
- "fsync", /* fsync output before exit */
- "sync", /* sync output before exit */
- "rusage", /* dump rusage stats */
- #ifdef FLUSH
- "flush", /* map in out and invalidate (flush) */
- #endif
- 0,
- };
-
- main(ac, av)
- char **av;
- {
- uint *buf;
- int misses, mismatch, outpat, inpat, bs, in, gotcnt, count;
- int skip;
- extern char *valloc();
- void done();
- int i;
-
- for (i = 1; i < ac; ++i) {
- chkarg(av[i]);
- }
- misses = mismatch = getarg("mismatch=", ac, av);
- inpat = getarg("ipat=", ac, av);
- outpat = getarg("opat=", ac, av);
- in = getfile("if=", ac, av);
- if (in == -1)
- in = 0;
- out = getfile("of=", ac, av);
- if (out == -1)
- out = 1;
- bs = getarg("bs=", ac, av);
- if (bs < 0)
- bs = 8192;
- Fsync = getarg("fsync=", ac, av);
- Sync = getarg("sync=", ac, av);
- ru = getarg("rusage=", ac, av);
- count = getarg("count=", ac, av);
- Flush = getarg("flush=", ac, av);
- if (count < 0)
- gotcnt = 0;
- else
- gotcnt = 1;
- c = 0;
- skip = getarg("skip=", ac, av);
-
- if (inpat != -1 || outpat != -1 && (bs & 3)) {
- printf("Block size must be word aligned\n");
- exit(1);
- }
- if (!(buf = (uint *) valloc((unsigned) bs))) {
- perror("valloc");
- exit(1);
- }
- bzero((char *) buf, bs);
-
- signal(SIGINT, done);
- if (skip > 0)
- lseek(in, skip * bs, 0);
- start();
- for (;;) {
- register x;
-
- if (gotcnt && count-- <= 0)
- done();
- if (in >= 0)
- x = read(in, buf, bs);
- else
- x = bs;
- if (x <= 0)
- done();
- if (inpat != -1) {
- register foo, cnt;
-
- for (foo = 0, cnt = x >> 2; cnt--; foo++) {
- if (buf[foo] != (uint) (c + foo)) {
- printf("ERROR: off=%d want=%x got=%x\n",
- c + foo, c + foo, buf[foo]);
- if (mismatch != -1 && --misses == 0)
- done();
- }
- }
- }
- if (outpat != -1) {
- register foo, cnt;
-
- for (foo = 0, cnt = x >> 2; cnt--; foo++)
- buf[foo] = c + foo;
- }
- if (out >= 0)
- if (write(out, buf, x) != x)
- done();
- c += x >> 2;
- }
- }
-
- chkarg(arg)
- char *arg;
- {
- int i;
- char *a, *b;
-
- for (i = 0; cmds[i]; ++i) {
- for (a = arg, b = cmds[i]; *a && *b && *a == *b; a++, b++)
- ;
- if (*a == '=')
- return (0);
- }
- printf("Bad arg: %s\n", arg);
- exit(1);
- }
-
- void
- done()
- {
- close(1);
- open("/dev/tty", 1);
- if (Sync > 0)
- sync();
- if (Fsync > 0)
- fsync(out);
- if (Flush > 0)
- flush(out);
- stop();
- #ifndef SVR4
- if (ru != -1)
- rusage();
- #endif
- ptime(c << 2);
- exit(0);
- }
-
- #define secs(tv) (tv.tv_sec + tv.tv_usec / 1000000.0)
-
- #ifndef SVR4
- rusage()
- {
- struct rusage r;
- double timespent();
- double idle;
-
- getrusage(RUSAGE_SELF, &r);
- idle = timespent() - (secs(r.ru_stime) + secs(r.ru_utime));
- idle = idle / timespent() * 100;
- printf("sys=%g user=%g stalled=%.0f%% rd=%d wr=%d min=%d maj=%d\n",
- secs(r.ru_stime), secs(r.ru_utime),
- idle, r.ru_inblock, r.ru_oublock,
- r.ru_minflt, r.ru_majflt);
- }
-
- #endif
-
- getarg(s, ac, av)
- char *s;
- char **av;
- {
- register len, i;
-
- len = strlen(s);
-
- for (i = 1; i < ac; ++i)
- if (!strncmp(av[i], s, len)) {
- register bs = atoi(&av[i][len]);
-
- if (rindex(&av[i][len], 'k'))
- bs *= 1024;
- else if (rindex(&av[i][len], 'm'))
- bs *= (1024 * 1024);
- return (bs);
- }
- return (-1);
- }
-
- char *output;
-
- getfile(s, ac, av)
- char *s;
- char **av;
- {
- register ret, len, i;
-
- len = strlen(s);
-
- for (i = 1; i < ac; ++i) {
- if (!strncmp(av[i], s, len)) {
- if (av[i][0] == 'o') {
- if (!strcmp("of=internal", av[i]))
- return (-2);
- ret = creat(&av[i][len], 0644);
- if (ret == -1)
- error(&av[i][len]);
- output = &av[i][len];
- return (ret);
- } else {
- if (!strcmp("if=internal", av[i]))
- return (-2);
- ret = open(&av[i][len], 0);
- if (ret == -1)
- error(&av[i][len]);
- return (ret);
- }
- }
- }
- return (-1);
- }
-
- #ifdef FLUSH
- flush()
- {
- int fd;
- struct stat sb;
- caddr_t where;
-
- if (output == NULL || (fd = open(output, 2)) == -1)
- return (warning("No output file"));
- if (fstat(fd, &sb) == -1 || sb.st_size == 0)
- return (warning(output));
- where = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
- msync(where, sb.st_size, MS_INVALIDATE);
- /* XXX - didn't unmap */
- }
- #endif
-
- /*
- * utilities for timing
- */
- #include "stdio.h"
- #include "sys/types.h"
- #include "sys/time.h"
-
- static struct timeval t1, t2;
-
- warning(s)
- char *s;
- {
- perror(s);
- return (-1);
- }
-
- error(s)
- char *s;
- {
- perror(s);
- exit(1);
- }
-
- start() {
- gettimeofday(&t1, (struct timezone *) 0);
- }
-
- stop() {
- gettimeofday(&t2, (struct timezone *) 0);
- }
-
- ptime(bytes) {
- ptransfer(bytes, &t1, &t2);
- }
- double
- timespent()
- {
- struct timeval td;
-
- tvsub(&td, &t2, &t1);
- return (td.tv_sec + (td.tv_usec / 1000000.) + STARTUP);
- }
-
- ptransfer(bytes, t0, t1)
- struct timeval *t0, *t1;
- {
- struct timeval td;
- float s, bs;
-
- tvsub(&td, t1, t0);
- s = td.tv_sec + (td.tv_usec / 1000000.);
- #define nz(x) ((x) == 0 ? 1 : (x))
- #define MB (1024*1024.0)
- bs = bytes / nz(s);
- printf("%.2f MB in %.2f seconds (%.4f MB/sec)\n", bytes / MB, s, bs / MB);
- }
-
- tvsub(tdiff, t1, t0)
- struct timeval *tdiff, *t1, *t0;
- {
-
- tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
- tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
- if (tdiff->tv_usec < 0)
- tdiff->tv_sec--, tdiff->tv_usec += 1000000;
- }
-