Logo Search packages:      
Sourcecode: hercules version File versions

dasdcopy.c

/* DASDCOPY.C   (c) Copyright Roger Bowler, 1999-2003                */
/*       Copy a dasd file to another dasd file.                      */
/*       Input file and output file may be compressed or not.        */
/*       Files may be either ckd (or cckd) or fba (or cfba) but      */
/*       file types (ckd/cckd or fba/cfba) may not be mixed.         */
/*-------------------------------------------------------------------*/

#include "hercules.h"
#include "dasdblks.h"

int syntax (char *);
void status (int, int);
int nulltrk(BYTE *, int, int);

#ifdef EXTERNALGUI
/* Special flag to indicate whether or not we're being
   run under the control of the external GUI facility. */
int  extgui = 0;
#endif /*EXTERNALGUI*/

#define CKD      0x01
#define CCKD     0x02
#define FBA      0x04
#define CFBA     0x06
#define CKDMASK  0x03
#define FBAMASK  0x0c
#define COMPMASK 0x0a

/*-------------------------------------------------------------------*/
/* Copy a dasd file to another dasd file                             */
/*-------------------------------------------------------------------*/
int main (int argc, char *argv[])
{
char           *pgm;                    /* -> Program name           */
int             ckddasd=-1;             /* 1=CKD  0=FBA              */
int             rc;                     /* Return code               */
int             quiet=0;                /* 1=Don't display status    */
int             comp=255;               /* Compression algorithm     */
int             cyls=-1, blks=-1;       /* Size of output file       */
int             lfs=0;                  /* 1=Create 1 large file     */
int             alt=0;                  /* 1=Create alt cyls         */
int             r=0;                    /* 1=Replace output file     */
int             in=0, out=0;            /* Input/Output file types   */
int             fd;                     /* Input file descriptor     */
char           *ifile, *ofile;          /* -> Input/Output file names*/
char           *sfile=NULL;             /* -> Input shadow file name */
CIFBLK         *icif, *ocif;            /* -> Input/Output CIFBLK    */
DEVBLK         *idev, *odev;            /* -> Input/Output DEVBLK    */
CKDDEV         *ckd=NULL;               /* -> CKD device table entry */
FBADEV         *fba=NULL;               /* -> FBA device table entry */
int             i, n, max;              /* Loop index, limits        */
BYTE            unitstat;               /* Device unit status        */
char            buf[512];               /* FBA i/o buffer            */

#if defined(ENABLE_NLS)
    setlocale(LC_ALL, "");
    bindtextdomain(PACKAGE, LOCALEDIR);
    textdomain(PACKAGE);
#endif

#ifdef EXTERNALGUI
    if (argc >= 1 && strcmp(argv[argc-1],"EXTERNALGUI") == 0)
    {
        extgui = 1;
        argc--;
    }
#endif /*EXTERNALGUI*/

    /* Figure out processing based on the program name */
    pgm = strrchr (argv[0], '/');
    if (pgm) pgm++;
    else pgm = argv[0];
    strtok (pgm, ".");
    if (strcmp(pgm, "ckd2cckd") == 0)
    {
        in = CKD;
        out = CCKD;
    }
    else if (strcmp(pgm, "cckd2ckd") == 0)
    {
        in = CCKD;
        out = CKD;
    }
    else if (strcmp(pgm, "fba2cfba") == 0)
    {
        in = FBA;
        out = CFBA;
    }
    else if (strcmp(pgm, "cfba2fba") == 0)
    {
        in = CFBA;
        out = FBA;
    }

    /* Process the arguments */
    for (argc--, argv++ ; argc > 0 ; argc--, argv++)
    {
        if (argv[0][0] != '-') break;
        if (strcmp(argv[0], "-v") == 0)
        {
             snprintf (buf, 512, _("Hercules %s copy program "), pgm);
             display_version (stderr, buf);
             return 0;
        }
        else if (strcmp(argv[0], "-h") == 0)
        {
            syntax(pgm);
            return 0;
        }
        else if (strcmp(argv[0], "-q") == 0
              || strcmp(argv[0], "-quiet") == 0)
            quiet = 1;  
        else if (strcmp(argv[0], "-r") == 0)
            r = 1;
#ifdef CCKD_COMPRESS_ZLIB
        else if (strcmp(argv[0], "-z") == 0)
            comp = CCKD_COMPRESS_ZLIB;
#endif
#ifdef CCKD_COMPRESS_BZIP2
        else if (strcmp(argv[0], "-bz2") == 0)
            comp = CCKD_COMPRESS_BZIP2;
#endif
        else if (strcmp(argv[0], "-0") == 0)
            comp = CCKD_COMPRESS_NONE;
        else if ((strcmp(argv[0], "-cyl") == 0
               || strcmp(argv[0], "-cyls") == 0) && cyls < 0)
        {
            if (argc < 2 || (cyls = atoi(argv[1])) < 0)
                return syntax(pgm);
            argc--; argv++;
        }
        else if ((strcmp(argv[0], "-blk") == 0
               || strcmp(argv[0], "-blks") == 0) && blks < 0)
        {
            if (argc < 2 || (blks = atoi(argv[1])) < 0)
                return syntax(pgm);
            argc--; argv++;
        }
        else if (strcmp(argv[0], "-a") == 0
              || strcmp(argv[0], "-alt") == 0
              || strcmp(argv[0], "-alts") == 0)
            alt = 1;
        else if (strcmp(argv[0], "-lfs") == 0)
            lfs = 1;
        else if (out == 0 && strcmp(argv[0], "-o") == 0)
        {
            if (argc < 2 || out != 0) return syntax(pgm);
            if (strcasecmp(argv[1], "ckd") == 0)
                out = CKD;
            else if (strcasecmp(argv[1], "cckd") == 0)
                out = CCKD;
            else if (strcasecmp(argv[1], "fba") == 0)
                out = FBA;
            else if (strcasecmp(argv[1], "cfba") == 0)
                out = CFBA;
            else
                return syntax(pgm);
            argc--; argv++;
        }
        else
            return syntax(pgm);
    }

    /* Get the file names:
       input-file [sf=shadow-file] output-file   */
    if (argc < 2 || argc > 3) return syntax(pgm);
    ifile = argv[0];
    if (argc < 3)
        ofile = argv[1];
    else
    {
        if (strlen(argv[1]) < 4 || memcmp(argv[1], "sf=", 3))
            return syntax(pgm);
        sfile = argv[1];
        ofile = argv[2];
    }

    /* If we don't know what the input file is then find out */
    if (in == 0)
    {
        fd = open (ifile, O_RDONLY|O_BINARY);
        if (fd < 0)
        {
            fprintf (stderr, _("HHCDC001E %s: %s open error: %s\n"),
                     pgm, ifile, strerror(errno));
            return -1;
        }
        rc = read (fd, buf, 8);
        if (rc < 8)
        {
            fprintf (stderr, _("HHCDC002E %s: %s read error: %s\n"),
                     pgm, ifile, strerror(errno));
            return -1;
        }
        if (memcmp(buf, "CKD_P370", 8) == 0)
            in = CKD;
        else if (memcmp(buf, "CKD_C370", 8) == 0)
            in = CCKD;
        else if (memcmp(buf, "FBA_C370", 8) == 0)
            in = CFBA;
        else
            in = FBA;
        close (fd);
    }

    /* If we don't know what the output file type is
       then derive it from the input file type */
    if (out == 0)
    {
        switch (in) {
        case CKD:  if (!lfs) out = CCKD;
                   else out = CKD;
                   break;
        case CCKD: if (comp == 255) out = CKD;
                   else out = CCKD;
                   break;
        case FBA:  if (!lfs) out = CFBA;
                   else out = FBA;
                   break;
        case CFBA: if (comp == 255) out = FBA;
                   else out = CFBA;
                   break;
        }
    }

    /* Set default compression if out file is to be compressed */
    if (comp == 255 && (out & COMPMASK))
#ifdef CCKD_COMPRESS_ZLIB
        comp = CCKD_COMPRESS_ZLIB;
#else
        comp = CCKD_COMPRESS_NONE;
#endif

    /* Perform sanity checks on the options */
    if ((in & CKDMASK) && !(out & CKDMASK)) return syntax(pgm);
    if ((in & FBAMASK) && !(out & FBAMASK)) return syntax(pgm);        
    if (sfile && !(in & COMPMASK)) return syntax(pgm);
    if (comp != 255 && !(out & COMPMASK)) return syntax(pgm);
    if (lfs && (out & COMPMASK)) return syntax(pgm);
    if (cyls >= 0 && !(in & CKDMASK)) return syntax(pgm);
    if (blks >= 0 && !(in & FBAMASK)) return syntax(pgm);
    if (!(in & CKDMASK) && alt) return syntax(pgm);

    /* Set the type of processing (ckd or fba) */
    ckddasd = (in & CKDMASK);

    /* Open the input file */
    if (ckddasd)
        icif = open_ckd_image (ifile, sfile, O_RDONLY|O_BINARY, 0);
    else
        icif = open_fba_image (ifile, sfile, O_RDONLY|O_BINARY, 0);
    if (icif == NULL)
    {
        fprintf (stderr, _("HHCDC003E %s: %s open failed\n"), pgm, ifile);
        return -1;
    }
    idev = &icif->devblk;

    /* Calculate the number of tracks or blocks to copy */
    if (ckddasd)
    {
        if (cyls < 0) cyls = idev->ckdcyls;
        else if (cyls == 0) cyls = (idev->ckdused)(idev);
        ckd = dasd_lookup (DASD_CKDDEV, NULL, idev->devtype, cyls);
        if (ckd == NULL)
        {
            fprintf (stderr, _("HHCDC004E %s: ckd lookup failed for %4.4X "
                     "cyls %d\n"),
                     pgm, idev->devtype, cyls);
            close_image_file (icif);
            return -1;
        }
        if (out == CCKD) cyls = ckd->cyls;
        if (cyls <= ckd->cyls && alt) cyls = ckd->cyls + ckd->altcyls;
        n = cyls * idev->ckdheads;
        max = idev->ckdtrks;
        if (max < n && out == CCKD) n = max;
    }
    else
    {
        if (blks < 0) blks = idev->fbanumblk;
        else if (blks == 0) blks = (idev->fbaused)(idev);
        fba = dasd_lookup (DASD_FBADEV, NULL, idev->devtype, blks);
        if (fba == NULL)
        {
            fprintf (stderr, _("HHCDC005E %s: fba lookup failed, blks %d\n"),
                     pgm, blks);
            close_image_file (icif);
            return -1;
        }
        n = blks;
        max = idev->fbanumblk;
        if (max < n && out == CFBA) n = max;
    }

    /* Create the output file */
    if (ckddasd)
        rc = create_ckd(ofile, idev->devtype, idev->ckdheads,
                        ckd->r1, cyls, "", comp, lfs, 1+r);
    else
        rc = create_fba(ofile, idev->devtype, fba->size,
                        blks, "", comp, lfs, 1+r);
    if (rc < 0)
    {
        fprintf (stderr, _("HHCDC006E %s: %s create failed\n"), pgm, ofile);
        close_image_file (icif);
        return -1;
    }

    /* Open the output file */
    if (ckddasd)
        ocif = open_ckd_image (ofile, NULL, O_RDWR|O_BINARY, 1);
    else
        ocif = open_fba_image (ofile, NULL, O_RDWR|O_BINARY, 1);
    if (ocif == NULL)
    {
        fprintf (stderr, _("HHCDC007E %s: %s open failed\n"), pgm, ofile);
        close_image_file (icif);
        return -1;
    }
    odev = &ocif->devblk;

    /* Copy the files */
    if (!quiet) printf (_("  %3d%% %7d of %d"), 0, 0, n);
    for (i = 0; i < n; i++)
    {
        /* Read a track or block */
        if (ckddasd)
        {
            if (i < max)
                rc = (idev->ckdrdtrk)(idev, i / idev->ckdheads,
                                      i % idev->ckdheads, &unitstat);
            else rc = nulltrk(&idev->buf[idev->bufoff], i, idev->ckdheads);
        }
        else
        {
            if (i < max)
                rc = (idev->fbardblk)(idev, buf, fba->size, &unitstat);
            else
                memset (buf, 0, 512);
                rc = 0;
        }
        if (rc < 0)
        {
            fprintf (stderr, _("HHCDC008E %s: %s read error %s %d "
                               "stat=%2.2X\n"),
                     pgm, ifile, ckddasd ? "track" : "block", i, unitstat);
            close_image_file(icif); close_image_file(ocif);
            return -1;
        }

        /* Write the track or block just read */
        if (ckddasd)
        {
            rc = (odev->ckdrdtrk)(odev, i / idev->ckdheads,
                  i % idev->ckdheads, &unitstat);
            if (rc == 0)
                rc = (odev->ckdupdtrk)(odev, &idev->buf[idev->bufoff],
                      idev->ckdtrksz, &unitstat);
        }
        else
            rc = (odev->fbawrblk)(odev, buf, fba->size, &unitstat);
        if (rc < 0)
        {
            fprintf (stderr, _("HHCDC009E %s: %s write error %s %d "
                               "stat=%2.2X\n"),
                     pgm, ofile, ckddasd ? "track" : "block", i, unitstat);
            close_image_file(icif); close_image_file(ocif);
            return -1;
        }

        /* Update the status indicator */
        if (!quiet) status (i+1, n);
    }

    if (!quiet) printf (_("\nHHCDC010I Copy successful !!!       \n"));
    close_image_file(icif); close_image_file(ocif);

    return 0;
}

