Metropoli BBS
VIEWER: copy.c MODE: TEXT (ASCII)
/****************************************************************/
/*								*/
/*			      copy.c				*/
/*								*/
/*		      command.com copy command 			*/
/*								*/
/*			  August 9, 1991			*/
/*								*/
/*		        Copyright (c) 1995			*/
/*			Pasquale J. Villani			*/
/*			All Rights Reserved			*/
/*								*/
/* This file is part of DOS-C.					*/
/*								*/
/* DOS-C is free software; you can redistribute it and/or	*/
/* modify it under the terms of the GNU General Public License	*/
/* as published by the Free Software Foundation; either version	*/
/* 2, or (at your option) any later version.			*/
/*								*/
/* DOS-C is distributed in the hope that it will be useful, but	*/
/* WITHOUT ANY WARRANTY; without even the implied warranty of	*/
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See	*/
/* the GNU General Public License for more details.		*/
/*								*/
/* You should have received a copy of the GNU General Public	*/
/* License along with DOS-C; see the file COPYING.  If not,	*/
/* write to the Free Software Foundation, 675 Mass Ave,		*/
/* Cambridge, MA 02139, USA.					*/
/****************************************************************/


/* $Logfile:   C:/dos-c/src/command/copy.c_v  $ */

/*
 * $Log:   C:/dos-c/src/command/copy.c_v  $ 
 * 
 *    Rev 1.1   01 Sep 1995 18:04:32   patv
 * First GPL release.
 * 
 *    Rev 1.0   02 Jul 1995 10:01:38   patv
 * Initial revision.
 */


#include "../../hdr/portab.h"
#include "globals.h"
#include "proto.h"

static BYTE *RcsId = "$Header:   C:/dos-c/src/command/copy.c_v   1.1   01 Sep 1995 18:04:32   patv  $";

#define CHUNK	16384

