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