Category : File Managers
Archive   : COPYDSK.ZIP
Filename : COPYDISK.C
Output of file : COPYDISK.C contained in archive : COPYDSK.ZIP
* 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
#include
#include
#include
#include
#include
#include
#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 );
}
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/