home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / disks / tools / dupfinder / dupfinder.c < prev    next >
C/C++ Source or Header  |  1981-06-29  |  9KB  |  320 lines

  1. #define __USE_SYSBASE
  2.  
  3. #include <exec/execbase.h>
  4. #include <exec/memory.h>
  5. #include <dos/exall.h>
  6. #include <libraries/utgui.h>
  7. #include <clib/exec_protos.h>
  8. #include <clib/dos_protos.h>
  9. #include <clib/utgui_protos.h>
  10. #include <clib/alib_protos.h>
  11. #include <pragmas/exec_pragmas.h>
  12. #include <pragmas/dos_pragmas.h>
  13. #include <pragmas/utgui_pragmas.h>
  14. #include <string.h>
  15. #include <stdlib.h>
  16.  
  17. #define BUFSIZE 2000
  18.  
  19. static UBYTE *version_string = "$VER: DupFinder 1.0 (24.4.95)";
  20.  
  21. UBYTE *template = "PATH/A/M,NAMES/S,MINSIZE=MIN/N,NOICONS=NOINFO/S,PRI/N";
  22.  
  23. enum {
  24.     PATH,
  25.     NAMES,
  26.     MINSIZE,
  27.     NOICONS,
  28.     PRI,
  29.     NUM_ARGS
  30. };
  31.  
  32. typedef struct l {
  33.     BPTR dir;
  34.     struct ExAllControl *eac;
  35.     struct ExAllData *entry;
  36.     struct l *next; 
  37. } list;
  38.  
  39. extern void * __asm AsmCreatePool(register __d0 ULONG, register __d1 ULONG, register __d2 ULONG, register __a6 struct ExecBase *);
  40. extern void __asm AsmDeletePool(register __a0 void *, register __a6 struct ExecBase *);
  41. extern void * __asm AsmAllocPooled(register __a0 void *, register __d0 ULONG, register __a6 struct ExecBase *);
  42. extern void __asm AsmFreePooled(register __a0 void *, register __a1 void *, register __d0 ULONG, register __a6 struct ExecBase *);
  43.  
  44. UWORD exall(struct ExecBase *SysBase, struct DosLibrary *DOSBase, list **myold, char *path, ULONG *numfiles, void *pool);
  45. __inline BOOL compare(BOOL first, BPTR thisdir, struct ExAllData *this, BPTR otherdir, struct ExAllData *other, LONG *arg_array, struct DosLibrary *DOSBase, struct ExecBase *SysBase, void *pool);
  46.  
  47. int __saveds main(void)
  48. {
  49.     struct ExecBase *SysBase = *(struct ExecBase **)4L;
  50.     struct RDArgs *rdargs=NULL;
  51.     LONG arg_array[NUM_ARGS];
  52.     struct DosLibrary *DOSBase = (struct DosLibrary *)OpenLibrary(DOSNAME, 37L);
  53.     struct Library *UTGuiBase = OpenLibrary("utgui.library", 1L);
  54.     struct ExAllData *this, *other;
  55.     list *mylist, *mynew, *myold;
  56.     char **trav; //, this_string[256], other_string[256];
  57.     void *pool;
  58.     UWORD ret;
  59.     APTR    progbar = NULL;
  60.     ULONG    files = 0L, filenum;
  61.     LONG oldpri=256;
  62.     BOOL first;
  63.  
  64.     if(!DOSBase) return(20L);
  65.  
  66.     if(!(pool = AsmCreatePool(MEMF_ANY, 10240, 5120, SysBase)))
  67.         goto quit;
  68.     
  69.     if(!(mylist = myold = AsmAllocPooled(pool, sizeof(list), SysBase))) goto quit;
  70.     mylist->next = NULL;
  71.     mylist->entry = NULL;
  72.     memset(arg_array, 0, sizeof(LONG)*NUM_ARGS);
  73.     if(!(rdargs = ReadArgs(template, arg_array, NULL))){
  74.         Printf("Usage: dupfinder <path1> [<path2> ...] [names] [minsize=<bytes>]\n"
  75.                  "                 [noicons] [pri=<priority>]\n");
  76.         goto quit;
  77.     }
  78.  
  79.     if(arg_array[PRI])
  80.         oldpri = SetTaskPri(FindTask(0), *(LONG *)arg_array[PRI]);
  81.  
  82.     for(trav = (char **)arg_array[PATH];*trav;trav++){
  83.         if(ret = exall(SysBase, DOSBase, &myold, *trav, &files, pool)){
  84.             if(ret != 2)
  85.                 Printf("ExAll() failed\n");
  86.             goto quit;
  87.         }
  88.     }
  89.  
  90.     if(UTGuiBase)
  91.         progbar = ugOpenProgressBar("DupFinder", PB_ProgressText, "Comparing files...", PB_Total, files, PB_InactiveWin, TRUE, TAG_DONE);
  92.  
  93.     for(mynew = mylist->next, filenum = 0; mynew; mynew = mynew->next){
  94.         for(this = mynew->entry; this; this=this->ed_Next, ++filenum){
  95.             first = TRUE;
  96.             if(progbar)
  97.                 ugUpdateProgressBar(progbar, PB_Current, filenum, TAG_DONE);
  98.             if(this->ed_Next) other = this->ed_Next;
  99.             else if(mynew->next) other = (mynew->next)->entry;
  100.             else break;
  101.             myold = mynew;
  102.             for(;; other->ed_Next ? (other = other->ed_Next)
  103.                  : (myold->next ? (other = (myold = myold->next)->entry)
  104.                  : (other = NULL))){
  105.                 if(!other) break;
  106.                 if(SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C){
  107.                     Printf("***Break\n");
  108.                     goto quit;
  109.                 }
  110.                 if(compare(first, mynew->dir, this, myold->dir, other, arg_array, DOSBase,
  111.                     SysBase, pool)) first = FALSE;
  112.             }
  113.             if(!first) Printf("\n");
  114.         }
  115.     }
  116.  
  117. quit:
  118.     if(progbar)
  119.         ugCloseProgressBar(progbar);
  120.  
  121.     for(myold = mynew = mylist; myold; myold=mynew){
  122.         if(mynew) mynew=mynew->next;
  123.         if(myold != mylist && myold->eac){
  124.             FreeDosObject(DOS_EXALLCONTROL, myold->eac);
  125.             UnLock(myold->dir);
  126.         }
  127.     }
  128.     AsmDeletePool(pool, SysBase);
  129.     if(oldpri!=256) SetTaskPri(FindTask(0), oldpri);
  130.     if(rdargs) FreeArgs(rdargs);
  131.     CloseLibrary(UTGuiBase);
  132.     CloseLibrary((struct Library *)DOSBase);
  133.     return(0L);
  134. }
  135.  
  136.  
  137. UWORD exall(struct ExecBase *SysBase, struct DosLibrary *DOSBase, list **myold, char *path, ULONG *numfiles, void *pool)
  138. {
  139.     list *mynew;
  140.     int more;
  141.     char *buffer, *nfl_buf;
  142.     struct ExAllData *entry;
  143.     BPTR mylock;
  144.     struct ExAllControl *eac;
  145.     BOOL first=TRUE, broken=FALSE;
  146.     UWORD ret;
  147.  
  148.     if(!(mylock = Lock(path, ACCESS_READ))){
  149.         Printf("Can't lock \"%s\".\n", path);
  150.         return(2);
  151.     }
  152.  
  153.     if(!(eac = AllocDosObject(DOS_EXALLCONTROL, NULL))){
  154.         UnLock(mylock);
  155.         return(1);
  156.     }
  157.     eac->eac_LastKey = 0;
  158.     do {
  159.         if(SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C){
  160.             if(DOSBase->dl_lib.lib_Version >= 39){
  161.                 Printf("***Break\n");
  162.                 UnLock(mylock);
  163.                 if(first) FreeDosObject(DOS_EXALLCONTROL, eac);
  164.                 return(2);
  165.             }
  166.             else broken = TRUE;
  167.         }
  168.         if(buffer = AsmAllocPooled(pool, BUFSIZE, SysBase))
  169.             more = ExAll(mylock, (struct ExAllData *)buffer, BUFSIZE, ED_SIZE, eac);
  170.         if(!buffer || (!more && (IoErr() !=ERROR_NO_MORE_ENTRIES))){
  171.             if(first) FreeDosObject(DOS_EXALLCONTROL, eac);
  172.             UnLock(mylock);
  173.             return(1);  // Something seriously wrong.
  174.         }
  175.         if(eac->eac_Entries==0){
  176.             if(first) FreeDosObject(DOS_EXALLCONTROL, eac);
  177.             UnLock(mylock);
  178.             return(0);
  179.         }
  180.         *numfiles += eac->eac_Entries;
  181.  
  182.         if(!(mynew = AsmAllocPooled(pool, sizeof(list), SysBase))){
  183.             if(first) FreeDosObject(DOS_EXALLCONTROL, eac);
  184.             UnLock(mylock);
  185.             return(1);
  186.         }
  187.         memset(mynew, 0, sizeof(list));
  188.         (*myold)->next = mynew;
  189.         if(first){
  190.             mynew->eac = eac;
  191.             first = FALSE;
  192.         }
  193.         mynew->entry = (struct ExAllData *) buffer;
  194.         mynew->dir = mylock;
  195.         *myold = mynew;
  196.  
  197.         if(!broken && (nfl_buf = AsmAllocPooled(pool, 256, SysBase))){
  198.             for(entry = mynew->entry; entry; entry=entry->ed_Next)
  199.             if(entry->ed_Type == ST_USERDIR){
  200.                 NameFromLock(mylock, nfl_buf, 255);
  201.                 AddPart(nfl_buf, entry->ed_Name, 255);
  202.                 if(ret = exall(SysBase, DOSBase, myold, nfl_buf, numfiles, pool)){
  203.                     if(ret != 2)
  204.                         Printf("Couldn't check \"%s\"\n", nfl_buf);
  205.                     AsmFreePooled(pool, nfl_buf, 256, SysBase);
  206.                     return(ret);
  207.                 }
  208.             }
  209.             AsmFreePooled(pool, nfl_buf, 256, SysBase);
  210.         }
  211.     } while(more);
  212.     if(broken){
  213.         Printf("***Break\n");
  214.         return(2);
  215.     }
  216.     return(0);
  217. }
  218.  
  219. #define BSIZE 32768
  220.  
  221. __inline BOOL compare(BOOL first, BPTR thisdir, struct ExAllData *this, BPTR otherdir,
  222.                       struct ExAllData *other, LONG *arg_array,
  223.                       struct DosLibrary *DOSBase, struct ExecBase *SysBase, void *pool)
  224. {
  225.     char other_string[256], this_string[256];
  226.     static char *other_buffer = NULL, *this_buffer = NULL;
  227.     int actual = this->ed_Size, bsize = 512;
  228.     BPTR fh_this, fh_other;
  229.  
  230.     // Compare files
  231.     if(this->ed_Type!=ST_FILE
  232.         || !this->ed_Size
  233.         || (!arg_array[NAMES] && this->ed_Size != other->ed_Size)
  234.         || (arg_array[MINSIZE] ? (this->ed_Size < *(LONG *)arg_array[MINSIZE]) : FALSE))
  235.         return(FALSE);
  236.  
  237.     if(this->ed_Size != other->ed_Size){
  238.         if(!stricmp(this->ed_Name, other->ed_Name)){
  239.             NameFromLock(thisdir, this_string, 255);
  240.             AddPart(this_string, this->ed_Name, 255);
  241.             NameFromLock(otherdir, other_string, 255);
  242.             AddPart(other_string, other->ed_Name, 255);
  243.             if(!strcmp(this_string, other_string)) return(FALSE);
  244.             if(first) Printf("\"%s\"  ;identical to\n\"%s\" ;name only\n",
  245.                                   this_string, other_string);
  246.             else Printf("\"%s\" ;name only\n", other_string);
  247.             return(TRUE);
  248.         }
  249.         return(FALSE);
  250.     }
  251.  
  252.     NameFromLock(thisdir, this_string, 255);
  253.     AddPart(this_string, this->ed_Name, 255);
  254.     NameFromLock(otherdir, other_string, 255);
  255.     AddPart(other_string, other->ed_Name, 255);
  256.  
  257.     if(!strcmp(this_string, other_string)) return(FALSE);
  258.  
  259.     if(arg_array[NOICONS] && (strlen(this_string)>5
  260.         && !stricmp(&this_string[strlen(this_string)-5], ".info")))
  261.         return(FALSE);
  262.  
  263.     if(!(fh_this = Open(this_string, MODE_OLDFILE))){
  264.         Printf("Can't open \"%s\".\n", this_string);
  265.         return(FALSE);
  266.     }
  267.     if(!(fh_other = Open(other_string, MODE_OLDFILE))){
  268.         Printf("Can't open \"%s\".\n", other_string);
  269.         Close(fh_this);
  270.         return(FALSE);
  271.     }
  272.  
  273.     if(!this_buffer)
  274.         if(!(this_buffer = AsmAllocPooled(pool, BSIZE, SysBase))){
  275.             PutStr("Out of memory.\n");
  276.             return(FALSE);
  277.         }
  278.     if(!other_buffer)
  279.         if(!(other_buffer = AsmAllocPooled(pool, BSIZE, SysBase))){
  280.             PutStr("Out of memory.\n");
  281.             return(FALSE);
  282.         }
  283.  
  284.     while(actual>0){
  285.         if(Read(fh_this, this_buffer, bsize)!=-1){
  286.             if(Read(fh_other, other_buffer, bsize)!=-1){
  287.                 if(memcmp(this_buffer, other_buffer, (actual<bsize) ? actual : bsize)){
  288.                     Close(fh_other);
  289.                     Close(fh_this);
  290.                     if(arg_array[NAMES] && !strcmp(this->ed_Name, other->ed_Name)){
  291.                         if(first) Printf("\"%s\"  ;identical to\n\"%s\" ;name only\n",
  292.                                               this_string, other_string);
  293.                         else Printf("\"%s\" ;name only\n", other_string);
  294.                         return(TRUE);
  295.                     }
  296.                     return(FALSE);
  297.                 }
  298.             } else {
  299.                 Printf("Error reading from \"%s\" (error: %ld)\n", other_string, IoErr());
  300.                 Close(fh_other);
  301.                 Close(fh_this);
  302.                 return(FALSE);
  303.             }
  304.         } else {
  305.             Printf("Error reading from \"%s\" (error: %ld)\n", this_string, IoErr());
  306.             Close(fh_other);
  307.             Close(fh_this);
  308.             return(FALSE);
  309.         }
  310.         actual-=bsize;
  311.         bsize = BSIZE;
  312.     }
  313.     if(first) Printf("\"%s\"  ;identical to\n\"%s\"\n", this_string, other_string);
  314.     else Printf("\"%s\"\n", other_string);
  315.     other->ed_Type = ~ST_FILE;
  316.     Close(fh_other);
  317.     Close(fh_this);
  318.     return(TRUE);
  319. }
  320.