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