]> git.llucax.com Git - z.facultad/75.06/emufs.git/blob - emufs/fsc.c
* BUGFIX : estaba mal el modo de apertura del archivo.
[z.facultad/75.06/emufs.git] / emufs / fsc.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:  vie abr  9 16:17:50 ART 2004
22  * Autores: Nicolás Dimov <sagardua@uolsinectis.com.ar>
23  *          Leandro Lucarella <llucare@fi.uba.ar>
24  *----------------------------------------------------------------------------
25  *
26  * $Id$
27  *
28  */
29
30 /** \file
31  *
32  * Archivo para administrar el espacio libre disponible.
33  * 
34  * Implementación del archivo para administrar el espacio libre disponible.
35  *
36  */
37
38 #include "fsc.h"
39 #include <string.h>
40 #include <unistd.h>
41
42 /* Crea un archivo de Gaps o Espacio Libre en Bloque */
43 int emufs_fsc_crear(EMUFS* efs)
44 {
45         return emufs_crear_archivo_auxiliar(efs->nombre, EMUFS_FSC_EXT);
46 }
47
48 /* Agrega un registro al archivo de espacio libre en bloque. */
49 int emufs_fsc_agregar(EMUFS *emu, EMUFS_BLOCK_ID marker, EMUFS_FREE freespace)
50 {
51         FILE *f_fsc;
52         EMUFS_FSC reg;
53         char name_f_fsc[255];
54         
55         strcpy(name_f_fsc,emu->nombre);
56         strcat(name_f_fsc, EMUFS_FSC_EXT);
57         
58         /* Lo guardo en el archivo al final "a+"*/
59         if ( (f_fsc = fopen(name_f_fsc,"r+"))==NULL ) return -1;
60         /* lo busco.. si esta lo modifico y si no lo agrego */
61         fseek(f_fsc,0,SEEK_SET);
62         while ( !feof(f_fsc) ){
63                 if ( fread(&reg,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
64                 if ( reg.marker == marker ){
65                         fseek(f_fsc,-sizeof(EMUFS_FSC),SEEK_CUR);
66                         reg.freespace = freespace;
67                         fwrite(&reg,sizeof(EMUFS_FSC),1,f_fsc);
68                         fclose(f_fsc);
69                         return 0;
70                 }
71         }
72         /* Cargo el registro */
73         reg.marker = marker;
74         reg.freespace = freespace;
75         fwrite(&reg,sizeof(EMUFS_FSC),1,f_fsc);
76         fclose(f_fsc);
77         return 0;
78 }
79
80 /* Agrega un GAP en el archivo de Gaps para Filetype 2 */
81 int emufs_fsc_agregar_gap(EMUFS *emu, EMUFS_OFFSET marker, EMUFS_FREE freespace)
82 {
83         FILE *f_fsc;
84         EMUFS_FSC gap_aux,gap_before,gap_after,gap_new;
85         char name_f_fsc[255];
86         EMUFS_REG_ID pos_gap_before = 0, pos_gap_after = 0;
87         unsigned long source,destination,limit,file_size,reg_count = 0,cant_moved = 0;
88         char found = 0;
89                 
90         strcpy(name_f_fsc,emu->nombre);
91         strcat(name_f_fsc, EMUFS_FSC_EXT);
92         
93         gap_before.marker = -1;
94         gap_after.marker = -1;
95         
96         /* Busco si hay un GAP por delante y/o por detras del que se esta por crear */
97         /* para en dicho caso realizar un merge! */
98         if ( (f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1; 
99         while ( !feof(f_fsc) ){
100                 if ( fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
101                 
102                 /* Chequeo si es un gap justo anterior al nuestro */
103                 if (gap_aux.marker+gap_aux.freespace == marker) {
104                         gap_before.marker = gap_aux.marker;
105                         gap_before.freespace = gap_aux.freespace;
106                         pos_gap_before = reg_count;
107                 }
108                 
109                 /* Chequeo si es un gap justo posterior al nuestro */           
110                 if (gap_aux.marker == marker+freespace) {
111                         gap_after.marker = gap_aux.marker;
112                         gap_after.freespace = gap_aux.freespace;
113                         pos_gap_after = reg_count;
114                 }               
115                 reg_count += 1;
116         }
117         
118 /* Si no encontre gaps ni por delante ni por detras */
119         if ((gap_before.marker == -1) && (gap_after.marker == -1)) {
120                 /* Lo guardo ordenado donde deba ir */
121                 gap_new.marker = marker;
122                 gap_new.freespace = freespace;
123                 /* Busco el gap que sucede a este */
124                 fseek(f_fsc,0,SEEK_SET);
125                 while (!feof(f_fsc)) {
126                         fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
127                         if (gap_aux.marker > gap_new.marker) {
128                                 found = 1;
129                                 break;
130                         }
131                 }
132                 if (found == 1) {
133                         /* Movemos todos los gaps desde el sucesor hasta el final, una pos adelante */
134                         limit = ftell(f_fsc) - sizeof(EMUFS_FSC);
135                         fseek(f_fsc,0,SEEK_END);
136                         reg_count = (ftell(f_fsc) - limit) / sizeof(EMUFS_FSC);                 
137                         source = ftell(f_fsc) - sizeof(EMUFS_FSC);
138
139                         while (cant_moved < reg_count)
140                         {
141                                 fseek(f_fsc,source,SEEK_SET);
142                                 fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
143                                 fwrite(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
144                                 source -= sizeof(EMUFS_FSC);
145                                 ++cant_moved;
146                         }
147                         /* Agrego el nuevo registro */
148                         fseek(f_fsc,limit,SEEK_SET);
149                         fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
150                 }
151                 else {
152                         fseek(f_fsc,0,SEEK_END);
153                         fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
154                 }
155                 
156                 fclose(f_fsc);          
157         }
158         
159         /* Si encuentro un GAP Justo por delante pero no por detras */
160         if ((gap_before.marker != -1) && (gap_after.marker == -1))
161         {
162           /* Me posiciono en el registro que indica dicho gap y lo reescribo con */
163           /* la suma de los espacios libres */    
164           fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_before,0);
165       gap_new.marker = gap_before.marker;
166           gap_new.freespace = gap_before.freespace + freespace;
167           fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
168           fclose(f_fsc);
169         }
170         
171         /* Si encuentro un GAP Justo por detras pero no por delante */
172         if ((gap_before.marker == -1) && (gap_after.marker != -1))
173         {  
174           /* Me posiciono en el registro que indica dicho gap y lo reescribo con */
175           /* los datos actualizados de offset y espacio */
176           fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_after,0);
177       gap_new.marker = gap_after.marker - freespace;
178           gap_new.freespace = gap_after.freespace + freespace;
179           fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
180           fclose(f_fsc);
181         }
182         
183         /* Finalmente, si encuentro Justo por delante y por detras..*/
184         if ((gap_before.marker != -1) && (gap_after.marker != -1))
185         { 
186           /* Guardo el nuevo GAP que posee los tres espacios sumados */
187           if (pos_gap_before < pos_gap_after) {
188                 fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_before,0);
189                 destination = sizeof(EMUFS_FSC)*pos_gap_after;
190           }
191           else {
192                 fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_after,0);
193                 destination = sizeof(EMUFS_FSC)*pos_gap_before;
194           }
195       gap_new.marker = gap_before.marker;
196           gap_new.freespace = gap_before.freespace + freespace + gap_after.freespace;
197           fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
198                 
199           /* Preparo el escenario para la movida de registros */
200           source = destination+sizeof(EMUFS_FSC); /* Salteo el gap que elimino! */
201           fseek(f_fsc,0,SEEK_END);
202           file_size = ftell(f_fsc);
203           reg_count = (file_size - source) / sizeof(EMUFS_FSC);
204           
205           /* Comienzo a mover */
206           while (cant_moved < reg_count) {
207         fseek(f_fsc,source,0);
208         fread(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
209                 fseek(f_fsc,-sizeof(EMUFS_FSC)*2,SEEK_CUR);
210                 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
211                 source += sizeof(EMUFS_FSC);            
212                 ++cant_moved;
213           }
214           fclose(f_fsc);
215           truncate(name_f_fsc, file_size - sizeof(EMUFS_FSC));
216         }       
217         
218     return 0;
219 }
220
221 /* Elimina un registro GAP del archivo de espacios libres (gaps) */
222 int emufs_fsc_remove_gap(EMUFS *emu, EMUFS_OFFSET marker)
223 {
224         FILE *f_fsc;
225         EMUFS_FSC gap_aux;
226         char name_f_fsc[255];
227     unsigned long source,destination,file_size,reg_count = 0,cant_moved = 0;    
228                 
229         strcpy(name_f_fsc,emu->nombre);
230         strcat(name_f_fsc, EMUFS_FSC_EXT);
231         
232         /* Busco el Gap en el .fsc */
233     if ((f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1; 
234         while ( !feof(f_fsc) ){
235                 if ( fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
236                 if ( gap_aux.marker == marker ) break;
237         }
238         
239         /* Preparo el escenario para la movida de registros */
240         fseek(f_fsc,-sizeof(EMUFS_FSC),SEEK_CUR);
241         destination = ftell(f_fsc);
242         source = destination+sizeof(EMUFS_FSC); /* Salteo el gap a eliminar! */
243         fseek(f_fsc,0,SEEK_END);
244         file_size = ftell(f_fsc);
245         reg_count = (file_size - source) / sizeof(EMUFS_FSC);
246                 
247         /* Comienzo a mover */
248         while (cant_moved < reg_count) {
249           fseek(f_fsc,source,0);
250       fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
251           fseek(f_fsc,-sizeof(EMUFS_FSC)*2,SEEK_CUR);
252           fwrite(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
253           source += sizeof(EMUFS_FSC);          
254           ++cant_moved;
255         }
256         fclose(f_fsc);
257         truncate(name_f_fsc, file_size - sizeof(EMUFS_FSC));
258         
259         return 0;
260 }
261
262 /* Objetivo: Actualiza un registro de espacio libre de acorde al FType */
263 int emufs_fsc_actualizar(EMUFS *emu, EMUFS_BLOCK_ID marker, EMUFS_FREE freespace)
264 {
265         FILE *f_fsc;
266         EMUFS_FSC reg;
267         char name_f_fsc[255];
268         
269         strcpy(name_f_fsc,emu->nombre);
270         strcat(name_f_fsc, EMUFS_FSC_EXT);
271
272         /*busco el bloque o gap que modifique*/
273         if ( (f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1; 
274         while ( !feof(f_fsc) ){
275                 if ( fread(&reg,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
276                 if ( reg.marker == marker ){
277                         reg.freespace = freespace;
278                         fseek(f_fsc,-sizeof(EMUFS_FSC),SEEK_CUR);
279                         fwrite(&reg,sizeof(EMUFS_FSC),1,f_fsc);
280                         break;
281                 }
282         }
283         fclose(f_fsc);
284         return 0;
285 }
286
287 /* Actualiza un registro de gap, en el archivo de Gaps en Disco */
288 int emufs_fsc_actualizar_gap(EMUFS *emu, EMUFS_OFFSET marker, EMUFS_FREE freespace)
289 {
290         FILE *f_fsc;
291         EMUFS_FSC gap_aux;
292         char name_f_fsc[255];
293         
294         strcpy(name_f_fsc,emu->nombre);
295         strcat(name_f_fsc, EMUFS_FSC_EXT);
296
297         /*busco el bloque o gap que modifique*/
298         if ( (f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1; 
299         while ( !feof(f_fsc) ){
300                 if ( fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
301                 if ( gap_aux.marker == marker ){
302                         gap_aux.marker = marker + gap_aux.freespace - freespace;
303                         gap_aux.freespace = freespace;
304                         fseek(f_fsc,-sizeof(EMUFS_FSC),SEEK_CUR);
305                         fwrite(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
306                         break;
307                 }
308         }
309         fclose(f_fsc);
310         return 0;
311 }
312
313 /* Me devuelve el ID del bloque u Offset del Gap donde quepa un registro, y guarda en n_freespace el espacio libre actualizado */
314 EMUFS_BLOCK_ID emufs_fsc_buscar_lugar(EMUFS *emu, EMUFS_FREE reg_size, EMUFS_FREE *freespace)
315 {
316         FILE *f_fsc;
317         EMUFS_FSC reg;
318         char name_f_fsc[255];
319         char found = 0;
320         
321         strcpy(name_f_fsc,emu->nombre);
322         strcat(name_f_fsc, EMUFS_FSC_EXT);
323
324         if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return EMUFS_NOT_FOUND;
325
326         if ( emu->tam_reg > emu->tam_bloque-sizeof(EMUFS_REG_ID) ){
327                 fseek(f_fsc,0,SEEK_SET);
328                 while(!feof(f_fsc)){
329                         if (fread(&reg,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
330                         if (reg.freespace == emu->tam_bloque) {
331                                 fclose(f_fsc);
332                                 *freespace = reg.freespace;
333                                 return reg.marker;
334                         }
335                 }
336         }       
337         /* Inicializamos la estructura para devolver algun valor en concreto */
338         /* en caso de que no se halle un espacio libre apropiado */
339         while(!feof(f_fsc)){
340                 if (fread(&reg,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
341                 if (reg.freespace >= reg_size) {
342                         found = 1;
343                         break;
344                 }
345         }
346         
347         /* Si salio por error o por fin de archivo y no encontro space... */
348         if (!found) {
349           reg.marker = EMUFS_NOT_FOUND;
350           *freespace = emu->tam_bloque; 
351         }
352         else *freespace = reg.freespace;
353         
354         fclose(f_fsc);
355         return reg.marker;
356 }
357
358 /** Busca n lugares consecutivos devolviendo el id del primer bloque. */
359 EMUFS_BLOCK_ID emufs_fsc_buscar_n_lugares(EMUFS* efs, size_t n,
360                 EMUFS_FREE reg_size, EMUFS_FREE *freespace, int* err)
361 {
362         FILE *f_fsc;
363         EMUFS_FSC reg;
364         char name_f_fsc[255];
365
366         /* chequeo que al menos se busque un lugar */
367         if (!n) {
368                 PERR("Se debe buscar al menos un lugar");
369                 *err = 13; /* EMUFS_ERROR_WRONG_ARGUMENT */
370                 return EMUFS_NOT_FOUND;
371         }
372
373         /* abre archivo */
374         strcpy(name_f_fsc, efs->nombre);
375         strcat(name_f_fsc, EMUFS_FSC_EXT);
376         if (!(f_fsc = fopen(name_f_fsc, "rb"))) {
377                 PERR("No se puede abrir archivo");
378                 *err = 4; /* EMUFS_ERROR_CANT_OPEN_FILE */
379                 return EMUFS_NOT_FOUND;
380         }
381
382         /* busca el espacio libre */
383         while(!feof(f_fsc)) {
384                 if ((fread(&reg, sizeof(EMUFS_FSC), 1, f_fsc) != 1)) {
385                         if (feof(f_fsc)) break;
386                         PERR("No se puede leer el archivo");
387                         *err = 3; /* EMUFS_ERROR_FILE_READ */
388                         return EMUFS_NOT_FOUND;
389                 }
390                 if (reg.freespace >= reg_size) {
391                         int found = 1;
392                         EMUFS_BLOCK_ID first_id = reg.marker;
393                         *freespace = reg.freespace;
394                         while (--n) {
395                                 if (fread(&reg, sizeof(EMUFS_FSC), 1, f_fsc) != 1) {
396                                         if (feof(f_fsc)) break;
397                                         PERR("No se puede leer el archivo");
398                                         *err = 3; /* EMUFS_ERROR_FILE_READ */
399                                         return EMUFS_NOT_FOUND;
400                                 }
401                                 /* no hay otro lugar consecutivo */
402                                 if (reg.freespace < reg_size) {
403                                         found = 0;
404                                         break;
405                                 }
406                         }
407                         if (found) {
408                                 fclose(f_fsc);
409                                 return first_id;
410                         }
411                 }
412         }
413         /* no se encontró espacio libre */
414         *freespace = efs->tam_bloque;
415         return EMUFS_NOT_FOUND;
416 }
417
418 /* Devuelve el espacio libre de un Bloque o Gap dado */
419 EMUFS_FREE emufs_fsc_get_fs(EMUFS *emu, EMUFS_BLOCK_ID marker)
420 {
421         FILE *f_fsc;
422         EMUFS_FSC reg;
423         char name_f_fsc[255];
424         
425         strcpy(name_f_fsc,emu->nombre);
426         strcat(name_f_fsc, EMUFS_FSC_EXT);
427
428         /* Busco el Bloque o Gap pedido y obtengo su espacio libre */
429         if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
430         while ( !feof(f_fsc) ){
431                 if ( fread(&reg,sizeof(EMUFS_FSC),1,f_fsc) != 1 ) continue;
432                 if ( reg.marker == marker )
433                         break;
434         }
435                 
436         fclose(f_fsc);
437         return reg.freespace;
438 }
439
440 EMUFS_FREE emufs_fsc_get_total_fs(EMUFS *emu)
441 {
442         FILE *f_fsc;
443         EMUFS_FSC reg;
444         char name_f_fsc[255];
445         EMUFS_FREE total;
446         
447         strcpy(name_f_fsc,emu->nombre);
448         strcat(name_f_fsc, EMUFS_FSC_EXT);
449
450         if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
451         total = 0;
452         while ( !feof(f_fsc) ){
453                 if ( fread(&reg, sizeof(EMUFS_FSC), 1, f_fsc) != 1) continue;
454                 total += reg.freespace;
455         }
456         fclose(f_fsc);
457         return total;
458 }
459
460 int emufs_fsc_get_max_min_fs(EMUFS *emu, EMUFS_FREE *min, EMUFS_FREE *max)
461 {
462         FILE *f_fsc;
463         EMUFS_FSC reg;
464         char name_f_fsc[255];
465         
466         strcpy(name_f_fsc,emu->nombre);
467         strcat(name_f_fsc, EMUFS_FSC_EXT);
468
469         if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
470                 
471         /* Si el file esta vacio, devuelvo valores nulos */
472         fseek(f_fsc,0,SEEK_END);
473         if (ftell(f_fsc) == 0) {
474                 *min = 0;
475                 *max = 0;
476                 return 0;               
477         }
478         else
479         {
480                 /* Busco Min y Max */
481                 *min = ULONG_MAX;
482                 *max = 0;               
483                 fseek(f_fsc,0,SEEK_SET);                
484                 while ( !feof(f_fsc) ){
485                         if ( fread(&reg, sizeof(EMUFS_FSC), 1, f_fsc) != 1) continue;
486                         if (  reg.freespace < *min )
487                                 *min = reg.freespace;
488                         if ( reg.freespace > *max )
489                                 *max = reg.freespace;
490                 }
491                 fclose(f_fsc);
492                 return 0;               
493         }
494 }
495
496 EMUFS_FREE emufs_fsc_get_media_fs(EMUFS *emu)
497 {
498         FILE *f_fsc;
499         EMUFS_FSC reg;
500         char name_f_fsc[255];
501         EMUFS_FREE total_fs = 0;
502         EMUFS_REG_ID gap_count = 0;
503         
504         strcpy(name_f_fsc,emu->nombre);
505         strcat(name_f_fsc, EMUFS_FSC_EXT);
506
507         if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
508         
509         while ( !feof(f_fsc) ){
510                 if ( fread(&reg, sizeof(EMUFS_FSC), 1, f_fsc) != 1) continue;           
511                 total_fs += reg.freespace;
512                 ++gap_count;
513         }
514
515         fclose(f_fsc);
516         
517         if (gap_count > 0) return total_fs/gap_count;
518         else return 0;
519 }
520
521 int emufs_fsc_get_cant_bloques_vacios(EMUFS *emu)
522 {
523         FILE *f_fsc;
524         EMUFS_FSC reg;
525         char name_f_fsc[255];
526         int cant=0;
527         
528         strcpy(name_f_fsc,emu->nombre);
529         strcat(name_f_fsc, EMUFS_FSC_EXT);
530
531         if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
532         while ( !feof(f_fsc) ){
533                 fread(&reg, sizeof(EMUFS_FSC), 1, f_fsc);
534                 if ( reg.freespace == emu->tam_bloque )
535                         cant++;
536         }
537                 
538         fclose(f_fsc);
539         return cant;
540 }
541
542 int emufs_fsc_truncate(EMUFS* efs, EMUFS_BLOCK_ID blocks)
543 {
544         char name_f_fsc[255];
545
546         strcpy(name_f_fsc, efs->nombre);
547         strcat(name_f_fsc, EMUFS_FSC_EXT);
548         return truncate(name_f_fsc, blocks * sizeof(EMUFS_FSC));
549 }