]> git.llucax.com Git - z.facultad/75.06/emufs.git/blobdiff - emufs/tipo1.c
Bugfix.
[z.facultad/75.06/emufs.git] / emufs / tipo1.c
index 78a3806991816ac9efb2262deffe79db6498b5d7..fbebc53fdcedcdca12bb19aa44a3526dae78d3da 100644 (file)
 #include "idx.h"
 #include "fsc.h"
 #include "did.h"
 #include "idx.h"
 #include "fsc.h"
 #include "did.h"
+#include "error.h"
+#include <unistd.h>
+#include <sys/types.h>
 #include <stdio.h>
 #include <stdio.h>
+#include <math.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 
 #ifndef MIN
 #      define MIN(x, y) (((x) > (y)) ? (y) : (x))
 
 #ifndef MIN
 #      define MIN(x, y) (((x) > (y)) ? (y) : (x))
@@ -62,26 +65,19 @@ static int emufs_tipo1_header_jump(FILE*);
 
 static int emufs_tipo1_block_jump(EMUFS*, FILE*, EMUFS_BLOCK_ID);
 
 
 static int emufs_tipo1_block_jump(EMUFS*, FILE*, EMUFS_BLOCK_ID);
 
-static void emufs_tipo1_escribir_reg_en_memoria(char*, EMUFS_TIPO1_REG_HEADER,
-               char*);
-
 static void emufs_tipo1_escribir_reg_chunk_en_memoria(char* dst,
                EMUFS_TIPO1_REG_HEADER header, char* reg, EMUFS_REG_SIZE reg_size);
 
 /** Lee el bloque \param num_bloque y lo almacena en \c ptr. */
 static void* emufs_tipo1_leer_bloque(EMUFS*, EMUFS_BLOCK_ID, int*);
 
 static void emufs_tipo1_escribir_reg_chunk_en_memoria(char* dst,
                EMUFS_TIPO1_REG_HEADER header, char* reg, EMUFS_REG_SIZE reg_size);
 
 /** Lee el bloque \param num_bloque y lo almacena en \c ptr. */
 static void* emufs_tipo1_leer_bloque(EMUFS*, EMUFS_BLOCK_ID, int*);
 
-/** Graba el bloque apuntado por \c ptr en el archivo. */
-static EMUFS_BLOCK_ID emufs_tipo1_grabar_bloque(EMUFS*, void*, EMUFS_BLOCK_ID,
-               int*);
+/** Graba un bloque en el archivo y actualiza .fsc, si se solicita. */
+static EMUFS_BLOCK_ID emufs_tipo1_grabar_bloque_fsc(EMUFS*, void*,
+               EMUFS_BLOCK_ID, EMUFS_FREE, int*);
 
 /** Obtiene el tamaño del archivo. */
 static long emufs_tipo1_get_file_size(EMUFS*, int*);
 
 
 /** Obtiene el tamaño del archivo. */
 static long emufs_tipo1_get_file_size(EMUFS*, int*);
 
-/** Guarda un registro con un id determinado */
-static int emufs_tipo1_grabar_registro_con_id(EMUFS* efs, void* reg,
-               EMUFS_TIPO1_REG_HEADER header);
-
 /*------------------ Funciones públicas ----------------------*/
 
 int emufs_tipo1_inicializar(EMUFS* efs)
 /*------------------ Funciones públicas ----------------------*/
 
 int emufs_tipo1_inicializar(EMUFS* efs)
@@ -91,17 +87,19 @@ int emufs_tipo1_inicializar(EMUFS* efs)
         * mala */
        if (efs->tam_bloque < (sizeof(EMUFS_TIPO1_REG_HEADER) * 2)) {
                PERR("bloque demasiado chico");
         * mala */
        if (efs->tam_bloque < (sizeof(EMUFS_TIPO1_REG_HEADER) * 2)) {
                PERR("bloque demasiado chico");
-               return 1000; /* EMUFS_ERROR_BLOCK_SIZE_TOO_SMALL */
+               return EMUFS_ERROR_BLOCK_TOO_SMALL;
        }
        /* Asigna punteros a funciones. */
        efs->leer_bloque       = emufs_tipo1_leer_bloque;
        }
        /* Asigna punteros a funciones. */
        efs->leer_bloque       = emufs_tipo1_leer_bloque;
+       efs->leer_bloque_raw   = emufs_tipo1_leer_bloque_raw;
        efs->grabar_registro   = emufs_tipo1_grabar_registro;
        efs->borrar_registro   = emufs_tipo1_borrar_registro;
        efs->leer_registro     = emufs_tipo1_leer_registro;
        efs->leer_registro_raw = emufs_tipo1_leer_registro_raw;
        efs->leer_estadisticas = emufs_tipo1_leer_estadisticas;
        efs->compactar         = emufs_tipo1_compactar;
        efs->grabar_registro   = emufs_tipo1_grabar_registro;
        efs->borrar_registro   = emufs_tipo1_borrar_registro;
        efs->leer_registro     = emufs_tipo1_leer_registro;
        efs->leer_registro_raw = emufs_tipo1_leer_registro_raw;
        efs->leer_estadisticas = emufs_tipo1_leer_estadisticas;
        efs->compactar         = emufs_tipo1_compactar;
