home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume38
/
awdc
/
part01
/
awdc.c
next >
Wrap
C/C++ Source or Header
|
1993-07-13
|
8KB
|
279 lines
/* awdc - sector level floppy copy
awdc is a floppy disk copy problem with a difference - it copies at a
sector level, ignoring such trivia as the number of sectors per track
and number of tracks. It stops when it reaches the end of either disc
or encounters a transfer error.
It was written to solve a specific problem - transcribing UNIX tar
archive discs from one type of floppy disc to another, on a DOS machine.
For safety, the program will only copy sectors between removable media,
so it should leave hard disks alone. I am not particularly proud of it,
but it solved my problem and may help others, so I am placing it in the
public domain. Use it entirely at your own risk.
Adrian Wontroba, Stade Computers Limited. phone: (+44) 21 373 9546
uucp: ...!uknet!stade!aw1 other: aw1%stade.co.uk@uknet.ac.uk
snail: 14 Fourlands Avenue, Sutton Coldfield, West Midlands, B72 1YY, UK
*/
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#include <ctype.h>
#include <string.h>
#undef NO_WRITE /* if defined, no writes! */
#define BUFFERSIZE 32768 /* size of disk io buffer, max 64k */
char *progname; /* program name */
/*
* setmessage - output warning about disk parameter blocks
*
*/
void
setmessage(void)
{
fprintf(stderr,
"The action of this program is strongly influenced by\n"
"the content of the Disk Parameter Block for each drive.\n\n");
fprintf(stderr,
"Before using it (especially with non DOS media), the DPBs\n"
"should be initialised by issuing 'DIR x:' commands on the\n"
"input and output drives with equivalent DOS media.\n\n");
fprintf(stderr,
"The output disk must be pre-formatted.\n\n");
fprintf(stderr,
"As a safety measure, the program will only copy between\n"
"removeable media.\n\n");
} /* setmessage */
/*
* usage - output usage message
*
*/
void
usage(void)
{
fprintf(stderr, "usage: %s <input drive letter> "
"<output drive letter>\n"
"eg 'awdc a b' to copy from a to b\n\n",
progname);
setmessage();
} /* usage */
/*
* myerror - print error message and errno and _doserrno to stderr
*
*/
void
myerror(char *s)
{
int e = errno;
int d = _doserrno;
fprintf(stderr, "\n%s: %s: %s (%d/%x), _doserrno = %d\n",
progname, s,
((e > 0) && (e <= sys_nerr)) ? sys_errlist[e] : "Unknown error",
e, e, d);
} /* myerror */
/*
* get_drive - turn drive letter into drive number for absread/abswrite
* 0=A, 1=B etc.
*
* Note - most DOS functions use 0=default, 1=A. etc. Beware.
*
* error message and exit(1) on error
*
*/
int
get_drive(char *s)
{
int c;
int d;
union REGS regs;
c = toupper(s[0]);
if ((c < 'A') || (c > 'Z')) {
fprintf(stderr, "Drive '%c' not supported\n", c);
exit(1);
} else {
d = c - 'A';
regs.h.ah = 0x44; /* ioctl */
regs.h.al = 0x8; /* check if block device is removeable */
regs.h.bl = d + 1; /* drive code - 0 def, 1=A, etc */
intdos(®s, ®s);
if (regs.x.cflag) {
fprintf(stderr, "Unable to determine "
"exchangeability of %c, "
"ioctl error %d\n",
c, regs.x.ax);
exit(1);
}
if (regs.x.ax) {
fprintf(stderr, "%c is not an exchangeable drive\n",
c);
exit(1);
}
/* phew, its exchangeable */
}
return d;
} /* get_drive */
/*
* copy - copy one logical drive to another, until failure
*
*/
void
copy(int in, int out)
{
union REGS regs;
int in_sectors; /* sectors on input drive */
int in_sector_size; /* sector size */
int out_sectors;/* sectors on output drive */
int out_sector_size; /* sector size */
int sectors; /* sectors to copy */
int num; /* max sectors per transfer */
int n; /* current sectors per transfer */
int s_read; /* sectors read */
int s_written; /* sectors written */
int s; /* current sector */
char *buff; /* buffer */
/* device parameter block */
struct DPB {
unsigned char special_functions;
unsigned char device_type;
unsigned short int device_attributes;
unsigned short int max_cylinders;
unsigned char media_type;
unsigned short int bytes_per_sector;
unsigned char sectors_per_au;
unsigned short int sectors_reserved;
unsigned char fats;
unsigned short int maxroot;
unsigned short int sectors;
unsigned char media;
unsigned short int sectors_per_fat;
unsigned short int sectors_per_track;
unsigned short int heads;
unsigned long int hidden_sectors;
unsigned char reserved[11];
};
struct DPB dpb;
/* get number of sectors on input drive */
memset(&dpb, 0, sizeof dpb);
regs.h.ah = 0x44; /* ioctl */
regs.h.al = 0xd; /* generic i/o control */
regs.h.bl = in + 1; /* drive number */
regs.h.ch = 0x8; /* disk drive */
regs.h.cl = 0x60; /* get drive parameters */
regs.x.dx = (unsigned int) &dpb; /* ugh! */
dpb.special_functions = 128;/* return build device driver bpb */
intdos(®s, ®s);
if (regs.x.cflag) {
fprintf(stderr, "Unable to get drive parameters for %c"
", ioctl error %d\n",
in + 'A', regs.x.ax);
exit(1);
}
in_sectors = dpb.sectors;
in_sector_size = dpb.bytes_per_sector;
printf("Input drive %c has %d sectors of %d bytes\n",
in + 'A', in_sectors, in_sector_size);
/* get number of sectors on output drive */
memset(&dpb, 0, sizeof dpb);
regs.h.ah = 0x44; /* ioctl */
regs.h.al = 0xd; /* generic i/o control */
regs.h.bl = out + 1; /* drive number */
regs.h.ch = 0x8; /* disk drive */
regs.h.cl = 0x60; /* get drive parameters */
regs.x.dx = (unsigned int) &dpb; /* ugh! */
dpb.special_functions = 128;/* return build device driver bpb */
intdos(®s, ®s);
if (regs.x.cflag) {
fprintf(stderr, "Unable to get drive parameters for %c"
", ioctl error %d\n",
out + 'A', regs.x.ax);
exit(1);
}
out_sectors = dpb.sectors;
out_sector_size = dpb.bytes_per_sector;
printf("Output drive %c has %d sectors of %d bytes\n",
out + 'A', out_sectors, out_sector_size);
if (in_sector_size != out_sector_size) {
fprintf(stderr, "Drives have different sector sizes\n");
exit(1);
}
/* decide how many sectors to copy */
if (in_sectors > out_sectors) {
fprintf(stderr, "Input drive larger than output\n"
"Data may be lost\n");
sectors = out_sectors;
} else {
sectors = in_sectors;
}
printf("Copying %d sectors\n", sectors);
/* get buffer */
if ((buff = malloc(BUFFERSIZE)) == NULL) {
fprintf(stderr, "malloc failed\n");
exit(1);
}
/* decide how many sectors to handle at a time */
num = BUFFERSIZE / in_sector_size;
s_read = 0;
s_written = 0;
s = 0;
while (sectors > 0) {
n = min(sectors, num);
printf("Sectors %5d to %5d\r", s, s + n - 1);
if (absread(in, n, s, buff)) {
/* read error */
myerror("absread");
break;
} else {
s_read += n;
#ifdef NO_WRITE
/* do nothing to output drive ! */
#else
if (abswrite(out, n, s, buff)) {
/* write error */
myerror("abswrite");
break;
} else {
s_written += num;
}
#endif /* NO_WRITE */
}
sectors -= n;
s += n;
}
printf("Sectors read from %c: %5d\n"
"Sectors written to %c: %5d\n",
in + 'A', s_read, out + 'A', s_written);
} /* copy */
/*
* main
*/
int
main(int argc, char *argv[])
{
int in_drive; /* input drive number */
int out_drive; /* output drive number */
progname = argv[0];
if (argc != 3) {
usage();
exit(1);
}
in_drive = get_drive(argv[1]);
out_drive = get_drive(argv[2]);
setmessage();
copy(in_drive, out_drive);
printf("OK\n");
exit(0);
} /* main */