It checks a path for files equal in size, and then compares its content.
I should have made a hash algoritm for comparing, but this was a snippet, so don't use it with huge files.
/*
Repeated File Finder by Ca0s
[st4ck-3rr0r.blogspot.com]
[Ka0 Team 2010]
*/
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
// SHIT es obligatorio dejarlo siempre el ultimo. Será ignorado.
#define DEFEXST "jpg,png,wmv,gif,mp4,mp3,wma,txt,SHIT"
char usage[]="Uso: RFF.exe -path PATH -maxdepth MAXDEPTH -ext EXTENSION1,EXTENSION2,...";
char firstPath[MAX_PATH];
char myPath[MAX_PATH];
int maxDepth=-1;
char *extensions=NULL;
int verbose=0;
char fileLog[MAX_PATH];
int isLog=0;
FILE *fLog;
typedef struct archivo archivo;
struct archivo {
archivo *anterior;
char name[MAX_PATH];
char path[MAX_PATH];
int size;
//char *hash;
char extension[16];
int found;
archivo *siguiente;
};
typedef struct retorno retorno;
struct retorno {
archivo *first;
archivo *last;
};
typedef struct exts exts;
struct exts {
char myExt[16];
exts *next;
exts *ant;
};
exts *globalExts=NULL;
int cuenta=0;
retorno *getDirList(char *path, int cDepth);
void getExtension(char *path, char *dest);
int checkExtensions(char *given, exts *validas);
int comparar(char *file1, char *file2);
int main(int argc, char *argv[])
{
// Parseamos los argumentos
if(argc<3)
{
printf("%s", usage);
exit(0);
}
int cArgv;
for(cArgv=1; cArgv<argc; cArgv++)
{
if(strcmp(argv[cArgv], "-path")==0) strncpy(firstPath, argv[cArgv+1], MAX_PATH);
if(strcmp(argv[cArgv], "-maxdepth")==0) maxDepth=atoi(argv[cArgv+1]);
if( (strcmp(argv[cArgv], "-ext")==0) && (argc>cArgv+1) )
{
int extsLen=strlen(argv[cArgv+1])-2;
extensions=(char *)malloc((extsLen*sizeof(char))+2+(strlen(",NULL")));
strcpy(extensions, argv[cArgv+1]);
strcat(extensions, "\0");
char *rbuf=(char *)malloc(sizeof(char)*strlen(extensions));
sprintf(rbuf, extensions);
sprintf(extensions, "%s\,NULL", rbuf);
strcat(extensions, "\0");
//printf("%s", extensions);
}
if(strcmp(argv[cArgv], "-v")==0) verbose=1;
if(strcmp(argv[cArgv], "-log")==0)
{
printf("asd");
isLog=1;
strncpy(fileLog, argv[cArgv+1], MAX_PATH);
fLog=fopen(fileLog, "a+");
}
}
if(strcmp(firstPath, "")==0)
{
printf("%s", usage);
exit(0);
}
if(maxDepth==-1) maxDepth=0;
if(extensions==NULL)
{
extensions=(char *)malloc((strlen(DEFEXST)*sizeof(char)));
strncpy(extensions, DEFEXST, strlen(DEFEXST));
strncat(extensions, "\0", 2);
//printf("Extensiones por defecto: %s", extensions);
}
char *myTok;
exts *myExts;
exts *cExt;
myExts=(exts *)malloc(sizeof(exts));
myExts->ant=NULL;
cExt=myExts;
myTok=(char *)strtok(extensions, ",");
while(myTok!=NULL)
{
//printf("Tok %s\n", myTok);
strncpy(cExt->myExt, myTok, strlen(myTok));
strcat(cExt->myExt, "\0");
cExt->next=(exts *)malloc(sizeof(exts));
cExt->next->ant=cExt;
cExt=cExt->next;
myTok=(char *)strtok(NULL, ",");
}
cExt->ant->ant->next=NULL;
cExt=myExts;
globalExts=myExts;
//
printf("\n<< Ca0s' Repeated File Finder >>\n\nFirst path: %s\nMax Depth: %d\nExtensiones: ", firstPath, maxDepth);
while(cExt!=NULL)
{
printf("%s ", cExt->myExt);
if((cExt->next)!=NULL) cExt=cExt->next;
else break;
}
printf("\n");
if(isLog==1)
{
printf("Usando log: %s\n", fileLog);
if(fLog==NULL)
{
printf("-- Error abriendo archivo de log.\n");
exit(0);
}
}
archivo *actual;
archivo *primero;
retorno *unRetorno;
unRetorno=(retorno *)malloc(sizeof(retorno));
unRetorno=getDirList(firstPath, 0);
actual=unRetorno->first;
//printf("\n\nTest\n\n%s", actual->name);
int tmpSize;
int isFirst=0;
int isFound=0;
archivo *tmpBuffer;
printf("\nREPETIDOS:\n\n");
while(actual->siguiente!=NULL)
{
isFirst=0;
isFound=0;
tmpSize=actual->size;
tmpBuffer=actual->siguiente;
while(tmpBuffer->siguiente!=NULL)
{
if((tmpSize==tmpBuffer->size)&&(tmpBuffer->size!=-2)&&(tmpBuffer->found==0))
{
if(comparar(tmpBuffer->path, actual->path)==1)
{
isFound=1;
if(isFirst==0)
{
printf("Found:: %s", actual->path);
if(fLog!=NULL) fprintf(fLog, "Found:: %s", actual->path);
isFirst=1;
}
printf(" - %s", tmpBuffer->path);
if(fLog!=NULL) fprintf(fLog, " - %s", tmpBuffer->path);
tmpBuffer->found=1;
}
}
tmpBuffer=tmpBuffer->siguiente;
}
if(isFound==1)
{
printf("\n");
if(fLog!=NULL) fprintf(fLog, "\n");
}
actual=actual->siguiente;
}
if(fLog!=NULL) fclose(fLog);
printf("\n\n>> Terminado.\n");
return 0;
}
retorno *getDirList(char *path, int cDepth)
{
DIR *myDir;
struct dirent *myFile;
struct stat myStat;
char myPath[MAX_PATH];
char *myExt;
myExt=(char *)malloc(16*sizeof(char));
//printf("\n\nProbando carpeta: %s\n\n", path);
myDir=opendir(path);
if(!myDir)
{
printf("Error opening folder.\n");
return NULL;
}
archivo *actual;
archivo *primero=(archivo *)malloc(sizeof(archivo));
actual=primero;
retorno *myReturn;
myReturn=(retorno *)malloc(sizeof(retorno));
while(NULL!=(myFile=readdir(myDir)))
{
sprintf(myPath, "%s%s", path, myFile->d_name);
//printf("%s\n", myFile->d_name);
if(stat(myPath, &myStat)==-1) printf("Error stateando.\n");
sprintf(actual->name, myFile->d_name);
sprintf(actual->path, myPath);
if(verbose==1) printf("%s\n", myPath);
if(S_ISDIR(myStat.st_mode)!=0)
{
actual->size=-2;
sprintf(actual->extension, "DIRECTORY");
if((cDepth<maxDepth)&&(strcmp(myFile->d_name, ".")!=0)&&(strcmp(myFile->d_name, "..")!=0))
{
sprintf(myPath, "%s\\\\", myPath);
myReturn=getDirList(myPath, cDepth+1);
actual->siguiente=(archivo *)malloc(sizeof(archivo));
actual->siguiente=myReturn->first;
actual=myReturn->last;
}
}
else
{
actual->size=myStat.st_size;
getExtension(myPath, myExt);
if(checkExtension(myExt, globalExts)==0) continue;
sprintf(actual->extension, myExt);
//printf("%s\n", actual->extension);
// Esto es para proximamente cambiar la comparacion de archivo
// entero por un hash.
//actual->hash=(char *)malloc(11*sizeof(char));
//hash(myPath, actual->hash);
}
actual->found=0;
actual->siguiente=(archivo *)malloc(sizeof(archivo));
actual->siguiente->anterior=actual;
actual=actual->siguiente;
}
retorno *lastReturn;
lastReturn=(retorno *)malloc(sizeof(retorno));
lastReturn->first=primero;
lastReturn->last=actual;
return lastReturn;
}
void getExtension(char *file, char *dest)
{
char fileName[MAX_PATH];
char extension[16];
strncpy(fileName, file, MAX_PATH);
int r;
for(r=strlen(fileName); r>=0; r--)
{
if(strncmp(&fileName[r], ".", 1)==0)
{
strncpy(extension, &fileName[r+1], strlen(fileName)-r);
strncpy(dest, extension, 16);
strcat(dest, "\0");
return;
}
}
strcpy(dest, "NULL");
return;
}
int checkExtension(char *given, exts *validas)
{
exts *buffer;
buffer=validas;
while(buffer!=NULL)
{
//printf("Probando: %s", buffer->myExt);
if(strcmp(given, buffer->myExt)==0) return 1;
buffer=buffer->next;
}
return 0;
}
int comparar(char *file1, char *file2)
{
FILE *arc1, *arc2;
struct stat stat1;
stat(file1, &stat1);
struct stat stat2;
stat(file2, &stat2);
if(stat1.st_size!=stat2.st_size) return 0;
char *string1=(char *)malloc(stat1.st_size);
char *string2=(char *)malloc(stat2.st_size);
arc1=fopen(file1, "rb");
arc2=fopen(file2, "rb");
fread(string1, stat1.st_size, 1, arc1);
fread(string2, stat2.st_size, 1, arc2);
fclose(arc1);
fclose(arc2);
if(memcmp(string1, string2, stat1.st_size)==0)
{
free(string1);
free(string2);
return 1;
}
else
{
free(string1);
free(string2);
return 0;
}
}
Usage:
-path [path to start checking in] -maxdepth [maximum number of subfolders] -ext [extensions to check, not mandatory] -log [file for logging result, not mandatory]