-       return 0; /* EMUFS_OK */
+       efs->tam_reg = 0;
+       return EMUFS_OK;
 }
 
 void* emufs_tipo1_leer_registro(EMUFS* efs, EMUFS_REG_ID reg_id,
 }
 
 void* emufs_tipo1_leer_registro(EMUFS* efs, EMUFS_REG_ID reg_id,
@@ -115,15 +113,13 @@ void* emufs_tipo1_leer_registro(EMUFS* efs, EMUFS_REG_ID reg_id,
 
        block_id = emufs_idx_buscar_registro(efs, reg_id);
        if (block_id == EMUFS_NOT_FOUND) {
 
        block_id = emufs_idx_buscar_registro(efs, reg_id);
        if (block_id == EMUFS_NOT_FOUND) {
-               /* TODO Manejo de errores */
                PERR("Registro no encontrado");
                *err = EMUFS_NOT_FOUND;
                return NULL;
        }
        if (!(block = (char*) emufs_tipo1_leer_bloque(efs, block_id, err))) {
                PERR("Registro no encontrado");
                *err = EMUFS_NOT_FOUND;
                return NULL;
        }
        if (!(block = (char*) emufs_tipo1_leer_bloque(efs, block_id, err))) {
-               /* TODO Manejo de errores */
                PERR("no se pudo reservar memoria");
                PERR("no se pudo reservar memoria");
-               *err = 2; /* EMUFS_ERROR_OUT_OF_MEMORY */
+               *err = EMUFS_ERROR_OUT_OF_MEMORY;
                return NULL;
        }
 
                return NULL;
        }
 
@@ -145,10 +141,9 @@ void* emufs_tipo1_leer_registro(EMUFS* efs, EMUFS_REG_ID reg_id,
                        *reg_size = curr_reg_header.size;
                        registro = chunk_ptr = (char*) malloc(*reg_size);
                        if (registro == NULL) {
                        *reg_size = curr_reg_header.size;
                        registro = chunk_ptr = (char*) malloc(*reg_size);
                        if (registro == NULL) {
-                               /* TODO Manejo de errores */
                                free(block);
                                PERR("No hay memoria");
                                free(block);
                                PERR("No hay memoria");
-                               *err = 2; /* EMUFS_ERROR_OUT_OF_MEMORY */
+                               *err = EMUFS_ERROR_OUT_OF_MEMORY;
                                return NULL;
                        }
                        while (1) {
                                return NULL;
                        }
                        while (1) {
@@ -162,10 +157,9 @@ void* emufs_tipo1_leer_registro(EMUFS* efs, EMUFS_REG_ID reg_id,
                                        free(block);
                                        if (!(block = (char*) emufs_tipo1_leer_bloque(efs,
                                                                        ++block_id, err))) {
                                        free(block);
                                        if (!(block = (char*) emufs_tipo1_leer_bloque(efs,
                                                                        ++block_id, err))) {
-                                               /* TODO Manejo de errores */
                                                free(registro);
                                                PERR("no se pudo reservar memoria");
                                                free(registro);
                                                PERR("no se pudo reservar memoria");
-                                               *err = 2; /* EMUFS_ERROR_OUT_OF_MEMORY */
+                                               *err = EMUFS_ERROR_OUT_OF_MEMORY;
                                                return NULL;
                                        }
                                } else { /* se terminó de leer */
                                                return NULL;
                                        }
                                } else { /* se terminó de leer */
@@ -184,9 +178,7 @@ void* emufs_tipo1_leer_registro(EMUFS* efs, EMUFS_REG_ID reg_id,
        return registro;
 }
 
        return registro;
 }
 
-/* @todo TODO hacer que soporte registros de más de un bloque */
-void* emufs_tipo1_leer_registro_raw(EMUFS *efs, EMUFS_REG_ID id,
-               EMUFS_REG_SIZE *size, int *pos)
+void* emufs_tipo1_leer_registro_raw(EMUFS *efs, EMUFS_REG_ID id, EMUFS_REG_SIZE *size, int *pos)
 {
        char *chunk_ptr;
        char* block; /* bloque leido (en donde está el registro a leer) */
 {
        char *chunk_ptr;
        char* block; /* bloque leido (en donde está el registro a leer) */
@@ -195,11 +187,10 @@ void* emufs_tipo1_leer_registro_raw(EMUFS *efs, EMUFS_REG_ID id,
        EMUFS_BLOCK_SIZE offset, block_space; /* offset del bloque leído */
        EMUFS_TIPO1_REG_HEADER curr_reg_header; /* cabecera del registro a leer */
        EMUFS_REG_SIZE cant_bloques;
        EMUFS_BLOCK_SIZE offset, block_space; /* offset del bloque leído */
        EMUFS_TIPO1_REG_HEADER curr_reg_header; /* cabecera del registro a leer */
        EMUFS_REG_SIZE cant_bloques;
-       int err, i;
+       int err = 0, i;
 
        block_id = emufs_idx_buscar_registro(efs, id);
        if (block_id == EMUFS_NOT_FOUND) {
 
        block_id = emufs_idx_buscar_registro(efs, id);
        if (block_id == EMUFS_NOT_FOUND) {
-               /* TODO Manejo de errores */
                PERR("Registro no encontrado");
                *pos = 0;
                *size = 0;
                PERR("Registro no encontrado");
                *pos = 0;
                *size = 0;
@@ -207,17 +198,16 @@ void* emufs_tipo1_leer_registro_raw(EMUFS *efs, EMUFS_REG_ID id,
        }
        err = 0;
        if (!(block = (char*) emufs_tipo1_leer_bloque(efs, block_id, &err))) {
        }
        err = 0;
        if (!(block = (char*) emufs_tipo1_leer_bloque(efs, block_id, &err))) {
-               /* TODO Manejo de errores */
                PERR("no se pudo reservar memoria");
                *pos = 0;
                *size = 0;
                return NULL;
        }
 
                PERR("no se pudo reservar memoria");
                *pos = 0;
                *size = 0;
                return NULL;
        }
 
-       /* Busco secuencialmente en el bloque el registro a leer */
+       /* busco secuencialmente en el bloque el registro a leer */
        offset = 0;
        do {
        offset = 0;
        do {
-               /* Copio la cabecera del registro actual. */
+               /* copio la cabecera del registro actual. */
                memcpy(&curr_reg_header, block + offset, sizeof(EMUFS_TIPO1_REG_HEADER));
                offset += sizeof(EMUFS_TIPO1_REG_HEADER);
                if (curr_reg_header.id == id) {
                memcpy(&curr_reg_header, block + offset, sizeof(EMUFS_TIPO1_REG_HEADER));
                offset += sizeof(EMUFS_TIPO1_REG_HEADER);
                if (curr_reg_header.id == id) {
@@ -228,9 +218,8 @@ void* emufs_tipo1_leer_registro_raw(EMUFS *efs, EMUFS_REG_ID id,
 
                        cant_bloques = curr_reg_header.size / block_space + 1;
                        *size = cant_bloques*efs->tam_bloque;
 
                        cant_bloques = curr_reg_header.size / block_space + 1;
                        *size = cant_bloques*efs->tam_bloque;
-                       registro = chunk_ptr = (char*) malloc(*size - (cant_bloques-1)*sizeof(EMUFS_TIPO1_REG_HEADER));
+                       registro = chunk_ptr = (char*) malloc(*size - (cant_bloques-1)*sizeof(EMUFS_TIPO1_REG_HEADER) + (cant_bloques-1)*2);
                        if (registro == NULL) {
                        if (registro == NULL) {
-                               /* TODO Manejo de errores */
                                free(block);
                                PERR("No hay memoria");
                                *pos = 0;
                                free(block);
                                PERR("No hay memoria");
                                *pos = 0;
@@ -239,18 +228,19 @@ void* emufs_tipo1_leer_registro_raw(EMUFS *efs, EMUFS_REG_ID id,
                        }
                        memcpy(registro, block, efs->tam_bloque);
                        chunk_ptr += efs->tam_bloque;
                        }
                        memcpy(registro, block, efs->tam_bloque);
                        chunk_ptr += efs->tam_bloque;
-                       /* Copio los otros bloques, si los hay */
+                       /* copio los otros bloques, si los hay */
                        free(block);
                        free(block);
-                       for(i=1; i<cant_bloques; i++) {
+                       for (i = 1; i < cant_bloques; ++i) {
                                err = 0;
                                block = (char*)emufs_tipo1_leer_bloque(efs, block_id+i, &err);
                                /* Solo grabo el header del primer pedazo! */
                                err = 0;
                                block = (char*)emufs_tipo1_leer_bloque(efs, block_id+i, &err);
                                /* Solo grabo el header del primer pedazo! */
-                               memcpy(registro, block+sizeof(EMUFS_TIPO1_REG_HEADER), efs->tam_bloque);
-                               chunk_ptr += efs->tam_bloque;
+                               memcpy(chunk_ptr, "<>", 2);
+                               chunk_ptr += 2;
+                               memcpy(chunk_ptr, block+sizeof(EMUFS_TIPO1_REG_HEADER), efs->tam_bloque-sizeof(EMUFS_TIPO1_REG_HEADER));
+                               chunk_ptr += efs->tam_bloque-sizeof(EMUFS_TIPO1_REG_HEADER);
                                free(block);
                        }
                                free(block);
                        }
-                       /* Todo listo! */
-                       break;
+                       break; /* se terminó el trabajo. */
                }
                /* Desplazo el offset */
                offset += curr_reg_header.size;
                }
                /* Desplazo el offset */
                offset += curr_reg_header.size;
@@ -259,7 +249,7 @@ void* emufs_tipo1_leer_registro_raw(EMUFS *efs, EMUFS_REG_ID id,
        return registro;
 }
 
        return registro;
 }
 
-void* emufs_tipo1_leer_bloque(EMUFS* efs, EMUFS_BLOCK_ID block_id, int *err)
+void* emufs_tipo1_leer_bloque(EMUFS* efs, EMUFS_BLOCK_ID block_id, interr)
 {
        FILE* file;
        char* block; /* bloque leido (en donde está el registro a leer) */
 {
        FILE* file;
        char* block; /* bloque leido (en donde está el registro a leer) */
@@ -270,33 +260,42 @@ void* emufs_tipo1_leer_bloque(EMUFS* efs, EMUFS_BLOCK_ID block_id, int *err)
 
        if ((file = fopen(name_f, "r")) == NULL) {
                PERR("No se puede abrir archivo");
 
        if ((file = fopen(name_f, "r")) == NULL) {
                PERR("No se puede abrir archivo");
-               *err = 4; /* EMUFS_ERROR_CANT_OPEN_FILE */
-               return NULL; /* FIXME ERROR */
+               *err = EMUFS_ERROR_CANT_OPEN_FILE;
+               return NULL;
        }
        emufs_tipo1_header_jump(file); /* salta cabeceras */
        emufs_tipo1_block_jump(efs, file, block_id); /* salta bloques */
        }
        emufs_tipo1_header_jump(file); /* salta cabeceras */
        emufs_tipo1_block_jump(efs, file, block_id); /* salta bloques */
-       /* FIXME: verificar que no se pase de fin de archivo*/
        block = (char*) malloc(efs->tam_bloque);
        if (block == NULL) {
        block = (char*) malloc(efs->tam_bloque);
        if (block == NULL) {
-               /* TODO Manejo de errores */
                PERR("No hay memoria");
                PERR("No hay memoria");
-               *err = 2; /* EMUFS_ERROR_OUT_OF_MEMORY */
+               *err = EMUFS_ERROR_OUT_OF_MEMORY;
                return NULL;
        }
        if (fread(block, efs->tam_bloque, 1, file) != 1) {
                return NULL;
        }
        if (fread(block, efs->tam_bloque, 1, file) != 1) {
-               /* TODO Manejo de errores */
                free(block);
                PERR("Error al leer bloque");
                free(block);
                PERR("Error al leer bloque");
-               *err = 3; /* EMUFS_ERROR_FILE_READ */
+               *err = EMUFS_ERROR_FILE_READ;
                return NULL;
        }
        fclose(file);
        return block;
 }
 
                return NULL;
        }
        fclose(file);
        return block;
 }
 
-EMUFS_REG_ID emufs_tipo1_grabar_registro(EMUFS* efs, void* reg, EMUFS_REG_SIZE reg_size, int* err)
+EMUFS_REG_ID emufs_tipo1_grabar_registro(EMUFS* efs, void* reg,
+               EMUFS_REG_SIZE reg_size, int* err)
 {
        EMUFS_TIPO1_REG_HEADER header; /* cabecera del registro a leer */
 {
        EMUFS_TIPO1_REG_HEADER header; /* cabecera del registro a leer */
+       EMUFS_FREE fs; /* espacio libre en el bloque */
+       EMUFS_BLOCK_ID block_id; /* identificador del 1er bloque */
+       char* block; /* buffer del bloque a guardar en disco */
+       char* chunk_ptr = reg; /* puntero a la poción del registro */
+       EMUFS_BLOCK_SIZE block_space /* tamaño máximo para datos en un bloque */
+               = efs->tam_bloque - sizeof(EMUFS_TIPO1_REG_HEADER);
+       /* identificador del bloque que se guarda */
+       EMUFS_BLOCK_ID curr_block_id;
+       /* tamaño de la porción de registro que se guarda */
+       EMUFS_REG_SIZE chunk_size = 0; 
+
        /* obtengo identificador que corresponderá al registro */
        header.id = emufs_idx_get_new_id(efs, err);
        if (*err) {
        /* obtengo identificador que corresponderá al registro */
        header.id = emufs_idx_get_new_id(efs, err);
        if (*err) {
@@ -304,10 +303,75 @@ EMUFS_REG_ID emufs_tipo1_grabar_registro(EMUFS* efs, void* reg, EMUFS_REG_SIZE r
                return EMUFS_NOT_FOUND;
        }
        header.size = reg_size; /* tamaño del registro */
                return EMUFS_NOT_FOUND;
        }
        header.size = reg_size; /* tamaño del registro */
-       if ((*err = emufs_tipo1_grabar_registro_con_id(efs, reg, header))) {
-               PERR("error al grabar el registro");
+
+       /* busco lugar para el registro en un bloque existente */
+       block_id = emufs_fsc_buscar_n_lugares(efs,
+                       /* cantidad de bloques que necesita el registro */
+                       (EMUFS_BLOCK_SIZE) ceil(header.size / (double) block_space),
+                       /* cabecera + si es un registro multibloque, tomo el bloque */
+                       sizeof(EMUFS_TIPO1_REG_HEADER) + MIN(header.size, block_space),
+                       &fs, err);
+       /* si no hay bloques con suficiente espacio creo un bloque nuevo */
+       if (block_id == EMUFS_NOT_FOUND) {
+               /* crear un nuevo bloque en memoria */
+               block = (char*) malloc(efs->tam_bloque);
+               if (block == NULL) {
+                       PERR("No hay memoria");
+                       *err = EMUFS_ERROR_OUT_OF_MEMORY;
+                       return EMUFS_NOT_FOUND;
+               }
+               memset(block, 0, efs->tam_bloque); /* inicializa bloque */
+               curr_block_id = EMUFS_NOT_FOUND; /* pongo de bloque actual el final */
+       /* si hay bloques con suficiente espacio, levanto el primero */
+       } else {
+               /* cargo el bloque en block_id */
+               if (!(block = (char*) emufs_tipo1_leer_bloque(efs, block_id, err))) {
+                       PERR("no se pudo leer el bloque");
+                       return EMUFS_NOT_FOUND;
+               }
+               curr_block_id = block_id; /* pongo de bloque actual el primero */
+       }
+
+       do {
+               EMUFS_BLOCK_ID new_block_id; /* identificador del bloque nuevo */
+               chunk_ptr += chunk_size; /* Avanzo para guardar prox chunk */
+               header.size -= chunk_size; /* Resto lo que ya guardé */
+               chunk_size = MIN(header.size, block_space);
+
+               /* graba porción del registro en bloque */ /* destino: fin de bloque */
+               emufs_tipo1_escribir_reg_chunk_en_memoria(block + efs->tam_bloque - fs,
+                               header, chunk_ptr, chunk_size);
+               /* graba el bloque en el archivo */
+               new_block_id = emufs_tipo1_grabar_bloque_fsc(efs, block, curr_block_id,
+                               fs - sizeof(EMUFS_TIPO1_REG_HEADER) - chunk_size, err);
+               if (*err) {
+                       PERR("error al grabar bloque");
+                       free(block);
+                       return EMUFS_NOT_FOUND;
+               }
+               /* si es el primer id de bloque obtenido, lo guardo para
+                * agregarlo después al archivo de índices. */
+               if (block_id == EMUFS_NOT_FOUND) {
+                       block_id = new_block_id;
+               }
+               /* si no estoy por fuera del archivo, incremento el nro. de bloque */
+               if (curr_block_id != EMUFS_NOT_FOUND) {
+                       ++curr_block_id;
+               }
+
+       /* mientras que el chunk no entre en un bloque */
+       } while (header.size > block_space);
+
+       /* libera el bloque */
+       free(block);
+
+       /* actualizo el indice de bloques y registros */
+       *err = emufs_idx_agregar(efs, header.id, block_id);
+       if (*err) {
+               PERR("No se pudo agregar idx");
                return EMUFS_NOT_FOUND;
        }
                return EMUFS_NOT_FOUND;
        }
+
        return header.id;
 }
 
        return header.id;
 }
 
@@ -321,12 +385,10 @@ int emufs_tipo1_borrar_registro(EMUFS* efs, EMUFS_REG_ID reg_id)
 
        block_id = emufs_idx_buscar_registro(efs, reg_id);
        if (block_id == EMUFS_NOT_FOUND) {
 
        block_id = emufs_idx_buscar_registro(efs, reg_id);
        if (block_id == EMUFS_NOT_FOUND) {
-               /* TODO Manejo de errores */
                PERR("Registro no encontrado");
                return EMUFS_NOT_FOUND;
        }
        if (!(block = (char*) emufs_tipo1_leer_bloque(efs, block_id, &err))) {
                PERR("Registro no encontrado");
                return EMUFS_NOT_FOUND;
        }
        if (!(block = (char*) emufs_tipo1_leer_bloque(efs, block_id, &err))) {
-               /* TODO Manejo de errores */
                PERR("no se pudo reservar memoria");
                return err;
        }
                PERR("no se pudo reservar memoria");
                return err;
        }
@@ -350,7 +412,6 @@ int emufs_tipo1_borrar_registro(EMUFS* efs, EMUFS_REG_ID reg_id)
                                        + MIN(curr_reg_header.size, block_space)
                                        + sizeof(EMUFS_TIPO1_REG_HEADER);
                                if ((err = emufs_fsc_actualizar(efs, curr_block_id, fs))) {
                                        + MIN(curr_reg_header.size, block_space)
                                        + sizeof(EMUFS_TIPO1_REG_HEADER);
                                if ((err = emufs_fsc_actualizar(efs, curr_block_id, fs))) {
-                                       /* TODO Manejo de errores */
                                        PERR("no se pudo actualizar .fsc");
                                        free(block);
                                        return err;
                                        PERR("no se pudo actualizar .fsc");
                                        free(block);
                                        return err;
@@ -360,7 +421,6 @@ int emufs_tipo1_borrar_registro(EMUFS* efs, EMUFS_REG_ID reg_id)
                                        free(block);
                                        if (!(block = (char*) emufs_tipo1_leer_bloque(efs,
                                                                        ++curr_block_id, &err))) {
                                        free(block);
                                        if (!(block = (char*) emufs_tipo1_leer_bloque(efs,
                                                                        ++curr_block_id, &err))) {
-                                               /* TODO Manejo de errores */
                                                PERR("no se pudo leer el bloque");
                                                return err;
                                        }
                                                PERR("no se pudo leer el bloque");
                                                return err;
                                        }
@@ -375,14 +435,12 @@ int emufs_tipo1_borrar_registro(EMUFS* efs, EMUFS_REG_ID reg_id)
 
                        /* actualizo archivo de identificadores de registros borrados */
                        if ((err = emufs_did_agregar(efs, reg_id))) {
 
                        /* actualizo archivo de identificadores de registros borrados */
                        if ((err = emufs_did_agregar(efs, reg_id))) {
-                               /* TODO Manejo de errores */
                                PERR("no se pudo actualizar .did");
                                free(block);
                                return err;
                        }
                        /*actualizo archivo .idx*/
                        if ((err = emufs_idx_borrar(efs, reg_id))) {
                                PERR("no se pudo actualizar .did");
                                free(block);
                                return err;
                        }
                        /*actualizo archivo .idx*/
                        if ((err = emufs_idx_borrar(efs, reg_id))) {
-                               /* TODO Manejo de errores */
                                PERR("no se pudo actualizar .did");
                                free(block);
                                return err;
                                PERR("no se pudo actualizar .did");
                                free(block);
                                return err;
@@ -399,16 +457,16 @@ int emufs_tipo1_borrar_registro(EMUFS* efs, EMUFS_REG_ID reg_id)
                                                efs->tam_bloque - offset_reg_end);
                                }
                        }
                                                efs->tam_bloque - offset_reg_end);
                                }
                        }
-                       /* guardo el bloque en disco */
-                       emufs_tipo1_grabar_bloque(efs, block, curr_block_id, &err);
+                       /* guardo el bloque en disco (actualizando espacio libre) */
+                       emufs_tipo1_grabar_bloque_fsc(efs, block, curr_block_id,
+                                       EMUFS_NOT_FOUND, &err);
                        if (err) {
                        if (err) {
-                               /* TODO Manejo de errores */
                                PERR("no se pudo grabar bloque en disco");
                                free(block);
                                return err;
                        }
 
                                PERR("no se pudo grabar bloque en disco");
                                free(block);
                                return err;
                        }
 
-                       break; /* salgo del loop, ya hice todo lo que tenía que hacer */
+                       break; /* salgo del loop, ya terminé lo que tenía que hacer */
                }
                /* desplazo el offset */
                offset += sizeof(EMUFS_TIPO1_REG_HEADER) + curr_reg_header.size;
                }
                /* desplazo el offset */
                offset += sizeof(EMUFS_TIPO1_REG_HEADER) + curr_reg_header.size;
@@ -417,7 +475,7 @@ int emufs_tipo1_borrar_registro(EMUFS* efs, EMUFS_REG_ID reg_id)
        } while (offset < efs->tam_bloque); /* registro está en el bloque */
 
        free(block);
        } while (offset < efs->tam_bloque); /* registro está en el bloque */
 
        free(block);
-       return 0; /* EMUFS_OK */
+       return EMUFS_OK;
 }
 
 EMUFS_Estadisticas emufs_tipo1_leer_estadisticas(EMUFS* efs)
 }
 
 EMUFS_Estadisticas emufs_tipo1_leer_estadisticas(EMUFS* efs)
@@ -428,7 +486,6 @@ EMUFS_Estadisticas emufs_tipo1_leer_estadisticas(EMUFS* efs)
 
        stats.tam_archivo_bytes = emufs_tipo1_get_file_size(efs, &err);
        if (err) {
 
        stats.tam_archivo_bytes = emufs_tipo1_get_file_size(efs, &err);
        if (err) {
-               /* TODO manejo de errores */
                PERR("no se pudo obtener el tamaño del archivo");
                return stats;
        }
                PERR("no se pudo obtener el tamaño del archivo");
                return stats;
        }
@@ -458,6 +515,8 @@ EMUFS_Estadisticas emufs_tipo1_leer_estadisticas(EMUFS* efs)
 
 void emufs_tipo1_compactar(EMUFS* efs)
 {
 
 void emufs_tipo1_compactar(EMUFS* efs)
 {
+       EMUFS_BLOCK_SIZE block_space /* tamaño para datos de un bloque */
+               = efs->tam_bloque - sizeof(EMUFS_TIPO1_REG_HEADER);
        EMUFS_REG_ID total_ids; /* cantidad total de registros en el array */
        /* array con los identificadores de los registros */
        EMUFS_REG_ID* reg_ids = emufs_idx_get(efs, &total_ids);
        EMUFS_REG_ID total_ids; /* cantidad total de registros en el array */
        /* array con los identificadores de los registros */
        EMUFS_REG_ID* reg_ids = emufs_idx_get(efs, &total_ids);
@@ -465,45 +524,38 @@ void emufs_tipo1_compactar(EMUFS* efs)
 
        /* recorro cada registro válido del archivo */
        for (i = 0; i < total_ids; ++i) {
 
        /* recorro cada registro válido del archivo */
        for (i = 0; i < total_ids; ++i) {
-               EMUFS_FREE fs; /* espacio libre en el bloque */
                EMUFS_TIPO1_REG_HEADER header; /* cabecera del registro a leer */
                EMUFS_TIPO1_REG_HEADER header; /* cabecera del registro a leer */
+               char* reg; /* buffer para el registro a mover */
                int err = 0; /* para almacenar código de error */
                /* bloque al que pertenece el registro */
                EMUFS_BLOCK_ID block_id = emufs_idx_buscar_registro(efs, reg_ids[i]);
                int err = 0; /* para almacenar código de error */
                /* bloque al que pertenece el registro */
                EMUFS_BLOCK_ID block_id = emufs_idx_buscar_registro(efs, reg_ids[i]);
-               /* obtengo un bloque con espacio suficiente para almacenarlo */
-               EMUFS_BLOCK_ID free_block_id = emufs_fsc_buscar_lugar(efs,
-                               sizeof(EMUFS_TIPO1_REG_HEADER) + reg_ids[i], &fs);
 
 
+               /* obtengo identificador del registro actual */
+               header.id = reg_ids[i];
                /* si el registro está borrado, continúo con el próximo */
                if (block_id == EMUFS_NOT_FOUND) {
                        continue;
                }
                /* si el registro está borrado, continúo con el próximo */
                if (block_id == EMUFS_NOT_FOUND) {
                        continue;
                }
-               /* obtengo identificador del registro actual */
-               header.id = reg_ids[i];
-               /* TODO analizar caso de registros multibloque */
-               /* si el bloque obtenido está antes del bloque actual */
-               if (free_block_id < block_id) {
-                       /* leo el registro */
-                       char* reg = (char*) efs->leer_registro(efs, header.id,
-                                       &header.size, &err);
-                       if (err) {
-                               PERR("error al leer registro");
-                               return;
-                       }
-                       /* borro el registro */
-                       if ((err = efs->borrar_registro(efs, header.id))) {
-                               PERR("error al borrar registro");
-                               free(reg);
-                               return;
-                       }
-                       /* lo inserto en la nueva posición */
-                       if ((err = emufs_tipo1_grabar_registro_con_id(efs, reg, header))) {
-                               PERR("error al borrar registro");
-                               free(reg);
-                               return;
-                       }
+               /* leo el registro */
+               reg = (char*) efs->leer_registro(efs, header.id, &header.size, &err);
+               if (err) {
+                       PERR("error al leer registro");
+                       return;
+               }
+               /* borro el registro */
+               if ((err = efs->borrar_registro(efs, header.id))) {
+                       PERR("error al borrar registro");
                        free(reg);
                        free(reg);
+                       return;
                }
                }
+               /* lo inserto en la nueva posición */
+               emufs_tipo1_grabar_registro(efs, reg, header.size, &err);
+               if (err) {
+                       PERR("error al grabar registro");
+                       free(reg);
+                       return;
+               }
+               free(reg);
        }
        free(reg_ids); /* libero lista de ids */
 
        }
        free(reg_ids); /* libero lista de ids */
 
@@ -511,8 +563,7 @@ void emufs_tipo1_compactar(EMUFS* efs)
        {
                EMUFS_FREE fs; /* espacio libre en el bloque */
                /* busco si hay algún bloque completo libre */
        {
                EMUFS_FREE fs; /* espacio libre en el bloque */
                /* busco si hay algún bloque completo libre */
-               EMUFS_BLOCK_ID block_id = emufs_fsc_buscar_lugar(efs, efs->tam_bloque
-                               - sizeof(EMUFS_TIPO1_REG_HEADER), &fs);
+               EMUFS_BLOCK_ID block_id = emufs_fsc_buscar_lugar(efs, block_space, &fs);
                /* si hay, el resto del archivo tiene que estar vacío */
                if (block_id != EMUFS_NOT_FOUND) {
                        long size = emufs_tipo1_header_size() /* cabecera del archivo */
                /* si hay, el resto del archivo tiene que estar vacío */
                if (block_id != EMUFS_NOT_FOUND) {
                        long size = emufs_tipo1_header_size() /* cabecera del archivo */
@@ -529,33 +580,45 @@ void emufs_tipo1_compactar(EMUFS* efs)
        }
 }
 
        }
 }
 
-EMUFS_BLOCK_ID emufs_tipo1_grabar_bloque(EMUFS *efs, void *block,
-               EMUFS_BLOCK_ID block_id, int* err)
+EMUFS_BLOCK_ID emufs_tipo1_grabar_bloque_fsc(EMUFS *efs, void *block,
+               EMUFS_BLOCK_ID block_id, EMUFS_FREE fs, int* err)
 {
        FILE* file;
        char name_f[255];
 {
        FILE* file;
        char name_f[255];
+       /* obtengo cantidad de bloques */
+       EMUFS_BLOCK_SIZE num_blocks =
+               (emufs_tipo1_get_file_size(efs, err) - emufs_tipo1_header_size())
+               / efs->tam_bloque;
 
 
+       /* abre archivo */
        strcpy(name_f,efs->nombre);
        strcat(name_f,".dat");
        strcpy(name_f,efs->nombre);
        strcat(name_f,".dat");
-
        if ((file = fopen(name_f, "r+b")) == NULL) {
        if ((file = fopen(name_f, "r+b")) == NULL) {
-               /* TODO Manejo de errores */
                PERR("Error al abrir archivo");
                PERR("Error al abrir archivo");
-               *err = 4; /* EMUFS_ERROR_CANT_OPEN_FILE */
+               *err = EMUFS_ERROR_CANT_OPEN_FILE;
                return EMUFS_NOT_FOUND;
        }
                return EMUFS_NOT_FOUND;
        }
-       /* Si es NOT_FOUND tengo que agregar un bloque al final del archivo */
-       if (block_id == EMUFS_NOT_FOUND) {
+       /* Si es NOT_FOUND o mayor a la cantidad de bloques presentes,
+        * tengo que agregar un bloque al final del archivo */
+       if ((block_id == EMUFS_NOT_FOUND) || (block_id >= num_blocks)) {
                /* me paro al final del archivo */
                if (fseek(file, 0l, SEEK_END)) {
                /* me paro al final del archivo */
                if (fseek(file, 0l, SEEK_END)) {
-                       /* TODO Manejo de errores */
                        PERR("No se pudo hacer fseek()");
                        fclose(file);
                        PERR("No se pudo hacer fseek()");
                        fclose(file);
-                       *err = 8; /* EMUFS_ERROR_SEEK_FILE */
+                       *err = EMUFS_ERROR_SEEK_FILE;
                        return EMUFS_NOT_FOUND;
                }
                /* Obtengo ID del bloque nuevo */
                block_id = (ftell(file) - emufs_tipo1_header_size()) / efs->tam_bloque;
                        return EMUFS_NOT_FOUND;
                }
                /* Obtengo ID del bloque nuevo */
                block_id = (ftell(file) - emufs_tipo1_header_size()) / efs->tam_bloque;
+               /* si me lo solicitan, actualizo el .fsc */
+               if (fs != EMUFS_NOT_FOUND) {
+                       *err = emufs_fsc_agregar(efs, block_id, fs);
+                       if (*err) {
+                               PERR("No se pudo agregar al .fsc");
+                               fclose(file);
+                               return EMUFS_NOT_FOUND;
+                       }
+               }
        /* Si es un ID válido, salto hasta ese bloque. */
        } else {
                /* Salta el header del archivo */
        /* Si es un ID válido, salto hasta ese bloque. */
        } else {
                /* Salta el header del archivo */
@@ -570,12 +633,20 @@ EMUFS_BLOCK_ID emufs_tipo1_grabar_bloque(EMUFS *efs, void *block,
                        fclose(file);
                        return EMUFS_NOT_FOUND;
                }
                        fclose(file);
                        return EMUFS_NOT_FOUND;
                }
+               /* si me lo solicitan, actualizo el .fsc */
+               if (fs != EMUFS_NOT_FOUND) {
+                       if ((*err = emufs_fsc_actualizar(efs, block_id, fs))) {
+                               PERR("no se pudo actualizar .fsc");
+                               fclose(file);
+                               return EMUFS_NOT_FOUND;
+                       }
+               }
        }
        /* Grabo el bloque */
        if (fwrite(block, efs->tam_bloque, 1, file) != 1) {
                PERR("No se pudo escribir el archivo");
                fclose(file);
        }
        /* Grabo el bloque */
        if (fwrite(block, efs->tam_bloque, 1, file) != 1) {
                PERR("No se pudo escribir el archivo");
                fclose(file);
-               *err = 6; /* EMUFS_ERROR_WRITE_FILE */
+               *err = EMUFS_ERROR_WRITE_FILE;
                return EMUFS_NOT_FOUND;
        }
 
                return EMUFS_NOT_FOUND;
        }
 
@@ -583,111 +654,11 @@ EMUFS_BLOCK_ID emufs_tipo1_grabar_bloque(EMUFS *efs, void *block,
        return block_id;
 }
 
        return block_id;
 }
 
-static int emufs_tipo1_grabar_registro_con_id(EMUFS* efs, void* reg,
-               EMUFS_TIPO1_REG_HEADER header)
-{
-       EMUFS_FREE     fs; /* espacio libre en el bloque */
-       EMUFS_BLOCK_ID block_id; /* identificador del 1er bloque */
-       char*          block; /* buffer del bloque a guardar en disco */
-       char           name_f[255];
-       int            err = 0;
-
-       strcpy(name_f, efs->nombre);
-       strcat(name_f, ".dat");
-
-       /* busco lugar para el registro en un bloque existente */
-       block_id = emufs_fsc_buscar_lugar(efs, sizeof(EMUFS_TIPO1_REG_HEADER)
-                       + header.size, &fs);
-       /* si no hay bloques con suficiente espacio creo un bloque nuevo */
-       if (block_id == EMUFS_NOT_FOUND) {
-               /* tamaño máximo ultilizable para datos en un bloque */
-               EMUFS_BLOCK_SIZE block_space = efs->tam_bloque - sizeof(EMUFS_TIPO1_REG_HEADER);
-               /* identificador del bloque que se guarda */
-               EMUFS_BLOCK_ID curr_block_id = EMUFS_NOT_FOUND;
-               /* tamaño de la porción de registro que se guarda */
-               EMUFS_REG_SIZE chunk_size = 0; 
-               /* puntero a la poción del registro */
-               char* chunk_ptr = reg; 
-
-               /* crear un nuevo bloque en memoria */
-               block = (char*) malloc(efs->tam_bloque);
-               if (block == NULL) {
-                       /* TODO Manejo de errores */
-                       PERR("No hay memoria");
-                       return 2; /* EMUFS_ERROR_OUT_OF_MEMORY */
-               }
-               do {
-                       memset(block, 0, efs->tam_bloque); /* inicializa bloque */
-                       chunk_ptr += chunk_size; /* Avanzo para guardar prox chunk */
-                       header.size -= chunk_size; /* Resto lo que ya guardé */
-                       chunk_size = MIN(header.size, block_space);
-                       /* graba porción del registro en bloque */
-                       emufs_tipo1_escribir_reg_chunk_en_memoria(block, header, chunk_ptr, chunk_size);
-                       /* graba el bloque en el archivo */
-                       curr_block_id = emufs_tipo1_grabar_bloque(efs, block, EMUFS_NOT_FOUND, &err);
-                       if (err) {
-                               PERR("error al grabar bloque");
-                               free(block);
-                               return err;
-                       }
-                       /* grabo el nuevo registro en el archivo de espacios libres */
-                       err = emufs_fsc_agregar(efs, curr_block_id, block_space - chunk_size);
-                       if (err) {
-                               PERR("No se pudo agregar fsc");
-                               free(block);
-                               return err;
-                       }
-                       /* si es el primer id de bloque obtenido, lo guardo para
-                        * agregarlo después al archivo de índices. */
-                       if (block_id == EMUFS_NOT_FOUND) {
-                               block_id = curr_block_id;
-                       }
-               } while (header.size > block_space);
-               free(block);
-
-       /* Encontró espacio en un bloque existente, graba registro ahí */
-       } else {
-               /* cargo el bloque en block_id */
-               if (!(block = (char*) emufs_tipo1_leer_bloque(efs, block_id, &err))) {
-                       /* TODO Manejo de errores */
-                       PERR("no se pudo leer el bloque");
-                       return err;
-               }
-               /* graba registro en bloque */
-               emufs_tipo1_escribir_reg_en_memoria(block + efs->tam_bloque - fs,
-                               header, reg);
-               /* graba el bloque en el archivo */
-               block_id = emufs_tipo1_grabar_bloque(efs, block, block_id, &err);
-               if (err) {
-                       PERR("error al grabar bloque");
-                       free(block);
-                       return err;
-               }
-               free(block);
-               /* actualizo el archivo de espacios libres */
-               err = emufs_fsc_actualizar(efs, block_id, fs - header.size
-                               - sizeof(EMUFS_TIPO1_REG_HEADER));
-               if (err) {
-                       PERR("No se pudo actualizar fsc");
-                       return err;
-               }
-       }
-               
-       /* actualizo el indice de bloques y registros */
-       err = emufs_idx_agregar(efs, header.id, block_id);
-       if (err){
-               PERR("No se pudo agregar idx");
-               return err;
-       }
-       
-       return err;
-}
-
-EMUFS_REG_ID emufs_tipo1_modificar_registro(EMUFS *emu, EMUFS_REG_ID id,
-               void *data, EMUFS_REG_SIZE size, int *error)
+EMUFS_REG_ID emufs_tipo1_modificar_registro(EMUFS* efs, EMUFS_REG_ID id,
+               void *data, EMUFS_REG_SIZE size, int* err)
 {
 {
-       emufs_tipo1_borrar_registro(emu, id);
-       return emufs_tipo1_grabar_registro(emu, data, size, error);
+       emufs_tipo1_borrar_registro(efs, id);
+       return emufs_tipo1_grabar_registro(efs, data, size, err);
 }
 
 size_t emufs_tipo1_header_size(void)
 }
 
 size_t emufs_tipo1_header_size(void)
@@ -699,24 +670,18 @@ int emufs_tipo1_header_jump(FILE* fp)
 {
        if (fseek(fp, emufs_tipo1_header_size(), SEEK_CUR)) {
                PERR("No se pudo hacer fseek()");
 {
        if (fseek(fp, emufs_tipo1_header_size(), SEEK_CUR)) {
                PERR("No se pudo hacer fseek()");
-               return 8; /* EMUFS_ERROR_SEEK_FILE */
+               return EMUFS_ERROR_SEEK_FILE;
        }
        }
-       return 0; /* EMUFS_OK */
+       return EMUFS_OK;
 }
 
 int emufs_tipo1_block_jump(EMUFS* efs, FILE* fp, EMUFS_BLOCK_ID block_count)
 {
        if (fseek(fp, block_count * efs->tam_bloque, SEEK_CUR)) {
                PERR("No se pudo hacer fseek()");
 }
 
 int emufs_tipo1_block_jump(EMUFS* efs, FILE* fp, EMUFS_BLOCK_ID block_count)
 {
        if (fseek(fp, block_count * efs->tam_bloque, SEEK_CUR)) {
                PERR("No se pudo hacer fseek()");
-               return 8; /* EMUFS_ERROR_SEEK_FILE */
+               return EMUFS_ERROR_SEEK_FILE;
        }
        }
-       return 0; /* EMUFS_OK */
-}
-
-void emufs_tipo1_escribir_reg_en_memoria(char* dst, EMUFS_TIPO1_REG_HEADER header,
-               char* reg)
-{
-       emufs_tipo1_escribir_reg_chunk_en_memoria(dst, header, reg, header.size);
+       return EMUFS_OK;
 }
 
 void emufs_tipo1_escribir_reg_chunk_en_memoria(char* dst,
 }
 
 void emufs_tipo1_escribir_reg_chunk_en_memoria(char* dst,
@@ -739,9 +704,8 @@ long emufs_tipo1_get_file_size(EMUFS* efs, int* err)
        strcpy(name_f, efs->nombre);
        strcat(name_f, ".dat");
        if ((file = fopen(name_f, "ab")) == NULL) {
        strcpy(name_f, efs->nombre);
        strcat(name_f, ".dat");
        if ((file = fopen(name_f, "ab")) == NULL) {
-               /* TODO Manejo de errores */
                PERR("Error al abrir archivo");
                PERR("Error al abrir archivo");
-               *err = 4; /* EMUFS_ERROR_CANT_OPEN_FILE */
+               *err = EMUFS_ERROR_CANT_OPEN_FILE;
                return 0;
        }
        file_size = ftell(file);
                return 0;
        }
        file_size = ftell(file);
@@ -749,3 +713,12 @@ long emufs_tipo1_get_file_size(EMUFS* efs, int* err)
        return file_size;
 }
 
        return file_size;
 }
 
+void emufs_tipo1_leer_bloque_raw(EMUFS *efs, EMUFS_BLOCK_ID id, char **actual, char **anterior, char **siguiente, EMUFS_BLOCK_SIZE *size1, EMUFS_BLOCK_SIZE *size2, EMUFS_BLOCK_SIZE *size3)
+{
+       int err = 0;
+       (*actual) = emufs_tipo1_leer_bloque(efs, id, &err);
+       (*anterior) = emufs_tipo1_leer_bloque(efs, id-1, &err);
+       (*siguiente) = emufs_tipo1_leer_bloque(efs, id+1, &err);
+       (*size1) = (*size2) = (*size3) = efs->tam_bloque;
+}
+