#include <u.h>#include <libc.h>#include <bio.h> #include "scsireq.h" enum { /* fundamental constants/defaults */ /* * default & maximum `maximum i/o size'; overridden by -m. * limits kernel memory consumption. * 240K is exabyte maximum block size. */ MaxIOsize = 240*1024,}; #define MIN(a, b) ((a) < (b) ? (a): (b)) static char rwbuf[MaxIOsize];static int verbose = 1; Biobuf bin, bout;long maxiosize = MaxIOsize;int exabyte = 0;int force6bytecmds = 0; typedef struct { char *name; long (*f)(ScsiReq *, int, char *[]); int open; char *help;} ScsiCmd; static ScsiCmd scsicmd[]; static vlongvlmin(vlong a, vlong b){ if (a < b) return a; else return b;} static longcmdready(ScsiReq *rp, int argc, char *argv[]){ USED(argc, argv); return SRready(rp);} static longcmdrewind(ScsiReq *rp, int argc, char *argv[]){ USED(argc, argv); return SRrewind(rp);} static longcmdreqsense(ScsiReq *rp, int argc, char *argv[]){ long nbytes; USED(argc, argv); if((nbytes = SRreqsense(rp)) != -1) makesense(rp); return nbytes;} static longcmdformat(ScsiReq *rp, int argc, char *argv[]){ USED(argc, argv); return SRformat(rp);} static longcmdrblimits(ScsiReq *rp, int argc, char *argv[]){ uchar l[6]; long n; USED(argc, argv); if((n = SRrblimits(rp, l)) == -1) return -1; Bprint(&bout, " %2.2uX %2.2uX %2.2uX %2.2uX %2.2uX %2.2uX\n", l[0], l[1], l[2], l[3], l[4], l[5]); return n;} static intmkfile(char *file, int omode, int *pid){ int fd[2]; if(*file != '|'){ *pid = -1; if(omode == OWRITE) return create(file, OWRITE, 0666); else if(omode == OREAD) return open(file, OREAD); return -1; } file++; if(*file == 0 || pipe(fd) == -1) return -1; if((*pid = fork()) == -1){ close(fd[0]); close(fd[1]); return -1; } if(*pid == 0){ switch(omode){ case OREAD: dup(fd[0], 1); break; case OWRITE: dup(fd[0], 0); break; } close(fd[0]); close(fd[1]); execl("/bin/rc", "rc", "-c", file, nil); exits("exec"); } close(fd[0]); return fd[1];} intwaitfor(int pid){ int msg; Waitmsg *w; while((w = wait()) != nil){ if(w->pid != pid){ free(w); continue; } msg = (w->msg[0] != '\0'); free(w); return msg; } return -1;} static longcmdread(ScsiReq *rp, int argc, char *argv[]){ long n, iosize, prevsize = 0; vlong nbytes, total; int fd, pid; char *p; iosize = maxiosize; nbytes = ~0ULL >> 1; switch(argc){ default: rp->status = Status_BADARG; return -1; case 2: nbytes = strtoll(argv[1], &p, 0); if(nbytes == 0 && p == argv[1]){ rp->status = Status_BADARG; return -1; } /*FALLTHROUGH*/ case 1: if((fd = mkfile(argv[0], OWRITE, &pid)) == -1){ rp->status = Status_BADARG; return -1; } break; } print("bsize=%lud\n", rp->lbsize); total = 0; while(nbytes){ n = vlmin(nbytes, iosize); if((n = SRread(rp, rwbuf, n)) == -1){ if(total == 0) total = -1; break; } if (n == 0) break; if (prevsize != n) { print("tape block size=%ld\n", n); prevsize = n; } if(write(fd, rwbuf, n) != n){ if(total == 0) total = -1; if(rp->status == STok) rp->status = Status_SW; break; } nbytes -= n; total += n; } close(fd); if(pid >= 0 && waitfor(pid)){ rp->status = Status_SW; return -1; } return total;} static longcmdwrite(ScsiReq *rp, int argc, char *argv[]){ long n, prevsize = 0; vlong nbytes, total; int fd, pid; char *p; nbytes = ~0ULL >> 1; switch(argc){ default: rp->status = Status_BADARG; return -1; case 2: nbytes = strtoll(argv[1], &p, 0); if(nbytes == 0 && p == argv[1]){ rp->status = Status_BADARG; return -1; } /*FALLTHROUGH*/ case 1: if((fd = mkfile(argv[0], OREAD, &pid)) == -1){ rp->status = Status_BADARG; return -1; } break; } total = 0; while(nbytes){ n = vlmin(nbytes, maxiosize); if((n = read(fd, rwbuf, n)) == -1){ if(total == 0) total = -1; break; } if (n == 0) break; if (prevsize != n) { print("tape block size=%ld\n", n); prevsize = n; } if(SRwrite(rp, rwbuf, n) != n){ if(total == 0) total = -1; if(rp->status == STok) rp->status = Status_SW; break; } nbytes -= n; total += n; } close(fd); if(pid >= 0 && waitfor(pid)){ rp->status = Status_SW; return -1; } return total;} static longcmdseek(ScsiReq *rp, int argc, char *argv[]){ char *p; long offset; int type; type = 0; switch(argc){ default: rp->status = Status_BADARG; return -1; case 2: if((type = strtol(argv[1], &p, 0)) == 0 && p == argv[1]){ rp->status = Status_BADARG; return -1; } /*FALLTHROUGH*/ case 1: if((offset = strtol(argv[0], &p, 0)) == 0 && p == argv[0]){ rp->status = Status_BADARG; return -1; } break; } return SRseek(rp, offset, type);} static longcmdfilemark(ScsiReq *rp, int argc, char *argv[]){ char *p; ulong howmany; howmany = 1; if(argc && (howmany = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){ rp->status = Status_BADARG; return -1; } return SRfilemark(rp, howmany);} static longcmdspace(ScsiReq *rp, int argc, char *argv[]){ uchar code; long howmany; char option, *p; code = 0x00; howmany = 1; while(argc && (*argv)[0] == '-'){ while(option = *++argv[0]){ switch(option){ case '-': break; case 'b': code = 0x00; break; case 'f': code = 0x01; break; default: rp->status = Status_BADARG; return -1; } break; } argc--; argv++; if(option == '-') break; } if(argc && ((howmany = strtol(argv[0], &p, 0)) == 0 && p == argv[0])){ rp->status = Status_BADARG; return -1; } return SRspace(rp, code, howmany);} static longcmdinquiry(ScsiReq *rp, int argc, char *argv[]){ long status; int i, n; uchar *p; USED(argc, argv); if((status = SRinquiry(rp)) != -1){ n = rp->inquiry[4]+4; for(i = 0; i < MIN(8, n); i++) Bprint(&bout, " %2.2uX", rp->inquiry[i]); p = &rp->inquiry[8]; n = MIN(n, sizeof(rp->inquiry)-8); while(n && (*p == ' ' || *p == '\t' || *p == '\n')){ n--; p++; } Bprint(&bout, "\t%.*s\n", n, (char*)p); } return status;} static longcmdmodeselect6(ScsiReq *rp, int argc, char *argv[]){ uchar list[MaxDirData]; long nbytes, ul; char *p; memset(list, 0, sizeof list); for(nbytes = 0; argc; argc--, argv++, nbytes++){ if((ul = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){ rp->status = Status_BADARG; return -1; } list[nbytes] = ul; } if(!(rp->flags & Finqok) && SRinquiry(rp) == -1) Bprint(&bout, "warning: couldn't determine whether SCSI-1/SCSI-2 mode"); return SRmodeselect6(rp, list, nbytes);} longsel(ScsiReq *rp, uchar *list, long nbytes, int save){ uchar cmd[10]; memset(cmd, 0, sizeof cmd); cmd[0] = 0x55; cmd[1] = 0x10 | save!=0; /* standard (scsi-2) format */ cmd[7] = nbytes>>8; cmd[8] = nbytes; rp->cmd.p = cmd; rp->cmd.count = sizeof cmd; rp->data.p = list; rp->data.count = nbytes; rp->data.write = 1; return SRrequest(rp);} static longcmdmodeselect10(ScsiReq *rp, int argc, char *argv[]){ uchar list[MaxDirData]; int nbytes, save; char *p; save = 0; if(argc >= 1 && strcmp(*argv, "-s") == 0){ save = 1; argv++; argc--; } if(argc >= nelem(list)){ rp->status = Status_BADARG; return -1; } memset(list, 0, sizeof list); for(nbytes = 0; argc; argc--, argv++, nbytes++) if((list[nbytes] = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){ rp->status = Status_BADARG; return -1; } if(!(rp->flags & Finqok) && SRinquiry(rp) == -1) Bprint(&bout, "warning: couldn't determine whether SCSI-1/SCSI-2 mode");print("%d %d\n", nbytes, (rp->flags & Finqok) && (rp->inquiry[2] & 0x07) >= 2);// return SRmodeselect10(rp, list, nbytes); return sel(rp, list, nbytes, save);} static char*pflag(char *s, char *e, uint f, char **tab, uint ntab){ char *s0; uchar i; s0 = s; for(i = 0; i < ntab; i++) if(f & (1 << i)) s = seprint(s, e, "%s ", tab[i]); if(s > s0 && s[-1] == ' ') s--; *s = 0; return s;} static char*xlatenum(uint f, char **tab, uint ntab){ static char buf[64]; if(f < ntab && tab[f]) return tab[f]; snprint(buf, sizeof buf, "unknown val %#ux", f); return buf;} static char *recftab[] = {[0] "dcr",[1] "dte",[2] "per",[3] "eer",[4] "rc",[5] "tb",[6] "arre",[7] "awre",};voidrecoverpage(uchar *u){ char buf[128]; uint t; pflag(buf, buf + sizeof buf, u[2], recftab, nelem(recftab)); t = u[10]<<8 | u[11];Lines 1–500 of 2491. Load more
#include <u.h> #include <libc.h> #include <bio.h> #include "scsireq.h" enum { /* fundamental constants/defaults */ /* * default & maximum `maximum i/o size'; overridden by -m. * limits kernel memory consumption. * 240K is exabyte maximum block size. */ MaxIOsize = 240*1024, }; #define MIN(a, b) ((a) < (b) ? (a): (b)) static char rwbuf[MaxIOsize]; static int verbose = 1; Biobuf bin, bout; long maxiosize = MaxIOsize; int exabyte = 0; int force6bytecmds = 0; typedef struct { char *name; long (*f)(ScsiReq *, int, char *[]); int open; char *help; } ScsiCmd; static ScsiCmd scsicmd[]; static vlong vlmin(vlong a, vlong b) { if (a < b) return a; else return b; } static long cmdready(ScsiReq *rp, int argc, char *argv[]) { USED(argc, argv); return SRready(rp); } static long cmdrewind(ScsiReq *rp, int argc, char *argv[]) { USED(argc, argv); return SRrewind(rp); } static long cmdreqsense(ScsiReq *rp, int argc, char *argv[]) { long nbytes; USED(argc, argv); if((nbytes = SRreqsense(rp)) != -1) makesense(rp); return nbytes; } static long cmdformat(ScsiReq *rp, int argc, char *argv[]) { USED(argc, argv); return SRformat(rp); } static long cmdrblimits(ScsiReq *rp, int argc, char *argv[]) { uchar l[6]; long n; USED(argc, argv); if((n = SRrblimits(rp, l)) == -1) return -1; Bprint(&bout, " %2.2uX %2.2uX %2.2uX %2.2uX %2.2uX %2.2uX\n", l[0], l[1], l[2], l[3], l[4], l[5]); return n; } static int mkfile(char *file, int omode, int *pid) { int fd[2]; if(*file != '|'){ *pid = -1; if(omode == OWRITE) return create(file, OWRITE, 0666); else if(omode == OREAD) return open(file, OREAD); return -1; } file++; if(*file == 0 || pipe(fd) == -1) return -1; if((*pid = fork()) == -1){ close(fd[0]); close(fd[1]); return -1; } if(*pid == 0){ switch(omode){ case OREAD: dup(fd[0], 1); break; case OWRITE: dup(fd[0], 0); break; } close(fd[0]); close(fd[1]); execl("/bin/rc", "rc", "-c", file, nil); exits("exec"); } close(fd[0]); return fd[1]; } int waitfor(int pid) { int msg; Waitmsg *w; while((w = wait()) != nil){ if(w->pid != pid){ free(w); continue; } msg = (w->msg[0] != '\0'); free(w); return msg; } return -1; } static long cmdread(ScsiReq *rp, int argc, char *argv[]) { long n, iosize, prevsize = 0; vlong nbytes, total; int fd, pid; char *p; iosize = maxiosize; nbytes = ~0ULL >> 1; switch(argc){ default: rp->status = Status_BADARG; return -1; case 2: nbytes = strtoll(argv[1], &p, 0); if(nbytes == 0 && p == argv[1]){ rp->status = Status_BADARG; return -1; } /*FALLTHROUGH*/ case 1: if((fd = mkfile(argv[0], OWRITE, &pid)) == -1){ rp->status = Status_BADARG; return -1; } break; } print("bsize=%lud\n", rp->lbsize); total = 0; while(nbytes){ n = vlmin(nbytes, iosize); if((n = SRread(rp, rwbuf, n)) == -1){ if(total == 0) total = -1; break; } if (n == 0) break; if (prevsize != n) { print("tape block size=%ld\n", n); prevsize = n; } if(write(fd, rwbuf, n) != n){ if(total == 0) total = -1; if(rp->status == STok) rp->status = Status_SW; break; } nbytes -= n; total += n; } close(fd); if(pid >= 0 && waitfor(pid)){ rp->status = Status_SW; return -1; } return total; } static long cmdwrite(ScsiReq *rp, int argc, char *argv[]) { long n, prevsize = 0; vlong nbytes, total; int fd, pid; char *p; nbytes = ~0ULL >> 1; switch(argc){ default: rp->status = Status_BADARG; return -1; case 2: nbytes = strtoll(argv[1], &p, 0); if(nbytes == 0 && p == argv[1]){ rp->status = Status_BADARG; return -1; } /*FALLTHROUGH*/ case 1: if((fd = mkfile(argv[0], OREAD, &pid)) == -1){ rp->status = Status_BADARG; return -1; } break; } total = 0; while(nbytes){ n = vlmin(nbytes, maxiosize); if((n = read(fd, rwbuf, n)) == -1){ if(total == 0) total = -1; break; } if (n == 0) break; if (prevsize != n) { print("tape block size=%ld\n", n); prevsize = n; } if(SRwrite(rp, rwbuf, n) != n){ if(total == 0) total = -1; if(rp->status == STok) rp->status = Status_SW; break; } nbytes -= n; total += n; } close(fd); if(pid >= 0 && waitfor(pid)){ rp->status = Status_SW; return -1; } return total; } static long cmdseek(ScsiReq *rp, int argc, char *argv[]) { char *p; long offset; int type; type = 0; switch(argc){ default: rp->status = Status_BADARG; return -1; case 2: if((type = strtol(argv[1], &p, 0)) == 0 && p == argv[1]){ rp->status = Status_BADARG; return -1; } /*FALLTHROUGH*/ case 1: if((offset = strtol(argv[0], &p, 0)) == 0 && p == argv[0]){ rp->status = Status_BADARG; return -1; } break; } return SRseek(rp, offset, type); } static long cmdfilemark(ScsiReq *rp, int argc, char *argv[]) { char *p; ulong howmany; howmany = 1; if(argc && (howmany = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){ rp->status = Status_BADARG; return -1; } return SRfilemark(rp, howmany); } static long cmdspace(ScsiReq *rp, int argc, char *argv[]) { uchar code; long howmany; char option, *p; code = 0x00; howmany = 1; while(argc && (*argv)[0] == '-'){ while(option = *++argv[0]){ switch(option){ case '-': break; case 'b': code = 0x00; break; case 'f': code = 0x01; break; default: rp->status = Status_BADARG; return -1; } break; } argc--; argv++; if(option == '-') break; } if(argc && ((howmany = strtol(argv[0], &p, 0)) == 0 && p == argv[0])){ rp->status = Status_BADARG; return -1; } return SRspace(rp, code, howmany); } static long cmdinquiry(ScsiReq *rp, int argc, char *argv[]) { long status; int i, n; uchar *p; USED(argc, argv); if((status = SRinquiry(rp)) != -1){ n = rp->inquiry[4]+4; for(i = 0; i < MIN(8, n); i++) Bprint(&bout, " %2.2uX", rp->inquiry[i]); p = &rp->inquiry[8]; n = MIN(n, sizeof(rp->inquiry)-8); while(n && (*p == ' ' || *p == '\t' || *p == '\n')){ n--; p++; } Bprint(&bout, "\t%.*s\n", n, (char*)p); } return status; } static long cmdmodeselect6(ScsiReq *rp, int argc, char *argv[]) { uchar list[MaxDirData]; long nbytes, ul; char *p; memset(list, 0, sizeof list); for(nbytes = 0; argc; argc--, argv++, nbytes++){ if((ul = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){ rp->status = Status_BADARG; return -1; } list[nbytes] = ul; } if(!(rp->flags & Finqok) && SRinquiry(rp) == -1) Bprint(&bout, "warning: couldn't determine whether SCSI-1/SCSI-2 mode"); return SRmodeselect6(rp, list, nbytes); } long sel(ScsiReq *rp, uchar *list, long nbytes, int save) { uchar cmd[10]; memset(cmd, 0, sizeof cmd); cmd[0] = 0x55; cmd[1] = 0x10 | save!=0; /* standard (scsi-2) format */ cmd[7] = nbytes>>8; cmd[8] = nbytes; rp->cmd.p = cmd; rp->cmd.count = sizeof cmd; rp->data.p = list; rp->data.count = nbytes; rp->data.write = 1; return SRrequest(rp); } static long cmdmodeselect10(ScsiReq *rp, int argc, char *argv[]) { uchar list[MaxDirData]; int nbytes, save; char *p; save = 0; if(argc >= 1 && strcmp(*argv, "-s") == 0){ save = 1; argv++; argc--; } if(argc >= nelem(list)){ rp->status = Status_BADARG; return -1; } memset(list, 0, sizeof list); for(nbytes = 0; argc; argc--, argv++, nbytes++) if((list[nbytes] = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){ rp->status = Status_BADARG; return -1; } if(!(rp->flags & Finqok) && SRinquiry(rp) == -1) Bprint(&bout, "warning: couldn't determine whether SCSI-1/SCSI-2 mode"); print("%d %d\n", nbytes, (rp->flags & Finqok) && (rp->inquiry[2] & 0x07) >= 2); // return SRmodeselect10(rp, list, nbytes); return sel(rp, list, nbytes, save); } static char* pflag(char *s, char *e, uint f, char **tab, uint ntab) { char *s0; uchar i; s0 = s; for(i = 0; i < ntab; i++) if(f & (1 << i)) s = seprint(s, e, "%s ", tab[i]); if(s > s0 && s[-1] == ' ') s--; *s = 0; return s; } static char* xlatenum(uint f, char **tab, uint ntab) { static char buf[64]; if(f < ntab && tab[f]) return tab[f]; snprint(buf, sizeof buf, "unknown val %#ux", f); return buf; } static char *recftab[] = { [0] "dcr", [1] "dte", [2] "per", [3] "eer", [4] "rc", [5] "tb", [6] "arre", [7] "awre", }; void recoverpage(uchar *u) { char buf[128]; uint t; pflag(buf, buf + sizeof buf, u[2], recftab, nelem(recftab)); t = u[10]<<8 | u[11];