/************************************************************************/ /* */ /* SFBASICO.C */ /* ========== */ /* */ /* Implementación de un sistema de ficheros muy simple, */ /* para realizar prácticas de diseño de sistemas operativos. */ /* */ /* Características: */ /* */ /* - Sólo un directorio raíz */ /* - Ficheros de tamaño fijo */ /* - Transferencias por bloques (no por bytes) */ /* - Si se borra un fichero, los bloques ocupados */ /* no quedan disponibles */ /* */ /* Versión 2.0b */ /* */ /* © José Miguel Santos, Carmelo Rubén García, Gabino Padrón, */ /* 1996-97-98 */ /* */ /************************************************************************/ /* Ficheros cabeceras de la aplicación */ #include "sfbasico.h" /* Interfaz pública de este módulo */ #include "sffisico.h" /* Funciones de acceso a disco */ #include "errores.h" /* Códigos de error */ #include "descr.h" /* Descriptor de sistema de ficheros y superbloque */ #include "bfb.h" /* Estructura Bloque de Fichero Básico (BFB) */ /* Ficheros cabeceras para las bibliotecas del C */ #include #include #include /* En esta implementación, todos los ficheros tienen longitud fija */ /* Habrá que reformarlo para permitir longitudes variables */ #define NUM_BLOQUES_FICHERO 4 /* Macro para conocer si hay un disco montado */ /* Se utiliza por todo el código */ #define MONTADO \ { Error_SF=ERR_SINERROR; \ if (DESC.montado==0) \ { Error_SF=ERR_INACTIVO; return -1; } \ } /************************************************************************/ /* */ /* FUNCIONES PÚBLICAS DEL MÓDULO */ /* IMPLEMENTACIÓN */ /* */ /************************************************************************/ /* Reserva espacio para un fichero */ /* En esta implementación, reserva un número fijo de bloques */ static DWORD ReservaEspacio (void); /* Función FormateaSFB (nombre_fichero,args[]) */ /* */ /* Da formato a un disco, cuya ruta UNIX es el parámetro */ /* "nombre_fichero". "args" es un vector de cadenas de */ /* caracteres que contienen los parámetros para el formato.*/ /* Después del último parámetro, debería venir una cadena */ /* nula. */ /* */ /* En esta implementación básica, se pasan dos parámetros: */ /* */ /* args[0] - Cantidad de BFBs */ /* args[1] - Tamaño de bloque de datos */ /* Funciones secundarias del formato */ /* para dar formato a los BFB y los bloques de datos */ static void FormatoBFBs(void); static void FormatoBloquesDatos(void); int FormateaSFB ( const char* nombre_fichero, const char* args[] ) { DWORD nbloques_BFB; /* No puede haber un disco montado mientras se formatea */ if (DESC.montado==1) { Error_SF=ERR_MONTADO; return -1; } /* Lee los parámetros del formateo */ if ( args[0]==0 || args[1]==0 || args[2]!=0 ) { Error_SF = ERR_PARAMETRO; return -1; } DESC.num_BFB = atoi(args[0]); DESC.tam_bloque_datos = atoi(args[1]); if ( DESC.num_BFB<=0 || DESC.tam_bloque_datos<=0 ) { Error_SF = ERR_PARAMETRO; return -1; } /* Monta el disco físico y recoge los parámetros del disco */ Error_SF = ERR_SINERROR; MontaDisco(nombre_fichero,0); LeeDatosDisco (&DESC.tam_bloque_fisico, &DESC.num_bloques_fisicos); if (HAY_ERROR) { return -1; } /* Comprueba si hay espacio suficiente: */ /* - el BFB tiene que caber en un bloque físico */ /* - los BFBs no deben ocupar todo el disco */ /* - debería haber bloques de datos suficientes */ /* para crear todos los ficheros */ nbloques_BFB = (DESC.num_BFB*TAM_BFB)/(DESC.tam_bloque_fisico)+1; if ( DESC.tam_bloque_fisico < TAM_BFB || nbloques_BFB >= DESC.num_bloques_fisicos || DESC.num_bloques_fisicos < DESC.tam_bloque_datos*DESC.num_BFB + 2 ) { DesmontaDisco(); Error_SF = ERR_ESPACIO; return -1; } /* Calcula tamaños y límites */ DESC.org_BFB = 1; DESC.org_datos = nbloques_BFB+1; DESC.nbloques_datos = (DESC.num_bloques_fisicos-DESC.org_datos) / DESC.tam_bloque_datos; assert(DESC.nbloques_datos>0); DESC.primer_bloque_libre = 0; DESC.ultimo_bloque_datos = DESC.nbloques_datos-1; /* Si todo está correcto, */ /* escribe la nueva información en el superbloque del disco */ EscribeSuperbloque(&DESC); DesmontaDisco(); /* Se monta el nuevo sistema, para inicializar bloques, etc. */ MontaSFB(nombre_fichero,0); /* Da formato a los bloques de fichero básicos */ FormatoBFBs(); /* Da formato a los bloques de datos */ /* (en esta implementación, no se hace nada con ellos) */ FormatoBloquesDatos(); /* Desmonta el disco y retorna */ return DesmontaSFB(); } /* FormateaSFB() */ /* Implementación de las funciones secundarias */ static void FormatoBFBs (void) { int indice; for ( indice=0; indice=NUM_BLOQUES_FICHERO ) { Error_SF = ERR_RANGO; return -1; } /* Lee el BFB correspondiente */ BFB_recoge (&bfb,fichero); if (bfb.estado==BFB_LIBRE) { Error_SF = ERR_LIBRE; return -1; } /* Accede al bloque de datos */ { DWORD bloque_datos = bfb.bloque + num_bloque; DWORD bloque_fisico = DESC.org_datos + bloque_datos*DESC.tam_bloque_datos; int nbloque; if ( bloque_datos > DESC.nbloques_datos ) { Error_SF = ERR_RANGO; return -1; } /* Como un bloque de datos puede consistir en varios bloques físicos, se entra en un bucle de transferencias */ for ( nbloque=0; nbloque= DESC.ultimo_bloque_datos - NUM_BLOQUES_FICHERO ) { Error_SF = ERR_ESPACIO; return CHUNGO; } /* Mueve el apuntador a los bloques libres*/ bloque_inicial = DESC.primer_bloque_libre; DESC.primer_bloque_libre += NUM_BLOQUES_FICHERO; /* Por seguridad, se actualiza el superbloque */ EscribeSuperbloque (&DESC); if (HAY_ERROR) return CHUNGO; return bloque_inicial; } /* ReservaEspacio() */