home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Meeting Pearls 3
/
Meeting_Pearls_III.iso
/
Pearls
/
disk
/
Misc
/
DupFinder10
/
dupfinder.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-24
|
9KB
|
320 lines
#define __USE_SYSBASE
#include <exec/execbase.h>
#include <exec/memory.h>
#include <dos/exall.h>
#include <libraries/utgui.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/utgui_protos.h>
#include <clib/alib_protos.h>
#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/utgui_pragmas.h>
#include <string.h>
#include <stdlib.h>
#define BUFSIZE 2000
static UBYTE *version_string = "$VER: DupFinder 1.0 (24.4.95)";
UBYTE *template = "PATH/A/M,NAMES/S,MINSIZE=MIN/N,NOICONS=NOINFO/S,PRI/N";
enum {
PATH,
NAMES,
MINSIZE,
NOICONS,
PRI,
NUM_ARGS
};
typedef struct l {
BPTR dir;
struct ExAllControl *eac;
struct ExAllData *entry;
struct l *next;
} list;
extern void * __asm AsmCreatePool(register __d0 ULONG, register __d1 ULONG, register __d2 ULONG, register __a6 struct ExecBase *);
extern void __asm AsmDeletePool(register __a0 void *, register __a6 struct ExecBase *);
extern void * __asm AsmAllocPooled(register __a0 void *, register __d0 ULONG, register __a6 struct ExecBase *);
extern void __asm AsmFreePooled(register __a0 void *, register __a1 void *, register __d0 ULONG, register __a6 struct ExecBase *);
UWORD exall(struct ExecBase *SysBase, struct DosLibrary *DOSBase, list **myold, char *path, ULONG *numfiles, void *pool);
__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);
int __saveds main(void)
{
struct ExecBase *SysBase = *(struct ExecBase **)4L;
struct RDArgs *rdargs=NULL;
LONG arg_array[NUM_ARGS];
struct DosLibrary *DOSBase = (struct DosLibrary *)OpenLibrary(DOSNAME, 37L);
struct Library *UTGuiBase = OpenLibrary("utgui.library", 1L);
struct ExAllData *this, *other;
list *mylist, *mynew, *myold;
char **trav; //, this_string[256], other_string[256];
void *pool;
UWORD ret;
APTR progbar = NULL;
ULONG files = 0L, filenum;
LONG oldpri=256;
BOOL first;
if(!DOSBase) return(20L);
if(!(pool = AsmCreatePool(MEMF_ANY, 10240, 5120, SysBase)))
goto quit;
if(!(mylist = myold = AsmAllocPooled(pool, sizeof(list), SysBase))) goto quit;
mylist->next = NULL;
mylist->entry = NULL;
memset(arg_array, 0, sizeof(LONG)*NUM_ARGS);
if(!(rdargs = ReadArgs(template, arg_array, NULL))){
Printf("Usage: dupfinder <path1> [<path2> ...] [names] [minsize=<bytes>]\n"
" [noicons] [pri=<priority>]\n");
goto quit;
}
if(arg_array[PRI])
oldpri = SetTaskPri(FindTask(0), *(LONG *)arg_array[PRI]);
for(trav = (char **)arg_array[PATH];*trav;trav++){
if(ret = exall(SysBase, DOSBase, &myold, *trav, &files, pool)){
if(ret != 2)
Printf("ExAll() failed\n");
goto quit;
}
}
if(UTGuiBase)
progbar = ugOpenProgressBar("DupFinder", PB_ProgressText, "Comparing files...", PB_Total, files, PB_InactiveWin, TRUE, TAG_DONE);
for(mynew = mylist->next, filenum = 0; mynew; mynew = mynew->next){
for(this = mynew->entry; this; this=this->ed_Next, ++filenum){
first = TRUE;
if(progbar)
ugUpdateProgressBar(progbar, PB_Current, filenum, TAG_DONE);
if(this->ed_Next) other = this->ed_Next;
else if(mynew->next) other = (mynew->next)->entry;
else break;
myold = mynew;
for(;; other->ed_Next ? (other = other->ed_Next)
: (myold->next ? (other = (myold = myold->next)->entry)
: (other = NULL))){
if(!other) break;
if(SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C){
Printf("***Break\n");
goto quit;
}
if(compare(first, mynew->dir, this, myold->dir, other, arg_array, DOSBase,
SysBase, pool)) first = FALSE;
}
if(!first) Printf("\n");
}
}
quit:
if(progbar)
ugCloseProgressBar(progbar);
for(myold = mynew = mylist; myold; myold=mynew){
if(mynew) mynew=mynew->next;
if(myold != mylist && myold->eac){
FreeDosObject(DOS_EXALLCONTROL, myold->eac);
UnLock(myold->dir);
}
}
AsmDeletePool(pool, SysBase);
if(oldpri!=256) SetTaskPri(FindTask(0), oldpri);
if(rdargs) FreeArgs(rdargs);
CloseLibrary(UTGuiBase);
CloseLibrary((struct Library *)DOSBase);
return(0L);
}
UWORD exall(struct ExecBase *SysBase, struct DosLibrary *DOSBase, list **myold, char *path, ULONG *numfiles, void *pool)
{
list *mynew;
int more;
char *buffer, *nfl_buf;
struct ExAllData *entry;
BPTR mylock;
struct ExAllControl *eac;
BOOL first=TRUE, broken=FALSE;
UWORD ret;
if(!(mylock = Lock(path, ACCESS_READ))){
Printf("Can't lock \"%s\".\n", path);
return(2);
}
if(!(eac = AllocDosObject(DOS_EXALLCONTROL, NULL))){
UnLock(mylock);
return(1);
}
eac->eac_LastKey = 0;
do {
if(SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C){
if(DOSBase->dl_lib.lib_Version >= 39){
Printf("***Break\n");
UnLock(mylock);
if(first) FreeDosObject(DOS_EXALLCONTROL, eac);
return(2);
}
else broken = TRUE;
}
if(buffer = AsmAllocPooled(pool, BUFSIZE, SysBase))
more = ExAll(mylock, (struct ExAllData *)buffer, BUFSIZE, ED_SIZE, eac);
if(!buffer || (!more && (IoErr() !=ERROR_NO_MORE_ENTRIES))){
if(first) FreeDosObject(DOS_EXALLCONTROL, eac);
UnLock(mylock);
return(1); // Something seriously wrong.
}
if(eac->eac_Entries==0){
if(first) FreeDosObject(DOS_EXALLCONTROL, eac);
UnLock(mylock);
return(0);
}
*numfiles += eac->eac_Entries;
if(!(mynew = AsmAllocPooled(pool, sizeof(list), SysBase))){
if(first) FreeDosObject(DOS_EXALLCONTROL, eac);
UnLock(mylock);
return(1);
}
memset(mynew, 0, sizeof(list));
(*myold)->next = mynew;
if(first){
mynew->eac = eac;
first = FALSE;
}
mynew->entry = (struct ExAllData *) buffer;
mynew->dir = mylock;
*myold = mynew;
if(!broken && (nfl_buf = AsmAllocPooled(pool, 256, SysBase))){
for(entry = mynew->entry; entry; entry=entry->ed_Next)
if(entry->ed_Type == ST_USERDIR){
NameFromLock(mylock, nfl_buf, 255);
AddPart(nfl_buf, entry->ed_Name, 255);
if(ret = exall(SysBase, DOSBase, myold, nfl_buf, numfiles, pool)){
if(ret != 2)
Printf("Couldn't check \"%s\"\n", nfl_buf);
AsmFreePooled(pool, nfl_buf, 256, SysBase);
return(ret);
}
}
AsmFreePooled(pool, nfl_buf, 256, SysBase);
}
} while(more);
if(broken){
Printf("***Break\n");
return(2);
}
return(0);
}
#define BSIZE 32768
__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)
{
char other_string[256], this_string[256];
static char *other_buffer = NULL, *this_buffer = NULL;
int actual = this->ed_Size, bsize = 512;
BPTR fh_this, fh_other;
// Compare files
if(this->ed_Type!=ST_FILE
|| !this->ed_Size
|| (!arg_array[NAMES] && this->ed_Size != other->ed_Size)
|| (arg_array[MINSIZE] ? (this->ed_Size < *(LONG *)arg_array[MINSIZE]) : FALSE))
return(FALSE);
if(this->ed_Size != other->ed_Size){
if(!stricmp(this->ed_Name, other->ed_Name)){
NameFromLock(thisdir, this_string, 255);
AddPart(this_string, this->ed_Name, 255);
NameFromLock(otherdir, other_string, 255);
AddPart(other_string, other->ed_Name, 255);
if(!strcmp(this_string, other_string)) return(FALSE);
if(first) Printf("\"%s\" ;identical to\n\"%s\" ;name only\n",
this_string, other_string);
else Printf("\"%s\" ;name only\n", other_string);
return(TRUE);
}
return(FALSE);
}
NameFromLock(thisdir, this_string, 255);
AddPart(this_string, this->ed_Name, 255);
NameFromLock(otherdir, other_string, 255);
AddPart(other_string, other->ed_Name, 255);
if(!strcmp(this_string, other_string)) return(FALSE);
if(arg_array[NOICONS] && (strlen(this_string)>5
&& !stricmp(&this_string[strlen(this_string)-5], ".info")))
return(FALSE);
if(!(fh_this = Open(this_string, MODE_OLDFILE))){
Printf("Can't open \"%s\".\n", this_string);
return(FALSE);
}
if(!(fh_other = Open(other_string, MODE_OLDFILE))){
Printf("Can't open \"%s\".\n", other_string);
Close(fh_this);
return(FALSE);
}
if(!this_buffer)
if(!(this_buffer = AsmAllocPooled(pool, BSIZE, SysBase))){
PutStr("Out of memory.\n");
return(FALSE);
}
if(!other_buffer)
if(!(other_buffer = AsmAllocPooled(pool, BSIZE, SysBase))){
PutStr("Out of memory.\n");
return(FALSE);
}
while(actual>0){
if(Read(fh_this, this_buffer, bsize)!=-1){
if(Read(fh_other, other_buffer, bsize)!=-1){
if(memcmp(this_buffer, other_buffer, (actual<bsize) ? actual : bsize)){
Close(fh_other);
Close(fh_this);
if(arg_array[NAMES] && !strcmp(this->ed_Name, other->ed_Name)){
if(first) Printf("\"%s\" ;identical to\n\"%s\" ;name only\n",
this_string, other_string);
else Printf("\"%s\" ;name only\n", other_string);
return(TRUE);
}
return(FALSE);
}
} else {
Printf("Error reading from \"%s\" (error: %ld)\n", other_string, IoErr());
Close(fh_other);
Close(fh_this);
return(FALSE);
}
} else {
Printf("Error reading from \"%s\" (error: %ld)\n", this_string, IoErr());
Close(fh_other);
Close(fh_this);
return(FALSE);
}
actual-=bsize;
bsize = BSIZE;
}
if(first) Printf("\"%s\" ;identical to\n\"%s\"\n", this_string, other_string);
else Printf("\"%s\"\n", other_string);
other->ed_Type = ~ST_FILE;
Close(fh_other);
Close(fh_this);
return(TRUE);
}