util.c

Vai alla documentazione di questo file.
00001 
00013 #include <stdio.h>
00014 #include <stdlib.h>
00015 #include <errno.h>
00016 #include <libgen.h>
00017 #include <string.h>
00018 
00019 #include "Include/fat.h"
00020 #include "Include/util.h"
00021 #include "Include/sfaterror.h"
00022 
00064 static int percorso(FILE *fs, struct fat_ctrl *f_ctrl, char *path);
00065 
00066 int parsing(FILE *fs, struct fat_ctrl *f_ctrl, char *path, Action azione){
00067         char *dirc, *basec, *bname, *dname;
00068         int ret_val;
00069         
00070         if (!(fs) || !(f_ctrl) || !(path)) return EBDP;
00071         
00072         /* Metto il puntatore fs all'inizio della data region */
00073         fseek(fs, f_ctrl->blk_base, SEEK_SET);
00074 
00075         /* Faccio una copia della path */
00076         if (!(dirc = strdup(path))) return STDLIBERR;
00077         /* Elimino l'ultimo 'path element' */
00078         dname = dirname(dirc);
00079         ret_val = percorso(fs, f_ctrl, dname);
00080 
00081         free(dirc);
00082         if (ret_val) return ret_val;
00083         
00084         /* Reperisco l'ultimo 'path element' */
00085         if (!(basec = strdup(path))) return STDLIBERR;
00086         bname = basename(basec);
00087         if (strlen(bname)>MAX_LEN_NAME){free(basec); return ENTL;} 
00088 
00089         switch(azione){
00090                 case LS:        /* ritorna settando 'fs' sull'entry della cartella cercata */           
00091                 case RDFILE:/* ritorna settando 'fs' sull'entry del file cercato */
00092                 case WRFILE:/* ritorna settando 'fs' sull'entry del file cercato */
00093                         ret_val = find(fs, f_ctrl, bname, azione); 
00094                 break;          
00095                 case MKFILE:
00096                 case MKDIR:
00097                         ;
00098                 break;
00099         }
00100         free(basec);
00101         return ret_val;
00102 }
00103 
00104 static int percorso(FILE *fs, struct fat_ctrl *f_ctrl, char *path){
00105         char *dirc, *basec, *bname, *dname;
00106         int ret_val = 0;
00107         
00108         if (!(fs) || !(f_ctrl) || !(path) ) return EBDP;
00109         if (!(dirc = strdup(path))) return STDLIBERR;
00110         if (!(basec = strdup(path))) return STDLIBERR;
00111         dname = dirname(dirc);
00112         bname = basename(basec);
00113         
00114         if (strlen(bname) > MAX_LEN_NAME) ret_val = ENTL;
00115         
00116         if (!ret_val && strcmp(dname, ".") && strcmp(dname, "/"))
00117                 ret_val = percorso(fs, f_ctrl, dname);
00118 
00119         if (!ret_val && !strcmp(dname, ".")) ret_val = EBDP;
00120         if (!ret_val) ret_val = find(fs, f_ctrl, bname, LS);
00121 
00122         free(dirc);
00123         free(basec);
00124         return ret_val;
00125 }
00126 
00127 
00128 int find(FILE *fs, struct fat_ctrl *f_ctrl, char *path, Action azione){
00129         struct dir_entry cart_p;
00130         int numero_entry, i, j, MAX_ENTRY;
00131         unsigned int indice_fat, new_index;
00132         long fs_pos;
00133         
00134         if (!(fs) || !(f_ctrl) || !(path)) return EBDP;
00135         /* Se sono nella radice ritorna */
00136         if ((azione==LS) && !strcmp(path, "/")) return 0;
00137         /* Calcolo qual'e' il numero massimo di entry memorizzabile in un
00138          *  blocco, in realazione alla dimensione del blocco stesso */
00139         MAX_ENTRY = f_ctrl->b_sector.block_size/sizeof(struct dir_entry);
00140         
00141         fs_pos = ftell(fs);
00142         /* Leggo la dir_entry "." */
00143         if (!(fread(&cart_p, sizeof(struct dir_entry), 1, fs))) return ERBD;
00144         numero_entry = cart_p.len/sizeof(struct dir_entry);
00145         /* Ricorda l'indice della fat memorizzato nel blocco della entry iniziale '.'
00146          * della cartella in cui noi stiamo ciclando  */
00147         indice_fat = cart_p.index;
00148         if (indice_fat > f_ctrl->b_sector.num_block) return ERFCD;
00149         
00150         /* Relative path navigation "/." (Solo in caso di listing delle cartelle) */
00151         if ((azione==LS) && !strcmp(cart_p.name, path) && (cart_p.attr == SUB_ENTRY)){
00152                 fseek(fs, fs_pos, SEEK_SET);
00153                 return 0;
00154         }
00155         
00156         for (i=1, j=1; i<numero_entry; i++, j++){               
00157                 if (j==MAX_ENTRY){
00158                         /* Ho letto tutte le entry del blocco.
00159                          * Devo controllare il blocco DATA REGION successivo nella fat */                       
00160                         if (f_ctrl->fat_ptr[indice_fat] == BLOCK_FREE) return ERFCD;
00161                         if (f_ctrl->fat_ptr[indice_fat] == LAST_BLOCK) return ERFCD;                            
00162                         /* La posizione successiva di 'fs' e' uguale a blk_base +
00163                          * la posizione indicata nell'array della FAT * la dimensione dei blocchi. */
00164                         fs_pos = f_ctrl->blk_base + f_ctrl->fat_ptr[indice_fat] * f_ctrl->b_sector.block_size;
00165                         fseek(fs, fs_pos, SEEK_SET);
00166                         /* Aggiorno l'indice della FAT col nuovo valore memorizzato nella locazione stessa della FAT */
00167                         indice_fat = f_ctrl->fat_ptr[indice_fat];
00168                         /* if (indice_fat > f_ctrl->b_sector.num_block) return ERFCD; */
00169                         j=1;
00170                 }
00171                 /* Salvo la posizione dell'entry del file. Utile solo per le azioni WRFILE e RDFILE */
00172                 fs_pos = ftell(fs);
00173                 /* Leggo la dir_entry successiva */
00174                 if (!(fread(&cart_p, sizeof(struct dir_entry), 1, fs))) return ERBD;
00175                 /* Ho trovato il nome che cercavo ed e' una cartella (condizione di uscita) */
00176                 if ((azione==LS) && !strcmp(cart_p.name, path) && (cart_p.attr == SUB_ENTRY)) break;
00177                 /* Ho trovato il nome che cercavo ed e' una cartella ma non avrei dovuto trovarlo!! */
00178                 if ((azione==MKDIR) && !strcmp(cart_p.name, path) && (cart_p.attr ==SUB_ENTRY)) return EDAEX;
00179                 /* Ho trovato il nome che cercavo ed e' un file ma non avrei dovuto trovarlo!! */
00180                 if ((azione==MKFILE) && !strcmp(cart_p.name, path) && (cart_p.attr==FILE_ENTRY)) return EDAEX;
00181                 /* Ho trovato il nome che cercavo ed e' un file (condizione di uscita) */
00182                 if ((azione==WRFILE || azione==RDFILE) && !strcmp(cart_p.name, path) && (cart_p.attr==FILE_ENTRY)) break;
00183         }
00184 
00185         switch(azione){
00186                 case LS:
00187                         /* Cartella non trovata (Error Not Such File or Directory) */
00188                         if (strcmp(cart_p.name, path)) return ENSFD;
00189                         else if (!strcmp(cart_p.name, path) && (cart_p.attr==FILE_ENTRY)) return ENSFD;
00190                         /* Posiziono il file pointer fs all'inizio del blocco che contiene la prima
00191                          * porzione della Directory Table relativa alla cartella cercata */
00192                         fs_pos = f_ctrl->blk_base + cart_p.index * f_ctrl->b_sector.block_size;
00193                         fseek(fs, fs_pos, SEEK_SET);
00194                 break;
00195                 case RDFILE:
00196                 case WRFILE:
00197                         /* File non trovato (Error Not Such File or Directory) */
00198                         if (strcmp(cart_p.name, path) || (cart_p.attr!=FILE_ENTRY)) return ENSFD;
00199                         /* Posiziono il file pointer fs all'inizio dell'entry del file su cui devo
00200                          * andare a scrivere (o a leggere) */
00201                         fseek(fs, fs_pos, SEEK_SET);
00202                 break;
00203                 case MKFILE:
00204                 case MKDIR:
00205                         /* La funzione ritorna settando 'fs' sul primo spazio vuoto del blocco dalla
00206                          * data region di modo che la write della nuova entry sia nel punto corretto */         
00207                         if (j==MAX_ENTRY){
00208                                 /* Cerco un nuovo indice di blocco libero nella FAT */
00209                                 for (new_index=0; new_index<f_ctrl->b_sector.num_block; new_index++)
00210                                         if (f_ctrl->fat_ptr[new_index] == BLOCK_FREE) break;
00211                                 if (new_index>=f_ctrl->b_sector.num_block) return ENMSD;
00212                                 /* Imposto il blocco libero trovato della FAT ad LAST_BLOCK. */
00213                                 f_ctrl->fat_ptr[new_index] = LAST_BLOCK;
00214                                 fs_pos = f_ctrl->blk_base + new_index * f_ctrl->b_sector.block_size;
00215                                 /* Aggiorno la locazione della fat puntata dal vecchio indice */
00216                                 f_ctrl->fat_ptr[indice_fat]= new_index;
00217                                 /* Setto il puntatore 'fs' al nuovo blocco libero della fat */
00218                                 fseek(fs, fs_pos, SEEK_SET);
00219                         }               
00220                 break;
00221         }
00222         return 0;
00223 }
Generato il Fri Jan 28 22:16:31 2011 per SFAT: Simplified File Allocation Table Project da  doxygen 1.6.3