home *** CD-ROM | disk | FTP | other *** search
- /*
- QDCopy Version 1.0
-
- Quick & Dirty File Copier (or Qwazy Darren File Copier!)
-
- Created on July 10, 1991
- Last revised July 15, 1991
-
- Copyright (C) 1991 by Darren Ewaniuk
- Freely distributable with conditions
- (See "distribution" section of the documentation file for more information)
-
- Compiled using the Freely distributable DICE C compiler version 2.06.16
- (Thanks to Matt Dillon for DICE - as soon as it includes the 2.0
- specific files, I'm sending in the registration for it)
-
- Compile using "DCC QDCopy.c /arplib/aztecglue.o -o QDCopy"
-
- Library functions used:
-
- Exec
- OpenLibrary To open ARP library
- CloseLibrary To close ARP library
- SetSignal Break handling
-
- DOS.library
- Close Close files
- DeleteFile Delete incomplete file when disk full
- IoErr Check what error occurred
- Open Open files
- Read Read files
- SetComment Set file comment
- SetProtection Set protection bits
- Write Write files
-
- Arp.library V39
- BaseName Finds base name of read files
- DosAllocMem Allocates memory
- DosFreeMem Frees memory
- FindFile Finds first wildcard file
- FindNext Finds subsequent wildcard files
- FreeAnchorChain Frees ARP's wildcard file structures
- ReadLine Gets user input during diskchanges
- TackOn Puts together filename from basename and pathname
-
- NOTE: The C functions malloc() and free() can be used instead of
- DosAllocMem() and DosFreeMem() but I've heard problems with
- one of the 'big-name' compilers that use these functions,
- so I just used the ARP ones since I'm using ARP anyways.
- /*
-
- /* Pretend DICE is Aztec C so that arpbase.h does not try to use #pragmas */
-
- #define AZTEC_C 1
-
- /* Include the necessary files */
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <libraries/dos.h>
- #include <libraries/arpbase.h>
- #include <stdio.h>
- #include <stdlib.h>
-
- /* Set up Arp library base */
-
- struct ArpBase *ArpBase;
-
- /* Stuff for file name buffers */
-
- #define MaxPathSize 130
- #define MaxFileNameSize 30
- #define MaxPathNameSize MaxPathSize+MaxFileNameSize+1
-
- /* This is where I store the filenames which match the wildcard */
-
- struct QDFileChain /* Structure for each file buffer entry */
- {
- struct QDFileChain *Next; /* Pointer to next file name */
- void *FileBuffer; /* Pointer to storage buffer */
- char FileName[MaxPathNameSize]; /* full path file name */
- LONG Protection; /* DOS protection bits */
- LONG Size; /* DOS file size */
- char Comment[80]; /* DOS file comment */
- };
-
- /* This function cleans up all memory used by QDFileChain structures */
- /* Shouldn't be needed for normal exit, but if premature, this frees */
- /* the memory used by the programs */
-
- void cleanupchain (struct QDFileChain *chainhead)
- {
- struct QDFileChain *nextptr;
-
- while (chainhead) /* While the head is not NULL free up the next */
- {
- nextptr = chainhead->Next;
-
- if (chainhead->FileBuffer) /* Is the file buffered in memory? */
- {
- DosFreeMem (chainhead->FileBuffer); /* Free it back to the system */
- }
- DosFreeMem (chainhead); /* Free this file chain structure */
- chainhead = nextptr;
- }
- }
-
- /* This function tests a file or path name for an explicitly specified */
- /* device name. If the name contains ':' then I assume one is specified */
-
- int isfullname (char *name)
- {
- int pos = 0;
- while ((name[pos] != 0) && (name[pos] != ':'))
- {
- pos++;
- }
- if (name[pos]) /* If not end of string, current char is ':' */
- {
- return(TRUE);
- }
- else /* Reached end of string first. No ':' in name */
- {
- return(FALSE);
- }
- }
-
- /* Kill DICE's break handling */
-
- void chkabort()
- {
- }
-
- /* Checks for break and returns TRUE if pressed */
-
- int taskbreak()
- {
- /* Check and clear break signal */
-
- if ((SetSignal(0L, SIGBREAKF_CTRL_C)) & SIGBREAKF_CTRL_C)
- {
- printf ("***QDCOPY BREAK\n");
- return (TRUE);
- }
- else
- {
- return (FALSE);
- }
- }
-
- /* Start of the main program */
-
- void main (int argc, char *argv[])
- {
- BPTR filehandle; /* BPTR file handle for src, dest files */
- LONG len; /* # of bytes read from/written to file */
-
- int warncode = 0; /* Exit code for return to shell */
- int breaksignal; /* Break flag */
- int memfull = FALSE; /* Memory full flag */
- int newdest; /* Prompt for new Destination disk flag */
-
- char destpath[MaxPathSize+1]; /* Current destination path */
- char pathname[MaxPathNameSize]; /* Full path name for write */
- char *basename; /* Base name for write */
-
- /* Used for diskchange prompt */
-
- char inputline [MaxInputBuf]; /* Input line buffer */
- LONG inputlength; /* Length of input line buffer */
-
- struct QDFileChain *filehead = NULL; /* First file in chain */
- struct QDFileChain *fileptr1 = NULL; /* Last file read */
- struct QDFileChain *fileptr2 = NULL; /* Last file written */
- struct AnchorPath *anchorpath; /* ARP wildcard anchorpath structure */
-
- LONG errorcode; /* DOS & ARP error code */
-
- /* DICE leaves before 0 args are passed because there's no WBMain() */
- /* but I thought I'd leave it in for people with other compilers */
-
- if (argc == 0) /* Too bad, cannot run from Workbench. */
- {
- exit (0);
- }
- else if (argc !=3) /* User doesn't know what he's doing! */
- {
- printf ("\n\033[33mQDCopy 1.0\033[31m (July 15, 1991) Quick and Dirty file copier\n");
- printf ("Copyright \251 1991 by Darren Ewaniuk, freely distributable with conditions\n");
- printf ("Usage: QDCopy <source file pattern> <destination path>\n\n");
- exit (1);
- }
- else /* Right number of arguments. Lets go! */
- {
- /* Open ARP library V39+ */
-
- if (!(ArpBase = (struct ArpBase *) OpenLibrary ("arp.library",39L)))
- {
- printf ("\n\033[33mQDCopy Error: ARP library V39+ required\033[31m\n\n");
- exit (10);
- }
- /* Make a 'to read' file list */
-
- /* Get memory for anchor path structure including */
- /* a MaxPathNameSize full path name buffer */
-
- if (!(anchorpath = DosAllocMem (sizeof (struct AnchorPath) + MaxPathNameSize)))
- {
- printf ("\n\033[33mQDCopy Error: Cannot allocate memory for AnchorPath\033[31m\n\n");
- CloseLibrary (ArpBase);
- exit (10);
- }
-
- /* Initialize anchorpath structure */
-
- anchorpath->ap_BreakBits = 0; /* Not equipped to handle break */
- anchorpath->ap_StrLen = MaxPathNameSize; /* Handle full path names */
- anchorpath->ap_Flags = 0; /* Don't use special features */
-
- /* Initial destination is specified by user */
- /* This might change later when disk error or disk full */
-
- strcpy (destpath, argv[2]);
-
- /* Prompt for source disk */
-
- /* If source pattern is relative to current directory, don't */
- /* bother to prompt for the source disk since its already in use */
- /* or if it isn't, the system knows where it is and can prompt */
- /* for it itself. */
-
- if (isfullname (argv[1]))
- {
- printf ("\nInsert SOURCE and press RETURN\n");
- inputlength = ReadLine (inputline);
- }
- /* Start FindFirst */
-
- if (!(breaksignal = taskbreak()))
- {
- errorcode = FindFirst (argv[1], anchorpath);
-
- /* Continue searching until an error, break, or no files left */
-
- while ((!errorcode) && (!breaksignal))
- {
- /* Fill in a QDFileChain block */
-
- if (fileptr1 = DosAllocMem (sizeof (struct QDFileChain)))
- {
- if (anchorpath->ap_Info.fib_DirEntryType < 0)
- {
- /* Its a file so add it to the list */
-
- fileptr1->Next = NULL;
- fileptr1->FileBuffer = NULL;
- strcpy (fileptr1->FileName, anchorpath->ap_Buf);
- fileptr1->Protection = anchorpath->ap_Info.fib_Protection;
- fileptr1->Size = anchorpath->ap_Info.fib_Size;
- strcpy (fileptr1->Comment, anchorpath->ap_Info.fib_Comment);
-
- /* If this is the first, set the head of the list here */
-
- if (!filehead)
- {
- filehead = fileptr1;
- }
- else
-
- /* Link previous item in chain to new header */
- {
- fileptr2->Next = fileptr1;
- }
- /* Now make this pointer the previous pointer */
-
- fileptr2 = fileptr1;
- }
- else
- {
- /* Hey! This isn't a file! Don't put it in list */
-
- DosFreeMem (fileptr1);
- }
- }
- else
- {
- /* System is in sorry state if there is no memory for the */
- /* file structure. Free memory and leave */
-
- printf ("\n\033[33mQDCopy Error: Cannot allocate memory for filename storage\033[31m\n\n");
- FreeAnchorChain (anchorpath);
- DosFreeMem (anchorpath);
- cleanupchain (filehead);
- CloseLibrary (ArpBase);
- exit (10);
- }
- /* Get ready for next file name */
-
- breaksignal = taskbreak();
- errorcode = FindNext (anchorpath);
- }
- /* Now all wildcard files are accounted for */
-
- /* Nuke the structures required by ARP */
-
- FreeAnchorChain (anchorpath);
- }
-
- DosFreeMem (anchorpath);
-
- /* Now read in the files */
-
- while ((filehead) && (!breaksignal)) /* While there are more files to read */
- {
- /* Set up for a new batch read cycle */
-
- /* Prompt for source disk if it was not a relative directory */
- /* Otherwise, the system knows where it is and will prompt itself */
-
- if (memfull && isfullname(argv[1]))
- {
- printf ("\nInsert SOURCE and press RETURN\n");
- inputlength = ReadLine (inputline);
- }
- memfull = FALSE;
- fileptr1 = filehead;
-
- /* Batch read files until no files left or memory full */
-
- while ((fileptr1) && (!memfull) && (!(breaksignal = taskbreak())))
- {
- /* If the file is not empty then copy it */
-
- if (fileptr1->Size > 0)
- {
- /* Get memory for buffer */
-
- if (fileptr1->FileBuffer = DosAllocMem (fileptr1->Size))
- {
- /* Read file */
-
- if (filehandle = Open (fileptr1->FileName, MODE_OLDFILE))
- {
- printf ("Reading %s\n", fileptr1->FileName);
-
- /* Read the file into the buffer */
-
- len = Read (filehandle, fileptr1->FileBuffer, fileptr1->Size);
- Close (filehandle);
- if (len != fileptr1->Size)
- {
- /* File changed before reading */
- /* Clear it from the buffer and ignore it */
-
- warncode = 5;
- printf ("\033[33m%s not read: File changed since tested\033[31m\n", fileptr1->FileName);
- DosFreeMem (fileptr1->FileBuffer);
- fileptr1->FileBuffer = NULL;
- }
- }
- else
- {
- /* File was deleted before reading */
- /* or cannot be opened. Ignore it */
-
- warncode = 5;
- errorcode = IoErr();
- printf ("\033[33m%s not read: Error %d opening file\033[31m\n",fileptr1->FileName, errorcode);
- DosFreeMem (fileptr1->FileBuffer);
- fileptr1->FileBuffer = NULL;
- }
- /* No matter what happened during opening or */
- /* reading, go on to next file */
- fileptr1 = fileptr1->Next;
- }
- else
- {
- /* Out of memory */
-
- if (fileptr1 == filehead)
- {
- /* First file this pass and still too big */
- /* So skip it */
-
- warncode = 5;
- printf ("\033[33m%s not read: File too big for memory\033[31m\n", fileptr1->FileName);
- fileptr1 = fileptr1->Next;
- }
- else
- {
- /* This is not the first file this pass, so */
- /* start writing and come back to this */
- /* file on the next pass */
-
- memfull = TRUE;
- }
- }
- }
- else /* File size is zero. Skip it. */
- {
- printf ("\033[33m%s not read: Blank file\033[31m\n",fileptr1->FileName);
- fileptr1 = fileptr1->Next;
- }
- }
-
- /* Now batch write the buffered files to destination */
-
- /* Reset file pointer to first in memory */
-
- fileptr2 = filehead;
-
- /* If destination path is relative to current directory, don't */
- /* bother to prompt for the destination disk since its already */
- /* in use, or if not, the system knows where it is */
-
- if (isfullname (destpath))
- {
- newdest = TRUE; /* Drive specified, ask for disk */
- }
- else
- {
- newdest = FALSE; /* Don't need to ask for disk */
- }
- while ((fileptr2 != fileptr1) && (!breaksignal))
- {
- if (fileptr2->FileBuffer != NULL)
- {
- if (newdest)
- {
- printf ("\nInsert DESTINATION and press RETURN or type new destination path\n");
- inputlength = ReadLine (inputline);
-
- /* If user typed something, use it for new path */
-
- if (inputlength > 1) /* Anything input? */
- {
- strcpy (destpath, inputline);
- }
- }
- if (!(breaksignal = taskbreak()))
- {
- newdest = FALSE;
-
- /* Create destination file name */
-
- strcpy (pathname, destpath);
- basename = BaseName (fileptr2->FileName);
- TackOn (pathname, basename);
-
- if (filehandle = Open (pathname, MODE_NEWFILE))
- {
- /* Write out the destination file */
-
- printf ("Writing %s\n", pathname);
- len = Write (filehandle, fileptr2->FileBuffer, fileptr2->Size);
- errorcode = IoErr();
- Close (filehandle);
- if (len != fileptr2->Size)
- {
- /* Error writing file */
-
- /* Try to delete file */
-
- if (errorcode != ERROR_DISK_FULL)
- {
- printf ("\033[33mError %d writing %s:", errorcode, pathname);
- }
- else
- {
- printf ("\033[33mDisk full writing %s:", pathname);
- }
- if (DeleteFile (pathname))
- {
- printf (" Incomplete file deleted\033[31m\n");
- }
- else
- {
- printf (" Incomplete file not deleted\033[31m\n");
- }
-
- newdest = TRUE;
- }
- else
- {
- /* Successful write */
-
- /* Set protection bits */
-
- if (!(SetProtection (pathname, fileptr2->Protection)))
- {
- warncode = 5;
- printf ("\033[33m%s protection bits not set\033[31m\n", pathname);
- }
- /* Set file comment */
-
- if (!(SetComment (pathname, fileptr2->Comment)))
- {
- warncode = 5;
- printf ("\033[33m%s comment not set\033[31m\n", pathname);
- }
- /* Free current file, go to next file */
-
- DosFreeMem (fileptr2->FileBuffer);
- fileptr2 = fileptr2->Next;
- DosFreeMem (filehead);
- filehead = fileptr2;
- }
- }
- else
- {
- /* Could not open file */
-
- /* Could be write protected disk, etc. */
-
- errorcode = IoErr();
- newdest = TRUE;
-
- printf ("\033[33mError %d writing %s: Cannot open file\033[31m\n", errorcode, pathname);
- }
- }
- /* above if not break */
- }
- else
- {
- /* File is empty or could not be read earlier */
- /* Just skip it */
-
- fileptr2 = fileptr2->Next;
- DosFreeMem (filehead);
- filehead = fileptr2;
- }
- }
- }
- cleanupchain (filehead);
-
- if (breaksignal)
- {
- warncode = 6;
- }
-
- if (warncode)
- {
- printf ("\nQDCopy: Copy not completely successful\n\n");
- }
- else
- {
- printf ("\nQDCopy: Copy successful\n\n");
- }
- CloseLibrary (ArpBase);
- exit (warncode);
- }
- }
-