/* Sistema de ficheros básico con asignación de espacio indexada de un solo nivel */ #include "sfbasico.h" #include "sbfisico.h" #include "errores.h" /* #include "superblq.h" */ #include #include /* Constantes y límites */ #define MAX_BLOQUES 100 #define LIBRE 0 #define OCUPADO 1 /************************/ /* Estructuras de datos */ /************************/ /* Estructura de descripción del sistema de ficheros básico */ struct DescriptorSFB { /* Tamaños */ WORD tam_BF; /* tamaño de bloque físico */ WORD tam_BFB; /* tamaño del bloque de fichero básico */ WORD tam_DFE; /* tamaño del descriptor de fichero extendido */ WORD num_BFB; /* numero de BFBs */ WORD BFBs_por_BF; /* bloques de fichero en un bloque físico */ DWORD nbloques_BFB; /* número de bloques físicos ocupados por BFBs */ DWORD nbloques_mapa; /* número de bloques físicos para el mapa de bits */ DWORD nbloques_datos; /* número de bloques de datos */ WORD tam_bldatos; /* tama¤o del bloque de datos (en BF) */ /* Orígenes de las áreas en disco (medidos en bloques físicos) */ DWORD org_BFB; /* origen de los bloques de ficheros básicos */ DWORD org_mapa; /* origen del mapa de bits */ DWORD org_datos; /* origen de los bloques de datos */ /* Control de montaje */ int montado; /* 0 si no hay sistema montado */ }; static struct DescriptorSFB DESC; #define MONTADO if (DESC.montado==0) { Error_SF=ERR_INACTIVO; return -1; } \ else Error_SF=0; /* Estructura de descripción de un fichero básico */ struct BloqueFicheroBasico { BYTE estado; /* estado de la entrada */ DWORD id; /* identificador */ WORD num_bloques; /* Número de bloques de datos */ DWORD tabla [MAX_BLOQUES]; /* apuntadores a los bloques de datos */ }; typedef struct BloqueFicheroBasico BFB; #define BFB_LIBRE 0 #define BFB_OCUPADO 1 #define MAPA_LIBRE 0 #define MAPA_OCUPADO 1 #define tam_DFB (sizeof(struct BloqueFicheroBasico)) /**********************/ /* Funciones privadas */ /**********************/ /* Toma espacio para un bloque f¡sico */ /* static char* nuevo_bloque() { return (char*)malloc(DESC.tam_BF); } */ #define nuevo_bloque() ((char*)malloc(DESC.tam_BF)) /* Comprueba la integridad de un superbloque */ int comprueba_integridad (struct Superbloque*); /* Funciones de manipulaci¢n de descriptores de ficheros */ /* Estas funciones son privadas de este m¢dulo */ /* y equivalen a funciones miembros de la clase BFB */ void BFB_calcula(IFB,DWORD*,WORD*); void BFB_lee(IFB,BFB*); void BFB_escribe(IFB,BFB*); void BFB_inicial(BFB*,int numero); void BFB_expande(BFB*,WORD num_bloques); void BFB_trunca (BFB*,WORD num_bloques); /*************************/ /* Da formato a un disco */ /*************************/ /* El disco ha de estar montado */ /* Destruye la información preexistente */ void FormatoBFBs(void); void FormatoMapaBits(void); int FormateaSFB ( const char* nombre_fichero, WORD BF_reservados, WORD tam_DFE, WORD tam_bloque_datos, WORD num_ficheros ) { struct Superbloque superbloque; long BF_restantes; int result; /* temporal para resultados */ /* Primero, monta el disco físico */ Error_SF = 0; MontaDisco(nombre_fichero,0); if (HAY_ERROR) { Error_SF = ERR_INACTIVO; return -1; } /* Recoge los parámetros del sistema de ficheros */ /* y comprueba la integridad */ LeeSuperbloque(&superbloque); result=comprueba_integridad(&superbloque); if (result==-1) return -1; /* Calcula tamaños y límites */ DESC.tam_BF = superbloque.tam_bloque_fisico; /* BFBs */ DESC.tam_BFB = tam_DFB + tam_DFE; if ( DESC.tam_BFB > DESC.tam_BF ) { Error_SF=ERR_RANGO; return -1; } DESC.BFBs_por_BF = DESC.tam_BF / DESC.tam_BFB; DESC.nbloques_BFB = num_ficheros / DESC.BFBs_por_BF; /* Mapa de bits y bloques de datos */ BF_restantes = superbloque.num_bloques_fisicos - (1 + BF_reservados + DESC.nbloques_BFB); if (BF_restantes<0) { Error_SF=ERR_ESPACIO; return -1; } /* Mapa de bits y bloques de datos */ { int temp = 1 + DESC.tam_BF*tam_bloque_datos; DESC.nbloques_mapa = (BF_restantes/temp) + (BF_restantes%temp!=0); DESC.nbloques_datos = BF_restantes - DESC.nbloques_mapa; } /* orígenes de cada área */ DESC.org_BFB = 1 + BF_reservados; DESC.org_mapa = DESC.org_BFB + DESC.nbloques_BFB; DESC.org_datos = DESC.org_mapa + DESC.nbloques_mapa; /* Escribe la información en el superbloque */ superbloque.BF_bloque_datos = tam_bloque_datos; superbloque.bytes_bloque_datos = tam_bloque_datos * DESC.tam_BF; superbloque.num_BF_reservados = BF_reservados; superbloque.tam_BFB = DESC.tam_BFB; superbloque.num_BFB = num_ficheros; superbloque.tam_DFE = tam_DFE; EscribeSuperbloque(&superbloque); /****/ /* Da formato a los bloques de fichero básicos */ FormatoBFBs(); /****/ /* Da formato al mapa de bits */ FormatoMapaBits(); /****/ /* Da formato a los bloques de datos */ /* (no se hace nada con ellos) */ ; /* Desmonta el disco */ result = DesmontaDisco(); return result==0 ? 0 : (Error_SF=ERR_DISCO,-1) ; } /* FormateaSFB */ static int comprueba_integridad (struct Superbloque* sb) { if (strcmp(sb->magico,MAGICO)) { Error_SF=ERR_FORMATO; return -1; } if ( sb->tam_bloque_fisicotam_bloque_fisico>MAX_TAMBLOQUE ) { Error_SF=ERR_ESPACIO; return -1; } return 0; } static void FormatoBFBs (void) { int i,k; int bloque=DESC.org_BFB; int contador=0; char* buf = nuevo_bloque(); for (i=0;iestado == BFB_LIBRE ) { bfb->estado = BFB_OCUPADO; BFB_expande(bfb,num_bloques); EscribeBloqueFisico(DESC.org_BFB+i,bufer); if (HAY_ERROR) return -1; return contador; } else contador++; } } Error_SF = ERR_ESPACIO; return -1; } /* CreaFB */ int DestruyeFB (IFB fichero) { DWORD bloque_fisico; WORD desplazamiento; BFB* bfb; char* bufer = nuevo_bloque(); MONTADO BFB_calcula(fichero,&bloque_fisico,&desplazamiento); if (HAY_ERROR) return -1; LeeBloqueFisico(bloque_fisico,bufer); if (HAY_ERROR) return -1; bfb = (BFB*)(bufer+desplazamiento); if (bfb->estado==BFB_LIBRE) { Error_SF = ERR_LIBRE; return -1; } BFB_trunca(bfb,0); bfb->estado = BFB_LIBRE; EscribeBloqueFisico(bloque_fisico,bufer); if (HAY_ERROR) return -1; free(bufer); return 0; } /* DestruyeFB */ /**********************/ /* Tamaño del fichero */ /**********************/ WORD LongitudFB ( IFB fichero ) { BFB bfb; MONTADO BFB_lee(fichero,&bfb); return HAY_ERROR ? (WORD)-1 : bfb.num_bloques; } int ExpandeFB ( IFB fichero, WORD num_bloques ) { DWORD bloque; WORD desplaz; char* bufer = nuevo_bloque(); MONTADO BFB_calcula(fichero,&bloque,&desplaz); LeeBloqueFisico(bloque,bufer); if (HAY_ERROR) return -1; BFB_expande ( (BFB*)(bufer+desplaz), num_bloques); EscribeBloqueFisico(bloque,bufer); free(bufer); return HAY_ERROR ? -1 : 0; } /* ExpandeFB */ int TruncaFB ( IFB fichero, WORD num_bloques ) { DWORD bloque; WORD desplaz; char* bufer = nuevo_bloque(); MONTADO BFB_calcula(fichero,&bloque,&desplaz); LeeBloqueFisico(bloque,bufer); if (HAY_ERROR) return -1; BFB_trunca( (BFB*)(bufer+desplaz), num_bloques ); EscribeBloqueFisico(bloque,bufer); free(bufer); return 0; } /**********************************/ /* Lectura y escritura de bloques */ /**********************************/ #define LECTURA 0 #define ESCRITURA 1 /* Funci¢n general para lecturas y escrituras */ static int AccedeBloqueFB ( IFB fichero, WORD num_bloque, void* bufer, int tipo ) { BFB bfb; MONTADO BFB_lee(fichero,&bfb); if (bfb.estado==BFB_LIBRE) { Error_SF = ERR_LIBRE; return -1; } if ( num_bloque==(WORD)-1 || num_bloque>bfb.num_bloques ) { Error_SF = ERR_RANGO; return -1; } /* Accede al bloque de datos bfb.tabla[num_bloque] */ { DWORD bloque_datos = bfb.tabla[num_bloque]; DWORD bloque_fisico = DESC.org_datos + (bloque_datos-1)*DESC.tam_bldatos; int i; if ( bloque_datos==0 || bloque_datos>DESC.nbloques_datos ) { Error_SF = ERR_RANGO; return -1; } for (i=0;iDESC.nbloques_datos ) { Error_SF = ERR_RANGO; return -1; } bloque--; BF = DESC.org_mapa + (bloque/DESC.tam_BF); desplaz = bloque%DESC.tam_BF; LeeBloqueFisico(BF,bufer); if (HAY_ERROR) return -1; if (bufer[desplaz]==MAPA_LIBRE) { Error_SF = ERR_LIBRE; return -1; } bufer[desplaz] = MAPA_LIBRE; EscribeBloqueFisico(BF,bufer); free(bufer); return HAY_ERROR ? -1 : 0; } /************************************/ /* Funciones de BFB: implementaci¢n */ /************************************/ static void BFB_inicial (BFB* bfb,int numero) { int i; bfb->estado = BFB_LIBRE; bfb->id = numero; bfb->num_bloques = 0; for (i=0;itabla[i] = 0; } static void BFB_calcula (IFB fichero,DWORD* bloque,WORD* desplaz) { if (fichero==(IFB)-1 || fichero>DESC.num_BFB) Error_SF = ERR_RANGO; else { *bloque = DESC.org_BFB + fichero/DESC.BFBs_por_BF; *desplaz = (fichero%DESC.BFBs_por_BF) * DESC.tam_BFB; } } static void BFB_lee (IFB fichero,BFB* bfb) { DWORD bloque; WORD desplaz; char* bufer = nuevo_bloque(); BFB_calcula(fichero,&bloque,&desplaz); if (HAY_ERROR) goto salir; LeeBloqueFisico(bloque,bufer); if (HAY_ERROR) goto salir; memcpy(bfb,bufer+desplaz,sizeof(BFB)); salir: free(bufer); } static void BFB_escribe (IFB fichero,BFB* bfb) { DWORD bloque; WORD desplaz; char* bufer = nuevo_bloque(); BFB_calcula(fichero,&bloque,&desplaz); if (HAY_ERROR) goto salir; LeeBloqueFisico(bloque,bufer); if (HAY_ERROR) goto salir; memcpy(bufer+desplaz,bfb,sizeof(BFB)); EscribeBloqueFisico(bloque,bufer); salir: free(bufer); } static void BFB_expande (BFB* bfb,WORD num_bloques) { int i; if ( num_bloques+bfb->num_bloques > MAX_BLOQUES ) { Error_SF = ERR_RANGO; return; } for ( i=bfb->num_bloques; inum_bloques+num_bloques; i++ ) { bfb->tabla[i] = ReservaBloqueDatos(); /* Si hay error, se devuelven los bloques ya tomados */ if (HAY_ERROR) { int k; for ( k=bfb->num_bloques; ktabla[k]); bfb->tabla[k] = 0; } Error_SF=ERR_RANGO; return; } } bfb->num_bloques += num_bloques; } void BFB_trunca (BFB* bfb,WORD num_bloques) { int i; if (bfb->num_bloquesnum_bloques; i++) { LiberaBloqueDatos(bfb->tabla[i]); bfb->tabla[i] = 0; if (HAY_ERROR) return; } bfb->num_bloques=num_bloques; } void InformeSFB(void) { /* no hace nada */ }