1 /* vim: set noexpandtab tabstop=4 shiftwidth=4 wrap:
2 *----------------------------------------------------------------------------
4 *----------------------------------------------------------------------------
5 * This file is part of emufs.
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
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
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 *----------------------------------------------------------------------------
31 * Archivo con bloque de longitud parametrizada, registro de longitud variable.
33 * Implementación del archivo con bloques de longitud parametrizada y registros
34 * de longitud variable.
49 # define MIN(x, y) (((x) > (y)) ? (y) : (x))
52 /*------------------ Declaraciones privadas ----------------------*/
54 /** Cabecera de un registro de un archivo tipo1. */
56 EMUFS_REG_ID id; /**< Identificador del registro. */
57 EMUFS_REG_SIZE size; /**< Tamaño del registro. */
58 } EMUFS_TIPO1_REG_HEADER;
60 static size_t emufs_tipo1_header_size(void);
62 static int emufs_tipo1_header_jump(FILE*);
64 static int emufs_tipo1_block_jump(EMUFS*, FILE*, EMUFS_BLOCK_ID);
66 static void emufs_tipo1_escribir_reg_en_memoria(char*, EMUFS_TIPO1_REG_HEADER,
69 static void emufs_tipo1_escribir_reg_chunk_en_memoria(char* dst,
70 EMUFS_TIPO1_REG_HEADER header, char* reg, EMUFS_REG_SIZE reg_size);
72 /** Lee el bloque \param num_bloque y lo almacena en \c ptr. */
73 static void* emufs_tipo1_leer_bloque(EMUFS*, EMUFS_BLOCK_ID, int*);
75 /** Graba un bloque en el archivo y actualiza .fsc, si se solicita. */
76 static EMUFS_BLOCK_ID emufs_tipo1_grabar_bloque_fsc(EMUFS*, void*,
77 EMUFS_BLOCK_ID, EMUFS_FREE, int*);
79 /** Obtiene el tamaño del archivo. */
80 static long emufs_tipo1_get_file_size(EMUFS*, int*);
82 /*------------------ Funciones públicas ----------------------*/
84 int emufs_tipo1_inicializar(EMUFS* efs)
86 /* como mínimo el tamaño de bloque debe ser 2 veces el tamaño de la cabecera
87 * (una relación 1/2 entre datos e info de control ya es lo suficientemente
89 if (efs->tam_bloque < (sizeof(EMUFS_TIPO1_REG_HEADER) * 2)) {
90 PERR("bloque demasiado chico");
91 return 1000; /* EMUFS_ERROR_BLOCK_SIZE_TOO_SMALL */
93 /* Asigna punteros a funciones. */
94 efs->leer_bloque = emufs_tipo1_leer_bloque;
95 efs->grabar_registro = emufs_tipo1_grabar_registro;
96 efs->borrar_registro = emufs_tipo1_borrar_registro;
97 efs->leer_registro = emufs_tipo1_leer_registro;
98 efs->leer_registro_raw = emufs_tipo1_leer_registro_raw;
99 efs->leer_estadisticas = emufs_tipo1_leer_estadisticas;
100 efs->compactar = emufs_tipo1_compactar;
101 return 0; /* EMUFS_OK */
104 void* emufs_tipo1_leer_registro(EMUFS* efs, EMUFS_REG_ID reg_id,
105 EMUFS_REG_SIZE* reg_size, int *err)
107 char* block; /* bloque leido (en donde está el registro a leer) */
108 char* registro; /* registro a leer */
109 EMUFS_BLOCK_ID block_id; /* id del bloque en donde esta el registro a leer */
110 EMUFS_BLOCK_SIZE offset; /* offset del bloque leído */
111 EMUFS_TIPO1_REG_HEADER curr_reg_header; /* cabecera del registro a leer */
113 block_id = emufs_idx_buscar_registro(efs, reg_id);
114 if (block_id == EMUFS_NOT_FOUND) {
115 /* TODO Manejo de errores */
116 PERR("Registro no encontrado");
117 *err = EMUFS_NOT_FOUND;
120 if (!(block = (char*) emufs_tipo1_leer_bloque(efs, block_id, err))) {
121 /* TODO Manejo de errores */
122 PERR("no se pudo reservar memoria");
123 *err = 2; /* EMUFS_ERROR_OUT_OF_MEMORY */
127 /* Busco secuencialmente en el bloque el registro a leer */
130 /* Copio la cabecera del registro actual. */
131 memcpy(&curr_reg_header, block + offset, sizeof(EMUFS_TIPO1_REG_HEADER));
132 offset += sizeof(EMUFS_TIPO1_REG_HEADER);
133 if (curr_reg_header.id == reg_id) {
134 /* tamaño máximo ultilizable para datos en un bloque */
135 EMUFS_BLOCK_SIZE block_space
136 = efs->tam_bloque - sizeof(EMUFS_TIPO1_REG_HEADER);
137 /* tamaño de la porción de registro que se guarda */
138 EMUFS_REG_SIZE chunk_size = 0;
139 /* puntero a la porción actual del registro */
142 *reg_size = curr_reg_header.size;
143 registro = chunk_ptr = (char*) malloc(*reg_size);
144 if (registro == NULL) {
145 /* TODO Manejo de errores */
147 PERR("No hay memoria");
148 *err = 2; /* EMUFS_ERROR_OUT_OF_MEMORY */
152 chunk_ptr += chunk_size; /* Avanzo para guardar prox chunk */
153 curr_reg_header.size -= chunk_size; /* Resto lo que ya guardé */
154 chunk_size = MIN(curr_reg_header.size, block_space);
155 /* copio porción de registro en el buffer */
156 memcpy(chunk_ptr, block + offset, chunk_size);
157 /* falta leer un bloque */
158 if (curr_reg_header.size > block_space) {
160 if (!(block = (char*) emufs_tipo1_leer_bloque(efs,
162 /* TODO Manejo de errores */
164 PERR("no se pudo reservar memoria");
165 *err = 2; /* EMUFS_ERROR_OUT_OF_MEMORY */
168 } else { /* se terminó de leer */
174 /* Desplazo el offset */
175 offset += curr_reg_header.size;
177 /* esto no debería ser nunca false porque sé positivamente que el */
178 } while (offset < efs->tam_bloque); /* registro está en el bloque */
184 void* emufs_tipo1_leer_registro_raw(EMUFS *efs, EMUFS_REG_ID id, EMUFS_REG_SIZE *size, int *pos)
187 char* block; /* bloque leido (en donde está el registro a leer) */
188 char* registro; /* registro a leer */
189 EMUFS_BLOCK_ID block_id; /* id del bloque en donde esta el registro a leer */
190 EMUFS_BLOCK_SIZE offset, block_space; /* offset del bloque leído */
191 EMUFS_TIPO1_REG_HEADER curr_reg_header; /* cabecera del registro a leer */
192 EMUFS_REG_SIZE cant_bloques;
195 block_id = emufs_idx_buscar_registro(efs, id);
196 if (block_id == EMUFS_NOT_FOUND) {
197 /* TODO Manejo de errores */
198 PERR("Registro no encontrado");
204 if (!(block = (char*) emufs_tipo1_leer_bloque(efs, block_id, &err))) {
205 /* TODO Manejo de errores */
206 PERR("no se pudo reservar memoria");
212 /* Busco secuencialmente en el bloque el registro a leer */
215 /* Copio la cabecera del registro actual. */
216 memcpy(&curr_reg_header, block + offset, sizeof(EMUFS_TIPO1_REG_HEADER));
217 offset += sizeof(EMUFS_TIPO1_REG_HEADER);
218 if (curr_reg_header.id == id) {
219 /* tamaño máximo ultilizable para datos en un bloque */
220 *pos = offset-sizeof(EMUFS_TIPO1_REG_HEADER);
221 block_space = efs->tam_bloque - sizeof(EMUFS_TIPO1_REG_HEADER);
222 /* tamaño de la porción de registro que se guarda */
224 cant_bloques = curr_reg_header.size / block_space + 1;
225 *size = cant_bloques*efs->tam_bloque;
226 registro = chunk_ptr = (char*) malloc(*size - (cant_bloques-1)*sizeof(EMUFS_TIPO1_REG_HEADER) + (cant_bloques-1)*2);
227 if (registro == NULL) {
228 /* TODO Manejo de errores */
230 PERR("No hay memoria");
235 memcpy(registro, block, efs->tam_bloque);
236 chunk_ptr += efs->tam_bloque;
237 /* Copio los otros bloques, si los hay */
239 for(i=1; i<cant_bloques; i++) {
241 block = (char*)emufs_tipo1_leer_bloque(efs, block_id+i, &err);
242 /* Solo grabo el header del primer pedazo! */
243 memcpy(chunk_ptr, "<>", 2);
245 memcpy(chunk_ptr, block+sizeof(EMUFS_TIPO1_REG_HEADER), efs->tam_bloque-sizeof(EMUFS_TIPO1_REG_HEADER));
246 chunk_ptr += efs->tam_bloque-sizeof(EMUFS_TIPO1_REG_HEADER);
252 /* Desplazo el offset */
253 offset += curr_reg_header.size;
254 } while (offset < efs->tam_bloque);
259 void* emufs_tipo1_leer_bloque(EMUFS* efs, EMUFS_BLOCK_ID block_id, int *err)
262 char* block; /* bloque leido (en donde está el registro a leer) */
265 strcpy(name_f,efs->nombre);
266 strcat(name_f,".dat");
268 if ((file = fopen(name_f, "r")) == NULL) {
269 PERR("No se puede abrir archivo");
270 *err = 4; /* EMUFS_ERROR_CANT_OPEN_FILE */
271 return NULL; /* FIXME ERROR */
273 emufs_tipo1_header_jump(file); /* salta cabeceras */
274 emufs_tipo1_block_jump(efs, file, block_id); /* salta bloques */
275 /* FIXME: verificar que no se pase de fin de archivo*/
276 block = (char*) malloc(efs->tam_bloque);
278 /* TODO Manejo de errores */
279 PERR("No hay memoria");
280 *err = 2; /* EMUFS_ERROR_OUT_OF_MEMORY */
283 if (fread(block, efs->tam_bloque, 1, file) != 1) {
284 /* TODO Manejo de errores */
286 PERR("Error al leer bloque");
287 *err = 3; /* EMUFS_ERROR_FILE_READ */
294 EMUFS_REG_ID emufs_tipo1_grabar_registro(EMUFS* efs, void* reg,
295 EMUFS_REG_SIZE reg_size, int* err)
297 EMUFS_TIPO1_REG_HEADER header; /* cabecera del registro a leer */
298 EMUFS_FREE fs; /* espacio libre en el bloque */
299 EMUFS_BLOCK_ID block_id; /* identificador del 1er bloque */
300 char* block; /* buffer del bloque a guardar en disco */
301 char* chunk_ptr = reg; /* puntero a la poción del registro */
302 EMUFS_BLOCK_SIZE block_space /* tamaño máximo para datos en un bloque */
303 = efs->tam_bloque - sizeof(EMUFS_TIPO1_REG_HEADER);
304 /* identificador del bloque que se guarda */
305 EMUFS_BLOCK_ID curr_block_id;
306 /* tamaño de la porción de registro que se guarda */
307 EMUFS_REG_SIZE chunk_size = 0;
309 /* obtengo identificador que corresponderá al registro */
310 header.id = emufs_idx_get_new_id(efs, err);
312 PERR("no se pudo obtener un id para el registro nuevo");
313 return EMUFS_NOT_FOUND;
315 header.size = reg_size; /* tamaño del registro */
317 /* busco lugar para el registro en un bloque existente */
318 block_id = emufs_fsc_buscar_n_lugares(efs,
319 /* cantidad de bloques que necesita el registro */
320 (EMUFS_BLOCK_SIZE) ceil(header.size / (double) block_space),
321 /* cabecera + si es un registro multibloque, tomo el bloque */
322 sizeof(EMUFS_TIPO1_REG_HEADER) + MIN(header.size, block_space),
324 /* si no hay bloques con suficiente espacio creo un bloque nuevo */
325 if (block_id == EMUFS_NOT_FOUND) {
326 /* crear un nuevo bloque en memoria */
327 block = (char*) malloc(efs->tam_bloque);
329 /* TODO Manejo de errores */
330 PERR("No hay memoria");
331 *err = 2; /* EMUFS_ERROR_OUT_OF_MEMORY */
332 return EMUFS_NOT_FOUND;
334 memset(block, 0, efs->tam_bloque); /* inicializa bloque */
335 curr_block_id = EMUFS_NOT_FOUND; /* pongo de bloque actual el final */
336 /* si hay bloques con suficiente espacio, levanto el primero */
338 /* cargo el bloque en block_id */
339 if (!(block = (char*) emufs_tipo1_leer_bloque(efs, block_id, err))) {
340 /* TODO Manejo de errores */
341 PERR("no se pudo leer el bloque");
342 return EMUFS_NOT_FOUND;
344 curr_block_id = block_id; /* pongo de bloque actual el primero */
348 EMUFS_BLOCK_ID new_block_id; /* identificador del bloque nuevo */
349 chunk_ptr += chunk_size; /* Avanzo para guardar prox chunk */
350 header.size -= chunk_size; /* Resto lo que ya guardé */
351 chunk_size = MIN(header.size, block_space);
353 /* graba porción del registro en bloque */ /* destino: fin de bloque */
354 emufs_tipo1_escribir_reg_chunk_en_memoria(block + efs->tam_bloque - fs,
355 header, chunk_ptr, chunk_size);
356 /* graba el bloque en el archivo */
357 new_block_id = emufs_tipo1_grabar_bloque_fsc(efs, block, curr_block_id,
358 fs - sizeof(EMUFS_TIPO1_REG_HEADER) - chunk_size, err);
360 PERR("error al grabar bloque");
362 return EMUFS_NOT_FOUND;
364 /* si es el primer id de bloque obtenido, lo guardo para
365 * agregarlo después al archivo de índices. */
366 if (block_id == EMUFS_NOT_FOUND) {
367 block_id = new_block_id;
369 /* si no estoy por fuera del archivo, incremento el nro. de bloque */
370 if (curr_block_id != EMUFS_NOT_FOUND) {
374 /* mientras que el chunk no entre en un bloque */
375 } while (header.size > block_space);
377 /* libera el bloque */
380 /* actualizo el indice de bloques y registros */
381 *err = emufs_idx_agregar(efs, header.id, block_id);
383 PERR("No se pudo agregar idx");
384 return EMUFS_NOT_FOUND;
390 int emufs_tipo1_borrar_registro(EMUFS* efs, EMUFS_REG_ID reg_id)
392 char* block; /* bloque leido (en donde está el registro a leer) */
393 EMUFS_BLOCK_ID block_id; /* id del bloque en donde esta el registro a leer */
394 EMUFS_BLOCK_SIZE offset; /* offset del bloque leído */
395 EMUFS_TIPO1_REG_HEADER curr_reg_header; /* cabecera del registro a leer */
396 int err = 0; /* para almacenar código de error */
398 block_id = emufs_idx_buscar_registro(efs, reg_id);
399 if (block_id == EMUFS_NOT_FOUND) {
400 /* TODO Manejo de errores */
401 PERR("Registro no encontrado");
402 return EMUFS_NOT_FOUND;
404 if (!(block = (char*) emufs_tipo1_leer_bloque(efs, block_id, &err))) {
405 /* TODO Manejo de errores */
406 PERR("no se pudo reservar memoria");
410 /* Busco secuencialmente en el bloque el registro a leer */
413 /* Copio la cabecera del registro actual. */
414 memcpy(&curr_reg_header, block + offset, sizeof(EMUFS_TIPO1_REG_HEADER));
415 if (curr_reg_header.id == reg_id) {
416 /* identificador del bloque actual */
417 EMUFS_BLOCK_ID curr_block_id = block_id;
418 /* tamaño máximo ultilizable para datos en un bloque */
419 EMUFS_BLOCK_SIZE block_space
420 = efs->tam_bloque - sizeof(EMUFS_TIPO1_REG_HEADER);
421 EMUFS_FREE fs; /* cantidad de espacio libre en el bloque */
424 /* actualizo archivo de espacio libre por bloque */
425 fs = emufs_fsc_get_fs(efs, curr_block_id)
426 + MIN(curr_reg_header.size, block_space)
427 + sizeof(EMUFS_TIPO1_REG_HEADER);
428 if ((err = emufs_fsc_actualizar(efs, curr_block_id, fs))) {
429 /* TODO Manejo de errores */
430 PERR("no se pudo actualizar .fsc");
434 /* falta liberar un bloque (o porción) */
435 if (curr_reg_header.size > block_space) {
437 if (!(block = (char*) emufs_tipo1_leer_bloque(efs,
438 ++curr_block_id, &err))) {
439 /* TODO Manejo de errores */
440 PERR("no se pudo leer el bloque");
443 /* copio la cabecera del primer registro (si ocupa más de un
444 * registro está en bloques contiguos) */
445 memcpy(&curr_reg_header, block,
446 sizeof(EMUFS_TIPO1_REG_HEADER));
447 } else { /* se terminó de leer */
452 /* actualizo archivo de identificadores de registros borrados */
453 if ((err = emufs_did_agregar(efs, reg_id))) {
454 /* TODO Manejo de errores */
455 PERR("no se pudo actualizar .did");
459 /*actualizo archivo .idx*/
460 if ((err = emufs_idx_borrar(efs, reg_id))) {
461 /* TODO Manejo de errores */
462 PERR("no se pudo actualizar .did");
467 /* desplazo registros a izquierda */
468 { /* offset del fin del registro a borrar */
469 EMUFS_BLOCK_SIZE offset_reg_end = offset
470 + sizeof(EMUFS_TIPO1_REG_HEADER) + curr_reg_header.size;
471 /* si es necesario desplazar */
472 if (offset < offset_reg_end) {
473 /* muevo la porción de bloque a izquierda */
474 memcpy(block + offset, block + offset_reg_end,
475 efs->tam_bloque - offset_reg_end);
478 /* guardo el bloque en disco (actualizando espacio libre) */
479 emufs_tipo1_grabar_bloque_fsc(efs, block, curr_block_id,
480 EMUFS_NOT_FOUND, &err);
482 /* TODO Manejo de errores */
483 PERR("no se pudo grabar bloque en disco");
488 break; /* salgo del loop, ya hice todo lo que tenía que hacer */
490 /* desplazo el offset */
491 offset += sizeof(EMUFS_TIPO1_REG_HEADER) + curr_reg_header.size;
493 /* esto no debería ser nunca false porque sé positivamente que el */
494 } while (offset < efs->tam_bloque); /* registro está en el bloque */
497 return 0; /* EMUFS_OK */
500 EMUFS_Estadisticas emufs_tipo1_leer_estadisticas(EMUFS* efs)
503 EMUFS_Estadisticas stats;
504 memset(&stats, 0, sizeof(EMUFS_Estadisticas));
506 stats.tam_archivo_bytes = emufs_tipo1_get_file_size(efs, &err);
508 /* TODO manejo de errores */
509 PERR("no se pudo obtener el tamaño del archivo");
513 /* obtengo cantidad de bloques */
514 stats.cant_bloques = (stats.tam_archivo_bytes - emufs_tipo1_header_size())
517 /* obtengo la cantidad de registros en el archivo */
519 EMUFS_REG_ID *tmp = emufs_idx_get(efs, &stats.tam_archivo);
520 if (tmp) free(tmp); /* libera memoria innecesaria */
523 /* obtengo total de información de control que guarda el archivo */
524 stats.info_control = emufs_tipo1_header_size() /* cabecera del archivo */
525 /* mas las cabeceras de todos los registros */
526 + stats.tam_archivo * sizeof(EMUFS_TIPO1_REG_HEADER);
528 /* obtengo las estadísticas del archivo de espacio libre por bloque */
529 stats.total_fs = emufs_fsc_get_total_fs(efs);
530 stats.media_fs = emufs_fsc_get_media_fs(efs);
531 emufs_fsc_get_max_min_fs(efs, &stats.min_fs, &stats.max_fs);
536 void emufs_tipo1_compactar(EMUFS* efs)
538 EMUFS_BLOCK_SIZE block_space /* tamaño para datos de un bloque */
539 = efs->tam_bloque - sizeof(EMUFS_TIPO1_REG_HEADER);
540 EMUFS_REG_ID total_ids; /* cantidad total de registros en el array */
541 /* array con los identificadores de los registros */
542 EMUFS_REG_ID* reg_ids = emufs_idx_get(efs, &total_ids);
543 int i; /* índice de elemento actual del array */
545 /* recorro cada registro válido del archivo */
546 for (i = 0; i < total_ids; ++i) {
547 EMUFS_TIPO1_REG_HEADER header; /* cabecera del registro a leer */
548 char* reg; /* buffer para el registro a mover */
549 int err = 0; /* para almacenar código de error */
550 /* bloque al que pertenece el registro */
551 EMUFS_BLOCK_ID block_id = emufs_idx_buscar_registro(efs, reg_ids[i]);
553 /* obtengo identificador del registro actual */
554 header.id = reg_ids[i];
555 /* si el registro está borrado, continúo con el próximo */
556 if (block_id == EMUFS_NOT_FOUND) {
559 /* leo el registro */
560 reg = (char*) efs->leer_registro(efs, header.id, &header.size, &err);
562 PERR("error al leer registro");
565 /* borro el registro */
566 if ((err = efs->borrar_registro(efs, header.id))) {
567 PERR("error al borrar registro");
571 /* lo inserto en la nueva posición */
572 emufs_tipo1_grabar_registro(efs, reg, header.size, &err);
574 PERR("error al grabar registro");
580 free(reg_ids); /* libero lista de ids */
582 /* truncamos el archivo si hay bloques libres al final */
584 EMUFS_FREE fs; /* espacio libre en el bloque */
585 /* busco si hay algún bloque completo libre */
586 EMUFS_BLOCK_ID block_id = emufs_fsc_buscar_lugar(efs, block_space, &fs);
587 /* si hay, el resto del archivo tiene que estar vacío */
588 if (block_id != EMUFS_NOT_FOUND) {
589 long size = emufs_tipo1_header_size() /* cabecera del archivo */
590 + block_id * efs->tam_bloque; /* mas los bloques compactos */
593 /* trunca archivo de datos */
594 strcpy(filename, efs->nombre);
595 strcat(filename, ".dat");
596 truncate(filename, size);
597 /* trunca archivo de de espacio libre */
598 emufs_fsc_truncate(efs, block_id);
603 EMUFS_BLOCK_ID emufs_tipo1_grabar_bloque_fsc(EMUFS *efs, void *block,
604 EMUFS_BLOCK_ID block_id, EMUFS_FREE fs, int* err)
608 /* obtengo cantidad de bloques */
609 EMUFS_BLOCK_SIZE num_blocks =
610 (emufs_tipo1_get_file_size(efs, err) - emufs_tipo1_header_size())
614 strcpy(name_f,efs->nombre);
615 strcat(name_f,".dat");
616 if ((file = fopen(name_f, "r+b")) == NULL) {
617 /* TODO Manejo de errores */
618 PERR("Error al abrir archivo");
619 *err = 4; /* EMUFS_ERROR_CANT_OPEN_FILE */
620 return EMUFS_NOT_FOUND;
622 /* Si es NOT_FOUND o mayor a la cantidad de bloques presentes,
623 * tengo que agregar un bloque al final del archivo */
624 if ((block_id == EMUFS_NOT_FOUND) || (block_id >= num_blocks)) {
625 /* me paro al final del archivo */
626 if (fseek(file, 0l, SEEK_END)) {
627 /* TODO Manejo de errores */
628 PERR("No se pudo hacer fseek()");
630 *err = 8; /* EMUFS_ERROR_SEEK_FILE */
631 return EMUFS_NOT_FOUND;
633 /* Obtengo ID del bloque nuevo */
634 block_id = (ftell(file) - emufs_tipo1_header_size()) / efs->tam_bloque;
635 /* si me lo solicitan, actualizo el .fsc */
636 if (fs != EMUFS_NOT_FOUND) {
637 *err = emufs_fsc_agregar(efs, block_id, fs);
639 PERR("No se pudo agregar al .fsc");
641 return EMUFS_NOT_FOUND;
644 /* Si es un ID válido, salto hasta ese bloque. */
646 /* Salta el header del archivo */
647 if ((*err = emufs_tipo1_header_jump(file))) {
648 PERR("no se pudo saltar la cabecera del archivo");
650 return EMUFS_NOT_FOUND;
653 if ((*err = emufs_tipo1_block_jump(efs, file, block_id))) {
654 PERR("no se pudo saltar la cabecera del bloque");
656 return EMUFS_NOT_FOUND;
658 /* si me lo solicitan, actualizo el .fsc */
659 if (fs != EMUFS_NOT_FOUND) {
660 if ((err = emufs_fsc_actualizar(efs, block_id, fs))) {
661 /* TODO Manejo de errores */
662 PERR("no se pudo actualizar .fsc");
664 return EMUFS_NOT_FOUND;
668 /* Grabo el bloque */
669 if (fwrite(block, efs->tam_bloque, 1, file) != 1) {
670 PERR("No se pudo escribir el archivo");
672 *err = 6; /* EMUFS_ERROR_WRITE_FILE */
673 return EMUFS_NOT_FOUND;
680 EMUFS_REG_ID emufs_tipo1_modificar_registro(EMUFS *emu, EMUFS_REG_ID id,
681 void *data, EMUFS_REG_SIZE size, int *error)
683 emufs_tipo1_borrar_registro(emu, id);
684 return emufs_tipo1_grabar_registro(emu, data, size, error);
687 size_t emufs_tipo1_header_size(void)
689 return sizeof(EMUFS_Tipo) + sizeof(EMUFS_BLOCK_SIZE);
692 int emufs_tipo1_header_jump(FILE* fp)
694 if (fseek(fp, emufs_tipo1_header_size(), SEEK_CUR)) {
695 PERR("No se pudo hacer fseek()");
696 return 8; /* EMUFS_ERROR_SEEK_FILE */
698 return 0; /* EMUFS_OK */
701 int emufs_tipo1_block_jump(EMUFS* efs, FILE* fp, EMUFS_BLOCK_ID block_count)
703 if (fseek(fp, block_count * efs->tam_bloque, SEEK_CUR)) {
704 PERR("No se pudo hacer fseek()");
705 return 8; /* EMUFS_ERROR_SEEK_FILE */
707 return 0; /* EMUFS_OK */
710 void emufs_tipo1_escribir_reg_en_memoria(char* dst, EMUFS_TIPO1_REG_HEADER header,
713 emufs_tipo1_escribir_reg_chunk_en_memoria(dst, header, reg, header.size);
716 void emufs_tipo1_escribir_reg_chunk_en_memoria(char* dst,
717 EMUFS_TIPO1_REG_HEADER header, char* reg, EMUFS_REG_SIZE reg_size)
719 /* grabo cabecera del registro en el bloque */
720 memcpy(dst, &header, sizeof(EMUFS_TIPO1_REG_HEADER));
721 /* incremento puntero de escritura */
722 dst += sizeof(EMUFS_TIPO1_REG_HEADER);
723 /* grabo el registro en el bloque */
724 memcpy(dst, reg, reg_size);
727 long emufs_tipo1_get_file_size(EMUFS* efs, int* err)
733 strcpy(name_f, efs->nombre);
734 strcat(name_f, ".dat");
735 if ((file = fopen(name_f, "ab")) == NULL) {
736 /* TODO Manejo de errores */
737 PERR("Error al abrir archivo");
738 *err = 4; /* EMUFS_ERROR_CANT_OPEN_FILE */
741 file_size = ftell(file);