Xinu7/src/cmd/dd58.c.RAW

/*
 *              V A X  -  T O  -  T U 5 8   C O P Y
 *
 * use:
 * dd58 [[-]verify] [[-]sam] [[-]maint] [count=c] [drive=d] [posit=p] action
 * where:
 * verify turns on verification mode (read and written data is checked)
 * sam    sets special addressing mode (address blocks of 128 bytes)
 * maint  turns on maintenance mode (no retries on data errors)
 * [A prefixed "-" turns the option off]
 * c      number of bytes to be used [MUST be present for read, defaults to
 *        the input size on write]
 * d      drive to be used
 * p      block number at which action is to commence
 * action one of:
 *        read          read from the TU58
 *        write         write to the TU58
 *        seek          position the TU58
 */

/*
 * useful goodies
 */
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include "{Xinu-directory}/include/tu58io.h"
#include "{Xinu-directory}/include/tu58errno.h"

/*
 * the defaults
 */
#define DEFCOUNT        (2048 * 128 + 1)        /* whole tape + 1 byte */
#define DEFDRIVE        "0"
#define DEFBLOCK        0
#define DEFBSIZ         512
#define DEFVFY          1
#define DEFMAINT        0
#define min(x,y)        ((x)>(y))?(y):(x)

/*
 * variables
 */
extern int terrno;              /* tape error number */
int count = DEFCOUNT;           /* number of bytes to be used */
char *drive = DEFDRIVE;         /* drive number */
int posit = DEFBLOCK;           /* drive position */
int blksiz = DEFBSIZ;           /* size of blocks (128 vs. 512) */
int verify = DEFVFY;            /* verification mode */
int maint = DEFMAINT;           /* maint mode */
int readflg = 0;                /* 1 for reading */
int writeflg = 0;               /* 1 for writing */
int seekflg = 0;                /* 1 for seeking */
int dn;                         /* drive descriptor */

/*
 * and we're off!
 */
main(argc, argv)
int argc;
char **argv;
{
        int i;                  /* counter in a for loop */

        /* walk arg list, setting parameters */
        for(i = 1; i < argc; i++)
                if (match(argv[i], "sam"))
                        blksiz = 128;
                else if (match(argv[i], "-sam"))
                        blksiz = 512;
                else if (match(argv[i], "verify"))
                        verify = 1;
                else if (match(argv[i], "-verify"))
                        verify = 0;
                else if (match(argv[i], "maint"))
                        maint = 1;
                else if (match(argv[i], "-maint"))
                        maint = 0;
                else if (match(argv[i], "drive")){
                        if ((drive = argv[i] + 5 + (argv[i][5] == '=')) == '\0')
                                drive = DEFDRIVE;
                }
                else if (match(argv[i], "posit"))
                        posit = atoi(argv[i] + 5 + (argv[i][5] == '='));
                else if (match(argv[i], "count"))
                        count = atoi(argv[i] + 5 + (argv[i][5] == '='));
                else if (match(argv[i], "read"))
                        readflg = 1;
                else if (match(argv[i], "write"))
                        writeflg = 1;
                else if (match(argv[i], "seek"))
                        seekflg = 1;
                else
                        fprintf(stderr, "%s: unknown option; ignored\n", argv[0]);

        /* exactly ONE action MUST be specified */
        if (readflg + writeflg + seekflg < 1){
                fprintf(stderr, "no action requested\n");
                exit(1);
        }
        else if (readflg + writeflg + seekflg > 1){
                fprintf(stderr, "inconsistent actions requested\n");
                exit(1);
        }

        /* open the drive ... */
        if (readflg)    /* ... for reading */
                if ((dn = topen(drive, 0, (char *) NULL)) < 0){
                        tperror("error opening TU58");
                        exit(1);
                }
                else if (count == DEFCOUNT){
                        fprintf(stderr, "no count given\n");
                        exit(1);
                }
                else{
                        /* go ! */
                        setioctl();
                        readtape(fileno(stdout));
                }
        else if (writeflg)      /* ... for writing */
                if ((dn = topen(drive, 1, (char *) NULL)) < 0){
                        tperror("error opening TU58");
                        exit(1);
                }
                else{
                        /* go ! */
                        setioctl();
                        writetape(fileno(stdin));
                }
        else if (seekflg)       /* ... for seeking */
                if ((dn = topen(drive, 2, (char *) NULL)) < 0){
                        tperror("error opening TU58");
                        exit(1);
                }
                else{
                        /* go ! */
                        setioctl();
                        seektape();
                }

        /* close the tape */
        if (tclose(dn) < 0)
                tperror("error closing TU58");
        exit(0);

}

/*
 * this sets the required parameters
 */
setioctl()
{
        /* position the drive (quicker than a seek) */
        if (tioctl(dn, TU58SPOS, &posit) < 0){
                tperror("error setting drive position");
                exit(1);
        }
        /* set special address mode */
        if (tioctl(dn, (blksiz == 128) ? TU58SSAM : TU58CSAM, NULL) < 0){
                tperror("error setting special address mode");
                exit(1);
        }
        /* set verify mode */
        if (tioctl(dn, verify ? TU58SVFY : TU58CVFY, NULL) < 0){
                tperror("error setting verify mode");
                exit(1);
        }
        /* set maintenance mode */
        if (tioctl(dn, maint ? TU58SMTM : TU58CMTM, NULL) < 0){
                tperror("error setting maintenance mode");
                exit(1);
        }
}

/*
 * this reads the tape
 */
readtape(fd)
int fd;                 /* output file descriptor */
{
        char buf[1024];         /* buffer for input */
        int n;                  /* number of bytes read */
        int ct;                 /* number of bytes remaining to be read */
        int x;                  /* number of bytes to be read this loop */

        /* your usual plug-and-chug loop */
        for(ct = count; ct > 0; ct -= x){
                x = min(blksiz, ct);
                if ((n = tread(dn, buf, x)) != x || terrno != TENONE)
                        tperror("dd58");
                else if (write(fd, buf, n) != n)
                        perror("dd58");
        }
        fprintf(stderr, "%d bytes, %d blocks read from block %d",
                                count-ct, (count-ct+blksiz-1)/blksiz, posit);
        fprintf(stderr, " (%d bytes to a block)\n", blksiz);
}

/*
 * this writes the tape
 */
writetape(fd)
int fd;                 /* output file descriptor */
{
        char buf[1024];         /* buffer for input */
        int n;                  /* number of bytes read */
        int ct;                 /* number of bytes remaining to be read */
        int x;                  /* number of bytes to be read on next loop */

        for(ct = 0; ct < count && (n = read(fd, buf, blksiz)) > 0; ct += n)
                if (twrite(dn, buf, n) != n || terrno != TENONE)
                        tperror("dd58");

        fprintf(stderr, "%d bytes, %d blocks written from block %d",
                                ct, (ct+blksiz-1)/blksiz, posit);
        fprintf(stderr, " (%d bytes to a block)\n", blksiz);
}

/*
 * this positions the tape
 */
seektape()
{
        /* try to position the tape */
        if (tseek(dn, posit, 0) != posit)
                perror("error positioning TU58");
        else{
                /* print "all done" message */
                fprintf(stderr, "drive %d positioned at block %d", dn, posit);
                fprintf(stderr, " (%d bytes to a block)\n", blksiz);
        }
}

/*
 * this matches patterns
 */
int match(a, b)
char *a, *b;                    /* return 1 if a matches b */
{
        while(*a && *a != '=' && *b++ == *a++);

        return(*a == '=' || !*b);
}