Index: soft/giet_vm/giet_fat32/fat32.c
===================================================================
--- soft/giet_vm/giet_fat32/fat32.c	(revision 289)
+++ soft/giet_vm/giet_fat32/fat32.c	(revision 291)
@@ -83,5 +83,5 @@
 } // end display_fat_cache()  
 #endif
- 
+
 //////////////////////////////////////////////////////////////////////////////////
 // This function returns the length of a FAT field. This field is identified
@@ -92,4 +92,26 @@
 {
     return length;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Write one 32 bits word "value" in a char[] buffer. 
+// This field is defined by the offset and size arguments.
+//////////////////////////////////////////////////////////////////////////////
+static void write_entry( unsigned int   offset,
+                         unsigned int   size,
+                         char*          buffer,
+                         unsigned int   value )
+{
+    unsigned int turn = 0;
+    unsigned int res  = value;
+    unsigned int mask = 0x000000ff;
+
+    while( turn != size - 1 )
+    {
+        buffer[ offset + turn ] = res & mask;
+        res = res >> 8;
+        turn++;
+    }
+    buffer[offset + turn] = res & mask;
 }
 
@@ -200,14 +222,4 @@
     }
 }
-
-///////////////////////////////////////////////////////////////////////////////
-// This function returns the cluster index from a (32 bytes) directory entry
-///////////////////////////////////////////////////////////////////////////////
-static inline unsigned int read_cluster( char* buf )                 
-{
-   unsigned int cluster = read_entry( DIR_FST_CLUS_HI, buf, 1 ) << 16;
-   cluster = cluster | read_entry( DIR_FST_CLUS_LO, buf, 1 );
-   return cluster;
-} 
 
 //////////////////////////////////////////////////////
@@ -356,4 +368,34 @@
 }
 
