
#include <exec/memory.h>
#include <devices/trackdisk.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <libraries/filehandler.h>
#include <workbench/workbench.h>
#include <workbench/startup.h>
#include <workbench/icon.h>
#include "defs.h"

#define SOURCE		0
#define DESTINATION	1
#define FORMATTED	(UBYTE) 0xFF

/*	System Calls : exec.library		*/

extern void				*AllocMem();
extern void				CloseLibrary();
extern struct IOExtTD	*CreateExtIO();
extern struct MsgPort	*CreatePort();
extern void				DeleteExtIO();
extern void				DeletePort();
extern void				DoIO();	
extern void				FreeMem();
extern long				OpenDevice();
extern struct Library	*OpenLibrary();
extern void				SendIO();
extern void				WaitIO();

/*	System Calls : icon.library		*/

extern struct DiskObject	GetDiskObjekt();
extern char*				FindToolType();
extern void					FreeDiskObject();

/*	System Calls : dos.library		*/

extern struct DosLibrary	*DOSBase;
extern struct MsgPort		*DeviceProc();

/*	Workbenchmessage */

extern struct WBStartup		*WBenchMsg;

ULONG strlen();
char *rindex();

/* externals in logic.c */

extern void init();
extern void checksize();
extern void	travel();
extern void	moveblock();
extern void	sortfiles();
extern void	makefiles();
extern void	makedirs();
extern void	makeroot();
extern void	writeheaders();
extern short scmp();

/*	Global Variables	*/

struct Library		*IconBase;
struct IOExtTD		*diskreq0,*diskreq1,*diskreq2;
struct MsgPort		*diskport0,*diskport1,*diskport2;

unsigned long	diskchangecount0,diskchangecount1;
unsigned short	wbflag, formatflag, fastloadflag;
unsigned long	**readmap;	  /* Array of Pointers to Data-Sectors in Memory */
UBYTE			*trackmap;    /* Array of Flags for formatted Tracks */
unsigned long	**buffermap;  /* Array of Pointers to Header-Sectors in Memory */
unsigned long	*sectormap;   /* Conversion-Table for Sectornumbers */
unsigned long	*stack;       /* Stack for Source-Directories and FileHeaders */
unsigned long	*trackbuffer; /* Pointer to Trackdata (for Format) */
unsigned long	*writebuffer; /* Pointer to Blockdata (for WriteSector) */
unsigned long	*readbuffer; /* Pointer to Blockdata (for ReadSector) */
unsigned long	*oldbuffer;
unsigned long	SourceBlocks; /* # of Used Blocks on Sourcedevicce */
unsigned long	curtrack;	  /* Current Track */
unsigned long	last_checked;
struct DevPar	Source, Dest;

/*	Internal Funktions	*/

unsigned long	*allocbuffer();
unsigned long 	*GetSector();
short			is_special();
char			*getenv();

