Initial Commit.
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
*.o
|
||||
*.exe
|
||||
build
|
||||
_tests
|
||||
63
Makefile
Normal file
63
Makefile
Normal file
@@ -0,0 +1,63 @@
|
||||
|
||||
CC=gcc
|
||||
RM=rm -f
|
||||
ECHO=echo
|
||||
MKDIR=mkdir
|
||||
|
||||
HEADS = util.h crc.h fileutil.h filenode.h
|
||||
OBJS_BASE = \
|
||||
$(BUILDDIR)/util.o \
|
||||
$(BUILDDIR)/crc.o \
|
||||
$(BUILDDIR)/fileutil.o \
|
||||
$(BUILDDIR)/filenode.o
|
||||
OBJS_APP = \
|
||||
$(OBJS_BASE) \
|
||||
$(BUILDDIR)/main.o
|
||||
|
||||
RES_APP=filesync
|
||||
|
||||
CFLAGS = -g
|
||||
LIBS = -lm
|
||||
BUILDDIR = build
|
||||
|
||||
|
||||
|
||||
DO_CC=@$(ECHO) "CC: $@" ;\
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
all: $(RES_APP)
|
||||
|
||||
|
||||
clean:
|
||||
$(RM) $(OBJS_BASE)
|
||||
$(RM) $(OBJS_APP)
|
||||
|
||||
$(BUILDDIR):
|
||||
@-$(MKDIR) $(BUILDDIR)
|
||||
|
||||
|
||||
|
||||
$(BUILDDIR)/util.o: util.c $(HEADS)
|
||||
$(DO_CC)
|
||||
|
||||
$(BUILDDIR)/crc.o: crc.c $(HEADS)
|
||||
$(DO_CC)
|
||||
|
||||
$(BUILDDIR)/fileutil.o: fileutil.c $(HEADS)
|
||||
$(DO_CC)
|
||||
|
||||
$(BUILDDIR)/filenode.o: filenode.c $(HEADS)
|
||||
$(DO_CC)
|
||||
|
||||
|
||||
|
||||
$(BUILDDIR)/main.o: main.c $(HEADS)
|
||||
$(DO_CC)
|
||||
|
||||
|
||||
$(RES_APP): $(BUILDDIR) $(OBJS_APP)
|
||||
@$(ECHO) "LINK: $@"
|
||||
@$(CC) $(OBJS_APP) \
|
||||
-o $(RES_APP) $(LIBS)
|
||||
|
||||
|
||||
19
NOTAS.txt
Normal file
19
NOTAS.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
POR HACER
|
||||
=========
|
||||
* Comparador de FileNodes que genere una lista de AccionFileCmp (filenodecmp.h)
|
||||
* Realizar las acciones especificadas por la lista de AccionFileCmp
|
||||
* Demonio
|
||||
* GUI
|
||||
|
||||
|
||||
|
||||
HECHO
|
||||
=====
|
||||
|
||||
* CRC de ficheros (CRC_File en crc.h)
|
||||
* Lectura y Escritura de fechas de ficheros (FileTime end fileutil.h)
|
||||
* Utilidades de ficheros (fileutil.h)
|
||||
* Representacion de arboles de directorios que contienen informacion
|
||||
de cada fichero; crc, fecha, estado (FileNode en filenode.h)
|
||||
* Scaneo, construccion y reconstruccion de arboles FileNode, detectando cambios.
|
||||
69
crc.c
Normal file
69
crc.c
Normal file
@@ -0,0 +1,69 @@
|
||||
#include <stdio.h>
|
||||
|
||||
unsigned long CRCTable[256];
|
||||
int CRCTable_initialized=0;
|
||||
|
||||
#define CRC32_POLYNOMIAL 0xEDB88320L
|
||||
|
||||
void CRCTable_Init(){
|
||||
int i;
|
||||
int j;
|
||||
unsigned long crc;
|
||||
|
||||
if(CRCTable_initialized){
|
||||
return;
|
||||
}
|
||||
CRCTable_initialized=1;
|
||||
|
||||
for (i=0;i<256;i++){
|
||||
crc=i;
|
||||
for (j=8;j>0;j--){
|
||||
if (crc&1)
|
||||
crc=(crc>>1)^CRC32_POLYNOMIAL;
|
||||
else
|
||||
crc>>=1;
|
||||
}
|
||||
CRCTable[i]=crc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned long CRC_Buffer(unsigned char *buffer,int len,unsigned long crc){
|
||||
unsigned char *p;
|
||||
unsigned long temp1;
|
||||
unsigned long temp2;
|
||||
|
||||
// Calcular CRC del buffer
|
||||
p=(unsigned char*)buffer;
|
||||
while(len--!=0) {
|
||||
temp1=(crc>>8)&0x00FFFFFFL;
|
||||
temp2=CRCTable[((int)crc^*p++)&0xff];
|
||||
crc=temp1^temp2;
|
||||
}
|
||||
|
||||
return(crc);
|
||||
}
|
||||
|
||||
|
||||
unsigned long CRC_File(FILE *file){
|
||||
unsigned long crc;
|
||||
int count;
|
||||
unsigned char buffer[512];
|
||||
unsigned char *p;
|
||||
unsigned long temp1;
|
||||
unsigned long temp2;
|
||||
|
||||
CRCTable_Init();
|
||||
|
||||
crc=0xFFFFFFFFL;
|
||||
for(;;){
|
||||
// Llenar el buffer
|
||||
count=fread(buffer,1,512,file);
|
||||
if(count==0)
|
||||
break;
|
||||
|
||||
// Calcular CRC del buffer
|
||||
crc=CRC_Buffer(buffer,count,crc);
|
||||
}
|
||||
return(crc^=0xFFFFFFFFL);
|
||||
}
|
||||
9
crc.h
Normal file
9
crc.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef _CRC_
|
||||
#define _CRC_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
unsigned long CRC_Buffer(unsigned char *buffer,int len,unsigned long crc);
|
||||
unsigned long CRC_File(FILE *file);
|
||||
|
||||
#endif
|
||||
515
filenode.c
Normal file
515
filenode.c
Normal file
@@ -0,0 +1,515 @@
|
||||
#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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
61
filenode.h
Normal file
61
filenode.h
Normal file
@@ -0,0 +1,61 @@
|
||||
#ifndef _FILENODE_H_
|
||||
#define _FILENODE_H_
|
||||
|
||||
|
||||
#define FileNode_Version 4
|
||||
|
||||
#define FileFlag_Raiz 1
|
||||
#define FileFlag_Normal 2
|
||||
#define FileFlag_Directorio 4
|
||||
#define FileFlag_TieneTamanho 8
|
||||
#define FileFlag_TieneFecha 16
|
||||
#define FileFlag_TieneCRC 32
|
||||
#define FileFlag_MarcaRevision 1024
|
||||
|
||||
typedef enum {
|
||||
EstadoFichero_Nada,
|
||||
EstadoFichero_Nuevo,
|
||||
EstadoFichero_Modificado,
|
||||
EstadoFichero_Borrado
|
||||
} EstadoFichero;
|
||||
|
||||
typedef struct FileNode_Tag{
|
||||
char name[512];
|
||||
|
||||
int flags;
|
||||
|
||||
EstadoFichero estado;
|
||||
|
||||
long long size;
|
||||
|
||||
unsigned long crc;
|
||||
|
||||
FileTime ft;
|
||||
|
||||
struct FileNode_Tag *child;
|
||||
int n_childs;
|
||||
|
||||
struct FileNode_Tag *sig;
|
||||
struct FileNode_Tag *padre;
|
||||
} FileNode;
|
||||
|
||||
FileNode *FileNode_New();
|
||||
void FileNode_Delete(FileNode *fn);
|
||||
void FileNode_AddChild(FileNode *file,FileNode *file2);
|
||||
|
||||
void FileNode_GetTamanho(FileNode *fn,char *file);
|
||||
void FileNode_GetFecha(FileNode *fn,char *file);
|
||||
void FileNode_GetCRC(FileNode *fn,char *file);
|
||||
|
||||
void FileNode_Save(FileNode *fn,char *fichero);
|
||||
FileNode *FileNode_Load(char *fichero);
|
||||
|
||||
void FileNode_Print(FileNode *fn);
|
||||
|
||||
|
||||
FileNode *FileNode_Build(char *path);
|
||||
|
||||
FileNode *FileNode_Refresh(FileNode *file,char *path);
|
||||
|
||||
|
||||
#endif
|
||||
25
filenodecmp.c
Normal file
25
filenodecmp.c
Normal file
@@ -0,0 +1,25 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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(){
|
||||
|
||||
}
|
||||
|
||||
|
||||
void AccionFileNode_Destruir(AccionFileNode *afn){
|
||||
|
||||
}
|
||||
|
||||
AccionFileNode *AccionFileNode_Build(FileNode *izquierda,FileNode *derecha){
|
||||
|
||||
}
|
||||
30
filenodecmp.h
Normal file
30
filenodecmp.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef _FILENODE_H_
|
||||
#define _FILENODE_H_
|
||||
|
||||
#include "filenode.h"
|
||||
|
||||
|
||||
typedef enum {
|
||||
AccionFileCmp_Nada,
|
||||
AccionFileCmp_IzquierdaADerecha,
|
||||
AccionFileCmp_DerechaAIzquierda,
|
||||
AccionFileCmp_BorrarIzquierda,
|
||||
AccionFileCmp_BorrarDerecha
|
||||
} AccionFileCmp;
|
||||
|
||||
|
||||
typedef struct Tag_AccionFileNode {
|
||||
AccionFileCmp accion;
|
||||
FileNode *izquierda;
|
||||
FileNode *derecha;
|
||||
struct Tag_AccionFileNode *sig;
|
||||
} AccionFileNode;
|
||||
|
||||
|
||||
AccionFileNode *AccionFileNode_Crear();
|
||||
void AccionFileNode_Destruir(AccionFileNode *afn);
|
||||
|
||||
AccionFileNode *AccionFileNode_Build(FileNode *izquierda,FileNode *derecha);
|
||||
|
||||
|
||||
#endif
|
||||
312
fileutil.c
Normal file
312
fileutil.c
Normal file
@@ -0,0 +1,312 @@
|
||||
#include <stdio.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <utime.h>
|
||||
#include <time.h>
|
||||
#ifdef WIN32
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#include <signal.h>
|
||||
#include <windows.h>
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "fileutil.h"
|
||||
|
||||
#ifdef WIN32
|
||||
long long FileTime_to_POSIX(FILETIME ft){
|
||||
LARGE_INTEGER date, adjust;
|
||||
|
||||
// takes the last modified date
|
||||
date.HighPart = ft.dwHighDateTime;
|
||||
date.LowPart = ft.dwLowDateTime;
|
||||
|
||||
// 100-nanoseconds = milliseconds * 10000
|
||||
adjust.QuadPart = 11644473600000ll * 10000;
|
||||
|
||||
// removes the diff between 1970 and 1601
|
||||
date.QuadPart -= adjust.QuadPart;
|
||||
|
||||
// converts back from 100-nanoseconds to seconds
|
||||
return date.QuadPart / 10000000ll;
|
||||
}
|
||||
|
||||
FILETIME POSIX_to_FileTime(FileTime ft){
|
||||
LARGE_INTEGER date, adjust;
|
||||
FILETIME filetime;
|
||||
|
||||
// converts to 100-nanoseconds from seconds
|
||||
date.QuadPart=ft*10000000ll;
|
||||
|
||||
// 100-nanoseconds = milliseconds * 10000
|
||||
adjust.QuadPart = 11644473600000ll * 10000ll;
|
||||
|
||||
// removes the diff between 1970 and 1601
|
||||
date.QuadPart += adjust.QuadPart;
|
||||
|
||||
// asigns to filetime
|
||||
filetime.dwHighDateTime=date.HighPart;
|
||||
filetime.dwLowDateTime=date.LowPart;
|
||||
return filetime;
|
||||
}
|
||||
|
||||
FileTime FileTime_Get(char *filename){
|
||||
HANDLE hFile;
|
||||
FILETIME ftCreate, ftAccess, ftWrite;
|
||||
hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite);
|
||||
CloseHandle(hFile);
|
||||
return(FileTime_to_POSIX(ftWrite));
|
||||
}
|
||||
|
||||
void FileTime_Set(char *filename,FileTime t){
|
||||
HANDLE hFile;
|
||||
FILETIME ftWrite;
|
||||
hFile = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ,
|
||||
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
ftWrite=POSIX_to_FileTime(t);
|
||||
SetFileTime(hFile, NULL, NULL, &ftWrite);
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
FileTime FileTime_Get(char *filename){
|
||||
struct stat fs;
|
||||
lstat(filename,&fs);
|
||||
return(fs.st_mtime);
|
||||
}
|
||||
|
||||
void FileTime_Set(char *filename,FileTime t){
|
||||
struct utimbuf utb;
|
||||
|
||||
utb.actime=t;
|
||||
utb.modtime=t;
|
||||
utime(filename,&utb);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void FileTime_Print(FileTime t){
|
||||
struct tm *tms;
|
||||
|
||||
tms=localtime((time_t *)&t);
|
||||
printf("%d/%d/%d %02d:%02d:%02d",
|
||||
tms->tm_year+1900,
|
||||
tms->tm_mon+1,
|
||||
tms->tm_mday,
|
||||
tms->tm_hour,
|
||||
tms->tm_min,
|
||||
tms->tm_sec);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void File_GetName(char *path,char *name){
|
||||
int i,j;
|
||||
|
||||
i=strlen(path)-1;
|
||||
while(i>=0 ){
|
||||
if(path[i]=='/' || path[i]=='\\'){
|
||||
i++;
|
||||
break;
|
||||
}else{
|
||||
i--;
|
||||
}
|
||||
}
|
||||
if(i<0)
|
||||
i++;
|
||||
|
||||
j=0;
|
||||
while(path[i]){
|
||||
name[j]=path[i];
|
||||
i++;j++;
|
||||
}
|
||||
name[j]=0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
int File_ExistePath(char *path){
|
||||
unsigned rc;
|
||||
rc=GetFileAttributes(path);
|
||||
|
||||
if(rc==INVALID_FILE_ATTRIBUTES){
|
||||
return(0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
int File_EsDirectorio(char *dir){
|
||||
unsigned rc;
|
||||
rc=GetFileAttributes(dir);
|
||||
|
||||
if(rc==INVALID_FILE_ATTRIBUTES){
|
||||
return(0);
|
||||
}
|
||||
if(rc&FILE_ATTRIBUTE_DIRECTORY){
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
int File_EsFichero(char *fichero){
|
||||
unsigned rc;
|
||||
rc=GetFileAttributes(fichero);
|
||||
|
||||
if(rc==INVALID_FILE_ATTRIBUTES){
|
||||
return(0);
|
||||
}
|
||||
if(rc&FILE_ATTRIBUTE_DIRECTORY){
|
||||
return(0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
#else
|
||||
int File_ExistePath(char *path){
|
||||
struct stat info;
|
||||
|
||||
if(lstat(path,&info)==-1){
|
||||
return(0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
int File_EsDirectorio(char *dir){
|
||||
struct stat info;
|
||||
|
||||
if(lstat(dir,&info)==-1){
|
||||
return(0);
|
||||
}
|
||||
if(S_ISDIR(info.st_mode)){
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
int File_EsFichero(char *fichero){
|
||||
struct stat info;
|
||||
|
||||
if(lstat(fichero,&info)==-1){
|
||||
return(0);
|
||||
}
|
||||
if(S_ISDIR(info.st_mode)){
|
||||
return(0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
long long File_TamanhoFichero(char *fichero){
|
||||
FILE *f;
|
||||
long long tamanho;
|
||||
|
||||
f=fopen(fichero,"rb");
|
||||
if(!f)
|
||||
return(-1);
|
||||
|
||||
fseek(f,0,SEEK_END);
|
||||
tamanho=ftell(f);
|
||||
fclose(f);
|
||||
return(tamanho);
|
||||
}
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
int File_CrearDir(char *path){
|
||||
return(_mkdir(path));
|
||||
}
|
||||
#else
|
||||
int File_CrearDir(char *path){
|
||||
return(mkdir(path,0777));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
void File_IterateDir(char *path,
|
||||
int (*func)(char *path,char *name,void *data),void *data)
|
||||
{
|
||||
int handle;
|
||||
struct _finddata_t fileinfo;
|
||||
char f_path[512];
|
||||
int fin=0;
|
||||
int findnext_rc;
|
||||
char path_aux[512];
|
||||
char *ptr;
|
||||
|
||||
snprintf(path_aux,512,
|
||||
"%s/*",path);
|
||||
handle=_findfirst(path_aux,&fileinfo);
|
||||
if(handle==-1)
|
||||
return;
|
||||
|
||||
// Recorrer el directorio
|
||||
do{
|
||||
if(strcmp(fileinfo.name,".") &&
|
||||
strcmp(fileinfo.name,".."))
|
||||
{
|
||||
// Apartir de aqui hay un fichero
|
||||
// (o directorio)
|
||||
snprintf(f_path,512,
|
||||
"%s/%s",path,fileinfo.name);
|
||||
fin=func(f_path,fileinfo.name,data);
|
||||
}
|
||||
findnext_rc=_findnext(handle,&fileinfo);
|
||||
}while(findnext_rc!=-1 && !fin);
|
||||
_findclose(handle);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void File_IterateDir(char *path,
|
||||
int (*func)(char *path,char *name,void *data),void *data)
|
||||
{
|
||||
DIR *directorio;
|
||||
struct dirent *entidad_dir;
|
||||
char f_path[512];
|
||||
int fin=0;
|
||||
char *ptr;
|
||||
|
||||
directorio=opendir(path);
|
||||
if(directorio==NULL)
|
||||
return;
|
||||
|
||||
// Recorrer el directorio
|
||||
do{
|
||||
entidad_dir=readdir(directorio);
|
||||
if(entidad_dir!=NULL){
|
||||
if(strcmp(entidad_dir->d_name,".") &&
|
||||
strcmp(entidad_dir->d_name,".."))
|
||||
{
|
||||
// A partir de aqui hay un fichero
|
||||
// (o directorio)
|
||||
snprintf(f_path,512,
|
||||
"%s/%s",path,entidad_dir->d_name);
|
||||
fin=func(f_path,
|
||||
entidad_dir->d_name,
|
||||
data);
|
||||
}
|
||||
}
|
||||
}while(entidad_dir!=NULL && !fin);
|
||||
closedir(directorio);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
36
fileutil.h
Normal file
36
fileutil.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef _FILEUTIL_
|
||||
#define _FILEUTIL_
|
||||
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// FileTime
|
||||
|
||||
typedef long long FileTime;
|
||||
|
||||
FileTime FileTime_Get(char *filename);
|
||||
void FileTime_Set(char *filename,FileTime t);
|
||||
void FileTime_Print(FileTime t);
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// File
|
||||
void File_GetName(char *path,char *name);
|
||||
|
||||
int File_ExistePath(char *path);
|
||||
|
||||
int File_EsDirectorio(char *path);
|
||||
|
||||
int File_EsFichero(char *path);
|
||||
|
||||
long long File_TamanhoFichero(char *ficheros);
|
||||
|
||||
int File_CrearDir(char *path);
|
||||
|
||||
void File_IterateDir(char *path,
|
||||
int (*func)(char *path,char *name,void *data),void *data);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
122
main.c
Normal file
122
main.c
Normal file
@@ -0,0 +1,122 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "crc.h"
|
||||
#include "fileutil.h"
|
||||
#include "filenode.h"
|
||||
|
||||
void help(char *exe){
|
||||
printf("%s info [file] {[file] {..}}\n",exe);
|
||||
printf("%s scan [dir] [tree] \n",exe);
|
||||
printf("%s rescan [dir] [tree] \n",exe);
|
||||
printf("%s read [file] [tree]\n",exe);
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[]){
|
||||
FILE *f;
|
||||
unsigned long crc;
|
||||
FileTime ft;
|
||||
int i;
|
||||
|
||||
if(argc<2){
|
||||
help(argv[0]);
|
||||
}else
|
||||
if(!strcmp(argv[1],"info") && argc>=3){
|
||||
// Informacion de ficheros
|
||||
for(i=2;i<argc;i++){
|
||||
f=fopen(argv[i],"rb");
|
||||
if(f){
|
||||
crc=CRC_File(f);
|
||||
fclose(f);
|
||||
ft=FileTime_Get(argv[i]);
|
||||
printf("%s:\t[%08X]\t",argv[i],crc);
|
||||
FileTime_Print(ft);printf("\n");
|
||||
}
|
||||
}
|
||||
}else
|
||||
if(!strcmp(argv[1],"scan") && argc==4){
|
||||
// Scanear informacion de directorio y guardar arbol
|
||||
FileNode *fn;
|
||||
printf("Building FileNode..\n");
|
||||
fn=FileNode_Build(argv[2]);
|
||||
FileNode_Save(fn,argv[3]);
|
||||
}else
|
||||
if(!strcmp(argv[1],"rescan") && argc==4){
|
||||
// Scanear informacion de directorio y guardar arbol
|
||||
FileNode *fn;
|
||||
printf("Loading FileNode..\n");
|
||||
fn=FileNode_Load(argv[3]);
|
||||
if(fn){
|
||||
printf("Rebuilding FileNode..\n");
|
||||
fn=FileNode_Refresh(fn,argv[2]);
|
||||
FileNode_Save(fn,argv[3]);
|
||||
}
|
||||
}else
|
||||
if(!strcmp(argv[1],"read") && argc==3){
|
||||
// Leer informacion de arbol
|
||||
FileNode *fn;
|
||||
fn=FileNode_Load(argv[2]);
|
||||
if(fn)FileNode_Print(fn);
|
||||
}else{
|
||||
help(argv[0]);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
if(argc<2){
|
||||
return(1);
|
||||
}
|
||||
|
||||
f=fopen(argv[1],"rb");
|
||||
if(f){
|
||||
crc=CRC_File(f);
|
||||
fclose(f);
|
||||
printf("%s:\t%08X\n",argv[1],crc);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
if(argc<2){
|
||||
return(1);
|
||||
}
|
||||
|
||||
//printf("%d\n",FileTime_Get(argv[1]));
|
||||
FileTime ft;
|
||||
ft=FileTime_Get(argv[1]);
|
||||
FileTime_Print(ft);printf("\n");
|
||||
FileTime_Set(argv[1],ft+120);
|
||||
ft=FileTime_Get(argv[1]);
|
||||
FileTime_Print(ft);printf("\n");
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
if(argc<2){
|
||||
return(1);
|
||||
}
|
||||
|
||||
FileNode *fn;
|
||||
printf("Building FileNode..\n");
|
||||
fn=FileNode_Build(argv[1]);
|
||||
//printf("FileNode Contents:\n");
|
||||
//FileNode_Print(fn);
|
||||
extern int _n_filenode;
|
||||
printf("%d\n",_n_filenode);
|
||||
printf("END\n");
|
||||
|
||||
FileNode_Save(fn,"test2.fs");
|
||||
*/
|
||||
/*
|
||||
|
||||
FileNode *fn;
|
||||
fn=FileNode_Load("test2.fs");
|
||||
FileNode_Print(fn);
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
return(0);
|
||||
}
|
||||
15
util.c
Normal file
15
util.c
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
char *String_Copy(char *str){
|
||||
char *strnew;
|
||||
int len;
|
||||
len=strlen(str);
|
||||
strnew=malloc(len+1);
|
||||
strcpy(strnew,str);
|
||||
return(strnew);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user