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