main(argc,argv)
register int	argc;
register char	*argv[];
{
	register short int 	drivetype,i;
	register char		*str;
	register struct DiskObject	*dop;

	/* Defaults */

	wbflag = 0;
	formatflag = 1;
	fastloadflag = 1;
	strcpy(Source.Device,"DF0:");
	strcpy(Dest.Device,"DF1:");

	/* Environment Variables */

	str = getenv("NOFORMAT");
	if (strlen(str) != NULL) {
		if (scmp(str,"ON",2)) {
			formatflag = 0;
		} else if (scmp(str,"OFF",3)) {
			formatflag = 1;
		}
	}
	str = getenv("FASTDIR");
	if (strlen(str) != NULL) {
		if (scmp(str,"ON",2)) {
			fastloadflag = 0;
		} else if (scmp(str,"OFF",3)) {
			fastloadflag = 1;
		}
	}
	str = getenv("FROM");
	if (strlen(str) != NULL) {
		if (rindex(str,':') == (char *) (str + strlen(str) - 1L)) {
			strcpy(Source.Device,str);
		}
	}
	str = getenv("TO");
	if (strlen(str) != NULL) {
		if (rindex(str,':') == (char *) (str + strlen(str) - 1L)) {
			strcpy(Dest.Device,str);
		}
	}

	drivetype = SOURCE;
	if (argc) {

		/* CLI - Startup */

		for (i=1; i < argc; i++) {
			str = argv[i];
			if (scmp(str,"NOFORMAT",8)) {
				formatflag = 0;
			} else if (scmp(str,"FASTDIR",7)) {
				fastloadflag = 0;
			} else if (scmp(str,"FROM",4)) {
				drivetype = SOURCE;
			} else if (scmp(str,"TO",2)) {
				drivetype = DESTINATION;
			} else if (rindex(str,':') == (char *) (str + strlen(str) -1L)) {
				if (drivetype == SOURCE) {
					strcpy(Source.Device,str);
					drivetype = DESTINATION;
				} else {
					strcpy(Dest.Device,str);
				}
			} else {
				printf("Usage   : %s [FROM] device [TO] device [NOFORMAT] [FASTDIR]\n",argv[0]);
				printf("Defaults: FROM df0: TO df1:\n");
				exit(20);
			}
		}
	} else {

		/* Workbench-Startup */

		wbflag = 1;

		if (!(IconBase = OpenLibrary(ICONNAME,0L))) {
			printf("Where is the Icon-Library ?\n");
			error();
		}
		if (!(dop = GetDiskObject(WBenchMsg -> sm_ArgList -> wa_Name))) {
			printf("Couldn't find Disk-Object!\n");
			error();
		}
		if (str = FindToolType(dop -> do_ToolTypes, "NOFORMAT")) {
			if (scmp(str,"ON",2)) {
				formatflag = 0;
			}
		}
		if (str = FindToolType(dop -> do_ToolTypes, "FASTDIR")) {
			if (scmp(str,"ON",2)) {
				fastloadflag = 0;
			}
		}
		if (str = FindToolType(dop -> do_ToolTypes, "FROM")) {
			if (rindex(str,':') == (char *) (str + strlen(str) - 1L)) {
				strcpy(Source.Device,str);
			}
		}
		if (str = FindToolType(dop -> do_ToolTypes, "TO")) {
			if (rindex(str,':') == (char *) (str + strlen(str) - 1L)) {
				strcpy(Dest.Device,str);
			}
		}
		FreeDiskObject(dop);		
	}

	if (scmp(Source.Device, Dest.Device, (USHORT) strlen(Source.Device))) {
		printf("Can't copy from %s to %s !\n", Source.Device, Dest.Device);
		error();
	}
	
	openall();

	printf("\n [3;4;33m FastDisk V1.8 [0;1;31m -  Written 1989 by Torsten Stolpmann [0m\n\n");
	printf(" Please insert SOURCE      Disk in Device %s\n",Source.Device);
	printf(" Please insert DESTINATION Disk in Device %s\n",Dest.Device);
	printf(" Press RETURN to continue\n");
	getchar();

	checkdisks();
	init();
	checksize();
	travel(Source.RootBlock);
	moveblock();
	sortfiles();
	makefiles();
	makedirs();
	makeroot();
	writeheaders();
	writeblank();
	update();
	closeall();
}

writeblank()
{
	register unsigned long track;

	/* Format all unused Tracks */

	if (trackmap[curtrack] != FORMATTED) {
		formattrack(curtrack);
	}

	if (formatflag) {
		for (track=0L; track < Dest.NumTracks; track++) {
			if (trackmap[track] != FORMATTED) {
				formattrack(track);
			}
		}
	}
}

moveboot()
{
	register unsigned long *workbuffer;
	register unsigned long count;

	/* Check Bootsector */

	workbuffer = allocbuffer();
	ReadSector (0L,workbuffer);
	if (workbuffer[FILESYSTEM] == FFS) {
		releasebuffer(workbuffer);
		printf("Disk in Device %s is a FastFileSystem-Disk.\nThis is not supported in this Release.\n",Source.Device);
		error();
	} else if (workbuffer[FILESYSTEM] != STANDARD) {
		releasebuffer(workbuffer);
		printf("Disk in Device %s is not a Dos-Disk!\n",Source.Device);
		error();
	}

	/* Move Reserved Blocks */

	count = 0L;
	while (count < Source.ReservedBlks) {
		ReadSector(count,workbuffer);
		WriteSector(count,workbuffer);
		readmap[count++] = BLOCKED;
		WaitIO(diskreq1);
	}
	releasebuffer(workbuffer);
}

update()
{
	WaitIO(diskreq1);
	diskreq1 -> iotd_Req.io_Command = ETD_UPDATE;
	diskreq1 -> iotd_Count		= diskchangecount1;
	DoIO (diskreq1);
}

