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,file_size,reg_count = 0,cant_moved = 0;
89 strcpy(name_f_fsc,emu->nombre);
90 strcat(name_f_fsc, EMUFS_FSC_EXT);
92 gap_before.marker = -1;
93 gap_after.marker = -1;
95 /* Busco si hay un GAP por delante y/o por detras del que se esta por crear */
96 /* para en dicho caso realizar un merge! */
97 if ( (f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1;
98 while ( !feof(f_fsc) ){
99 if ( fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
101 /* Chequeo si es un gap justo anterior al nuestro */
102 if (gap_aux.marker+gap_aux.freespace == marker) {
103 gap_before.marker = gap_aux.marker;
104 gap_before.freespace = gap_aux.freespace;
105 pos_gap_before = reg_count;
108 /* Chequeo si es un gap justo posterior al nuestro */
109 if (gap_aux.marker == marker+freespace) {
110 gap_after.marker = gap_aux.marker;
111 gap_after.freespace = gap_aux.freespace;
112 pos_gap_after = reg_count;
117 /* Si no encontre gaps ni por delante ni por detras */
118 if ((gap_before.marker == -1) && (gap_after.marker == -1)) {
119 /* Lo guardo en el archivo al final */
120 gap_new.marker = marker;
121 gap_new.freespace = freespace;
122 fseek(f_fsc,0,SEEK_END);
123 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
127 /* Si encuentro un GAP Justo por delante pero no por detras */
128 if ((gap_before.marker != -1) && (gap_after.marker == -1))
130 /* Me posiciono en el registro que indica dicho gap y lo reescribo con */
131 /* la suma de los espacios libres */
132 fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_before,0);
133 gap_new.marker = gap_before.marker;
134 gap_new.freespace = gap_before.freespace + freespace;
135 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
139 /* Si encuentro un GAP Justo por detras pero no por delante */
140 if ((gap_before.marker == -1) && (gap_after.marker != -1))
142 /* Me posiciono en el registro que indica dicho gap y lo reescribo con */
143 /* los datos actualizados de offset y espacio */
144 fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_after,0);
145 gap_new.marker = gap_after.marker - freespace;
146 gap_new.freespace = gap_after.freespace + freespace;
147 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
151 /* Finalmente, si encuentro Justo por delante y por detras..*/
152 if ((gap_before.marker != -1) && (gap_after.marker != -1))
154 /* Guardo el nuevo GAP que posee los tres espacios sumados */
155 if (pos_gap_before < pos_gap_after) {
156 fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_before,0);
157 destination = sizeof(EMUFS_FSC)*pos_gap_after;
160 fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_after,0);
161 destination = sizeof(EMUFS_FSC)*pos_gap_before;
163 gap_new.marker = gap_before.marker;
164 gap_new.freespace = gap_before.freespace + freespace + gap_after.freespace;
165 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
167 /* Preparo el escenario para la movida de registros */
168 source = destination+sizeof(EMUFS_FSC); /* Salteo el gap que elimino! */
169 fseek(f_fsc,0,SEEK_END);
170 file_size = ftell(f_fsc);
171 reg_count = (file_size - source) / sizeof(EMUFS_FSC);
173 /* Comienzo a mover */
174 while (cant_moved < reg_count) {
175 fseek(f_fsc,source,0);
176 fread(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
177 fseek(f_fsc,-sizeof(EMUFS_FSC)*2,SEEK_CUR);
178 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
179 source += sizeof(EMUFS_FSC);
183 truncate(name_f_fsc, file_size - sizeof(EMUFS_FSC));
189 /* Elimina un registro GAP del archivo de espacios libres (gaps) */
190 int emufs_fsc_remove_gap(EMUFS *emu, EMUFS_OFFSET marker)
194 char name_f_fsc[255];
195 unsigned long source,destination,file_size,reg_count = 0,cant_moved = 0;
197 strcpy(name_f_fsc,emu->nombre);
198 strcat(name_f_fsc, EMUFS_FSC_EXT);
200 /* Busco el Gap en el .fsc */
201 if ((f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1;
202 while ( !feof(f_fsc) ){
203 if ( fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
204 if ( gap_aux.marker == marker ) break;
207 /* Preparo el escenario para la movida de registros */
208 fseek(f_fsc,-sizeof(EMUFS_FSC),SEEK_CUR);
209 destination = ftell(f_fsc);
210 source = destination+sizeof(EMUFS_FSC); /* Salteo el gap a eliminar! */
211 fseek(f_fsc,0,SEEK_END);
212 file_size = ftell(f_fsc);
213 reg_count = (file_size - source) / sizeof(EMUFS_FSC);
215 /* Comienzo a mover */
216 while (cant_moved < reg_count) {
217 fseek(f_fsc,source,0);
218 fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
219 fseek(f_fsc,-sizeof(EMUFS_FSC)*2,SEEK_CUR);
220 fwrite(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
221 source += sizeof(EMUFS_FSC);
225 truncate(name_f_fsc, file_size - sizeof(EMUFS_FSC));
230 /* Objetivo: Actualiza un registro de espacio libre de acorde al FType */
231 int emufs_fsc_actualizar(EMUFS *emu, EMUFS_BLOCK_ID marker, EMUFS_FREE freespace)
235 char name_f_fsc[255];
237 strcpy(name_f_fsc,emu->nombre);
238 strcat(name_f_fsc, EMUFS_FSC_EXT);
240 /*busco el bloque o gap que modifique*/
241 if ( (f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1;
242 while ( !feof(f_fsc) ){
243 if ( fread(®,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
244 if ( reg.marker == marker ){
245 reg.freespace = freespace;
246 fseek(f_fsc,-sizeof(EMUFS_FSC),SEEK_CUR);
247 fwrite(®,sizeof(EMUFS_FSC),1,f_fsc);
255 /* Actualiza un registro de gap, en el archivo de Gaps en Disco */
256 int emufs_fsc_actualizar_gap(EMUFS *emu, EMUFS_OFFSET marker, EMUFS_FREE freespace)
260 char name_f_fsc[255];
262 strcpy(name_f_fsc,emu->nombre);
263 strcat(name_f_fsc, EMUFS_FSC_EXT);
265 /*busco el bloque o gap que modifique*/
266 if ( (f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1;
267 while ( !feof(f_fsc) ){
268 if ( fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
269 if ( gap_aux.marker == marker ){
270 gap_aux.marker = marker + gap_aux.freespace - freespace;
271 gap_aux.freespace = freespace;
272 fseek(f_fsc,-sizeof(EMUFS_FSC),SEEK_CUR);
273 fwrite(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
281 /* Me devuelve el ID del bloque u Offset del Gap donde quepa un registro, y guarda en n_freespace el espacio libre actualizado */
282 EMUFS_BLOCK_ID emufs_fsc_buscar_lugar(EMUFS *emu, EMUFS_FREE reg_size, EMUFS_FREE *freespace)
286 char name_f_fsc[255];
289 strcpy(name_f_fsc,emu->nombre);
290 strcat(name_f_fsc, EMUFS_FSC_EXT);
292 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return EMUFS_NOT_FOUND;
294 if ( emu->tam_reg > emu->tam_bloque-sizeof(EMUFS_REG_ID) ){
295 fseek(f_fsc,0,SEEK_SET);
297 if (fread(®,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
298 if (reg.freespace == emu->tam_bloque) {
300 *freespace = reg.freespace;
305 /* Inicializamos la estructura para devolver algun valor en concreto */
306 /* en caso de que no se halle un espacio libre apropiado */
308 if (fread(®,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
309 if (reg.freespace >= reg_size) {
315 /* Si salio por error o por fin de archivo y no encontro space... */
317 reg.marker = EMUFS_NOT_FOUND;
318 *freespace = emu->tam_bloque;
320 else *freespace = reg.freespace;
326 /* Devuelve el espacio libre de un Bloque o Gap dado */
327 EMUFS_FREE emufs_fsc_get_fs(EMUFS *emu, EMUFS_BLOCK_ID marker)
331 char name_f_fsc[255];
333 strcpy(name_f_fsc,emu->nombre);
334 strcat(name_f_fsc, EMUFS_FSC_EXT);
336 /* Busco el Bloque o Gap pedido y obtengo su espacio libre */
337 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
338 while ( !feof(f_fsc) ){
339 if ( fread(®,sizeof(EMUFS_FSC),1,f_fsc) != 1 ) continue;
340 if ( reg.marker == marker )
345 return reg.freespace;
348 EMUFS_FREE emufs_fsc_get_total_fs(EMUFS *emu)
352 char name_f_fsc[255];
355 strcpy(name_f_fsc,emu->nombre);
356 strcat(name_f_fsc, EMUFS_FSC_EXT);
358 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
360 while ( !feof(f_fsc) ){
361 if ( fread(®, sizeof(EMUFS_FSC), 1, f_fsc) != 1) continue;
362 total += reg.freespace;
368 int emufs_fsc_get_max_min_fs(EMUFS *emu, EMUFS_FREE *min, EMUFS_FREE *max)
372 char name_f_fsc[255];
374 strcpy(name_f_fsc,emu->nombre);
375 strcat(name_f_fsc, EMUFS_FSC_EXT);
377 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
379 /* Si el file esta vacio, devuelvo valores nulos */
380 fseek(f_fsc,0,SEEK_END);
381 if (ftell(f_fsc) == 0) {
388 /* Busco Min y Max */
391 fseek(f_fsc,0,SEEK_SET);
392 while ( !feof(f_fsc) ){
393 if ( fread(®, sizeof(EMUFS_FSC), 1, f_fsc) != 1) continue;
394 if ( reg.freespace < *min )
395 *min = reg.freespace;
396 if ( reg.freespace > *max )
397 *max = reg.freespace;
404 EMUFS_FREE emufs_fsc_get_media_fs(EMUFS *emu)
408 char name_f_fsc[255];
409 EMUFS_FREE total_fs = 0;
410 EMUFS_REG_ID gap_count = 0;
412 strcpy(name_f_fsc,emu->nombre);
413 strcat(name_f_fsc, EMUFS_FSC_EXT);
415 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
417 while ( !feof(f_fsc) ){
418 if ( fread(®, sizeof(EMUFS_FSC), 1, f_fsc) != 1) continue;
419 total_fs += reg.freespace;
425 if (gap_count > 0) return total_fs/gap_count;
429 int emufs_fsc_get_cant_bloques_vacios(EMUFS *emu)
433 char name_f_fsc[255];
436 strcpy(name_f_fsc,emu->nombre);
437 strcat(name_f_fsc, EMUFS_FSC_EXT);
439 if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
440 while ( !feof(f_fsc) ){
441 fread(®, sizeof(EMUFS_FSC), 1, f_fsc);
442 if ( reg.freespace == emu->tam_bloque )
450 int emufs_fsc_truncate(EMUFS* efs, EMUFS_BLOCK_ID blocks)
452 char name_f_fsc[255];
454 strcpy(name_f_fsc, efs->nombre);
455 strcat(name_f_fsc, EMUFS_FSC_EXT);
456 return truncate(name_f_fsc, blocks * sizeof(EMUFS_FSC));