Files
org-hyperion-cules/dasdcopy.c
Jan Jaeger 69ca87cc62 Rollback a number of changes :-(
git-svn-id: file:///home/jj/hercules.svn/trunk@1403 956126f8-22a0-4046-8f4a-272fa8102e63
2003-06-02 13:16:07 +00:00

590 lines
20 KiB
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"
#include "devtype.h"
#define FBA_BLKGRP_SIZE (120 * 512) /* Size of block group */
#define FBA_BLKS_PER_GRP 120 /* Blocks per group */
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 0x08
#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 */
BYTE msgbuf[512]; /* Message 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 (msgbuf, 512, _("Hercules %s copy program "), pgm);
display_version (stderr, msgbuf);
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];
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->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
{
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);
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->hnd->read)(idev, i, &unitstat);
else rc = nulltrk(idev->buf, i, idev->ckdheads);
}
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\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->hnd->write)(odev, i, 0, idev->buf,
idev->ckdtrksz, &unitstat);
}
else
rc = (odev->hnd->write)(odev, i, 0, idev->buf,
idev->buflen, &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 */