DoCheckSum(buffer,pos)
register unsigned long	*buffer;
register unsigned short	pos;
{
	register unsigned long	count;
	register unsigned long	checksum;

	/* Build CheckSum for normal and Bit-Map Blocks */

	buffer[pos] = checksum = NULL;
	for (count=0; count < Dest.Size; ++count) {
		checksum += (unsigned long) buffer[count];
	}
	buffer[pos] -= (unsigned long) checksum;
}

ReadSector (sector,buffer)
unsigned long sector,*buffer;
{
	/* Reads a Sector from Source-Device */

	if ((Source.MemBufType & MEMF_CHIP) && !(TypeOfMem(buffer) & MEMF_CHIP)) {
		diskreq0 -> iotd_Req.io_Data	= (APTR) readbuffer;
	} else {
		diskreq0 -> iotd_Req.io_Data	= (APTR) buffer;
	}
	diskreq0 -> iotd_Req.io_Length 	= Source.BlockSize;      
	diskreq0 -> iotd_Req.io_Command = ETD_READ;
	diskreq0 -> iotd_Count 		= diskchangecount0;
	diskreq0 -> iotd_Req.io_Offset 	= Source.Offset + sector * Source.BlockSize;
	DoIO (diskreq0);
	if (diskreq0 -> iotd_Req.io_Error) {
		printf("Error %d while reading sector %4ld from device %s !\n",
			(USHORT) diskreq0 -> iotd_Req.io_Error,
			sector, Source.Device);
		error();
	}
	if ((Source.MemBufType & MEMF_CHIP) && !(TypeOfMem(buffer) & MEMF_CHIP)) {
		CopyMemQuick(readbuffer, buffer, Dest.BlockSize);
	}
}

unsigned long *GetSector(sector) /* returns Pointer to allocated SectorData */
register unsigned long	sector;  /* # of Sector to be Read */
{
	register unsigned long	*workbuffer,*temp;
	register unsigned long	track,sec;

	/* Calls ReadSector or returns previously allocated Sector */

	Chk_Abort();

	if (sector >= Source.NumBlocks) {
		printf("Illegal sector detected, Disk in Device %s is corrupt !\n",
			Source.Device);
		printf("Use diskdoctor to correct this disk.\n");
		error();
	}
	if (readmap[sector]) {
		if (readmap[sector] == BLOCKED) {
			printf("Double Reference to sector %ld, disk in Device %s is corrupt !\n",
				sector,Source.Device);
			printf("Use diskdoctor to correct this disk.\n");
			error();
		} else {
			temp = readmap[sector];
			readmap[sector] = BLOCKED;
			return (temp);
		}
	} else {
		workbuffer = allocbuffer();
		ReadSector (sector,workbuffer);
		readmap[sector] = BLOCKED;
		track = sector / Source.SecsPerCyl;
		for (sec=track*Source.SecsPerCyl; sec < (track+1)*Source.SecsPerCyl; sec++) {
			if (readmap[sec] == EMPTY) {
				if (readmap[sec] = allocbuffer()) {
					ReadSector(sec,readmap[sec]);
				} else {
					break;
				}
			}
		}
		return (workbuffer);
	}
}

formattrack(track)
unsigned long track;
{
	register unsigned long	count;

	/* Formatiert einen Track auf der Zieldiskette */

	Chk_Abort();

	diskreq2 -> iotd_Req.io_Length	= Dest.NumSecs * Dest.BlockSize;      
	diskreq2 -> iotd_Req.io_Data	= (APTR) trackbuffer;
	diskreq2 -> iotd_Req.io_Command = TD_FORMAT;
	diskreq2 -> iotd_Count			= diskchangecount1;
	diskreq2 -> iotd_Req.io_Offset	= Dest.Offset + (track * Dest.NumSecs * Dest.BlockSize);
	DoIO(diskreq2);
	trackmap[track] = FORMATTED;
	for (count=0L; count < Dest.NumSecs * Dest.Size; count++) {
		trackbuffer[count] = 0xFFFFFFFF;
	}
	if (diskreq2 -> iotd_Req.io_Error) {
		printf("Error %d while formatting Track %2ld on Device %s !\n",
			(USHORT) diskreq2 -> iotd_Req.io_Error,
			track, Dest.Device);
		error();
	}
}

