516 lines
9.1 KiB
C
516 lines
9.1 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "util.h"
|
|
#include "crc.h"
|
|
#include "fileutil.h"
|
|
#include "filenode.h"
|
|
|
|
|
|
|
|
FileNode *_free_filenode=NULL;
|
|
int _n_filenode=0;
|
|
#define FileNode_Tocho 1024
|
|
FileNode *FileNode_New(){
|
|
FileNode *fn;
|
|
|
|
if(_free_filenode==NULL){
|
|
FileNode *nodos;
|
|
int i;
|
|
// Reservar un tocho
|
|
nodos=malloc(sizeof(FileNode)*FileNode_Tocho);
|
|
for(i=0;i<FileNode_Tocho-1;i++){
|
|
nodos[i].sig=&nodos[i+1];
|
|
}
|
|
nodos[FileNode_Tocho-1].sig=NULL;
|
|
_free_filenode=&nodos[0];
|
|
}
|
|
|
|
// Obtener el primero libre
|
|
fn=_free_filenode;
|
|
_free_filenode=fn->sig;
|
|
_n_filenode++;
|
|
|
|
// Iniciar
|
|
fn->name[0]=0;
|
|
fn->flags=0;
|
|
fn->estado=EstadoFichero_Nada;
|
|
fn->size=0;
|
|
fn->crc=0;
|
|
fn->ft=0;
|
|
fn->child=NULL;
|
|
fn->n_childs=0;
|
|
fn->sig=NULL;
|
|
fn->padre=NULL;
|
|
|
|
return(fn);
|
|
}
|
|
|
|
void FileNode_Delete(FileNode *fn){
|
|
fn->sig=_free_filenode;
|
|
_free_filenode=fn;
|
|
_n_filenode--;
|
|
}
|
|
|
|
void FileNode_AddChild(FileNode *file,FileNode *file2){
|
|
if(!file2 || !file)
|
|
return;
|
|
file2->sig=file->child;
|
|
file->child=file2;
|
|
file->n_childs++;
|
|
file2->padre=file;
|
|
}
|
|
|
|
|
|
void FileNode_SetEstadoRec(FileNode *file,EstadoFichero estado){
|
|
FileNode *fn_child;
|
|
file->estado=estado;
|
|
fn_child=file->child;
|
|
while(fn_child!=NULL){
|
|
FileNode_SetEstadoRec(fn_child,estado);
|
|
fn_child=fn_child->sig;
|
|
}
|
|
}
|
|
|
|
void FileNode_GetPath_Rec(FileNode *fn,char **pathnode){
|
|
if(fn->padre){
|
|
pathnode[0]=fn->padre->name;
|
|
FileNode_GetPath_Rec(fn->padre,pathnode+1);
|
|
}else{
|
|
pathnode[0]=NULL;
|
|
}
|
|
}
|
|
char temppath[1024];
|
|
char *FileNode_GetPath(FileNode *fn,char *path){
|
|
char *pathnodes[100];
|
|
int levels,i;
|
|
char *pathptr=temppath;
|
|
if(path)pathptr=path;
|
|
|
|
FileNode_GetPath_Rec(fn,pathnodes);
|
|
levels=0;while(pathnodes[levels]){levels++;}
|
|
strcpy(pathptr,"");
|
|
for(i=levels-1;i>=0;i--){
|
|
strcat(pathptr,pathnodes[i]);
|
|
strcat(pathptr,"/");
|
|
}
|
|
strcat(pathptr,fn->name);
|
|
}
|
|
|
|
|
|
|
|
void FileNode_GetTamanho(FileNode *fn,char *file){
|
|
fn->flags|=FileFlag_TieneTamanho;
|
|
fn->size=File_TamanhoFichero(file);
|
|
}
|
|
|
|
void FileNode_GetFecha(FileNode *fn,char *file){
|
|
fn->flags|=FileFlag_TieneFecha;
|
|
fn->ft=FileTime_Get(file);
|
|
}
|
|
|
|
void FileNode_GetCRC(FileNode *fn,char *file){
|
|
FILE *f;
|
|
f=fopen(file,"rb");
|
|
if(!f){ return; }
|
|
fn->flags|=FileFlag_TieneCRC;
|
|
fn->crc=CRC_File(f);
|
|
fclose(f);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void FileNode_SaveNode(FileNode *fn,FILE *file){
|
|
short name_len;
|
|
|
|
// Escribir nombre
|
|
name_len=strlen(fn->name);
|
|
fwrite((void *)&name_len,sizeof(name_len),1,file);
|
|
fputs(fn->name,file);
|
|
|
|
// Escribir flags
|
|
fwrite((void *)&fn->flags,sizeof(fn->flags),1,file);
|
|
|
|
// Escribir estado
|
|
fputc((char)fn->estado,file);
|
|
|
|
// Escribir tamanho
|
|
if(fn->flags&FileFlag_TieneTamanho){
|
|
fwrite((void *)&fn->size,sizeof(fn->size),1,file);
|
|
}
|
|
|
|
// Escribir fecha
|
|
if(fn->flags&FileFlag_TieneFecha){
|
|
fwrite((void *)&fn->ft,sizeof(fn->ft),1,file);
|
|
}
|
|
|
|
// Escribir CRC
|
|
if(fn->flags&FileFlag_TieneCRC){
|
|
fwrite((void *)&fn->crc,sizeof(fn->crc),1,file);
|
|
}
|
|
|
|
// Escribir ficheros del directorio
|
|
if(fn->flags&FileFlag_Directorio){
|
|
FileNode *fnc;
|
|
fwrite((void *)&fn->n_childs,sizeof(fn->n_childs),1,file);
|
|
fnc=fn->child;
|
|
while(fnc){
|
|
FileNode_SaveNode(fnc,file);
|
|
fnc=fnc->sig;
|
|
}
|
|
}
|
|
}
|
|
|
|
void FileNode_Save(FileNode *fn,char *fichero){
|
|
FILE *file;
|
|
char marca[5];
|
|
int version;
|
|
|
|
if(!fn)
|
|
return;
|
|
file=fopen(fichero,"wb+");
|
|
if(!file)
|
|
return;
|
|
|
|
// Escribir marca y version
|
|
strcpy(marca,"sYnC");
|
|
fwrite((void *)marca,sizeof(char),4,file);
|
|
version=FileNode_Version;
|
|
fwrite((void *)&version,sizeof(int),1,file);
|
|
|
|
|
|
FileNode_SaveNode(fn,file);
|
|
fclose(file);
|
|
}
|
|
|
|
|
|
FileNode *FileNode_LoadNode(FILE *file){
|
|
short name_len;
|
|
FileNode *fn;
|
|
int i;
|
|
|
|
fn=FileNode_New();
|
|
|
|
// Leer el nombre
|
|
fread((void *)&name_len,sizeof(name_len),1,file);
|
|
fread((void *)fn->name,sizeof(char),name_len,file);
|
|
fn->name[name_len]=0;
|
|
|
|
// Leer vanderas
|
|
fread((void *)&fn->flags,sizeof(fn->flags),1,file);
|
|
|
|
// Leer estado
|
|
fn->estado=fgetc(file);
|
|
|
|
// Leer tamanho
|
|
if(fn->flags&FileFlag_TieneTamanho){
|
|
fread((void *)&fn->size,sizeof(fn->size),1,file);
|
|
}
|
|
|
|
// Leer fecha
|
|
if(fn->flags&FileFlag_TieneFecha){
|
|
fread((void *)&fn->ft,sizeof(fn->ft),1,file);
|
|
}
|
|
|
|
// Leer CRC
|
|
if(fn->flags&FileFlag_TieneCRC){
|
|
fread((void *)&fn->crc,sizeof(fn->crc),1,file);
|
|
}
|
|
|
|
// Leer ficheros del directorio
|
|
if(fn->flags&FileFlag_Directorio){
|
|
FileNode *fnca=NULL,*fnc;
|
|
fread((void *)&fn->n_childs,sizeof(fn->n_childs),1,file);
|
|
for(i=0;i<fn->n_childs;i++){
|
|
fnc=FileNode_LoadNode(file);
|
|
fnc->padre=fn;
|
|
if(!fnca){
|
|
fn->child=fnc;
|
|
}else{
|
|
fnca->sig=fnc;
|
|
}
|
|
fnca=fnc;
|
|
}
|
|
}
|
|
|
|
return(fn);
|
|
}
|
|
|
|
|
|
FileNode *FileNode_Load(char *fichero){
|
|
FILE *file;
|
|
FileNode *fn;
|
|
char marca[5];
|
|
int version;
|
|
|
|
file=fopen(fichero,"rb");
|
|
if(!file)
|
|
return(NULL);
|
|
|
|
// Leer marca y version
|
|
fread((void *)marca,sizeof(char),4,file);
|
|
marca[4]=0;
|
|
if(strcmp(marca,"sYnC")){
|
|
// Marca incorrecta
|
|
fclose(file);
|
|
return(NULL);
|
|
}
|
|
fread((void *)&version,sizeof(int),1,file);
|
|
if(version!=FileNode_Version){
|
|
// Version incorrecta
|
|
fclose(file);
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
fn=FileNode_LoadNode(file);
|
|
fclose(file);
|
|
|
|
return(fn);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void FileNode_Print(FileNode *fn){
|
|
FileNode *padre;
|
|
|
|
// Nombre
|
|
printf(FileNode_GetPath(fn,NULL));
|
|
if(fn->flags&FileFlag_Normal){
|
|
printf(" File");
|
|
}else{
|
|
printf(" Dir");
|
|
}
|
|
printf(" %d",fn->estado);
|
|
if(fn->estado==EstadoFichero_Nuevo){
|
|
printf(" Nuevo");
|
|
}
|
|
if(fn->estado==EstadoFichero_Modificado){
|
|
printf(" Modificado");
|
|
}
|
|
if(fn->estado==EstadoFichero_Borrado){
|
|
printf(" Borrado!!!");
|
|
}
|
|
printf("\n");
|
|
|
|
/*
|
|
// Tamanho
|
|
if(fn->flags&FileFlag_TieneTamanho){
|
|
printf("\\-Tamanho: %lld\n",fn->size);
|
|
}
|
|
|
|
// Fecha
|
|
if(fn->flags&FileFlag_TieneFecha){
|
|
printf("\\-Fecha : ");FileTime_Print(fn->ft);printf("\n");
|
|
}
|
|
|
|
// CRC
|
|
if(fn->flags&FileFlag_TieneCRC){
|
|
printf("\\-CRC : [%08X]\n",fn->crc);
|
|
}
|
|
*/
|
|
// Hijos
|
|
if(fn->flags&FileFlag_Directorio){
|
|
FileNode *fn2;
|
|
fn2=fn->child;
|
|
while(fn2){
|
|
FileNode_Print(fn2);
|
|
fn2=fn2->sig;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int FileNode_Build_Iterate(char *path,char *name,void *d);
|
|
|
|
FileNode *FileNode_Build(char *path){
|
|
FileNode *file;
|
|
|
|
if(!File_ExistePath(path))
|
|
return(NULL);
|
|
|
|
// Crear el nodo
|
|
file=FileNode_New();
|
|
File_GetName(path,file->name);
|
|
|
|
// Determinar si es un fichero o directorio
|
|
if(File_EsDirectorio(path)){
|
|
// Obtener datos para los directorios
|
|
file->flags|=FileFlag_Directorio;
|
|
FileNode_GetFecha(file,path);
|
|
File_IterateDir(path,FileNode_Build_Iterate,file);
|
|
}else{
|
|
// Obtener datos para los ficheros
|
|
file->flags|=FileFlag_Normal;
|
|
FileNode_GetTamanho(file,path);
|
|
FileNode_GetFecha(file,path);
|
|
}
|
|
|
|
return(file);
|
|
}
|
|
|
|
|
|
int FileNode_Build_Iterate(char *path,char *name,void *d){
|
|
FileNode *file,*fn_padre=d;;
|
|
|
|
file=FileNode_Build(path);
|
|
FileNode_AddChild(fn_padre,file);
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int FileNode_Refresh_Iterate(char *path,char *name,void *d);
|
|
|
|
FileNode *FileNode_Refresh(FileNode *fn,char *path){
|
|
|
|
|
|
if(!File_ExistePath(path)){
|
|
// El fichero ha sido borrado
|
|
if(!fn){
|
|
fn=FileNode_New();
|
|
File_GetName(path,fn->name);
|
|
}
|
|
FileNode_SetEstadoRec(fn,EstadoFichero_Borrado);
|
|
return(fn);
|
|
}
|
|
if(!fn){
|
|
// El fichero ha sido creado
|
|
fn=FileNode_Build(path);
|
|
FileNode_SetEstadoRec(fn,EstadoFichero_Nuevo);
|
|
}else{
|
|
// Comprobar si ha sido modificado
|
|
FileTime ft;
|
|
long long size;
|
|
int crc;
|
|
|
|
// Marcar normal
|
|
fn->estado=EstadoFichero_Nada;
|
|
fn->flags&=~FileFlag_MarcaRevision;
|
|
|
|
// Determinar si es un fichero o directorio
|
|
if(File_EsDirectorio(path)){
|
|
FileNode *fn_child;
|
|
|
|
// Comparar datos de los directorios
|
|
if(!(fn->flags&FileFlag_Directorio)){
|
|
fn->estado=EstadoFichero_Modificado;
|
|
fn->flags|=FileFlag_Directorio;
|
|
fn->flags&=~FileFlag_Normal;
|
|
}
|
|
ft=FileTime_Get(path);
|
|
if(ft!=fn->ft){
|
|
fn->estado=EstadoFichero_Modificado;
|
|
fn->ft=ft;
|
|
}
|
|
|
|
// Marcar hijos para determinar cual es actualizado
|
|
fn_child=fn->child;while(fn_child){
|
|
fn_child->flags|=FileFlag_MarcaRevision;
|
|
fn_child=fn_child->sig;
|
|
}
|
|
|
|
// Escanear subdirectorios
|
|
File_IterateDir(path,FileNode_Refresh_Iterate,fn);
|
|
|
|
// Buscar que sigan marcados (borrados)
|
|
fn_child=fn->child;while(fn_child){
|
|
if(fn_child->flags&FileFlag_MarcaRevision){
|
|
fn_child->flags&=~FileFlag_MarcaRevision;
|
|
fn_child->estado=EstadoFichero_Borrado;
|
|
}
|
|
fn_child=fn_child->sig;
|
|
}
|
|
}else{
|
|
// Comprar datos de los ficheros
|
|
if(!(fn->flags&FileFlag_Normal)){
|
|
fn->estado=EstadoFichero_Modificado;
|
|
fn->flags|=FileFlag_Normal;
|
|
fn->flags&=~FileFlag_Directorio;
|
|
}
|
|
size=File_TamanhoFichero(path);
|
|
if(size!=fn->size){
|
|
fn->estado=EstadoFichero_Modificado;
|
|
fn->size=size;
|
|
}
|
|
ft=FileTime_Get(path);
|
|
if(ft!=fn->ft){
|
|
fn->estado=EstadoFichero_Modificado;
|
|
fn->ft=ft;
|
|
}
|
|
if(fn->estado==EstadoFichero_Modificado){
|
|
fn->flags&=~FileFlag_TieneCRC;
|
|
}
|
|
}
|
|
}
|
|
return(fn);
|
|
}
|
|
|
|
int FileNode_Refresh_Iterate(char *path,char *name,void *d){
|
|
FileNode *fn=d;
|
|
FileNode *fn_child;
|
|
|
|
// Buscar el fichero entre los del arbol
|
|
fn_child=fn->child;
|
|
while(fn_child){
|
|
if(!strcmp(fn_child->name,name)){
|
|
break;
|
|
}
|
|
fn_child=fn_child->sig;
|
|
}
|
|
if(fn_child){
|
|
// Existe, refrescar
|
|
FileNode_Refresh(fn_child,path);
|
|
}else{
|
|
// Nuevo, construir
|
|
fn_child=FileNode_Refresh(NULL,path);
|
|
FileNode_AddChild(fn,fn_child);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|