home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d6xx / d652 / burf.lha / Burf / Burf next >
Text File  |  1992-05-14  |  19KB  |  342 lines

  1. /* BackUp ReFresher 1.00 */
  2. /* Copyright © Michael Tanzer, 1992 */
  3. /* See additional notices in accompanying documentation */
  4.  
  5. flagsw = 0                 /* 1 = check & set archive flag; 0 = check date */
  6. clonesw = 1                /* 1 = Delete disused directories and files...  */
  7.                            /*     ...and ensure exact match on names       */
  8. ressw = 0                  /* 1 = Make COPY and PROTECT commands resident  */
  9. asynchsw = 1               /* 1 = Run Burf asynchronously                  */
  10. log = 'ram:BurfLog'        /* Log file: may be '*' (console) or a file id  */
  11.                            /*     e.g. 'RAM:BurfLog')                      */
  12.  
  13. parse arg source target .               /* Get requested directories       */
  14. if source=='?' | upper(source)=='HELP' | words(source)=0 then do
  15.   say 'Use Burf to refresh a backup of a directory.'
  16.   say 'Format: RX BURF source <target>'
  17.   say 'If no target is specified, the current directory will be used.'
  18.   exit
  19.   end
  20.  
  21. /* Make sure support library is available */
  22. call addlib 'rexxsupport.library',0,-30,0
  23.  
  24. /* If running asynchronously, get source and target */
  25. if getclip('Burf.asynchsw')=1 then do   /* Already running asynchronously  */
  26.   source = getclip('Burf.source')       /* Get the source directory        */
  27.   target = getclip('Burf.target')       /* Get the target directory        */
  28.   call setclip('Burf.asynchsw')         /* Delete clips                    */
  29.   call setclip('Burf.source')
  30.   call setclip('Burf.target')
  31.   end
  32.  
  33. /* If running synchronously, verify parameters */
  34. else do
  35.   w = word(statef(source),1)            /* Check source data               */
  36.   if w=='FILE' then do                  /* Source is not a directory       */
  37.     say 'Source object not of required type.'
  38.     exit 212
  39.     end
  40.   if w~=='DIR' then do                  /* Source not found                */
  41.     say 'Source directory not found.'
  42.     exit 204
  43.     end
  44.   w = substr(source,length(source),1)   /* Dir must end in '/' or ':'      */
  45.   if w~=='/' & w~==':' then source = source'/'
  46.   if words(target)=0 then target = pragma('directory') /* Cur if no target */
  47.   w = word(statef(target),1)            /* Check target data               */
  48.   if w=='FILE' then do                  /* Target is not a directory       */
  49.     say 'Target object not of required type.'
  50.     exit 212
  51.     end
  52.   if clonesw then do                    /* Cloning can be dangerous!       */
  53.     say 'Burf may delete subdirectories and files in' target'.'
  54.     say 'Enter ''GO'' if you want to continue.'
  55.     pull w
  56.     if w~='GO' then do
  57.       say 'Operation aborted.'
  58.       exit
  59.       end
  60.     end
  61.   w = substr(target,length(target),1)   /* Dir must end in '/' or ':'      */
  62.   if w~=='/' & w~==':' then target = target'/'
  63.   if asynchsw then do                   /* Set up for asynch task          */
  64.     if log='*' then do                  /* Can't run asynch w/console      */
  65.       say 'Burf cannot run asynchronously and write its log to a console.'
  66.       say 'Change the setting of either ''asynchsw'' or ''log''.'
  67.       exit 97
  68.       end
  69.     call setclip('Burf.asynchsw',1)     /* Set flag for asynch task        */
  70.     call setclip('Burf.source',source)  /* Store source for asynch task    */
  71.     call setclip('Burf.target',target)  /* Store target for asynch task    */
  72.     address arexx 'Burf' source target  /* Launch asynch task              */
  73.     say 'Asynchronous Burf task started.'
  74.     exit                                /* Free up CLI                     */
  75.     end
  76.   end
  77.  
  78. /* Open the log file */
  79. call open 'logfile',log,'W'
  80. if ~result then do                      /* Handle error                    */
  81.   say 'Unable to open log file.'        /* Try to display error message    */
  82.   exit 99                               /* Pass non-zero return code       */
  83.   end
  84.  
  85. source.1 = source                       /* Check source directory first    */
  86. target.1 = target                       /* Set corresponding target        */
  87. dx = 1                                  /* Set directory index             */
  88. dircnt  = 0                             /* Clear directory count           */
  89. mdircnt = 0                             /* Clear directories made count    */
  90. drencnt = 0                             /* Clear directories renamed count */
  91. ddelcnt = 0                             /* Clear directories deleted count */
  92. filecnt = 0                             /* Clear file count                */
  93. replcnt = 0                             /* Clear files replaced count      */
  94. copycnt = 0                             /* Clear files copied count        */
  95. frencnt = 0                             /* Clear files renamed count       */
  96. fdelcnt = 0                             /* Clear files deleted count       */
  97. errorcnt = 0                            /* Clear error count               */
  98.  
  99. signal on error                         /* Trap ADDRESS COMMAND errors     */
  100.  
  101. /* Make COPY and PROTECT commands resident */
  102. if ressw then do
  103.   address command 'RESIDENT C:COPY'
  104.   if flagsw then address command 'RESIDENT C:PROTECT'
  105.   end
  106.  
  107. /* Loop through files and subdirectories */
  108. do forever
  109.   if dx=0 then leave                    /* No more subdirs                 */
  110.   source = source.dx                    /* Get new source directory        */
  111.   target = target.dx                    /* Get corresponding target dir    */
  112.   call ckfiles                          /* Go check files                  */
  113.   dx = dx-1                             /* Decrement directory index       */
  114.   call getdirs                          /* Go get more subdirs             */
  115.   end
  116.  
  117. /* Remove COPY and PROTECT commands from storage */
  118. if ressw then do
  119.   address command 'RESIDENT COPY REMOVE'
  120.   if flagsw then address command 'RESIDENT PROTECT REMOVE'
  121.   end
  122.  
  123. /* Type the totals and get out */
  124. call writelog 'Source directories checked:' right(dircnt,5)
  125. call writelog 'Target directories made:   ' right(mdircnt,5)
  126. call writelog 'Target directories renamed:' right(drencnt,5)
  127. call writelog 'Target directories deleted:' right(ddelcnt,5)
  128. call writelog 'Source files checked:      ' right(filecnt,5)
  129. call writelog 'Target files replaced:     ' right(replcnt,5)
  130. call writelog 'Target files added:        ' right(copycnt,5)
  131. call writelog 'Target files renamed:      ' right(frencnt,5)
  132. call writelog 'Target files deleted:      ' right(fdelcnt,5)
  133. call writelog 'Errors:                    ' right(errorcnt,5)
  134. if asynchsw then address command,
  135.   'sys:utilities/say "Burf has finished."'
  136. exit
  137.  
  138. /* Subroutines */
  139. getdirs:                                /* Get subdirectories              */
  140.   sdirnames = showdir(source,'d')       /* Get the source subdir names     */
  141.   if clonesw then do                    /* If deleting disused dirs...     */
  142.     tdirnames = showdir(target,'d')     /* ...get target subdir names...   */
  143.     udirnames = upper(tdirnames)        /* ...get UC version               */
  144.     end
  145.   wcnt = words(sdirnames)               /* Save the count                  */
  146.   do wx = 1 to wcnt                     /* Add names to array              */
  147.     dirname = word(sdirnames,wx)        /* Get directory name              */
  148.     dx = dx+1                           /* Bump directory index            */
  149.     source.dx = source||dirname'/'      /* Save new subdir name            */
  150.     target.dx = target||dirname'/'      /* Save corresp target             */
  151.     if ~clonesw then iterate            /* Don't delete disused dirs       */
  152.     w = find(udirnames,upper(dirname))  /* Find name in UC list            */
  153.     if w=0 then iterate                 /* Go for next one if not found    */
  154.     tdirname = word(tdirnames,w)        /* Get name from target list       */
  155.     if tdirname~==dirname then do       /* Case mismatch                   */
  156.       call writelog '  Renaming directory: ' target||tdirname 'to',
  157.         target||dirname
  158.       call rename target||tdirname,target||dirname /* Rename it            */
  159.       if result then drencnt = drencnt+1/* Bump directories renamed count  */
  160.       else do                           /* Handle error                    */
  161.         errorcnt = errorcnt+1           /* Bump error count                */
  162.         call writelog '! Rename failed.'
  163.         end
  164.       end
  165.     udirnames = delword(udirnames,w,1)  /* Remove name from UC list        */
  166.     tdirnames = delword(tdirnames,w,1)  /* Remove name from LC list        */
  167.     end
  168.   if ~clonesw then return               /* Don't delete disused subdirs    */
  169.   wcnt = words(tdirnames)               /* Get number of dirs to delete    */
  170.   do wx = 1 to wcnt                     /* Add names to array              */
  171.     victim.wx = target||word(tdirnames,wx)'/' /* Name must end with '/'    */
  172.     end
  173.   vx = wcnt                             /* Get number of disused subdirs   */
  174.   do forever                            /* Loop through disused subdirs    */
  175.     if vx=0 then leave                  /* No more subdirs                 */
  176.     victim = victim.vx                  /* Get next disused subdir         */
  177.     vdirnames = showdir(victim,'d')     /* Get lower level subdir names    */
  178.     wcnt = words(vdirnames)             /* Save the count                  */
  179.     do wx = 1 to wcnt                   /* Add names to array              */
  180.       dirname = word(vdirnames,wx)      /* Get subdir name                 */
  181.       vx = vx+1                         /* Bump disused subdir index       */
  182.       victim.vx = victim||dirname'/'    /* Save new name                   */
  183.       end
  184.     if wcnt>0 then iterate              /* More subdirs to check           */
  185.     vfilenames = showdir(victim,'f')    /* Get the disused file names      */
  186.     wcnt = words(vfilenames)            /* Save the count                  */
  187.     do wx = 1 to wcnt                   /* Loop through disused files      */
  188.       filename = victim||word(vfilenames,wx) /* File to be deleted         */
  189.       call writelog '      Deleting file:  ' filename
  190.       call delete filename              /* Delete it                       */
  191.       if result then fdelcnt = fdelcnt+1/* Bump files deleted count        */
  192.       else do                           /* Handle error                    */
  193.         errorcnt = errorcnt+1           /* Bump error count                */
  194.         call writelog '!     Delete failed'
  195.         end
  196.       end
  197.     dirname = substr(victim,1,length(victim)-1) /* Remove '/' from name    */
  198.     call writelog '  Deleting directory: ' dirname
  199.     call delete dirname                 /* Delete disused subdir           */
  200.     if result then ddelcnt = ddelcnt+1  /* Bump directories deleted count  */
  201.     else do                             /* Handle error                    */
  202.       errorcnt = errorcnt+1             /* Bump error count                */
  203.       call writelog '! Delete failed.'
  204.       end
  205.     vx = vx-1                           /* Decrement index                 */
  206.     end
  207.   drop victim. victim vdirnames vfilenames
  208.   return
  209.  
  210. ckfiles:                                /* Check file dates or flags       */
  211.   dircnt = dircnt+1                     /* Bump directory count            */
  212.   call writelog '  Checking directory: ' source
  213.   w = word(statef(target),1)            /* Make sure target dir exists     */
  214.   if w=='FILE' then do                  /* Target exists as file           */
  215.     w = substr(target,1,length(target)-1) /* Remove '/' from target        */
  216.     errorcnt = errorcnt+1               /* Bump error count                */
  217.     call writelog '! File found:         ' w
  218.     return                              /* Bypass this directory           */
  219.     end
  220.   if w~=='DIR' then do                  /* Target does not exist           */
  221.     w = length(target)                  /* Get length of target name       */
  222.     if substr(target,w)==':' then do    /* Target is a device              */
  223.       call writelog 'Device not found:' target
  224.       call writelog 'Operation aborted.'
  225.       exit 205
  226.       end
  227.     w = substr(target,1,w-1)            /* Remove '/' from target          */
  228.     call writelog '  Making directory:   ' target
  229.     call makedir(w)                     /* Make new directory              */
  230.     if result then mdircnt = mdircnt+1  /* Bump directories made count     */
  231.     else do                             /* Handle error                    */
  232.       call writelog 'Unable to make directory:' w
  233.       call writelog 'Operation aborted.'
  234.       exit 204
  235.       end
  236.     end
  237.  
  238.   sfilenames = showdir(source,'f')      /* Get the source file names       */
  239.   if clonesw then do                    /* If deleting disused files...    */
  240.     tfilenames = showdir(target,'f')    /* ...get target file names...     */
  241.     ufilenames = upper(tfilenames)      /* ...get UC version               */
  242.     end
  243.   wcnt = words(sfilenames)              /* Save the count                  */
  244.   do wx = 1 to wcnt
  245.     filecnt = filecnt+1                 /* Bump file count                 */
  246.     filename = word(sfilenames,wx)      /* Get a filename                  */
  247.     call writelog '      Checking file:  ' filename
  248.     sourcefile = source||filename       /* Get source filename             */
  249.     targetfile = target||filename       /* Get target filename             */
  250.     tinfo = statef(targetfile)          /* Get target file info            */
  251.     if word(tinfo,1)=='DIR' then do     /* Target exists as directory      */
  252.       errorcnt = errorcnt+1             /* Bump error count                */
  253.       call writelog '!     Directory found:' targetfile
  254.       iterate                           /* Go check next file              */
  255.       end
  256.     if length(tinfo)=0 then do          /* Target file does not exist      */
  257.       call writelog '      Copying file:   ' filename
  258.       address command 'COPY "'sourcefile'" "'targetfile'" CLONE' /* Copy   */
  259.       if flagsw then address command 'PROTECT "'sourcefile'" +A'/* Set flag*/
  260.       copycnt = copycnt+1               /* Bump copy count                 */
  261.       iterate                           /* Go check next file              */
  262.       end
  263.     if clonesw then do                  /* If deleting disused files:      */
  264.       w = find(ufilenames,upper(filename)) /* Find name in UC list         */
  265.       tfilename = word(tfilenames,w)       /* Get name from LC list        */
  266.       ufilenames = delword(ufilenames,w,1) /* Remove name from UC list     */
  267.       tfilenames = delword(tfilenames,w,1) /* Remove name from LC list     */
  268.       end
  269.     sinfo = statef(sourcefile)          /* Get source file info            */
  270.     if flagsw then do                   /* Check arhcive flag, not date    */
  271.       w = substr(word(sinfo,4),4,1)     /* Isolate archive flag            */
  272.       if w='A' then do                  /* File has been archived          */
  273.         if clonesw then call ckcase     /* Go check for case mismatch      */
  274.         iterate                         /* Go check next file              */
  275.         end
  276.       call writelog '      Replacing file: ' filename
  277.       address command 'COPY "'sourcefile'" "'targetfile'" CLONE' /* Replace*/
  278.       address command 'PROTECT "'sourcefile'" +A' /* Set archive flag      */
  279.       replcnt = replcnt+1               /* Bump replace count              */
  280.       iterate                           /* Go check next file              */
  281.       end
  282.     days = right(word(sinfo,5),4,'0')   /* Get days                        */
  283.     mins = right(word(sinfo,6),4,'0')   /* Get minutes                     */
  284.     tics = right(word(sinfo,7),4,'0')   /* Get ticks                       */
  285.     sourcedate = days||mins||tics       /* Build source date               */
  286.     days = right(word(tinfo,5),4,'0')   /* Get days                        */
  287.     mins = right(word(tinfo,6),4,'0')   /* Get minutes                     */
  288.     tics = right(word(tinfo,7),4,'0')   /* Get ticks                       */
  289.     targetdate = days||mins||tics       /* Build target date               */
  290.     if sourcedate<targetdate then do    /* Target file is newer            */
  291.       errorcnt = errorcnt+1             /* Bump error count                */
  292.       call writelog '!     Backup is newer.'
  293.       iterate                           /* Go check next file              */
  294.       end
  295.     if sourcedate~>targetdate then do   /* No replacement required         */
  296.       if clonesw then call ckcase       /* Go check for case mismatch      */
  297.       iterate                           /* Go check next file              */
  298.       end
  299.     call writelog '      Replacing file: ' filename
  300.     address command 'COPY "'sourcefile'" "'targetfile'" CLONE' /* Replace  */
  301.     replcnt = replcnt+1                 /* Bump replace count              */
  302.     end
  303.   if ~clonesw then return               /* Don't delete disused files      */
  304.   wcnt = words(tfilenames)              /* Get number of files to delete   */
  305.   do wx = 1 to wcnt                     /* Delete disused files            */
  306.     filename = target||word(tfilenames,wx) /* File to be deleted           */
  307.     call writelog '      Deleting file:  ' filename
  308.     call delete filename                /* Delete it                       */
  309.     if result then fdelcnt = fdelcnt+1  /* Bump files deleted count        */
  310.     else do                             /* Handle error                    */
  311.       errorcnt = errorcnt+1             /* Bump error count                */
  312.       call writelog '!     Delete failed'
  313.       end
  314.     end
  315.   return
  316.  
  317. /* Check filename case and rename if required */
  318. ckcase:
  319.   if tfilename==filename then return    /* No case mismatch                */
  320.   call writelog '      Renaming file:  ' target||tfilename
  321.   call rename target||tfilename,target||filename /* Rename it              */
  322.   if result then frencnt = frencnt+1    /* Bump files renamed count        */
  323.   else do                               /* Handle error                    */
  324.     errorcnt = errorcnt+1               /* Bump error count                */
  325.     call writelog '!     Rename failed.'
  326.     end
  327.   return
  328.  
  329. /* Write a line to the log file */
  330. writelog:
  331.   parse arg line                        /* Get the line                    */
  332.   call writeln 'logfile',line           /* Write it                        */
  333.   if result>0 then return               /* Return if all is well           */
  334.   say 'Unable to write to log file.'    /* Try to display error message    */
  335.   exit 98                               /* Pass non-zero return code       */
  336.  
  337. /* Handle non-zero return code from ADDRESS COMMAND */
  338. error:
  339.   call writelog 'Operation aborted.'
  340.   if asynchsw then address command,
  341.     'sys:utilities/say "Burf operation aborted"'
  342.   exit rc