file.c

Go to the documentation of this file.
00001 /* file.c */
00002 #include "routix/system.h"
00003 #include "string.h"
00004 #include "drivers/fat.h"
00005 #include "routix/paging.h"
00006 #include "routix/kalloc.h"
00007 #include <routix/kstdio.h>
00008 #include "routix/file.h"
00009 #include "routix/task.h"
00010 #include <drivers/floppy.h>
00011 #include <fs/blockcache.h>
00012 #include <error.h>
00013 
00014 #define RUNSTATS 1
00015 
00016 file_opened_t *header_archivos_abiertos;
00017 
00018 extern dev_fat_t dev_fat[0];
00019 
00021 // Funcion auxiliar usada para buscar en la lista enlazada, el file descriptor fd
00022 // en caso de no encontrarse devuelve NULL, en caso contrario devuelve un puntero al nodo correspondiente
00024 
00025 
00026 // Header a una lista enlazada con todos los archivos abiertos por el sistema
00027 file_opened_t *header_archivos_abiertos=NULL;
00028 
00029 // Como abrir_archivo va a retornar un fd, creo una variable dword file_descriptor_actual, la cual va incrementando
00030 // el fd por cada archivo abierto. Es decir, el primer fd que entregaria seria el 1
00031 
00032 dword file_descriptor_actual=1; 
00033 
00034 // La idea es que haya una lista enlazada con todos los archivos abiertos en el sistema (independientemente a que
00035 // cada proceso tengo en su estructura de datos info de los archivos que abrio.
00036 // Cada nodo de la lista, contiene una estructura fat12_entry_ext_t datos, un puntero a un bloque de memoria (que sera
00037 // levantado de disco por la funcion read, y un dword sector_actual que indica a que sector corresponde el bloque
00038 // apuntado por byte *bloque.
00039 // Si bien es ineficiente, para hacer bien claro el manejo, se levantara de disco de a 1 sector por vez.
00040 
00041 
00042 extern task_struct_t *actual;
00043 
00044 int open (char *nombre)
00045 {
00046     word i;
00047     int fd = -1;
00048 
00049 
00050     // Verificar que el proceso tenga algun slot libre para abrir un archivo
00051     for (i=0 ; i < MAX_FILES_POR_TAREA ; i++)
00052                 if ( actual->open_files[i] == NULL ) {
00053                 fd = i;
00054                 break;
00055                 }
00056         
00057     if ( fd < 0 ) {
00058         actual->err_no = EMFILE;
00059                 return -1;      //el proceso posee la maxima cantidad de archivos abiertos, no se puede abrir otro
00060     }
00061     struct file aux;
00062 
00063 /*  Esta funcion me devuelve en que dispositivo (aux.device) y en que file system (aux.fs) se encuentra el archivo
00064     vfs_find(nombre, aux);      
00065     como el file system virtual y el sistema de montajes no esta implementado, completo los valores a mano.
00066 */                      
00067     aux.device = DRIVE_0 ;
00068     aux.fs = FAT12;
00069 
00070     actual->open_files[fd] = (struct file *) malloc (sizeof(struct file));
00071     if ( ! actual->open_files[fd] )
00072                 return -1;
00073 
00074         file_alloc++;
00075     
00076     if ( aux.fs == FAT12 ) 
00077                 if ( open_FAT12(nombre, fd)!=OK ) {
00078                         kprintf("POR ACA....\n");
00079                 free(actual->open_files[fd]);
00080                 actual->open_files[fd] = NULL;
00081                 return -1;
00082         }
00083             
00084     return fd;
00085 }       
00086 
00087 // Abrir un archivo desde un dispositivo FAT12
00088 int open_FAT12 (char *nombre, int fd)
00089 {
00090     if ((dev_fat[0].boot_leido==FALSE) || (dev_fat[0].fat_levantada==FALSE) ) 
00091         if ( init_floppy_fs() != OK ) {
00092             kprintf("No se puede leer disco\n");
00093             return -1;
00094         }
00095     
00096     fat12_entry_ext_t archivo;
00097 
00098     
00099     if ( fat_file_find(nombre , &archivo.fat12_data) == NULL )  {//Archivo no se encuentra o no se puede abrir
00100 kprintf("Cantidad de Mallocs: %d\tFrees: %d\n", num_mallocs, num_frees);
00101                 kprintf("No se encuentra el archivete\n");
00102                 return -1;
00103     }
00104     
00105     actual->open_files[fd]->sectores = archivo.fat12_data.size / SECTOR_SIZE;
00106 
00107     if ( archivo.fat12_data.size % SECTOR_SIZE )            //Si no es un sector justo, aumentarlo en 1
00108         actual->open_files[fd]->sectores++;
00109 
00110     actual->open_files[fd]->offset = 0;
00111     actual->open_files[fd]->offset_rel = 0;
00112     actual->open_files[fd]->sector_origen = archivo.fat12_data.sector + dev_fat[0].root_dir_start + \
00113                 dev_fat[0].root_dir_size - 2;
00114     actual->open_files[fd]->sector_actual = actual->open_files[fd]->sector_origen;
00115 
00116     actual->open_files[fd]->size = archivo.fat12_data.size;
00117     
00118     return OK;
00119 }       
00120 
00121 
00122 
00123 int lseek (int fd, int offset, int donde)
00124 {
00125     
00126     struct file *aux = actual->open_files[fd];
00127 
00128     dword sector_aux;   // Numero de orden del sector (no es el numero del sector en el dispositivo. Toma los valores
00129                         // 0,1,2,3,4,5, etc dependiendo del sector sobre el cual este el offset
00130     if (aux == NULL)
00131                 return -1;
00132 
00133 
00134     if (donde == SEEK_SET) {            //Posicionarse relativo al comienzo
00135       
00136                 aux->sector_actual = aux->sector_origen;    //Apuntar al primer sector (corrigiendolo)
00137                 if (offset < 0) {
00138                     aux->offset = 0;
00139                     return 0;               //Posiciono al origen
00140                 }
00141 
00142                 sector_aux = offset / SECTOR_SIZE;
00143 
00144                 // Recorrer la FAT en busca del sector del proxumo sector
00145                 while ( sector_aux--  ) {
00146                     aux->sector_actual = fat_next_sector(aux->sector_actual);
00147                     if (aux->sector_actual <= 31)       //provisorio
00148                                 return 0;       //El offset esta mas alla del tamaņo del archivo
00149                 }
00150 
00151                 aux->offset = offset;
00152                 aux->offset_rel = offset % SECTOR_SIZE;     //Offset relativo al comienzo del sector actual
00153                 return offset;
00154     }
00155         
00156     else if (donde == SEEK_CUR) {
00157 
00158                 offset = aux->offset + offset;  //Aca obtuve el offset relativo al comienzo
00159                 return lseek(fd, offset , SEEK_SET);        //AMO LA RECURSIVIDAD !!! no puedo creer que despues de escribir
00160     }                                               //tanto codigo repetido e ineficiente, me haya iluminado
00161 
00162         else if (donde == SEEK_END) {
00163                 if (offset > 0) 
00164                     return 0;
00165         
00166                 offset = aux->size + offset;    // Recordar que en este caso el offset seria negativo
00167                 return lseek(fd, offset , SEEK_SET);
00168     }
00169 
00170     else return aux->offset;
00171     
00172 }       
00173 
00174 
00175 
00176 
00177 int close (int fd)
00178 {
00179     struct file *aux;
00180     if ( (aux = actual->open_files[fd])==NULL )
00181                 return -1;
00182     
00183     free(actual->open_files[fd]);
00184     actual->open_files[fd] = NULL;
00185 file_free++;
00186     return fd;
00187 }
00188 
00189 
00190 //ssize_t read (int fd, void *buf, size_t nbytes)
00191 //{
00192 //    size_t len=nbytes;
00193 //    ssize_t aux_len;
00194 //    
00195 //    struct file *aux;     //Apunta a la estructura de archivo abierto
00196 //    
00197 //    if ( (aux=actual->open_files[fd] )==NULL)     //Archivo no esta abierto
00198 //              return -1;
00199 //
00200 //    //Corregir len en caso de que sea mayor que el tamaņo del archivo
00201 //    if ( (aux->size) < (len + aux->offset) )
00202 //              len = (aux->size) - aux->offset;
00203 //
00204 //    aux_len = len;
00205 //    
00206 //    char *bloque;   //Puntero a bloque que contiene el sector ( mantenido por floppy_cache)
00207 //
00208 //    //Esta variable me indica a cuantos bytes estoy del final del sector actual
00209 //    word remanente = SECTOR_SIZE - aux->offset_rel;
00210 //    word desplaz=0;
00211 //    
00212 //
00213 //    //Este ciclo va a ser el encargado de ir leyendo el sector que corresponde, y poniendolo en el buffer (buf)
00214 //    while (len > 0) {
00215 //        bloque = floppy_cache( aux->sector_actual );
00216 //        if (bloque == NULL) //Si no se pudo levantar al cache ese bloque...
00217 //                  return -1;
00218 //
00219 //              if (len <= remanente)   //Si lo que voy a leer es menor que lo que falta para el final del sector
00220 //                  aux_len = len;      //no es necesario que cargue lea desde el disco (o desde el cache) es sector siguiente
00221 //
00222 //              else aux_len = remanente;   //Si en cambio, lo que tengo que leer es mayor a lo que queda de este sector
00223 //                                  //voy a tener que ir cargando del disco (o del cache) otros sectores hasta completar
00224 //                                  //el total
00225 //
00226 //              //Poner en el buffer del llamante lo que lei del bloque actual
00227 //              memcpy( (buf + desplaz), (bloque + aux->offset_rel), aux_len);
00228 //      
00229 //              //Corregir el offset
00230 //              lseek(fd, aux_len, SEEK_CUR );
00231 //              desplaz = desplaz + aux_len;
00232 //              len = len - aux_len;
00233 //        remanente = SECTOR_SIZE - aux->offset_rel;
00234 //    }
00235 //    
00236 //      return desplaz;
00237 //}
00238 
00239 ssize_t read (int fd, void *buf, size_t nbytes)
00240 {
00241     size_t len=nbytes;
00242     ssize_t aux_len;
00243     
00244     struct file *aux;       //Apunta a la estructura de archivo abierto
00245 
00246 #ifdef RUNSTATS
00247                 long long counter;
00248 
00249                 if ( getvar("debugread") == 2 ) {
00250                         rdtscl(counter);
00251                 }
00252 #endif
00253         
00254     
00255     if ( (aux=actual->open_files[fd] )==NULL)       //Archivo no esta abierto
00256                         return -1;
00257 
00258     //Corregir len en caso de que sea mayor que el tamaņo del archivo
00259     if ( (aux->size) < (len + aux->offset) )
00260                         len = (aux->size) - aux->offset;
00261 
00262     aux_len = len;
00263     
00264     //Esta variable me indica a cuantos bytes estoy del final del sector actual
00265     word remanente = SECTOR_SIZE - aux->offset_rel;
00266     word desplaz=0;
00267     
00268 
00269     //Este ciclo va a ser el encargado de ir leyendo el sector que corresponde, y poniendolo en el buffer (buf)
00270     while (len > 0) {
00271                         
00272                                 /*
00273         bloque = floppy_cache( aux->sector_actual );
00274         if (bloque == NULL) //Si no se pudo levantar al cache ese bloque...
00275                     return -1;
00276                                 */
00277                         
00278                                 //setvar("debugcache",1);
00279                                 //setvar("debugfloppy",1);
00280                                 if ( cache_read(fd0,aux->sector_actual,aux->offset_rel,buf+desplaz,aux_len) == -1 )
00281                                         return -1;
00282                                                 
00283 
00284                 if (len <= remanente)   //Si lo que voy a leer es menor que lo que falta para el final del sector
00285                     aux_len = len;      //no es necesario que cargue lea desde el disco (o desde el cache) es sector siguiente
00286 
00287                 else aux_len = remanente;   //Si en cambio, lo que tengo que leer es mayor a lo que queda de este sector
00288                                     //voy a tener que ir cargando del disco (o del cache) otros sectores hasta completar
00289                                     //el total
00290 
00291                 //Poner en el buffer del llamante lo que lei del bloque actual
00292                 //memcpy( (buf + desplaz), (bloque + aux->offset_rel), aux_len);
00293         
00294                 //Corregir el offset
00295                 lseek(fd, aux_len, SEEK_CUR );
00296                 desplaz = desplaz + aux_len;
00297                 len = len - aux_len;
00298         remanente = SECTOR_SIZE - aux->offset_rel;
00299     }
00300 
00301 #ifdef RUNSTATS
00302   if ( getvar("debugread") == 2 ) {
00303                 long long int counterfinal;
00304                 rdtscl(counterfinal);
00305                 kprintf("R0x%llx ",counterfinal-counter);
00306         }       
00307 #endif
00308                 
00309 
00310         return desplaz;
00311 }
00312 

Generated on Sun May 30 18:38:34 2004 for Routix OS by doxygen 1.3.6