/************************************************************************/
/*									*/
/*	DESCR.C								*/
/*	=======								*/
/*									*/
/*	Implementación de un sistema de ficheros muy simple,		*/
/*	para realizar prácticas de diseño de sistemas operativos.	*/
/*								 	*/
/*	Este módulo se encarga de las transferencias del superbloque	*/
/*	al/del disco. En el superbloque se almacena la información     	*/
/*	descriptora del sistema de ficheros: tamaños de bloques y 	*/
/*	áreas, orígenes de áreas de BFBs y datos, etc.			*/
/*						      			*/
/************************************************************************/ 


#include "descr.h"
#include "sffisico.h"
#include "errores.h"

#include "bfb.h"	/* Constante TAM_BFB */


#include <assert.h>
#include <stdlib.h>
#include <string.h>


/* Descriptor del sistema de ficheros */
 
struct DescriptorSFB DESC = { 0,0,0,0,0,0,0,0,0,0,0,0 }; 
 

/* Datos del SFB guardados en disco */
/* Estructura que se almacena en el disco */
 
struct Descripcion_en_disco 
{ 
  WORD  tam_bloque_datos; 
  WORD  num_BFB; 
  DWORD org_BFB; 
  DWORD org_datos; 
  DWORD primer_bloque_libre; 
  DWORD ultimo_bloque_datos; 
  char magicoSFB[8]; 
}; 
 
#define MAGICO_SFB "CORRECTO" 



/* Función LeeSuperbloque (&DESC)				*/
/*								*/ 
/*	Lee desde el disco la descripción del sistema		*/
/*	de ficheros y la guarda en DESC. Algunos campos 	*/
/*	se calculan a partir de la información en disco.	*/


int LeeSuperbloque ( struct DescriptorSFB* DESC )
{ 
	struct Descripcion_en_disco* desc; 
	char* bufer;
	WORD tam_bloque;
	DWORD num_bloques; 
 
        /* Lee datos del disco (tam. de bloque y número de bloques) */

	LeeDatosDisco( &tam_bloque, &num_bloques );
	assert (sizeof(struct Descripcion_en_disco) <= tam_bloque );
	bufer = malloc(tam_bloque);
	assert (bufer!=0); 

	DESC->tam_bloque_fisico = tam_bloque;
	DESC->num_bloques_fisicos = num_bloques;

	 
	/* Lee el superbloque */ 

	LeeBloqueFisico(0,bufer); 
	if (HAY_ERROR) return -1; 
 
	/* Recoge del disco los campos propios del SFB */ 

	desc = (struct Descripcion_en_disco*)(bufer+TAM_SUPERBLOQUE); 
 
	if ( strncmp(desc->magicoSFB,MAGICO_SFB,8) ) 
	 { Error_SF=ERR_FORMATO; free(bufer); return -1; }
	  
	DESC->tam_bloque_datos = desc->tam_bloque_datos; 
	DESC->num_BFB = desc->num_BFB; 
	DESC->org_BFB = desc->org_BFB; 
	DESC->org_datos = desc->org_datos; 
	DESC->primer_bloque_libre = desc->primer_bloque_libre; 
	DESC->ultimo_bloque_datos = desc->ultimo_bloque_datos; 
 

	/* Calcula los campos no presentes en disco */
 
	DESC->BFBs_por_BF = DESC->tam_bloque_fisico / TAM_BFB; 
	DESC->nbloques_BFB = DESC->num_BFB / DESC->BFBs_por_BF; 
	DESC->nbloques_datos = 
	  (DESC->num_bloques_fisicos-DESC->org_datos) / DESC->tam_bloque_datos; 
 

	/* Todo esto deberia ser cierto */
 
	assert(DESC->tam_bloque_fisico>=TAM_BFB); 
	assert(DESC->num_BFB>0); 
	assert(DESC->org_BFB==1); 
	assert(DESC->org_datos>DESC->org_BFB); 
	assert(DESC->primer_bloque_libre<DESC->ultimo_bloque_datos); 
	assert(DESC->nbloques_datos>0);


	/* Retorna */

	free(bufer);
	return 0;
	 
} /* LeeSuperbloque() */ 


 
/* Función EscribeSuperbloque (&DESC)				*/
/*								*/ 
/*	Escribe en el disco la descripción del sistema		*/
/*	de ficheros almacenada en DESC. Algunos campos 		*/
/*	no se guardan, ya que se pueden reconstruir.		*/


int EscribeSuperbloque ( const struct DescriptorSFB* DESC ) 
{ 
	struct Descripcion_en_disco* desc; 
	char* bufer; 
 
	assert (sizeof(struct Descripcion_en_disco) <= DESC->tam_bloque_fisico); 
	bufer = malloc(DESC->tam_bloque_fisico); 
	assert (bufer!=0); 
 
	/* Lee el superbloque */ 
	LeeBloqueFisico(0,bufer); 
 
	/* Rellena los campos del SFB */ 
	desc = (struct Descripcion_en_disco*)(bufer+TAM_SUPERBLOQUE); 

	strncpy(desc->magicoSFB,MAGICO_SFB,8); 
	desc->tam_bloque_datos = DESC->tam_bloque_datos; 
	desc->num_BFB = DESC->num_BFB; 
	desc->org_BFB = DESC->org_BFB; 
	desc->org_datos = DESC->org_datos; 
	desc->primer_bloque_libre = DESC->primer_bloque_libre; 
	desc->ultimo_bloque_datos = DESC->ultimo_bloque_datos; 
 
	/* Guarda el bloque modificado en disco */ 
	EscribeBloqueFisico(0,bufer); 

	free(bufer);
	return 0;

} /* EscribeSuperbloque()  */