]> git.llucax.com Git - z.facultad/75.06/emufs.git/blob - emufs/tipo1.c
Se pasan algunas funciones "privadas" al .c.
[z.facultad/75.06/emufs.git] / emufs / tipo1.c
1 /* vim: set noexpandtab tabstop=4 shiftwidth=4 wrap:
2  *----------------------------------------------------------------------------
3  *                                  emufs
4  *----------------------------------------------------------------------------
5  * This file is part of emufs.
6  *
7  * emufs is free software; you can redistribute it and/or modify it under the
8  * terms of the GNU General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option) any later
10  * version.
11  *
12  * emufs is distributed in the hope that it will be useful, but WITHOUT ANY
13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15  * details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with emufs; if not, write to the Free Software Foundation, Inc., 59 Temple
19  * Place, Suite 330, Boston, MA  02111-1307  USA
20  *----------------------------------------------------------------------------
21  * Creado:  vie abr  9 16:47:32 ART 2004
22  * Autores: Leandro Lucarella <llucare@fi.uba.ar>
23  *----------------------------------------------------------------------------
24  *
25  * $Id$
26  *
27  */
28
29 /** \file
30  *
31  * Archivo con bloque de longitud parametrizada, registro de longitud variable.
32  * 
33  * Implementación del archivo con bloques de longitud parametrizada y registros
34  * de longitud variable.
35  *
36  */
37
38 #include "tipo1.h"
39 #include "idx.h"
40 #include "fsc.h"
41 #include "did.h"
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46
47 #ifndef MIN
48 #       define MIN(x, y) (((x) > (y)) ? (y) : (x))
49 #endif
50
51 /*------------------ Declaraciones privadas ----------------------*/
52
53 /** Cabecera de un registro de un archivo tipo1. */
54 typedef struct {
55         EMUFS_REG_ID   id;   /**< Identificador del registro. */
56         EMUFS_REG_SIZE size; /**< Tamaño del registro. */
57 } EMUFS_TIPO1_REG_HEADER;
58
59 static size_t emufs_tipo1_header_size(void);
60
61 static int emufs_tipo1_header_jump(FILE*);
62
63 static int emufs_tipo1_block_jump(EMUFS*, FILE*, EMUFS_BLOCK_ID);
64
65 static void emufs_tipo1_escribir_reg_en_memoria(char*, EMUFS_TIPO1_REG_HEADER,
66                 char*);
67
68 static void emufs_tipo1_escribir_reg_chunk_en_memoria(char* dst,
69                 EMUFS_TIPO1_REG_HEADER header, char* reg, EMUFS_REG_SIZE reg_size);
70
71 /** Lee el bloque \param num_bloque y lo almacena en \c ptr. */
72 static void* emufs_tipo1_leer_bloque(EMUFS*, EMUFS_BLOCK_ID, int*);
73
74 /** Graba el bloque apuntado por \c ptr en el archivo. */
75 static EMUFS_BLOCK_ID emufs_tipo1_grabar_bloque(EMUFS*, void*, EMUFS_BLOCK_ID,
76                 int*);
77
78 /*------------------ Funciones públicas ----------------------*/
79
80 int emufs_tipo1_inicializar(EMUFS* efs)
81 {
82         /* Asigna punteros a funciones. */
83         efs->leer_bloque       = emufs_tipo1_leer_bloque;
84         efs->grabar_registro   = emufs_tipo1_grabar_registro;
85         efs->borrar_registro   = emufs_tipo1_borrar_registro;
86         efs->leer_registro     = emufs_tipo1_leer_registro;
87         efs->leer_registro_raw = emufs_tipo1_leer_registro_raw;
88         return 0;
89 }
90
91 void* emufs_tipo1_leer_registro(EMUFS* efs, EMUFS_REG_ID reg_id,
92                 EMUFS_REG_SIZE* reg_size, int *err)
93 {
94         char* block; /* bloque leido (en donde está el registro a leer) */
95         char* registro; /* registro a leer */
96         EMUFS_BLOCK_ID block_id; /* id del bloque en donde esta el registro a leer */
97         EMUFS_BLOCK_SIZE offset; /* offset del bloque leído */
98         EMUFS_TIPO1_REG_HEADER curr_reg_header; /* cabecera del registro a leer */
99
100         block_id = emufs_idx_buscar_registro(efs, reg_id);
101         if (block_id == EMUFS_NOT_FOUND) {
102                 /* TODO Manejo de errores */
103                 PERR("Registro no encontrado");
104                 *err = EMUFS_NOT_FOUND;
105                 return NULL;
106         }
107         if (!(block = (char*) emufs_tipo1_leer_bloque(efs, block_id, err))) {
108                 /* TODO Manejo de errores */
109                 PERR("no se pudo reservar memoria");
110                 *err = 2; /* EMUFS_ERROR_OUT_OF_MEMORY */
111                 return NULL;
112         }
113
114         /* Busco secuencialmente en el bloque el registro a leer */
115         offset = 0;
116         do {
117                 /* Copio la cabecera del registro actual. */
118                 memcpy(&curr_reg_header, block + offset, sizeof(EMUFS_TIPO1_REG_HEADER));
119                 offset += sizeof(EMUFS_TIPO1_REG_HEADER);
120                 if (curr_reg_header.id == reg_id) {
121                         /* tamaño máximo ultilizable para datos en un bloque */
122                         EMUFS_BLOCK_SIZE block_space
123                                         = efs->tam_bloque - sizeof(EMUFS_TIPO1_REG_HEADER);
124                         /* tamaño de la porción de registro que se guarda */
125                         EMUFS_REG_SIZE chunk_size = 0; 
126                         /* puntero a la porción actual del registro */
127                         char* chunk_ptr;
128
129                         *reg_size = curr_reg_header.size;
130                         registro = chunk_ptr = (char*) malloc(*reg_size);
131                         if (registro == NULL) {
132                                 /* TODO Manejo de errores */
133                                 free(block);
134                                 PERR("No hay memoria");
135                                 *err = 2; /* EMUFS_ERROR_OUT_OF_MEMORY */
136                                 return NULL;
137                         }
138                         while (1) {
139                                 chunk_ptr += chunk_size; /* Avanzo para guardar prox chunk */
140                                 curr_reg_header.size -= chunk_size; /* Resto lo que ya guardé */
141                                 chunk_size = MIN(curr_reg_header.size, block_space);
142                                 /* copio porción de registro en el buffer */
143                                 memcpy(chunk_ptr, block + offset, chunk_size);
144                                  /* falta leer un bloque */
145                                 if (curr_reg_header.size > block_space) {
146                                         free(block);
147                                         if (!(block = (char*) emufs_tipo1_leer_bloque(efs,
148                                                                         ++block_id, err))) {
149                                                 /* TODO Manejo de errores */
150                                                 free(registro);
151                                                 PERR("no se pudo reservar memoria");
152                                                 *err = 2; /* EMUFS_ERROR_OUT_OF_MEMORY */
153                                                 return NULL;
154                                         }
155                                 } else { /* se terminó de leer */
156                                         break;
157                                 }
158                         }
159                         break;
160                 }
161                 /* Desplazo el offset */
162                 offset += curr_reg_header.size;
163
164         /* esto no debería ser nunca false porque sé positivamente que el */
165         } while (offset < efs->tam_bloque); /* registro está en el bloque */
166
167         free(block);
168         return registro;
169 }
170
171 /* @todo TODO hacer que soporte registros de más de un bloque */
172 void* emufs_tipo1_leer_registro_raw(EMUFS *efs, EMUFS_REG_ID id,
173                 EMUFS_REG_SIZE *size, int *pos)
174 {
175         char* block; /* bloque leido (en donde está el registro a leer) */
176         EMUFS_BLOCK_ID block_id; /* id del bloque en donde esta el registro a leer */
177         EMUFS_BLOCK_SIZE offset; /* offset del bloque leído */
178         EMUFS_TIPO1_REG_HEADER curr_reg_header; /* cabecera del registro a leer */
179         int err;
180
181         block_id = emufs_idx_buscar_registro(efs, id);
182         if (block_id == EMUFS_NOT_FOUND) {
183                 return NULL;
184         }
185         err = 0;
186         if (!(block = (char*) emufs_tipo1_leer_bloque(efs, block_id, &err))) {
187                 return NULL;
188         }
189
190         /* Busco secuencialmente en el bloque el registro a leer */
191         offset = 0;
192         do {
193                 /* Copio la cabecera del registro. */
194                 memcpy(&curr_reg_header, block + offset, sizeof(EMUFS_TIPO1_REG_HEADER));
195                 offset += sizeof(EMUFS_TIPO1_REG_HEADER);
196                 if (curr_reg_header.id == id) {
197                         *pos = offset - sizeof(EMUFS_TIPO1_REG_HEADER);
198                         break;
199                 }
200                 /* Desplazo el offset */
201                 offset += curr_reg_header.size;
202         } while (offset < efs->tam_bloque);
203
204         (*size) = efs->tam_bloque;
205         return block;
206 }
207
208 void* emufs_tipo1_leer_bloque(EMUFS* efs, EMUFS_BLOCK_ID block_id, int *err)
209 {
210         FILE* file;
211         char* block; /* bloque leido (en donde está el registro a leer) */
212         char  name_f[255];
213
214         strcpy(name_f,efs->nombre);
215         strcat(name_f,".dat");
216
217         if ((file = fopen(name_f, "r")) == NULL) {
218                 PERR("No se puede abrir archivo");
219                 *err = 4; /* EMUFS_ERROR_CANT_OPEN_FILE */
220                 return NULL; /* FIXME ERROR */
221         }
222         emufs_tipo1_header_jump(file); /* salta cabeceras */
223         emufs_tipo1_block_jump(efs, file, block_id); /* salta bloques */
224         /* FIXME: verificar que no se pase de fin de archivo*/
225         block = (char*) malloc(efs->tam_bloque);
226         if (block == NULL) {
227                 /* TODO Manejo de errores */
228                 PERR("No hay memoria");
229                 *err = 2; /* EMUFS_ERROR_OUT_OF_MEMORY */
230                 return NULL;
231         }
232         if (fread(block, efs->tam_bloque, 1, file) != 1) {
233                 /* TODO Manejo de errores */
234                 free(block);
235                 PERR("Error al leer bloque");
236                 *err = 3; /* EMUFS_ERROR_FILE_READ */
237                 return NULL;
238         }
239         fclose(file);
240         return block;
241 }
242
243 EMUFS_REG_ID emufs_tipo1_grabar_registro(EMUFS* efs, void* reg, EMUFS_REG_SIZE reg_size, int* err)
244 {
245         EMUFS_TIPO1_REG_HEADER reg_header; /* cabecera del registro a guardar */
246         EMUFS_FREE             fs; /* espacio libre en el bloque */
247         EMUFS_BLOCK_ID         block_id; /* identificador del 1er bloque */
248         char*                  block; /* buffer del bloque a guardar en disco */
249         char                   name_f[255];
250
251         strcpy(name_f, efs->nombre);
252         strcat(name_f, ".dat");
253
254         /* pongo tamaño del registro en la cabecera. */
255         reg_header.size = reg_size;
256         /* busco lugar para el registro en un bloque existente */
257         block_id = emufs_fsc_buscar_lugar(efs, sizeof(EMUFS_TIPO1_REG_HEADER)
258                         + reg_size, &fs);
259         /* si no hay bloques con suficiente espacio creo un bloque nuevo */
260         if (block_id == EMUFS_NOT_FOUND) {
261                 /* tamaño máximo ultilizable para datos en un bloque */
262                 EMUFS_BLOCK_SIZE block_space = efs->tam_bloque - sizeof(EMUFS_TIPO1_REG_HEADER);
263                 /* identificador del bloque que se guarda */
264                 EMUFS_BLOCK_ID curr_block_id = EMUFS_NOT_FOUND;
265                 /* tamaño de la porción de registro que se guarda */
266                 EMUFS_REG_SIZE chunk_size = 0; 
267                 /* puntero a la poción del registro */
268                 char* chunk_ptr = reg; 
269
270                 /* crear un nuevo bloque en memoria */
271                 block = (char*) malloc(efs->tam_bloque);
272                 if (block == NULL) {
273                         /* TODO Manejo de errores */
274                         PERR("No hay memoria");
275                         *err = 2; /* EMUFS_ERROR_OUT_OF_MEMORY */
276                         return EMUFS_NOT_FOUND;
277                 }
278                 reg_header.id = emufs_idx_get_new_id(efs, err);
279                 do {
280                         memset(block, 0, efs->tam_bloque); /* inicializa bloque */
281                         chunk_ptr += chunk_size; /* Avanzo para guardar prox chunk */
282                         reg_header.size -= chunk_size; /* Resto lo que ya guardé */
283                         chunk_size = MIN(reg_header.size, block_space);
284                         /* graba porción del registro en bloque */
285                         emufs_tipo1_escribir_reg_chunk_en_memoria(block, reg_header, chunk_ptr, chunk_size);
286                         /* graba el bloque en el archivo */
287                         curr_block_id = emufs_tipo1_grabar_bloque(efs, block, EMUFS_NOT_FOUND, err);
288                         if (*err) {
289                                 PERR("error al grabar bloque");
290                                 free(block);
291                                 return EMUFS_NOT_FOUND;
292                         }
293                         /* grabo el nuevo registro en el archivo de espacios libres */
294                         *err = emufs_fsc_agregar(efs, curr_block_id, block_space - chunk_size);
295                         if (*err) {
296                                 PERR("No se pudo agregar fsc");
297                                 free(block);
298                                 return EMUFS_NOT_FOUND;
299                         }
300                         /* si es el primer id de bloque obtenido, lo guardo para
301                          * agregarlo después al archivo de índices. */
302                         if (block_id == EMUFS_NOT_FOUND) {
303                                 block_id = curr_block_id;
304                         }
305                 } while (reg_header.size > block_space);
306                 free(block);
307
308         /* Encontró espacio en un bloque existente, graba registro ahí */
309         } else {
310                 /* cargo el bloque en block_id */
311                 if (!(block = (char*) emufs_tipo1_leer_bloque(efs, block_id, err))) {
312                         /* TODO Manejo de errores */
313                         PERR("no se pudo leer el bloque");
314                         return EMUFS_NOT_FOUND;
315                 }
316                 /* inserta el registro en el bloque */
317                 /* tengo que buscar un ID válido para el nuevo registro */
318                 reg_header.id = emufs_idx_get_new_id(efs, err);
319                 /* graba registro en bloque */
320                 emufs_tipo1_escribir_reg_en_memoria(block + efs->tam_bloque - fs,
321                                 reg_header, reg);
322                 /* graba el bloque en el archivo */
323                 block_id = emufs_tipo1_grabar_bloque(efs, block, block_id, err);
324                 if (*err) {
325                         PERR("error al grabar bloque");
326                         free(block);
327                         return EMUFS_NOT_FOUND;
328                 }
329                 free(block);
330                 /* actualizo el archivo de espacios libres */
331                 *err = emufs_fsc_actualizar(efs, block_id, fs - reg_size
332                                 - sizeof(EMUFS_TIPO1_REG_HEADER));
333                 if (*err) {
334                         PERR("No se pudo actualizar fsc");
335                         return EMUFS_NOT_FOUND;
336                 }
337         }
338                 
339         /* actualizo el indice de bloques y registros */
340         *err = emufs_idx_agregar(efs, reg_header.id, block_id);
341         if (*err){
342                 PERR("No se pudo agregar idx");
343                 return EMUFS_NOT_FOUND;
344         }
345         
346         return reg_header.id;
347 }
348
349 int emufs_tipo1_borrar_registro(EMUFS* efs, EMUFS_REG_ID reg_id)
350 {
351         char* block; /* bloque leido (en donde está el registro a leer) */
352         EMUFS_BLOCK_ID block_id; /* id del bloque en donde esta el registro a leer */
353         EMUFS_BLOCK_SIZE offset; /* offset del bloque leído */
354         EMUFS_TIPO1_REG_HEADER curr_reg_header; /* cabecera del registro a leer */
355         int err = 0; /* para almacenar código de error */
356
357         block_id = emufs_idx_buscar_registro(efs, reg_id);
358         if (block_id == EMUFS_NOT_FOUND) {
359                 /* TODO Manejo de errores */
360                 PERR("Registro no encontrado");
361                 return EMUFS_NOT_FOUND;
362         }
363         if (!(block = (char*) emufs_tipo1_leer_bloque(efs, block_id, &err))) {
364                 /* TODO Manejo de errores */
365                 PERR("no se pudo reservar memoria");
366                 return err;
367         }
368
369         /* Busco secuencialmente en el bloque el registro a leer */
370         offset = 0;
371         do {
372                 /* Copio la cabecera del registro actual. */
373                 memcpy(&curr_reg_header, block + offset, sizeof(EMUFS_TIPO1_REG_HEADER));
374                 if (curr_reg_header.id == reg_id) {
375                         /* identificador del bloque actual */
376                         EMUFS_BLOCK_ID curr_block_id = block_id;
377                         /* tamaño máximo ultilizable para datos en un bloque */
378                         EMUFS_BLOCK_SIZE block_space
379                                         = efs->tam_bloque - sizeof(EMUFS_TIPO1_REG_HEADER);
380                         EMUFS_FREE fs; /* cantidad de espacio libre en el bloque */
381
382                         while (1) {
383                                 /* actualizo archivo de espacio libre por bloque */
384                                 fs = emufs_fsc_get_fs(efs, curr_block_id)
385                                         + MIN(curr_reg_header.size, block_space)
386                                         + sizeof(EMUFS_TIPO1_REG_HEADER);
387                                 if ((err = emufs_fsc_actualizar(efs, curr_block_id, fs))) {
388                                         /* TODO Manejo de errores */
389                                         PERR("no se pudo actualizar .fsc");
390                                         free(block);
391                                         return err;
392                                 }
393                                 /* falta liberar un bloque (o porción) */
394                                 if (curr_reg_header.size > block_space) {
395                                         free(block);
396                                         if (!(block = (char*) emufs_tipo1_leer_bloque(efs,
397                                                                         ++curr_block_id, &err))) {
398                                                 /* TODO Manejo de errores */
399                                                 PERR("no se pudo leer el bloque");
400                                                 return err;
401                                         }
402                                         /* copio la cabecera del primer registro (si ocupa más de un
403                                          * registro está en bloques contiguos) */
404                                         memcpy(&curr_reg_header, block,
405                                                         sizeof(EMUFS_TIPO1_REG_HEADER));
406                                 } else { /* se terminó de leer */
407                                         break;
408                                 }
409                         }
410
411                         /* actualizo archivo de identificadores de registros borrados */
412                         if ((err = emufs_did_agregar(efs, reg_id))) {
413                                 /* TODO Manejo de errores */
414                                 PERR("no se pudo actualizar .did");
415                                 free(block);
416                                 return err;
417                         }
418                         /*actualizo archivo .idx*/
419                         if ((err = emufs_idx_borrar(efs, reg_id))) {
420                                 /* TODO Manejo de errores */
421                                 PERR("no se pudo actualizar .did");
422                                 free(block);
423                                 return err;
424                         }
425
426                         /* desplazo registros a izquierda */
427                         {   /* offset del fin del registro a borrar */
428                                 EMUFS_BLOCK_SIZE offset_reg_end = offset
429                                         + sizeof(EMUFS_TIPO1_REG_HEADER) + curr_reg_header.size;
430                                 /* si es necesario desplazar */
431                                 if (offset < offset_reg_end) {
432                                         /* muevo la porción de bloque a izquierda */
433                                         memcpy(block + offset, block + offset_reg_end,
434                                                 efs->tam_bloque - offset_reg_end);
435                                 }
436                         }
437                         /* guardo el bloque en disco */
438                         emufs_tipo1_grabar_bloque(efs, block, curr_block_id, &err);
439                         if (err) {
440                                 /* TODO Manejo de errores */
441                                 PERR("no se pudo grabar bloque en disco");
442                                 free(block);
443                                 return err;
444                         }
445
446                         break; /* salgo del loop, ya hice todo lo que tenía que hacer */
447                 }
448                 /* desplazo el offset */
449                 offset += sizeof(EMUFS_TIPO1_REG_HEADER) + curr_reg_header.size;
450
451         /* esto no debería ser nunca false porque sé positivamente que el */
452         } while (offset < efs->tam_bloque); /* registro está en el bloque */
453
454         free(block);
455         return 0; /* EMUFS_OK */
456 }
457
458 /** Graba un bloque en el archivo. */
459 EMUFS_BLOCK_ID emufs_tipo1_grabar_bloque(EMUFS *efs, void *block,
460                 EMUFS_BLOCK_ID block_id, int* err)
461 {
462         FILE* file;
463         char name_f[255];
464
465         strcpy(name_f,efs->nombre);
466         strcat(name_f,".dat");
467
468         if ((file = fopen(name_f, "r+b")) == NULL) {
469                 /* TODO Manejo de errores */
470                 PERR("Error al abrir archivo");
471                 *err = 4; /* EMUFS_ERROR_CANT_OPEN_FILE */
472                 return EMUFS_NOT_FOUND;
473         }
474         /* Si es NOT_FOUND tengo que agregar un bloque al final del archivo */
475         if (block_id == EMUFS_NOT_FOUND) {
476                 /* me paro al final del archivo */
477                 if (fseek(file, 0l, SEEK_END)) {
478                         /* TODO Manejo de errores */
479                         PERR("No se pudo hacer fseek()");
480                         fclose(file);
481                         *err = 8; /* EMUFS_ERROR_SEEK_FILE */
482                         return EMUFS_NOT_FOUND;
483                 }
484                 /* Obtengo ID del bloque nuevo */
485                 block_id = (ftell(file) - emufs_tipo1_header_size()) / efs->tam_bloque;
486         /* Si es un ID válido, salto hasta ese bloque. */
487         } else {
488                 /* Salta el header del archivo */
489                 if ((*err = emufs_tipo1_header_jump(file))) {
490                         PERR("no se pudo saltar la cabecera del archivo");
491                         fclose(file);
492                         return EMUFS_NOT_FOUND;
493                 }
494                 /* Salta bloques */
495                 if ((*err = emufs_tipo1_block_jump(efs, file, block_id))) {
496                         PERR("no se pudo saltar la cabecera del bloque");
497                         fclose(file);
498                         return EMUFS_NOT_FOUND;
499                 }
500         }
501         /* Grabo el bloque */
502         if (fwrite(block, efs->tam_bloque, 1, file) != 1) {
503                 PERR("No se pudo escribir el archivo");
504                 fclose(file);
505                 *err = 6; /* EMUFS_ERROR_WRITE_FILE */
506                 return EMUFS_NOT_FOUND;
507         }
508
509         fclose(file);
510         return block_id;
511 }
512
513 EMUFS_REG_ID emufs_tipo1_modificar_registro(EMUFS *emu, EMUFS_REG_ID id,
514                 void *data, EMUFS_REG_SIZE size, int *error)
515 {
516         emufs_tipo1_borrar_registro(emu, id);
517         return emufs_tipo1_grabar_registro(emu, data, size, error);
518 }
519
520 size_t emufs_tipo1_header_size(void)
521 {
522         return sizeof(EMUFS_Tipo) + sizeof(EMUFS_BLOCK_SIZE);
523 }
524
525 int emufs_tipo1_header_jump(FILE* fp)
526 {
527         if (fseek(fp, emufs_tipo1_header_size(), SEEK_CUR)) {
528                 PERR("No se pudo hacer fseek()");
529                 return 8; /* EMUFS_ERROR_SEEK_FILE */
530         }
531         return 0; /* EMUFS_OK */
532 }
533
534 int emufs_tipo1_block_jump(EMUFS* efs, FILE* fp, EMUFS_BLOCK_ID block_count)
535 {
536         if (fseek(fp, block_count * efs->tam_bloque, SEEK_CUR)) {
537                 PERR("No se pudo hacer fseek()");
538                 return 8; /* EMUFS_ERROR_SEEK_FILE */
539         }
540         return 0; /* EMUFS_OK */
541 }
542
543 void emufs_tipo1_escribir_reg_en_memoria(char* dst, EMUFS_TIPO1_REG_HEADER header,
544                 char* reg)
545 {
546         emufs_tipo1_escribir_reg_chunk_en_memoria(dst, header, reg, header.size);
547 }
548
549 void emufs_tipo1_escribir_reg_chunk_en_memoria(char* dst,
550                 EMUFS_TIPO1_REG_HEADER header, char* reg, EMUFS_REG_SIZE reg_size)
551 {
552         /* grabo cabecera del registro en el bloque */
553         memcpy(dst, &header, sizeof(EMUFS_TIPO1_REG_HEADER));
554         /* incremento puntero de escritura */
555         dst += sizeof(EMUFS_TIPO1_REG_HEADER);
556         /* grabo el registro en el bloque */
557         memcpy(dst, reg, reg_size);
558 }
559