BOOL copy()
{
	COUNT ifd, ofd, ret, CopyCount = 0;
	seg MemSeg;
	BYTE FAR *MemBuffer;
	date fdate;
	time ftime;
	BYTE FromPath[MAX_CMDLINE], ToPath[MAX_CMDLINE];
	COUNT dest_driveno = -1, src_driveno = -1;
	BYTE src_path[MAX_CMDLINE], src[MAX_CMDLINE];
	BYTE dest_path[MAX_CMDLINE], dest[MAX_CMDLINE];
	BOOL bflag, aflag, AppendMode = FALSE, FirstTime = TRUE, IsWild, Error;
	dmatch dmp;

	/* Intialize the dta to put the dir info into			*/
	DosSetDta((BYTE FAR *)&dmp);

	/* And initialize our current location				*/
        FindHome();

	/* Parse the command line, and get our destination		*/
	/* First initialize parameters ...				*/
	aflag = bflag = FALSE;
	*dest = *src = *src_path = *dest_path = *FromPath = *ToPath = '\0';

	/* Then get the options.					*/
	dosopt("$d$p*$d$p*[ab]+", (BYTE FAR *)tail,
	 &src_driveno, src_path, src,
	 &dest_driveno, dest_path, dest,
	 &aflag, &bflag);

	/* Need at least source or source and destination		*/
	if(*src == '\0')
	{
		error_message(INV_NUM_PARAMS);
		GoHome();
		return FALSE;
	}

	/* Now start looking at what was passed.			*/
	/* First, substitute current drive if the source or destination	*/
	/* drive was not specified.					*/
	if(src_driveno < 0)
		src_driveno = DosGetDrive();
	if(dest_driveno < 0)
		dest_driveno = DosGetDrive();

	/* If the source path was not specified, get the current path	*/
	/* and substitute that.						*/
	if(*src_path == '\0')
	{
		*src_path = '\\';
		DosPwd(src_driveno + 1, (BYTE FAR *)&src_path[1]);
	}


	/* If no destination has been specified, build one ...		*/
	/* If the destination path was not specified, get the current	*/
	/* path and substitute that.					*/
	if(*dest_path == '\0')
	{
		/* No specification, build it as source in this		*/
		/* directory.						*/
		*dest_path = '\\';
		DosPwd(dest_driveno + 1, (BYTE FAR *)&dest_path[1]);

	}

	/* Now check for special case where dest is really a directory	*/
	if(*dest != '\0')
	{
		COUNT cudrvno;
		BYTE cudir[67];

		/* Get where we are					*/
		cudrvno = DosGetDrive();
		*cudir = '\\';
		DosPwd(cudrvno + 1, (BYTE FAR *)&cudir[1]);

		/* Change to the path and then test the file name. If	*/
		/* it is a directory, concatenate the source base name	*/
		/* to it to build a full path.				*/
		DosSetDrive(dest_driveno);
		if(DosCd((BYTE FAR *)dest_path) == SUCCESS)
		{
			/* This is a gimmick.  If the cd does not work,	*/
			/* the path is unaffected, so we let DOS do our	*/
			/* building of the path.			*/
			if(DosCd((BYTE FAR *)dest) != SUCCESS)
				AppendMode = TRUE;
			DosPwd(DosGetDrive() + 1, (BYTE FAR *)&dest_path[1]);
		}

		/* Change back to the current drive and directory.	*/
		DosSetDrive(cudrvno);
		if((DosCd((BYTE FAR *)cudir)) != SUCCESS)
		{
			error_message(INV_DIR);
			GoHome();
			return FALSE;
		}
	}

	/* Since we have to comply with wild card specifications, the	*/
	/* only way to expand the source is to switch there, do your	*/
	/* thing and then switch back.					*/

	/* Switch to the requested directory to copy from		*/
	DosSetDrive(src_driveno);

	/* Change to the path and then test the file name. If it is a	*/
	/* directory, concatenate the source base name to it to build a	*/
	/* full path.							*/
	if(DosCd((BYTE FAR *)src_path) != SUCCESS)
	{
		error_message(FILE_NOT_FOUND);
		GoHome();
		return FALSE;
	}

	/* Finally ! Expand the wild cards!				*/
	IsWild = iswild(src);
	if(DosFindFirst(D_NORMAL | D_RDONLY , (BYTE FAR *)src) != SUCCESS)
	{
		error_message(FILE_NOT_FOUND);
		GoHome();
		return TRUE;
	}

	do
	{
		BYTE *s;

		/* Build the from file specification and the to file	*/
		/* specification from above parts.			*/
		/* First the source					*/
		*FromPath = 'A' +  src_driveno;
		strcpy(&FromPath[1], ":");
		strcat(FromPath, src_path);
		if(FromPath[3] != '\0')
			strcat(FromPath, "\\");
		strcat(FromPath, dmp.dm_name);
		for(s = FromPath; *s != '\0'; s++)
			*s = toupper(*s);

		/* Then the destination.				*/
		if(!AppendMode || (AppendMode && FirstTime))
		{
			*ToPath = 'A' +  dest_driveno;
			strcpy(&ToPath[1], ":");
			strcat(ToPath, dest_path);
			if(ToPath[3] != '\0')
				strcat(ToPath, "\\");
			if(AppendMode)
				strcat(ToPath, dest);
			else
				strcat(ToPath, dmp.dm_name);
			for(s = ToPath; *s != '\0'; s++)
				*s = toupper(*s);
		}

		/* Check for a match between source and destination.	*/
		/* Quit if they match					*/
		if(strcmp(FromPath, ToPath) == 0)
		{
			if(AppendMode && !IsWild)
			{
				error_message(FILE_ON_ITSELF);
				if(AppendMode && !FirstTime)
					DosClose(ofd);
				GoHome();
			}
			else
                        	continue;
			return FALSE;
		}

		if(IsWild)
			printf("  %s\n", dmp.dm_name);
		if((ifd = DosOpen((BYTE FAR *)FromPath, O_RDONLY)) < 0)
		{
			strcpy(error_mess_str, FromPath);
			error_message(FILE_NOT_FOUND);
			if(AppendMode && !FirstTime)
				DosClose(ofd);
			GoHome();
			return FALSE;
		}
		if(!AppendMode || (AppendMode && FirstTime))
		{
			if((ofd = DosCreat((BYTE FAR *)ToPath, D_NORMAL)) < 0)
			{
				strcpy(error_mess_str, ToPath);
				error_message(FILE_CREATE_ERR);
				GoHome();
				DosClose(ifd);
				if(AppendMode && !FirstTime)
					DosClose(ofd);
				return FALSE;
			}
			FirstTime = FALSE;
		}

		/* Get a buffer from DOS				*/
		MemSeg = DosAllocMem(CHUNK / PARASIZE, (BOOL FAR *)&Error);
		if(Error)
		{
			error_message(INSUFF_MEM);
			GoHome();
			DosClose(ifd);
			if(AppendMode && !FirstTime)
				DosClose(ofd);
			return FALSE;
		}
		MemBuffer = MK_FP(MemSeg, 0);

                /* Dos the file copy itself				*/
		while((ret = DosRead(ifd, (BYTE FAR *)MemBuffer, CHUNK)) > 0)
		{
			if(DosWrite(ofd, (BYTE FAR *)MemBuffer, ret) != ret)
			{
				error_message(INSUFF_DISK);
				DosClose(ifd);
				DosClose(ofd);
				DosDelete((BYTE FAR *)ToPath);
				return FALSE;
			}
			if(ret != CHUNK)
				break;
		}

		/* Free the buffer					*/
		DosFreeMem(MemSeg, (BOOL FAR *)&Error);

		/* And update the file time if applicable		*/
		if(!AppendMode || (AppendMode && !IsWild))
		{
			DosGetftime(ifd, &fdate, &ftime);
			DosSetftime(ofd, &fdate, &ftime);
		}
		DosClose(ifd);
		++CopyCount;
		if(!AppendMode)
			DosClose(ofd);
	}
	while(DosFindNext() == SUCCESS);

	/* Change back to the current drive and directory.		*/
	if(AppendMode)
		DosClose(ofd);
	if(AppendMode)
		printf("\n%d File(s) copied\n", CopyCount);
	return GoHome();
}

[ RETURN TO DIRECTORY ]