WriteSector(sector,buffer)
register unsigned long sector;  /* Sector # to be written */
register unsigned long *buffer; /* Pointer to SectorData  */
{
	register unsigned long	track;
	register unsigned long	sec;

	/* If not happened earlier, format Destination-Track */

	track = sector / Dest.NumSecs;
	sec   = sector % Dest.NumSecs;
	if ((track == curtrack) && (trackmap[curtrack] != FORMATTED)) {
		CopyMemQuick(buffer, &trackbuffer[sec * Dest.Size], Dest.BlockSize);
	} else {
		if ((track != curtrack) && (trackmap[curtrack] != FORMATTED)) {
			formattrack(curtrack);
		}
		curtrack = track;
		if (trackmap[track] != FORMATTED) {
			CopyMemQuick(buffer, &trackbuffer[sec * Dest.Size], Dest.BlockSize);
		} else {

			/* Write a Sector to Destination-Device */

			if ((Dest.MemBufType & MEMF_CHIP) && !(TypeOfMem(buffer) & MEMF_CHIP)) {
				CopyMemQuick(buffer, writebuffer, Dest.BlockSize);
				diskreq1 -> iotd_Req.io_Data	= (APTR) writebuffer;
			} else {
				diskreq1 -> iotd_Req.io_Data	= (APTR) buffer;
			}
			diskreq1 -> iotd_Req.io_Length	= Dest.BlockSize;      
			diskreq1 -> iotd_Req.io_Command = ETD_WRITE;
			diskreq1 -> iotd_Count		= diskchangecount1;
			diskreq1 -> iotd_Req.io_Offset	= Dest.Offset + sector * Dest.BlockSize;
			SendIO (diskreq1); /* ASynch Write ! */
		}
	}
}

PutSector(sector,buffer)
register unsigned long sector;  /* # of Sector to be written */
register unsigned long *buffer; /* Pointer to SectorData */
{

	/* Synchs with WriteSector and deallocates Buffer */

	if (oldbuffer) {
		WaitIO(diskreq1); /* Waits for end of last Write-Operation */
		if (diskreq1 -> iotd_Req.io_Error) {
			printf("Error %d while writing Sector %ld to Device %s !\n",
				(USHORT) diskreq1 -> iotd_Req.io_Error,
				(diskreq1 -> iotd_Req.io_Offset - Dest.Offset)/Dest.BlockSize,
				Dest.Device);
			error();
		}
		releasebuffer(oldbuffer);
	}
	if (oldbuffer = buffer) {
		WriteSector(sector, buffer);
	}
}

unsigned long *allocbuffer() /* Returns Pointer to Buffer (Size = Source.BlockSize) */
{
	register unsigned long	*buffer;
	register unsigned long	sec;

	/* Allocates Source.BlockSize Bytes of Memory */
	/* If there is not enough Memory, we try to   */
	/* release a DataSector already read.         */

	buffer = AllocMem((long) Source.BlockSize, MEMF_PUBLIC);
	if (buffer == NULL) {
		for (sec=last_checked; sec < Source.NumBlocks; sec++) {
			buffer = readmap[sec];
			if ((buffer) && (buffer != BLOCKED)) {
				readmap[sec] = EMPTY;
				last_checked = sec;
				return (buffer);
			}
		}
		for (sec=Source.ReservedBlks; sec < last_checked; sec++) {
			buffer = readmap[sec];
			if ((buffer) && (buffer != BLOCKED)) {
				readmap[sec] = EMPTY;
				last_checked = sec;
				return (buffer);
			}
		}
		printf("Sorry, not enough CHIP-Memory to continue ...\n");
		printf("Program terminated unsuccessfully.\n");
		error();
	}
	return (buffer);
}

releasebuffer(buffer)
register unsigned long *buffer;
{

	/* Deallocates a Sector-Buffer */

	if (buffer) {
		FreeMem(buffer, Source.BlockSize);
	}
}

