Changeset 291 for soft


Ignore:
Timestamp:
Feb 13, 2014, 3:29:33 PM (11 years ago)
Author:
devigne
Message:
  • Added fat_allocate function to enlarge the size of a file.
  • Recovery of FS_INFO in fat_init function, FS_INFO contains important information for the allocation of new clusters such as the last cluster allocated and the number of still free cluster.
  • Added update functions :
    • For FAT : update the chaining of clusters after allocation.
    • For DIR_ENTRY : update a field into a DIR_ENTRY, eg FILE_SIZE field after a write.
    • For FS_INFO : after allocation we must update the last cluster allocated and number of free cluster fields.
Location:
soft/giet_vm/giet_fat32
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • soft/giet_vm/giet_fat32/fat32.c

    r289 r291  
    8383} // end display_fat_cache() 
    8484#endif
    85  
     85
    8686//////////////////////////////////////////////////////////////////////////////////
    8787// This function returns the length of a FAT field. This field is identified
     
    9292{
    9393    return length;
     94}
     95
     96//////////////////////////////////////////////////////////////////////////////
     97// Write one 32 bits word "value" in a char[] buffer.
     98// This field is defined by the offset and size arguments.
     99//////////////////////////////////////////////////////////////////////////////
     100static void write_entry( unsigned int   offset,
     101                         unsigned int   size,
     102                         char*          buffer,
     103                         unsigned int   value )
     104{
     105    unsigned int turn = 0;
     106    unsigned int res  = value;
     107    unsigned int mask = 0x000000ff;
     108
     109    while( turn != size - 1 )
     110    {
     111        buffer[ offset + turn ] = res & mask;
     112        res = res >> 8;
     113        turn++;
     114    }
     115    buffer[offset + turn] = res & mask;
    94116}
    95117
     
    200222    }
    201223}
    202 
    203 ///////////////////////////////////////////////////////////////////////////////
    204 // This function returns the cluster index from a (32 bytes) directory entry
    205 ///////////////////////////////////////////////////////////////////////////////
    206 static inline unsigned int read_cluster( char* buf )                 
    207 {
    208    unsigned int cluster = read_entry( DIR_FST_CLUS_HI, buf, 1 ) << 16;
    209    cluster = cluster | read_entry( DIR_FST_CLUS_LO, buf, 1 );
    210    return cluster;
    211 }
    212224
    213225//////////////////////////////////////////////////////
     
    356368}
    357369
     370///////////////////////////////////////////////////////////////////////
     371// This function analyses the pathname argument, from the character
     372// defined by the *nb_read argument.
     373// It copies the found name (between '/') in the name[] buffer,
     374// and updates the nb_read argument.
     375// Return 1 if name found, Return 0 if NUL character found,
     376///////////////////////////////////////////////////////////////////////
     377static int get_name_from_path( char*          pathname,
     378                               char*          name,
     379                               unsigned int*  nb_read )
     380{
     381    if ( pathname[*nb_read] == 0 ) return 0;
     382
     383    int i = (pathname[*nb_read] == '/')? (*nb_read) + 1 : *nb_read;
     384    int j = 0;
     385   
     386    while(pathname[i] != '/' && pathname[i] != '\0')
     387    {
     388        name[j] = pathname[i];   
     389        j++;
     390        i++;
     391    }
     392    name[j] = 0;
     393
     394    if ( pathname[i] == '/' ) *nb_read += j+1;
     395    else                      *nb_read += j;
     396
     397    return 1;
     398}
     399
    358400////////////////////////////////////////////////////////////////////////////////
    359401static int get_name_from_short( char* dir_entry,     // input:  SFN dir_entry
     
    372414    return i;
    373415}
     416
    374417///////////////////////////////////////////////////////////////////////////////
    375 static int get_name_from_long( char *dir_entry,    // input : LFN dir_entry
    376                                char *entry_name)   // output : name
     418static int get_name_from_long( char *dir_entry,     // input : LFN dir_entry
     419                               char *entry_name )   // output : name
    377420{
    378421    unsigned int   entry_name_offset   = 0;
     
    444487} // end get_name_from_long()
    445488
     489//////////////////////////////////////////////////////////////////////////////////////
     490// This function update a DIR_ENTRY, write a new value into a specific field
     491// (ex : DIR_FILE_SIZE, when we want update the file size after a fat_write)
     492// Return 0 in case of success, > 0 if failure.
     493//////////////////////////////////////////////////////////////////////////////////////
     494// TODO : make this function less complex
     495//////////////////////////////////////////////////////////////////////////////////////
     496static inline unsigned int update_entry( unsigned int fd_id,
     497                                         unsigned int field,
     498                                         unsigned int size,
     499                                         unsigned int value )
     500{
     501    char dir_entry[32];   // buffer to store a full directory_entry
     502    char name_entry[14];  // buffer to store a 13 characters (partial) name
     503    char file_name[256];  // buffer to store the name (not pathname) of the file
     504    char sfn[12]            = {[0 ... 10] = ' ', '\0'};      // buffer for a Short File Name
     505
     506    unsigned int lba       = fat.fd[fd_id].lba_dir_entry;    // Lba of file dir_entry
     507    unsigned int is_sfn;         
     508    unsigned int attr      = 0;                              // directory entry attribute
     509    unsigned int ord       = 0;                              // directory entry sequence
     510    unsigned int found     = 0;                              // name found
     511    unsigned int offset    = 0;
     512    unsigned int i         = 0;
     513    unsigned int nb_read   = 0;
     514
     515    for ( i = 0 ; i < 32 ; i++ ) dir_entry[i]  = 0;
     516    for ( i = 0 ; i < 14 ; i++ ) name_entry[i] = 0;
     517   
     518    // Get the name of the file.
     519    while ( get_name_from_path( fat.fd[fd_id].name, file_name, &nb_read ) )
     520    {
     521    }
     522
     523    // Check if file_name is short
     524    is_sfn = is_short( file_name, sfn );
     525
     526    if ( _ioc_read( IOC_KERNEL_MODE, // mode for IOC driver
     527                    lba,             // sector index
     528                    fat.fat_cache,   // buffer address
     529                    1 ) )            // one sector
     530    {
     531        _tty_get_lock( 0 );
     532        _puts("[FAT ERROR] in update_entry() cannot read sector ");
     533        _putd( lba );
     534        _puts("\n");
     535        _tty_release_lock( 0 );
     536        return 1;
     537    }
     538    fat.cache_lba = lba;
     539
     540    // - the offset increment is an integer number of directory entry (32 bytes)
     541    // - the exit condition is success (name found) or failure (end of directory)
     542    while ( !found )
     543    {
     544        attr = read_entry( DIR_ATTR, fat.fat_cache + offset, 0 );
     545        ord  = read_entry( LDIR_ORD, fat.fat_cache + offset, 0 );
     546
     547        if ( is_sfn == 1 )                                     // searched name is short
     548        {
     549            if      ( (ord != FREE_ENTRY ) &&
     550                    (ord != NO_MORE_ENTRY) &&
     551                    (attr == ATTR_LONG_NAME_MASK) )    // LFN entry : skipped
     552            {
     553                offset     = offset + ((ord & 0xF) * DIR_ENTRY_SIZE);
     554                continue;
     555            }
     556            else if ( (attr != ATTR_LONG_NAME_MASK) &&
     557                    (ord  != FREE_ENTRY) &&
     558                    (ord  != NO_MORE_ENTRY ) )         // SFN entry : checked
     559            {
     560                _memcpy( dir_entry, fat.fat_cache + offset, DIR_ENTRY_SIZE );   
     561            }
     562            else if (ord == NO_MORE_ENTRY )            // end of directory : return
     563            {
     564                _tty_get_lock( 0 );
     565                _puts("[FAT ERROR] in update_entry() end of directory reaches ");
     566                _puts("\n");
     567                _tty_release_lock( 0 );
     568                return 1;
     569            }
     570            else                                                                           // free entry : skipped
     571            {
     572                offset = offset + DIR_ENTRY_SIZE;
     573                continue;
     574            }
     575        }
     576        else                                           // searched name is long
     577        {
     578            if      ( (attr == ATTR_LONG_NAME_MASK) &&
     579                    (ord != FREE_ENTRY) &&
     580                    (ord != NO_MORE_ENTRY) )           // LFN entry : checked
     581            {
     582                _memcpy( dir_entry, fat.fat_cache + offset, DIR_ENTRY_SIZE );   
     583            }
     584            else if ( (attr != ATTR_LONG_NAME_MASK) &&
     585                    (ord  != FREE_ENTRY) &&
     586                    (ord  != NO_MORE_ENTRY))               // SFN entry : skipped
     587            {
     588                offset = offset + DIR_ENTRY_SIZE;
     589                continue;
     590            }
     591            else if (ord == NO_MORE_ENTRY )                        // end of directory : return
     592            {
     593                _tty_get_lock( 0 );
     594                _puts("[FAT ERROR] in update_entry() end of directory reaches ");
     595                _puts("\n");
     596                _tty_release_lock( 0 );
     597                return 1;
     598            }
     599            else                                       // free entry : skipped
     600            {
     601                offset = offset + DIR_ENTRY_SIZE;
     602                continue;
     603            }
     604        }
     605
     606        // testing the name extracted from dir entry
     607
     608        if ( is_sfn == 1 )                             // searched name is short
     609        {
     610            get_name_from_short( dir_entry, name_entry );
     611
     612            if ( _strncmp( (char*)sfn, (char*)name_entry, 13 ) == 0 )
     613            {
     614                write_entry(offset + field, size, fat.fat_cache, value);
     615                found = 1;
     616            }
     617            else                                                                       // no matching : skip
     618            {
     619                offset = offset + DIR_ENTRY_SIZE;
     620            }
     621        }
     622        else                                           // searched name is long
     623        {
     624            get_name_from_long( dir_entry, name_entry );
     625
     626            unsigned shift = ((ord & 0xf) - 1) * 13;
     627            if ( _strncmp( (char*)(file_name + shift), (char*)name_entry, 13 ) == 0 )
     628            {
     629                if ( (ord & 0xf) == 1 )
     630                {
     631                    offset = offset + DIR_ENTRY_SIZE;
     632                    write_entry(offset + field, size, fat.fat_cache, value);
     633                    found = 1;
     634                }
     635                offset = offset + DIR_ENTRY_SIZE;
     636                continue;
     637            }
     638            else                                                                       // no matching : skip
     639            {
     640                offset = offset + ((ord & 0xf) * DIR_ENTRY_SIZE) + DIR_ENTRY_SIZE;
     641            }
     642        }
     643    }
     644
     645    return _ioc_write( IOC_KERNEL_MODE,
     646                       lba, 
     647                       fat.fat_cache,
     648                       1     );
     649}
     650//////////////////////////////////////////////////////////////////////////////////
     651// This function update FS_INFO, for new last cluster allocated and number of free
     652// cluster.
     653// Return 0 in case of success, > 0 if failure.
     654//////////////////////////////////////////////////////////////////////////////////
     655static inline unsigned int update_fs_info( )
     656{
     657    unsigned int lba = fat.fs_info_lba;
     658
     659#if GIET_DEBUG_FAT
     660_tty_get_lock( 0 );
     661_puts("\n[FAT DEBUG] Enter in update_fs_info()\n");
     662_tty_release_lock( 0 );
     663#endif
     664
     665    if ( lba == fat.cache_lba )            // hit cache
     666    {
     667        write_entry( FS_FREE_CLUSTER     , fat.fat_cache, fat.number_free_cluster );
     668        write_entry( FS_FREE_CLUSTER_HINT, fat.fat_cache, fat.last_cluster_allocated );
     669    }
     670    else                                   // miss cache
     671    {
     672        if ( _ioc_read( IOC_KERNEL_MODE,   // mode for IOC driver
     673                        lba,               // sector index
     674                        fat.fat_cache,     // fat cache
     675                        1 ) )              // one sector
     676        {
     677            _tty_get_lock( 0 );
     678            _puts("[FAT_ERROR] in update_fat() cannot read block ");
     679            _putd( lba );
     680            _puts("\n");
     681            _tty_release_lock( 0 );
     682            return 1;
     683        }
     684        fat.cache_lba = lba;
     685        write_entry( FS_FREE_CLUSTER     , fat.fat_cache, fat.number_free_cluster );
     686        write_entry( FS_FREE_CLUSTER_HINT, fat.fat_cache, fat.last_cluster_allocated );
     687    }
     688    return _ioc_write( IOC_KERNEL_MODE,       
     689                       lba,           
     690                       fat.fat_cache,           
     691                       1 );
     692}
     693
     694//////////////////////////////////////////////////////////////////////////////////
     695// This function update FAT, write a new value into cluster index.
     696// Used by the function _fat_allocate to update the chaining of clusters.
     697// Return 0 in case of success, > 0 if failure.
     698//////////////////////////////////////////////////////////////////////////////////
     699static inline unsigned int update_fat( unsigned int cluster,
     700                                       unsigned int value  )
     701{
     702    unsigned int lba = fat.partition_lba + 32 + (cluster / 128);
     703
     704#if GIET_DEBUG_FAT
     705_tty_get_lock( 0 );
     706_puts("\n[FAT DEBUG] Enter in update_fat() :\n");
     707_puts("    - Cluster to update = ");
     708_putd( cluster );
     709_puts("\n");
     710_puts("    - Value to write = ");
     711_putd( value );
     712_puts("\n");
     713_tty_release_lock( 0 );
     714#endif
     715
     716    if ( lba == fat.cache_lba )            // hit cache
     717    {
     718        write_entry( ((cluster % 128) << 2), 4, fat.fat_cache, value );
     719    }
     720    else                                   // miss cache
     721    {
     722        if ( _ioc_read( IOC_KERNEL_MODE,   // mode for IOC driver
     723                        lba,               // sector index
     724                        fat.fat_cache,     // fat cache
     725                        1 ) )              // one sector
     726        {
     727            _tty_get_lock( 0 );
     728            _puts("[FAT_ERROR] in update_fat() cannot read block ");
     729            _putd( lba );
     730            _puts("\n");
     731            _tty_release_lock( 0 );
     732            return 1;
     733        }
     734        fat.cache_lba = lba;
     735        write_entry( ((cluster % 128) << 2), 4, fat.fat_cache, value );
     736    }
     737    return _ioc_write( IOC_KERNEL_MODE,       
     738                       lba,           
     739                       fat.fat_cache,           
     740                       1 );
     741}
     742
     743//////////////////////////////////////////////////////////////////////////////////
     744// This function allocate a count number of cluster to a file by calling the
     745// update_fat function that takes care to update the chaining of clusters.
     746// return 0 if success, -1 if failure
     747//////////////////////////////////////////////////////////////////////////////////
     748static inline int _fat_allocate( unsigned int fd_id,
     749                                 unsigned int count )
     750{
     751    unsigned int next_cluster        = fat.fd[fd_id].first_cluster;   // Get the first cluster of file
     752    unsigned int cluster_to_allocate = count;                         // Number of cluster to allocate
     753
     754    unsigned int last_cluster_file;                                   // Last cluster of the file (EOC)
     755
     756    unsigned int free_cluster = fat.last_cluster_allocated + 1;       // First free cluster
     757
     758    // Check if free_cluster is really free (must be true)
     759    if ( get_next_cluster_id( IOC_KERNEL_MODE, free_cluster ) != FREE_CLUSTER)
     760    {
     761        _tty_get_lock( 0 );
     762        _puts("\n[FAT ERROR] in _fat_allocate() : first free_cluster isnt free\n");
     763        _tty_release_lock( 0 );
     764        return -1;
     765    }
     766    // Check if FAT contains enough cluster free for this allocation
     767    if ( count > fat.number_free_cluster )
     768    {
     769        _tty_get_lock( 0 );
     770        _puts("\n[FAT ERROR] in _fat_allocate() : Not enough free cluster(s) for this allocation\n");
     771        _tty_release_lock( 0 );
     772        return -1;
     773    }
     774
     775#if GIET_DEBUG_FAT
     776_tty_get_lock( 0 );
     777_puts("\n[FAT DEBUG] Enter in _fat_allocate() :\n");
     778_puts("    - Need to allocate ");
     779_putd( count );
     780_puts(" cluster(s) for file ");
     781_putd( fd_id );
     782_puts("\n");
     783_tty_release_lock( 0 );
     784#endif
     785
     786    // Get the last cluster allocated for the file (seek END_OF_CHAIN_CLUSTER).
     787    do{
     788        last_cluster_file = next_cluster;
     789        next_cluster      = get_next_cluster_id( IOC_KERNEL_MODE, next_cluster );
     790    }while ( next_cluster < END_OF_CHAIN_CLUSTER );
     791
     792    // Loop on the number of cluster needed to be allocated
     793    while ( cluster_to_allocate > 0 )
     794    {
     795
     796#if GIET_DEBUG_FAT
     797_tty_get_lock( 0 );
     798_puts("\n[FAT DEBUG] Cluster to update is : ");
     799_putd( last_cluster_file );
     800_puts("\n");
     801_puts("[FAT DEBUG] Free cluster is : ");
     802_putd( free_cluster );
     803_puts("\n");
     804_puts("[FAT DEBUG] Number of cluster need to be allocated : ");
     805_putd( cluster_to_allocate );
     806_puts("\n");
     807_tty_release_lock( 0 );
     808#endif
     809
     810        // update, in the FAT, the value of last cluster allocated by the index
     811        // of free cluster.
     812        if ( update_fat( last_cluster_file, free_cluster ) )
     813        {
     814            _tty_get_lock( 0 );
     815            _puts("\n[FAT ERROR] in _fat_allocate() : update fat for file ");
     816            _putd( fd_id );
     817            _puts(" failed\n");
     818            _tty_release_lock( 0 );
     819            return -1;
     820        }
     821
     822        cluster_to_allocate = cluster_to_allocate - 1;
     823        // Last cluster allocated is then free_cluster
     824        last_cluster_file = free_cluster;
     825
     826        // Last cluster to allocate done, then we must close the chain of clusters
     827        if ( cluster_to_allocate == 0 )
     828        {
     829            // update, in the FAT, the value of the last cluster allocated by
     830            // END_OF_CHAIN_CLUSTER
     831            if ( update_fat( last_cluster_file, END_OF_CHAIN_CLUSTER ) )
     832            {
     833                _tty_get_lock( 0 );
     834                _puts("\n[FAT ERROR] in _fat_allocate() : update fat for file ");
     835                _putd( fd_id );
     836                _puts(" failed\n");
     837                _tty_release_lock( 0 );
     838                return -1;
     839            }
     840        }
     841
     842        free_cluster = free_cluster + 1;
     843
     844        // Check if free_cluster is really free (must be true)
     845        if ( get_next_cluster_id( IOC_KERNEL_MODE, free_cluster ) != FREE_CLUSTER)
     846        {
     847            _tty_get_lock( 0 );
     848            _puts("\n[FAT ERROR] in _fat_allocate() : free_cluster isnt free\n");
     849            _tty_release_lock( 0 );
     850            return -1;
     851        }
     852    }
     853
     854    // Update field number_free_cluster and last_cluster_allocated
     855    // of structure fat for next fat_allocate
     856    fat.last_cluster_allocated = last_cluster_file;
     857    fat.number_free_cluster    = fat.number_free_cluster - count;
     858
     859    if ( update_fs_info() )
     860    {
     861        _tty_get_lock( 0 );
     862        _puts("\n[FAT ERROR] in _fat_allocate() : update fs_info for file ");
     863        _putd( fd_id );
     864        _puts(" failed\n");
     865        _tty_release_lock( 0 );
     866        return -1;
     867    }
     868
     869    return 0;
     870}
     871
     872///////////////////////////////////////////////////////////////////////////////
     873// This function returns the cluster index from a (32 bytes) directory entry
     874///////////////////////////////////////////////////////////////////////////////
     875static inline unsigned int read_cluster( char* buf )                 
     876{
     877   unsigned int cluster = read_entry( DIR_FST_CLUS_HI, buf, 1 ) << 16;
     878   cluster = cluster | read_entry( DIR_FST_CLUS_LO, buf, 1 );
     879   return cluster;
     880}
     881
     882
    446883////////////////////////////////////////////////////////////////////////////////////////
    447884// This function read the blocks defined by the cluster index argument, in a data
     
    450887// Return cluster index if name found / Return -1 if not found,
    451888////////////////////////////////////////////////////////////////////////////////////////
    452 static int scan_directory( unsigned int   mode,        // mode for IOC driver
    453                            unsigned int   cluster,     // cluster containing dir_entry
    454                            char*          file_name,   // searched file/directory name
    455                            unsigned int*  file_size )  // file size
     889static int scan_directory( unsigned int   mode,            // mode for IOC driver
     890                           unsigned int   cluster,         // cluster containing dir_entry
     891                           char*          file_name,       // searched file/directory name
     892                           unsigned int*  file_size,       // file size
     893                           unsigned int*  lba_dir_entry )  // lba of dir_entry
    456894{
    457895
     
    523961                block_id = fat.sectors_per_cluster;
    524962            }
    525             if( _ioc_read( mode,             // mode for IOC driver
    526                            lba,              // sector index
     963            if( _ioc_read( mode,            // mode for IOC driver
     964                           lba,             // sector index
    527965                           fat.fat_cache,   // buffer address
    528                            1 ) )             // one sector
     966                           1 ) )            // one sector
    529967            {
    530968                _tty_get_lock( 0 );
     
    6071045                {
    6081046                    *file_size = read_entry( DIR_FILE_SIZE , dir_entry, 1 );
     1047                    *lba_dir_entry = lba;
    6091048                    return read_cluster( dir_entry );
    6101049                }
     
    6311070            offset     = offset + DIR_ENTRY_SIZE;
    6321071            *file_size = read_entry( DIR_FILE_SIZE, dir_entry, 1 );
     1072            *lba_dir_entry = lba;
    6331073
    6341074#if GIET_DEBUG_FAT
     
    6431083} // end scan_directory()
    6441084
    645 ///////////////////////////////////////////////////////////////////////
    646 // This function analyses the pathname argument, from the character
    647 // defined by the *nb_read argument.
    648 // It copies the found name (between '/') in the name[] buffer,
    649 // and updates the nb_read argument.
    650 // Return 1 if name found, Return 0 if NUL character found,
    651 ///////////////////////////////////////////////////////////////////////
    652 static int get_name_from_path( char*          pathname,
    653                                char*          name,
    654                                unsigned int*  nb_read )
    655 {
    656     if ( pathname[*nb_read] == 0 ) return 0;
    657 
    658     int i = (pathname[*nb_read] == '/')? (*nb_read) + 1 : *nb_read;
    659     int j = 0;
    660    
    661     while(pathname[i] != '/' && pathname[i] != '\0')
    662     {
    663         name[j] = pathname[i];   
    664         j++;
    665         i++;
    666     }
    667     name[j] = 0;
    668 
    669     if ( pathname[i] == '/' ) *nb_read += j+1;
    670     else                      *nb_read += j;
    671 
    672     return 1;
    673 }
    6741085
    6751086//////////////////////////////////////////////////////////////////////
     
    7441155
    7451156    // load Partition Boot Record (first partition sector) into fat cache
    746     if ( _ioc_read( mode,                 // mode for IOC driver
     1157    if ( _ioc_read( mode,                // mode for IOC driver
    7471158                    fat.partition_lba,   // sector index
    7481159                    fat.fat_cache,       // buffer address
    749                     1 ) )                 // one sector
     1160                    1 ) )                // one sector
    7501161    {
    7511162        _tty_get_lock( 0 );
     
    8021213        return -1; 
    8031214    }
     1215    fat.fs_info_lba         = read_entry( BPB_FAT32_FSINFO, fat.fat_cache, 1 ) + fat.partition_lba;
    8041216
    8051217    // initialise fat descriptor from partition first sector
     
    8141226    for( n = 0 ; n < GIET_OPEN_FILES_MAX ; n++ ) fat.fd[n].used = 0;
    8151227
    816 #if (GIET_DEBUG_FAT == 1)
     1228#if GIET_DEBUG_FAT
     1229_tty_get_lock( 0 );
     1230_puts("\n[FAT DEBUG] FS_INFO Sector = ");
     1231_putd(fat.fs_info_lba);
     1232_puts("\n");
     1233_tty_release_lock( 0 );
     1234#endif
     1235
     1236    // load FS_INFO into fat cache
     1237    if ( _ioc_read( mode,               // mode for IOC driver
     1238                    fat.fs_info_lba,    // sector index
     1239                    fat.fat_cache,      // buffer address
     1240                    1 ) )               // one sector
     1241    {
     1242        _tty_get_lock( 0 );
     1243        _puts("\n[FAT ERROR] in _fat_init() cannot load FS_INFO Sector\n");
     1244        _tty_release_lock( 0 );
     1245        return -1;
     1246    }
     1247    fat.cache_lba = fat.fs_info_lba;
     1248
     1249    fat.number_free_cluster    = read_entry( FS_FREE_CLUSTER     , fat.fat_cache, 1);
     1250    fat.last_cluster_allocated = read_entry( FS_FREE_CLUSTER_HINT, fat.fat_cache, 1);
     1251
     1252#if GIET_DEBUG_FAT
     1253_tty_get_lock( 0 );
     1254_puts("\n[FAT DEBUG] Number of Free Clusters = ");
     1255_putd(fat.number_free_cluster);
     1256_puts("\n");
     1257_puts("\n[FAT DEBUG] Last known cluster allocated = ");
     1258_putd(fat.last_cluster_allocated);
     1259_puts("\n");
     1260_puts("\n[FAT DEBUG] FS_INFO Sector Loaded\n");
     1261_tty_release_lock( 0 );
     1262#endif
     1263
     1264
     1265#if GIET_DEBUG_FAT
    8171266_tty_get_lock( 0 );
    8181267_puts("\n[FAT DEBUG] Exit _fat_init()\n");
     
    8591308    unsigned int         file_size;    // number of bytes
    8601309    unsigned int         last_name;    // directory containing file name is reached
     1310    unsigned int         lba;          // lba of dir_entry for this file
    8611311   
    8621312#if GIET_DEBUG_FAT
     
    8731323        if ( _fat_init( mode ) )
    8741324        {
    875             _puts("[FAT ERROR] Cannot initialize FAT descriptor fom Boot Sector\n");
     1325            _puts("[FAT ERROR] Cannot initialize FAT descriptor from Boot Sector\n");
    8761326            _exit();
    8771327        }
     
    9061356_tty_release_lock( 0 );
    9071357#endif
     1358
    9081359        // test if we reach the last name (file name)
    9091360        if( pathname[nb_read] == 0 ) 
     
    9141365
    9151366        // scan current directory
    916         cluster  = scan_directory( mode, cluster, name, &file_size );
     1367        cluster  = scan_directory( mode, cluster, name, &file_size, &lba );
    9171368
    9181369        if( cluster == END_OF_CHAIN_CLUSTER && last_name && creat )
     
    9591410            fat.fd[fd_id].first_cluster = cluster;
    9601411            fat.fd[fd_id].file_size     = file_size;
     1412            fat.fd[fd_id].lba_dir_entry = lba;
    9611413            _strcpy( fat.fd[fd_id].name, pathname );
    9621414
     
    11621614// - mode   : mode for the IOC driver
    11631615// - fd_id  : open file descriptor index 
    1164 // - fd_id  : open file descriptor index 
    11651616// - buffer : base address of the memory buffer (must be sector aligned)
    11661617// - offset : number of sectors to skip in file
     
    11841635    unsigned int sectors_to_skip;   // number of sectors to skip in first iteration
    11851636    unsigned int allocate;          // need allocate or not
     1637    unsigned int current_cluster;   // number of cluster allocated to the file
     1638    unsigned int required_cluster;  // number of cluster needed for the write
    11861639
    11871640    // compute file size as a number of sectors
     
    11891642    if ( file_size & 0x1FF ) file_sectors = (file_size >> 9) + 1;
    11901643    else                     file_sectors = (file_size >> 9);
    1191    
    1192     allocate = ( ((count + offset) / spc) > (file_sectors / spc) );
     1644
     1645    // Compute the number of clusters occupied by the file
     1646    current_cluster = file_sectors / spc;
     1647
     1648    // Compute the number of clusters that will occupy the file (after fat_write)
     1649    required_cluster = (count + offset) / spc;
     1650
     1651    // Check if we need to allocate new cluster(s) for the file 
     1652    allocate = ( required_cluster > current_cluster );
    11931653
    11941654#if GIET_DEBUG_FAT
     
    12051665_putd( file_sectors );
    12061666_puts("\n - need allocate = ");
    1207 allocate ? _puts( "True" ) : _puts( "False");
    1208 _tty_release_lock( 0 );
    1209 #endif
    1210 
    1211     if ( allocate  )
    1212     {
    1213         _tty_get_lock( 0 );
    1214         _puts("\n[FAT ERROR] in _fat_write() : \n");
    1215         _puts("we need to allocate more cluster... But this function is not implemented\n");
    1216         _tty_release_lock( 0 );
    1217         return -1;
    1218     }
     1667 allocate ? _puts( "True" ) : _puts( "False");
     1668_tty_release_lock( 0 );
     1669#endif
     1670
    12191671    // arguments checking
    12201672    if ( fd_id >= GIET_OPEN_FILES_MAX )
     
    12381690        _tty_release_lock( 0 );
    12391691        return -1;
     1692    }
     1693
     1694    if ( allocate  )
     1695    {
     1696        if ( _fat_allocate( fd_id, (required_cluster - current_cluster) ) < 0 )
     1697        {
     1698            _tty_get_lock( 0 );
     1699            _puts("\n[FAT ERROR] in _fat_write() : fat_allocate for file ");
     1700            _putd( fd_id );
     1701            _puts(" failed\n");
     1702            _tty_release_lock( 0 );
     1703            return -1;
     1704        }
    12401705    }
    12411706
     
    13141779        if ( todo_sectors > spc ) iter_sectors = spc;
    13151780        else                      iter_sectors = todo_sectors;
     1781    }
     1782
     1783    // Update structure file descriptor, field file_size with
     1784    // the new file size if the file is bigger than the previous file
     1785    if ( ( offset + count ) > file_sectors )
     1786    {
     1787        fat.fd[fd_id].file_size = (count + offset) << 9;
     1788    }
     1789
     1790    // Update entry of directory with the new value
     1791    // of file size (Field : DIR_FILE_SIZE)
     1792    if ( update_entry(fd_id, DIR_FILE_SIZE, fat.fd[fd_id].file_size) )
     1793    {
     1794            _tty_get_lock( 0 );
     1795            _puts("\n[FAT ERROR] in _fat_write() update entry for file ");
     1796            _putd( fd_id );
     1797            _puts(" failed\n");
     1798            _tty_release_lock( 0 );
     1799            return -1;
    13161800    }
    13171801         
  • soft/giet_vm/giet_fat32/fat32.h

    r260 r291  
    6767#define FS_SIGNATURE_POSITION_2           484 , 4
    6868#define FS_SIGNATURE_POSITION_3           508 , 4 
    69 #define FS_FREE_CLUSTER                   492 , 4
    70 #define FS_FREE_CLUSTER_HINT              496 , 4
     69#define FS_FREE_CLUSTER                   488 , 4
     70#define FS_FREE_CLUSTER_HINT              492 , 4
    7171/***************************************************************************************/
    7272
     
    9898/***************************************************************************************/
    9999
    100 /***********************  DIR_ATTR values  (attributes) ********************************/ 
     100/***********************  DIR_ATTR values  (attributes) ********************************/
    101101#define ATTR_READ_ONLY          0x01
    102102#define ATTR_HIDDEN             0x02
     
    128128   unsigned int  first_cluster;             // first cluster index in partition
    129129   unsigned int  file_size;                 // number of bytes   
     130   unsigned int  lba_dir_entry;             // lba of dir_entry for an open file
    130131   char          name[244];                 // pathname
    131132}  file_desc_t;
     
    146147    unsigned int    data_lba;                // lba of first data sector 
    147148    unsigned int    cache_lba;               // lba of sector loaded in fat_cache
     149    unsigned int    last_cluster_allocated;  // Last known cluster allocated
     150    unsigned int    number_free_cluster;     // number of free clusters
     151    unsigned int    fs_info_lba;             // lba of fs_info
    148152} fat32_fs_t;
    149153/***************************************************************************************/
Note: See TracChangeset for help on using the changeset viewer.