home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
utils
/
dskutl
/
syscop.cq
/
SYSCOP.C
Wrap
Text File
|
1985-06-13
|
10KB
|
349 lines
/*
* SYSCOPY - a portable replacement for the CP/M SYSGEN utility
* This program uses the disk parameter tables in CP/M 2.x if
* possible, but can also be configured to prompt for CP/M 1.x
* The input and output files are biased to 0900h so that they
* can be loaded and debugged with DDT/SID ala the documentation
*/
#include "bdscio.h"
#define INPUT 0
#define OUTPUT 1
#define UPDATE 2
#define SELDSK 9
#define SETTRK 10
#define SETSEC 11
#define SETDMA 12
#define READS 13
#define WRITES 14
#define VERSION 12
#define CURRENT 25
#define READR 33
#define WRITER 34
#define COMFSZ 35
#define dpb struct DPB
struct DPB {
int dpb_spt;
char dpb_bsh;
char dpb_blm;
char dpb_exm;
unsigned dpb_dsm;
unsigned dpb_drm;
char dpb_al0;
char dpb_al1;
int dpb_cks;
int dpb_off;
};
#define dph struct DPH
struct DPH {
unsigned dph_xlt;
char dph_res11[6];
char *dph_dirbuf;
dpb *dph_dpb;
char *dph_csv;
char *dph_alv;
};
#define DRIVES "ABCDEFGHIJKLMNOP"
#define MAXINT 32767
#define MAXSYS 64
main(argc,argv)
int argc;
char *argv[];
{
char source[32],destination[32],number[32],reply[32]; /* plenty big */
int fromdisk,todisk; /* signal file or direct I/O */
int version,inres,outres,inspt,outspt,indrive,outdrive;
int i,count,infd,outfd,insec,outsec,intrk,outtrk,insize,outsize;
dph *indph,*outdph;
dpb *indpb,*outdpb;
char current,buffer[SECSIZ],system[MAXSYS][SECSIZ];
/*
* Output the signon message, init, and check for a help request
*/
current = bdos(CURRENT,0); /* get current disk number */
version = bdos(VERSION,0); /* get the CP/M version number */
if ((argc > 1) && (argv[1][0] == '?'))
{
printf("Syscopy utility version 1.0 - by Stephen M. Kenton\n\n");
printf("Syntax: syscpy [input [output [count]]]\n");
printf("Input and output may be either a disk or a filename\n");
printf("If specified, a colon ':' must be included with a disk\n");
printf("name, or it will be considered to be a short file name\n");
printf("Count is the number of sectors to be read and written\n");
printf("It will normally be 1 for the boot block or '*' for all\n");
printf("Count may be in decimal, or preceeded by a $ for hex\n");
printf("Any argument(s) that are omitted will be prompted for\n");
exit(0);
}
printf("Portable system copy utility. For help, enter 'syscopy ?'\n\n");
/*
* Get the input arguments from the command line or the user
*/
if (argc > 1)
strcpy(source,argv[1]);
else
{
printf("Enter source, or return for current drive: ");
gets(source);
}
if (strlen(source) == 0)
{
source[0] = DRIVES[current]; /* fabricate a string */
strcpy(source+1,":");
}
if ((strlen(source) == 2) && (source[1] == ':'))
{
fromdisk = TRUE;
indrive = index(DRIVES,toupper(source[0]));
}
else
fromdisk = FALSE;
if (argc > 2)
strcpy(destination,argv[2]);
else
{
printf("Enter destination, or return for current drive: ");
gets(destination);
}
if (strlen(destination) == 0)
{
destination[0] = DRIVES[current]; /* fabricate a string */
strcpy(source+1,":");
}
if ((strlen(destination) == 2) && (destination[1] == ':'))
{
todisk = TRUE;
outdrive = index(DRIVES,toupper(destination[0]));
}
else
todisk = FALSE;
if (argc > 3)
strcpy(number,argv[3]);
else
{
printf("Enter number of sectors, or return for all: ");
gets(number);
}
if (strlen(number) == 0)
{
strcpy(number,"*"); /* asterisk means copy all sectors */
}
if (number[0] == '*') /* wild card */
count = MAXINT; /* largest possible value */
else if (number[0] == '$') /* hexidecimal */
sscanf(number+1,"%x",&count);
else /* decimal */
sscanf(number,"%d",&count);
/*
* Now determine the characteristics of the drives or files
*/
if ((version == 0) || (version > 255)) /* CP/M 1.x or MP/M */
{
printf("MP/M does not allow access to some disk I/O calls, and\n");
printf("CP/M 1.x does not supply some needed information\n");
printf("for this utility to run, use CP/M 2.x to run it\n");
exit(1);
}
else
{
if (fromdisk) /* if reading from the system tracks */
{
indph = dphaddr(indrive); /* DPH address */
if (indph == 0)
{
printf("Invalid source drive %s selected\n",source);
exit(1);
}
indpb = indph->dph_dpb; /* DPB address */
inres = indpb->dpb_off; /* number of reserved tracks */
inspt = indpb->dpb_spt; /* number of sectors per track */
insize = inres * inspt; /* number of reserved sectors */
if (inres > 3)
{
printf("There are more than 3 reserved tracks on this drive\n");
printf("This normally indicates that it is a logical disk\n");
printf("rather than a bootable physical disk volume\n");
printf("If this is the case, reading the reserved tracks\n");
printf("will result in garbage being in the buffer\n");
printf("Do you with to continue? (Y/N): ");
scanf("%s",reply); /* get the response */
if (toupper(reply[0]) != 'Y')
exit(1);
}
}
else /* if reading from a file */
{
if ((infd = open(source,INPUT)) == ERROR)
{
printf("Can not open source file %s\n",source);
exit(1);
}
insize = rcfsiz(infd) - 16; /* file size - bias */
for (i=0; i<16; i++)
read(infd,buffer,1); /* dump the bias sectors */
}
if (todisk) /* if writing to the system tracks */
{
outdph = dphaddr(outdrive); /* DPH address */
if (outdph == 0)
{
printf("Invalid destination drive %s selected\n",destination);
exit(1);
}
outdpb = outdph->dph_dpb; /* DPB address */
outres = outdpb->dpb_off;
outspt = outdpb->dpb_spt;
outsize = outres * outspt; /* number of reserved sectors */
if (inres > 3)
{
printf("There are more than 3 reserved tracks on this drive\n");
printf("This normally indicates that it is a logical disk\n");
printf("rather than a bootable physical disk volume\n");
printf("If this is the case, writing on the reserved\n");
printf("tracks will destroy another logical disk\n");
printf("Do you with to continue? (Y/N): ");
scanf("%s",reply); /* get the response */
if (toupper(reply[0]) != 'Y')
exit(1);
}
}
else /* if writing to a file */
{
if ((outfd = creat(destination)) == ERROR)
{
printf("Can not open destination file %s\n",destination);
exit(1);
}
outsize = MAXINT; /* largest possible value */
setmem(buffer,SECSIZ,'\0'); /* clear the buffer */
for (i=0; i<16; i++)
write(outfd,buffer,1); /* write the bias sectors */
}
}
insize = (count < insize) ? count : insize; /* choose the smaller */
if (insize > outsize)
{
printf("Source is longer than destination, truncate? (Y/N): ");
scanf("%s",reply); /* check answer */
if (toupper(reply[0]) == 'Y')
insize = outsize;
else
exit(1);
}
if (insize > MAXSYS)
{
printf("System size exceeds memory buffer limit\n");
exit(1);
}
/*
* Copy the source to the destination
*/
outsize = insize; /* write only as much as was specified */
if (fromdisk) /* read from the system tracks */
{
bios(SELDSK,indrive); /* select the input drive */
for (intrk=0; intrk<inres; intrk++)
{
bios(SETTRK,intrk); /* select the track */
for (insec=1; insec<=inspt; insec++)
{
count = intrk*inspt+insec-1; /* number of sectors */
if (count > insize)
goto stopin; /* we just hit the limit */
bios(SETSEC,insec); /* set the sector number */
bios(SETDMA,system[count]); /* set DMA address */
bios(READS,0); /* read the sector in */
}
}
stopin:
bios(SELDSK,current); /* select the origianal drive */
}
else /* read from a file */
{
if (read(infd,system,insize) < insize) /* read what you need */
{
printf("Error reading %s\n",source);
exit(1);
}
}
if (todisk) /* write to the system tracks */
{
bios(SELDSK,outdrive); /* select the output drive */
for (outtrk=0; outtrk<outres; outtrk++)
{
bios(SETTRK,outtrk); /* select the track */
for (outsec=1; outsec<=outspt; outsec++)
{
count = outtrk*outspt+outsec-1; /* number of sectors */
if (count > outsize)
goto stopout; /* we just hit the limit */
bios(SETSEC,outsec); /* set the sector */
bios(SETDMA,system[count]); /* set DMA address */
bios(WRITES,0); /* write the sector */
}
}
stopout:
bios(SELDSK,current); /* select the original drive */
}
else /* write to a file */
{
if (write(outfd,system,outsize) < outsize) /* write what you have */
{
printf("Error writing %s\n",destination);
exit(1);
}
}
/*
* Clean up and exit
*/
if (!fromdisk) /* if reading from a file */
close(infd);
if (!todisk) /* if writing to a file */
close(outfd);
printf("%d sectors were copied from %s to %s\n",insize,source,destination);
}
/*
* Index - return the index of the first occurance of a char in a
* string, or ERROR if it is not found
*/
index(str,c)
char *str,c;
{
int i;
for (i=0; str[i]; i++)
{
if (str[i] == c)
return(i); /* found it */
}
return(ERROR); /* did not find it */
}
/*
* Dphaddr - return the address of a disk parameter header
* This is performed by bios call 9, but the Bios() function
* can not be used, because it returns a <A> not <HL>
*/
dphaddr(drive)
int drive;
{
unsigned *warmstart,seldsk,result;
char current;
current = bdos(CURRENT,0); /* save the current drive */
warmstart = 1;
seldsk = *warmstart + 24; /* address of SELDSK routine */
result = call(seldsk,0,0,drive,0); /* call the bios seldsk routine */
bios(SELDSK,current); /* restore the original disk */
return(result);
}