/*-------------------------------------------------------------------*/
/* Build a null track image                                          */
/*-------------------------------------------------------------------*/
int nulltrk(BYTE *buf, int trk, int heads)
{
    BYTE cchh[4];
    int  cyl, head;
    static BYTE eighthexFF[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};

    /* cylinder and head calculations */
    cyl = trk / heads;
    head = trk % heads;
    cchh[0] = cyl >> 8;
    cchh[1] = cyl & 0xFF;
    cchh[2] = head >> 8;
    cchh[3] = head & 0xFF;

    /* A null track has a 5 byte track hdr, 8 byte r0 count,
       8 byte r0 data and 8 ff's */
    memset(buf, 0, 29);
    memcpy (&buf[1], cchh, sizeof(cchh));
    memcpy (&buf[5], cchh, sizeof(cchh));
    buf[12] = 8;
    memcpy (&buf[21], eighthexFF, 8);
    return 0;
}

/*-------------------------------------------------------------------*/
/* Display command syntax                                            */
/*-------------------------------------------------------------------*/
int syntax (char *pgm)
{
    char usage[8192];

    if (strcmp(pgm, "ckd2cckd") == 0)
        snprintf(usage,8192,_(
            "usage:  ckd2cckd [-options] ifile ofile\n"
            "\n"
            "     copy a ckd dasd file to a compressed ckd dasd file\n"
            "\n"
            "     ifile        --   input ckd dasd file\n"
            "     ofile        --   output compressed ckd dasd file\n"
            "\n"
            "   options:\n"
            "     -v                display program version and quit\n"
            "     -h                display this help and quit\n"
            "     -q                quiet mode, don't display status\n"
            "     -r                replace the output file if it exists\n"
            "%s"
            "%s"
            "     -0                don't compress track images\n"
            "     -cyls  n          size of output file\n"
            "     -a                output file will have alt cyls\n"
            ),
#ifdef CCKD_COMPRESS_ZLIB
            _(
            "     -z                compress using zlib [default]\n"
            ),
#else
            "",
#endif
#ifdef CCKD_COMPRESS_BZIP2
            _(
            "     -bz2              compress using bzip2\n"
            )
#else
            ""
#endif
            );
    else if (strcmp(pgm, "cckd2ckd") == 0)
        snprintf(usage,8192,_(
            "usage:  cckd2ckd [-options] ifile [sf=sfile] ofile\n"
            "\n"
            "     copy a compressed ckd file to a ckd file\n"
            "\n"
            "     ifile        --   input compressed ckd dasd file\n"
            "     sfile        --   input compressed ckd shadow file\n"
            "                       (optional)\n"
            "     ofile        --   output ckd dasd file\n"
            "\n"
            "   options:\n"
            "     -v                display program version and quit\n"
            "     -h                display this help and quit\n"
            "     -q                quiet mode, don't display status\n"
            "     -r                replace the output file if it exists\n"
            "     -lfs              create single large output file\n"
            "     -cyls  n          size of output file\n"
            "     -a                output file will have alt cyls\n"
            ));
    else if (strcmp(pgm, "fba2cfba") == 0)
        snprintf(usage,8192,_(
            "usage:  fba2cfba [-options] ifile ofile\n"
            "\n"
            "     copy a fba dasd file to a compressed fba dasd file\n"
            "\n"
            "     ifile        --   input fba dasd file\n"
            "     ofile        --   output compressed fba dasd file\n"
            "\n"
            "   options:\n"
            "     -v                display program version and quit\n"
            "     -h                display this help and quit\n"
            "     -q                quiet mode, don't display status\n"
            "     -r                replace the output file if it exists\n"
            "%s"
            "%s"
            "     -0                don't compress track images\n"
            "     -blks  n          size of output file\n"
            ),
#ifdef CCKD_COMPRESS_ZLIB
            _(
            "     -z                compress using zlib [default]\n"
            ),
#else
            "",
#endif
#ifdef CCKD_COMPRESS_BZIP2
            _(
            "     -bz2              compress using bzip2\n"
            )
#else
            ""
#endif
            );
    else if (strcmp(pgm, "cfba2fba") == 0)
        snprintf(usage,8192,_(
            "usage:  cfba2fba [-options] ifile [sf=sfile] ofile\n"
            "\n"
            "     copy a compressed fba file to a fba file\n"
            "\n"
            "     ifile        --   input compressed fba dasd file\n"
            "     sfile        --   input compressed fba shadow file\n"
            "                       (optional)\n"
            "     ofile        --   output fba dasd file\n"
            "\n"
            "   options:\n"
            "     -v                display program version and quit\n"
            "     -h                display this help and quit\n"
            "     -q                quiet mode, don't display status\n"
            "     -r                replace the output file if it exists\n"
            "     -lfs              create single large output file\n"
            "     -blks  n          size of output file\n"
            ));
    else
        snprintf(usage,8192,_(
            "usage:  %s [-options] ifile [sf=sfile] ofile\n"
            "\n"
            "     copy a dasd file to another dasd file\n"
            "\n"
            "     ifile        --   input dasd file\n"
            "     sfile        --   input shadow file [optional]\n"
            "     ofile        --   output dasd file\n"
            "\n"
            "   options:\n"
            "     -v                display program version and quit\n"
            "     -h                display this help and quit\n"
            "     -q                quiet mode, don't display status\n"
            "     -r                replace the output file if it exists\n"
            "%s"
            "%s"
            "     -0                don't compress output\n"
            "     -blks  n          size of output fba file\n"
            "     -cyls  n          size of output ckd file\n"
            "     -a                output ckd file will have alt cyls\n"
            "     -lfs              output ckd file will be a single file\n"
            "                       even if it exceeds 2G in size\n"
            "     -o     type       output file type (CKD, CCKD, FBA, CFBA)\n"
            ),
            pgm,
#ifdef CCKD_COMPRESS_ZLIB
            _(
            "     -z                compress using zlib [default]\n"
            ),
#else
            "",
#endif
#ifdef CCKD_COMPRESS_BZIP2
            _(
            "     -bz2              compress output using bzip2\n"
            )
#else
            ""
#endif
            );
    printf (usage);
    return -1;
} /* end function syntax */

/*-------------------------------------------------------------------*/
/* Display progress status                                           */
/*-------------------------------------------------------------------*/
void status (int i, int n)
{
static char indic[] = "|/-\\";

#ifdef EXTERNALGUI
    if (extgui)
    {
        if (i % 100) return;
        fprintf (stderr, "TRK=%d\n", i);
        return; 
    } 
#endif /*EXTERNALGUI*/
//  if (i % 101 != 1) return;
    printf ("\r%c %3d%% %7d", indic[i%4], (int)((i*100.0)/n), i);
} /* end function status */

Generated by  Doxygen 1.6.0   Back to index