home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Supreme Volume 6 #1
/
swsii.zip
/
swsii
/
126
/
SPRDPR20.ZIP
/
COPYDISK.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-03-12
|
15KB
|
504 lines
/*******************************************************************************
* Program: COPYDISK.C C 5.1 and MASM 5.1
*
* Purpose: Copies volume label, subdirectory structure and all files
* regardless of attribute type from one disk medium to another.
*
* Author: Gordon Harris
* 3349 Humboldt Ave S
* Minneapolis, MN 55408
*
* Comments can be addressed to my
* CompuSurve address: [72611,620]
*
*
*
* Description: COPYDISK is an XCOPY like utility which allows you to copy
* an entire disk to a drive of differing type, e.g. copy
* the contents of a 1.2 m floppy to a 1.44 m floppy, etc.
*
* Unlike XCOPY, COPYDISK will copy the volume label from the
* source disk to the target, as well as copying all
* subdirectories and files including hidden, system or read-
* only files and directories. All files on the target disk
* created by COPYDISK will have identical attributes (dates,
* times, etc) as the files on the source disk. If the
* source disk is bootable, so will the resulting target disk.
*
* Syntax: The syntax for using COPYDISK is:
*
* COPYDISK sourcedrive: targetdrive: [-n] [-x] [-f]
*
* where "sourcedrive:" and "targetdrive:" are valid dos drives
* and [-n], [-x] and [-f] are optional parameters.
*
* Operation: Given valid parameters, COPYDISK (1) performs a media check
* on the indicated drives, (2) prompts the user for permission
* to delete all existing data from the target drive, (3) copies
* the volume label from the source drive to the target and then
* (4) proceeds to copy all files and directories from the source
* to the target.
*
* COPYDISK will abort if its check of the media type of the
* target disk reveals that it is a fixed disk. This protects
* you from inadvertently deleting the contents of a hard disk
* either by using an incorrect parameter for the target drive
* or by using a virtual drive name created by ASSIGN or SUBST
* which represents a fixed disk drive or subdirectory on a
* hard disk.
*
* During the media check, COPYDISK installs its own critical
* error handler. If a error is detected reading either the
* source or target drives, COPYDISK will prompt you to retry
* access to the disk. If you choose not to retry access to
* the target disk, COPYDISK will prompt you as to whether you
* wish to format the target.
*
* COPYDISK will also abort if the data on the source disk is
* too large to fit on the empty target disk, or if any errors
* occur reading data from the source or writing data to the
* target disks.
*
* Optional Parameters:
* -n (no prompt). This is useful when using COPYDISK in batch
* files. With the "-n" parameter, COPYDISK will not prompt you
* for permission to delete all data from the target disk.
*
* -x (relaxed media checking). With this parameter, the target
* disk may be a hard disk and the source data may be larger
* than the capacity of the target disk.
*
* -f (format target automatically if media check failure). With
* this parameter, the DOS FORMAT.COM command will be spawned
* without prompting if the target disk fails the media check.
*
* Credits: Ray Duncan, Advanced MS DOS Programming, 1988, Microsoft Press
* Kevin P. Welch, "WFINDER"
*
*
********************************************************************************/
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <malloc.h>
#include <process.h>
#include "COPYDISK.h"
char *pSource;
size_t nBufSize;
int errno;
int nNumFiles;
char szSyntaxMsg [] = "Syntax: COPYDISK sourcedrive: targetdrive: -NoPrompt \n\n",
szMsg[80] = "\n";
union REGS inregs, outregs;
struct SREGS segregs;
unsigned _osversion;
main(int argc, char * argv[] )
{
int bPrompt, bCheck, bFormat, n;
struct drvinfo_t drv1, drv2;
int crterror = 0;
char szDrive1 [10], szDrive2 [10];
errno = EINVAL;
strcpy (szDrive1, " :\\*.*");
strcpy (szDrive2, " :");
if (argc < 3)
ErrExit("");
szDrive1 [0] = toupper(*argv [1]);
szDrive2 [0] = toupper(*argv [2]);
/* check for same source & target drives */
if (szDrive1 [0] == szDrive2 [0])
ErrExit("Sourcedrive = Targetdrive");
/* check remaining parameters */
bPrompt = TRUE;
bCheck = TRUE;
bFormat = FALSE;
for (n = 3; n < argc; n++)
{
if (argv [n] [0] == '-' || argv [n] [0] == '/')
switch ( toupper(argv [n] [1]) )
{
case 'N':
bPrompt = FALSE;
break;
case 'X':
bCheck = FALSE;
break;
case 'F':
bFormat = TRUE;
}
}
/* install critical error handler */
setint24 (&crterror);
/* perform media check on source drive */
while ( !drvinfo(szDrive1 [0] - '@', &drv1))
{
if (!crterror)
{
sprintf (szMsg, "Source drive %c: not valid", *szDrive1);
ErrExit (szMsg);
}
crterror = 0;
printf("\r\7Error reading source disk %c: Retry? (Y/N) \b", *szDrive1);
if (toupper (getche()) != 'Y')
ErrExit ("");
}
/* perform media check on target drive */
while ( !drvinfo(szDrive2 [0] - '@', &drv2))
{
if (!crterror)
{
sprintf (szMsg, "Target drive %c: not valid", *szDrive2);
ErrExit (szMsg);
}
if (!bFormat)
{
printf("\r\7Error reading target disk %c: Retry? (Y/N) \b", *szDrive2);
if (toupper (getche()) == 'Y')
continue;
printf ("\rDo you wish to format disk in drive %c: ? (Y/N) ",*szDrive2);
bFormat = (toupper (getche()) == 'Y');
}
if (crterror && bFormat)
{
switch (LOBYTE(_osversion))
{
case 3:
strcpy(szMsg, "/H");
break;
case 4:
strcpy(szMsg, "/AUTOTEST");
break;
default:
szMsg[0] = '\0';
}
printf("\rFormatting %s \n", szDrive2);
spawnlp(P_WAIT,"format.com", "format.com", szDrive2, szMsg, NULL);
}
else
{
ErrExit("");
}
crterror = 0;
bFormat = FALSE;
}
/* de-install critical error handler here */
restint24 ();
/* check results of previous media check */
if (bCheck)
{
if (drv2.type == 0x0f8)
{
errno = EACCES;
sprintf(szMsg, "Targetdrive %c: is a fixed disk", *szDrive2);
ErrExit(szMsg);
}
if (drv1.lDataSize > drv2.lDiskSpace)
{
sprintf (szMsg, "Source drive %c: data too large for target drive %c",
*szDrive1, *szDrive2);
ErrExit(szMsg);
}
}
if (bPrompt)
{
printf ("\rWARNING: all data on drive %c will be deleted. Do you wish to continue? (Y/N) ", *szDrive2);
if (toupper (getche()) != 'Y')
exit(1);
}
volcopy (szDrive1[0] - '@', szDrive2 [0] - '@');
printf ("\rDeleting files and directories on drive %c:"
" \r", *szDrive2);
strcat (szDrive2, "\\");
chdir (szDrive2);
strcat (szDrive2, "*.*");
DelAll(szDrive2, _A_NORMAL | _A_RDONLY | _A_HIDDEN | _A_SYSTEM);
/* Allocate file buffer */
nBufSize = _memmax();
pSource = malloc (nBufSize);
if (pSource == NULL)
{
ErrExit ("Insufficient memory available");
}
nNumFiles = 0;
szDrive1 [2] = '\0';
szDrive2 [2] = '\0';
printf ("Copying files and directories from drive %c: to %c:\n%s\\\n", *szDrive1, *szDrive2, szDrive2);
strcat (szDrive1, "\\*.*");
strcat (szDrive2, "\\*.*");
CopyAll(szDrive1, szDrive2, _A_NORMAL | _A_RDONLY | _A_HIDDEN | _A_SYSTEM);
free(pSource);
printf(" %d file(s) copied \n", nNumFiles);
}
void ErrExit (char *msg)
{
fprintf(stderr, "\nError %d--%s%s", errno, _strerror(msg), szSyntaxMsg);
exit(errno);
}
BOOL DelAll(
PSTR szFileSpec,
WORD wAttributes)
{
BOOL bContinue;
WORD wEntry, wDirEntries;
struct find_t DirEntry;
char szPath[64], szSpec[64], szEntry[64],
szCurFile [64], szCurDir [64];
/* initialization */
bContinue = TRUE;
wDirEntries = 0;
/* separate file spec into path and wildcards */
for (wEntry=strlen(szFileSpec)-1; szFileSpec[wEntry]!='\\'; wEntry-- );
strcpy( szPath, szFileSpec );
szPath[wEntry] = 0;
strcpy( szCurFile, szFileSpec );
szCurFile[wEntry + 1] = 0;
strcpy( szSpec, &szFileSpec[wEntry+1] );
/* perform search for normal files */
if ( _dos_findfirst(szFileSpec,wAttributes,&DirEntry) == 0 )
{
/* repeat until all entries exhausted */
do {
/* output current file name */
szCurFile[wEntry + 1] = 0;
strcat (szCurFile, DirEntry.name);
if (DirEntry.attrib != _A_NORMAL || DirEntry.attrib != _A_ARCH)
_dos_setfileattr (szCurFile, _A_NORMAL);
unlink (szCurFile);
} while ( _dos_findnext(&DirEntry) == 0 );
}
/* perform search for sub-directories */
sprintf( szEntry, "%s\\*.*", szPath );
if ( _dos_findfirst(szEntry,_A_SUBDIR | _A_NORMAL | _A_RDONLY | _A_HIDDEN | _A_SYSTEM, &DirEntry) == 0 )
{
/* repeat until all entries exhausted */
do {
/* eliminate special directory entries */
if ( (DirEntry.attrib & _A_SUBDIR) && (DirEntry.name[0]!='.') )
{
sprintf( szEntry, "%s\\%s\\%s", szPath, DirEntry.name, szSpec );
sprintf( szCurDir, "%s\\%s", szPath, DirEntry.name);
bContinue = DelAll( szEntry, wAttributes );
rmdir (szCurDir);
}
} while ( (bContinue)&&(_dos_findnext(&DirEntry) == 0) );
}
/* return final result */
return( bContinue );
}
BOOL CopyAll(
PSTR szFileSpec1,
PSTR szFileSpec2,
WORD wAttributes)
{
BOOL bContinue;
WORD wEntry, wDirEntries;
struct find_t DirEntry;
struct find_t near *pDirEntry;
char near *pPos;
int hSource, hTarget;
size_t nRead, nWrite, nNumRead, nNumWrite;
long lTotRead, lTotWrite;
int n, nFiles;
char szPath[64], szSpec[64], szEntry[64],
szCurFile [68], szNewFile [68], szNewDir [64];
/* initialization */
bContinue = TRUE;
wDirEntries = 0;
/* separate file spec into path and wildcards */
for (wEntry=strlen(szFileSpec1)-1; szFileSpec1[wEntry]!='\\'; wEntry-- );
strcpy( szPath, szFileSpec1 );
szPath[wEntry] = 0;
strcpy( szCurFile, szFileSpec1 );
szCurFile[wEntry + 1] = 0;
strcpy( szNewFile, szFileSpec1 );
szNewFile[wEntry + 1] = 0;
szNewFile[0] = szFileSpec2[0];
strcpy( szSpec, &szFileSpec1[wEntry+1] );
lTotRead = 0L;
lTotWrite = 0;
/* perform search for normal files */
if ( _dos_findfirst(szFileSpec1,wAttributes,&DirEntry) == 0 )
{
/* repeat until all entries exhausted */
do {
nFiles = 0;
pPos = pSource;
while (pPos + (sizeof (DirEntry) * 2) < pSource + nBufSize)
{
/* copy DirEntry into buffer */
memcpy (pPos, &DirEntry, sizeof (DirEntry) );
pDirEntry = pPos;
pPos += sizeof (DirEntry);
/* Open source file */
szCurFile[wEntry + 1] = '\0';
strcat (szCurFile, DirEntry.name);
if (lTotRead == 0L)
{
if (_dos_open (szCurFile, O_RDONLY, &hSource) != 0)
{
sprintf (szMsg, "Could not open file %s", szCurFile);
ErrExit(szMsg);
}
}
/* read as much of file into buffer as possible */
if(_dos_read(hSource, pPos, nBufSize - (pPos - pSource), &nNumRead) != 0)
{
sprintf (szMsg, "Error reading file %s", szCurFile);
ErrExit (szMsg);
}
pPos += nNumRead;
lTotRead += (long) nNumRead;
nFiles++;
printf(" %-12s %7ld bytes read \r",
pDirEntry->name,
lTotRead);
if (lTotRead == DirEntry.size)
{
_dos_close (hSource);
lTotRead = 0L;
if (_dos_findnext(&DirEntry) != 0)
break;
}
else
break;
}
/* Write new files */
/* position of first file */
pDirEntry = pSource;
pPos = pSource + sizeof (DirEntry);
for (n = 0; n < nFiles; n++)
{
/* check to see if we are finishing a file.. */
if (lTotWrite == 0)
{
szNewFile[wEntry + 1] = '\0';
strcat (szNewFile, pDirEntry->name);
if (_dos_creat (szNewFile, pDirEntry->attrib, &hTarget) != 0)
{
sprintf (szMsg, "Could not create file %s", szNewFile);
ErrExit (szMsg);
}
}
if (pDirEntry->size > nBufSize - (pPos - pSource))
nWrite = nBufSize - (pPos - pSource);
else
nWrite = pDirEntry->size;
if ( (pDirEntry->size - lTotWrite) < nWrite)
nWrite = (unsigned int) (pDirEntry->size - lTotWrite);
if ( _dos_write (hTarget, pPos, nWrite, &nNumWrite) != 0 )
{
sprintf (szMsg, "Error writing file %s", szNewFile);
ErrExit (szMsg);
}
if (nNumWrite != nWrite)
{
sprintf (szMsg, "Error writing file %s", szNewFile);
ErrExit (szMsg);
}
lTotWrite += (long) nNumWrite;
pPos += (unsigned long) nWrite;
printf(" %-12s %7ld bytes written\r",
pDirEntry->name,
lTotWrite);
if (lTotWrite == pDirEntry->size)
{
lTotWrite = 0L;
_dos_setftime( hTarget, pDirEntry->wr_date, pDirEntry->wr_time);
_dos_close (hTarget);
nNumFiles++;
}
pDirEntry = pPos;
pPos += sizeof (DirEntry);
}
} while ( lTotRead != 0L || _dos_findnext(&DirEntry) == 0 );
}
/* perform search for sub-directories */
sprintf( szEntry, "%s\\*.*", szPath );
if ( _dos_findfirst(szEntry,_A_SUBDIR | _A_NORMAL | _A_RDONLY | _A_HIDDEN | _A_SYSTEM, &DirEntry) == 0 )
{
/* repeat until all entries exhausted */
do {
/* eliminate special directory entries */
if ( (DirEntry.attrib & _A_SUBDIR) && (DirEntry.name[0]!='.') )
{
sprintf( szEntry, "%s\\%s\\%s", szPath, DirEntry.name, szSpec );
sprintf( szNewDir, "%s\\%s", szPath, DirEntry.name);
szNewDir [0] = szFileSpec2 [0];
mkdir (szNewDir);
_dos_setfileattr(szNewDir, DirEntry.attrib);
printf("%s%s\n", szNewDir, " ");
bContinue = CopyAll( szEntry,szFileSpec2, wAttributes );
}
} while ( (bContinue)&&(_dos_findnext(&DirEntry) == 0) );
}
/* return final result */
return( bContinue );
}