openall()
{
	register unsigned long				err;
	register struct DeviceNode			*DeviceNode;
	register struct DeviceList			*DeviceList;
	register struct DosInfo				*DosInfo;
	register struct RootNode			*RootNode;

	oldbuffer = NULL;

	/* Get Devicenames and Units */

	RootNode   = (struct RootNode *)   (DOSBase -> dl_Root);
    DosInfo    = (struct DosInfo *)    (ULONG) ((RootNode   -> rn_Info)    << 2);
	DeviceList = (struct DeviceList *) (ULONG) ((DosInfo    -> di_DevInfo) << 2);
	DeviceNode = (struct DeviceNode *) DeviceList;

	Forbid(); /* Just in Case ... */
	do {
		if (DeviceNode -> dn_Type == DLT_DEVICE) {
			getDevice(DeviceNode, &Source);
			getDevice(DeviceNode, &Dest);
		}
	} while (DeviceNode = (struct DeviceNode *) ((ULONG) (DeviceNode -> dn_Next) << 2));
	/* I   H A T E   B C P L !   */

	Permit();

	/* Opening the Devices */

	if ( !(diskport0 = CreatePort (NULL, NULL))) {
		printf("Can't create DiskPort !\n");
		error();
	}
	if ( !(diskport1 = CreatePort (NULL, NULL))) {
		printf("Can't create DiskPort !\n");
		error();
	}
	if ( !(diskport2 = CreatePort (NULL, NULL))) {
		printf("Can't create DiskPort !\n");
		error();
	}

	if ( !(diskreq0 = CreateExtIO (diskport0, (long) sizeof (*diskreq0)))) {
		printf("Can't make IO block !\n");
		error();
	}

	if ( !(diskreq1 = CreateExtIO (diskport1, (long) sizeof (*diskreq1)))) {
		printf("Can't make IO block !\n");
		error();
	}

	if ( !(diskreq2 = CreateExtIO (diskport2, (long) sizeof (*diskreq2)))) {
		printf("Can't make IO block !\n");
		error();
	}

	if (err = OpenDevice (Source.Name, Source.Unit, diskreq0, Source.Flags)) {
		printf ("Can't get Device %s, Error %ld.\n", Source.Name, err);
		error();
	}

	if (err = OpenDevice (Dest.Name, Dest.Unit, diskreq1, Dest.Flags)) {
		printf ("Can't get Device %s, Error %ld\n", Dest.Name, err);
		error();
	}

	if (err = OpenDevice (Dest.Name, Dest.Unit, diskreq2, Dest.Flags)) {
		printf ("Can't get Device %s, Error %ld\n", Dest.Name, err);
		error();
	}

	/* Suspend Disk-Validation */

	dos_packet(DeviceProc(Dest.Device), ACTION_INHIBIT,
		   1L,0L,0L,0L,0L,0L,0L);

	dos_packet(DeviceProc(Source.Device), ACTION_INHIBIT,
		   1L,0L,0L,0L,0L,0L,0L);
}

getDevice(DeviceNode, Dev)

struct DeviceNode	*DeviceNode;
struct DevPar		*Dev;

{
	register struct FileSysStartupMsg	*FileSysStartupMsg;
	register unsigned long				*env;

	if (scmp(((LONG) (DeviceNode -> dn_Name) << 2) + 1L,
			 Dev->Device,(USHORT) (strlen(Dev->Device) - 1L))) {
		if ((FileSysStartupMsg = (struct FileSysStartupMsg *)
						((ULONG) (DeviceNode -> dn_Startup) << 2)) > 100L) {
			strcpy(Dev->Name,
			       (char *) (((LONG) (FileSysStartupMsg -> fssm_Device) << 2) + 1L));
			Dev->Unit = FileSysStartupMsg -> fssm_Unit;
			env = (unsigned long *) (FileSysStartupMsg -> fssm_Environ << 2);

			/* I really  H A T E  BCPL ! */

			/* Getting Device-Parameters */

			Dev->NumHeads		= env[DE_NUMHEADS];
			Dev->NumSecs		= env[DE_BLKSPERTRACK];
			Dev->NumCyls		= env[DE_UPPERCYL] - env[DE_LOWCYL] + 1L;
			Dev->NumTracks		= Dev->NumCyls * Dev->NumHeads;
			Dev->ReservedBlks	= env[DE_RESERVEDBLKS];
			Dev->Size			= env[DE_SIZEBLOCK];
			Dev->BlockSize		= Dev->Size << 2;
			Dev->NumBlocks		= Dev->NumCyls * Dev->NumHeads * Dev->NumSecs;
			Dev->RootBlock		= Dev->NumBlocks >> 1;
			Dev->NumEntries		= Dev->Size - 51L - 5L;
			Dev->NumLongs		= Dev->NumBlocks >> 5;
			Dev->SecsPerCyl		= Dev->NumSecs * Dev->NumHeads;
			Dev->MemBufType		= env[DE_MEMBUFTYPE];
			Dev->Flags			= FileSysStartupMsg -> fssm_Flags;
			Dev->Offset			= env[DE_LOWCYL] * Dev->SecsPerCyl * Dev->BlockSize;
			Dev->NumBMSecs		= 1L + ((Dev->NumBlocks - Dev->ReservedBlks) / ((Dev->Size - 1L) << 5));
			Dev->BlocksPerBMSec	= (Dev->Size - 1L) << 5;
		}
	}
}

