Esempio n. 1
0
int do_ls(char *file, char *sfile)
{
    CIFBLK *cif = open_ckd_image(file, sfile, O_RDONLY|O_BINARY, IMAGE_OPEN_NORMAL);

    if (!cif || do_ls_cif(cif) || close_ckd_image(cif))
        return -1;
    return 0;
}
Esempio n. 2
0
int main(int argc, char **argv) {

    DADSM    dadsm;                  // DADSM workarea
    FILE    *fout = NULL;           // output file
    CIFBLK  *cif;
    int      dsn_recs_written = 0, bail, dsorg, rc;
    char     pathname[MAX_PATH];

    fprintf(stderr, "dasdseq %s (C) Copyright 1999-2010 Roger Bowler\n"
        "Portions (C) Copyright 2001-2010 James M. Morrison\n", VERSION);
    if (debug) fprintf(stderr, "DEBUG enabled\n");

//  Parse command line

    memset(&dadsm, 0, sizeof(dadsm));           // init DADSM workarea
    rc = parsecmd(argc, argv, &dadsm);
    if (rc) exit(rc);

//  Open CKD image

    cif = open_ckd_image(din, sfn, O_RDONLY | O_BINARY, 0);
    if (!cif) {
        fprintf(stderr, "dasdseq unable to open image file %s\n", din);
        exit(20);
    }

//  Unless -abs specified (in which case trust the expert user):
//  Retrieve extent information for the dataset
//  Display dataset attributes
//  Verify dataset has acceptable attributes

    if (!absvalid) {
        rc = dadsm_setup(cif, &argdsn, &dadsm, local_verbose);
        if (rc) {
            close_ckd_image(cif);
            exit(rc);
        }
        if (local_verbose) {
            fprintf(stderr, "\n"); 
            showf1(stderr, &dadsm.f1buf, dadsm.f1ext, copy_verbose);
            fprintf(stderr, "\n");
        }
        bail = 1;
        dsorg = (dadsm.f1buf.ds1dsorg[0] << 8) | (dadsm.f1buf.ds1dsorg[1]); 
        if (dsorg & (DSORG_PS * 256)) {
            if ((dadsm.f1buf.ds1recfm & RECFM_FORMAT) == RECFM_FORMAT_F) 
                bail = 0;
            if ((dadsm.f1buf.ds1recfm & RECFM_FORMAT) == RECFM_FORMAT_V) {
                bail = 1;               // not yet
                fprintf(stderr, "dasdseq only supports RECFM=F[B]\n");
            }
        } else 
            fprintf(stderr, "dasdseq only supports DSORG=PS datasets\n");
        if (bail) {
            close_ckd_image(cif);
            exit(21);
        }
    }

//  Open output dataset (EBCDIC requires binary open)

    hostpath(pathname, argdsn, sizeof(pathname));

    fout = fopen(pathname, (tran_ascii) ? "wb" : "w");
    if (fout == NULL) {
        fprintf(stderr, "dasdseq unable to open output file %s, %s\n",
                argdsn, strerror(errno));
        close_ckd_image(cif);
        exit(22);
    }
    if (local_verbose)
        fprintf(stderr, "dasdseq writing %s\n", argdsn);

//  Write dasd data to output dataset

    dsn_recs_written = fbcopy(fout, cif, &dadsm, tran_ascii, copy_verbose);
    if (dsn_recs_written == -1)
        fprintf(stderr, "dasdseq error processing %s\n", argdsn);
    else
        fprintf(stderr, "dasdseq wrote %d records to %s\n", 
                dsn_recs_written, argdsn);

//  Close output dataset, dasd image and return to caller

    fclose(fout);
    if (local_verbose > 2) fprintf(stderr, "CLOSED %s\n", argdsn);
    if (local_verbose > 3) {
        fprintf(stderr, "CIFBLK\n");
        data_dump((void *) cif, sizeof(CIFBLK));
    }
    close_ckd_image(cif);
    if (local_verbose > 2) fprintf(stderr, "CLOSED image\n");
    return rc;

} /* main */
Esempio n. 3
0
/*-------------------------------------------------------------------*/
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            msgbuf[512];            /* Message buffer            */
size_t          fba_bytes_remaining=0;  /* FBA bytes to be copied    */
int             nullfmt = CKDDASD_NULLTRK_FMT0; /* Null track format */
char            pathname[MAX_PATH];     /* file path in host format  */
char            pgmpath[MAX_PATH];      /* prog path in host format  */

    INITIALIZE_UTILITY("dasdcopy");

    /* Figure out processing based on the program name */
    hostpath(pgmpath, argv[0], sizeof(pgmpath));
    pgm = strrchr (pgmpath, '/');
    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 (msgbuf, 512, _("Hercules %s copy program "), pgm);
             display_version (stderr, msgbuf, FALSE);
             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)
    {
        BYTE buf[8];
        hostpath(pathname, ifile, sizeof(pathname));
        fd = hopen(pathname, 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;
    if (idev->oslinux) nullfmt = CKDDASD_NULLTRK_FMT2;

    /* Calculate the number of tracks or blocks to copy */
    if (ckddasd)
    {
        if (cyls < 0) cyls = idev->ckdcyls;
        else if (cyls == 0) cyls = (idev->hnd->used)(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
    {
        fba_bytes_remaining = idev->fbanumblk * idev->fbablksiz;
        if (blks < 0) blks = idev->fbanumblk;
        else if (blks == 0) blks = (idev->hnd->used)(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;
        n = (n + FBA_BLKS_PER_GRP - 1) / FBA_BLKS_PER_GRP;
        max = (max + FBA_BLKS_PER_GRP - 1) / FBA_BLKS_PER_GRP;
    }

    /* Create the output file */
    if (ckddasd)
        rc = create_ckd(ofile, idev->devtype, idev->ckdheads,
                        ckd->r1, cyls, "", comp, lfs, 1+r, nullfmt, 0);
    else
        rc = create_fba(ofile, idev->devtype, fba->size,
                        blks, "", comp, lfs, 1+r, 0);
    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 */
#ifdef EXTERNALGUI
    if (extgui)
        /* Notify GUI of total #of tracks or blocks being copied... */
        fprintf (stderr, "TRKS=%d\n", n);
    else
#endif /*EXTERNALGUI*/
    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->hnd->read)(idev, i, &unitstat);
            else
            {
                memset (idev->buf, 0, idev->ckdtrksz);
                rc = nulltrk(idev->buf, i, idev->ckdheads, nullfmt);
            }
        }
        else
        {
            if (i < max)
                rc = (idev->hnd->read)(idev, i, &unitstat);
            else
                memset (idev->buf, 0, FBA_BLKGRP_SIZE);
                rc = 0;
        }
        if (rc < 0)
        {
            fprintf (stderr, _("HHCDC008E %s: %s read error %s %d "
                               "stat=%2.2X, null %s substituted\n"),
                     pgm, ifile, ckddasd ? "track" : "block", i, unitstat,
                     ckddasd ? "track" : "block");
            if (ckddasd)
                nulltrk(idev->buf, i, idev->ckdheads, nullfmt);
            else
                memset (idev->buf, 0, FBA_BLKGRP_SIZE);
            if (!quiet)
            {
                printf (_("  %3d%% %7d of %d"), 0, 0, n);
                status (i, n);
            }
        }

        /* Write the track or block just read */
        if (ckddasd)
        {
            rc = (odev->hnd->write)(odev, i, 0, idev->buf,
                      idev->ckdtrksz, &unitstat);
        }
        else
        {
            if (fba_bytes_remaining >= (size_t)idev->buflen)
            {
                rc = (odev->hnd->write)(odev,  i, 0, idev->buf,
                          idev->buflen, &unitstat);
                fba_bytes_remaining -= (size_t)idev->buflen;
            }
            else
            {
                ASSERT(fba_bytes_remaining > 0 && (i+1) >= n);
                rc = (odev->hnd->write)(odev,  i, 0, idev->buf,
                          (int)fba_bytes_remaining, &unitstat);
                fba_bytes_remaining = 0;
            }
        }
        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);
    }

    close_image_file(icif); close_image_file(ocif);
    if (!quiet) printf (_("\r"));
    printf (_("HHCDC010I %s successfully completed.\n"), pgm);
    return 0;
}
Esempio n. 4
0
int main(int argc, char **argv)
{
 char           *pgm;                    /* less any extension (.ext) */
 int             rc = 0;
 CIFBLK         *cif = 0;
 char           *fn;
 char           *sfn;

    INITIALIZE_UTILITY( UTILITY_NAME, "DASD cat program", &pgm );

    if (argc < 2)
    {
        // "Usage: dasdcat..."
        WRMSG( HHC02405, "I", pgm );
        return 1;
    }

 /*
 * If your version of Hercules doesn't have support in its
 * dasdutil.c for turning off verbose messages, then remove
 * the following line but you'll have to live with chatty
 * progress output on stdout.
 */
 set_verbose_util(0);

 while (*++argv)
 {
     if (!strcmp(*argv, "-i"))
     {
         fn = *++argv;
         if (*(argv+1) && strlen (*(argv+1)) > 3 && !memcmp(*(argv+1), "sf=", 3))
             sfn = *++argv;
         else sfn = NULL;
         if (cif)
         {
             close_ckd_image(cif);
             cif = 0;
         }
         cif = open_ckd_image(fn, sfn, O_RDONLY | O_BINARY, IMAGE_OPEN_NORMAL);
         if (!cif)
         {
             // "Failed opening %s"
             FWRMSG( stderr, HHC02403, "E", *argv );
             rc = 1;
             break;
         }
     }
     else if (cif)
     {
         if ((rc = do_cat( cif, *argv )) != 0)
         {
             rc = 1;
             break;
         }
     }
 }

 if (cif)
 close_ckd_image(cif);

 return rc;
}
Esempio n. 5
0
/*-------------------------------------------------------------------*/
int main (int argc, char *argv[])
{
char           *pgm;                    /* less any extension (.ext) */
int             rc;                     /* Return code               */
int             i=0;                    /* Arument index             */
U16             len;                    /* Record length             */
U32             cyl;                    /* Cylinder number           */
U8              head;                   /* Head number               */
U8              rec;                    /* Record number             */
u_int           trk;                    /* Relative track number     */
char           *fname;                  /* -> CKD image file name    */
char           *sfname=NULL;            /* -> CKD shadow file name   */
char            dsnama[45];             /* Dataset name (ASCIIZ)     */
int             noext;                  /* Number of extents         */
DSXTENT         extent[16];             /* Extent descriptor array   */
BYTE           *blkptr;                 /* -> PDS directory block    */
BYTE            dirblk[256];            /* Copy of directory block   */
CIFBLK         *cif;                    /* CKD image file descriptor */

    INITIALIZE_UTILITY( UTILITY_NAME,  "PDS unload", &pgm );

    /* Check the number of arguments */
    if (argc < 3 || argc > 5)
    {
        FWRMSG( stderr, HHC02463, "I", pgm, " pdsname [ascii]" );
        return -1;
    }

    /* The first argument is the name of the CKD image file */
    fname = argv[1];

    /* The next argument may be the shadow file name */
    if (!memcmp (argv[2], "sf=", 3))
    {
        sfname = argv[2];
        i = 1;
    }

    /* The second argument is the dataset name */
    memset (dsnama, 0, sizeof(dsnama));
    strncpy (dsnama, argv[2|+i], sizeof(dsnama)-1);
    string_to_upper (dsnama);

    /* The third argument is an optional keyword */
    if (argc > 3+i && argv[3+i] != NULL)
    {
        if (strcasecmp(argv[3+i], "ascii") == 0)
            asciiflag = 1;
        else
        {
            FWRMSG( stderr, HHC02465, "E", argv[3+i] );
            FWRMSG( stderr, HHC02463, "I", argv[0], " pdsname [ascii]" );
            return -1;
        }
    }

    /* Open the CKD image file */
    cif = open_ckd_image (fname, sfname, O_RDONLY|O_BINARY, IMAGE_OPEN_NORMAL);
    if (cif == NULL) return -1;

    /* Build the extent array for the requested dataset */
    rc = build_extent_array (cif, dsnama, extent, &noext);
    if (rc < 0) return -1;

#ifdef EXTERNALGUI
    /* Calculate ending relative track */
    if (extgui)
    {
        int bcyl;  /* Extent begin cylinder     */
        int btrk;  /* Extent begin head         */
        int ecyl;  /* Extent end cylinder       */
        int etrk;  /* Extent end head           */
        int trks;  /* total tracks in dataset   */
        int i;     /* loop control              */

        for (i = 0, trks = 0; i < noext; i++)
        {
            bcyl = (extent[i].xtbcyl[0] << 8) | extent[i].xtbcyl[1];
            btrk = (extent[i].xtbtrk[0] << 8) | extent[i].xtbtrk[1];
            ecyl = (extent[i].xtecyl[0] << 8) | extent[i].xtecyl[1];
            etrk = (extent[i].xtetrk[0] << 8) | extent[i].xtetrk[1];

            trks += (((ecyl * cif->heads) + etrk) - ((bcyl * cif->heads) + btrk)) + 1;
        }

        EXTGUIMSG( "ETRK=%d\n", trks-1 );
    }
#endif /*EXTERNALGUI*/

    /* Point to the start of the directory */
    trk = 0;
    rec = 1;

    /* Read the directory */
    while (1)
    {
        EXTGUIMSG( "CTRK=%d\n", trk );

        /* Convert relative track to cylinder and head */
        rc = convert_tt (trk, noext, extent, cif->heads, &cyl, &head);
        if (rc < 0) return -1;

        /* Read a directory block */
        WRMSG( HHC02466, "I", cyl, head, rec );

        rc = read_block (cif, cyl, head, rec,
                        NULL, NULL, &blkptr, &len);
        if (rc < 0) return -1;

        /* Move to next track if block not found */
        if (rc > 0)
        {
            trk++;
            rec = 1;
            continue;
        }

        /* Exit at end of directory */
        if (len == 0) break;

        /* Copy the directory block */
        memcpy (dirblk, blkptr, sizeof(dirblk));

        /* Process each member in the directory block */
        rc = process_dirblk (cif, noext, extent, dirblk);
        if (rc < 0) return -1;
        if (rc > 0) break;

        /* Point to the next directory block */
        rec++;

    } /* end while */

    WRMSG( HHC02467, "I" );

    /* Close the CKD image file and exit */
    rc = close_ckd_image (cif);
    return rc;

} /* end function main */
Esempio n. 6
0
/*-------------------------------------------------------------------*/
int main (int argc, char *argv[])
{
char           *pgm;                    /* less any extension (.ext) */
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        */
size_t          fba_bytes_remaining=0;  /* FBA bytes to be copied    */
int             nullfmt = CKDDASD_NULLTRK_FMT0; /* Null track format */
char            pathname[MAX_PATH];     /* file path in host format  */

    INITIALIZE_UTILITY( UTILITY_NAME, "DASD copy/convert", &pgm );

    if (strcasecmp(pgm, "ckd2cckd") == 0)
    {
        in = CKD;
        out = CCKD;
    }
    else if (strcasecmp(pgm, "cckd2ckd") == 0)
    {
        in = CCKD;
        out = CKD;
    }
    else if (strcasecmp(pgm, "fba2cfba") == 0)
    {
        in = FBA;
        out = CFBA;
    }
    else if (strcasecmp(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], "-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)
    {
        BYTE buf[8];
        hostpath(pathname, ifile, sizeof(pathname));
        fd = HOPEN (pathname, O_RDONLY|O_BINARY);
        if (fd < 0)
        {
            // "Error in function %s: %s"
            FWRMSG( stderr, HHC02412, "E", "open()", strerror(errno) );
            return -1;
        }
        rc = read (fd, buf, 8);
        if (rc < 8)
        {
            // "Error in function %s: %s"
            FWRMSG( stderr, HHC02412, "E", "read()", 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, IMAGE_OPEN_NORMAL);
    else
        icif = open_fba_image (ifile, sfile, O_RDONLY|O_BINARY, IMAGE_OPEN_NORMAL);
    if (icif == NULL)
    {
        // "Failed opening %s"
        FWRMSG( stderr, HHC02403, "E", ifile );
        return -1;
    }
    idev = &icif->devblk;
    if (idev->oslinux) nullfmt = CKDDASD_NULLTRK_FMT2;

    /* Calculate the number of tracks or blocks to copy */
    if (ckddasd)
    {
        if (cyls < 0) cyls = idev->ckdcyls;
        else if (cyls == 0) cyls = (idev->hnd->used)(idev);
        ckd = dasd_lookup (DASD_CKDDEV, NULL, idev->devtype, 0);
        if (ckd == NULL)
        {
            // "CKD lookup failed: device type %04X cyls %d"
            FWRMSG( stderr, HHC02430, "E",
                     idev->devtype, cyls );
            close_image_file (icif);
            return -1;
        }
        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
    {
        fba_bytes_remaining = idev->fbanumblk * idev->fbablksiz;
        if (blks < 0) blks = idev->fbanumblk;
        else if (blks == 0) blks = (idev->hnd->used)(idev);
        fba = dasd_lookup (DASD_FBADEV, NULL, idev->devtype, 0);
        if (fba == NULL)
        {
            // "FBA lookup failed: blks %d"
            FWRMSG( stderr, HHC02431, "E", blks );
            close_image_file (icif);
            return -1;
        }
        n = blks;
        max = idev->fbanumblk;
        if (max < n && out == CFBA) n = max;
        n = (n + FBA_BLKS_PER_GRP - 1) / FBA_BLKS_PER_GRP;
        max = (max + FBA_BLKS_PER_GRP - 1) / FBA_BLKS_PER_GRP;
    }

    /* Create the output file */
    if (ckddasd)
        rc = create_ckd(ofile, idev->devtype, idev->ckdheads,
                        ckd->r1, cyls, "", comp, lfs, 1+r, nullfmt, 0,
                        1, 0);
    else
        rc = create_fba(ofile, idev->devtype, fba->size,
                        blks, "", comp, lfs, 1+r, 0);
    if (rc < 0)
    {
        // "Failed creating %s"
        FWRMSG( stderr, HHC02432, "E", ofile );
        close_image_file (icif);
        return -1;
    }

    /* Open the output file */
    if (ckddasd)
        ocif = open_ckd_image (ofile, NULL, O_RDWR|O_BINARY, IMAGE_OPEN_DASDCOPY);
    else
        ocif = open_fba_image (ofile, NULL, O_RDWR|O_BINARY, IMAGE_OPEN_DASDCOPY);
    if (ocif == NULL)
    {
        // "Failed opening %s"
        FWRMSG( stderr, HHC02403, "E", ofile );
        close_image_file (icif);
        return -1;
    }
    odev = &ocif->devblk;

    /* Notify GUI of total #of tracks or blocks being copied... */
    EXTGUIMSG( "TRKS=%d\n", n );

    /* Copy the files */

#if defined( EXTERNALGUI )
    if (!extgui)
#endif
        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->hnd->read)(idev, i, &unitstat);
            else
            {
                memset (idev->buf, 0, idev->ckdtrksz);
                rc = nulltrk(idev->buf, i, idev->ckdheads, nullfmt);
            }
        }
        else
        {
            if (i < max)
                rc = (idev->hnd->read)(idev, i, &unitstat);
            else
                memset (idev->buf, 0, FBA_BLKGRP_SIZE);
                rc = 0;
        }
        if (rc < 0)
        {
            // "Read error on file %s: %s %d stat=%2.2X, null %s substituted"
            FWRMSG( stderr, HHC02433, "E",
                     ifile, ckddasd ? "track" : "block", i, unitstat,
                     ckddasd ? "track" : "block" );
            if (ckddasd)
                nulltrk(idev->buf, i, idev->ckdheads, nullfmt);
            else
                memset (idev->buf, 0, FBA_BLKGRP_SIZE);
            if (!quiet)
            {
#if defined( EXTERNALGUI )
                if (!extgui)
#endif
                    printf ( "  %3d%% %7d of %d", 0, 0, n );
                status (i, n);
            }
        }

        /* Write the track or block just read */
        if (ckddasd)
        {
            rc = (odev->hnd->write)(odev, i, 0, idev->buf,
                      idev->ckdtrksz, &unitstat);
        }
        else
        {
            if (fba_bytes_remaining >= (size_t)idev->buflen)
            {
                rc = (odev->hnd->write)(odev,  i, 0, idev->buf,
                          idev->buflen, &unitstat);
                fba_bytes_remaining -= (size_t)idev->buflen;
            }
            else
            {
                ASSERT(fba_bytes_remaining > 0 && (i+1) >= n);
                rc = (odev->hnd->write)(odev,  i, 0, idev->buf,
                          (int)fba_bytes_remaining, &unitstat);
                fba_bytes_remaining = 0;
            }
        }
        if (rc < 0)
        {
            // "Write error on file %s: %s %d stat=%2.2X"
            FWRMSG( stderr, HHC02434, "E",
                     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);
    }

    close_image_file(icif); close_image_file(ocif);

#if defined( EXTERNALGUI )
    if (!extgui)
#endif
        if (!quiet)
            printf (_("\r"));

    // "DASD operation completed"
    WRMSG( HHC02423, "I" );
    return 0;
}