#include "all.h" enum { Magic = 0xdeadbabe, Tocaddr = 100, Dataddr = 200, Second = 75*Bcdda/sizeof(long), }; typedef struct Buf Buf; struct Buf { long n; /* longs left in buffer */ long a; /* block address of beginning */ long da; /* offset to current block */ long o; /* total shorts read */ long s; /* total size */ long* buf; long* p; }; static Dev dev; static long blocksize; static long numblocks; static uchar* wbuf; static long fortot; static long forfs; static long forbs; static long maxlen; static long wlen; static long waddr; static long firstwaddr; static int dgetcap(void); static long bestlen(long); static void dumptrack(int, char*); static void pubtrack(int); static int Bget32(Buf*); int dopen(void) { int i; if(dev.chan.open == 0) { doprobe(Ddisk, &dev.chan); if(dev.chan.open == 0) { print("disk not on scsi\n"); return 1; } } if(dgetcap()) return 1; if(readscsi(dev.chan, dev.table, Tocaddr, sizeof(dev.table), blocksize, 0x28, 0)) return 1; for(i=0; i= Ntrack) { if(fromtrack != Trackall) { print("from track out of range %d-%d\n", 0, Ntrack); return; } } else if(dev.table[fromtrack].size == 0) { print("no data on track %d\n", fromtrack); return; } if(eol()) { print("file name: "); } getword(); if(fromtrack == Trackall) { for(i=0; i= 0 && m < l) l = m; } if(l == numblocks) l = numblocks - a; return l; } static void dumptrack(int track, char *file) { int f; long n, m, addr; f = create(file, OWRITE, 0666); if(f < 0) { print("cant open %s: %r\n", file); return; } if(wbuf) free(wbuf); forfs = dev.table[track].fsize; forbs = dev.table[track].bsize; fortot = dev.table[track].tsize; wlen = (forfs*forbs + blocksize - 1) / blocksize; wbuf = malloc(wlen*blocksize); if(wbuf == 0) { print("malloc failed\n"); return; } addr = dev.table[track].start; while(fortot > 0) { if(readscsi(dev.chan, wbuf, addr, wlen*blocksize, blocksize, 0x28, 0)) return; n = forfs*forbs; if(n > fortot) n = fortot; m = write(f, wbuf, n); if(m != n) { print("short write %d/%d: %r\n", m, n); break; } fortot -= n; addr += wlen; } close(f); } uchar* dbufalloc(long fs, long bs) { long l, a; int i; forfs = fs; forbs = bs; fortot = 0; wlen = (forfs*forbs + blocksize - 1) / blocksize; if(wbuf) free(wbuf); wbuf = malloc(wlen*blocksize); if(wbuf == 0) { print("malloc failed\n"); return 0; } maxlen = bestlen(Dataddr); waddr = Dataddr; for(i=0; i maxlen) { maxlen = l; waddr = a; } } firstwaddr = waddr; return wbuf; } void dcommit(int track, int type) { if(track < 0 || track >= Ntrack) { print("disk track not in range\n"); return; } dev.table[track].type = type; dev.table[track].start = firstwaddr; dev.table[track].size = waddr - firstwaddr; dev.table[track].fsize = forfs; dev.table[track].bsize = forbs; dev.table[track].tsize = fortot; writescsi(dev.chan, dev.table, Tocaddr, sizeof(dev.table), blocksize); } int dwrite(uchar *buf, long nb) { if(wbuf != buf) { print("horrible\n"); return 1; } if(waddr-firstwaddr+wlen > maxlen) { print("write overflow max = %ld\n", maxlen); return 1; } if(writescsi(dev.chan, buf, waddr, wlen*blocksize, blocksize)) return 1; waddr += wlen; fortot += nb*forbs; return 0; } void dpublish(void) { int fromtrack, i; fromtrack = gettrack("disk track [number]/*"); if(fromtrack < 0 || fromtrack >= Ntrack) { if(fromtrack != Trackall) { print("from track out of range %d-%d\n", 0, Ntrack); return; } } else if(dev.table[fromtrack].size == 0) { print("no data on track %d\n", fromtrack); return; } if(fromtrack == Trackall) { for(i=0; in > 0) { c = *b->p; b->p++; b->n--; b->o++; return c & 0x7fffffffL; } if(b->o >= b->s) return -1; if(readscsi(dev.chan, b->buf, b->a+b->da, wlen*blocksize, blocksize, 0x28, 0)) return -1; b->da += wlen; b->p = b->buf; b->n = forfs*forbs/sizeof(*b->p); if(b->o + b->n > b->s) b->n = b->s - b->o; goto loop; } static int verify1(Buf *b1, Buf *b2) { long c1, c2, n; b1->n = 0; b2->n = 0; b1->o = 0; b2->o = 0; b1->da = 0; b2->da = 0; n = 0; for(;;) { c1 = Bget32(b1); c2 = Bget32(b2); if(c2 == -1) break; if(c1 == c2) { if(c1 != 0) { n++; if(n > Second) break; } continue; } n = 0; c2 = Bget32(b2); if(c2 == -1 || b2->o > b1->o+Second) return 0; } n = b2->o - b1->o; b1->n = 0; b2->n = 0; b1->o = 0; b2->o = 0; b1->da = 0; b2->da = 0; for(; n>0; n--) Bget32(b2); for(;;) { c1 = Bget32(b1); c2 = Bget32(b2); if(c2 == -1) return 1; if(c1 != c2) return 0; } } int dverify(int track1, int track2) { Buf b1, b2; int f; if(dev.table[track1].fsize != dev.table[track2].fsize || dev.table[track1].bsize != dev.table[track2].bsize || dev.table[track1].tsize != dev.table[track2].tsize) { print("verify -- tracks not compat\n"); return 0; } forfs = dev.table[track1].fsize; forbs = dev.table[track1].bsize; fortot = dev.table[track1].tsize; wlen = (forfs*forbs + blocksize - 1) / blocksize; b1.buf = malloc(wlen*blocksize); b2.buf = malloc(wlen*blocksize); if(b1.buf == 0 || b2.buf == 0) { print("malloc failed\n"); exits("malloc"); } b1.a = dev.table[track1].start; b2.a = dev.table[track2].start; b1.s = fortot/sizeof(*b1.p); b2.s = fortot/sizeof(*b2.p); f = verify1(&b2, &b1) || verify1(&b1, &b2); free(b1.buf); free(b2.buf); if(f) print("tracks do not verify\n"); return f; } static void leadin(int n) { int i; memset(wbuf, 0, forbs); for(i=0; i 0) { if(readscsi(dev.chan, wbuf, addr, wlen*blocksize, blocksize, 0x28, 0)) break; n = forfs*forbs; if(n > fortot) n = fortot; m = pwrite(wbuf, n); if(m != n) { print("short write %d/%d: %r\n", m, n); break; } fortot -= n; addr += wlen; } pflush(); } static void sumtrack(int track) { long n, i, w, addr, sum; if(wbuf) free(wbuf); forfs = dev.table[track].fsize; forbs = dev.table[track].bsize; fortot = dev.table[track].tsize; wlen = (forfs*forbs + blocksize - 1) / blocksize; wbuf = malloc(wlen*blocksize); if(wbuf == 0) { print("malloc failed\n"); return; } sum = 0; addr = dev.table[track].start; while(fortot > 0) { if(readscsi(dev.chan, wbuf, addr, wlen*blocksize, blocksize, 0x28, 0)) break; n = forfs*forbs; if(n > fortot) n = fortot; for(i=0; i= Ntrack) { if(fromtrack != Trackall) { print("from track out of range %d-%d\n", 0, Ntrack); return; } } else if(dev.table[fromtrack].size == 0) { print("no data on track %d\n", fromtrack); return; } if(fromtrack == Trackall) { for(i=0; i