home *** CD-ROM | disk | FTP | other *** search
- /*******************************************************************************
- * 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 );
- }
-