www.pudn.com > minix.instalation.cd-rom-2.0.rar > FDVOL.C, change:1996-09-22,size:8140b


/* fdvol.c - A stripped down version of the MINIX vol program.  It takes  
 * a file and breaks into into floppy-sized chunks, writing each one raw  
 * to a floppy.  
 *  
 *      Usage:          fdvol file drive KB [slow]  
 *  
 *	Examples:	fdvol 1440 a: foo.taz		# 1.4 MB floppy a:  
 *			fdvol 1200 b: foo.taz		# 1.2 MB floppy b:  
 *                      fdvol slow 360 a: foo.taz	# old machine  
 *                      fdvol 1440 a: foo bar		# concatenate  
 *  
 * The optional 'slow' parameter forces the program to write in units of 3  
 * sectors. Folk tradition has it that this works around some buggy BIOSes.  
 *  
 * This code borrows heavily from Mark Becker's RaWrite program.  
 */  
  
  
#include   
#include   
#include   
#include   
#include   
#include   
  
#define TEST 0  
  
#if !TEST  
#include   
#include   
#include   
#include   
#include   
#endif  
  
#define FALSE	0  
#define TRUE	(!FALSE)  
  
#define SECTORSIZE	512  
  
#define	RESET	0  
#define	LAST	1  
#define	READ	2  
#define	WRITE	3  
#define	VERIFY	4  
#define	FORMAT	5  
  
int done;  
char buffer[18*SECTORSIZE];	/* do I/O in units of up to 18 sectors */  
char testbuf[SECTORSIZE];	/* to do a test read of the first sector */  
  
  
int handler(void)  
{  
/* Catch CTRL-C and CTRL-Break. */  
  
  done = 1;  
  return(0);  
}  
  
void msg(char (*s))  
{  
/* Print an error message and quit. */  
  
  fprintf(stderr, "%s\n", s);  
  _exit(1);  
}  
  
