/* Auto: sc */ /* $Revision Header built automatically *************** (do not edit) ************ ** ** © Copyright by GuntherSoft ** ** File : SnakeSYS:CPrgs/Utils/Move.c ** Created on : Wednesday, 11.08.93 15:01:14 ** Created by : Kai Iske ** Current revision : V1.8 ** ** ** Purpose ** ------- ** - Small move utility which supports wildcards and doesn`t use ** Rename() nor Copy() nor anything similar... ** ** Revision V1.8 ** -------------- ** created on Sunday, 19.12.93 01:44:05 by Kai Iske. LogMessage : ** -*- changed on Sunday, 19.12.93 01:47:54 by Kai Iske. LogMessage : ** - Added PURE information to Doc, since Move really is pure ** (Suggested by : Albert-Jan Brouver) ** -*- changed on Sunday, 19.12.93 01:46:23 by Kai Iske. LogMessage : ** - Due to the move-renaming bug one couldn`t rename a dir ** an Assign was put on. ** (Reported by : Albert-Jan Brouver) ** -*- created on Sunday, 19.12.93 01:44:05 by Kai Iske. LogMessage : ** - Fixed move-renaming of directories. ** (Reported by : Albert-Jan Brouver) ** - Move had some severe problems recursively moving ** the contents of a directory ** ** Revision V1.7 ** -------------- ** created on Saturday, 04.12.93 23:19:03 by Kai Iske. LogMessage : ** -*- changed on Saturday, 04.12.93 23:26:25 by Kai Iske. LogMessage : ** - Error while moving to a "device full" disk ** (Reported by : Chris Conger) ** -*- created on Saturday, 04.12.93 23:19:03 by Kai Iske. LogMessage : ** - FileName length-bug fixed ** (Reported by : Juergen Lang) ** - Recompiled using SAS 6.50 ** - Stack usage reduced ** ** Revision V1.6 ** -------------- ** created on Friday, 15.10.93 15:51:13 by Kai Iske. LogMessage : ** -*- changed on Saturday, 16.10.93 15:17:29 by Kai Iske. LogMessage : ** - Move got screwed up, when attempting to move a ** zero size file ** -*- changed on Friday, 15.10.93 16:03:35 by Kai Iske. LogMessage : ** - Added Buffer Keyword to specify the maximum buffer ** size for an inter device move. Normally Move would have used ** the max amount of available free memory in order to ** accomplish the move, or the size needed by the file... ** (Suggested by : Christof Damian) ** -*- created on Friday, 15.10.93 15:51:13 by Kai Iske. LogMessage : ** - One couldn`t rename a file using move, because the ** "destination" file was removed before doing the rename, ** ie. the source file was deleted. ** (Reported by : Chris Conger) ** ** Revision V1.5 ** -------------- ** created on Tuesday, 05.10.93 01:42:53 by Kai Iske. LogMessage : ** -*- changed on Tuesday, 05.10.93 02:03:22 by Kai Iske. LogMessage : ** - Freed the FileInfoBlock _BEFORE_ setting the Bits, Comment ** etc. This lead to MungWall hits (of course it did) ** (Reported by Nico Francois) ** -*- created on Tuesday, 05.10.93 01:42:53 by Kai Iske. LogMessage : ** - Exidentially called one ExAll() without ED_SIZE ** This lead to some calls to DoTheMove without the Size set ;) ** (Reported by Karsten Weiss) ** ** Revision V1.4 ** -------------- ** created on Friday, 01.10.93 16:55:15 by Kai Iske. LogMessage : ** -*- created on Friday, 01.10.93 16:55:15 by Kai Iske. LogMessage : ** - Now uses Rename() when source and dest are on the same ** device. This is faster ;) Why haven`t I thought of that ** earlier ??? ;) ** ** Revision V1.3 ** -------------- ** created on Wednesday, 25.08.93 16:32:43 by Kai Iske. LogMessage : ** - UnLock Problem solved when doing recursive Dir-Moves ** This bug lead to "Object in use" error messages ** ** Revision V1.2 ** -------------- ** created on Tuesday, 17.08.93 22:48:38 by Kai Iske. LogMessage : ** - Added CTRL-C checking ** - Added FORCE Flag in order to move read/deleteprotected or ** to overwrite a delete/writeprotected files ** ** Revision V1.1 ** -------------- ** created on Monday, 16.08.93 22:53:34 by Kai Iske. LogMessage : ** - Added well known CLONE, DATES, COM, NOPRO, ** QUIET and NOREQ options also used by e.g. Rename ** ** Revision V1.0 ** -------------- ** created on Wednesday, 11.08.93 15:01:14 by Kai Iske. LogMessage : ** --- Initial release --- ** *********************************************************************************/ #define REVISION "1.8" #define REVDATE "19.12.93" #define REVTIME "01:47:54" #define AUTHOR "Kai Iske" #define VERNUM 1 #define REVNUM 8 #include #include #include #include #include #include #include #include #include #include /**********************************************************************/ /* Defines for Flags */ /**********************************************************************/ #define CLONE 0x0001 #define DATES 0x0002 #define NOPRO 0x0004 #define COM 0x0008 #define QUIET 0x0010 #define FORCE 0x0020 #define WATCHSIGS SIGBREAKF_CTRL_C /**********************************************************************/ /* Static char definitions */ /**********************************************************************/ static const char *Version = "$VER: Move "REVISION" ("REVDATE")\0"; static const char *Template = "FROM/M,TO/A,CLONE/S,DATES/S,NOPRO/S,COM/S,QUIET/S,NOREQ/S,FORCE/S,BUFFER/N/K"; enum {FROM_ARG, TO_ARG, CLONE_ARG, DATES_ARG, NOPRO_ARG, COM_ARG, QUIET_ARG, NOREQ_ARG, FORCE_ARG, BUFFER_ARG, LAST_ARG}; /**********************************************************************/ /* Prototypes */ /**********************************************************************/ int __saveds DoMove(void); BOOL __stdargs DoTheMove(char *FromFile, char *ToPath, BOOL PatternFrom, BPTR OutHandle, struct DOSBase *DOSBase, LONG Type, ULONG Size, UWORD CopyFlags, LONG *HitMask, ULONG MaxBuffer); BOOL __stdargs DoMoveFile(char *FromFile, char *ToPath, char *Buffer, BPTR OutHandle, struct DOSBase *DOSBase, ULONG Size, UWORD CopyFlags, LONG *HitMask, ULONG MaxBuffer); /**********************************************************************/ /* The main program */ /**********************************************************************/ int __saveds DoMove(void) { struct FileInfoBlock *FIB; struct ExecBase *SysBase = *((struct ExecBase **)0x4L); struct DOSBase *DOSBase; struct Process *MyProc = (struct Process *)SysBase->ThisTask; struct RDArgs *RDArgs; struct ExAllControl *EAC; struct ExAllData *EAB, *EAD; APTR *Args, *OldWindow; BPTR DirLock, OutHandle; char **FromPtr; char *ToPtr; char *Pattern; char *PathName = NULL; char *Buffer = NULL; LONG HitMask; UWORD NumFrom = 0, PatternType, CopyFlags = 0; ULONG MaxBuffer = 0; BOOL PatternFrom, GoOn = FALSE, Scanning; // Ignore startup from WB if(!(MyProc->pr_CLI)) { struct Message *MyMsg; WaitPort(&MyProc->pr_MsgPort); MyMsg = GetMsg(&MyProc->pr_MsgPort); Disable(); ReplyMsg(MyMsg); return(10); } // Do the wild thing if((DOSBase = (struct DOSBase *)OpenLibrary("dos.library", 37))) { // Allocate buffers if((Pattern = AllocVec(1024, MEMF_CLEAR)) && (PathName = AllocVec(1024, MEMF_CLEAR)) && (Buffer = AllocVec(1024, MEMF_CLEAR))) { if((FIB = AllocVec(sizeof(struct FileInfoBlock), MEMF_CLEAR))) { // Get buffer for ReadArgs() if((Args = AllocVec((LAST_ARG * sizeof(ULONG)), MEMF_CLEAR))) { // Get structure for ExAll() if((EAC = AllocDosObject(DOS_EXALLCONTROL, NULL))) { // Get buffer for ExAll() if((EAB = AllocVec((sizeof(struct ExAllData)*20), MEMF_CLEAR))) { // Parse commandline if((RDArgs = ReadArgs((char *)Template, (LONG *)Args, NULL))) { // From and to really there ?? if(Args[FROM_ARG] && Args[TO_ARG]) { // A O.K. so far GoOn = TRUE; // Get output handle OutHandle = Output(); // Get Flags if(Args[CLONE_ARG]) CopyFlags |= CLONE; if(Args[DATES_ARG]) CopyFlags |= DATES; if(Args[NOPRO_ARG]) CopyFlags |= NOPRO; if(Args[COM_ARG]) CopyFlags |= COM; if(Args[QUIET_ARG]) CopyFlags |= QUIET; if(Args[FORCE_ARG]) CopyFlags |= FORCE; if(Args[BUFFER_ARG]) MaxBuffer = *((ULONG *)Args[BUFFER_ARG]) * 1024; // Check for NOREQ Option if(Args[NOREQ_ARG]) { OldWindow = MyProc->pr_WindowPtr; MyProc->pr_WindowPtr = (void *)(-1L); } // Get pointers to Files FromPtr = (char **)Args[FROM_ARG]; ToPtr = (char *)Args[TO_ARG]; // Count FROM entries while(*FromPtr++) NumFrom++; // Restore FromPtr FromPtr = (char **)Args[FROM_ARG]; // Set pattern if there are more than 1 // FROM files or if the only FROM file // is a pattern if(NumFrom > 1) PatternFrom = TRUE; else PatternFrom = ParsePatternNoCase(*FromPtr, Pattern, 1024); // If a pattern is used, check // whether the dest really is a dir if(PatternFrom) { // Try to obtain a lock if((DirLock = Lock(ToPtr, ACCESS_READ))) { // Check file if(Examine(DirLock, FIB)) { // Get type of destination entry GoOn = (FIB->fib_DirEntryType >= 0); // If it`s not a directory (multiple files are to be moved) // issue an error if(!GoOn) FPuts(OutHandle, "\nMove : Multiple files may not be moved to a single file\n"); } else { // Examine() failed -> Abort GoOn = FALSE; PrintFault(IoErr(), "\nMove "); } // Unlock CheckDir UnLock(DirLock); } else { // If lock failed issue an error PrintFault(IoErr(), "\nMove "); GoOn = FALSE; } } // Loop for all source files while(NumFrom && GoOn) { // Check for CTRL-C if(GoOn) HitMask = CheckSignal(WATCHSIGS); if(!HitMask && GoOn) { // Check if this source is a pattern strcpy(Buffer, FilePart(*FromPtr)); strupr(Buffer); PatternType = ParsePatternNoCase(Buffer, Pattern, 1024); // It is a pattern if(PatternType == 1) { // Create name of source strcpy(Buffer, *FromPtr); *PathPart(Buffer) = '\0'; // Get Lock for Source - Directory if((DirLock = Lock(Buffer, ACCESS_READ))) { // Setup ExAllControl-Structure EAC->eac_LastKey = 0L; EAC->eac_MatchString = Pattern; EAC->eac_MatchFunc = NULL; do { // Check for CTRL-C if(GoOn) HitMask = CheckSignal(WATCHSIGS); if(HitMask) GoOn = FALSE; // Scan directory Scanning = ExAll(DirLock, EAB, (20*sizeof(struct ExAllData)), ED_SIZE, EAC); // Issue Error if(GoOn && (!Scanning) && (IoErr() != ERROR_NO_MORE_ENTRIES)) { PrintFault(IoErr(), "\nMove "); GoOn = FALSE; } // End of Dir reached if(EAC->eac_Entries == 0) Scanning = FALSE; else if(GoOn) { EAD = EAB; do { // Check for CTRL-C if(GoOn) HitMask = CheckSignal(WATCHSIGS); if(!HitMask && GoOn) { // Create filename for this file to be moved strcpy(PathName, *FromPtr); *PathPart(PathName) = '\0'; AddPart(PathName, EAD->ed_Name, 1024); // Move file GoOn = DoTheMove(PathName, ToPtr, TRUE, OutHandle, DOSBase, EAD->ed_Type, EAD->ed_Size, CopyFlags, &HitMask, MaxBuffer); EAD = EAD->ed_Next; } else GoOn = FALSE; } while(EAD && GoOn); } } while(Scanning); // Unlock source directory UnLock(DirLock); } else { // Issue error, if dir could not be locked PrintFault(IoErr(), "\nMove "); GoOn = FALSE; } } // No pattern else if(PatternType == 0) { // Try to lock source file/dir if((DirLock = Lock(*FromPtr, ACCESS_READ))) { // Examine this lock if(Examine(DirLock, FIB)) { // Unlock directory and do the move UnLock(DirLock); GoOn = DoTheMove(*FromPtr, ToPtr, TRUE, OutHandle, DOSBase, FIB->fib_DirEntryType, FIB->fib_Size, CopyFlags, &HitMask, MaxBuffer); } else { // Issue error on failed Examine() PrintFault(IoErr(), "\nMove "); GoOn = FALSE; UnLock(DirLock); } } else { // No Lock() no more moves PrintFault(IoErr(), "\nMove "); GoOn = FALSE; } } // Error condition else { PrintFault(IoErr(), "\nMove "); GoOn = FALSE; } NumFrom--; FromPtr++; } else GoOn = FALSE; } } // Free ReadArgs FreeArgs(RDArgs); } else PrintFault(IoErr(), "\nMove "); // Free ExAll-Buffer FreeVec(EAB); } else PrintFault(ERROR_NO_FREE_STORE, "\nMove "); // Free ExAllControl Structure FreeDosObject(DOS_EXALLCONTROL, (void *)EAC); } else PrintFault(IoErr(), "\nMove "); // Free Argument Buffer FreeVec(Args); } else PrintFault(ERROR_NO_FREE_STORE, "\nMove "); FreeVec(FIB); } else PrintFault(ERROR_NO_FREE_STORE, "\nMove "); } else PrintFault(ERROR_NO_FREE_STORE, "\nMove "); // Free allocated buffers if(Pattern) FreeVec(Pattern); if(PathName) FreeVec(PathName); if(Buffer) FreeVec(Buffer); // Check for Abort-Signals if(HitMask && !(CopyFlags & QUIET)) { // Display appropriate message if(HitMask & SIGBREAKF_CTRL_C) FPuts(OutHandle, "\nMove ^C...\n"); } // Close DOSLibrary CloseLibrary((struct Library *)DOSBase); } // Restore old window pointer (if any) if(OldWindow) MyProc->pr_WindowPtr = OldWindow; // Depending on this flag return appropriate return code if(GoOn) return(0); else return(10); } /**********************************************************************/ /* Do the move */ /**********************************************************************/ BOOL __stdargs DoTheMove(char *FromFile, char *ToPath, BOOL PatternFrom, BPTR OutHandle, struct DOSBase *DOSBase, LONG Type, ULONG Size, UWORD CopyFlags, LONG *HitMask, ULONG MaxBuffer) { struct ExAllControl *EAC; struct ExAllData *EAB, *EAD; struct DevProc *FromDev, *ToDev; char *NewDir; char *Buffer = NULL; char *ToDir = NULL; UWORD Len; BPTR DirLock; BOOL RetVal = TRUE, Scanning, DoRename = FALSE; // Try to allocate buffers if((NewDir = AllocVec(1024, MEMF_CLEAR)) && (Buffer = AllocVec(1024, MEMF_CLEAR)) && (ToDir = AllocVec(1024, MEMF_CLEAR))) { // If a pattern is used print the name of the file to be moved if(PatternFrom && !(CopyFlags & QUIET)) { strcpy(Buffer, FromFile); strcat(Buffer, "..."); Write(OutHandle, " ", 1); Write(OutHandle, Buffer, strlen(Buffer)); } // Is it a directory ??? // If yes, recursively loop for all entries within dir if(Type >= 0) { strcpy(Buffer, FromFile); // Get length of from name Len = strlen(Buffer); if(Len) { if(Buffer[Len - 1] == '/') Buffer[Len - 1] = '\0'; // Copy dest name to buffer strcpy(NewDir, ToPath); // Check whether dest dir is on same device // If so, do a simple rename FromDev = GetDeviceProc(Buffer, NULL); ToDev = GetDeviceProc(NewDir, NULL); // If the same device is used -> Do the rename if(FromDev && ToDev && (FromDev->dvp_Port == ToDev->dvp_Port)) DoRename = TRUE; if(FromDev) FreeDeviceProc(FromDev); if(ToDev) FreeDeviceProc(ToDev); if(DoRename) { // Do the rename if(!Rename(Buffer, NewDir)) { PrintFault(IoErr(), "\nMove "); RetVal = FALSE; } } else { // Add name of from directory AddPart(NewDir, FilePart(Buffer), 1024); // Clone directory name of source strcpy(ToDir, Buffer); // Try to lock directory or // create it, if not existent if(!(DirLock = Lock(NewDir, ACCESS_READ))) { if((DirLock = CreateDir(NewDir)) && PatternFrom && !(CopyFlags & QUIET)) Write(OutHandle, " [created]...", 13); } // Got the destination directory ??? if(DirLock) { // Unlock Directory UnLock(DirLock); // Lock sourcedirectory if((DirLock = Lock(Buffer, ACCESS_READ))) { // Get ExAll Control for recursive directory search if((EAC = AllocDosObject(DOS_EXALLCONTROL, NULL))) { // Allocate buffer for move if((EAB = AllocVec((20*sizeof(struct ExAllData)), MEMF_CLEAR))) { EAC->eac_LastKey = 0L; EAC->eac_MatchString = NULL; EAC->eac_MatchFunc = NULL; do { // Check for CTRL-C if(RetVal) (*HitMask) = CheckSignal(WATCHSIGS); if((*HitMask)) RetVal = FALSE; // Scan directory for entries Scanning = ExAll(DirLock, EAB, (20*sizeof(struct ExAllData)), ED_SIZE, EAC); // Check for an error if(RetVal && (!Scanning) && (IoErr() != ERROR_NO_MORE_ENTRIES)) { PrintFault(IoErr(), "\nMove "); RetVal = FALSE; } // End of Dir reached if(EAC->eac_Entries == 0) Scanning = FALSE; else if(RetVal) { EAD = EAB; do { // Check for CTRL-C if(RetVal) (*HitMask) = CheckSignal(WATCHSIGS); if(!(*HitMask) && RetVal) { // Create filename of source strcpy(Buffer, FromFile); AddPart(Buffer, EAD->ed_Name, 1024); // And start recursion RetVal = DoTheMove(Buffer, NewDir, FALSE, OutHandle, DOSBase, EAD->ed_Type, EAD->ed_Size, CopyFlags, HitMask, MaxBuffer); // Loop for all entries EAD = EAD->ed_Next; } else RetVal = FALSE; } while(EAD && RetVal); } } while(Scanning); // Free ExAll Buffer FreeVec(EAB); } else { PrintFault(ERROR_NO_FREE_STORE, "\nMove "); RetVal = FALSE; } // Free ExAllControl Structure FreeDosObject(DOS_EXALLCONTROL, EAC); } else { PrintFault(IoErr(), "\nMove "); RetVal = FALSE; } UnLock(DirLock); } else { PrintFault(IoErr(), "\nMove "); RetVal = FALSE; } } else { PrintFault(IoErr(), "\nMove "); RetVal = FALSE; } } } // Ok, this dir was moved (no rename), so remove it if(RetVal && !DoRename) { // With force mode set on, // First make dir deletable if(CopyFlags & FORCE) SetProtection(ToDir, ~(FIBF_OTR_WRITE|FIBF_OTR_DELETE|FIBF_WRITE|FIBF_DELETE)); // Delete directory if(!DeleteFile(ToDir)) { PrintFault(IoErr(), "\nMove "); RetVal = FALSE; } } } else { // On a plain file -> Simply move it RetVal = DoMoveFile(FromFile, ToPath, Buffer, OutHandle, DOSBase, Size, CopyFlags, HitMask, MaxBuffer); } // If there was a pattern (or a single directory) // end the Move string if(PatternFrom && RetVal && !(CopyFlags & QUIET)) FPuts(OutHandle, " moved\n"); } else { PrintFault(ERROR_NO_FREE_STORE, "\nMove "); RetVal = FALSE; } // De-Allocate buffers if(NewDir) FreeVec(NewDir); if(Buffer) FreeVec(Buffer); if(ToDir) FreeVec(ToDir); // Return Code return(RetVal); } /**********************************************************************/ /* Ein File wirklich moven */ /**********************************************************************/ BOOL __stdargs DoMoveFile(char *FromFile, char *ToPath, char *Buffer, BPTR OutHandle, struct DOSBase *DOSBase, ULONG Size, UWORD CopyFlags, LONG *HitMask, ULONG MaxBuffer) { struct FileInfoBlock *FIB; struct DevProc *FromDev, *ToDev; BPTR InFile, OutFile; APTR CopyBuffer; char *DestName; ULONG AvailSize, ReadSize; LONG InKey = -1, OutKey = -1; BOOL RetVal = TRUE, ErrCpy = FALSE, LoopCpy = TRUE, DoRename = FALSE, RemoveFirst = FALSE; // Allocate buffer for Destination name if(!(DestName = AllocVec(1024, MEMF_CLEAR))) { PrintFault(ERROR_NO_FREE_STORE, "\nMove "); return(FALSE); } if((FIB = AllocVec(sizeof(struct FileInfoBlock), MEMF_CLEAR))) { strcpy(DestName, ToPath); // Check, if destfile already exists // If so, check if it`s a dir. // Yes -> Copy with sourcename // No -> Copy with given name if((OutFile = Lock(DestName, ACCESS_READ))) { if(Examine(OutFile, FIB)) { // If dest is a directory move with source name if(FIB->fib_DirEntryType >= 0) AddPart(DestName, FilePart(FromFile), 1024); else { OutKey = ((struct FileLock *)BADDR(OutFile))->fl_Key; RemoveFirst = TRUE; } } else { // No examine -> Use source filename AddPart(DestName, FilePart(FromFile), 1024); } UnLock(OutFile); } // Try to lock input file if((InFile = Lock(FromFile, ACCESS_READ))) { // Get DiskBlock for inputfile InKey = ((struct FileLock *)BADDR(InFile))->fl_Key; // Get old protection bits, comment and filedate if(Examine(InFile, FIB)) { // In Force mode -> Force read and delete permissons // for input file if(CopyFlags & FORCE) SetProtection(FromFile, ~(FIBF_OTR_READ|FIBF_OTR_DELETE|FIBF_READ|FIBF_DELETE)); } else { PrintFault(IoErr(), "\nMove "); RetVal = FALSE; } // If so, unlock UnLock(InFile); } else { PrintFault(IoErr(), "\nMove "); RetVal = FALSE; } // Check whether to use a Rename() or a real Copy-Mode FromDev = GetDeviceProc(FromFile, NULL); ToDev = GetDeviceProc(DestName, NULL); // If the same device is used -> Do the rename if(FromDev && ToDev && (FromDev->dvp_Port == ToDev->dvp_Port)) DoRename = TRUE; if(FromDev) FreeDeviceProc(FromDev); if(ToDev) FreeDeviceProc(ToDev); // No Rename -> Do the right move ;) if(!DoRename) { // Open Input file if(RetVal && (InFile = Open(FromFile, MODE_OLDFILE))) { // Outfile already there ??? and in force mode ??? if((CopyFlags & FORCE) && ((OutFile = Lock(DestName, ACCESS_READ)))) { // Force delete and write permissons UnLock(OutFile); SetProtection(DestName, ~(FIBF_OTR_WRITE|FIBF_OTR_DELETE|FIBF_WRITE|FIBF_DELETE)); } // Open Output file if((OutFile = Open(DestName, MODE_NEWFILE))) { // Is there any data within the file ??? if(Size) { // Get available size of memory // or take the user`s buffer size into account AvailSize = (MaxBuffer != 0) ? MaxBuffer : (AvailMem(MEMF_LARGEST) - 102400); Size = (Size > AvailSize) ? AvailSize : Size; // Loop till we get a buffer while(Size && !(CopyBuffer = AllocVec(Size, MEMF_CLEAR))) Size -= 1024; if(CopyBuffer) { // Loop for portions of the source file while(RetVal && LoopCpy) { // Check for CTRL-C if(RetVal) (*HitMask) = CheckSignal(WATCHSIGS); if(!(*HitMask) && RetVal) { // Read part of file if((ReadSize = Read(InFile, CopyBuffer, Size)) > 0) { // And write it back if(Write(OutFile, CopyBuffer, ReadSize) == -1) { PrintFault(IoErr(), "\nMove "); RetVal = FALSE; ErrCpy = TRUE; } } else { // EOF ??? -> End copy if(ReadSize == 0) LoopCpy = FALSE; else { // Otherwise issue error PrintFault(IoErr(), "\nMove "); RetVal = FALSE; ErrCpy = TRUE; } } } else RetVal = FALSE; } // Free Copy buffer FreeVec(CopyBuffer); } else { // Issue error PrintFault(ERROR_NO_FREE_STORE, "\nMove "); RetVal = FALSE; ErrCpy = TRUE; } // Close outfile } Close(OutFile); } else { // Issue error PrintFault(IoErr(), "\nMove "); RetVal = FALSE; } // Close InFile Close(InFile); } else { // Issue error PrintFault(IoErr(), "\nMove "); RetVal = FALSE; } } else { // If RemoveFirst is not set, check again ;) if(!RemoveFirst) { if((OutFile = Lock(DestName, ACCESS_READ))) { if(Examine(OutFile, FIB)) { // If dest is a file, delete first if(FIB->fib_DirEntryType < 0) { // Get Disk block of dest file OutKey = ((struct FileLock *)BADDR(OutFile))->fl_Key; RemoveFirst = TRUE; } } UnLock(OutFile); } } // Check if only a rename should be accomplished if(InKey != -1 && OutKey != -1) { if(InKey == OutKey) RemoveFirst = FALSE; } // In Rename() mode, the destination has to be removed first if(RemoveFirst) { // If dest file is protected check for FORCE flag if(CopyFlags & FORCE) SetProtection(DestName, ~(FIBF_OTR_WRITE|FIBF_OTR_DELETE|FIBF_WRITE|FIBF_DELETE)); if(!DeleteFile(DestName)) { PrintFault(IoErr(), "\nMove "); RetVal = FALSE; } } if(RetVal) { // Now try to "rename" the file if(!Rename(FromFile, DestName)) { PrintFault(IoErr(), "\nMove "); RetVal = FALSE; } } } // Error while copying ?? -> Remove Dest file if(ErrCpy) { FPuts(OutHandle, "\nMove : Error while moving; destination removed.\n"); DeleteFile(DestName); } // No Error -> Remove Source file if(RetVal && !ErrCpy) { if(!DoRename && !(RetVal = DeleteFile(FromFile))) PrintFault(IoErr(), "\nMove "); else { // Set bits etc. as requested if((CopyFlags & CLONE) || (CopyFlags & DATES)) SetFileDate(DestName, &FIB->fib_Date); if((CopyFlags & CLONE) || (CopyFlags & COM)) SetComment(DestName, FIB->fib_Comment); if(((CopyFlags & CLONE) && !(CopyFlags & NOPRO)) || (!(CopyFlags & CLONE) && !(CopyFlags & NOPRO))) SetProtection(DestName, FIB->fib_Protection); } } // Free FileInfo Block FreeVec(FIB); } else { PrintFault(ERROR_NO_FREE_STORE, "\nMove "); RetVal = FALSE; } // Free buffer for destination name FreeVec(DestName); return(RetVal); }