checkdisks()
{

	if (Source.Size != Dest.Size) {
		printf("Devices have different Sectorsizes !\n");
		error();
	}

	diskreq0 -> iotd_Req.io_Command = TD_CHANGESTATE;
	DoIO (diskreq0);
	if (diskreq0 -> iotd_Req.io_Actual) {
		printf("No Disk in Device %s !\n",Source.Device);
		error();
	}

	diskreq1 -> iotd_Req.io_Command = TD_CHANGESTATE;
	DoIO (diskreq1);
	if (diskreq1 -> iotd_Req.io_Actual) {
		printf("No Disk in Device %s !\n",Dest.Device);
		error();
	}

	diskreq1 -> iotd_Req.io_Command = TD_PROTSTATUS;
	DoIO (diskreq1);
	if (diskreq1 -> iotd_Req.io_Actual) {
		printf("Disk in Device %s is write-protected !\n",Dest.Device);
		error();
	}

	diskreq0 -> iotd_Req.io_Command = TD_CHANGENUM;
	DoIO (diskreq0);
	diskchangecount0 = diskreq0 -> iotd_Req.io_Actual;

	diskreq1 -> iotd_Req.io_Command = TD_CHANGENUM;
	DoIO (diskreq1);
	diskchangecount1 = diskreq1 -> iotd_Req.io_Actual;
}

Chk_Abort()
{
	if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
		printf("[F** BREAK\n");
		error();
	}
}

error()
{
	closeall();
	if (wbflag) {
		printf("Press Return to abort.\n");
		getchar();
	}
	exit(20);
}

closeall()
{
	register unsigned long	count;

	/* Closing Disk-Devices */
	/* Deallocating Buffers */
	/* Closing Libraries    */

	if (oldbuffer) {
		releasebuffer(oldbuffer);
	}

	if (buffermap) {
		for (count = NULL; count < Source.NumBlocks; ++count) {
			if (buffermap[count]) {
				releasebuffer(buffermap[count]);
			}
		}
		FreeMem(buffermap, Source.NumBlocks << 2);
	}

	if (readmap) {
		for (count = NULL; count < Source.NumBlocks; ++count) {
			if ((readmap[count]) && (readmap[count] != BLOCKED)) {
				releasebuffer(readmap[count]);
			}
		}
		FreeMem(readmap, Source.NumBlocks << 2);
	}

	if (sectormap) {
		FreeMem(sectormap, Source.NumBlocks << 2);
	}

	if (stack) {
		FreeMem(stack, SourceBlocks << 2);
	}

	if (trackmap) {
		FreeMem(trackmap, Dest.NumTracks);
	}

	if (trackbuffer) {
		FreeMem(trackbuffer,Dest.NumSecs * Dest.BlockSize);
	}

	if (writebuffer) {
		FreeMem(writebuffer, Dest.BlockSize);
	}

	if (readbuffer) {
		FreeMem(readbuffer, Dest.BlockSize);
	}

	if (diskreq0) {
		if (((long) diskreq0 -> iotd_Req.io_Device != -1L) &&
		    ((long) diskreq0 -> iotd_Req.io_Device != 0L)) {
			CloseDevice(diskreq0);
		}
		DeleteExtIO(diskreq0, (long) sizeof (*diskreq0));
	}

	if (diskreq1) {

		if (((long) diskreq1 -> iotd_Req.io_Device != -1L) &&
		    ((long) diskreq1 -> iotd_Req.io_Device != 0L)) {
			CloseDevice(diskreq1);

			/* Forced Diskchange */

			dos_packet(DeviceProc(Dest.Device), ACTION_INHIBIT,
				   0L,0L,0L,0L,0L,0L,0L);

			dos_packet(DeviceProc(Source.Device), ACTION_INHIBIT,
				   0L,0L,0L,0L,0L,0L,0L);
		}
		DeleteExtIO(diskreq1, (long) sizeof (*diskreq1));
	}

	if (diskreq2) {
		if (((long) diskreq2 -> iotd_Req.io_Device != -1L) &&
		    ((long) diskreq2 -> iotd_Req.io_Device != 0L)) {
			CloseDevice(diskreq2);
		}
		DeleteExtIO(diskreq2, (long) sizeof (*diskreq2));
	}

	if (diskport0) {
		DeletePort(diskport0);
	}
	if (diskport1) {
		DeletePort(diskport1);
	}
	if (diskport2) {
		DeletePort(diskport2);
	}
	if (IconBase) {
		CloseLibrary(IconBase);
	}
}
