Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

ext2.c

Go to the documentation of this file.
00001 /*!     \file fs/ext2/ext2.c
00002  *      \brief ext2 file system.
00003  *      \author
00004  *              Filippo Brogi
00005  *      \note Copyright (©) 2003
00006  *              Filippo Brogi
00007  *      \date Last update:
00008  *              2003-09-30 by Andrea Righi
00009  *                      init_ext2() now returns a boolean value.\n
00010  */
00011 
00012 #include <const.h>
00013 #include <string.h>
00014 
00015 #include <arch/i386.h>
00016 #include <arch/mem.h>
00017 
00018 #include <kernel/Ide.h>
00019 #include <kernel/IdeDebug.h>
00020 #include <kernel/IdeTimer.h> // must remove
00021 #include <kernel/IdeLow.h>   // must remove
00022 #include <kernel/keyboard.h>
00023 #include <kernel/kmalloc.h>
00024 #include <kernel/video.h>
00025 
00026 #include <kernel/ext2.h>
00027 
00028 #define min(a,b) (((a)<(b)) ? (a) : (b))
00029 
00030 struct super_block *super; // puntatore al superblocco
00031 // contenuto di un blocco su disco si usa come variabile ausiliaria nelle func
00032 byte *data_block;
00033 // codice errore lettura da disco
00034 int err;
00035 
00036 
00037 bool mount_ext2 = FALSE; // TRUE se il montaggio del file system é andato a buon fine
00038 char path_ext2[1024];
00039 int level;
00040 
00041 
00042 
00043 word spb,bpg,gdpb,ipb,sbpos;
00044 dword number_of_groups; // numero gruppi di blocchi nel file
00045 dword dim_block,dim_ptr,dim_frag; // dimensione del blocco dati e puntatore
00046 dword inodes_per_block; // numero inode per blocco
00047 dword dir_entries_per_block; // numero directory entries per block
00048 
00049 
00050 
00051 //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
00052 
00053 //                  FUNZIONI AUSILIARIE
00054 
00055 //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
00056 
00057 // TODO: il 63 va letto dalle partition table del MBR
00058 dword blocco_to_LBA(dword num_block){
00059         return(63 +(num_block*spb));
00060 
00061 }
00062 
00063 
00064 void stampa_bg(struct group_descriptor *bg){
00065 
00066         kprintf ("\n\n\rid primo blocco bitmap blocchi: %u",bg->bg_block_bitmap);
00067         kprintf ("\n\rid primo blocco bitmap inode: %u",bg->bg_inode_bitmap);
00068         kprintf ("\n\rid primo blocco tabella inode: %u",bg->bg_inode_table);
00069         kgetchar();
00070 }
00071 
00072 
00073 /*
00074     lettura del descrittore di gruppo. In generale é allocato
00075     consecutivamente al blocco del disco contenente il super
00076     blocco, cioè blocco 1 della partizione
00077 */
00078 
00079 
00080 // il primo descrittore di gruppo parte da 0
00081 bool ReadGroupDescriptor(dword grp,struct group_descriptor* data){
00082 
00083     if (grp>number_of_groups)
00084     {
00085         return FALSE;
00086     }
00087 
00088     return TRUE;
00089 }
00090 
00091 
00092 //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
00093 
00094 //                  GESTIONE DESCRITTORI DI GRUPPO
00095 
00096 //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
00097 
00098 // struttura tabella dei descrittori di gruppo
00099 struct group_descriptor  *group_desc_table;
00100 
00101 
00102 
00103 //------------ Inizializzazione Tabella Descrittori di gruppo ------------//
00104 bool init_group_desc_table(){
00105         if(!(group_desc_table = (struct group_descriptor*)kmalloc(sizeof(struct group_descriptor)*number_of_groups)))
00106         {
00107                 kprintf ("\n\rImpossible create group descriptor table: out of memory");
00108                 return FALSE;
00109         }
00110         memset(group_desc_table,0,sizeof(struct group_descriptor)*number_of_groups);
00111 
00112         data_block = kmalloc(dim_block);
00113         memset(data_block,0,dim_block);
00114 
00115 
00116         if ( (err = ReadSectorsLba(0,(int64_t)blocco_to_LBA(sbpos),spb,(word *)data_block,TRUE)) )
00117         {
00118                 // si stampa l'errore relativo al fallimento lettura disco
00119                 kprintf ("\n\rerror reading group descriptor block");
00120                 ShowIdeErrorMessage(err,TRUE);
00121                 return FALSE;
00122         }
00123         memcpy(group_desc_table,data_block, sizeof(struct group_descriptor)*number_of_groups);
00124 
00125         kfree(data_block);
00126         
00127         return TRUE;
00128 
00129 }
00130 
00131 
00132 struct group_descriptor * get_group_desc(dword grp){
00133 
00134         if(grp>number_of_groups)
00135         {
00136                 kprintf ("\n\rInvalid group descriptor number");
00137                 return NULL;
00138         }
00139         return(&group_desc_table[grp]);
00140 }
00141 
00142 //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
00143 
00144 //                      GESTIONE DEGLI INODE
00145 
00146 //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
00147 
00148 // struttura tabella inode
00149 struct i_node_tab
00150 {
00151         dword i_node_n; // numero dell'inode
00152         struct i_node inode; // informazioni generali inode
00153         // parametri per la gestione tabella inode
00154         word ref;
00155 } *inode_table;
00156 
00157 word dim_inode_table;
00158 word free_inode; //numero elementi della tabella inode liberi
00159 
00160 // stampa su video il contenuto di un inode
00161 
00162 void stampa_i(struct i_node *ino){
00163 int i;
00164 
00165         kprintf ("\n\n\rtipo inode: %X",ino->i_mode & MODE_MASK);
00166         kprintf ("\n\ruser id associato al file: %u",ino->i_uid);
00167         kprintf ("\n\rfile size (byte): %u",ino->i_size);
00168         kprintf ("\n\rnumero blocchi riservati al file: %u",ino->i_blocks);
00169         for (i=0;i<15;i++)
00170         {
00171                 kprintf ("\n\rblock[%u]: %u",i,ino->i_block[i]);
00172         }
00173         kgetchar();
00174 }
00175 
00176 // dato un inode mi dice dove é il blocco in cui si trova (0 errore lettura)
00177 dword Inode2Block(dword ino){
00178         struct group_descriptor* group_desc;
00179 
00180         if (!ino || ino>super->s_inodes_count)
00181         {
00182                 kprintf ("\n\rinvalid inode number");
00183                 return 0;
00184         }
00185 
00186         // il primo inode parte da 1
00187         ino--;
00188 
00189 
00190         // si cerca il descrittore del gruppo di blocchi in cui si trova l'inode
00191         if (!(group_desc = get_group_desc(ino/super->s_inodes_per_group)))
00192         {
00193                 kprintf ("\n\rNot group desc per inode");
00194                 return 0;
00195         }
00196 
00197         ino %= super->s_inodes_per_group;
00198 
00199         // bg_inode_table punta al primo blocco tabella inode
00200         //kprintf("\n\r%u",group_desc->bg_inode_table+ino/ipb);
00201         return (group_desc->bg_inode_table+ino/ipb);
00202 }
00203 
00204 
00205 // lettura di un inode dal disco
00206 bool ReadInode(dword ino, struct i_node* data){
00207         dword ino_block = Inode2Block(ino);
00208         if (!ino_block)
00209         {
00210                 kprintf ("\n\rerror finding inode block");
00211                 return FALSE;
00212         }
00213     
00214         data_block = kmalloc(dim_block);
00215         memset(data_block,0,dim_block);
00216         //kprintf("\n\rino_block: %u",ino_block);
00217         // TODO : si deve leggere in data_block il blocco del disco che contiene l'inode
00218         if ( (err = ReadSectorsLba(0,(int64_t)blocco_to_LBA(ino_block),spb,(word *)data_block,TRUE)) )
00219         {
00220                 // errore nella lettura del blocco relativo all'inode
00221                 kprintf ("\n\rerror reading inode block");
00222                 ShowIdeErrorMessage(err,TRUE);
00223                 return FALSE;
00224         }
00225         // si copia l'inode relativo
00226         memcpy(data,&data_block[((ino-1)%ipb)*sizeof(struct i_node)],sizeof(struct i_node));
00227         //stampa_i(data);
00228         kfree(data_block);
00229         return TRUE;
00230 }
00231 
00232 //--------------- Inizializzazione Tabella Inode ---------------//
00233 bool init_inode_table(){
00234         int i;
00235         // la cache degli inode può contenere il 1% degli inode su disco
00236         dim_inode_table = super->s_inodes_count / 100;
00237         if(!(inode_table = (struct i_node_tab*)kmalloc(sizeof(struct i_node_tab)*dim_inode_table)))
00238         {
00239                 kprintf("\n\rImpossible create inode table: out of memory");
00240                 return FALSE;
00241         }
00242         memset(inode_table,0,sizeof(struct i_node_tab)*dim_inode_table);
00243         for (i = 0;i < dim_inode_table; i++)
00244         {
00245                 inode_table[i].i_node_n = 0;
00246                 inode_table[i].ref = 0;
00247         }
00248         // tutti gli elementi della tabella sono liberi
00249         free_inode = dim_inode_table;
00250         //kprintf("\n\rtabella inode creata correttamente");
00251         return TRUE;
00252 }
00253 
00254 //---------------- Cerca elemento LRU -----------------------//
00255 int inode_LRU(){
00256         word lru = 0;
00257         int i;
00258 
00259         // l'elemento cercato é quello meno referenziato negli ultimi
00260         // 16 riferimenti in memoria, la variabile ref é a 16 bit
00261 
00262         for (i = 1;  i<dim_inode_table; i++)
00263                 if (inode_table[i].ref < inode_table[lru].ref)
00264                 {
00265                         lru = i;
00266                 }
00267         //kprintf("\n\rci sono passato lru: %u %u",lru,inode_table[lru].ref);
00268         return (lru);
00269 
00270 }
00271 
00272 
00273 //--------------- Cerca inode e restituisce la posizione -------------------//
00274 
00275 struct i_node *get_inode(dword i_node_number){
00276         int i;
00277         int pos_inode = -1;
00278         struct i_node new_inode;
00279 
00280         // controlliamo la validità dell'inode
00281         if (!i_node_number || i_node_number>super->s_inodes_count)
00282         {
00283                 kprintf("\n\rInvalid inode number");
00284                 return(NULL);
00285         }
00286 
00287         //kprintf("\n\r inode_number: %u",i_node_number);
00288 
00289         // si cerca se l'inode é presente nella tabella
00290         for (i=0; i < (dim_inode_table-free_inode); i++)
00291                 if (inode_table[i].i_node_n == i_node_number)
00292                 {
00293                         // memorizza posizione inode
00294                         pos_inode = i;
00295                         break;
00296                 }
00297 
00298         if (pos_inode == -1)
00299         {
00300                 // l'elemento non é presente nella cache dobbiamo reperirlo su disco
00301                 ReadInode(i_node_number,&new_inode);
00302                 //stampa_i(&new_inode);
00303 
00304                 if (free_inode>0) // ci sono posizioni non utilizzate
00305                 {
00306                         pos_inode = dim_inode_table - free_inode;
00307                         free_inode--; // decremento numero posizioni libere
00308                 }
00309                 else
00310                 {
00311                         pos_inode = inode_LRU();
00312                 }
00313                 inode_table[pos_inode].inode = new_inode; // inserisco nella tabella
00314                 inode_table[pos_inode].i_node_n = i_node_number; // inserisco numero inode
00315                 inode_table[pos_inode].ref = 0; // azzero il riferimento
00316         }
00317 
00318         // aggiornamento dei riferimenti
00319         for (i=0; i < (dim_inode_table-free_inode); i++)
00320         {
00321                 inode_table[i].ref = inode_table[i].ref >> 1;
00322                 if (i == pos_inode)
00323                 {
00324                         inode_table[i].ref = inode_table[i].ref | 0x8000;
00325                 }
00326         }
00327 
00328         //kprintf ("\n\rinode inserito nella tabella e restituito");
00329         //kprintf ("\n\rpos_inode %u",pos_inode);
00330         //kprintf ("\n\rinode number %u",inode_table[pos_inode].i_node_n);
00331         //stampa_i(&inode_table[pos_inode].inode);
00332         // restituisco puntatore all'inode cercato
00333         return (&inode_table[pos_inode].inode);
00334 
00335 }
00336 
00337 //############################################################
00338 
00339 //              GESTIONE DEI FILE
00340 
00341 //############################################################
00342 
00343 dword * ptr_dir;
00344 
00345 // funzione che permette di verificare se é un file regolare
00346 bool isFile(struct i_node* ino){
00347 
00348         if ((ino->i_mode & MODE_MASK)==MODE_FILE)
00349         {
00350                 return TRUE;
00351         }
00352         return FALSE;
00353 }
00354 
00355 // funzione che permette di determinare se é un fast symbolic link
00356 bool isFastSymbolicLink(struct i_node* ino){
00357 
00358         if ((ino->i_mode & MODE_MASK)==MODE_LINK)
00359         {
00360                 return TRUE;
00361         }
00362         return FALSE;
00363 }
00364 
00365 
00366 bool ReadIndirect1(dword* dst, dword* cnt, dword blk) {
00367         dword* r1;
00368         int m;
00369         // controlliamo se ci sono blocchi puntati indirettamente
00370         if(*cnt<=0)
00371         {
00372                 return TRUE;
00373         }
00374 
00375         //kprintf("\n\r read indirect 1");
00376         /* dword* */ r1 = (dword *)kmalloc(dim_ptr * sizeof(dword));
00377         memset(r1,0,dim_ptr * sizeof(dword));
00378         // si deve leggere il blocco dati puntato indirettamente
00379 
00380         if ( (err = ReadSectorsLba(0,(int64_t)blocco_to_LBA(blk),spb,(word *)r1,TRUE)) )
00381         {
00382                 kprintf ("\n\rerror reading indirect addressing");
00383                 ShowIdeErrorMessage(err,TRUE);
00384                 kfree(r1);
00385                 return FALSE;
00386         }
00387 
00388         /*int*/ m = min(*cnt,dim_ptr);
00389         // se cnt < dim_ptr vuol dire che non tutti gli indici
00390         // dei blocchi del blocco indice sono occupati dal file
00391         memcpy(dst,r1,m<<2);
00392         kfree(r1);
00393         *cnt -= m;
00394         dst += m;
00395         return TRUE;
00396 }
00397 
00398 bool ReadIndirect2(dword* dst, dword* cnt, dword blk) {
00399         int i;
00400         dword* r2;
00401         if(*cnt<=0)
00402         {
00403                 return TRUE;
00404         }
00405 
00406         //kprintf("\n\r read indirect 2");
00407         /*dword* */ r2 = (dword *)kmalloc(dim_ptr * sizeof(dword));
00408         if ( (err = ReadSectorsLba(0,(int64_t)blocco_to_LBA(blk),spb,(word *)r2,TRUE)) )
00409         {
00410                 kprintf ("\n\rerror reading second level indirect addressing");
00411                 ShowIdeErrorMessage(err,TRUE);
00412                 kfree(r2);
00413                 return FALSE;
00414         }
00415 
00416         for (i = 0; *cnt && i<dim_ptr; i++)
00417                 if(!ReadIndirect1(dst,cnt,r2[i]))
00418                         {
00419                                 kfree(r2);
00420                                 return FALSE;
00421                         }
00422 
00423         kfree(r2);
00424         return TRUE;
00425 }
00426 
00427 // apertura di un file sia esso directory, link o file
00428 
00429 bool Open_File (struct i_node* ino,word tipo_file){
00430 
00431         int i;
00432         char * fsl;
00433         dword n,m;
00434         dword *ptr;
00435         if (ino == NULL)
00436         {
00437                 // si é verificato un errore nessun inode specificato
00438                 kprintf ("\n\rInvalid inode\n\r");
00439                 return FALSE;
00440         }
00441 
00442         // check di validità dell'inode
00443         if (!(tipo_file == MODE_DIR || tipo_file == MODE_FILE || tipo_file == MODE_LINK))
00444         {
00445                 // tipo non valido
00446                 kprintf ("\n\rInvalid file type\n\r");
00447                 return FALSE;
00448         }
00449 
00450         // TODO : fast symbolic link
00451         if ((tipo_file==MODE_LINK) && (ino->i_size<64))
00452         {
00453                 kprintf ("\n\rFast symbolic link path : ");
00454 
00455                 fsl = (byte *)kmalloc(sizeof(struct i_node));
00456                 memset(fsl,0,sizeof(struct i_node));
00457                 memcpy(fsl,ino,sizeof(struct i_node));
00458                 for (i=39;i<(ino->i_size+39);i++)
00459                         kprintf("%c",fsl[i]);
00460                 kprintf("\n\n\r");
00461                 kfree(fsl);
00462                 ptr_dir = (dword *)kmalloc(0);
00463                 return FALSE;
00464         }
00465 
00466         // lettura di tutti i puntatori ai blocchi dati del file
00467 
00468         // numero di blocchi che compongono il file
00469         /*dword*/ n = (ino->i_size+dim_block-1)/dim_block;
00470 
00471         // si linearizzano tutti i puntatori ai blocchi dati in modo
00472         // tale da semplificare la struttura gerarchica ed ottimizzare
00473         // l'accesso ai blocchi dati veri e propri
00474         ptr_dir = (dword *)kmalloc(n * sizeof(dword));
00475         memset(ptr_dir,0,n * sizeof(dword));
00476 
00477         // scorre l'area di memoria 32 bit alla volta
00478         /*dword * */ptr = (dword *)ptr_dir;
00479 
00480         // i primi 12 blocchi sono indirizzati direttamente
00481         /*dword*/ m = (n<12) ? n : 12;
00482 
00483         // memcpy copia byte per byte perciò m<<2
00484         if (m) memcpy(ptr,ino->i_block,m<<2);
00485 
00486         //kprintf("\n\rstampo ptr:%u n:%u m:%u",ptr_dir[0],n,m);
00487         //kgetchar();
00488         // blocchi puntati indirettamente
00489         n-=m;
00490         // ptr avanza per indirizzare la memoria contenente i blocchi indiretti
00491         ptr += m;
00492         // se ci sono blocchi indiretti si aprono
00493         if (!ReadIndirect1(ptr,&n,ino->i_block[12]))
00494         {
00495                 //kprintf ("\n\rind1");
00496                 kfree(ptr_dir);
00497                 return FALSE;
00498         }
00499         // indirizzamento indiretto doppio
00500         if (!ReadIndirect2(ptr,&n,ino->i_block[13]))
00501         {
00502                 //kprintf ("\n\rind2");
00503                 kfree(ptr_dir);
00504                 return FALSE;
00505         }
00506         // indirizzamento indiretto triplo
00507         if(n)
00508         {
00509                 //kprintf ("\n\rind3");
00510                 dword* r3 = (dword *)kmalloc(dim_ptr * sizeof(dword));
00511                 // TODO : lettura indirizzamento triplo
00512                 if( (err = ReadSectorsLba(0,blocco_to_LBA(ino->i_block[14]),spb,(word *)r3,TRUE)) )
00513                 {
00514                         kprintf ("\n\rerror reading third level indirect addressing");
00515                         ShowIdeErrorMessage(err,TRUE);
00516                         kfree(r3);
00517                         return FALSE;
00518                 }
00519 
00520                 // TODO : ricontrollare la definizione di i indice
00521                 for(i = 0; n && i<dim_ptr; i++)
00522                         if(!ReadIndirect2(ptr,&n,r3[i]))
00523                         {
00524                                 kfree(ptr_dir);
00525                                 kfree(r3);
00526                                 return FALSE;
00527                         }
00528                 kfree(r3);
00529         }
00530 
00531     return TRUE;
00532     // a questo punto ptr_dir contiene il valore dei puntatori ai blocchi
00533     // del file aperto
00534 }
00535 
00536 
00537 
00538 
00539 
00540 //çççççççççççççççççççççççççççççççççççççççççççççççççççççççççççç
00541 
00542 //              GESTIONE DELLE DIRECTORY
00543 
00544 //çççççççççççççççççççççççççççççççççççççççççççççççççççççççççççç
00545 
00546 // variabili per gestire gli elementi delle directory
00547 word count_dir; // numero elementi della dir
00548 char** ext2_file_name = NULL; // filename
00549 dword* inode_dir = NULL; // inodes
00550 byte* file_type_dir = NULL; //file type
00551 char* text = NULL; // ext2_file_name[] punta dentro la stringa di caratteri
00552 char* name = NULL;
00553 
00554 
00555 // elementi che si usano per il backup della memoria
00556 char path_ext2_backup[1024];
00557 int level_backup;
00558 dword ino_dir_backup,ino_current_dir;
00559 
00560 
00561 // funzione che permette di verificare se é un file
00562 bool isDir(struct i_node* ino){
00563 
00564         if ((ino->i_mode & MODE_MASK)==MODE_DIR)
00565         {
00566                 return TRUE;
00567         }
00568         return FALSE;
00569 }
00570 
00571 // dato il nome trova l'inode (0 errore)
00572 dword FindFile(char* cmp){
00573         int i;
00574 
00575         for (i=0;i<count_dir;i++)
00576                 if (!strcmp(cmp,ext2_file_name[i]))
00577                 {
00578                         return inode_dir[i];
00579                 }
00580         return 0;
00581 }
00582 
00583 
00584 // Apertura di una directory dato l'inode relativo, FALSE = errore
00585 bool Open_Dir(struct i_node* inode){
00586 
00587         byte *ptr_block;
00588         dword block_dir; // blocchi che compongono la directory
00589         //dword *ptr_dir; // puntatori blocchi disco contenenti la directory
00590         byte *tmp; // memorizza il contenuto della direcotry
00591         int i,len,idx;
00592         struct dir_ff *dir;
00593 
00594 
00595         //controlliamo se si tratta effettivamente di una directory
00596 
00597         if (!(isDir(inode) || isFastSymbolicLink(inode)))
00598         {
00599                 return FALSE;
00600         }
00601 
00602         // si restituisce la memoria allocata per i campi se già utilizzati
00603         // if (name != NULL)
00604         if (ext2_file_name != NULL)
00605         {
00606                 kfree(inode_dir);
00607                 kfree(file_type_dir);
00608                 kfree(text);
00609                 kfree(ext2_file_name);
00610         }
00611 
00612         // se tutto va bene si procede all'apertura memorizzando i puntatori
00613         // ai blocchi dati nell'area di memoria puntata da ptr_dir
00614         if (!(Open_File(inode,inode->i_mode & MODE_MASK)))
00615         {
00616                 return FALSE;
00617         }
00618 
00619 
00620         // dimensione in blocchi della directory
00621         block_dir = (inode->i_size + dim_block - 1)/dim_block;
00622 
00623         // inserimento nella sezione di memoria tmp dei dati relativi alla directory
00624         tmp = (byte *)kmalloc(inode->i_size);
00625         memset(tmp,0,inode->i_size);
00626 
00627 
00628         //punta all'inizio dell'area di memoria tmp
00629         ptr_block = (byte *)tmp;
00630 
00631         //memset(ptr_block,0,dim_block);
00632         for (i = 0; i<block_dir;i++)
00633         {
00634                 //kprintf("\n\rptr_dir[%u]: %u",i,ptr_dir[i]);
00635                 if ( (err = ReadSectorsLba(0,(int64_t)blocco_to_LBA(ptr_dir[i]),spb,(word *)ptr_block,TRUE)) )
00636                 {
00637                         kprintf ("\n\rError reading data block");
00638                         ShowIdeErrorMessage(err,TRUE);
00639                         kfree(ptr_dir);
00640                         kfree(tmp);
00641                         return FALSE;
00642                 }
00643                 ptr_block += dim_block;
00644         }
00645 
00646         kfree(ptr_dir);
00647 
00648 
00649         // passo 1 : conteggio elementi della directory
00650 
00651         count_dir = 0; // memorizza il numero di elementi della dir
00652         len = 0;
00653         // i si incrementa della dimensione degli elementi della directory
00654         // len si incrementa della lunghezza degli elementi +1 per il fine stringa
00655         // dir punta ad ogni passo alla sequenza di byte di ogni elemento della dir
00656         for (i = 0; i<inode->i_size; )
00657         {
00658                 dir = (struct dir_ff*)&tmp[i];
00659                 if (dir->inode) // se uguale a zero vuol dire non utilizzato
00660                 {
00661                         //TODO: nel caso in cui non si stampino i fsl
00662                         count_dir++;
00663                         len += dir->name_len + 1;
00664                 }
00665                 i += dir->rec_len;
00666         }
00667 
00668         // vettore che contiene gli inode dei file nella directory
00669         inode_dir = (dword *)kmalloc(count_dir * sizeof(dword));
00670         memset(inode_dir,0,count_dir * sizeof(dword));
00671         // vettore che contiene il tipo dei file nella directory
00672         file_type_dir = (byte *)kmalloc(count_dir);
00673         memset(file_type_dir,0,count_dir);
00674         // nome dei file degli elementi della directory
00675         // *** Andrea Righi 2003-10-03 *********************************//
00676         // name = (char *)kmalloc(count_dir);
00677         // memset(name,0,count_dir);
00678         // ext2_file_name = &name;
00679         //**************************************************************//
00680         ext2_file_name = kmalloc(count_dir*sizeof(char *));
00681 
00682         text = (char *)kmalloc(len);
00683         memset(text,0,len);
00684 
00685         // secondo passo si registrano gli elementi
00686         idx = 0;
00687         for (len = i = 0;i<inode->i_size;)
00688         {
00689                 dir = (struct dir_ff*)&tmp[i];
00690                 // si memorizzano gli indirizzi degli inode degli elementi
00691                 if (dir->inode)
00692                 {
00693                         inode_dir[idx] = dir->inode;
00694                         file_type_dir[idx] = dir->file_type;
00695                         // copia dell'elemento di memoria
00696                         memcpy(&text[len],dir->name,dir->name_len);
00697                         // si azzera l'elemento dopo il nome
00698                         text[len+dir->name_len] = '\0';
00699                         //punta al corrispondente nome di file
00700                         ext2_file_name[idx++] = &text[len];
00701                         len += dir->name_len + 1;
00702                 }
00703                 i += dir->rec_len;
00704         }
00705 
00706         // si restituisce la memoria occupata da tmp
00707         kfree(tmp);
00708 
00709         return TRUE;
00710 }
00711 
00712 
00713 /**************************************************************************
00714 *
00715 *           Procedure che definiscono comandi della shell per Ext2
00716 *
00717 ***************************************************************************/
00718 
00719 
00720 //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
00721 
00722 //                      Gestione date relative ai file
00723 
00724 //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
00725 
00726 struct date_ext2{
00727     dword giorno;
00728     dword mese;
00729     dword anno;
00730 }data;
00731 
00732 struct time_ext2{
00733     dword secondi;
00734     dword minuti;
00735     dword ora;
00736 }tempo;
00737 
00738 
00739 struct time_ext2 det_time(dword ino_time){
00740         struct time_ext2 t;
00741         dword s;
00742 
00743         s = ino_time % 86400;
00744         // ora
00745         t.ora = s / 3600;
00746         s -= t.ora*3600;
00747         // minuti
00748         t.minuti = (s / 60);
00749         s -= t.minuti*60;
00750         // secondi
00751         t.secondi = s;
00752         return(t);
00753 
00754 }
00755 
00756 struct date_ext2 det_date(dword ino_time){
00757         struct date_ext2 d;
00758         dword mg;
00759 
00760         ino_time = ino_time / 86400; //(60*60*24)
00761 
00762         // tempo in giorni trascorso dal 1/1/1970
00763 
00764         mg = ino_time + 1;
00765 
00766         // si determina l'anno
00767         for (d.anno=1970;;d.anno++)
00768         {
00769                 if ((d.anno % 4)==0) // bisestile
00770                 {
00771                         if (mg<366) break;
00772                         mg -= 366;
00773                 }
00774                 else
00775                 {
00776                         if (mg<365) break;
00777                         mg -= 365;
00778                 }
00779 
00780         }
00781 
00782         // mg contiene mese e giorno
00783         for (d.mese=1;;d.mese++)
00784         {
00785 
00786                 if ((d.mese==4)||(d.mese==6)||(d.mese==9)||(d.mese==11))
00787                 {
00788                         if (mg<=30) break;
00789                         mg -= 30;
00790                 }
00791                 else if ((d.mese==2)&&(d.anno%4==0))
00792                         {
00793                                 if (mg<=29) break;
00794                                 mg -= 29;
00795                         }
00796                         else if ((d.mese==2)&&(d.anno%4!=0))
00797                                 {
00798                                         if (mg<=28) break;
00799                                         mg -= 28;
00800                                 }
00801                                 else
00802                                 {
00803                                         if (mg<=31) break;
00804                                         mg -= 31;
00805                                 }
00806         }
00807 
00808         d.giorno = mg;
00809         return(d);
00810 
00811 }
00812 
00813 
00814 
00815 
00816 // restituisce la path corrente a partire dalla radice
00817 char *pwd_ext2(){
00818     if (mount_ext2)
00819         return(path_ext2);
00820      else return('\0');
00821 }
00822 
00823 
00824 // restituisce l'elenco dei file della directory corrente
00825 void ls_ext2(){
00826     int i;
00827     struct i_node* info_file;
00828     if (mount_ext2){
00829 
00830         clrscr();
00831         //kprintf("\n\r Total: %u",count_dir);
00832         for (i=0; i<count_dir; i++)
00833         {
00834 
00835                 info_file = get_inode(inode_dir[i]);
00836                 // data e ora di creazione del file
00837                 tempo = det_time(info_file->i_ctime);
00838                 data = det_date(info_file->i_ctime);
00839 
00840                 // TODO : fast symbolic link
00841                 if ((info_file->i_mode&MODE_MASK)==MODE_LINK)
00842                         continue;
00843                 switch (info_file->i_mode & MODE_MASK)
00844                 {
00845 
00846                 case MODE_FILE:
00847                 set_color(WHITE);
00848                 break;
00849 
00850                 case MODE_DIR:
00851                 set_color(LIGHT_BLUE);
00852                 break;
00853 
00854                 case MODE_CDEV:
00855                 set_color(LIGHT_GREEN);
00856                 break;
00857 
00858                 case MODE_BDEV:
00859                 set_color(LIGHT_RED);
00860                 break;
00861 
00862                 case MODE_FIFO:
00863                 set_color(LIGHT_MAGENTA);
00864                 break;
00865 
00866                 case MODE_SOCK:
00867                 set_color(LIGHT_CYAN);
00868                 break;
00869 
00870                 case MODE_LINK:
00871                 set_color(RED);
00872                 break;
00873 
00874                 }
00875 
00876                 kprintf("\n\r %s",ext2_file_name[i]);
00877                 set_color(DEFAULT_COLOR);
00878                 kprintf ("\r                    (%u)",inode_dir[i]);
00879                 set_color(WHITE);
00880                 kprintf("\r                                     %u",info_file->i_size);
00881                 kprintf("\r                                             %u:%u",tempo.ora,tempo.minuti);
00882                 kprintf("\r                                                      %u-%u-%u",data.anno,data.mese,data.giorno);
00883                 kprintf("\r                                                                     %u",info_file->i_blocks);
00884                 set_color(DEFAULT_COLOR);
00885                 if (((i+1)%22)==0)
00886                 {
00887                         kprintf ("\n\r ------ Continue ------");
00888                         if (kgetchar()==CTRL_C)
00889                         {
00890                                 kprintf("\n\n\r");
00891                                 return;
00892                         }
00893                         clrscr();
00894                 }
00895         }
00896         kprintf("\n\n");
00897     }
00898     else kprintf("\n\rUnmounted File System Ext2\n\n\r");
00899     return;
00900 }
00901 
00902 
00903 
00904 // permette di cambiare la directory corrente
00905 void cd_ext2(char *param){
00906         struct i_node* ino;
00907         int i,j_param,len_param,i_param;
00908         dword ino_dir;
00909         char elem_path[256]; // si usa per il parsing della path
00910         bool errore;
00911 
00912         //kprintf("\n\rparam %s",param);
00913         if(!mount_ext2)
00914         {
00915                 kprintf("\n\rUnmounted File System Ext2\n\n\r");
00916                 return;
00917         }
00918 
00919         if (!strcmp(param,"."))
00920         {
00921                 // si rimane nella directory corrente
00922                 return;
00923         }
00924 
00925         if (!strcmp(param,"/"))
00926         {
00927                 // si ritorna alla directory radice
00928                 if (!Open_Dir(get_inode(EXT2_ROOT_INO)))
00929                 {
00930                         // se non si può più aprire la root si smonta il file system
00931                         mount_ext2 = FALSE;
00932                         return;
00933                 }
00934                 level = 0;
00935                 path_ext2[0]='\0';
00936                 return;
00937         }
00938 
00939 
00940         if ((level == 0)&&!strcmp(param,".."))
00941         {
00942                 kprintf("\n\rCannot go up from root\n\n\r");
00943         }
00944         else if ((level ==1)&&!strcmp(param,".."))
00945                 {
00946                         // si ritorna alla directory radice
00947                         if (!Open_Dir(get_inode(EXT2_ROOT_INO)))
00948                         {
00949                                 // se non si può più aprire la root si smonta il file system
00950                                 mount_ext2 = FALSE;
00951                                 return;
00952                         }
00953                         level = 0;
00954                         path_ext2[0]='\0';
00955                         ino_current_dir = EXT2_ROOT_INO;
00956                 }
00957                 else
00958                 {
00959 
00960                         errore = FALSE;
00961                         // dobbiamo effettuare il salvataggio dei componenti
00962                         memcpy(&path_ext2_backup,&path_ext2,1024);
00963                         //kprintf ("\n\rpath_ext2_backup : %s\n\r",path_ext2_backup);
00964                         level_backup = level;
00965                         ino_dir_backup = ino_current_dir;
00966 
00967                         // dobbiamo fare il parsing della path
00968                         i_param = 0;
00969                         if (param[0]=='.'&&param[1]=='/')
00970                         {
00971                                 // ./ sta ad indicare restiamo nella dir corrente
00972                                 // non ha senso riaprirla
00973                                 i_param = 2;
00974                         }
00975                         if (param[strlen(param)-1]=='/')
00976                         {
00977                                 len_param = strlen(param)-1;
00978                         }
00979                         else len_param = strlen(param);
00980                         //kprintf ("\n\rlen_param : %u\n\r",len_param);
00981 
00982                         for (j_param=0;i_param<=len_param;i_param++)
00983                                 if ((param[i_param]=='/')||i_param==len_param)
00984                                 {
00985                                         elem_path[j_param]='\0';
00986                                         j_param = 0;
00987                                         //kprintf ("\n\relem_path : %s\n\r",elem_path);
00988                                         if (!(ino_dir=FindFile(elem_path)))
00989                                         {
00990                                                 // non esiste nella directory corrente la sottodirectory param
00991                                                 kprintf("\n\rDirectory no match\n\n\r");
00992                                                 errore = TRUE;
00993                                                 break;
00994                                         }
00995                                         else if (!(ino=get_inode(ino_dir)))
00996                                                 {
00997                                                 // invalid inode number
00998                                                 errore = TRUE;
00999                                                 break;
01000                                                 }
01001                                                 else if (!(isDir(ino)||isFastSymbolicLink(ino)))
01002                                                         {
01003                                                                 kprintf("\n\rNot a directory\n\n\r");
01004                                                                 errore = TRUE;
01005                                                                 break;
01006                                                         }
01007                                                         else if (!Open_Dir(ino))
01008                                                                 {
01009                                                                         if (!isFastSymbolicLink(ino))
01010                                                                                 kprintf("\n\rOpen failed\n\n\r");
01011                                                                         errore = TRUE;
01012                                                                         break;
01013                                                                 }
01014                                                                 else
01015                                                                 {
01016                                                                         // si aggiorna la path salendo nell'albero
01017                                                                         if (!strcmp(elem_path,".."))
01018                                                                         {
01019 
01020                                                                                 if (level)
01021                                                                                 {
01022                                                                                         level--;
01023                                                                                         for (i=strlen(path_ext2)-2;path_ext2[i]!='/';i--);
01024                                                                                         path_ext2[i+1]='\0';
01025                                                                                 }
01026                                                                                 if (!level)
01027                                                                                         path_ext2[0]='\0';
01028                                                                         }
01029                                                                         else
01030                                                                         {
01031                                                                                 strcat(path_ext2,elem_path);
01032                                                                                 strcat(path_ext2,"/");
01033                                                                                 level++;
01034                                                                         }
01035                                                                         ino_current_dir = ino_dir;
01036 
01037                                                                 }
01038                                 }
01039                                 else elem_path[j_param++] = param[i_param];
01040 
01041                                 if (errore)
01042                                 {
01043                                         // si ripristina la vecchia directory
01044                                         kprintf("\n\rerrore\n\r");
01045                                         level = level_backup;
01046                                         memcpy(&path_ext2,&path_ext2_backup,1024);
01047                                         ino_current_dir = ino_dir_backup;
01048                                         Open_Dir(get_inode(ino_current_dir));
01049 
01050 
01051                                 }
01052                                 kprintf("\n\r level :%u\n\r",level);
01053 
01054                 }
01055 }
01056 
01057 void cat_ext2(char *param){
01058         struct i_node * ino;
01059         dword i;
01060         word block_file;
01061         char *c=NULL;
01062         int stop=0,ll=0;
01063         dword ino_file;
01064 
01065         if (!mount_ext2)
01066         {
01067                 kprintf("\n\rUnmounted File System Ext2\n\r");
01068                 return;
01069         }
01070 
01071         if (!(ino_file = FindFile(param)))
01072         {
01073                 kprintf("\n\rNo such file\n\r");
01074                 return;
01075         }
01076         else if (!(ino=get_inode(ino_file)))
01077                 {
01078                         // invalid inode number
01079                 }
01080                 else if (!(isFile(ino)||isFastSymbolicLink(ino)))
01081                 {
01082                         kprintf("\n\rNot a regular file\n\r");
01083                         return;
01084                 }
01085                 else if (Open_File(ino,ino->i_mode & MODE_MASK))
01086                         {
01087                                 // dimensione in blocchi del file
01088                                 block_file = 0;
01089                                 stop = 3;
01090                                 data_block = (byte *)kmalloc(dim_block);
01091                                 memset(data_block,0,dim_block);
01092                                 //clrscr();
01093                                 set_color(LIGHT_BLUE);
01094                                 kprintf("filename: %s\n\n\r",param);
01095                                 set_color(DEFAULT_COLOR);
01096                                 for (i=0;i<ino->i_size;i++)
01097                                 {
01098                                         if (i % dim_block ==0)
01099                                         {
01100                                                 if ( (err = ReadSectorsLba(0,(int64_t)blocco_to_LBA(ptr_dir[block_file]),spb,(word *)data_block,TRUE)) )
01101                                                 {
01102                                                         kprintf ("\n\rError reading file data block");
01103                                                         ShowIdeErrorMessage(err,TRUE);
01104                                                         kfree(ptr_dir);
01105                                                         kfree(data_block);
01106                                                         return;
01107                                                 }
01108                                                 block_file++;
01109                                                 c = (char *)data_block;
01110                                         }
01111 
01112 
01113                                         if (*c==10) // carattere di fine linea
01114                                         {
01115                                                 stop++;
01116                                                 kprintf("\n\r");
01117                                                 ll=0;
01118                                         }
01119                                         else
01120                                         {
01121                                                 kputchar(*c);
01122                                                 if(ll++>70)
01123                                                 {
01124                                                         // se la linea eccede in lunghezza la dimensione
01125                                                         //dello schermo si divide in due linee
01126                                                         stop++;
01127                                                         ll = 0;
01128                                                 }
01129                                         }
01130 
01131                                         c++;
01132 
01133                                         if (((stop)%22)==0)
01134                                         {
01135                                                 kprintf ("\n\r ------ Continue ------");
01136                                                 if ( kgetchar()==CTRL_C )
01137                                                 {
01138                                                         // *** Andrea Righi 2003-10-04 *** //
01139                                                         kfree(data_block);
01140                                                         //********************************//
01141                                                         kprintf("\n\r");
01142                                                         return;
01143                                                 }
01144                                                 clrscr();
01145                                                 stop = 3;
01146                                                 set_color(LIGHT_BLUE);
01147                                                 kprintf("filename: %s\n\n\r",param);
01148                                                 set_color(DEFAULT_COLOR);
01149                                         }
01150                                 }
01151                                 kfree(data_block);
01152                         }
01153 }
01154 
01155 
01156 
01157 /**************************************************************************
01158 *
01159 *           Procedure di inizializzazione del file system Ext2
01160 *
01161 ***************************************************************************/
01162 
01163 
01164 //--------------- Lettura da disco Ext2 ---------------//
01165 bool read_ext2(){
01166 
01167         int dev,sec;
01168 
01169         kprintf ("\n\n\rInitializing Ext2...");
01170 
01171         /*
01172          lettura del superblocco a partire START_SUPER_BLOCK. Il super blocco
01173          si trova sempre nel primo blocco della partizione e occupa esattamente 1024 byte
01174         */
01175 
01176         data_block = kmalloc(DIM_SUPER_BLOCK);
01177         memset(data_block,0,DIM_SUPER_BLOCK);
01178 
01179         dev = 0;
01180         sec = 2;
01181 
01182         // seleziono il canale
01183         SelectAtaChannel(CC_PRIMARY);
01184 
01185         if ( (err = ReadSectorsLba(dev,(int64_t) blocco_to_LBA(0)+sec,2,(word *) data_block,TRUE)) )
01186         {
01187          // si stampa l'errore relativo al fallimento lettura disco
01188          ShowIdeErrorMessage(err,TRUE);
01189          return FALSE;
01190         }
01191         else    {
01192                  // si copia il settore nella variabile super
01193                         // *** Andrea Righi ****************************//
01194                         //! super must be allocated first...
01195                         super = kmalloc(sizeof(struct super_block));
01196                         // *********************************************//
01197                         memcpy(super,data_block,sizeof(struct super_block));
01198                         return TRUE;
01199                 }
01200         kfree(data_block);
01201 }
01202 
01203 
01204 //------------- Controllo validità Ext2 ---------------//
01205 bool check_ext2(){
01206         if ((super->s_magic != N_EXT2_NUMERO_MAGICO)&&(super->s_magic != P_EXT2_NUMERO_MAGICO))
01207         {
01208                 kprintf("\n\rNot a valid ext2.\n\r");
01209                 return(FALSE);
01210         }
01211         else return TRUE;
01212 }
01213 
01214 
01215 bool init_ext2(){
01216         path_ext2[0] = '\0'; //inizializzazione della path
01217 
01218         if (!read_ext2())
01219         {
01220                 //kprintf("\n\rDisk I/O error. Unable to read the super block!!!\n\r");
01221                 return(FALSE);
01222         }
01223         // inizializzazione ext2 a buon fine
01224 
01225         if (!check_ext2())
01226         {
01227                 return(FALSE);
01228         }
01229         // ext2 é valido
01230 
01231 
01232         // calcolo parametri della versione corrente file system
01233 
01234         dim_block = 1024 << super->s_log_block_size; //dimensione dei blocchi
01235 
01236         dim_frag = 1024 << super->s_log_frag_size; // dimensione dei frammenti
01237 
01238         spb = dim_block / SIZE_SEC; //settori per blocco
01239 
01240         sbpos = super->s_first_data_block + 1; // posizione del superblocco
01241 
01242         bpg = super->s_blocks_per_group; //blocchi per gruppo
01243 
01244         gdpb = dim_block / sizeof(struct group_descriptor); // desc di gruppo per blocco
01245 
01246         ipb = dim_block / super->s_inode_size; // inodes per blocco dim inode 128 bit
01247 
01248         number_of_groups = super->s_inodes_count / super->s_inodes_per_group; // numero gruppi
01249 
01250         dir_entries_per_block = dim_block / sizeof(struct dir_ff); //directory per blocco
01251 
01252         dim_ptr = dim_block >> 2; // dim del blocco in parole da 32 bit
01253 
01254         // informazioni di carattere generale sulla ext2 corrente
01255         kprintf("\n\rExt2 parameters\n\r");
01256         kprintf("\n\rTotal number of inodes:                         %u",super->s_inodes_count);
01257         kprintf("\n\rTotal number of block:                          %u",super->s_blocks_count);
01258         kprintf("\n\rNumber of blocks reserved for the super user:   %u",super->s_r_blocks_count);
01259         kprintf("\n\rNumber of groups:                               %u",number_of_groups);
01260         kprintf("\n\rBlock per group:                                %u",bpg);
01261         kprintf("\n\rBlock dimension:                                %u",dim_block);
01262         kprintf("\n\rFragment dimension:                             %u",dim_frag);
01263         kprintf("\n\rSector per block:                               %u",spb);
01264         kprintf("\n\rDirectories per block:                          %u",dir_entries_per_block);
01265         kprintf("\n\rGroup descriptors per block:                    %u",gdpb);
01266         kprintf("\n\rInodes per group:                               %u",super->s_inodes_per_group);
01267         kprintf("\n\rFrags per group:                                %u",super->s_frags_per_group);
01268         kprintf("\n\rInodes per block:                               %u",ipb);
01269         kprintf("\n\r");
01270 
01271         // inizializzazione tabella dei descrittori di gruppo
01272         if (!init_group_desc_table())
01273         {
01274                 return(FALSE);
01275         }
01276 
01277         // inizializzazione tabella degli inode
01278         if (!init_inode_table())
01279         {
01280                 return(FALSE);
01281         }
01282 
01283         // dobbiamo leggere l'inode relativo alla directory radice "inode 2 sempre"
01284 
01285         if (!Open_Dir(get_inode(EXT2_ROOT_INO)))
01286         {
01287                 // kprintf("\n\rNot able to open the root directory\n\r");
01288                 return(FALSE);
01289         }
01290 
01291         ino_current_dir = EXT2_ROOT_INO;
01292 
01293         mount_ext2 = TRUE; //file system montato
01294 
01295         level = 0; // livello nell'albero delle directory, root = 0
01296 
01297         return(TRUE);
01298 }
01299 
01300 
01301 

Generated on Fri Feb 20 15:32:15 2004 for Minirighi by doxygen1.2.18