home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / mar94 / os20 / cli / move.lha / Move / Move.c < prev    next >
C/C++ Source or Header  |  1994-01-31  |  28KB  |  1,178 lines

  1. /*
  2. Auto:        sc <file>
  3. */
  4.  
  5. /* $Revision Header built automatically *************** (do not edit) ************
  6. **
  7. ** © Copyright by GuntherSoft
  8. **
  9. ** File             : SnakeSYS:CPrgs/Utils/Move.c
  10. ** Created on       : Wednesday, 11.08.93 15:01:14
  11. ** Created by       : Kai Iske
  12. ** Current revision : V1.8
  13. **
  14. **
  15. ** Purpose
  16. ** -------
  17. **   - Small move utility which supports wildcards and doesn`t use
  18. **     Rename() nor Copy() nor anything similar...
  19. **
  20. ** Revision V1.8
  21. ** --------------
  22. ** created on Sunday, 19.12.93 01:44:05  by  Kai Iske.   LogMessage :
  23. **  -*-  changed on Sunday, 19.12.93 01:47:54  by  Kai Iske.   LogMessage :
  24. **   - Added PURE information to Doc, since Move really is pure
  25. **     (Suggested by : Albert-Jan Brouver)
  26. **  -*-  changed on Sunday, 19.12.93 01:46:23  by  Kai Iske.   LogMessage :
  27. **   - Due to the move-renaming bug one couldn`t rename a dir
  28. **     an Assign was put on.
  29. **     (Reported by : Albert-Jan Brouver)
  30. **  -*-  created on Sunday, 19.12.93 01:44:05  by  Kai Iske.   LogMessage :
  31. **   - Fixed move-renaming of directories.
  32. **     (Reported by : Albert-Jan Brouver)
  33. **   - Move had some severe problems recursively moving
  34. **     the contents of a directory
  35. **
  36. ** Revision V1.7
  37. ** --------------
  38. ** created on Saturday, 04.12.93 23:19:03  by  Kai Iske.   LogMessage :
  39. **  -*-  changed on Saturday, 04.12.93 23:26:25  by  Kai Iske.   LogMessage :
  40. **   - Error while moving to a "device full" disk
  41. **     (Reported by : Chris Conger)
  42. **  -*-  created on Saturday, 04.12.93 23:19:03  by  Kai Iske.   LogMessage :
  43. **   - FileName length-bug fixed
  44. **     (Reported by : Juergen Lang)
  45. **   - Recompiled using SAS 6.50
  46. **   - Stack usage reduced
  47. **
  48. ** Revision V1.6
  49. ** --------------
  50. ** created on Friday, 15.10.93 15:51:13  by  Kai Iske.   LogMessage :
  51. **  -*-  changed on Saturday, 16.10.93 15:17:29  by  Kai Iske.   LogMessage :
  52. **   - Move got screwed up, when attempting to move a
  53. **     zero size file
  54. **  -*-  changed on Friday, 15.10.93 16:03:35  by  Kai Iske.   LogMessage :
  55. **   - Added Buffer Keyword to specify the maximum buffer
  56. **     size for an inter device move. Normally Move would have used
  57. **     the max amount of available free memory in order to
  58. **     accomplish the move, or the size needed by the file...
  59. **     (Suggested by : Christof Damian)
  60. **  -*-  created on Friday, 15.10.93 15:51:13  by  Kai Iske.   LogMessage :
  61. **   - One couldn`t rename a file using move, because the
  62. **     "destination" file was removed before doing the rename,
  63. **     ie. the source file was deleted.
  64. **     (Reported by : Chris Conger)
  65. **
  66. ** Revision V1.5
  67. ** --------------
  68. ** created on Tuesday, 05.10.93 01:42:53  by  Kai Iske.   LogMessage :
  69. **  -*-  changed on Tuesday, 05.10.93 02:03:22  by  Kai Iske.   LogMessage :
  70. **   - Freed the FileInfoBlock _BEFORE_ setting the Bits, Comment
  71. **     etc. This lead to MungWall hits (of course it did)
  72. **     (Reported by Nico Francois)
  73. **  -*-  created on Tuesday, 05.10.93 01:42:53  by  Kai Iske.   LogMessage :
  74. **   - Exidentially called one ExAll() without ED_SIZE
  75. **     This lead to some calls to DoTheMove without the Size set ;)
  76. **     (Reported by  Karsten Weiss)
  77. **
  78. ** Revision V1.4
  79. ** --------------
  80. ** created on Friday, 01.10.93 16:55:15  by  Kai Iske.   LogMessage :
  81. **  -*-  created on Friday, 01.10.93 16:55:15  by  Kai Iske.   LogMessage :
  82. **   - Now uses Rename() when source and dest are on the same
  83. **     device. This is faster ;) Why haven`t I thought of that
  84. **     earlier ??? ;)
  85. **
  86. ** Revision V1.3
  87. ** --------------
  88. ** created on Wednesday, 25.08.93 16:32:43  by  Kai Iske.   LogMessage :
  89. **   - UnLock Problem solved when doing recursive Dir-Moves
  90. **     This bug lead to "Object in use" error messages
  91. **
  92. ** Revision V1.2
  93. ** --------------
  94. ** created on Tuesday, 17.08.93 22:48:38  by  Kai Iske.   LogMessage :
  95. **   - Added CTRL-C checking
  96. **   - Added FORCE Flag in order to move read/deleteprotected or
  97. **     to overwrite a delete/writeprotected files
  98. **
  99. ** Revision V1.1
  100. ** --------------
  101. ** created on Monday, 16.08.93 22:53:34  by  Kai Iske.   LogMessage :
  102. **   - Added well known CLONE, DATES, COM, NOPRO,
  103. **     QUIET and NOREQ options also used by e.g. Rename
  104. **
  105. ** Revision V1.0
  106. ** --------------
  107. ** created on Wednesday, 11.08.93 15:01:14  by  Kai Iske.   LogMessage :
  108. **     --- Initial release ---
  109. **
  110. *********************************************************************************/
  111. #define REVISION "1.8"
  112. #define REVDATE  "19.12.93"
  113. #define REVTIME  "01:47:54"
  114. #define AUTHOR   "Kai Iske"
  115. #define VERNUM   1
  116. #define REVNUM   8
  117.  
  118. #include    <string.h>
  119. #include    <stdlib.h>
  120. #include    <exec/types.h>
  121. #include    <proto/exec.h>
  122. #include    <proto/dos.h>
  123. #include    <exec/memory.h>
  124. #include    <exec/execbase.h>
  125. #include    <dos/exall.h>
  126. #include    <dos/dos.h>
  127. #include    <dos/dosextens.h>
  128.  
  129.  
  130.  
  131.  
  132. /**********************************************************************/
  133. /*                         Defines for Flags                          */
  134. /**********************************************************************/
  135. #define    CLONE        0x0001
  136. #define    DATES        0x0002
  137. #define    NOPRO        0x0004
  138. #define    COM        0x0008
  139. #define    QUIET        0x0010
  140. #define    FORCE        0x0020
  141.  
  142. #define    WATCHSIGS    SIGBREAKF_CTRL_C
  143.  
  144.  
  145.  
  146. /**********************************************************************/
  147. /*                      Static char definitions                       */
  148. /**********************************************************************/
  149. static    const char    *Version    = "$VER: Move "REVISION" ("REVDATE")\0";
  150. 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";
  151. enum    {FROM_ARG, TO_ARG, CLONE_ARG, DATES_ARG, NOPRO_ARG, COM_ARG, QUIET_ARG, NOREQ_ARG, FORCE_ARG, BUFFER_ARG, LAST_ARG};
  152.  
  153.  
  154.  
  155. /**********************************************************************/
  156. /*                             Prototypes                             */
  157. /**********************************************************************/
  158. int    __saveds DoMove(void);
  159. BOOL    __stdargs DoTheMove(char *FromFile, char *ToPath, BOOL PatternFrom, BPTR OutHandle, struct DOSBase *DOSBase, LONG Type, ULONG Size, UWORD CopyFlags, LONG *HitMask, ULONG MaxBuffer);
  160. BOOL    __stdargs DoMoveFile(char *FromFile, char *ToPath, char *Buffer, BPTR OutHandle, struct DOSBase *DOSBase, ULONG Size, UWORD CopyFlags, LONG *HitMask, ULONG MaxBuffer);
  161.  
  162.  
  163. /**********************************************************************/
  164. /*                          The main program                          */
  165. /**********************************************************************/
  166. int __saveds DoMove(void)
  167. {
  168.     struct    FileInfoBlock    *FIB;
  169.     struct    ExecBase    *SysBase = *((struct ExecBase **)0x4L);
  170.     struct    DOSBase        *DOSBase;
  171.     struct    Process        *MyProc = (struct Process *)SysBase->ThisTask;
  172.     struct    RDArgs        *RDArgs;
  173.     struct    ExAllControl    *EAC;
  174.     struct    ExAllData    *EAB, *EAD;
  175.     APTR    *Args,
  176.         *OldWindow;
  177.     BPTR    DirLock,
  178.         OutHandle;
  179.     char    **FromPtr;
  180.     char    *ToPtr;
  181.     char    *Pattern;
  182.     char    *PathName    = NULL;
  183.     char    *Buffer        = NULL;
  184.     LONG    HitMask;
  185.     UWORD    NumFrom = 0, PatternType, CopyFlags = 0;
  186.     ULONG    MaxBuffer = 0;
  187.     BOOL    PatternFrom, GoOn = FALSE, Scanning;
  188.  
  189.         // Ignore startup from WB
  190.  
  191.     if(!(MyProc->pr_CLI))
  192.     {
  193.         struct    Message    *MyMsg;
  194.  
  195.         WaitPort(&MyProc->pr_MsgPort);
  196.         MyMsg = GetMsg(&MyProc->pr_MsgPort);
  197.         Disable();
  198.         ReplyMsg(MyMsg);
  199.         return(10);
  200.     }
  201.  
  202.         // Do the wild thing
  203.  
  204.     if((DOSBase = (struct DOSBase *)OpenLibrary("dos.library", 37)))
  205.     {
  206.             // Allocate buffers
  207.  
  208.         if((Pattern = AllocVec(1024, MEMF_CLEAR)) && (PathName = AllocVec(1024, MEMF_CLEAR)) && (Buffer = AllocVec(1024, MEMF_CLEAR)))
  209.         {
  210.             if((FIB = AllocVec(sizeof(struct FileInfoBlock), MEMF_CLEAR)))
  211.             {
  212.                     // Get buffer for ReadArgs()
  213.  
  214.                 if((Args = AllocVec((LAST_ARG * sizeof(ULONG)), MEMF_CLEAR)))
  215.                 {
  216.                         // Get structure for ExAll()
  217.  
  218.                     if((EAC = AllocDosObject(DOS_EXALLCONTROL, NULL)))
  219.                     {
  220.                             // Get buffer for ExAll()
  221.  
  222.                         if((EAB = AllocVec((sizeof(struct ExAllData)*20), MEMF_CLEAR)))
  223.                         {
  224.                                 // Parse commandline
  225.  
  226.                             if((RDArgs = ReadArgs((char *)Template, (LONG *)Args, NULL)))
  227.                             {
  228.                                     // From and to really there ??
  229.  
  230.                                 if(Args[FROM_ARG] && Args[TO_ARG])
  231.                                 {
  232.                                         // A O.K. so far
  233.  
  234.                                     GoOn        = TRUE;
  235.  
  236.                                         // Get output handle
  237.  
  238.                                     OutHandle    = Output();
  239.  
  240.                                         // Get Flags
  241.  
  242.                                     if(Args[CLONE_ARG])
  243.                                         CopyFlags    |=    CLONE;
  244.                                     if(Args[DATES_ARG])
  245.                                         CopyFlags    |=    DATES;
  246.                                     if(Args[NOPRO_ARG])
  247.                                         CopyFlags    |=    NOPRO;
  248.                                     if(Args[COM_ARG])
  249.                                         CopyFlags    |=    COM;
  250.                                     if(Args[QUIET_ARG])
  251.                                         CopyFlags    |=    QUIET;
  252.                                     if(Args[FORCE_ARG])
  253.                                         CopyFlags    |=    FORCE;
  254.                                     if(Args[BUFFER_ARG])
  255.                                         MaxBuffer    =    *((ULONG *)Args[BUFFER_ARG]) * 1024;
  256.  
  257.                                         // Check for NOREQ Option
  258.  
  259.                                     if(Args[NOREQ_ARG])
  260.                                     {
  261.                                         OldWindow        = MyProc->pr_WindowPtr;
  262.                                         MyProc->pr_WindowPtr    = (void *)(-1L);
  263.                                     }
  264.  
  265.                                         // Get pointers to Files
  266.  
  267.                                     FromPtr    = (char **)Args[FROM_ARG];
  268.                                     ToPtr    = (char *)Args[TO_ARG];
  269.  
  270.                                         // Count FROM entries
  271.  
  272.                                     while(*FromPtr++)
  273.                                         NumFrom++;
  274.  
  275.                                         // Restore FromPtr
  276.  
  277.                                     FromPtr    = (char **)Args[FROM_ARG];
  278.  
  279.                                         // Set pattern if there are more than 1
  280.                                         // FROM files or if the only FROM file
  281.                                         // is a pattern
  282.  
  283.                                     if(NumFrom > 1)
  284.                                         PatternFrom = TRUE;
  285.                                     else
  286.                                         PatternFrom = ParsePatternNoCase(*FromPtr, Pattern, 1024);
  287.  
  288.                                         // If a pattern is used, check
  289.                                         // whether the dest really is a dir
  290.  
  291.                                     if(PatternFrom)
  292.                                     {
  293.                                             // Try to obtain a lock
  294.  
  295.                                         if((DirLock = Lock(ToPtr, ACCESS_READ)))
  296.                                         {
  297.                                                 // Check file
  298.  
  299.                                             if(Examine(DirLock, FIB))
  300.                                             {
  301.                                                     // Get type of destination entry
  302.  
  303.                                                 GoOn = (FIB->fib_DirEntryType >= 0);
  304.  
  305.                                                     // If it`s not a directory (multiple files are to be moved)
  306.                                                     // issue an error
  307.  
  308.                                                 if(!GoOn)
  309.                                                     FPuts(OutHandle, "\nMove : Multiple files may not be moved to a single file\n");
  310.                                             }
  311.                                             else
  312.                                             {
  313.                                                     // Examine() failed -> Abort
  314.  
  315.                                                 GoOn = FALSE;
  316.                                                 PrintFault(IoErr(), "\nMove ");
  317.                                             }
  318.  
  319.                                                 // Unlock CheckDir
  320.  
  321.                                             UnLock(DirLock);
  322.                                         }
  323.                                         else
  324.                                         {
  325.                                                 // If lock failed issue an error
  326.  
  327.                                             PrintFault(IoErr(), "\nMove ");
  328.                                             GoOn = FALSE;
  329.                                         }
  330.                                     }
  331.  
  332.  
  333.  
  334.                                         // Loop for all source files
  335.  
  336.                                     while(NumFrom && GoOn)
  337.                                     {
  338.                                             // Check for CTRL-C
  339.  
  340.                                         if(GoOn)
  341.                                             HitMask    = CheckSignal(WATCHSIGS);
  342.  
  343.                                         if(!HitMask && GoOn)
  344.                                         {
  345.                                                 // Check if this source is a pattern
  346.  
  347.                                             strcpy(Buffer, FilePart(*FromPtr));
  348.                                             strupr(Buffer);
  349.                                             PatternType = ParsePatternNoCase(Buffer, Pattern, 1024);
  350.  
  351.                                                 // It is a pattern
  352.  
  353.                                             if(PatternType == 1)
  354.                                             {
  355.                                                     // Create name of source
  356.  
  357.                                                 strcpy(Buffer, *FromPtr);
  358.                                                 *PathPart(Buffer)    = '\0';
  359.  
  360.                                                     // Get Lock for Source - Directory
  361.  
  362.                                                 if((DirLock = Lock(Buffer, ACCESS_READ)))
  363.                                                 {
  364.                                                         // Setup ExAllControl-Structure
  365.  
  366.                                                     EAC->eac_LastKey    = 0L;
  367.                                                     EAC->eac_MatchString    = Pattern;
  368.                                                     EAC->eac_MatchFunc    = NULL;
  369.  
  370.                                                     do
  371.                                                     {
  372.                                                             // Check for CTRL-C
  373.  
  374.                                                         if(GoOn)
  375.                                                             HitMask = CheckSignal(WATCHSIGS);
  376.  
  377.                                                         if(HitMask)
  378.                                                             GoOn = FALSE;
  379.  
  380.                                                             // Scan directory
  381.  
  382.                                                         Scanning = ExAll(DirLock, EAB, (20*sizeof(struct ExAllData)), ED_SIZE, EAC);
  383.  
  384.                                                             // Issue Error
  385.  
  386.                                                         if(GoOn && (!Scanning) && (IoErr() != ERROR_NO_MORE_ENTRIES))
  387.                                                         {
  388.                                                             PrintFault(IoErr(), "\nMove ");
  389.                                                             GoOn = FALSE;
  390.                                                         }
  391.  
  392.                                                             // End of Dir reached
  393.  
  394.                                                         if(EAC->eac_Entries == 0)
  395.                                                             Scanning = FALSE;
  396.                                                         else if(GoOn)
  397.                                                         {
  398.                                                             EAD    = EAB;
  399.  
  400.                                                             do
  401.                                                             {
  402.                                                                     // Check for CTRL-C
  403.  
  404.                                                                 if(GoOn)
  405.                                                                     HitMask = CheckSignal(WATCHSIGS);
  406.  
  407.                                                                 if(!HitMask && GoOn)
  408.                                                                 {
  409.                                                                         // Create filename for this file to be moved
  410.  
  411.                                                                     strcpy(PathName, *FromPtr);
  412.                                                                     *PathPart(PathName)    = '\0';
  413.                                                                     AddPart(PathName, EAD->ed_Name, 1024);
  414.  
  415.                                                                         // Move file
  416.  
  417.                                                                     GoOn = DoTheMove(PathName, ToPtr, TRUE, OutHandle, DOSBase, EAD->ed_Type, EAD->ed_Size, CopyFlags, &HitMask, MaxBuffer);
  418.  
  419.                                                                     EAD    = EAD->ed_Next;
  420.                                                                 }
  421.                                                                 else
  422.                                                                     GoOn = FALSE;
  423.  
  424.                                                             } while(EAD && GoOn);
  425.                                                         }
  426.                                                     } while(Scanning);
  427.  
  428.                                                         // Unlock source directory
  429.  
  430.                                                     UnLock(DirLock);
  431.                                                 }
  432.                                                 else
  433.                                                 {
  434.                                                         // Issue error, if dir could not be locked
  435.  
  436.                                                     PrintFault(IoErr(), "\nMove ");
  437.                                                     GoOn    = FALSE;
  438.                                                 }
  439.                                             }
  440.                                                 // No pattern
  441.  
  442.                                             else if(PatternType == 0)
  443.                                             {
  444.                                                     // Try to lock source file/dir
  445.  
  446.                                                 if((DirLock = Lock(*FromPtr, ACCESS_READ)))
  447.                                                 {
  448.                                                         // Examine this lock
  449.  
  450.                                                     if(Examine(DirLock, FIB))
  451.                                                     {
  452.                                                             // Unlock directory and do the move
  453.  
  454.                                                         UnLock(DirLock);
  455.                                                         GoOn = DoTheMove(*FromPtr, ToPtr, TRUE, OutHandle, DOSBase, FIB->fib_DirEntryType, FIB->fib_Size, CopyFlags, &HitMask, MaxBuffer);
  456.                                                     }
  457.                                                     else
  458.                                                     {
  459.                                                             // Issue error on failed Examine()
  460.  
  461.                                                         PrintFault(IoErr(), "\nMove ");
  462.                                                         GoOn = FALSE;
  463.                                                         UnLock(DirLock);
  464.                                                     }
  465.                                                 }
  466.                                                 else
  467.                                                 {
  468.                                                         // No Lock() no more moves
  469.  
  470.                                                     PrintFault(IoErr(), "\nMove ");
  471.                                                     GoOn = FALSE;
  472.                                                 }
  473.                                             }
  474.  
  475.                                                 // Error condition
  476.  
  477.                                             else
  478.                                             {
  479.                                                 PrintFault(IoErr(), "\nMove ");
  480.                                                 GoOn = FALSE;
  481.                                             }
  482.  
  483.                                             NumFrom--;
  484.                                             FromPtr++;
  485.                                         }
  486.                                         else
  487.                                             GoOn    = FALSE;
  488.                                     }
  489.                                 }
  490.  
  491.                                     // Free ReadArgs
  492.  
  493.                                 FreeArgs(RDArgs);
  494.                             }
  495.                             else
  496.                                 PrintFault(IoErr(), "\nMove ");
  497.  
  498.                                 // Free ExAll-Buffer
  499.  
  500.                             FreeVec(EAB);
  501.                         }
  502.                         else
  503.                             PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  504.  
  505.                             // Free ExAllControl Structure
  506.  
  507.                         FreeDosObject(DOS_EXALLCONTROL, (void *)EAC);
  508.                     }
  509.                     else
  510.                         PrintFault(IoErr(), "\nMove ");
  511.  
  512.                         // Free Argument Buffer
  513.  
  514.                     FreeVec(Args);
  515.                 }
  516.                 else
  517.                     PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  518.  
  519.                 FreeVec(FIB);
  520.             }
  521.             else
  522.                 PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  523.         }
  524.         else
  525.             PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  526.  
  527.  
  528.             // Free allocated buffers
  529.  
  530.         if(Pattern)
  531.             FreeVec(Pattern);
  532.  
  533.         if(PathName)
  534.             FreeVec(PathName);
  535.  
  536.         if(Buffer)
  537.             FreeVec(Buffer);
  538.  
  539.  
  540.             // Check for Abort-Signals
  541.  
  542.         if(HitMask && !(CopyFlags & QUIET))
  543.         {
  544.                 // Display appropriate message
  545.  
  546.             if(HitMask & SIGBREAKF_CTRL_C)
  547.                 FPuts(OutHandle, "\nMove ^C...\n");
  548.         }
  549.  
  550.             // Close DOSLibrary
  551.  
  552.         CloseLibrary((struct Library *)DOSBase);
  553.     }
  554.  
  555.         // Restore old window pointer (if any)
  556.  
  557.     if(OldWindow)
  558.         MyProc->pr_WindowPtr    = OldWindow;
  559.  
  560.  
  561.         // Depending on this flag return appropriate return code
  562.  
  563.     if(GoOn)
  564.         return(0);
  565.     else
  566.         return(10);
  567. }
  568.  
  569.  
  570.  
  571.  
  572. /**********************************************************************/
  573. /*                            Do the move                             */
  574. /**********************************************************************/
  575. BOOL __stdargs DoTheMove(char *FromFile, char *ToPath, BOOL PatternFrom, BPTR OutHandle, struct DOSBase *DOSBase, LONG Type, ULONG Size, UWORD CopyFlags, LONG *HitMask, ULONG MaxBuffer)
  576. {
  577.     struct    ExAllControl    *EAC;
  578.     struct    ExAllData    *EAB, *EAD;
  579.     struct    DevProc        *FromDev, *ToDev;
  580.     char    *NewDir;
  581.     char    *Buffer        = NULL;
  582.     char    *ToDir        = NULL;
  583.     UWORD    Len;
  584.     BPTR    DirLock;
  585.     BOOL    RetVal = TRUE, Scanning, DoRename = FALSE;
  586.  
  587.         // Try to allocate buffers
  588.  
  589.     if((NewDir = AllocVec(1024, MEMF_CLEAR)) && (Buffer = AllocVec(1024, MEMF_CLEAR)) && (ToDir = AllocVec(1024, MEMF_CLEAR)))
  590.     {
  591.             // If a pattern is used print the name of the file to be moved
  592.  
  593.         if(PatternFrom && !(CopyFlags & QUIET))
  594.         {
  595.             strcpy(Buffer, FromFile);
  596.             strcat(Buffer, "...");
  597.             Write(OutHandle, " ", 1);
  598.             Write(OutHandle, Buffer, strlen(Buffer));
  599.         }
  600.  
  601.             // Is it a directory ???
  602.             // If yes, recursively loop for all entries within dir
  603.  
  604.         if(Type >= 0)
  605.         {
  606.             strcpy(Buffer, FromFile);
  607.  
  608.                 // Get length of from name
  609.  
  610.             Len    = strlen(Buffer);
  611.             if(Len)
  612.             {
  613.                 if(Buffer[Len - 1] == '/')
  614.                     Buffer[Len - 1] = '\0';
  615.  
  616.                     // Copy dest name to buffer
  617.  
  618.                 strcpy(NewDir, ToPath);
  619.  
  620.                     // Check whether dest dir is on same device
  621.                     // If so, do a simple rename
  622.  
  623.                 FromDev    = GetDeviceProc(Buffer, NULL);
  624.                 ToDev    = GetDeviceProc(NewDir, NULL);
  625.  
  626.                     // If the same device is used -> Do the rename
  627.  
  628.                 if(FromDev && ToDev && (FromDev->dvp_Port == ToDev->dvp_Port))
  629.                     DoRename = TRUE;
  630.  
  631.                 if(FromDev)
  632.                     FreeDeviceProc(FromDev);
  633.  
  634.                 if(ToDev)
  635.                     FreeDeviceProc(ToDev);
  636.  
  637.  
  638.                 if(DoRename)
  639.                 {
  640.                         // Do the rename
  641.  
  642.                     if(!Rename(Buffer, NewDir))
  643.                     {
  644.                         PrintFault(IoErr(), "\nMove ");
  645.                         RetVal = FALSE;
  646.                     }
  647.                 }
  648.                 else
  649.                 {
  650.                         // Add name of from directory
  651.  
  652.                     AddPart(NewDir, FilePart(Buffer), 1024);
  653.  
  654.                         // Clone directory name of source
  655.  
  656.                     strcpy(ToDir, Buffer);
  657.  
  658.                         // Try to lock directory or
  659.                         // create it, if not existent
  660.  
  661.                     if(!(DirLock = Lock(NewDir, ACCESS_READ)))
  662.                     {
  663.                         if((DirLock = CreateDir(NewDir)) && PatternFrom && !(CopyFlags & QUIET))
  664.                             Write(OutHandle, " [created]...", 13);
  665.                     }
  666.  
  667.                         // Got the destination directory ???
  668.  
  669.                     if(DirLock)
  670.                     {
  671.                             // Unlock Directory
  672.  
  673.                         UnLock(DirLock);
  674.  
  675.                             // Lock sourcedirectory
  676.  
  677.                         if((DirLock = Lock(Buffer, ACCESS_READ)))
  678.                         {
  679.                                 // Get ExAll Control for recursive directory search
  680.  
  681.                             if((EAC = AllocDosObject(DOS_EXALLCONTROL, NULL)))
  682.                             {
  683.                                     // Allocate buffer for move
  684.  
  685.                                 if((EAB = AllocVec((20*sizeof(struct ExAllData)), MEMF_CLEAR)))
  686.                                 {
  687.                                     EAC->eac_LastKey    = 0L;
  688.                                     EAC->eac_MatchString    = NULL;
  689.                                     EAC->eac_MatchFunc    = NULL;
  690.  
  691.                                     do
  692.                                     {
  693.                                             // Check for CTRL-C
  694.  
  695.                                         if(RetVal)
  696.                                             (*HitMask) = CheckSignal(WATCHSIGS);
  697.  
  698.                                         if((*HitMask))
  699.                                             RetVal = FALSE;
  700.  
  701.                                             // Scan directory for entries
  702.  
  703.                                         Scanning = ExAll(DirLock, EAB, (20*sizeof(struct ExAllData)), ED_SIZE, EAC);
  704.  
  705.                                             // Check for an error
  706.  
  707.                                         if(RetVal && (!Scanning) && (IoErr() != ERROR_NO_MORE_ENTRIES))
  708.                                         {
  709.                                             PrintFault(IoErr(), "\nMove ");
  710.                                             RetVal = FALSE;
  711.                                         }
  712.  
  713.                                             // End of Dir reached
  714.  
  715.                                         if(EAC->eac_Entries == 0)
  716.                                             Scanning = FALSE;
  717.                                         else if(RetVal)
  718.                                         {
  719.                                             EAD = EAB;
  720.  
  721.                                             do
  722.                                             {
  723.                                                     // Check for CTRL-C
  724.  
  725.                                                 if(RetVal)
  726.                                                     (*HitMask) = CheckSignal(WATCHSIGS);
  727.  
  728.                                                 if(!(*HitMask) && RetVal)
  729.                                                 {
  730.                                                         // Create filename of source
  731.  
  732.                                                     strcpy(Buffer, FromFile);
  733.                                                     AddPart(Buffer, EAD->ed_Name, 1024);
  734.  
  735.                                                         // And start recursion
  736.  
  737.                                                     RetVal = DoTheMove(Buffer, NewDir, FALSE, OutHandle, DOSBase, EAD->ed_Type, EAD->ed_Size, CopyFlags, HitMask, MaxBuffer);
  738.  
  739.                                                         // Loop for all entries
  740.  
  741.                                                     EAD = EAD->ed_Next;
  742.                                                 }
  743.                                                 else
  744.                                                     RetVal = FALSE;
  745.  
  746.                                             } while(EAD && RetVal);
  747.                                         }
  748.                                     } while(Scanning);
  749.  
  750.                                         // Free ExAll Buffer
  751.  
  752.                                     FreeVec(EAB);
  753.                                 }
  754.                                 else
  755.                                 {
  756.                                     PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  757.                                     RetVal = FALSE;
  758.                                 }
  759.  
  760.                                     // Free ExAllControl Structure
  761.  
  762.                                 FreeDosObject(DOS_EXALLCONTROL, EAC);
  763.                             }
  764.                             else
  765.                             {
  766.                                 PrintFault(IoErr(), "\nMove ");
  767.                                 RetVal = FALSE;
  768.                             }
  769.  
  770.                             UnLock(DirLock);
  771.                         }
  772.                         else
  773.                         {
  774.                             PrintFault(IoErr(), "\nMove ");
  775.                             RetVal = FALSE;
  776.                         }
  777.                     }
  778.                     else
  779.                     {
  780.                         PrintFault(IoErr(), "\nMove ");
  781.                         RetVal = FALSE;
  782.                     }
  783.                 }
  784.             }
  785.  
  786.                 // Ok, this dir was moved (no rename), so remove it
  787.  
  788.             if(RetVal && !DoRename)
  789.             {
  790.                     // With force mode set on,
  791.                     // First make dir deletable
  792.  
  793.                 if(CopyFlags & FORCE)
  794.                     SetProtection(ToDir, ~(FIBF_OTR_WRITE|FIBF_OTR_DELETE|FIBF_WRITE|FIBF_DELETE));
  795.  
  796.                     // Delete directory
  797.  
  798.                 if(!DeleteFile(ToDir))
  799.                 {
  800.                     PrintFault(IoErr(), "\nMove ");
  801.                     RetVal = FALSE;
  802.                 }
  803.             }
  804.         }
  805.         else
  806.         {
  807.                 // On a plain file -> Simply move it
  808.  
  809.             RetVal = DoMoveFile(FromFile, ToPath, Buffer, OutHandle, DOSBase, Size, CopyFlags, HitMask, MaxBuffer);
  810.         }
  811.  
  812.             // If there was a pattern (or a single directory)
  813.             // end the Move string
  814.  
  815.         if(PatternFrom && RetVal && !(CopyFlags & QUIET))
  816.             FPuts(OutHandle, " moved\n");
  817.     }
  818.     else
  819.     {
  820.         PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  821.         RetVal = FALSE;
  822.     }
  823.  
  824.         // De-Allocate buffers
  825.  
  826.     if(NewDir)
  827.         FreeVec(NewDir);
  828.  
  829.     if(Buffer)
  830.         FreeVec(Buffer);
  831.  
  832.     if(ToDir)
  833.         FreeVec(ToDir);
  834.  
  835.         // Return Code
  836.  
  837.     return(RetVal);
  838. }
  839.  
  840.  
  841.  
  842.  
  843.  
  844. /**********************************************************************/
  845. /*                      Ein File wirklich moven                       */
  846. /**********************************************************************/
  847. BOOL __stdargs DoMoveFile(char *FromFile, char *ToPath, char *Buffer, BPTR OutHandle, struct DOSBase *DOSBase, ULONG Size, UWORD CopyFlags, LONG *HitMask, ULONG MaxBuffer)
  848. {
  849.     struct    FileInfoBlock    *FIB;
  850.     struct    DevProc        *FromDev, *ToDev;
  851.     BPTR    InFile, OutFile;
  852.     APTR    CopyBuffer;
  853.     char    *DestName;
  854.     ULONG    AvailSize, ReadSize;
  855.     LONG    InKey = -1, OutKey = -1;
  856.     BOOL    RetVal = TRUE, ErrCpy = FALSE, LoopCpy = TRUE, DoRename = FALSE, RemoveFirst = FALSE;
  857.  
  858.  
  859.         // Allocate buffer for Destination name
  860.  
  861.     if(!(DestName = AllocVec(1024, MEMF_CLEAR)))
  862.     {
  863.         PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  864.         return(FALSE);
  865.     }
  866.  
  867.     if((FIB = AllocVec(sizeof(struct FileInfoBlock), MEMF_CLEAR)))
  868.     {
  869.  
  870.         strcpy(DestName, ToPath);
  871.  
  872.             // Check, if destfile already exists
  873.             // If so, check if it`s a dir.
  874.             // Yes -> Copy with sourcename
  875.             // No -> Copy with given name
  876.  
  877.         if((OutFile = Lock(DestName, ACCESS_READ)))
  878.         {
  879.             if(Examine(OutFile, FIB))
  880.             {
  881.                     // If dest is a directory move with source name
  882.  
  883.                 if(FIB->fib_DirEntryType >= 0)
  884.                     AddPart(DestName, FilePart(FromFile), 1024);
  885.                 else
  886.                 {
  887.                     OutKey        = ((struct FileLock *)BADDR(OutFile))->fl_Key;
  888.                     RemoveFirst    = TRUE;
  889.                 }
  890.             }
  891.             else
  892.             {
  893.                     // No examine -> Use source filename
  894.  
  895.                 AddPart(DestName, FilePart(FromFile), 1024);
  896.             }
  897.  
  898.             UnLock(OutFile);
  899.         }
  900.  
  901.             // Try to lock input file
  902.  
  903.         if((InFile = Lock(FromFile, ACCESS_READ)))
  904.         {
  905.                 // Get DiskBlock for inputfile
  906.  
  907.             InKey    = ((struct FileLock *)BADDR(InFile))->fl_Key;
  908.  
  909.                 // Get old protection bits, comment and filedate
  910.  
  911.             if(Examine(InFile, FIB))
  912.             {
  913.                     // In Force mode -> Force read and delete permissons
  914.                     // for input file
  915.  
  916.                 if(CopyFlags & FORCE)
  917.                     SetProtection(FromFile, ~(FIBF_OTR_READ|FIBF_OTR_DELETE|FIBF_READ|FIBF_DELETE));
  918.             }
  919.             else
  920.             {
  921.                 PrintFault(IoErr(), "\nMove ");
  922.                 RetVal = FALSE;
  923.             }
  924.  
  925.                 // If so, unlock
  926.  
  927.             UnLock(InFile);
  928.         }
  929.         else
  930.         {
  931.             PrintFault(IoErr(), "\nMove ");
  932.             RetVal = FALSE;
  933.         }
  934.  
  935.  
  936.             // Check whether to use a Rename() or a real Copy-Mode
  937.  
  938.         FromDev    = GetDeviceProc(FromFile, NULL);
  939.         ToDev    = GetDeviceProc(DestName, NULL);
  940.  
  941.             // If the same device is used -> Do the rename
  942.  
  943.         if(FromDev && ToDev && (FromDev->dvp_Port == ToDev->dvp_Port))
  944.             DoRename = TRUE;
  945.  
  946.         if(FromDev)
  947.             FreeDeviceProc(FromDev);
  948.  
  949.         if(ToDev)
  950.             FreeDeviceProc(ToDev);
  951.  
  952.  
  953.             // No Rename -> Do the right move ;)
  954.  
  955.         if(!DoRename)
  956.         {
  957.                 // Open Input file
  958.  
  959.             if(RetVal && (InFile = Open(FromFile, MODE_OLDFILE)))
  960.             {
  961.                     // Outfile already there ??? and in force mode ???
  962.  
  963.                 if((CopyFlags & FORCE) && ((OutFile = Lock(DestName, ACCESS_READ))))
  964.                 {
  965.                         // Force delete and write permissons
  966.  
  967.                     UnLock(OutFile);
  968.                     SetProtection(DestName, ~(FIBF_OTR_WRITE|FIBF_OTR_DELETE|FIBF_WRITE|FIBF_DELETE));
  969.                 }
  970.  
  971.                     // Open Output file
  972.  
  973.                 if((OutFile = Open(DestName, MODE_NEWFILE)))
  974.                 {
  975.                         // Is there any data within the file ???
  976.  
  977.                     if(Size)
  978.                     {
  979.                             // Get available size of memory
  980.                             // or take the user`s buffer size into account
  981.  
  982.                         AvailSize    = (MaxBuffer != 0) ? MaxBuffer : (AvailMem(MEMF_LARGEST) - 102400);
  983.                         Size        = (Size > AvailSize) ? AvailSize : Size;
  984.  
  985.                             // Loop till we get a buffer
  986.  
  987.                         while(Size && !(CopyBuffer = AllocVec(Size, MEMF_CLEAR)))
  988.                             Size    -= 1024;
  989.  
  990.                         if(CopyBuffer)
  991.                         {
  992.                                 // Loop for portions of the source file
  993.  
  994.                             while(RetVal && LoopCpy)
  995.                             {
  996.                                     // Check for CTRL-C
  997.  
  998.                                 if(RetVal)
  999.                                     (*HitMask) = CheckSignal(WATCHSIGS);
  1000.  
  1001.                                 if(!(*HitMask) && RetVal)
  1002.                                 {
  1003.                                         // Read part of file
  1004.  
  1005.                                     if((ReadSize = Read(InFile, CopyBuffer, Size)) > 0)
  1006.                                     {
  1007.                                             // And write it back
  1008.  
  1009.                                         if(Write(OutFile, CopyBuffer, ReadSize) == -1)
  1010.                                         {
  1011.                                             PrintFault(IoErr(), "\nMove ");
  1012.                                             RetVal    = FALSE;
  1013.                                             ErrCpy    = TRUE;
  1014.                                         }
  1015.                                     }
  1016.                                     else
  1017.                                     {
  1018.                                             // EOF ??? -> End copy
  1019.  
  1020.                                         if(ReadSize == 0)
  1021.                                             LoopCpy    = FALSE;
  1022.                                         else
  1023.                                         {
  1024.                                                 // Otherwise issue error
  1025.  
  1026.                                             PrintFault(IoErr(), "\nMove ");
  1027.                                             RetVal    = FALSE;
  1028.                                             ErrCpy    = TRUE;
  1029.                                         }
  1030.                                     }
  1031.                                 }
  1032.                                 else
  1033.                                     RetVal = FALSE;
  1034.                             }
  1035.  
  1036.                                 // Free Copy buffer
  1037.  
  1038.                             FreeVec(CopyBuffer);
  1039.                         }
  1040.                         else
  1041.                         {
  1042.                                 // Issue error
  1043.  
  1044.                             PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  1045.                             RetVal    = FALSE;
  1046.                             ErrCpy    = TRUE;
  1047.                         }
  1048.  
  1049.                             // Close outfile
  1050.                     }
  1051.  
  1052.                     Close(OutFile);
  1053.                 }
  1054.                 else
  1055.                 {
  1056.                         // Issue error
  1057.  
  1058.                     PrintFault(IoErr(), "\nMove ");
  1059.                     RetVal = FALSE;
  1060.                 }
  1061.                     // Close InFile
  1062.  
  1063.                 Close(InFile);
  1064.             }
  1065.             else
  1066.             {
  1067.                     // Issue error
  1068.  
  1069.                 PrintFault(IoErr(), "\nMove ");
  1070.                 RetVal = FALSE;
  1071.             }
  1072.         }
  1073.         else
  1074.         {
  1075.                 // If RemoveFirst is not set, check again ;)
  1076.  
  1077.             if(!RemoveFirst)
  1078.             {
  1079.                 if((OutFile = Lock(DestName, ACCESS_READ)))
  1080.                 {
  1081.                     if(Examine(OutFile, FIB))
  1082.                     {
  1083.                             // If dest is a file, delete first
  1084.  
  1085.                         if(FIB->fib_DirEntryType < 0)
  1086.                         {
  1087.                                 // Get Disk block of dest file
  1088.  
  1089.                             OutKey    = ((struct FileLock *)BADDR(OutFile))->fl_Key;
  1090.                             RemoveFirst = TRUE;
  1091.                         }
  1092.                     }
  1093.                     UnLock(OutFile);
  1094.                 }
  1095.             }
  1096.  
  1097.                 // Check if only a rename should be accomplished
  1098.  
  1099.             if(InKey != -1 && OutKey != -1)
  1100.             {
  1101.                 if(InKey == OutKey)
  1102.                     RemoveFirst = FALSE;
  1103.             }
  1104.  
  1105.                 // In Rename() mode, the destination has to be removed first
  1106.  
  1107.             if(RemoveFirst)
  1108.             {
  1109.                     // If dest file is protected check for FORCE flag
  1110.  
  1111.                 if(CopyFlags & FORCE)
  1112.                     SetProtection(DestName, ~(FIBF_OTR_WRITE|FIBF_OTR_DELETE|FIBF_WRITE|FIBF_DELETE));
  1113.  
  1114.                 if(!DeleteFile(DestName))
  1115.                 {
  1116.                     PrintFault(IoErr(), "\nMove ");
  1117.                     RetVal = FALSE;
  1118.                 }
  1119.             }
  1120.  
  1121.             if(RetVal)
  1122.             {
  1123.                     // Now try to "rename" the file
  1124.  
  1125.                 if(!Rename(FromFile, DestName))
  1126.                 {
  1127.                     PrintFault(IoErr(), "\nMove ");
  1128.                     RetVal = FALSE;
  1129.                 }
  1130.             }
  1131.         }
  1132.  
  1133.             // Error while copying ?? -> Remove Dest file
  1134.  
  1135.         if(ErrCpy)
  1136.         {
  1137.             FPuts(OutHandle, "\nMove : Error while moving; destination removed.\n");
  1138.             DeleteFile(DestName);
  1139.         }
  1140.  
  1141.             // No Error -> Remove Source file
  1142.  
  1143.         if(RetVal && !ErrCpy)
  1144.         {
  1145.             if(!DoRename && !(RetVal = DeleteFile(FromFile)))
  1146.                 PrintFault(IoErr(), "\nMove ");
  1147.             else
  1148.             {
  1149.                     // Set bits etc. as requested
  1150.  
  1151.                 if((CopyFlags & CLONE) || (CopyFlags & DATES))
  1152.                     SetFileDate(DestName, &FIB->fib_Date);
  1153.  
  1154.                 if((CopyFlags & CLONE) || (CopyFlags & COM))
  1155.                     SetComment(DestName, FIB->fib_Comment);
  1156.  
  1157.                 if(((CopyFlags & CLONE) && !(CopyFlags & NOPRO)) || (!(CopyFlags & CLONE) && !(CopyFlags & NOPRO)))
  1158.                     SetProtection(DestName, FIB->fib_Protection);
  1159.             }
  1160.         }
  1161.  
  1162.             // Free FileInfo Block
  1163.  
  1164.         FreeVec(FIB);
  1165.     }
  1166.     else
  1167.     {
  1168.         PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  1169.         RetVal = FALSE;
  1170.     }
  1171.  
  1172.         // Free buffer for destination name
  1173.  
  1174.     FreeVec(DestName);
  1175.  
  1176.     return(RetVal);
  1177. }
  1178.