/*
 * Copyright (c) 1983 Regents of the University of California.
 * All rights reserved. The Berkeley Software License Agreement
 * specifies the terms and conditions for redistribution.
 */
#ifndef lint
static char rcsid[] = "$Header:flcopy_ca.c 12.0$";
#endif

#include <stdio.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <machine/dkio.h>
#include <machineio/fdio.h>

extern int errno;

main(argc, argv)
	register char **argv;
{
	register long count;
	register int n, file;
	register char *cp;
	int	floppydes;
	char	*flopname = "/dev/rfd0";
	long	dsize;
	long	track_size;
	int	hflag = 0;
	int	rflag = 0;
	int	tflag = 0;
	int	mflag = 0;
	int	vflag = 0;
	char	*buff;
	char	bptr[80];	/* for gets call */
	int tracks;


	/*
	 * parce the arguement list
	 */
	while ((cp = *++argv), --argc > 0) {
		while (*cp) {
			switch(*cp++) {

			case '-':
				continue;

			/*
			 * -h means only do the write to the floppy
			 */
			case 'h':
				if (rflag || mflag) {
				  fprintf(stderr,
				    "Can't use -h with the -r or -m flags\n");
				  exit(1);
				}
				hflag++;
				printf("Halftime!\n");
				if ((file = open("floppy", 0)) < 0) {
					printf("can't open \"floppy\"\n");
					exit(1);
				}
				continue;

			/*
			 * -f lets you specify another floppy device
			 */
			case 'f':
				if (argc < 1) {
					printf(
					    "flcopy: -f: missing file name\n");
					exit(1);
				}
				flopname = *++argv;
				argc--;
				break;

			/*
			 * -t lets you copy less than the whole disk
			 */
			case 't':
				tflag++;
				if (*cp >= '0' && *cp <= '9')
					tracks = atoi(cp);
				else if (argc > 1) {
					tracks = atoi(*++argv);
					argc--;
				} else
					tracks = -1;
				continue;

			/*
			 * -r only reads the floppy
			 */
			case 'r':
				if (hflag || mflag) {
				  fprintf(stderr,
				    "Can't use -r with the -h or -m flags\n");
				  exit(1);
				}
				rflag++;
				continue;

			/*
			 * -m allows you to use virtual memory to do the
			 * copy. (rather than a temp file.
			 */
			case 'm':
				if (hflag || rflag) {
				  fprintf(stderr,
				    "Can't use -m with the -h or -r flags\n");
				  exit(1);
				}
				mflag++;
				continue;
			/*
			 * -v verifies the disk type as you copy
			 */
			case 'v':
				vflag++;
				continue;
			}
			break;
		}
	}


	/*
	 * this piece does the read.
	 */
	if (!hflag) {

		/*
		 * open the floppy device and get the density
		 */
		if ((floppydes = open(flopname, 0)) < 0) {
			printf("Floppy open failed\n");
			exit(1);
		}
		getdensity(floppydes,tflag,vflag,tracks,&dsize,&track_size);


		if (mflag) {
			/*
			 * read the floppy into a single virtual memory buffer
			 */
			buff = (char *)malloc(dsize);
			if (buff == 0) {
				fprintf(stderr,"couldn't malloc %d bytes",
									dsize);
				perror(" ");
				exit (1);
			}
			read(floppydes,buff,dsize);
		} else {
			/*
			 * read the floppy to a disk file
			 */
			file = open("floppy", O_RDWR|O_CREAT|O_TRUNC, 0666);
			if (file < 0) {
				fprintf(stderr,"can't open \"floppy\"\n");
				exit(1);
			}
			buff = (char *)malloc(track_size);
			if (buff == 0) {
				fprintf(stderr,"couldn't malloc %d bytes",
								  track_size);
				perror(" ");
				exit (1);
			}
			for (count = dsize; count > 0 ; count -= track_size) {
				n = count > track_size ? track_size  : count;
				read(floppydes,buff,n);
				write(file, buff, n);
			}
			free(buff);
			buff = 0;
			close(file);
		}
		close(floppydes);
		close(file);
		/*
		 * if this is read-only, we are done...
		 */
		if (rflag)
			exit(0);
		/*
		 * otherwise we change the floppies
		 */
		printf("Change Floppy, Hit return when done.\n");
		gets(bptr);
	}
	/*
	 * now we write the floppy. Same steps as read, first we open
	 * the device and get the density
	 */
	if ((floppydes = open(flopname, 2)) < 0) {
		printf("Floppy open failed\n");
		exit(1);
	}
	getdensity(floppydes,tflag,vflag,tracks,&dsize,&track_size);
	
	if (mflag) {
		/* we write out the virtual memory buffer */
		write(floppydes,buff,dsize);
	} else {
		/* we write out the temp file */
		file = open("floppy", O_RDONLY,0);
		if (file < 0) {
			fprintf(stderr,"can't open \"floppy\"\n");
			exit(1);
		}
		buff = (char *)malloc(track_size);
		if (buff == 0) {
			fprintf(stderr,"couldn't malloc %d bytes",track_size);
			perror(" ");
			exit (1);
		}
		for (count = dsize; count > 0 ; count -= track_size) {
			n = count > track_size ? track_size  : count;
			read(file, buff, n);
			write(floppydes,buff,n);
		}
		free(buff);
		close(file);
	}
	exit(0);
}

/*
 * this routine uses DKIO ioctls to get the physical
 * parameters of the disk
 */
getdensity(floppydes,tflag,vflag,tracks,dsize,track_size)
	int	floppydes,tflag,vflag,tracks;
	long	*dsize,*track_size;
{
	struct	dkpart	dk;

	if (ioctl(floppydes,DKIOCGPART,&dk) < 0) {
		printf("Not a floppy\n");
		exit(1);
	}

	if (vflag)
		printf("disk type is %s\n",dk.dk_name);
	*dsize = dk.dk_size*dk.dk_blocksize;
	*track_size = dk.dk_nsector*dk.dk_ntrack*dk.dk_blocksize;

	if (tflag) {
		if (tracks == -1) {
			tracks = dk.dk_ncyl;
		}
		if (tracks <= 0 || tracks > dk.dk_ncyl) {
			printf("Bad number of tracks\n");
			exit(2);
		}
		*dsize = tracks * (*track_size);
	}
}
