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.
40 #include <sys/types.h>
43 /* Crea un archivo de Gaps o Espacio Libre en Bloque */
44 int emufs_fsc_crear(EMUFS* efs)
46 return emufs_crear_archivo_auxiliar(efs->nombre, EMUFS_FSC_EXT);
49 /* Agrega un registro al archivo de espacio libre en bloque. */
50 int emufs_fsc_agregar(EMUFS *emu, EMUFS_BLOCK_ID marker, EMUFS_FREE freespace)
56 strcpy(name_f_fsc,emu->nombre);
57 strcat(name_f_fsc, EMUFS_FSC_EXT);
59 /* Lo guardo en el archivo al final "a+"*/
60 if ( (f_fsc = fopen(name_f_fsc,"r+"))==NULL ) return -1;
61 /* lo busco.. si esta lo modifico y si no lo agrego */
62 fseek(f_fsc,0,SEEK_SET);
63 while ( !feof(f_fsc) ){
64 if ( fread(®,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
65 if ( reg.marker == marker ){
66 fseek(f_fsc,-sizeof(EMUFS_FSC),SEEK_CUR);
67 reg.freespace = freespace;
68 fwrite(®,sizeof(EMUFS_FSC),1,f_fsc);
73 /* Cargo el registro */
75 reg.freespace = freespace;
76 fwrite(®,sizeof(EMUFS_FSC),1,f_fsc);
81 /* Agrega un GAP en el archivo de Gaps para Filetype 2 */
82 int emufs_fsc_agregar_gap(EMUFS *emu, EMUFS_OFFSET marker, EMUFS_FREE freespace)
85 EMUFS_FSC gap_aux,gap_before,gap_after,gap_new;
87 EMUFS_REG_ID pos_gap_before = 0, pos_gap_after = 0;
88 unsigned long source,destination,limit,file_size,reg_count = 0,cant_moved = 0;
91 strcpy(name_f_fsc,emu->nombre);
92 strcat(name_f_fsc, EMUFS_FSC_EXT);
94 gap_before.marker = -1;
95 gap_after.marker = -1;
97 /* Busco si hay un GAP por delante y/o por detras del que se esta por crear */
98 /* para en dicho caso realizar un merge! */
99 if ( (f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1;
100 while ( !feof(f_fsc) ){
101 if ( fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
103 /* Chequeo si es un gap justo anterior al nuestro */
104 if (gap_aux.marker+gap_aux.freespace == marker) {
105 gap_before.marker = gap_aux.marker;
106 gap_before.freespace = gap_aux.freespace;
107 pos_gap_before = reg_count;
110 /* Chequeo si es un gap justo posterior al nuestro */
111 if (gap_aux.marker == marker+freespace) {
112 gap_after.marker = gap_aux.marker;
113 gap_after.freespace = gap_aux.freespace;
114 pos_gap_after = reg_count;
119 /* Si no encontre gaps ni por delante ni por detras */
120 if ((gap_before.marker == -1) && (gap_after.marker == -1)) {
121 /* Lo guardo ordenado donde deba ir */
122 gap_new.marker = marker;
123 gap_new.freespace = freespace;
124 /* Busco el gap que sucede a este */
125 fseek(f_fsc,0,SEEK_SET);
126 while (!feof(f_fsc)) {
127 fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
128 if (gap_aux.marker > gap_new.marker) {
134 /* Movemos todos los gaps desde el sucesor hasta el final, una pos adelante */
135 limit = ftell(f_fsc) - sizeof(EMUFS_FSC);
136 fseek(f_fsc,0,SEEK_END);
137 reg_count = (ftell(f_fsc) - limit) / sizeof(EMUFS_FSC);
138 source = ftell(f_fsc) - sizeof(EMUFS_FSC);
140 while (cant_moved < reg_count)
142 fseek(f_fsc,source,SEEK_SET);
143 fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
144 fwrite(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
145 source -= sizeof(EMUFS_FSC);
148 /* Agrego el nuevo registro */
149 fseek(f_fsc,limit,SEEK_SET);
150 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
153 fseek(f_fsc,0,SEEK_END);
154 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
160 /* Si encuentro un GAP Justo por delante pero no por detras */
161 if ((gap_before.marker != -1) && (gap_after.marker == -1))
163 /* Me posiciono en el registro que indica dicho gap y lo reescribo con */
164 /* la suma de los espacios libres */
165 fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_before,0);
166 gap_new.marker = gap_before.marker;
167 gap_new.freespace = gap_before.freespace + freespace;
168 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
172 /* Si encuentro un GAP Justo por detras pero no por delante */
173 if ((gap_before.marker == -1) && (gap_after.marker != -1))
175 /* Me posiciono en el registro que indica dicho gap y lo reescribo con */
176 /* los datos actualizados de offset y espacio */
177 fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_after,0);
178 gap_new.marker = gap_after.marker - freespace;
179 gap_new.freespace = gap_after.freespace + freespace;
180 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
184 /* Finalmente, si encuentro Justo por delante y por detras..*/
185 if ((gap_before.marker != -1) && (gap_after.marker != -1))
187 /* Guardo el nuevo GAP que posee los tres espacios sumados */
188 if (pos_gap_before < pos_gap_after) {
189 fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_before,0);
190 destination = sizeof(EMUFS_FSC)*pos_gap_after;
193 fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_after,0);
194 destination = sizeof(EMUFS_FSC)*pos_gap_before;
196 gap_new.marker = gap_before.marker;
197 gap_new.freespace = gap_before.freespace + freespace + gap_after.freespace;
198 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
200 /* Preparo el escenario para la movida de registros */
201 source = destination+sizeof(EMUFS_FSC); /* Salteo el gap que elimino! */
202 fseek(f_fsc,0,SEEK_END);
203 file_size = ftell(f_fsc);
204 reg_count = (file_size - source) / sizeof(EMUFS_FSC);
206 /* Comienzo a mover */
207 while (cant_moved < reg_count) {
208 fseek(f_fsc,source,0);
209 fread(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
210 fseek(f_fsc,-sizeof(EMUFS_FSC)*2,SEEK_CUR);
211 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
212 source += sizeof(EMUFS_FSC);
216 truncate(name_f_fsc, file_size - sizeof(EMUFS_FSC));
222 /* Elimina un registro GAP del archivo de espacios libres (gaps) */
223 int emufs_fsc_remove_gap(EMUFS *emu, EMUFS_OFFSET marker)
227 char name_f_fsc[255];
228 unsigned long source,destination,file_size,reg_count = 0,cant_moved = 0;
230 strcpy(name_f_fsc,emu->nombre);
231 strcat(name_f_fsc, EMUFS_FSC_EXT);
233 /* Busco el Gap en el .fsc */
234 if ((f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1;
235 while ( !feof(f_fsc) ){
236 if ( fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
237 if ( gap_aux.marker == marker ) break;
240 /* Preparo el escenario para la movida de registros */
241 fseek(f_fsc,-sizeof(EMUFS_FSC),SEEK_CUR);
242 destination = ftell(f_fsc);
243 source = destination+sizeof(EMUFS_FSC); /* Salteo el gap a eliminar! */
244 fseek(f_fsc,0,SEEK_END);
245 file_size = ftell(f_fsc);
246 reg_count = (file_size - source) / sizeof(EMUFS_FSC);
248 /* Comienzo a mover */
249 while (cant_moved < reg_count) {
250 fseek(f_fsc,source,0);
251 fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
252 fseek(f_fsc,-sizeof(EMUFS_FSC)*2,SEEK_CUR);
253 fwrite(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
254 source += sizeof(EMUFS_FSC);
258 truncate(name_f_fsc, file_size - sizeof(EMUFS_FSC));
263 /* Objetivo: Actualiza un registro de espacio libre de acorde al FType */
264 int emufs_fsc_actualizar(EMUFS *emu, EMUFS_BLOCK_ID marker, EMUFS_FREE freespace)
268 char name_f_fsc[255];
270 strcpy(name_f_fsc,emu->nombre);
271 strcat(name_f_fsc, EMUFS_FSC_EXT);
273 /*busco el bloque o gap que modifique*/
274 if ( (f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1;
275 while ( !feof(f_fsc) ){
276 if ( fread(®,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
277 if ( reg.marker == marker ){
278 reg.freespace = freespace;
279 fseek(f_fsc,-sizeof(EMUFS_FSC),SEEK_CUR);
280 fwrite(®,sizeof(EMUFS_FSC),1,f_fsc);
288 /* Actualiza un registro de gap, en el archivo de Gaps en Disco */
289 int emufs_fsc_actualizar_gap(EMUFS *emu, EMUFS_OFFSET marker, EMUFS_FREE freespace)
293 char name_f_fsc[255];
295 strcpy(name_f_fsc,emu->nombre);
296 strcat(name_f_fsc, EMUFS_FSC_EXT);
298 /*busco el bloque o gap que modifique*/
299 if ( (f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1;
300 while ( !feof(f_fsc) ){
301 if ( fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
302 if ( gap_aux.marker == marker ){
303 gap_aux.marker = marker + gap_aux.freespace - freespace;
304 gap_aux.freespace = freespace;
305 fseek(f_fsc,-sizeof(EMUFS_FSC),SEEK_CUR);
306 fwrite(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
314 /* Me devuelve el ID del bloque u Offset del Gap donde quepa un registro, y guarda en n_freespace el espacio libre actualizado */
315 EMUFS_BLOCK_ID emufs_fsc_buscar_lugar(EMUFS *emu, EMUFS_FREE reg_size, EMUFS_FREE *freespace)
319 char name_f_fsc[255];
322 strcpy(name_f_fsc,emu->nombre);
323 strcat(name_f_fsc, EMUFS_FSC_EXT);
325 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return EMUFS_NOT_FOUND;
327 if ( emu->tam_reg > emu->tam_bloque-sizeof(EMUFS_REG_ID) ){
328 fseek(f_fsc,0,SEEK_SET);
330 if (fread(®,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
331 if (reg.freespace == emu->tam_bloque) {
333 *freespace = reg.freespace;
338 /* Inicializamos la estructura para devolver algun valor en concreto */
339 /* en caso de que no se halle un espacio libre apropiado */
341 if (fread(®,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
342 if (reg.freespace >= reg_size) {
348 /* Si salio por error o por fin de archivo y no encontro space... */
350 reg.marker = EMUFS_NOT_FOUND;
351 *freespace = emu->tam_bloque;
353 else *freespace = reg.freespace;
359 /** Busca n lugares consecutivos devolviendo el id del primer bloque. */
360 EMUFS_BLOCK_ID emufs_fsc_buscar_n_lugares(EMUFS* efs, size_t n,
361 EMUFS_FREE reg_size, EMUFS_FREE *freespace, int* err)
365 char name_f_fsc[255];
367 /* chequeo que al menos se busque un lugar */
369 PERR("Se debe buscar al menos un lugar");
370 *err = 13; /* EMUFS_ERROR_WRONG_ARGUMENT */
371 return EMUFS_NOT_FOUND;
375 strcpy(name_f_fsc, efs->nombre);
376 strcat(name_f_fsc, EMUFS_FSC_EXT);
377 if (!(f_fsc = fopen(name_f_fsc, "rb"))) {
378 PERR("No se puede abrir archivo");
379 *err = 4; /* EMUFS_ERROR_CANT_OPEN_FILE */
380 return EMUFS_NOT_FOUND;
383 /* busca el espacio libre */
384 while(!feof(f_fsc)) {
385 if ((fread(®, sizeof(EMUFS_FSC), 1, f_fsc) != 1)) {
386 if (feof(f_fsc)) break;
387 PERR("No se puede leer el archivo");
388 *err = 3; /* EMUFS_ERROR_FILE_READ */
389 return EMUFS_NOT_FOUND;
391 if (reg.freespace >= reg_size) {
393 EMUFS_BLOCK_ID first_id = reg.marker;
394 *freespace = reg.freespace;
396 if (fread(®, sizeof(EMUFS_FSC), 1, f_fsc) != 1) {
397 if (feof(f_fsc)) break;
398 PERR("No se puede leer el archivo");
399 *err = 3; /* EMUFS_ERROR_FILE_READ */
400 return EMUFS_NOT_FOUND;
402 /* no hay otro lugar consecutivo */
403 if (reg.freespace < reg_size) {
414 /* no se encontró espacio libre */
415 *freespace = efs->tam_bloque;
416 return EMUFS_NOT_FOUND;
419 /* Devuelve el espacio libre de un Bloque o Gap dado */
420 EMUFS_FREE emufs_fsc_get_fs(EMUFS *emu, EMUFS_BLOCK_ID marker)
424 char name_f_fsc[255];
426 strcpy(name_f_fsc,emu->nombre);
427 strcat(name_f_fsc, EMUFS_FSC_EXT);
429 /* Busco el Bloque o Gap pedido y obtengo su espacio libre */
430 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
431 while ( !feof(f_fsc) ){
432 if ( fread(®,sizeof(EMUFS_FSC),1,f_fsc) != 1 ) continue;
433 if ( reg.marker == marker )
438 return reg.freespace;
441 EMUFS_FREE emufs_fsc_get_total_fs(EMUFS *emu)
445 char name_f_fsc[255];
448 strcpy(name_f_fsc,emu->nombre);
449 strcat(name_f_fsc, EMUFS_FSC_EXT);
451 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
453 while ( !feof(f_fsc) ){
454 if ( fread(®, sizeof(EMUFS_FSC), 1, f_fsc) != 1) continue;
455 total += reg.freespace;
461 int emufs_fsc_get_max_min_fs(EMUFS *emu, EMUFS_FREE *min, EMUFS_FREE *max)
465 char name_f_fsc[255];
467 strcpy(name_f_fsc,emu->nombre);
468 strcat(name_f_fsc, EMUFS_FSC_EXT);
470 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
472 /* Si el file esta vacio, devuelvo valores nulos */
473 fseek(f_fsc,0,SEEK_END);
474 if (ftell(f_fsc) == 0) {
481 /* Busco Min y Max */
484 fseek(f_fsc,0,SEEK_SET);
485 while ( !feof(f_fsc) ){
486 if ( fread(®, sizeof(EMUFS_FSC), 1, f_fsc) != 1) continue;
487 if ( reg.freespace < *min )
488 *min = reg.freespace;
489 if ( reg.freespace > *max )
490 *max = reg.freespace;
497 EMUFS_FREE emufs_fsc_get_media_fs(EMUFS *emu)
501 char name_f_fsc[255];
502 EMUFS_FREE total_fs = 0;
503 EMUFS_REG_ID gap_count = 0;
505 strcpy(name_f_fsc,emu->nombre);
506 strcat(name_f_fsc, EMUFS_FSC_EXT);
508 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
510 while ( !feof(f_fsc) ){
511 if ( fread(®, sizeof(EMUFS_FSC), 1, f_fsc) != 1) continue;
512 total_fs += reg.freespace;
518 if (gap_count > 0) return total_fs/gap_count;
522 int emufs_fsc_get_cant_bloques_vacios(EMUFS *emu)
526 char name_f_fsc[255];
529 strcpy(name_f_fsc,emu->nombre);
530 strcat(name_f_fsc, EMUFS_FSC_EXT);
532 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
533 while ( !feof(f_fsc) ){
534 fread(®, sizeof(EMUFS_FSC), 1, f_fsc);
535 if ( reg.freespace == emu->tam_bloque )
543 int emufs_fsc_truncate(EMUFS* efs, EMUFS_BLOCK_ID blocks)
545 char name_f_fsc[255];
547 strcpy(name_f_fsc, efs->nombre);
548 strcat(name_f_fsc, EMUFS_FSC_EXT);
549 return truncate(name_f_fsc, blocks * sizeof(EMUFS_FSC));