]> git.llucax.com Git - z.facultad/75.06/emufs.git/blob - emufs/tipo3.c
* Agrego libemufs.a en el Makefile
[z.facultad/75.06/emufs.git] / emufs / tipo3.c
1 /* vim: set noexpandtab tabstop=4 shiftwidth=4:
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:  mié mar 31 17:26:46 ART 2004
22  * Autores: Nicolás Dimov <sagardua@uolsinectis.com.ar>
23  *----------------------------------------------------------------------------
24  *
25  * $Id$
26  *
27  */
28
29 /** \file
30  *
31  * Archivo con bloques y registros de longitud parametrizada.
32  * 
33  * Implementación del archivo con bloques y registros de longitud
34  * parametrizada.
35  *
36  */
37
38 #include "tipo3.h"
39
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)
42 {
43         FILE* f_block_reg;
44         char* bloque;
45         char name_f_block_reg[255];
46         int block, ID_aux;
47         int iterador = 0;
48         strcpy(name_f_block_reg,emu->nombre);
49         strcat(name_f_block_reg,".idx");
50
51
52         if ( (f_block_reg = fopen(name_f_block_reg,"a+")) == NULL )
53                 return -1; /*ERROR*/
54         
55
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);
59         if (bloque == NULL) {
60                 printf("No hay memoria.\n");
61                 return -1;
62         }
63         
64         if (emufs_tipo3_leer_bloque(emu, block, bloque)==-1) {
65                 free(bloque);
66                 printf("no se pudo leer el bloque\n");
67                 return -1; /*No se pudo leer el bloque*/
68         }
69
70         ID_aux = -1;
71         iterador = 0;
72         while ( iterador < emu->tam_bloque ) {
73                 memcpy(&ID_aux, bloque+iterador, sizeof(int));
74                 iterador += sizeof(int);
75                 if ( ID_aux == ID ){
76                         memcpy(ptr,bloque+iterador,tam_reg);
77                         break;
78                 }
79                 iterador += tam_reg;
80         }
81         
82         fclose(f_block_reg);
83         free(bloque);
84         return 0;
85 }
86
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)
89 {
90         FILE* file;
91         char name_f[255];
92         
93         strcpy(name_f,emu->nombre);
94         strcat(name_f,".dat");
95         
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;
101
102         fclose(file);
103         return 0;
104 }
105
106 int emufs_tipo3_grabar_registro(EMUFS *emu, void *ptr, unsigned long tam)
107 {
108         int ID_aux, fs, num_bloque, cant;
109         FILE *file;
110         char name_f[255];
111         char* bloque;
112         
113         strcpy(name_f,emu->nombre);
114         strcat(name_f,".dat");
115         
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 */
141                 fclose(file);
142                 num_bloque = cant;
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 ) {
145                         free(bloque);
146                         return -1;
147                 }
148         } else {
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");
153                         return -1; 
154                 }
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 */    
167                 }
168                 /*actualizo el archivo de espacios libres*/
169                 if ( emufs_fsc_actualizar(emu, num_bloque, tam+sizeof(int)) != 0 ){
170                         free(bloque);
171                         return -1;
172                 }
173         }
174                 
175         /*actualizo el archivo de bloques y registros*/
176         if ( emufs_idx_agregar(emu, num_bloque, ID_aux) != 0 ){
177                 free(bloque);
178                 return -1;
179         }
180         
181         free(bloque);
182         return ID_aux;
183 }
184
185 /*Busco en el archivo de Id`s un Id valido para un nuevo registro*/
186 int emufs_tipo3_get_id(EMUFS *emu)
187 {
188         int id;
189
190         if ( (id = emufs_did_get_last(emu)) == -1 )
191                 id = emufs_idx_buscar_mayor_id(emu);
192         return id;      
193 }
194
195 /*Graba un bloque en el archivo*/
196 int emufs_tipo3_grabar_bloque(EMUFS *emu, void *ptr, int num)
197 {
198         FILE* file;
199         char name_f[255];
200         
201         strcpy(name_f,emu->nombre);
202         strcat(name_f,".dat");
203         
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);
208         
209         fclose(file);
210         return 0;
211 }
212
213
214
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)
217 {
218         FILE *f_block_free;
219         BLOCK_FREE_T reg;
220         char name_f_block_free[255];
221         
222         strcpy(name_f_block_free,emu->nombre);
223         strcat(name_f_block_free,".fsc");
224
225         if ( (f_block_free = fopen(name_f_block_free,"r"))==NULL ) return -1;
226
227         /* Inicializo la estructura para evitar que si el archivo esta vacio
228          * el resultado sea correcto
229          */
230         reg.block = -1;
231         *fs = emu->tam_bloque;
232         while( !feof(f_block_free) ){
233                 if (fread(&reg,sizeof(BLOCK_FREE_T),1,f_block_free) != 1) continue;
234                 if ( reg.free_space >= tam ) 
235                         break;
236                 else {
237                         reg.block = -1;
238                         *fs = emu->tam_bloque;
239                 }
240         }
241         
242         fclose(f_block_free);
243         if (reg.block != -1)
244                 *fs = reg.free_space;
245         return reg.block;
246 }
247
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)
250 {
251         int num_bloque, ptr_elim, ptr_mov, ID_aux, cant, i;
252         long size;
253         char *bloque;
254         FILE *f_block_reg;
255         BLOCK_REG_T reg_b;
256         BLOCK_REG_T buffer[10];
257         char name_f_block_reg[255];
258         
259         strcpy(name_f_block_reg,emu->nombre);
260         strcat(name_f_block_reg,".idx");
261
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");
266                 return -1;
267         }
268
269         /*apunto al registro que voy a eliminar*/
270         ptr_elim = 0;
271         while ( ptr_elim < emu->tam_bloque ){
272                 memcpy(&ID_aux, bloque+ptr_elim, sizeof(int));
273                 if ( ID_aux == ID )
274                         break;
275                 ptr_elim += tam_reg + sizeof(int);
276         }
277         
278         /*apunto al registro que voy a mover*/
279         ptr_mov = ptr_elim + tam_reg + sizeof(int);
280         
281         while ( ptr_mov < emu->tam_bloque ){
282                 memcpy(bloque+ptr_elim, bloque+ptr_mov, sizeof(int)+tam_reg);
283                 ptr_elim = ptr_mov;
284                 ptr_mov += sizeof(int) + tam_reg;
285         }
286         
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"); 
290                 return -1;
291         }
292         
293         /*actualizo archivo .fsc*/
294         if ( emufs_fsc_actualizar(emu, num_bloque, -(tam_reg + sizeof(int)) ) != 0 ) return -1;
295         
296         /*actualizo archivo .did*/
297         if ( emufs_did_agregar(emu, ID) != 0 ) return -1;
298                 
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(&reg_b,sizeof(BLOCK_REG_T),1,f_block_reg) != 1 ) continue;
304                 if ( reg_b.id_reg == ID )
305                         break;
306         }
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*/
311
312         /* GAZER : aca hago una prueba */
313         {
314                 long final, actual;
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 */
319
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);
326                         /* y lo leo */
327                         fread(buffer, sizeof(BLOCK_REG_T), 1, f_block_reg);
328
329                         /* Ahora me paro en la nueva posicion de este item */
330                         fseek(f_block_reg, actual, SEEK_SET);
331                         /* y lo guardo */
332                         fwrite(buffer, sizeof(BLOCK_REG_T), 1, f_block_reg);
333
334                         /* Ahora el proximo item va en la posicion siguiente */
335                         actual += sizeof(BLOCK_REG_T);
336                 }
337
338         }
339         /*trunco el ultimo registro del archiv*/
340         fseek(f_block_reg,0,SEEK_END);
341   size = ftell(f_block_reg);
342   fclose(f_block_reg);
343         truncate(name_f_block_reg,size - sizeof(BLOCK_REG_T));
344
345         free(bloque);
346
347 return 0;
348 }