1 /* vim: set noexpandtab tabstop=4 shiftwidth=4:
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: mié mar 31 17:26:46 ART 2004
22 * Autores: Nicolás Dimov <sagardua@uolsinectis.com.ar>
23 *----------------------------------------------------------------------------
31 * Archivo con bloques y registros de longitud parametrizada.
33 * Implementación del archivo con bloques y registros de longitud
40 /** Leo un registro del archivo, devuelve cero si no lo encuentra.**/
41 int emufs_tipo3_leer_registro(EMUFS *emu, int ID, void *ptr, unsigned long tam_reg)
45 char name_f_block_reg[255];
48 strcpy(name_f_block_reg,emu->nombre);
49 strcat(name_f_block_reg,".idx");
52 if ( (f_block_reg = fopen(name_f_block_reg,"a+")) == NULL )
56 /*si existe, lo busco en el archivo de bloques*/
57 block = emufs_idx_buscar_registro(emu,ID); /*me devuelve el nro de bloque al que pertenece el registro*/
58 bloque = (char*)malloc(emu->tam_bloque);
60 printf("No hay memoria.\n");
64 if (emufs_tipo3_leer_bloque(emu, block, bloque)==-1) {
66 printf("no se pudo leer el bloque\n");
67 return -1; /*No se pudo leer el bloque*/
72 while ( iterador < emu->tam_bloque ) {
73 memcpy(&ID_aux, bloque+iterador, sizeof(int));
74 iterador += sizeof(int);
76 memcpy(ptr,bloque+iterador,tam_reg);
87 /*leo el bloque "ID" del archivo que viene en "emu->nombre", y lo almaceno en "ptr"*/
88 int emufs_tipo3_leer_bloque(EMUFS *emu, int ID, void* ptr)
93 strcpy(name_f,emu->nombre);
94 strcat(name_f,".dat");
96 if ( (file = fopen(name_f,"r"))==NULL ) return -1; /*ERROR*/
97 fseek(file,sizeof(int)+sizeof(char)+sizeof(int),SEEK_SET);
98 /*FIXME: verificar que no se pase de fin de archivo*/
99 fseek(file,ID*emu->tam_bloque,SEEK_CUR);
100 if (fread(ptr,emu->tam_bloque,1,file)!=1) return -1;
106 int emufs_tipo3_grabar_registro(EMUFS *emu, void *ptr, unsigned long tam)
108 int ID_aux, fs, num_bloque, cant;
113 strcpy(name_f,emu->nombre);
114 strcat(name_f,".dat");
116 if ( (file = fopen(name_f,"a+"))==NULL ) return -1; /*ERROR*/
117 /* me devuelve el ID del bloque donde quepa un registro y el espacio libre en "fs"*/
118 num_bloque = emufs_tipo3_buscar_lugar(emu, tam, &fs);
119 printf("Lugar = %d bloque = %d\n", fs, num_bloque);
120 /*si no hay bloques con suficiente espacio creo un bloque nuevo */
121 if (num_bloque == -1) {
122 /*crear un nuevo bloque en memoria */
123 bloque = (char*)malloc(emu->tam_bloque);
124 /* grabar el registro al principio del bloque */
125 /*tengo que buscar un ID valido para el nuevo registro*/
126 ID_aux = emufs_tipo3_get_id(emu);
127 /*grabo el id en el bloque*/
128 memcpy(bloque,&ID_aux,sizeof(int));
129 /*grabo el registro en el bloque*/
130 memcpy(bloque+sizeof(int),ptr,tam);
131 /* me paro al final del archivo */
132 fseek(file, 0, SEEK_END);
133 /* grabo el bloque en el final del archivo */
134 fwrite(bloque,emu->tam_bloque,1,file);
135 /*actualizo el archivo de espacios libres*/
136 /*tengo que buscar la cantidad de bloques que existen*/
137 /*me paro al principio salteando el encabezado del archivo*/
138 fseek(file, 0, SEEK_END); /* Me paro al final */
139 cant = (ftell(file)-(sizeof(int)*2+sizeof(char))) / emu->tam_bloque;
140 cant--; /* Resto uno porque el numero de bloque debe empezar en 0 */
143 /* grabo el nuevo registro en el archivo de espacios libres */
144 if ( emufs_fsc_agregar(emu, num_bloque, emu->tam_bloque - tam-sizeof(int)) != 0 ) {
149 /*cargo el bloque en "bloque"*/
150 bloque = (char*)malloc(emu->tam_bloque);
151 if ( emufs_tipo3_leer_bloque(emu,num_bloque,bloque)== -1) {
152 printf("Error: no se pudo leer bloque\n");
155 /*El error puede haberse producido porque la funcion leer_bloque devolvio -1, el cual es un bloque invalido*/
156 /*insertar el registro en el bloque*/
157 /*tengo que buscar un ID valido para el nuevo registro*/
158 ID_aux = emufs_tipo3_get_id(emu);
159 /*grabo el id en el bloque*/
160 memcpy(bloque+emu->tam_bloque-fs,&ID_aux,sizeof(int));
161 /*grabo el registro en el bloque*/
162 memcpy(bloque+emu->tam_bloque-fs+sizeof(int),ptr,tam);
163 /*guardo el bloque en el archivo*/
164 if ( emufs_tipo3_grabar_bloque(emu, bloque, num_bloque) != 0) {
165 printf("error al grabar bloque\n");
166 return -1; /* se produjo un error */
168 /*actualizo el archivo de espacios libres*/
169 if ( emufs_fsc_actualizar(emu, num_bloque, tam+sizeof(int)) != 0 ){
175 /*actualizo el archivo de bloques y registros*/
176 if ( emufs_idx_agregar(emu, num_bloque, ID_aux) != 0 ){
185 /*Busco en el archivo de Id`s un Id valido para un nuevo registro*/
186 int emufs_tipo3_get_id(EMUFS *emu)
190 if ( (id = emufs_did_get_last(emu)) == -1 )
191 id = emufs_idx_buscar_mayor_id(emu);
195 /*Graba un bloque en el archivo*/
196 int emufs_tipo3_grabar_bloque(EMUFS *emu, void *ptr, int num)
201 strcpy(name_f,emu->nombre);
202 strcat(name_f,".dat");
204 if ( (file = fopen(name_f,"r+"))==NULL ) return -1; /*ERROR*/
205 fseek(file,sizeof(char)+sizeof(int)*2,SEEK_SET);
206 fseek(file,num*emu->tam_bloque,SEEK_CUR);
207 fwrite(ptr, emu->tam_bloque, 1, file);
215 /* me devuelve el ID del bloque donde quepa un registro, y guarda en fs el espacio libre que queda en el bloque */
216 int emufs_tipo3_buscar_lugar(EMUFS *emu, unsigned long tam, int *fs)
220 char name_f_block_free[255];
222 strcpy(name_f_block_free,emu->nombre);
223 strcat(name_f_block_free,".fsc");
225 if ( (f_block_free = fopen(name_f_block_free,"r"))==NULL ) return -1;
227 /* Inicializo la estructura para evitar que si el archivo esta vacio
228 * el resultado sea correcto
231 *fs = emu->tam_bloque;
232 while( !feof(f_block_free) ){
233 if (fread(®,sizeof(BLOCK_FREE_T),1,f_block_free) != 1) continue;
234 if ( reg.free_space >= tam )
238 *fs = emu->tam_bloque;
242 fclose(f_block_free);
244 *fs = reg.free_space;
248 /*borra un registro de un bloque y acomoda los registros que quedan*/
249 int emufs_tipo3_borrar_registro(EMUFS *emu, int ID, int tam_reg)
251 int num_bloque, ptr_elim, ptr_mov, ID_aux, cant, i;
256 BLOCK_REG_T buffer[10];
257 char name_f_block_reg[255];
259 strcpy(name_f_block_reg,emu->nombre);
260 strcat(name_f_block_reg,".idx");
262 num_bloque = emufs_idx_buscar_registro(emu, ID);
263 bloque = (char*)malloc(emu->tam_bloque);
264 if ( emufs_tipo3_leer_bloque(emu,num_bloque, bloque) == -1 ){
265 printf("No se encontro el bloque\n");
269 /*apunto al registro que voy a eliminar*/
271 while ( ptr_elim < emu->tam_bloque ){
272 memcpy(&ID_aux, bloque+ptr_elim, sizeof(int));
275 ptr_elim += tam_reg + sizeof(int);
278 /*apunto al registro que voy a mover*/
279 ptr_mov = ptr_elim + tam_reg + sizeof(int);
281 while ( ptr_mov < emu->tam_bloque ){
282 memcpy(bloque+ptr_elim, bloque+ptr_mov, sizeof(int)+tam_reg);
284 ptr_mov += sizeof(int) + tam_reg;
287 /*grabo el bloque en el archivo*/
288 if ( emufs_tipo3_grabar_bloque(emu, bloque, num_bloque) == -1 ){
289 printf("No se pudo grabar el bloque\n");
293 /*actualizo archivo .fsc*/
294 if ( emufs_fsc_actualizar(emu, num_bloque, -(tam_reg + sizeof(int)) ) != 0 ) return -1;
296 /*actualizo archivo .did*/
297 if ( emufs_did_agregar(emu, ID) != 0 ) return -1;
299 /*actualizo archivo .idx*/
300 /*busco el registro que tengo que eliminar*/
301 if ( (f_block_reg = fopen(name_f_block_reg,"r+")) == NULL ) return -1;
302 while ( !feof(f_block_reg) ){
303 if ( fread(®_b,sizeof(BLOCK_REG_T),1,f_block_reg) != 1 ) continue;
304 if ( reg_b.id_reg == ID )
307 fseek(f_block_reg, -sizeof(BLOCK_REG_T), SEEK_CUR);
308 /* Estoy parado sobre el punto id/registro que debo borrar */
309 printf("registro borrado= %ld en bloque = %d\n",reg_b.id_reg,reg_b.block);
310 /*justifico en archivo a la izquieda*/
312 /* GAZER : aca hago una prueba */
315 actual = ftell(f_block_reg); /* Guardo la posicion actual */
316 fseek(f_block_reg, 0, SEEK_END); /* me voy al final */
317 final = ftell(f_block_reg); /* veo cuando ocupa el archivo */
318 fseek(f_block_reg, actual, SEEK_SET); /* vuelvo al lugar desde donde quiero justificar */
320 cant = (final-actual)/sizeof(BLOCK_REG_T);
321 for(i=0; i<cant; i++) {
322 /* Calculo donde empieza el proximo elemento a mover */
323 final = actual+sizeof(BLOCK_REG_T);
324 /* Me paro en ese lugar */
325 fseek(f_block_reg, final, SEEK_SET);
327 fread(buffer, sizeof(BLOCK_REG_T), 1, f_block_reg);
329 /* Ahora me paro en la nueva posicion de este item */
330 fseek(f_block_reg, actual, SEEK_SET);
332 fwrite(buffer, sizeof(BLOCK_REG_T), 1, f_block_reg);
334 /* Ahora el proximo item va en la posicion siguiente */
335 actual += sizeof(BLOCK_REG_T);
339 /*trunco el ultimo registro del archiv*/
340 fseek(f_block_reg,0,SEEK_END);
341 size = ftell(f_block_reg);
343 truncate(name_f_block_reg,size - sizeof(BLOCK_REG_T));