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+"*/
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(®,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(®,sizeof(EMUFS_FSC),1,f_fsc);
74 /* Cargo el registro */
76 reg.freespace = freespace;
77 fwrite(®,sizeof(EMUFS_FSC),1,f_fsc);
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)
86 EMUFS_FSC gap_aux,gap_before,gap_after,gap_new;
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;
92 strcpy(name_f_fsc,emu->nombre);
93 strcat(name_f_fsc, EMUFS_FSC_EXT);
95 gap_before.marker = -1;
96 gap_after.marker = -1;
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;
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;
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;
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) {
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);
141 while (cant_moved < reg_count)
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);
149 /* Agrego el nuevo registro */
150 fseek(f_fsc,limit,SEEK_SET);
151 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
154 fseek(f_fsc,0,SEEK_END);
155 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
161 /* Si encuentro un GAP Justo por delante pero no por detras */
162 if ((gap_before.marker != -1) && (gap_after.marker == -1))
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);
173 /* Si encuentro un GAP Justo por detras pero no por delante */
174 if ((gap_before.marker == -1) && (gap_after.marker != -1))
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);
185 /* Finalmente, si encuentro Justo por delante y por detras..*/
186 if ((gap_before.marker != -1) && (gap_after.marker != -1))
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;
194 fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_after,0);
195 destination = sizeof(EMUFS_FSC)*pos_gap_before;
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);
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);
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);
217 truncate(name_f_fsc, file_size - sizeof(EMUFS_FSC));
223 /* Elimina un registro GAP del archivo de espacios libres (gaps) */
224 int emufs_fsc_remove_gap(EMUFS *emu, EMUFS_OFFSET marker)
228 char name_f_fsc[255];
229 unsigned long source,destination,file_size,reg_count = 0,cant_moved = 0;
231 strcpy(name_f_fsc,emu->nombre);
232 strcat(name_f_fsc, EMUFS_FSC_EXT);
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;
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);
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);
259 truncate(name_f_fsc, file_size - sizeof(EMUFS_FSC));
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)
269 char name_f_fsc[255];
271 strcpy(name_f_fsc,emu->nombre);
272 strcat(name_f_fsc, EMUFS_FSC_EXT);
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(®,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(®,sizeof(EMUFS_FSC),1,f_fsc);
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)
294 char name_f_fsc[255];
296 strcpy(name_f_fsc,emu->nombre);
297 strcat(name_f_fsc, EMUFS_FSC_EXT);
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);
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)
320 char name_f_fsc[255];
323 strcpy(name_f_fsc,emu->nombre);
324 strcat(name_f_fsc, EMUFS_FSC_EXT);
326 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return EMUFS_NOT_FOUND;
328 if ( emu->tam_reg > emu->tam_bloque-sizeof(EMUFS_REG_ID) ){
329 fseek(f_fsc,0,SEEK_SET);
331 if (fread(®,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
332 if (reg.freespace == emu->tam_bloque) {
334 *freespace = reg.freespace;
339 /* Inicializamos la estructura para devolver algun valor en concreto */
340 /* en caso de que no se halle un espacio libre apropiado */
342 if (fread(®,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
343 if (reg.freespace >= reg_size) {
349 /* Si salio por error o por fin de archivo y no encontro space... */
351 reg.marker = EMUFS_NOT_FOUND;
352 *freespace = emu->tam_bloque;
354 else *freespace = reg.freespace;
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 size, EMUFS_FREE *freespace, int* err)
366 char name_f_fsc[255];
368 /* chequeo que al menos se busque un lugar */
370 PERR("Se debe buscar al menos un lugar");
371 *err = EMUFS_ERROR_WRONG_ARGUMENT;
372 return EMUFS_NOT_FOUND;
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;
384 /* busca el espacio libre */
385 while(!feof(f_fsc)) {
386 if ((fread(®, 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;
391 return EMUFS_NOT_FOUND;
393 if (reg.freespace >= size) {
395 EMUFS_BLOCK_ID first_id = reg.marker;
396 *freespace = reg.freespace;
398 if (fread(®, sizeof(EMUFS_FSC), 1, f_fsc) != 1) {
399 if (feof(f_fsc)) break;
400 PERR("No se puede leer el archivo");
401 *err = EMUFS_ERROR_FILE_READ;
403 return EMUFS_NOT_FOUND;
405 /* no hay otro lugar consecutivo */
406 if (reg.freespace < size) {
417 /* no se encontró espacio libre */
418 *freespace = efs->tam_bloque;
419 return EMUFS_NOT_FOUND;
422 /* Devuelve el espacio libre de un Bloque o Gap dado */
423 EMUFS_FREE emufs_fsc_get_fs(EMUFS *emu, EMUFS_BLOCK_ID marker)
427 char name_f_fsc[255];
429 strcpy(name_f_fsc,emu->nombre);
430 strcat(name_f_fsc, EMUFS_FSC_EXT);
432 /* Busco el Bloque o Gap pedido y obtengo su espacio libre */
433 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
434 while ( !feof(f_fsc) ){
435 if ( fread(®,sizeof(EMUFS_FSC),1,f_fsc) != 1 ) continue;
436 if ( reg.marker == marker )
441 return reg.freespace;
444 EMUFS_FREE emufs_fsc_get_total_fs(EMUFS *emu)
448 char name_f_fsc[255];
451 strcpy(name_f_fsc,emu->nombre);
452 strcat(name_f_fsc, EMUFS_FSC_EXT);
454 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
456 while ( !feof(f_fsc) ){
457 if ( fread(®, sizeof(EMUFS_FSC), 1, f_fsc) != 1) continue;
458 if ( reg.freespace > 0 )
459 total += reg.freespace;
465 int emufs_fsc_get_max_min_fs(EMUFS *emu, EMUFS_FREE *min, EMUFS_FREE *max)
469 char name_f_fsc[255];
471 strcpy(name_f_fsc,emu->nombre);
472 strcat(name_f_fsc, EMUFS_FSC_EXT);
474 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
476 /* Si el file esta vacio, devuelvo valores nulos */
477 fseek(f_fsc,0,SEEK_END);
478 if (ftell(f_fsc) == 0) {
485 /* Busco Min y Max */
488 fseek(f_fsc,0,SEEK_SET);
489 while ( !feof(f_fsc) ){
490 if ( fread(®, 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;
501 EMUFS_FREE emufs_fsc_get_media_fs(EMUFS *emu)
505 char name_f_fsc[255];
506 EMUFS_FREE total_fs = 0;
507 EMUFS_REG_ID gap_count = 0;
509 strcpy(name_f_fsc,emu->nombre);
510 strcat(name_f_fsc, EMUFS_FSC_EXT);
512 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
514 while ( !feof(f_fsc) ){
515 if ( fread(®, sizeof(EMUFS_FSC), 1, f_fsc) != 1) continue;
516 total_fs += reg.freespace;
522 if (gap_count > 0) return total_fs/gap_count;
526 EMUFS_BLOCK_ID emufs_fsc_get_cant_bloques_vacios(EMUFS *emu)
530 char name_f_fsc[255];
531 EMUFS_BLOCK_ID cant=0;
533 strcpy(name_f_fsc,emu->nombre);
534 strcat(name_f_fsc, EMUFS_FSC_EXT);
536 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
537 while ( !feof(f_fsc) ){
538 fread(®, sizeof(EMUFS_FSC), 1, f_fsc);
539 if ( reg.freespace == emu->tam_bloque )
547 int emufs_fsc_truncate(EMUFS* efs, EMUFS_BLOCK_ID blocks)
549 char name_f_fsc[255];
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));
556 EMUFS_BLOCK_ID emufs_fsc_get_num_blocks(EMUFS* efs)
559 char name_f_fsc[255];
560 EMUFS_BLOCK_ID cant = 0;
562 strcpy(name_f_fsc, efs->nombre);
563 strcat(name_f_fsc, EMUFS_FSC_EXT);
565 if (!(f_fsc = fopen(name_f_fsc, "ab"))) {
566 PERR("error al abrir archivo .fsc");
567 return EMUFS_NOT_FOUND;
569 cant = ftell(f_fsc) / sizeof(EMUFS_FSC);
574 long emufs_fsc_get_file_size(EMUFS* efs, int* err)
577 strcpy(name, efs->nombre);
578 strcat(name, EMUFS_FSC_EXT);
579 return emufs_common_get_file_size(name, err);