+///////////////////////////////////////////////////////////////////////
+// This function analyses the pathname argument, from the character 
+// defined by the *nb_read argument.
+// It copies the found name (between '/') in the name[] buffer, 
+// and updates the nb_read argument.
+// Return 1 if name found, Return 0 if NUL character found, 
+///////////////////////////////////////////////////////////////////////
+static int get_name_from_path( char*          pathname,
+                               char*          name,
+                               unsigned int*  nb_read )	
+{
+    if ( pathname[*nb_read] == 0 ) return 0;
+
+    int i = (pathname[*nb_read] == '/')? (*nb_read) + 1 : *nb_read;
+    int j = 0;
+   
+    while(pathname[i] != '/' && pathname[i] != '\0')
+    {
+        name[j] = pathname[i];    
+        j++;
+        i++;
+    }
+    name[j] = 0;
+
+    if ( pathname[i] == '/' ) *nb_read += j+1;
+    else                      *nb_read += j;
+
+    return 1;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 static int get_name_from_short( char* dir_entry,     // input:  SFN dir_entry
@@ -372,7 +414,8 @@
     return i;
 }
+
 ///////////////////////////////////////////////////////////////////////////////
-static int get_name_from_long( char *dir_entry,    // input : LFN dir_entry
-                               char *entry_name)   // output : name
+static int get_name_from_long( char *dir_entry,     // input : LFN dir_entry
+                               char *entry_name )   // output : name
 {
     unsigned int   entry_name_offset   = 0;
@@ -444,4 +487,398 @@
 } // end get_name_from_long()
 
+//////////////////////////////////////////////////////////////////////////////////////
+// This function update a DIR_ENTRY, write a new value into a specific field 
+// (ex : DIR_FILE_SIZE, when we want update the file size after a fat_write)
+// Return 0 in case of success, > 0 if failure.
+//////////////////////////////////////////////////////////////////////////////////////
+// TODO : make this function less complex
+//////////////////////////////////////////////////////////////////////////////////////
+static inline unsigned int update_entry( unsigned int fd_id, 
+                                         unsigned int field,
+                                         unsigned int size,
+                                         unsigned int value )
+{
+    char dir_entry[32];   // buffer to store a full directory_entry
+    char name_entry[14];  // buffer to store a 13 characters (partial) name
+    char file_name[256];  // buffer to store the name (not pathname) of the file
+    char sfn[12]            = {[0 ... 10] = ' ', '\0'};      // buffer for a Short File Name
+
+    unsigned int lba       = fat.fd[fd_id].lba_dir_entry;    // Lba of file dir_entry
+    unsigned int is_sfn;         
+    unsigned int attr      = 0;                              // directory entry attribute
+    unsigned int ord       = 0;                              // directory entry sequence
+    unsigned int found     = 0;                              // name found
+    unsigned int offset    = 0;
+    unsigned int i         = 0;
+    unsigned int nb_read   = 0;
+
+    for ( i = 0 ; i < 32 ; i++ ) dir_entry[i]  = 0;
+    for ( i = 0 ; i < 14 ; i++ ) name_entry[i] = 0;
+    
+    // Get the name of the file.
+    while ( get_name_from_path( fat.fd[fd_id].name, file_name, &nb_read ) )
+    {
+    }
+
+    // Check if file_name is short
+    is_sfn = is_short( file_name, sfn );
+
+    if ( _ioc_read( IOC_KERNEL_MODE, // mode for IOC driver
+                    lba,             // sector index 
+                    fat.fat_cache,   // buffer address
+                    1 ) )            // one sector
+    {
+        _tty_get_lock( 0 );
+        _puts("[FAT ERROR] in update_entry() cannot read sector ");
+        _putd( lba );
+        _puts("\n");
+        _tty_release_lock( 0 );
+        return 1;
+    }
+    fat.cache_lba = lba;
+
+    // - the offset increment is an integer number of directory entry (32 bytes)
+    // - the exit condition is success (name found) or failure (end of directory) 
+    while ( !found )
+    {
+        attr = read_entry( DIR_ATTR, fat.fat_cache + offset, 0 );
+        ord  = read_entry( LDIR_ORD, fat.fat_cache + offset, 0 );
+
+        if ( is_sfn == 1 )		                       // searched name is short
+        {
+            if      ( (ord != FREE_ENTRY ) &&
+                    (ord != NO_MORE_ENTRY) &&
+                    (attr == ATTR_LONG_NAME_MASK) )    // LFN entry : skipped
+            {
+                offset     = offset + ((ord & 0xF) * DIR_ENTRY_SIZE);
+                continue;
+            }
+            else if ( (attr != ATTR_LONG_NAME_MASK) && 
+                    (ord  != FREE_ENTRY) && 
+                    (ord  != NO_MORE_ENTRY ) )         // SFN entry : checked
+            {
+                _memcpy( dir_entry, fat.fat_cache + offset, DIR_ENTRY_SIZE );    
+            }
+            else if (ord == NO_MORE_ENTRY )            // end of directory : return
+            {
+                _tty_get_lock( 0 );
+                _puts("[FAT ERROR] in update_entry() end of directory reaches ");
+                _puts("\n");
+                _tty_release_lock( 0 );
+                return 1;
+            }
+            else									   // free entry : skipped
+            {
+                offset = offset + DIR_ENTRY_SIZE;
+                continue;
+            }
+        }
+        else                                           // searched name is long
+        {
+            if      ( (attr == ATTR_LONG_NAME_MASK) && 
+                    (ord != FREE_ENTRY) &&
+                    (ord != NO_MORE_ENTRY) )           // LFN entry : checked
+            {
+                _memcpy( dir_entry, fat.fat_cache + offset, DIR_ENTRY_SIZE );    
+            }
+            else if ( (attr != ATTR_LONG_NAME_MASK) && 
+                    (ord  != FREE_ENTRY) && 
+                    (ord  != NO_MORE_ENTRY))		   // SFN entry : skipped
+            {
+                offset = offset + DIR_ENTRY_SIZE;
+                continue;
+            }
+            else if (ord == NO_MORE_ENTRY )			   // end of directory : return
+            {
+                _tty_get_lock( 0 );
+                _puts("[FAT ERROR] in update_entry() end of directory reaches ");
+                _puts("\n");
+                _tty_release_lock( 0 );
+                return 1;
+            }
+            else                                       // free entry : skipped
+            {
+                offset = offset + DIR_ENTRY_SIZE;
+                continue;
+            }
+        }
+
+        // testing the name extracted from dir entry
+
+        if ( is_sfn == 1 )                             // searched name is short
+        {
+            get_name_from_short( dir_entry, name_entry );
+
+            if ( _strncmp( (char*)sfn, (char*)name_entry, 13 ) == 0 )
+            {
+                write_entry(offset + field, size, fat.fat_cache, value);
+                found = 1;
+            }
+            else								       // no matching : skip
+            {
+                offset = offset + DIR_ENTRY_SIZE;
+            }
+        }
+        else                                           // searched name is long
+        {
+            get_name_from_long( dir_entry, name_entry );
+
+            unsigned shift = ((ord & 0xf) - 1) * 13;
+            if ( _strncmp( (char*)(file_name + shift), (char*)name_entry, 13 ) == 0 )
+            {
+                if ( (ord & 0xf) == 1 )
+                {
+                    offset = offset + DIR_ENTRY_SIZE;
+                    write_entry(offset + field, size, fat.fat_cache, value);
+                    found = 1;
+                }
+                offset = offset + DIR_ENTRY_SIZE;
+                continue;
+            }
+            else								       // no matching : skip
+            {
+                offset = offset + ((ord & 0xf) * DIR_ENTRY_SIZE) + DIR_ENTRY_SIZE;
+            }
+        }
+    }
+
+    return _ioc_write( IOC_KERNEL_MODE,
+                       lba,  
+                       fat.fat_cache,
+                       1     );
+}
+//////////////////////////////////////////////////////////////////////////////////
+// This function update FS_INFO, for new last cluster allocated and number of free
+// cluster. 
+// Return 0 in case of success, > 0 if failure.
+//////////////////////////////////////////////////////////////////////////////////
+static inline unsigned int update_fs_info( )
+{
+    unsigned int lba = fat.fs_info_lba;
+
+#if GIET_DEBUG_FAT
+_tty_get_lock( 0 );
+_puts("\n[FAT DEBUG] Enter in update_fs_info()\n");
+_tty_release_lock( 0 );
+#endif
+
+    if ( lba == fat.cache_lba )            // hit cache
+    {
+        write_entry( FS_FREE_CLUSTER     , fat.fat_cache, fat.number_free_cluster );
+        write_entry( FS_FREE_CLUSTER_HINT, fat.fat_cache, fat.last_cluster_allocated );
+    }
+    else                                   // miss cache
+    {
+        if ( _ioc_read( IOC_KERNEL_MODE,   // mode for IOC driver
+                        lba,               // sector index 
+                        fat.fat_cache,     // fat cache
+                        1 ) )              // one sector
+        {
+            _tty_get_lock( 0 );
+            _puts("[FAT_ERROR] in update_fat() cannot read block ");
+            _putd( lba );
+            _puts("\n");
+            _tty_release_lock( 0 );
+            return 1;
+        }
+        fat.cache_lba = lba;
+        write_entry( FS_FREE_CLUSTER     , fat.fat_cache, fat.number_free_cluster );
+        write_entry( FS_FREE_CLUSTER_HINT, fat.fat_cache, fat.last_cluster_allocated );
+    }
+    return _ioc_write( IOC_KERNEL_MODE,       
+                       lba,           
+                       fat.fat_cache,           
+                       1 ); 
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+// This function update FAT, write a new value into cluster index.
+// Used by the function _fat_allocate to update the chaining of clusters.
+// Return 0 in case of success, > 0 if failure.
+//////////////////////////////////////////////////////////////////////////////////
+static inline unsigned int update_fat( unsigned int cluster, 
+                                       unsigned int value  )
+{
+    unsigned int lba = fat.partition_lba + 32 + (cluster / 128);
+
+#if GIET_DEBUG_FAT
+_tty_get_lock( 0 );
+_puts("\n[FAT DEBUG] Enter in update_fat() :\n");
+_puts("    - Cluster to update = ");
+_putd( cluster );
+_puts("\n");
+_puts("    - Value to write = ");
+_putd( value );
+_puts("\n");
+_tty_release_lock( 0 );
+#endif
+
+    if ( lba == fat.cache_lba )            // hit cache
+    {
+        write_entry( ((cluster % 128) << 2), 4, fat.fat_cache, value );
+    }
+    else                                   // miss cache
+    {
+        if ( _ioc_read( IOC_KERNEL_MODE,   // mode for IOC driver
+                        lba,               // sector index 
+                        fat.fat_cache,     // fat cache
+                        1 ) )              // one sector
+        {
+            _tty_get_lock( 0 );
+            _puts("[FAT_ERROR] in update_fat() cannot read block ");
+            _putd( lba );
+            _puts("\n");
+            _tty_release_lock( 0 );
+            return 1;
+        }
+        fat.cache_lba = lba;
+        write_entry( ((cluster % 128) << 2), 4, fat.fat_cache, value );
+    }
+    return _ioc_write( IOC_KERNEL_MODE,       
+                       lba,           
+                       fat.fat_cache,           
+                       1 ); 
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+// This function allocate a count number of cluster to a file by calling the
+// update_fat function that takes care to update the chaining of clusters.
+// return 0 if success, -1 if failure
+//////////////////////////////////////////////////////////////////////////////////
+static inline int _fat_allocate( unsigned int fd_id, 
+                                 unsigned int count )
+{
+    unsigned int next_cluster        = fat.fd[fd_id].first_cluster;   // Get the first cluster of file
+    unsigned int cluster_to_allocate = count;                         // Number of cluster to allocate
+
+    unsigned int last_cluster_file;                                   // Last cluster of the file (EOC)
+
+    unsigned int free_cluster = fat.last_cluster_allocated + 1;       // First free cluster
+
+    // Check if free_cluster is really free (must be true)
+    if ( get_next_cluster_id( IOC_KERNEL_MODE, free_cluster ) != FREE_CLUSTER)
+    {
+        _tty_get_lock( 0 );
+        _puts("\n[FAT ERROR] in _fat_allocate() : first free_cluster isnt free\n");
+        _tty_release_lock( 0 );
+        return -1;
+    }
+    // Check if FAT contains enough cluster free for this allocation
+    if ( count > fat.number_free_cluster )
+    {
+        _tty_get_lock( 0 );
+        _puts("\n[FAT ERROR] in _fat_allocate() : Not enough free cluster(s) for this allocation\n");
+        _tty_release_lock( 0 );
+        return -1;
+    }
+
+#if GIET_DEBUG_FAT
+_tty_get_lock( 0 );
+_puts("\n[FAT DEBUG] Enter in _fat_allocate() :\n");
+_puts("    - Need to allocate ");
+_putd( count );
+_puts(" cluster(s) for file ");
+_putd( fd_id );
+_puts("\n");
+_tty_release_lock( 0 );
+#endif
+
+    // Get the last cluster allocated for the file (seek END_OF_CHAIN_CLUSTER).
+    do{
+        last_cluster_file = next_cluster;
+        next_cluster      = get_next_cluster_id( IOC_KERNEL_MODE, next_cluster );
+    }while ( next_cluster < END_OF_CHAIN_CLUSTER );
+
+    // Loop on the number of cluster needed to be allocated
+    while ( cluster_to_allocate > 0 )
+    {
+
+#if GIET_DEBUG_FAT
+_tty_get_lock( 0 );
+_puts("\n[FAT DEBUG] Cluster to update is : ");
+_putd( last_cluster_file );
+_puts("\n");
+_puts("[FAT DEBUG] Free cluster is : ");
+_putd( free_cluster );
+_puts("\n");
+_puts("[FAT DEBUG] Number of cluster need to be allocated : ");
+_putd( cluster_to_allocate );
+_puts("\n");
+_tty_release_lock( 0 );
+#endif
+
+        // update, in the FAT, the value of last cluster allocated by the index
+        // of free cluster.
+        if ( update_fat( last_cluster_file, free_cluster ) )
+        {
+            _tty_get_lock( 0 );
+            _puts("\n[FAT ERROR] in _fat_allocate() : update fat for file ");
+            _putd( fd_id );
+            _puts(" failed\n");
+            _tty_release_lock( 0 );
+            return -1;
+        }
+
+        cluster_to_allocate = cluster_to_allocate - 1;
+        // Last cluster allocated is then free_cluster
+        last_cluster_file = free_cluster;
+
+        // Last cluster to allocate done, then we must close the chain of clusters
+        if ( cluster_to_allocate == 0 )
+        {
+            // update, in the FAT, the value of the last cluster allocated by
+            // END_OF_CHAIN_CLUSTER
+            if ( update_fat( last_cluster_file, END_OF_CHAIN_CLUSTER ) )
+            {
+                _tty_get_lock( 0 );
+                _puts("\n[FAT ERROR] in _fat_allocate() : update fat for file ");
+                _putd( fd_id );
+                _puts(" failed\n");
+                _tty_release_lock( 0 );
+                return -1;
+            }
+        }
+
+        free_cluster = free_cluster + 1;
+
+        // Check if free_cluster is really free (must be true)
+        if ( get_next_cluster_id( IOC_KERNEL_MODE, free_cluster ) != FREE_CLUSTER)
+        {
+            _tty_get_lock( 0 );
+            _puts("\n[FAT ERROR] in _fat_allocate() : free_cluster isnt free\n");
+            _tty_release_lock( 0 );
+            return -1;
+        }
+    }
+
+    // Update field number_free_cluster and last_cluster_allocated 
+    // of structure fat for next fat_allocate
+    fat.last_cluster_allocated = last_cluster_file;
+    fat.number_free_cluster    = fat.number_free_cluster - count;
+
+    if ( update_fs_info() )
+    {
+        _tty_get_lock( 0 );
+        _puts("\n[FAT ERROR] in _fat_allocate() : update fs_info for file ");
+        _putd( fd_id );
+        _puts(" failed\n");
+        _tty_release_lock( 0 );
+        return -1;
+    }
+
+    return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// This function returns the cluster index from a (32 bytes) directory entry
+///////////////////////////////////////////////////////////////////////////////
+static inline unsigned int read_cluster( char* buf )                 
+{
+   unsigned int cluster = read_entry( DIR_FST_CLUS_HI, buf, 1 ) << 16;
+   cluster = cluster | read_entry( DIR_FST_CLUS_LO, buf, 1 );
+   return cluster;
+} 
+
+
 ////////////////////////////////////////////////////////////////////////////////////////
 // This function read the blocks defined by the cluster index argument, in a data 
@@ -450,8 +887,9 @@
 // Return cluster index if name found / Return -1 if not found,
 ////////////////////////////////////////////////////////////////////////////////////////
-static int scan_directory( unsigned int   mode,        // mode for IOC driver
-                           unsigned int   cluster,     // cluster containing dir_entry 
-                           char*          file_name,   // searched file/directory name
-                           unsigned int*  file_size )  // file size
+static int scan_directory( unsigned int   mode,            // mode for IOC driver
+                           unsigned int   cluster,         // cluster containing dir_entry 
+                           char*          file_name,       // searched file/directory name
+                           unsigned int*  file_size,       // file size
+                           unsigned int*  lba_dir_entry )  // lba of dir_entry
 {
 
@@ -523,8 +961,8 @@
                 block_id = fat.sectors_per_cluster;
             }
-            if( _ioc_read( mode,             // mode for IOC driver
-                           lba,              // sector index 
+            if( _ioc_read( mode,            // mode for IOC driver
+                           lba,             // sector index 
                            fat.fat_cache,   // buffer address
-                           1 ) )             // one sector
+                           1 ) )            // one sector
             {
                 _tty_get_lock( 0 );
@@ -607,4 +1045,5 @@
                 {
                     *file_size = read_entry( DIR_FILE_SIZE , dir_entry, 1 );
+                    *lba_dir_entry = lba;
                     return read_cluster( dir_entry );
                 }
@@ -631,4 +1070,5 @@
             offset     = offset + DIR_ENTRY_SIZE;
             *file_size = read_entry( DIR_FILE_SIZE, dir_entry, 1 );
+            *lba_dir_entry = lba;
 
 #if GIET_DEBUG_FAT
@@ -643,33 +1083,4 @@
 } // end scan_directory()
 
-///////////////////////////////////////////////////////////////////////
-// This function analyses the pathname argument, from the character 
-// defined by the *nb_read argument.
-// It copies the found name (between '/') in the name[] buffer, 
-// and updates the nb_read argument.
-// Return 1 if name found, Return 0 if NUL character found, 
-///////////////////////////////////////////////////////////////////////
-static int get_name_from_path( char*          pathname,
-                               char*          name,
-                               unsigned int*  nb_read )	
-{
-    if ( pathname[*nb_read] == 0 ) return 0;
-
-    int i = (pathname[*nb_read] == '/')? (*nb_read) + 1 : *nb_read;
-    int j = 0;
-   
-    while(pathname[i] != '/' && pathname[i] != '\0')
-    {
-        name[j] = pathname[i];    
-        j++;
-        i++;
-    }
-    name[j] = 0;
-
-    if ( pathname[i] == '/' ) *nb_read += j+1;
-    else                      *nb_read += j;
-
-    return 1;
-}
 
 //////////////////////////////////////////////////////////////////////
@@ -744,8 +1155,8 @@
 
     // load Partition Boot Record (first partition sector) into fat cache
-    if ( _ioc_read( mode,                 // mode for IOC driver
+    if ( _ioc_read( mode,                // mode for IOC driver
                     fat.partition_lba,   // sector index
                     fat.fat_cache,       // buffer address
-                    1 ) )                 // one sector
+                    1 ) )                // one sector
     {
         _tty_get_lock( 0 );
@@ -802,4 +1213,5 @@
         return -1;  
     }
+    fat.fs_info_lba         = read_entry( BPB_FAT32_FSINFO, fat.fat_cache, 1 ) + fat.partition_lba;
 
     // initialise fat descriptor from partition first sector
@@ -814,5 +1226,42 @@
     for( n = 0 ; n < GIET_OPEN_FILES_MAX ; n++ ) fat.fd[n].used = 0;
 
-#if (GIET_DEBUG_FAT == 1)
+#if GIET_DEBUG_FAT
+_tty_get_lock( 0 );
+_puts("\n[FAT DEBUG] FS_INFO Sector = ");
+_putd(fat.fs_info_lba);
+_puts("\n");
+_tty_release_lock( 0 );
+#endif
+
+    // load FS_INFO into fat cache
+    if ( _ioc_read( mode,               // mode for IOC driver
+                    fat.fs_info_lba,    // sector index 
+                    fat.fat_cache,      // buffer address
+                    1 ) )               // one sector
+    { 
+        _tty_get_lock( 0 );
+        _puts("\n[FAT ERROR] in _fat_init() cannot load FS_INFO Sector\n"); 
+        _tty_release_lock( 0 );
+        return -1;
+    }
+    fat.cache_lba = fat.fs_info_lba;
+
+    fat.number_free_cluster    = read_entry( FS_FREE_CLUSTER     , fat.fat_cache, 1);
+    fat.last_cluster_allocated = read_entry( FS_FREE_CLUSTER_HINT, fat.fat_cache, 1);
+
+#if GIET_DEBUG_FAT
+_tty_get_lock( 0 );
+_puts("\n[FAT DEBUG] Number of Free Clusters = ");
+_putd(fat.number_free_cluster);
+_puts("\n");
+_puts("\n[FAT DEBUG] Last known cluster allocated = ");
+_putd(fat.last_cluster_allocated);
+_puts("\n");
+_puts("\n[FAT DEBUG] FS_INFO Sector Loaded\n");
+_tty_release_lock( 0 );
+#endif
+
+
+#if GIET_DEBUG_FAT
 _tty_get_lock( 0 );
 _puts("\n[FAT DEBUG] Exit _fat_init()\n");
@@ -859,4 +1308,5 @@
     unsigned int         file_size;    // number of bytes
     unsigned int         last_name;    // directory containing file name is reached
+    unsigned int         lba;          // lba of dir_entry for this file
     
 #if GIET_DEBUG_FAT
@@ -873,5 +1323,5 @@
         if ( _fat_init( mode ) )
         {
-            _puts("[FAT ERROR] Cannot initialize FAT descriptor fom Boot Sector\n");
+            _puts("[FAT ERROR] Cannot initialize FAT descriptor from Boot Sector\n");
             _exit();
         }
@@ -906,4 +1356,5 @@
 _tty_release_lock( 0 );
 #endif
+
         // test if we reach the last name (file name)
         if( pathname[nb_read] == 0 )  
@@ -914,5 +1365,5 @@
 
         // scan current directory
-        cluster  = scan_directory( mode, cluster, name, &file_size );
+        cluster  = scan_directory( mode, cluster, name, &file_size, &lba );
 
         if( cluster == END_OF_CHAIN_CLUSTER && last_name && creat )
@@ -959,4 +1410,5 @@
             fat.fd[fd_id].first_cluster = cluster;
             fat.fd[fd_id].file_size     = file_size;
+            fat.fd[fd_id].lba_dir_entry = lba;
             _strcpy( fat.fd[fd_id].name, pathname );
 
@@ -1162,5 +1614,4 @@
 // - mode   : mode for the IOC driver
 // - fd_id  : open file descriptor index  
-// - fd_id  : open file descriptor index  
 // - buffer : base address of the memory buffer (must be sector aligned)
 // - offset : number of sectors to skip in file
@@ -1184,4 +1635,6 @@
     unsigned int sectors_to_skip;   // number of sectors to skip in first iteration
     unsigned int allocate;          // need allocate or not
+    unsigned int current_cluster;   // number of cluster allocated to the file
+    unsigned int required_cluster;  // number of cluster needed for the write
 
     // compute file size as a number of sectors 
@@ -1189,6 +1642,13 @@
     if ( file_size & 0x1FF ) file_sectors = (file_size >> 9) + 1;
     else                     file_sectors = (file_size >> 9); 
-    
-    allocate = ( ((count + offset) / spc) > (file_sectors / spc) );
+
+    // Compute the number of clusters occupied by the file
+    current_cluster = file_sectors / spc;
+
+    // Compute the number of clusters that will occupy the file (after fat_write)
+    required_cluster = (count + offset) / spc;
+
+    // Check if we need to allocate new cluster(s) for the file  
+    allocate = ( required_cluster > current_cluster );
 
 #if GIET_DEBUG_FAT
@@ -1205,16 +1665,8 @@
 _putd( file_sectors );
 _puts("\n - need allocate = "); 
-allocate ? _puts( "True" ) : _puts( "False");
-_tty_release_lock( 0 );
-#endif
-
-    if ( allocate  )
-    {
-        _tty_get_lock( 0 );
-        _puts("\n[FAT ERROR] in _fat_write() : \n");
-        _puts("we need to allocate more cluster... But this function is not implemented\n");
-        _tty_release_lock( 0 );
-        return -1;
-    }
+ allocate ? _puts( "True" ) : _puts( "False");
+_tty_release_lock( 0 );
+#endif
+
     // arguments checking
     if ( fd_id >= GIET_OPEN_FILES_MAX )
@@ -1238,4 +1690,17 @@
         _tty_release_lock( 0 );
         return -1;
+    }
+
+    if ( allocate  )
+    {
+        if ( _fat_allocate( fd_id, (required_cluster - current_cluster) ) < 0 )
+        {
+            _tty_get_lock( 0 );
+            _puts("\n[FAT ERROR] in _fat_write() : fat_allocate for file ");
+            _putd( fd_id );
+            _puts(" failed\n");
+            _tty_release_lock( 0 );
+            return -1;
+        }
     }
 
@@ -1314,4 +1779,23 @@
         if ( todo_sectors > spc ) iter_sectors = spc;
         else                      iter_sectors = todo_sectors;
+    }
+
+    // Update structure file descriptor, field file_size with
+    // the new file size if the file is bigger than the previous file
+    if ( ( offset + count ) > file_sectors )
+    {
+        fat.fd[fd_id].file_size = (count + offset) << 9;
+    }
+
+    // Update entry of directory with the new value 
+    // of file size (Field : DIR_FILE_SIZE)
+    if ( update_entry(fd_id, DIR_FILE_SIZE, fat.fd[fd_id].file_size) )
+    {
+            _tty_get_lock( 0 );
+            _puts("\n[FAT ERROR] in _fat_write() update entry for file ");
+            _putd( fd_id );
+            _puts(" failed\n"); 
+            _tty_release_lock( 0 );
+            return -1;
     }
          
