#include #include #include #include "util.h" #include "crc.h" #include "fileutil.h" #include "filenode.h" #include "filenodecmp.h" AccionFileNode *_free_accionfilenode=NULL; int _n_accionfilenode=0; #define AccionFileNode_Tocho 1024 AccionFileNode *AccionFileNode_Crear(){ AccionFileNode *afn; if(_free_accionfilenode==NULL){ AccionFileNode *nodos; int i; // Reservar un tocho nodos=malloc(sizeof(AccionFileNode)*AccionFileNode_Tocho); for(i=0;isig; _n_accionfilenode++; // Iniciar afn->accion=AccionFileCmp_Nada; afn->izquierda=NULL; afn->derecha=NULL; afn->sig=NULL; return(afn); } void AccionFileNode_Destruir(AccionFileNode *afn){ afn->sig=_free_accionfilenode; _free_accionfilenode=afn; _n_accionfilenode--; } AccionFileNode *AccionFileNode_CrearNormal(FileNode *fnIzq,FileNode *fnDer) { AccionFileNode *afnNew; afnNew=AccionFileNode_Crear(); afnNew->accion=AccionFileCmp_Nada; afnNew->izquierda=fnIzq; afnNew->derecha=fnDer; return afnNew; } void AccionFileNode_CompareChilds( AccionFileNode *afnRaiz, AccionFileNode **afnCola, void (*CheckPair)(FileNode *fnIzq,FileNode *fnDer,AccionFileNode **afnCola)) { FileNode *fnIzq,*fnDer; AccionFileNode *afnColaStart=(*afnCola); // Comprobar si hay algo que comparar if(!afnRaiz->izquierda && !afnRaiz->derecha){ // Nada que hacer return; } // Iterar todos los nodos de la izquierda if(afnRaiz->izquierda){ fnIzq=afnRaiz->izquierda->child; while(fnIzq){ if(afnRaiz->derecha){ fnDer=afnRaiz->derecha->child; while(fnDer){ if(!strcmp(fnIzq->name,fnDer->name)){ break; }else{ fnDer=fnDer->sig; } } }else{ fnDer=NULL; } CheckPair(fnIzq,fnDer,afnCola); fnIzq=fnIzq->sig; } } // Iterar todos los nodos de la derecha, // ignorando las comparaciones ya realizadas if(afnRaiz->derecha){ fnDer=afnRaiz->derecha->child; while(fnDer){ int doCheck=1; if(afnRaiz->izquierda){ fnIzq=afnRaiz->izquierda->child; while(fnIzq){ AccionFileNode *afnCheck=afnColaStart; while(afnCheck){ if(afnCheck->izquierda==fnIzq && afnCheck->derecha==fnDer){ break; }else{ afnCheck=afnCheck->sig; } } if(afnCheck){ doCheck=0; break; } if(!strcmp(fnIzq->name,fnDer->name)){ break; }else{ fnIzq=fnIzq->sig; } } }else{ fnIzq=NULL; } if(doCheck){ CheckPair(fnIzq,fnDer,afnCola); } fnDer=fnDer->sig; } } } void AccionFileNode_DeletePair( FileNode *fnIzq,FileNode *fnDer,AccionFileNode **afnCola) { AccionFileNode *afnNew=AccionFileNode_CrearNormal(fnIzq,fnDer); if(!fnIzq && !fnDer){ AccionFileNode_Destruir(afnNew); return; } if(!fnIzq && fnDer){ if(fnDer->flags&FileFlag_Directorio){ // Iterar hijos para borrarlos AccionFileNode_CompareChilds(afnNew,afnCola, AccionFileNode_DeletePair); } if(fnDer->estado!=EstadoFichero_Borrado){ // Accion de borrado para el nodo afnNew->accion=AccionFileCmp_BorrarDerecha; (*afnCola)->sig=afnNew; (*afnCola)=afnNew; }else{ AccionFileNode_Destruir(afnNew); } } if(fnIzq && !fnDer){ if(fnIzq->flags&FileFlag_Directorio){ // Iterar hijos para borrarlos AccionFileNode_CompareChilds(afnNew,afnCola, AccionFileNode_DeletePair); } if(fnIzq->estado!=EstadoFichero_Borrado){ // Accion de borrado para el nodo afnNew->accion=AccionFileCmp_BorrarIzquierda; (*afnCola)->sig=afnNew; (*afnCola)=afnNew; }else{ AccionFileNode_Destruir(afnNew); } } if(fnIzq && fnDer){ if(fnIzq->flags&FileFlag_Directorio || fnDer->flags&FileFlag_Directorio) { // Alguno es directorio // Iterar hijos para borrarlos AccionFileNode_CompareChilds(afnNew,afnCola, AccionFileNode_DeletePair); } if(fnIzq->estado!=EstadoFichero_Borrado){ // Accion de borrado para el nodo izquierdo afnNew->accion=AccionFileCmp_BorrarIzquierda; (*afnCola)->sig=afnNew; (*afnCola)=afnNew; afnNew=NULL; } if(fnDer->estado!=EstadoFichero_Borrado){ if(!afnNew){ afnNew=AccionFileNode_CrearNormal(fnIzq,fnDer); } // Accion de borrado para el nodo derecho afnNew->accion=AccionFileCmp_BorrarDerecha; (*afnCola)->sig=afnNew; (*afnCola)=afnNew; afnNew=NULL; } if(afnNew){ AccionFileNode_Destruir(afnNew); } } } void AccionFileNode_CheckPair( FileNode *fnIzq,FileNode *fnDer,AccionFileNode **afnCola) { AccionFileNode *afnNew=AccionFileNode_CrearNormal(fnIzq,fnDer); if(!fnIzq && !fnDer){ AccionFileNode_Destruir(afnNew); return; } if(!fnIzq && fnDer){ if(fnDer->flags&FileFlag_Directorio){ // Directory if(fnDer->estado==EstadoFichero_Borrado){ afnNew->accion=AccionFileCmp_Nada; // Anhadir a la lista de acciones (*afnCola)->sig=afnNew; (*afnCola)=afnNew; }else{ afnNew->accion=AccionFileCmp_CrearDirIzquierda; // Anhadir a la lista de acciones (*afnCola)->sig=afnNew; (*afnCola)=afnNew; // Iterar hijos AccionFileNode_CompareChilds(afnNew,afnCola, AccionFileNode_CheckPair); // Crear nueva accion para copiar la fecha afnNew=AccionFileNode_CrearNormal(fnIzq,fnDer); afnNew->accion=AccionFileCmp_FechaDerechaAIzquierda; (*afnCola)->sig=afnNew; (*afnCola)=afnNew; } }else{ // File if(fnDer->estado==EstadoFichero_Borrado){ afnNew->accion=AccionFileCmp_Nada; }else{ afnNew->accion=AccionFileCmp_DerechaAIzquierda; } (*afnCola)->sig=afnNew; (*afnCola)=afnNew; } } if(fnIzq && !fnDer){ if(fnIzq->flags&FileFlag_Directorio){ // Directory if(fnIzq->estado==EstadoFichero_Borrado){ afnNew->accion=AccionFileCmp_Nada; // Anhadir a la lista de acciones (*afnCola)->sig=afnNew; (*afnCola)=afnNew; }else{ afnNew->accion=AccionFileCmp_CrearDirDerecha; // Anhadir a la lista de acciones (*afnCola)->sig=afnNew; (*afnCola)=afnNew; // Iterar hijos AccionFileNode_CompareChilds(afnNew,afnCola, AccionFileNode_CheckPair); // Crear nueva accion para copiar la fecha afnNew=AccionFileNode_CrearNormal(fnIzq,fnDer); afnNew->accion=AccionFileCmp_FechaIzquierdaADerecha; (*afnCola)->sig=afnNew; (*afnCola)=afnNew; } }else{ // File if(fnIzq->estado==EstadoFichero_Borrado){ afnNew->accion=AccionFileCmp_Nada; }else{ afnNew->accion=AccionFileCmp_IzquierdaADerecha; } (*afnCola)->sig=afnNew; (*afnCola)=afnNew; } } if(fnIzq && fnDer){ if(fnIzq->flags&FileFlag_Directorio && fnDer->flags&FileFlag_Directorio) { // Directorios // Preparar accion para el par de directorios if(abs(fnIzq->ft-fnDer->ft)<=1){ // appoximadamente iguales if(fnDer->estado==EstadoFichero_Borrado && fnIzq->estado==EstadoFichero_Borrado) { afnNew->accion=AccionFileCmp_Nada; }else if(fnDer->estado==EstadoFichero_Borrado){ afnNew->accion=AccionFileCmp_BorrarIzquierda; if(fnIzq->estado==EstadoFichero_Borrado){ afnNew->accion=AccionFileCmp_Nada; } }else if(fnIzq->estado==EstadoFichero_Borrado){ afnNew->accion=AccionFileCmp_BorrarDerecha; if(fnDer->estado==EstadoFichero_Borrado){ afnNew->accion=AccionFileCmp_Nada; } }else{ afnNew->accion=AccionFileCmp_Nada; } }else if(fnIzq->ftft){ afnNew->accion=AccionFileCmp_FechaDerechaAIzquierda; if(fnDer->estado==EstadoFichero_Borrado){ afnNew->accion=AccionFileCmp_BorrarIzquierda; if(fnIzq->estado==EstadoFichero_Borrado){ afnNew->accion=AccionFileCmp_Nada; } } }else if(fnIzq->ft>fnDer->ft){ afnNew->accion=AccionFileCmp_FechaIzquierdaADerecha; if(fnIzq->estado==EstadoFichero_Borrado){ afnNew->accion=AccionFileCmp_BorrarDerecha; if(fnDer->estado==EstadoFichero_Borrado){ afnNew->accion=AccionFileCmp_Nada; } } } // Procesar nodos hijos if(afnNew->accion==AccionFileCmp_BorrarDerecha || afnNew->accion==AccionFileCmp_BorrarIzquierda || (fnIzq->estado==EstadoFichero_Borrado && fnDer->estado==EstadoFichero_Borrado)) { // Iterar nodos hijos para borrarlos AccionFileNode_CompareChilds(afnNew,afnCola, AccionFileNode_DeletePair); }else{ AccionFileNode_CompareChilds(afnNew,afnCola, AccionFileNode_CheckPair); } // Encolar accion para el directorio padre (*afnCola)->sig=afnNew; (*afnCola)=afnNew; }else if(fnIzq->flags&FileFlag_Normal && fnDer->flags&FileFlag_Normal) { // Ficheros // Preparar accion para el par de ficheros if(abs(fnIzq->ft-fnDer->ft)<=1){ // appoximadamente iguales if(fnDer->estado==EstadoFichero_Borrado && fnIzq->estado==EstadoFichero_Borrado) { afnNew->accion=AccionFileCmp_Nada; }else if(fnDer->estado==EstadoFichero_Borrado){ afnNew->accion=AccionFileCmp_BorrarIzquierda; if(fnIzq->estado==EstadoFichero_Borrado){ afnNew->accion=AccionFileCmp_Nada; } }else if(fnIzq->estado==EstadoFichero_Borrado){ afnNew->accion=AccionFileCmp_BorrarDerecha; if(fnDer->estado==EstadoFichero_Borrado){ afnNew->accion=AccionFileCmp_Nada; } }else{ afnNew->accion=AccionFileCmp_Nada; } }else if(fnIzq->ftft){ afnNew->accion=AccionFileCmp_DerechaAIzquierda; if(fnDer->estado==EstadoFichero_Borrado){ afnNew->accion=AccionFileCmp_BorrarIzquierda; if(fnIzq->estado==EstadoFichero_Borrado){ afnNew->accion=AccionFileCmp_Nada; } } }else if(fnIzq->ft>fnDer->ft){ afnNew->accion=AccionFileCmp_IzquierdaADerecha; if(fnIzq->estado==EstadoFichero_Borrado){ afnNew->accion=AccionFileCmp_BorrarDerecha; if(fnDer->estado==EstadoFichero_Borrado){ afnNew->accion=AccionFileCmp_Nada; } } } // Encolar accion para el fichero (*afnCola)->sig=afnNew; (*afnCola)=afnNew; }else{ // FIXME: !!!!! // Directory vs File } } } AccionFileNode *AccionFileNode_Build( FileNode *izquierda,FileNode *derecha) { AccionFileNode *afnRaiz=AccionFileNode_CrearNormal(izquierda,derecha); AccionFileNode *afnCola=afnRaiz; AccionFileNode_CompareChilds(afnRaiz,&afnCola, AccionFileNode_CheckPair); return afnRaiz; } void AccionFileNode_Print(AccionFileNode *afn){ char showPath[MaxPath]; while(afn!=NULL){ if(afn->izquierda){ FileNode_GetFullPath(afn->izquierda,"",showPath); }else{ FileNode_GetFullPath(afn->derecha,"",showPath); } switch(afn->accion){ case AccionFileCmp_Nada: //printf("%s == %s\n",pathIzq,pathDer); break; case AccionFileCmp_IzquierdaADerecha: printf(" => %s\n",showPath);break; case AccionFileCmp_DerechaAIzquierda: printf(" <= %s\n",showPath);break; case AccionFileCmp_BorrarIzquierda: printf(" *- %s\n",showPath);break; case AccionFileCmp_BorrarDerecha: printf(" -* %s\n",showPath);break; case AccionFileCmp_FechaIzquierdaADerecha: printf(" -> %s\n",showPath);break; case AccionFileCmp_FechaDerechaAIzquierda: printf(" <- %s\n",showPath);break; case AccionFileCmp_CrearDirDerecha: printf(" -D %s\n",showPath);break; case AccionFileCmp_CrearDirIzquierda: printf(" D- %s\n",showPath);break; } afn=afn->sig; } printf("End\n"); } void AccionFileNodeAux_CopyDate(char *pathOrig,char *pathDest){ FileTime ft=FileTime_Get(pathOrig); FileTime_Set(pathDest,ft); } void AccionFileNodeAux_Copy(char *pathOrig,char *pathDest){ if(File_Copiar(pathOrig,pathDest)){ AccionFileNodeAux_CopyDate(pathOrig,pathDest); }else{ File_Borrar(pathDest); } } void AccionFileNodeAux_Delete(char *pathOrig,char *pathDest){ if(File_EsDirectorio(pathDest)){ File_BorrarDirectorio(pathDest); }else{ File_Borrar(pathDest); } } void AccionFileNodeAux_MakeDir(char *pathOrig,char *pathDest){ File_CrearDir(pathDest); } void AccionFileNode_RunList(AccionFileNode *afn,char *pathIzquierda,char *pathDerecha){ char pathIzq[MaxPath],pathDer[MaxPath],showPath[MaxPath]; while(afn!=NULL){ if(afn->izquierda){ FileNode_GetFullPath(afn->izquierda,pathIzquierda,pathIzq); }else{ FileNode_GetFullPath(afn->derecha,pathIzquierda,pathIzq); } if(afn->derecha){ FileNode_GetFullPath(afn->derecha,pathDerecha,pathDer); }else{ FileNode_GetFullPath(afn->izquierda,pathDerecha,pathDer); } if(afn->izquierda){ FileNode_GetFullPath(afn->izquierda,"",showPath); }else{ FileNode_GetFullPath(afn->derecha,"",showPath); } switch(afn->accion){ case AccionFileCmp_Nada: //printf("%s == %s\n",pathIzq,pathDer); break; case AccionFileCmp_IzquierdaADerecha: printf(" => %s\n",showPath); AccionFileNodeAux_Copy(pathIzq,pathDer); break; case AccionFileCmp_DerechaAIzquierda: printf(" <= %s\n",showPath); AccionFileNodeAux_Copy(pathDer,pathIzq); break; case AccionFileCmp_BorrarIzquierda: printf(" *- %s\n",showPath); AccionFileNodeAux_Delete(pathDer,pathIzq); break; case AccionFileCmp_BorrarDerecha: printf(" -* %s\n",showPath); AccionFileNodeAux_Delete(pathIzq,pathDer); break; case AccionFileCmp_FechaIzquierdaADerecha: printf(" -> %s\n",showPath); AccionFileNodeAux_CopyDate(pathIzq,pathDer); break; case AccionFileCmp_FechaDerechaAIzquierda: printf(" <- %s\n",showPath); AccionFileNodeAux_CopyDate(pathDer,pathIzq); break; case AccionFileCmp_CrearDirDerecha: printf(" -D %s\n",showPath); AccionFileNodeAux_MakeDir(pathIzq,pathDer); break; case AccionFileCmp_CrearDirIzquierda: printf(" D- %s\n",showPath); AccionFileNodeAux_MakeDir(pathDer,pathIzq); break; } afn=afn->sig; } printf("End\n"); }