home *** CD-ROM | disk | FTP | other *** search
- #define NAME "Copy"
- #define REVISION "15"
- #define DISTRIBUTION "(Freeware) "
- //#define DEBUG
-
- /* Programmheader
-
- Name: Copy
- Author: SDI
- Distribution: Freeware
- Description: copies, moves, deletes and links files
- Compileropts: -
- Linkeropts: -gsi -l amiga
-
- 1.0 02.08.97 : first version, only raw source
- 1.1 06.08.97 : added more stuff
- 1.2 08.08.97 : completed option description, added new code
- 1.3 09.08.97 : and more stuff done and SILENT option
- 1.4 11.08.97 : fixed problem with DELETE and ExNext function
- 1.5 14.08.97 : fixed DoWork, added new stuff
- 1.6 17.08.97 : added more functions, program is near completion
- 1.7 24.08.97 : bug fixes in DoWork function
- 1.8 25.09.97 : included missing functions, started debugging
- 1.9 26.09.97 : debugging, source cleanup
- 1.10 28.09.97 : and still debugging
- 1.11 30.09.97 : fixed some errors
- 1.12 04.10.97 : Added FORCE Option
- 1.13 19.12.97 : added DIRECT option
- 1.14 20.04.98 : with DIRECT now all softlinks can be deleted (Thanks to
- Magnus Holmgren for reporting this)
- 1.15 06.05.98 : added automatic DIRECT detection with IsFileSystem
- */
-
- #include <proto/dos.h>
- #include <proto/exec.h>
- #include <exec/memory.h>
- #include "SDI_defines.h"
- #define SDI_TO_ANSI
- #include "SDI_ASM_STD_protos.h"
-
- #define PARAM "FROM/M,TO,PAT=PATTERN/K,BUF=BUFFER/K/N,ALL/S," \
- "DIRECT/S,CLONE/S,DATES/S,NOPRO/S,COM=COMMENT/S," \
- "QUIET/S,SILENT/S,NOREQ/S,ERRWARN/S,MAKEDIR/S," \
- "MOVE/S,DELETE/S,HARD=HARDLINK/S,SOFT=SOFTLINK/S," \
- "FOLNK=FORCELINK/S,FODEL=FORCEDELETE/S," \
- "FOOVR=FORCEOVERWRITE/S,DONTOVR=DONTOVERWRITE/S," \
- "FORCE/S"
-
- #define COPYFLAG_ALL (1<<0)
- #define COPYFLAG_DATES (1<<1)
- #define COPYFLAG_NOPRO (1<<2)
- #define COPYFLAG_COMMENT (1<<3)
- #define COPYFLAG_FORCELINK (1<<4)
- #define COPYFLAG_FORCEDELETE (1<<5)
- #define COPYFLAG_FORCEOVERWRITE (1<<6)
- #define COPYFLAG_DONTOVERWRITE (1<<7)
- #define COPYFLAG_QUIET (1<<8)
- #define COPYFLAG_SILENT (1<<9)
- #define COPYFLAG_ERRWARN (1<<10)
-
- #define COPYFLAG_SOFTLINK (1<<20) /* produce softlinks */
- #define COPYFLAG_DEST_FILE (1<<21) /* one file mode */
- #define COPYFLAG_DONE (1<<22) /* did something in DoWork */
- #define COPYFLAG_ENTERSECOND (1<<23) /* entered directory second time */
-
- #define COPYFLAG_SRCNOFILESYS (1<<24) /* source is no filesystem */
- #define COPYFLAG_DESNOFILESYS (1<<25) /* destination is no filesystem */
-
- #define COPYMODE_COPY 0
- #define COPYMODE_MOVE 1
- #define COPYMODE_DELETE 2
- #define COPYMODE_MAKEDIR 3
- #define COPYMODE_LINK 4
-
- #define PRINTOUT_SIZE 50 /* maximum size of name printout */
- #define PRINTOUT_SPACES 10 /* maximum number of spaces */
-
- #define FILEPATH_SIZE 300 /* maximum size of filepaths */
-
- /* return values */
- #define TESTDEST_DIR_OK 2 /* directory exists, go in */
- #define TESTDEST_DELETED 1 /* file or empty directory deleted */
- #define TESTDEST_NONE 0 /* nothing existed */
- #define TESTDEST_ERROR -1 /* an error occured */
- #define TESTDEST_CANTDELETE -2 /* deletion not allowed (DONTOV) */
-
- struct Args {
- STRPTR * from;
- STRPTR to;
- STRPTR pattern;
- LONG * buffer;
- LONG all;
- LONG direct;
- LONG clone;
- LONG dates;
- LONG nopro;
- LONG comment;
- LONG quiet;
- LONG silent;
- LONG noreq;
- LONG errwarn;
- LONG makedir;
- LONG move_mode;
- LONG delete_mode;
- LONG hardlink;
- LONG softlink;
- LONG forcelink;
- LONG forcedelete;
- LONG forceoverwrite;
- LONG dontoverwrite;
- LONG force;
- };
-
- struct CopyData {
- ULONG Flags;
- ULONG BufferSize;
- STRPTR Pattern;
- ULONG Destination;
- ULONG CurDest; /* Current Destination */
- ULONG DestPathSize;
- struct FileInfoBlock *Fib;
- UBYTE Mode;
- UBYTE RetVal; /* when set, error output is already done */
- UBYTE RetVal2; /* when set, error output must be done */
- UBYTE Deep;
- UBYTE FileName[FILEPATH_SIZE];
- UBYTE DestName[FILEPATH_SIZE];
- };
-
- #define TEXT_READ texts[0]
- #define TEXT_COPIED texts[1]
- #define TEXT_MOVED texts[2]
- #define TEXT_DELETED texts[3]
- #define TEXT_LINKED texts[4]
- #define TEXT_RENAMED texts[5]
- #define TEXT_CREATED texts[6]
- #define TEXT_ENTERED texts[7]
- #define TEXT_OPENED_FOR_OUTPUT texts[8]
- #define TEXTNUM_MODE 9
- #define TEXT_DIRECTORY texts[15]
- #define TEXT_NOT_DONE texts[16]
- #define TEXT_NOTHING_DONE texts[17]
- #define TEXT_ERR_FORCELINK texts[18]
- #define TEXT_ERR_DELETE_DEVICE texts[19]
- #define TEXT_ERR_DEST_DIR texts[20]
- #define TEXT_ERR_INFINITE_LOOP texts[21]
- #define TEXT_ERR_WILDCARD_DEST texts[22]
-
- STRPTR texts[] =
- {
- "read",
- "copied",
- "moved",
- "deleted",
- "linked",
- "renamed",
- "created",
- "entered",
- "opened for output",
- "COPY mode\n",
- "MOVE mode\n",
- "DELETE mode\n",
- "MAKEDIR mode\n",
- "HARDLINK mode\n",
- "SOFTLINK mode\n",
- "%s <Dir>", /* output of directories */
- "not %s: ",
- "No file was processed.\n",
- "FORCELINK keyword required.\n",
- "A device cannot be deleted.",
- "Destination must be a directory.\n",
- "Infinite loop not allowed.\n",
- "Wildcard destination invalid.\n",
- };
-
- LONG CopyFile(ULONG, ULONG, ULONG);
- void DoWork(STRPTR, struct CopyData *);
- LONG IsPattern(STRPTR); /* return 0 -> NOPATTERN, return -1 --> ERROR */
- LONG KillFile(STRPTR, ULONG);
- LONG LinkFile(ULONG, STRPTR, ULONG);
- ULONG OpenDestDir(STRPTR, struct CopyData *);
- void PatCopy(STRPTR, struct CopyData *);
- void PrintName(STRPTR, ULONG, ULONG, ULONG);
- void PrintNotDone(STRPTR, STRPTR, ULONG, ULONG);
- ULONG TestFileSys(STRPTR); /* returns value, when is a filesystem */
- void SetData(STRPTR, struct CopyData *);
- LONG TestDest(STRPTR, ULONG, struct CopyData *);
- ULONG TestLoop(ULONG, ULONG);
-
- struct DosLibrary *DOSBase;
-
- ULONG start(void)
- {
- struct Process *task;
- struct DosLibrary *dosbase;
- struct CopyData cd;
-
- /* test for WB and reply startup-message */
- if(!(task = (struct Process *) FindTask(0))->pr_CLI)
- {
- WaitPort(&task->pr_MsgPort);
- Forbid();
- ReplyMsg(GetMsg(&task->pr_MsgPort));
- return RETURN_FAIL;
- }
-
- memset(&cd, 0, sizeof(struct CopyData));
- cd.BufferSize = 102400;
- cd.Mode = COPYMODE_COPY;
- cd.RetVal2 = RETURN_FAIL;
- cd.Deep = 1;
-
- if((dosbase = (struct DosLibrary *) OpenLibrary("dos.library", 37)))
- {
- STRPTR a[2] = {"", 0};
- struct RDArgs *rda;
- struct Args args;
-
- DOSBase = dosbase;
-
- memset(&args, 0, sizeof(struct Args));
-
- if((rda = (struct RDArgs *) AllocDosObject(DOS_RDARGS, 0)))
- {
- rda->RDA_ExtHelp =
- "FROM multiple input files\n"
- "TO destination file or directory\n"
- "PATTERN a pattern the filenames must match\n"
- "BUFFER buffersize for copy buffer (default 200 [100K])\n"
- "ALL deep scan into sub directories\n"
- "DIRECT copy/delete only: work without any tests or options\n"
- "CLONE copy comment, protection bits and date as well\n"
- "DATES copy dates\n"
- "NOPRO do not copy protection bits\n"
- "COMMENT copy filecomment\n"
- "QUIET suppress all output and requesters\n"
- "SILENT suppress output, but not errors and requesters\n"
- "NOREQ suppress requesters\n"
- "ERRWARN do not proceed, when one file failed\n"
- "MAKEDIR produce directories\n"
- "MOVE delete source files after copying successful\n"
- "DELETE do not copy, but delete the source files\n"
- "HARDLINK make a hardlink to source instead of copying\n"
- "SOFTLINK make a softlink to source instead of copying\n"
- "FOLNK also makes links to directories\n"
- "FODEL delete protected files also\n"
- "FOOVR also overwrite protected files\n"
- "DONTOVR do never overwrite destination\n"
- "FORCE DO NOT USE. Call compatibility only.\n";
-
- if(ReadArgs(PARAM, (LONG *) &args, rda))
- {
- ULONG patbufsize = 0;
- LONG i = 0;
- APTR win = task->pr_WindowPtr;
-
- if(args.quiet) /* when QUIET, SILENT and NOREQ are also true! */
- args.silent = args.noreq = 1;
-
- if(args.buffer && *args.buffer > 0) /* minimum buffer size */
- cd.BufferSize = *args.buffer * 512;
-
- if(args.quiet) cd.Flags |= COPYFLAG_QUIET;
- if(args.silent) cd.Flags |= COPYFLAG_SILENT;
- if(args.all) cd.Flags |= COPYFLAG_ALL;
- if(args.clone) cd.Flags |= COPYFLAG_DATES|COPYFLAG_COMMENT;
- if(args.dates) cd.Flags |= COPYFLAG_DATES;
- if(args.comment) cd.Flags |= COPYFLAG_COMMENT;
- if(args.nopro) cd.Flags |= COPYFLAG_NOPRO;
- if(args.forcelink) cd.Flags |= COPYFLAG_FORCELINK;
- if(args.forcedelete) cd.Flags |= COPYFLAG_FORCEDELETE;
- if(args.forceoverwrite) cd.Flags |= COPYFLAG_FORCEOVERWRITE;
- if(args.dontoverwrite) cd.Flags |= COPYFLAG_DONTOVERWRITE;
- if(args.errwarn) cd.Flags |= COPYFLAG_ERRWARN;
-
- if(args.force) /* support OS Delete and MakeLink command options */
- {
- if(args.delete_mode)
- cd.Flags |= COPYFLAG_FORCEDELETE;
- if(args.hardlink || args.softlink)
- cd.Flags |= COPYFLAG_FORCELINK;
- }
-
- if(!args.from) /* no args.from means currentdir */
- args.from = a;
-
- if(args.noreq) /* no dos.library requests allowed */
- task->pr_WindowPtr = (APTR) -1;
-
- if(args.delete_mode) { ++i; cd.Mode = COPYMODE_DELETE; }
- if(args.move_mode) { ++i; cd.Mode = COPYMODE_MOVE; }
- if(args.makedir) { ++i; cd.Mode = COPYMODE_MAKEDIR; }
- if(args.hardlink) { ++i; cd.Mode = COPYMODE_LINK; }
- if(args.softlink)
- {
- ++i;
- cd.Mode = COPYMODE_LINK;
- cd.Flags |= COPYFLAG_SOFTLINK|COPYFLAG_FORCELINK;
- }
-
- if(cd.Mode != COPYMODE_DELETE && cd.Mode != COPYMODE_MAKEDIR &&
- !args.to)
- {
- if(*(args.from+1)) /* when no TO is specified, the arg is last */
- { /* one of from. Copy this argument into */
- STRPTR *a; /* args.to */
-
- a = args.from;
- while(*(++a))
- ;
- args.to = *(--a); *a = 0;
- }
- }
-
- /* test if more than one of the above four or any other wrong
- arguments */
-
- if(i > 1 ||
- (args.from == a && cd.Mode == COPYMODE_MAKEDIR) ||
- (args.direct && (args.from == a || !*args.from || cd.Pattern ||
- (cd.Flags & ~(COPYFLAG_QUIET|COPYFLAG_SILENT|COPYFLAG_ERRWARN)) ||
- (cd.Mode != COPYMODE_DELETE && (cd.Mode != COPYMODE_COPY ||
- !args.to || args.from[1])))) ||
- (args.dontoverwrite && args.forceoverwrite) ||
- (args.nopro && args.clone) ||
- (args.softlink && args.all) ||
- (!args.to && cd.Mode != COPYMODE_DELETE && cd.Mode != COPYMODE_MAKEDIR))
- SetIoErr(ERROR_TOO_MANY_ARGS);
- else if(cd.Mode == COPYMODE_MAKEDIR)
- {
- ULONG i;
- cd.RetVal2 = RETURN_OK;
-
- if(!args.silent)
- Printf(texts[TEXTNUM_MODE+COPYMODE_MAKEDIR]);
-
- while(!cd.RetVal && !cd.RetVal2 && *args.from)
- {
- if((i = IsPattern(*args.from)))
- {
- if(i != -1)
- {
- cd.RetVal = RETURN_ERROR;
- if(!args.quiet)
- Printf(TEXT_ERR_WILDCARD_DEST);
- }
- else
- cd.RetVal2 = RETURN_FAIL;
- }
- if((i = OpenDestDir(*args.from, &cd)))
- {
- UnLock(i);
- cd.Flags |= COPYFLAG_DONE;
- }
- ++args.from;
- }
- } /* cd.Mode == COPYMODE_MAKEDIR */
- else if(args.direct)
- {
- if(cd.Mode == COPYMODE_COPY)
- {
- ULONG in, out;
-
- if((in = Open(*args.from, MODE_OLDFILE)))
- {
- if((out = Open(args.to, MODE_NEWFILE)))
- {
- cd.RetVal2 = CopyFile(in, out, cd.BufferSize);
- Close(out);
- }
- Close(in);
- }
- }
- else /* COPYMODE_DELETE */
- {
- while(*args.from)
- KillFile(*(args.from++), cd.Flags & COPYFLAG_FORCEDELETE);
- cd.RetVal2 = RETURN_OK;
- }
- }
- else
- {
- if(args.pattern && *args.pattern)
- {
- patbufsize = (SDI_strlen(args.pattern)<<1) + 1;
- if((cd.Pattern = (STRPTR) AllocMem(patbufsize, MEMF_PUBLIC)))
- {
- if(ParsePattern(args.pattern, cd.Pattern, patbufsize) < 0)
- {
- FreeMem(cd.Pattern, patbufsize); cd.Pattern = 0;
- }
- }
- }
-
- if((cd.Fib = (struct FileInfoBlock *) AllocDosObject(DOS_FIB, 0)))
- {
- if(!args.silent)
- Printf(texts[TEXTNUM_MODE+cd.Mode+
- (cd.Flags & COPYFLAG_SOFTLINK ? 1 : 0)]);
-
- if(args.pattern && !cd.Pattern)
- {
- if(!*args.pattern)
- SetIoErr(ERROR_BAD_TEMPLATE);
- }
- else if(cd.Mode == COPYMODE_DELETE)
- {
- cd.RetVal2 = RETURN_OK;
-
- while(cd.RetVal <= (args.errwarn ? RETURN_OK : RETURN_WARN)
- && *args.from)
- PatCopy(*(args.from++), &cd);
-
- }
- else if((i = IsPattern(args.to)))
- {
- if(i != -1)
- {
- cd.RetVal = RETURN_ERROR;
- if(!args.quiet)
- Printf(TEXT_ERR_WILDCARD_DEST);
- }
- }
- else
- {
- STRPTR path;
-
- if(*(path = PathPart(args.to)) == '/')
- ++path; /* is destination a path description ? */
-
- if(*path && !*(args.from+1) && !(i = IsPattern(*args.from)))
- {
- ULONG lock;
-
- /* is destination an existing directory */
- if((lock = Lock(args.to, SHARED_LOCK)))
- {
- if(Examine(lock, cd.Fib))
- {
- if(cd.Fib->fib_DirEntryType > 0)
- cd.RetVal2 = RETURN_OK;
- /* indicate dir-mode for next if */
- }
- else
- i = 1;
- UnLock(lock);
- }
-
- /* is source a directory */
- if(!i && cd.RetVal2 && (lock = Lock(*args.from, SHARED_LOCK)))
- {
- if(Examine(lock, cd.Fib))
- {
- cd.RetVal2 = RETURN_OK;
- if(cd.Mode != COPYMODE_COPY ||
- cd.Fib->fib_DirEntryType < 0)
- {
- UBYTE sep;
-
- cd.Flags |= COPYFLAG_DEST_FILE;
- /* produce missing destination directories */
- sep = *path; *path = 0;
- if((cd.CurDest = OpenDestDir(args.to, &cd)))
- {
- *path = sep;
- /* do the job */
- UnLock(lock); lock = 0;
- CopyMem(*args.from, cd.FileName, 1+strlen(*args.from));
- DoWork(FilePart(args.to), &cd); /* on file call */
- UnLock(cd.CurDest);
- }
- }
- }
- if(lock)
- UnLock(lock);
- }
- else if(cd.Mode == COPYMODE_COPY && !TestFileSys(*args.from))
- {
- UBYTE sep;
- cd.Flags |= COPYFLAG_DEST_FILE|COPYFLAG_SRCNOFILESYS;
- cd.RetVal2 = RETURN_OK;
- /* produce missing destination directories */
- sep = *path; *path = 0;
- if((cd.CurDest = OpenDestDir(args.to, &cd)))
- {
- *path = sep;
- /* do the job */
- CopyMem(*args.from, cd.FileName, 1+strlen(*args.from));
- DoWork(FilePart(args.to), &cd); /* on file call */
- UnLock(cd.CurDest);
- }
- }
- }
- else if(i != -1)
- cd.RetVal2 = RETURN_OK;
-
- if(!cd.RetVal && !cd.RetVal2 && !(cd.Flags &
- COPYFLAG_DEST_FILE) && (cd.Destination =
- OpenDestDir(args.to, &cd)))
- {
- while(cd.RetVal <= (args.errwarn ? RETURN_OK : RETURN_WARN)
- && *args.from && !CTRL_C)
- PatCopy(*(args.from++), &cd);
-
- UnLock(cd.Destination);
- }
- } /* else */
-
- if(!(cd.Flags & COPYFLAG_DONE) && !args.silent && !cd.RetVal
- && !cd.RetVal2)
- Printf(TEXT_NOTHING_DONE);
-
- FreeDosObject(DOS_FIB, cd.Fib);
- } /* if((cd.Fib = ... )) */
-
- if(cd.Pattern)
- FreeMem(cd.Pattern, patbufsize);
- } /* else */
-
- task->pr_WindowPtr = win;
-
- FreeArgs(rda);
- } /* ReadArgs */
- FreeDosObject(DOS_RDARGS, rda);
- } /* AllocDosObject */
-
- if(!cd.RetVal2 && CTRL_C)
- {
- SetIoErr(ERROR_BREAK);
- cd.RetVal2 = RETURN_WARN;
- }
-
- if(cd.RetVal2 && !args.quiet && !cd.RetVal)
- PrintFault(IoErr(),0);
-
- if(cd.RetVal)
- cd.RetVal2 = cd.RetVal;
-
- CloseLibrary((struct Library *) dosbase);
-
- if(args.errwarn && cd.RetVal2 == RETURN_WARN)
- cd.RetVal2 = RETURN_ERROR;
- }
-
- return cd.RetVal2;
- }
-
- void PatCopy(STRPTR name, struct CopyData *cd)
- {
- struct AnchorPath *APath;
- ULONG retval, doit = 0, deep = 0, failval = RETURN_WARN, first = 0;
-
- #ifdef DEBUG
- Printf("PatCopy(%s, .)\n", name);
- #endif
-
- if((cd->Mode == COPYMODE_COPY || (cd->Flags & COPYFLAG_ALL)) &&
- !IsPattern(name))
- first = 1; /* enter first directory (support of old copy style) */
-
- if(cd->Flags & COPYFLAG_ERRWARN)
- failval = RETURN_OK;
-
- cd->CurDest = cd->Destination;
- cd->DestPathSize = 0;
-
- if(cd->Mode == COPYMODE_COPY && !TestFileSys(name))
- {
- cd->Flags |= COPYFLAG_SRCNOFILESYS;
- CopyMem(name, cd->FileName, 1+strlen(name));
- DoWork(FilePart(name), cd);
- cd->Flags &= ~COPYFLAG_SRCNOFILESYS;
- return;
- }
-
- if((APath = (struct AnchorPath *) AllocMem(sizeof(struct AnchorPath) + FILEPATH_SIZE,
- MEMF_PUBLIC|MEMF_CLEAR)))
- {
- APath->ap_BreakBits = SIGBREAKF_CTRL_C;
- APath->ap_Strlen = FILEPATH_SIZE;
-
- for(retval = MatchFirst(name, APath); !retval && cd->RetVal <=
- failval && !cd->RetVal2; retval = MatchNext(APath))
- {
- if(doit)
- {
- DoWork(cd->Fib->fib_FileName, cd); doit = 0;
- }
-
- if(deep) /* used for Deep checking */
- {
- ++cd->Deep; deep = 0;
- }
-
- cd->Flags &= ~COPYFLAG_ENTERSECOND;
-
- CopyMem(APath->ap_Buf, cd->FileName, FILEPATH_SIZE);
- CopyMem(&APath->ap_Info, cd->Fib, sizeof(struct FileInfoBlock));
-
- if(first && APath->ap_Info.fib_DirEntryType > 0)
- APath->ap_Flags |= APF_DODIR;
- else if(APath->ap_Flags & APF_DIDDIR)
- {
- ULONG i;
- cd->Flags |= COPYFLAG_ENTERSECOND;
- APath->ap_Flags &= ~APF_DIDDIR;
- --cd->Deep;
- if(cd->Mode == COPYMODE_DELETE || cd->Mode == COPYMODE_MOVE)
- doit = 1;
- if((i = cd->CurDest))
- {
- cd->CurDest = ParentDir(i);
- cd->DestPathSize = 0;
- if(i != cd->Destination)
- UnLock(i);
- if(!cd->CurDest)
- break;
- }
- }
- else if(APath->ap_Info.fib_DirEntryType > 0)
- {
- doit = 1;
- if(cd->Flags & COPYFLAG_ALL)
- {
- APath->ap_Flags |= APF_DODIR;
- deep = 1;
- }
- }
- else if(!cd->Pattern || MatchPatternNoCase(cd->Pattern,
- APath->ap_Info.fib_FileName))
- doit = 1;
- first = 0;
- }
- MatchEnd(APath);
-
- if(retval != ERROR_NO_MORE_ENTRIES)
- cd->RetVal2 = RETURN_FAIL;
-
- if(doit)
- DoWork(cd->Fib->fib_FileName, cd);
-
- /* No need to clear the flags here, as they are cleared on next PatJoin
- call (DoWork is not called first round, as lock is zero!). */
-
- FreeMem(APath, sizeof(struct AnchorPath) + FILEPATH_SIZE);
- }
- else
- {
- cd->RetVal = RETURN_FAIL;
- if(!cd->Flags & COPYFLAG_QUIET)
- PrintFault(ERROR_NO_FREE_STORE, 0);
- }
-
- if(cd->CurDest && cd->CurDest != cd->Destination)
- UnLock(cd->CurDest);
- }
-
- LONG IsPattern(STRPTR name)
- {
- LONG a, ret = -1;
- STRPTR buffer;
-
- a = (strlen(name)<<1) + 10;
-
- if((buffer = (STRPTR) AllocMem(a, MEMF_ANY)))
- {
- ret = ParsePattern(name, buffer, a);
- FreeMem(buffer, a);
- }
-
- if(ret == -1)
- SetIoErr(ERROR_NO_FREE_STORE);
-
- return ret;
- }
-
- LONG KillFile(STRPTR name, ULONG doit)
- {
- if(doit)
- SetProtection(name, 0);
- return DeleteFile(name);
- }
-
- ULONG OpenDestDir(STRPTR name, struct CopyData *cd)
- {
- LONG a, err = 0, cr = 0;
- STRPTR ptr = name;
- UBYTE as;
-
- if((cd->Mode == COPYMODE_COPY || cd->Mode == COPYMODE_MOVE) &&
- !TestFileSys(name))
- {
- cd->Flags |= COPYFLAG_DESNOFILESYS;
- CopyMem(name, cd->DestName, 1+strlen(name));
- return (ULONG) Lock("", SHARED_LOCK);
- }
-
- while(!err && *ptr != 0)
- {
- while(*ptr && *ptr != '/')
- ++ptr;
- as = *ptr;
- *ptr = 0;
-
- if((a = TestDest(name, 1, cd)) == TESTDEST_CANTDELETE)
- {
- if(!(cd->Flags & COPYFLAG_QUIET))
- Printf(TEXT_ERR_DEST_DIR);
- err = 2;
- }
- else if(a < 0)
- err = 1;
- else if(a != TESTDEST_DIR_OK)
- {
- if((a = CreateDir(name)))
- {
- ++cr;
- if(!(cd->Flags & COPYFLAG_SILENT))
- {
- PrintName(name, 1, 1, 1);
- Printf("%s\n", TEXT_CREATED);
- }
- UnLock(a);
- }
- else
- {
- if(!(cd->Flags & COPYFLAG_QUIET))
- PrintNotDone(name, TEXT_CREATED, 1, 1);
- err = 2;
- }
- }
-
- *(ptr++) = as;
- }
-
- if(err)
- {
- cd->RetVal = RETURN_ERROR;
-
- if(!(cd->Flags & COPYFLAG_QUIET) && err == 1)
- PrintNotDone(name, TEXT_OPENED_FOR_OUTPUT, 1, 1);
- return 0;
- }
-
- if(cd->Mode == COPYMODE_MAKEDIR && !cr && !(cd->Flags & COPYFLAG_QUIET))
- {
- SetIoErr(ERROR_OBJECT_EXISTS);
- PrintNotDone(name, TEXT_CREATED, 1, 1);
- }
-
- return (ULONG) Lock(name, SHARED_LOCK);
- }
-
- void PrintName(STRPTR name, ULONG deep, ULONG dir, ULONG txt)
- {
- deep %= PRINTOUT_SPACES; /* reduce number of spaces */
- /* This produces an error with MaxonC++ */
-
- while(deep--)
- Printf(" ");
-
- if((deep = strlen(name)) > PRINTOUT_SIZE) /* reduce name size */
- {
- name += deep-PRINTOUT_SIZE;
- Printf("...");
- }
-
- Printf((dir ? TEXT_DIRECTORY : "%s"), name);
- if(txt)
- Printf(" ..");
- Flush(Output());
- }
-
- void PrintNotDone(STRPTR name, STRPTR txt, ULONG deep, ULONG dir)
- {
- if(name)
- PrintName(name, deep, dir, 1);
- Printf(TEXT_NOT_DONE, txt);
- PrintFault(IoErr(),0);
- }
-
- /* returns value, when it seems to be a filesystem */
- ULONG TestFileSys(STRPTR name)
- {
- STRPTR n = name;
- ULONG ret = 1;
-
- while(*n && *n != ':')
- ++n;
-
- if(*(n++) == ':')
- {
- UBYTE a;
-
- a = *n; *n = 0;
- ret = IsFileSystem(name);
- *n = a;
- }
- return ret;
- }
-
- void DoWork(STRPTR name, struct CopyData *cd)
- {
- ULONG pdir, lock = 0;
- STRPTR printerr = 0, printok = "";
-
- #ifdef DEBUG
- Printf("DoWork(%s, .)\n", name);
- #endif
-
- if(cd->RetVal > (cd->Flags & COPYFLAG_ERRWARN ? RETURN_OK : RETURN_WARN)
- || cd->RetVal2)
- return;
-
- if(cd->Mode != COPYMODE_DELETE && !(cd->Flags & COPYFLAG_DESNOFILESYS))
- {
- if(!cd->DestPathSize)
- {
- if(!NameFromLock(cd->CurDest, cd->DestName, FILEPATH_SIZE))
- {
- cd->RetVal2 = RETURN_FAIL;
- UnLock(lock);
- return;
- }
- cd->DestPathSize = strlen(cd->DestName);
- }
- cd->DestName[cd->DestPathSize] = 0;
- AddPart(cd->DestName, name, FILEPATH_SIZE);
- }
-
- if(cd->Flags & (COPYFLAG_SRCNOFILESYS|COPYFLAG_DESNOFILESYS))
- {
- ULONG in, out, res = 0, kill = 1;
- STRPTR txt = TEXT_OPENED_FOR_OUTPUT;
-
- #ifdef DEBUG
- Printf("Partly DIRECT mode active now (%s - %s)\n", cd->FileName,
- cd->DestName);
- #endif
-
- if((out = Open(cd->DestName, MODE_NEWFILE)))
- {
- txt = cd->Mode == COPYMODE_MOVE ? TEXT_MOVED : TEXT_COPIED;
- if((in = Open(cd->FileName, MODE_OLDFILE)))
- {
- ULONG h;
-
- h = CopyFile(in, out, cd->BufferSize);
- Close(in);
- if(!h)
- {
- kill = 0;
- if(cd->Mode == COPYMODE_MOVE)
- {
- if(KillFile(cd->FileName, cd->Flags & COPYFLAG_FORCEDELETE))
- res = 1;
- }
- else
- res = 1;
- }
- }
- Close(out);
-
- if(kill)
- KillFile(cd->DestName, 0);
- }
- if(!res && !(cd->Flags & COPYFLAG_QUIET))
- PrintNotDone(cd->Flags & COPYFLAG_SILENT ? name : 0,
- txt, cd->Deep, cd->Fib->fib_DirEntryType > 0);
- else
- {
- cd->Flags |= COPYFLAG_DONE;
- if(!(cd->Flags & COPYFLAG_SILENT))
- Printf("%s\n", txt);
- }
- return;
- }
-
- if(!(lock = Lock(cd->FileName, SHARED_LOCK)))
- {
- cd->RetVal = RETURN_WARN;
- if(!(cd->Flags & COPYFLAG_QUIET))
- {
- PrintNotDone(cd->Fib->fib_FileName, TEXT_READ, cd->Deep,
- cd->Fib->fib_DirEntryType > 0);
- }
- return;
- }
-
- if(!(pdir = ParentDir(lock)))
- {
- cd->RetVal = RETURN_ERROR;
- if(cd->Mode == COPYMODE_DELETE)
- {
- if(!(cd->Flags & COPYFLAG_QUIET))
- {
- Printf(" %s ", cd->FileName);
- Printf(TEXT_NOT_DONE, TEXT_DELETED);
- Printf("%s\n", TEXT_ERR_DELETE_DEVICE);
- }
- }
- UnLock(lock);
- return;
- }
- UnLock(pdir);
-
- if(!(cd->Flags & COPYFLAG_SILENT))
- PrintName(name, cd->Deep, cd->Fib->fib_DirEntryType > 0,
- cd->Fib->fib_DirEntryType < 0 || (cd->Flags & COPYFLAG_ALL ?
- cd->Mode != COPYMODE_DELETE : cd->Mode != COPYMODE_COPY) ||
- cd->Flags & COPYFLAG_ENTERSECOND);
-
- if((cd->Flags & COPYFLAG_ENTERSECOND) || (cd->Mode == COPYMODE_DELETE
- && (!(cd->Flags & COPYFLAG_ALL) || cd->Fib->fib_DirEntryType < 0)))
- {
- UnLock(lock); lock = 0;
-
- if(KillFile(cd->FileName, cd->Flags & COPYFLAG_FORCEDELETE))
- printok = TEXT_DELETED;
- else
- {
- cd->RetVal = RETURN_WARN;
- printerr = TEXT_DELETED;
- }
- }
- else if(cd->Mode == COPYMODE_DELETE)
- ;
- else if(cd->Fib->fib_DirEntryType > 0)
- {
- ULONG a;
-
- if((cd->Flags & COPYFLAG_ALL || cd->Mode == COPYMODE_LINK ||
- cd->Mode == COPYMODE_MOVE) && TestLoop(lock, cd->CurDest))
- {
- printok = 0;
- cd->RetVal = RETURN_ERROR;
- if(!(cd->Flags & COPYFLAG_QUIET))
- {
- if(cd->Flags & COPYFLAG_SILENT)
- PrintName(name, cd->Deep, 1, 1);
- Printf(TEXT_NOT_DONE, TEXT_ENTERED);
- Printf(TEXT_ERR_INFINITE_LOOP);
- }
- }
- else if((a = TestDest(cd->DestName, 1, cd)) < 0)
- {
- printerr = TEXT_CREATED; cd->RetVal = RETURN_ERROR;
- }
- else if(cd->Flags & COPYFLAG_ALL)
- {
- ULONG i;
-
- i = cd->CurDest;
- cd->DestPathSize = 0;
-
- if(a == TESTDEST_DIR_OK)
- {
- if(!(cd->CurDest = Lock(cd->DestName, SHARED_LOCK)))
- {
- printerr = TEXT_ENTERED; cd->RetVal = RETURN_ERROR;
- }
- else
- printok = TEXT_ENTERED;
- }
- else if((cd->CurDest = CreateDir(cd->DestName)))
- {
- UnLock(cd->CurDest);
- if((cd->CurDest = Lock(cd->DestName, SHARED_LOCK)))
- printok = TEXT_CREATED;
- else
- {
- printerr = TEXT_ENTERED; cd->RetVal = RETURN_ERROR;
- }
- }
- else
- {
- printerr = TEXT_CREATED; cd->RetVal = RETURN_ERROR;
- }
- if(!cd->CurDest)
- cd->CurDest = i;
- else if(i != cd->Destination)
- UnLock(i);
- }
- else if(cd->Mode == COPYMODE_MOVE)
- {
- if(Rename(cd->FileName, cd->DestName))
- printok = TEXT_RENAMED;
- else
- {
- printerr = TEXT_RENAMED; cd->RetVal = RETURN_WARN;
- }
- }
- else if(cd->Mode == COPYMODE_LINK)
- {
- if(!(cd->Flags & COPYFLAG_FORCELINK))
- {
- printok = 0;
- cd->RetVal = RETURN_WARN;
- if(!(cd->Flags & COPYFLAG_QUIET))
- {
- if(cd->Flags & COPYFLAG_SILENT)
- PrintName(name, cd->Deep, 1, 1);
- Printf(TEXT_NOT_DONE, TEXT_LINKED);
- Printf(TEXT_ERR_FORCELINK);
- }
- }
- else if(LinkFile(lock, cd->DestName, cd->Flags & COPYFLAG_SOFTLINK))
- printok = TEXT_LINKED;
- else
- {
- printerr = TEXT_LINKED; cd->RetVal = RETURN_WARN;
- }
- }
- else /* COPY mode only displays directories, when not ALL */
- {
- printok = 0;
- if(!(cd->Flags & COPYFLAG_SILENT))
- Printf("\n");
- }
- }
- else
- {
- /* test for existing destination file */
- if(TestDest(cd->DestName, 0, cd) < 0)
- printerr = TEXT_OPENED_FOR_OUTPUT;
- else if(cd->Mode == COPYMODE_MOVE && Rename(cd->FileName, cd->DestName))
- printok = TEXT_RENAMED;
- else if(cd->Mode == COPYMODE_LINK)
- {
- if(!(cd->Flags & COPYFLAG_SOFTLINK) && LinkFile(lock, cd->DestName, 0))
- printok = TEXT_LINKED;
- else
- {
- printerr = TEXT_LINKED; cd->RetVal = RETURN_WARN;
- if(cd->Flags & COPYFLAG_SOFTLINK)
- SetIoErr(ERROR_OBJECT_WRONG_TYPE);
- }
- }
- else
- {
- ULONG in, out, res = 0, h;
- STRPTR txt = TEXT_OPENED_FOR_OUTPUT;
-
- if((out = Open(cd->DestName, MODE_NEWFILE)))
- {
- ULONG kill = 1;
-
- txt = cd->Mode == COPYMODE_MOVE ? TEXT_MOVED : TEXT_COPIED;
- UnLock(lock); lock = 0;
- if((in = Open(cd->FileName, MODE_OLDFILE)))
- {
- h = CopyFile(in, out, cd->BufferSize);
- Close(in);
- if(!h)
- {
- kill = 0;
- if(cd->Mode == COPYMODE_MOVE)
- {
- if(KillFile(cd->FileName, cd->Flags & COPYFLAG_FORCEDELETE))
- res = 1;
- }
- else
- res = 1;
- }
- }
- Close(out);
-
- if(kill)
- KillFile(cd->DestName, 0);
- }
- if(!res)
- {
- printerr = txt; cd->RetVal = RETURN_WARN;
- }
- else
- printok = txt;
- }
- }
-
- if(printerr && !(cd->Flags & COPYFLAG_QUIET))
- PrintNotDone(cd->Flags & COPYFLAG_SILENT ? name : 0,
- printerr, cd->Deep, cd->Fib->fib_DirEntryType > 0);
- else if(printok)
- {
- cd->Flags |= COPYFLAG_DONE;
- if(!(cd->Flags & COPYFLAG_SILENT))
- Printf("%s\n", printok);
- SetData(cd->DestName, cd);
- }
-
- if(lock)
- UnLock(lock);
- }
-
- LONG CopyFile(ULONG from, ULONG to, ULONG bufsize)
- {
- STRPTR buffer;
- LONG s, err = 0;
-
- if((buffer = (STRPTR) AllocMem(bufsize, MEMF_ANY)))
- {
- do
- {
- if((s = Read(from, buffer, bufsize)) == -1 ||
- Write(to, buffer, s) == -1)
- err = RETURN_FAIL;
- } while(s == bufsize && !err);
- FreeMem(buffer, bufsize);
- }
- else
- err = RETURN_FAIL;
-
- return err;
- }
-
- /* Softlink's path starts always with device name! f.e. "Ram Disk:T/..." */
- LONG LinkFile(ULONG from, STRPTR to, ULONG soft)
- {
- if(soft)
- {
- UBYTE name[FILEPATH_SIZE];
- NameFromLock(from, name, FILEPATH_SIZE);
- return MakeLink(to, (ULONG) name, LINK_SOFT);
- }
- else
- return MakeLink(to, from, LINK_HARD);
- }
-
- /* return 0 means no loop, return != 0 means loop found */
- ULONG TestLoop(ULONG srcdir, ULONG destdir)
- {
- ULONG par, lock, loop = 0;
-
- lock = destdir;
-
- if(SameDevice(srcdir, destdir))
- {
- do
- {
- if(!SameLock(srcdir, lock))
- loop = 1;
- else
- {
- par = ParentDir(lock);
- if(lock != destdir)
- UnLock(lock);
- lock = par;
- }
- } while(!loop && lock);
- }
-
- if(lock != destdir)
- UnLock(lock);
-
- return loop;
- }
-
- void SetData(STRPTR name, struct CopyData *cd)
- {
- if(cd->Flags & COPYFLAG_NOPRO)
- SetProtection(name, 0);
- else
- SetProtection(name, cd->Fib->fib_Protection);
- if(cd->Flags & COPYFLAG_DATES)
- SetFileDate(name, &cd->Fib->fib_Date);
- if(cd->Flags & COPYFLAG_COMMENT)
- SetComment(name, cd->Fib->fib_Comment);
- }
-
- LONG TestDest(STRPTR name, ULONG type, struct CopyData *cd)
- {
- LONG ret = TESTDEST_ERROR;
- ULONG lock;
-
- if((lock = Lock(name, SHARED_LOCK)))
- {
- struct FileInfoBlock *fib;
-
- if((fib = (struct FileInfoBlock *) AllocDosObject(DOS_FIB, 0)))
- {
- if(Examine(lock, fib))
- {
- UnLock(lock); lock = 0;
- if(type)
- {
- if(fib->fib_DirEntryType > 0)
- ret = TESTDEST_DIR_OK;
- else if(!(cd->Flags & COPYFLAG_DONTOVERWRITE))
- {
- if(KillFile(name, cd->Flags & COPYFLAG_FORCEOVERWRITE))
- ret = TESTDEST_DELETED;
- }
- else
- ret = TESTDEST_CANTDELETE;
- }
- else if(cd->Flags & COPYFLAG_DONTOVERWRITE)
- ret = TESTDEST_CANTDELETE;
- else if(KillFile(name, cd->Flags & COPYFLAG_FORCEOVERWRITE))
- ret = TESTDEST_DELETED;
- }
- FreeDosObject(DOS_FIB, fib);
- }
- if(lock)
- UnLock(lock);
- }
- else
- ret = TESTDEST_NONE;
-
- if(ret == TESTDEST_CANTDELETE)
- SetIoErr(ERROR_OBJECT_EXISTS);
-
- return ret;
- }
-
-