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.
42 /* Crea un archivo de Gaps o Espacio Libre en Bloque */
43 int emufs_fsc_crear(EMUFS* efs)
45 return emufs_crear_archivo_auxiliar(efs->nombre, EMUFS_FSC_EXT);
48 /* Agrega un registro al archivo de espacio libre en bloque. */
49 int emufs_fsc_agregar(EMUFS *emu, EMUFS_BLOCK_ID marker, EMUFS_FREE freespace)
55 strcpy(name_f_fsc,emu->nombre);
56 strcat(name_f_fsc, EMUFS_FSC_EXT);
58 /* Lo guardo en el archivo al final "a+"*/
59 if ( (f_fsc = fopen(name_f_fsc,"r+"))==NULL ) return -1;
60 /* lo busco.. si esta lo modifico y si no lo agrego */
61 fseek(f_fsc,0,SEEK_SET);
62 while ( !feof(f_fsc) ){
63 if ( fread(®,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
64 if ( reg.marker == marker ){
65 fseek(f_fsc,-sizeof(EMUFS_FSC),SEEK_CUR);
66 reg.freespace = freespace;
67 fwrite(®,sizeof(EMUFS_FSC),1,f_fsc);
72 /* Cargo el registro */
74 reg.freespace = freespace;
75 fwrite(®,sizeof(EMUFS_FSC),1,f_fsc);
80 /* Agrega un GAP en el archivo de Gaps para Filetype 2 */
81 int emufs_fsc_agregar_gap(EMUFS *emu, EMUFS_OFFSET marker, EMUFS_FREE freespace)
84 EMUFS_FSC gap_aux,gap_before,gap_after,gap_new;
86 EMUFS_REG_ID pos_gap_before = 0, pos_gap_after = 0;
87 unsigned long source,destination,limit,file_size,reg_count = 0,cant_moved = 0;
90 strcpy(name_f_fsc,emu->nombre);
91 strcat(name_f_fsc, EMUFS_FSC_EXT);
93 gap_before.marker = -1;
94 gap_after.marker = -1;
96 /* Busco si hay un GAP por delante y/o por detras del que se esta por crear */
97 /* para en dicho caso realizar un merge! */
98 if ( (f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1;
99 while ( !feof(f_fsc) ){
100 if ( fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
102 /* Chequeo si es un gap justo anterior al nuestro */
103 if (gap_aux.marker+gap_aux.freespace == marker) {
104 gap_before.marker = gap_aux.marker;
105 gap_before.freespace = gap_aux.freespace;
106 pos_gap_before = reg_count;
109 /* Chequeo si es un gap justo posterior al nuestro */
110 if (gap_aux.marker == marker+freespace) {
111 gap_after.marker = gap_aux.marker;
112 gap_after.freespace = gap_aux.freespace;
113 pos_gap_after = reg_count;
118 /* Si no encontre gaps ni por delante ni por detras */
119 if ((gap_before.marker == -1) && (gap_after.marker == -1)) {
120 /* Lo guardo ordenado donde deba ir */
121 gap_new.marker = marker;
122 gap_new.freespace = freespace;
123 /* Busco el gap que sucede a este */
124 fseek(f_fsc,0,SEEK_SET);
125 while (!feof(f_fsc)) {
126 fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
127 if (gap_aux.marker > gap_new.marker) {
133 /* Movemos todos los gaps desde el sucesor hasta el final, una pos adelante */
134 limit = ftell(f_fsc) - sizeof(EMUFS_FSC);
135 fseek(f_fsc,0,SEEK_END);
136 reg_count = (ftell(f_fsc) - limit) / sizeof(EMUFS_FSC);
137 source = ftell(f_fsc) - sizeof(EMUFS_FSC);
139 while (cant_moved < reg_count)
141 fseek(f_fsc,source,SEEK_SET);
142 fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
143 fwrite(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
144 source -= sizeof(EMUFS_FSC);
147 /* Agrego el nuevo registro */
148 fseek(f_fsc,limit,SEEK_SET);
149 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
152 fseek(f_fsc,0,SEEK_END);
153 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
159 /* Si encuentro un GAP Justo por delante pero no por detras */
160 if ((gap_before.marker != -1) && (gap_after.marker == -1))
162 /* Me posiciono en el registro que indica dicho gap y lo reescribo con */
163 /* la suma de los espacios libres */
164 fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_before,0);
165 gap_new.marker = gap_before.marker;
166 gap_new.freespace = gap_before.freespace + freespace;
167 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
171 /* Si encuentro un GAP Justo por detras pero no por delante */
172 if ((gap_before.marker == -1) && (gap_after.marker != -1))
174 /* Me posiciono en el registro que indica dicho gap y lo reescribo con */
175 /* los datos actualizados de offset y espacio */
176 fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_after,0);
177 gap_new.marker = gap_after.marker - freespace;
178 gap_new.freespace = gap_after.freespace + freespace;
179 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
183 /* Finalmente, si encuentro Justo por delante y por detras..*/
184 if ((gap_before.marker != -1) && (gap_after.marker != -1))
186 /* Guardo el nuevo GAP que posee los tres espacios sumados */
187 if (pos_gap_before < pos_gap_after) {
188 fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_before,0);
189 destination = sizeof(EMUFS_FSC)*pos_gap_after;
192 fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_after,0);
193 destination = sizeof(EMUFS_FSC)*pos_gap_before;
195 gap_new.marker = gap_before.marker;
196 gap_new.freespace = gap_before.freespace + freespace + gap_after.freespace;
197 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
199 /* Preparo el escenario para la movida de registros */
200 source = destination+sizeof(EMUFS_FSC); /* Salteo el gap que elimino! */
201 fseek(f_fsc,0,SEEK_END);
202 file_size = ftell(f_fsc);
203 reg_count = (file_size - source) / sizeof(EMUFS_FSC);
205 /* Comienzo a mover */
206 while (cant_moved < reg_count) {
207 fseek(f_fsc,source,0);
208 fread(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
209 fseek(f_fsc,-sizeof(EMUFS_FSC)*2,SEEK_CUR);
210 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
211 source += sizeof(EMUFS_FSC);
215 truncate(name_f_fsc, file_size - sizeof(EMUFS_FSC));
221 /* Elimina un registro GAP del archivo de espacios libres (gaps) */
222 int emufs_fsc_remove_gap(EMUFS *emu, EMUFS_OFFSET marker)
226 char name_f_fsc[255];
227 unsigned long source,destination,file_size,reg_count = 0,cant_moved = 0;
229 strcpy(name_f_fsc,emu->nombre);
230 strcat(name_f_fsc, EMUFS_FSC_EXT);
232 /* Busco el Gap en el .fsc */
233 if ((f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1;
234 while ( !feof(f_fsc) ){
235 if ( fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
236 if ( gap_aux.marker == marker ) break;
239 /* Preparo el escenario para la movida de registros */
240 fseek(f_fsc,-sizeof(EMUFS_FSC),SEEK_CUR);
241 destination = ftell(f_fsc);
242 source = destination+sizeof(EMUFS_FSC); /* Salteo el gap a eliminar! */
243 fseek(f_fsc,0,SEEK_END);
244 file_size = ftell(f_fsc);
245 reg_count = (file_size - source) / sizeof(EMUFS_FSC);
247 /* Comienzo a mover */
248 while (cant_moved < reg_count) {
249 fseek(f_fsc,source,0);
250 fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
251 fseek(f_fsc,-sizeof(EMUFS_FSC)*2,SEEK_CUR);
252 fwrite(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
253 source += sizeof(EMUFS_FSC);
257 truncate(name_f_fsc, file_size - sizeof(EMUFS_FSC));
262 /* Objetivo: Actualiza un registro de espacio libre de acorde al FType */
263 int emufs_fsc_actualizar(EMUFS *emu, EMUFS_BLOCK_ID marker, EMUFS_FREE freespace)
267 char name_f_fsc[255];
269 strcpy(name_f_fsc,emu->nombre);
270 strcat(name_f_fsc, EMUFS_FSC_EXT);
272 /*busco el bloque o gap que modifique*/
273 if ( (f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1;
274 while ( !feof(f_fsc) ){
275 if ( fread(®,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
276 if ( reg.marker == marker ){
277 reg.freespace = freespace;
278 fseek(f_fsc,-sizeof(EMUFS_FSC),SEEK_CUR);
279 fwrite(®,sizeof(EMUFS_FSC),1,f_fsc);
287 /* Actualiza un registro de gap, en el archivo de Gaps en Disco */
288 int emufs_fsc_actualizar_gap(EMUFS *emu, EMUFS_OFFSET marker, EMUFS_FREE freespace)
292 char name_f_fsc[255];
294 strcpy(name_f_fsc,emu->nombre);
295 strcat(name_f_fsc, EMUFS_FSC_EXT);
297 /*busco el bloque o gap que modifique*/
298 if ( (f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1;
299 while ( !feof(f_fsc) ){
300 if ( fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
301 if ( gap_aux.marker == marker ){
302 gap_aux.marker = marker + gap_aux.freespace - freespace;
303 gap_aux.freespace = freespace;
304 fseek(f_fsc,-sizeof(EMUFS_FSC),SEEK_CUR);
305 fwrite(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
313 /* Me devuelve el ID del bloque u Offset del Gap donde quepa un registro, y guarda en n_freespace el espacio libre actualizado */
314 EMUFS_BLOCK_ID emufs_fsc_buscar_lugar(EMUFS *emu, EMUFS_FREE reg_size, EMUFS_FREE *freespace)
318 char name_f_fsc[255];
321 strcpy(name_f_fsc,emu->nombre);
322 strcat(name_f_fsc, EMUFS_FSC_EXT);
324 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return EMUFS_NOT_FOUND;
326 if ( emu->tam_reg > emu->tam_bloque-sizeof(EMUFS_REG_ID) ){
327 fseek(f_fsc,0,SEEK_SET);
329 if (fread(®,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
330 if (reg.freespace == emu->tam_bloque) {
332 *freespace = reg.freespace;
337 /* Inicializamos la estructura para devolver algun valor en concreto */
338 /* en caso de que no se halle un espacio libre apropiado */
340 if (fread(®,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
341 if (reg.freespace >= reg_size) {
347 /* Si salio por error o por fin de archivo y no encontro space... */
349 reg.marker = EMUFS_NOT_FOUND;
350 *freespace = emu->tam_bloque;
352 else *freespace = reg.freespace;
358 /* Devuelve el espacio libre de un Bloque o Gap dado */
359 EMUFS_FREE emufs_fsc_get_fs(EMUFS *emu, EMUFS_BLOCK_ID marker)
363 char name_f_fsc[255];
365 strcpy(name_f_fsc,emu->nombre);
366 strcat(name_f_fsc, EMUFS_FSC_EXT);
368 /* Busco el Bloque o Gap pedido y obtengo su espacio libre */
369 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
370 while ( !feof(f_fsc) ){
371 if ( fread(®,sizeof(EMUFS_FSC),1,f_fsc) != 1 ) continue;
372 if ( reg.marker == marker )
377 return reg.freespace;
380 EMUFS_FREE emufs_fsc_get_total_fs(EMUFS *emu)
384 char name_f_fsc[255];
387 strcpy(name_f_fsc,emu->nombre);
388 strcat(name_f_fsc, EMUFS_FSC_EXT);
390 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
392 while ( !feof(f_fsc) ){
393 if ( fread(®, sizeof(EMUFS_FSC), 1, f_fsc) != 1) continue;
394 total += reg.freespace;
400 int emufs_fsc_get_max_min_fs(EMUFS *emu, EMUFS_FREE *min, EMUFS_FREE *max)
404 char name_f_fsc[255];
406 strcpy(name_f_fsc,emu->nombre);
407 strcat(name_f_fsc, EMUFS_FSC_EXT);
409 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
411 /* Si el file esta vacio, devuelvo valores nulos */
412 fseek(f_fsc,0,SEEK_END);
413 if (ftell(f_fsc) == 0) {
420 /* Busco Min y Max */
423 fseek(f_fsc,0,SEEK_SET);
424 while ( !feof(f_fsc) ){
425 if ( fread(®, sizeof(EMUFS_FSC), 1, f_fsc) != 1) continue;
426 if ( reg.freespace < *min )
427 *min = reg.freespace;
428 if ( reg.freespace > *max )
429 *max = reg.freespace;
436 EMUFS_FREE emufs_fsc_get_media_fs(EMUFS *emu)
440 char name_f_fsc[255];
441 EMUFS_FREE total_fs = 0;
442 EMUFS_REG_ID gap_count = 0;
444 strcpy(name_f_fsc,emu->nombre);
445 strcat(name_f_fsc, EMUFS_FSC_EXT);
447 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
449 while ( !feof(f_fsc) ){
450 if ( fread(®, sizeof(EMUFS_FSC), 1, f_fsc) != 1) continue;
451 total_fs += reg.freespace;
457 if (gap_count > 0) return total_fs/gap_count;
461 int emufs_fsc_get_cant_bloques_vacios(EMUFS *emu)
465 char name_f_fsc[255];
468 strcpy(name_f_fsc,emu->nombre);
469 strcat(name_f_fsc, EMUFS_FSC_EXT);
471 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
472 while ( !feof(f_fsc) ){
473 fread(®, sizeof(EMUFS_FSC), 1, f_fsc);
474 if ( reg.freespace == emu->tam_bloque )
482 int emufs_fsc_truncate(EMUFS* efs, EMUFS_BLOCK_ID blocks)
484 char name_f_fsc[255];
486 strcpy(name_f_fsc, efs->nombre);
487 strcat(name_f_fsc, EMUFS_FSC_EXT);
488 return truncate(name_f_fsc, blocks * sizeof(EMUFS_FSC));