void Error(int status, int cyl, int head, int sector)  
{  
/* Identify the error code with a real error message. */  
  
  
  fprintf(stderr, "\nError occured while writing cyl %d, head=%d, sector=%d\n", cyl,head,sector+1);  
  switch (status) {  
    case 0x00:	msg("Operation Successful");				break;  
    case 0x01:	msg("Bad command");					break;  
    case 0x02:	msg("Address mark not found");				break;  
    case 0x03:	msg("Attempt to write on write-protected disk");	break;  
    case 0x04:	msg("Sector not found");				break;  
    case 0x05:	msg("Reset failed (hard disk)");			break;  
    case 0x06:	msg("Disk changed since last operation");		break;  
    case 0x07:	msg("Drive parameter activity failed");			break;  
    case 0x08:	msg("DMA overrun");					break;  
    case 0x09:	msg("Attempt to DMA across 64K boundary");		break;  
    case 0x0A:	msg("Bad sector detected");				break;  
    case 0x0B:	msg("Bad track detected");				break;  
    case 0x0C:	msg("Unsupported track");				break;  
    case 0x10:	msg("Bad CRC/ECC on disk read");			break;  
    case 0x11:	msg("CRC/ECC corrected data error");			break;  
    case 0x20:	msg("Controller has failed");				break;  
    case 0x40:	msg("Seek operation failed");				break;  
    case 0x80:	msg("Attachment failed to respond");			break;  
    case 0xAA:	msg("Drive not ready (hard disk only");			break;  
    case 0xBB:	msg("Undefined error occurred (hard disk only)");	break;  
    case 0xCC:	msg("Write fault occurred");				break;  
    case 0xE0:	msg("Status error");					break;  
    case 0xFF:	msg("Sense operation failed");				break;  
  }  
  exit(1);  
}  
  
  
void main(int argc, char *argv[])  
{  
  int disknr = 1, fdin, count, drive, head, cyl, status, sector;  
  int max_cyl, chunk, nsectors, ct;  
  long offset, drive_size, r, cyl_size;  
  char *p, c;  
  int slow;  
  int kbsize;  
  char **files;  
  int nfiles, i;  
  
#if !TEST  
  /* Catch breaks. */  
  ctrlbrk(handler);  
#endif  
  
#if 0 /* Do we have to clear the screen? */  
  fprintf(stderr, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");  
#endif  
  
  if (argc > 1 && strcmp(argv[1], "slow") == 0) {	/* Lousy BIOS? */  
	slow = 1;  
	argc--;  
	argv++;  
  } else {  
	slow = 0;  
  }  
  
  /* Check the arguments for validity. */  
  if (argc < 4)  
        msg("Usage: fdvol [slow] #kilobytes drive-letter file1 [file2 ...]");  
  
  kbsize = atoi(argv[1]);  
  
  p = argv[2];  
  c = *p;  
  if (c == 'a' || c == 'A')  
	drive = 0;  
  else if (c == 'b' || c == 'B')  
        drive = 1;  
  else  
	msg("fdvol: Second parameter must be drive, either   a:   or   b:");  
  
  files = argv + 3;  
  nfiles = argc - 3;  
  
  switch(kbsize) {  
      case 360:  
        cyl_size = 9*2*SECTORSIZE;      /* bytes/cylinder */  
        max_cyl = 39;                   /* zero-based counting */  
	drive_size = cyl_size * (max_cyl+1);  
        chunk = (!slow ? 9 * SECTORSIZE : 3 * SECTORSIZE);  
        nsectors = chunk/SECTORSIZE;  
        break;  
  
      case 720:  
        cyl_size = 9*2*SECTORSIZE;      /* bytes/cylinder */  
        max_cyl = 79;                   /* zero-based counting */  
	drive_size = cyl_size * (max_cyl+1);  
        chunk = (!slow ? 9 * SECTORSIZE : 3 * SECTORSIZE);  
        nsectors = chunk/SECTORSIZE;  
        break;  
  
      case 1200:  
        cyl_size = 15*2*SECTORSIZE;          /* bytes/cylinder */  
        max_cyl = 79;                   /* zero-based counting */  
	drive_size = cyl_size * (max_cyl+1);  
        chunk = (!slow ? 15 * SECTORSIZE : 3 * SECTORSIZE);  
        nsectors = chunk/SECTORSIZE;  
        break;  
  
      case 1440:  
        cyl_size = 18*2*SECTORSIZE;     /* bytes/cylinder */  
        max_cyl = 79;                   /* zero-based counting */  
	drive_size = cyl_size * (max_cyl+1);  
        chunk = (!slow ? 18 * SECTORSIZE : 3 * SECTORSIZE);  
        nsectors = chunk/SECTORSIZE;  
        break;  
  
      default:  
	msg("fdvol: First parameter must be one of: 360, 720, 1200, or 1440");  
  }  
  
#if !TEST  
  biosdisk(RESET, drive, 0, 0, 0, 0, testbuf);  
#endif  
  
/*  
 * Start writing data to diskette until there is no more data to write.  
 * Optionally read and write in units of 3 sectors.  Folk tradition says  
 * that this makes fewer buggy BIOSes unhappy than doing a whole track at a  
 * time.  
 */  
  offset = 0;  
  i = 0;  
  fdin = -1;  
  
  while(1) {  
	if (done > 0) {  
		if (done == 1) msg("User abort");  
#if !TEST  
		biosdisk(READ, drive, 0, 0, 1, 1, testbuf); /* Retract head */  
#endif  
                fprintf(stderr, "Done.                                                      \n");  
		exit(done == 1 ? 1 : 0);  
	}  
  
	/* Until a chunk is read. */  
	count = 0;  
	while (count < chunk) {  
		if (fdin == -1) {			/* open next file */  
#if !TEST  
			_fmode = O_BINARY;  
#endif  
			fdin = open(files[i], O_RDONLY);  
			if (fdin < 0) {  
				perror(files[i]);  
				exit(1);  
			}  
		}  
							/* read from file */  
		ct = read(fdin, buffer + count, chunk - count);  
		if (ct < 0) {  
			perror(files[i]);  
			exit(1);  
		}  
		if (ct == 0) {				/* end of file */  
			close(fdin);  
			fdin = -1;  
  
			/* choose next file */  
			if (++i >= nfiles) break;	/* no more files */  
		}  
		count += ct;  
	}  
  
	if (count == 0) {				/* absolute EOF */  
		done = 2;  
		continue;  
	}  
  
	if (count < chunk) {				/* pad last track */  
		/* Pad out buffer with zeroes. */  
		p = &buffer[count];  
		while (p < &buffer[chunk]) *p++ = 0;  
		done = 2;  
	}  
  
	r = offset % drive_size;  
	if (r == 0) {  
		/* An integral number of diskettes have been filled. Prompt. */  
                fprintf(stderr, "Please insert formatted diskette #%d in drive %c, then hit Enter%c\n", disknr, c, 7);  
		disknr++;  
#if !TEST  
		while(bioskey(1) == 0) ;	/* wait for input */  
		if ((bioskey(0) & 0x7F)	== 3) exit(1);	/* CTRL-C */  
                biosdisk(READ,  drive, 0, 0, 1, 1, testbuf); /* get it going */  
#endif  
  
	}  
	/* Compute cyl, head, sector. */  
	cyl = r/cyl_size;  
	r -= cyl * cyl_size;  
	head = (r < cyl_size/2 ? 0 : 1);  
	r -= head * cyl_size/2;  
	sector = r/SECTORSIZE;  
	  
        fprintf(stderr, "Track: %2d  Head: %d  Sector: %2d    File offset: %ld\r",  
                cyl, head, sector+1,offset);  
#if !TEST  
        status = biosdisk(WRITE, drive, head, cyl, sector+1, nsectors, buffer);  
        if (status != 0) Error(status, cyl, head, sector);  
#else  
	write(1, buffer, chunk);  
#endif  
        offset += chunk;  
   }  
}