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: 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 *----------------------------------------------------------------------------
32 * Archivo para administrar el espacio libre disponible.
34 * Implementación del archivo para administrar el espacio libre disponible.
44 /* Crea un archivo de Gaps o Espacio Libre en Bloque */
45 int emufs_fsc_crear(EMUFS* efs)
47 return emufs_crear_archivo_auxiliar(efs->nombre, EMUFS_FSC_EXT);
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)
57 strcpy(name_f_fsc,emu->nombre);
58 strcat(name_f_fsc, EMUFS_FSC_EXT);
60 /* Lo guardo en el archivo al final "a+"*/
62 if ( (f_fsc = fopen(name_f_fsc,"r+"))==NULL ) return -1;
63 /* lo busco.. si esta lo modifico y si no lo agrego */
64 fseek(f_fsc,0,SEEK_SET);
65 while ( !feof(f_fsc) ){
66 if ( fread(®,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
67 if ( reg.marker == marker ){
68 fseek(f_fsc,-sizeof(EMUFS_FSC),SEEK_CUR);
69 reg.freespace = freespace;
70 fwrite(®,sizeof(EMUFS_FSC),1,f_fsc);
75 /* Cargo el registro */
77 reg.freespace = freespace;
78 fwrite(®,sizeof(EMUFS_FSC),1,f_fsc);
83 /* Agrega un GAP en el archivo de Gaps para Filetype 2 */
84 int emufs_fsc_agregar_gap(EMUFS *emu, EMUFS_OFFSET marker, EMUFS_FREE freespace)
87 EMUFS_FSC gap_aux,gap_before,gap_after,gap_new;
89 EMUFS_REG_ID pos_gap_before = 0, pos_gap_after = 0;
90 unsigned long source,destination,limit,file_size,reg_count = 0,cant_moved = 0;
93 strcpy(name_f_fsc,emu->nombre);
94 strcat(name_f_fsc, EMUFS_FSC_EXT);
96 gap_before.marker = -1;
97 gap_after.marker = -1;
99 /* Busco si hay un GAP por delante y/o por detras del que se esta por crear */
100 /* para en dicho caso realizar un merge! */
101 if ( (f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1;
102 while ( !feof(f_fsc) ){
103 if ( fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
105 /* Chequeo si es un gap justo anterior al nuestro */
106 if (gap_aux.marker+gap_aux.freespace == marker) {
107 gap_before.marker = gap_aux.marker;
108 gap_before.freespace = gap_aux.freespace;
109 pos_gap_before = reg_count;
112 /* Chequeo si es un gap justo posterior al nuestro */
113 if (gap_aux.marker == marker+freespace) {
114 gap_after.marker = gap_aux.marker;
115 gap_after.freespace = gap_aux.freespace;
116 pos_gap_after = reg_count;
121 /* Si no encontre gaps ni por delante ni por detras */
122 if ((gap_before.marker == -1) && (gap_after.marker == -1)) {
123 /* Lo guardo ordenado donde deba ir */
124 gap_new.marker = marker;
125 gap_new.freespace = freespace;
126 /* Busco el gap que sucede a este */
127 fseek(f_fsc,0,SEEK_SET);
128 while (!feof(f_fsc)) {
129 if (fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
130 if (gap_aux.marker > gap_new.marker) {
136 /* Movemos todos los gaps desde el sucesor hasta el final, una pos adelante */
137 limit = ftell(f_fsc) - sizeof(EMUFS_FSC);
138 fseek(f_fsc,0,SEEK_END);
139 reg_count = (ftell(f_fsc) - limit) / sizeof(EMUFS_FSC);
140 source = ftell(f_fsc) - sizeof(EMUFS_FSC);
142 while (cant_moved < reg_count)
144 fseek(f_fsc,source,SEEK_SET);
145 fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
146 fwrite(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
147 source -= sizeof(EMUFS_FSC);
150 /* Agrego el nuevo registro */
151 fseek(f_fsc,limit,SEEK_SET);
152 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
155 fseek(f_fsc,0,SEEK_END);
156 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
162 /* Si encuentro un GAP Justo por delante pero no por detras */
163 if ((gap_before.marker != -1) && (gap_after.marker == -1))
165 /* Me posiciono en el registro que indica dicho gap y lo reescribo con */
166 /* la suma de los espacios libres */
167 fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_before,0);
168 gap_new.marker = gap_before.marker;
169 gap_new.freespace = gap_before.freespace + freespace;
170 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
174 /* Si encuentro un GAP Justo por detras pero no por delante */
175 if ((gap_before.marker == -1) && (gap_after.marker != -1))
177 /* Me posiciono en el registro que indica dicho gap y lo reescribo con */
178 /* los datos actualizados de offset y espacio */
179 fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_after,0);
180 gap_new.marker = gap_after.marker - freespace;
181 gap_new.freespace = gap_after.freespace + freespace;
182 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
186 /* Finalmente, si encuentro Justo por delante y por detras..*/
187 if ((gap_before.marker != -1) && (gap_after.marker != -1))
189 /* Guardo el nuevo GAP que posee los tres espacios sumados */
190 if (pos_gap_before < pos_gap_after) {
191 fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_before,0);
192 destination = sizeof(EMUFS_FSC)*pos_gap_after;
195 fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_after,0);
196 destination = sizeof(EMUFS_FSC)*pos_gap_before;
198 gap_new.marker = gap_before.marker;
199 gap_new.freespace = gap_before.freespace + freespace + gap_after.freespace;
200 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
202 /* Preparo el escenario para la movida de registros */
203 source = destination+sizeof(EMUFS_FSC); /* Salteo el gap que elimino! */
204 fseek(f_fsc,0,SEEK_END);
205 file_size = ftell(f_fsc);
206 reg_count = (file_size - source) / sizeof(EMUFS_FSC);
208 /* Comienzo a mover */
209 while (cant_moved < reg_count) {
210 fseek(f_fsc,source,0);
211 fread(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
212 fseek(f_fsc,-sizeof(EMUFS_FSC)*2,SEEK_CUR);
213 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
214 source += sizeof(EMUFS_FSC);
218 truncate(name_f_fsc, file_size - sizeof(EMUFS_FSC));
224 /* Elimina un registro GAP del archivo de espacios libres (gaps) */
225 int emufs_fsc_remove_gap(EMUFS *emu, EMUFS_OFFSET marker)
229 char name_f_fsc[255];
230 unsigned long source,destination,file_size,reg_count = 0,cant_moved = 0;
232 strcpy(name_f_fsc,emu->nombre);
233 strcat(name_f_fsc, EMUFS_FSC_EXT);
235 /* Busco el Gap en el .fsc */
236 if ((f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1;
237 while ( !feof(f_fsc) ){
238 if ( fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
239 if ( gap_aux.marker == marker ) break;
242 /* Preparo el escenario para la movida de registros */
243 fseek(f_fsc,-sizeof(EMUFS_FSC),SEEK_CUR);
244 destination = ftell(f_fsc);
245 source = destination+sizeof(EMUFS_FSC); /* Salteo el gap a eliminar! */
246 fseek(f_fsc,0,SEEK_END);
247 file_size = ftell(f_fsc);
248 reg_count = (file_size - source) / sizeof(EMUFS_FSC);
250 /* Comienzo a mover */
251 while (cant_moved < reg_count) {
252 fseek(f_fsc,source,0);
253 fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
254 fseek(f_fsc,-sizeof(EMUFS_FSC)*2,SEEK_CUR);
255 fwrite(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
256 source += sizeof(EMUFS_FSC);
260 truncate(name_f_fsc, file_size - sizeof(EMUFS_FSC));
265 /* Objetivo: Actualiza un registro de espacio libre de acorde al FType */
266 int emufs_fsc_actualizar(EMUFS *emu, EMUFS_BLOCK_ID marker, EMUFS_FREE freespace)
270 char name_f_fsc[255];
272 strcpy(name_f_fsc,emu->nombre);
273 strcat(name_f_fsc, EMUFS_FSC_EXT);
275 /*busco el bloque o gap que modifique*/
276 if ( (f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1;
277 while ( !feof(f_fsc) ){
278 if ( fread(®,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
279 if ( reg.marker == marker ){
280 reg.freespace = freespace;
281 fseek(f_fsc,-sizeof(EMUFS_FSC),SEEK_CUR);
282 fwrite(®,sizeof(EMUFS_FSC),1,f_fsc);
290 /* Actualiza un registro de gap, en el archivo de Gaps en Disco */
291 int emufs_fsc_actualizar_gap(EMUFS *emu, EMUFS_OFFSET marker, EMUFS_FREE freespace)
295 char name_f_fsc[255];
297 strcpy(name_f_fsc,emu->nombre);
298 strcat(name_f_fsc, EMUFS_FSC_EXT);
300 /*busco el bloque o gap que modifique*/
301 if ( (f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1;
302 while ( !feof(f_fsc) ){
303 if ( fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
304 if ( gap_aux.marker == marker ){
305 gap_aux.marker = marker + gap_aux.freespace - freespace;
306 gap_aux.freespace = freespace;
307 fseek(f_fsc,-sizeof(EMUFS_FSC),SEEK_CUR);
308 fwrite(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
316 /* Me devuelve el ID del bloque u Offset del Gap donde quepa un registro, y guarda en n_freespace el espacio libre actualizado */
317 EMUFS_BLOCK_ID emufs_fsc_buscar_lugar(EMUFS *emu, EMUFS_FREE reg_size, EMUFS_FREE *freespace)
321 char name_f_fsc[255];
324 strcpy(name_f_fsc,emu->nombre);
325 strcat(name_f_fsc, EMUFS_FSC_EXT);
327 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return EMUFS_NOT_FOUND;
329 if ( emu->tam_reg > emu->tam_bloque-sizeof(EMUFS_REG_ID) ){
330 fseek(f_fsc,0,SEEK_SET);
332 if (fread(®,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
333 if (reg.freespace == emu->tam_bloque) {
335 *freespace = reg.freespace;
340 /* Inicializamos la estructura para devolver algun valor en concreto */
341 /* en caso de que no se halle un espacio libre apropiado */
343 if (fread(®,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
344 if (reg.freespace >= reg_size) {
350 /* Si salio por error o por fin de archivo y no encontro space... */
352 reg.marker = EMUFS_NOT_FOUND;
353 *freespace = emu->tam_bloque;
355 else *freespace = reg.freespace;
361 /** Busca n lugares consecutivos devolviendo el id del primer bloque. */
362 EMUFS_BLOCK_ID emufs_fsc_buscar_n_lugares(EMUFS* efs, size_t n,
363 EMUFS_FREE size, EMUFS_FREE *freespace, int* err)
367 char name_f_fsc[255];
369 /* chequeo que al menos se busque un lugar */
371 PERR("Se debe buscar al menos un lugar");
372 *err = EMUFS_ERROR_WRONG_ARGUMENT;
373 return EMUFS_NOT_FOUND;
377 strcpy(name_f_fsc, efs->nombre);
378 strcat(name_f_fsc, EMUFS_FSC_EXT);
379 if (!(f_fsc = fopen(name_f_fsc, "rb"))) {
380 PERR("No se puede abrir archivo");
381 *err = EMUFS_ERROR_CANT_OPEN_FILE;
382 return EMUFS_NOT_FOUND;
385 /* busca el espacio libre */
386 while(!feof(f_fsc)) {
387 if ((fread(®, sizeof(EMUFS_FSC), 1, f_fsc) != 1)) {
388 if (feof(f_fsc)) break;
389 PERR("No se puede leer el archivo");
390 *err = EMUFS_ERROR_FILE_READ;
392 return EMUFS_NOT_FOUND;
394 if (reg.freespace >= size) {
396 EMUFS_BLOCK_ID first_id = reg.marker;
397 *freespace = reg.freespace;
399 if (fread(®, sizeof(EMUFS_FSC), 1, f_fsc) != 1) {
400 if (feof(f_fsc)) break;
401 PERR("No se puede leer el archivo");
402 *err = EMUFS_ERROR_FILE_READ;
404 return EMUFS_NOT_FOUND;
406 /* no hay otro lugar consecutivo */
407 if (reg.freespace < size) {
418 /* no se encontró espacio libre */
419 *freespace = efs->tam_bloque;
420 return EMUFS_NOT_FOUND;
423 /* Devuelve el espacio libre de un Bloque o Gap dado */
424 EMUFS_FREE emufs_fsc_get_fs(EMUFS *emu, EMUFS_BLOCK_ID marker)
428 char name_f_fsc[255];
430 strcpy(name_f_fsc,emu->nombre);
431 strcat(name_f_fsc, EMUFS_FSC_EXT);
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(®,sizeof(EMUFS_FSC),1,f_fsc) != 1 ) continue;
437 if ( reg.marker == marker )
442 return reg.freespace;
445 EMUFS_FREE emufs_fsc_get_total_fs(EMUFS *emu)
449 char name_f_fsc[255];
452 strcpy(name_f_fsc,emu->nombre);
453 strcat(name_f_fsc, EMUFS_FSC_EXT);
455 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
457 while ( !feof(f_fsc) ){
458 if ( fread(®, sizeof(EMUFS_FSC), 1, f_fsc) != 1) continue;
459 if ( reg.freespace > 0 )
460 total += reg.freespace;
466 int emufs_fsc_get_max_min_fs(EMUFS *emu, EMUFS_FREE *min, EMUFS_FREE *max)
470 char name_f_fsc[255];
472 strcpy(name_f_fsc,emu->nombre);
473 strcat(name_f_fsc, EMUFS_FSC_EXT);
475 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
477 /* Si el file esta vacio, devuelvo valores nulos */
478 fseek(f_fsc,0,SEEK_END);
479 if (ftell(f_fsc) == 0) {
486 /* Busco Min y Max */
489 fseek(f_fsc,0,SEEK_SET);
490 while ( !feof(f_fsc) ){
491 if ( fread(®, sizeof(EMUFS_FSC), 1, f_fsc) != 1) continue;
492 if ( reg.freespace < *min )
493 *min = reg.freespace;
494 if ( reg.freespace > *max )
495 *max = reg.freespace;
502 EMUFS_FREE emufs_fsc_get_media_fs(EMUFS *emu)
506 char name_f_fsc[255];
507 EMUFS_FREE total_fs = 0;
508 EMUFS_REG_ID gap_count = 0;
510 strcpy(name_f_fsc,emu->nombre);
511 strcat(name_f_fsc, EMUFS_FSC_EXT);
513 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
515 while ( !feof(f_fsc) ){
516 if ( fread(®, sizeof(EMUFS_FSC), 1, f_fsc) != 1) continue;
517 total_fs += reg.freespace;
523 if (gap_count > 0) return total_fs/gap_count;
527 EMUFS_BLOCK_ID emufs_fsc_get_cant_bloques_vacios(EMUFS *emu)
531 char name_f_fsc[255];
532 EMUFS_BLOCK_ID cant=0;
534 strcpy(name_f_fsc,emu->nombre);
535 strcat(name_f_fsc, EMUFS_FSC_EXT);
537 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
538 while ( !feof(f_fsc) ){
539 fread(®, sizeof(EMUFS_FSC), 1, f_fsc);
540 if ( reg.freespace == emu->tam_bloque )
548 int emufs_fsc_truncate(EMUFS* efs, EMUFS_BLOCK_ID blocks)
550 char name_f_fsc[255];
552 strcpy(name_f_fsc, efs->nombre);
553 strcat(name_f_fsc, EMUFS_FSC_EXT);
554 return truncate(name_f_fsc, blocks * sizeof(EMUFS_FSC));
557 EMUFS_BLOCK_ID emufs_fsc_get_num_blocks(EMUFS* efs)
560 char name_f_fsc[255];
561 EMUFS_BLOCK_ID cant = 0;
563 strcpy(name_f_fsc, efs->nombre);
564 strcat(name_f_fsc, EMUFS_FSC_EXT);
566 if (!(f_fsc = fopen(name_f_fsc, "ab"))) {
567 PERR("error al abrir archivo .fsc");
568 return EMUFS_NOT_FOUND;
570 cant = ftell(f_fsc) / sizeof(EMUFS_FSC);
575 long emufs_fsc_get_file_size(EMUFS* efs, int* err)
578 strcpy(name, efs->nombre);
579 strcat(name, EMUFS_FSC_EXT);
580 return emufs_common_get_file_size(name, err);