- Main Page
- Modules
- Data Structures
- Files
- Related Pages

# file.c

Go to the documentation of this file.

    00001 /*This file has been prepared for Doxygen automatic documentation generation.*/
    00014 /* Copyright (C) 2006-2008, Atmel Corporation All rights reserved.
    00015  *
    00016  * Redistribution and use in source and binary forms, with or without
    00017  * modification, are permitted provided that the following conditions are met:
    00018  *
    00019  * 1. Redistributions of source code must retain the above copyright notice,
    00020  * this list of conditions and the following disclaimer.
    00021  *
    00022  * 2. Redistributions in binary form must reproduce the above copyright notice,
    00023  * this list of conditions and the following disclaimer in the documentation
    00024  * and/or other materials provided with the distribution.
    00025  *
    00026  * 3. The name of ATMEL may not be used to endorse or promote products derived
    00027  * from this software without specific prior written permission.
    00028  *
    00029  * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
    00030  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    00031  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE EXPRESSLY AND
    00032  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
    00033  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    00034  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    00035  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    00036  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    00037  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    00038  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    00039  */
    00040
    00041
    00042 //_____  I N C L U D E S ___________________________________________________
    00043 #include "conf_explorer.h"
    00044 #include "file.h"
    00045 #include "navigation.h"
    00046 #include LIB_MEM
    00047 #include LIB_CTRLACCESS
    00048
    00049
    00050 //_____ D E C L A R A T I O N S ____________________________________________
    00051
    00053 #if __GNUC__ && __AVR32__
    00054 __attribute__((__aligned__(4)))
    00055 #elif __ICCAVR32__
    00056 #pragma data_alignment = 4
    00057 #endif
    00058 extern   _MEM_TYPE_SLOW_   U8    fs_g_sector[ FS_CACHE_SIZE ];
    00059
    00060 static   void  file_load_segment_value( Fs_file_segment _MEM_TYPE_SLOW_ *segment );
    00061
    00062
    00063
    00069 Bool  file_ispresent( void )
    00070 {
    00071    if( !fat_check_mount_select() )
    00072       return FALSE;
    00073    return fat_check_is_file();
    00074 }
    00075
    00076
    00089 Bool  file_open( U8 fopen_mode )
    00090 {
    00091    if( !fat_check_mount_select_noopen())
    00092       return FALSE;
    00093
    00094    if( !fat_check_is_file())
    00095       return FALSE;
    00096
    00097    if(FOPEN_WRITE_ACCESS & fopen_mode)
    00098    {
    00099       if( !fat_check_nav_access_file( TRUE ) )
    00100          return FALSE;
    00101 #if (FSFEATURE_WRITE == (FS_LEVEL_FEATURES & FSFEATURE_WRITE))
    00102       if (FS_ATTR_READ_ONLY & fs_g_nav_entry.u8_attr)
    00103       {
    00104          fs_g_status = FS_ERR_READ_ONLY;  // File is read only
    00105          return FALSE;
    00106       }
    00107       if( mem_wr_protect( fs_g_nav.u8_lun  ))
    00108       {
    00109          fs_g_status = FS_LUN_WP;  // Disk read only
    00110          return FALSE;
    00111       }
    00112 #else
    00113       fs_g_status = FS_ERR_MODE_NOAVIALABLE;
    00114       return FALSE;
    00115 #endif  // FS_LEVEL_FEATURES
    00116    }
    00117    else
    00118    {
    00119       if( !fat_check_nav_access_file( FALSE ) )
    00120          return FALSE;
    00121    }
    00122
    00123    if(FOPEN_CLEAR_SIZE & fopen_mode)
    00124    {
    00125       fs_g_nav_entry.u32_size    = 0;     // The size is null
    00126    }
    00127    if(FOPEN_CLEAR_PTR & fopen_mode)
    00128    {
    00129       fs_g_nav_entry.u32_pos_in_file = 0;
    00130    }
    00131    else
    00132    {  // Go to at the end of file
    00133       fs_g_nav_entry.u32_pos_in_file = fs_g_nav_entry.u32_size;
    00134    }
    00135    fs_g_nav_entry.u8_open_mode = fopen_mode;
    00136    return TRUE;
    00137 }
    00138
    00139
    00144 static void file_load_segment_value( Fs_file_segment _MEM_TYPE_SLOW_ *segment )
    00145 {
    00146    segment->u8_lun = fs_g_nav.u8_lun;
    00147    segment->u32_addr = fs_g_seg.u32_addr;
    00148    segment->u16_size = fs_g_seg.u32_size_or_pos;
    00149 }
    00150
    00151
    00169 Bool  file_read( Fs_file_segment _MEM_TYPE_SLOW_ *segment )
    00170 {
    00171    U8 u8_nb_sector_truncated;
    00172
    00173    if( !fat_check_mount_select_open())
    00174       return FALSE;
    00175
    00176    if(!(FOPEN_READ_ACCESS & fs_g_nav_entry.u8_open_mode))
    00177    {
    00178       fs_g_status = FS_ERR_WRITE_ONLY;
    00179       return FALSE;
    00180    }
    00181
    00182    if ( file_eof() )
    00183    {
    00184       // End of the file
    00185       fs_g_status = FS_ERR_EOF;
    00186       return FALSE;
    00187    }
    00188
    00189    if( !fat_read_file(FS_CLUST_ACT_SEG))
    00190    {
    00191       if( FS_ERR_OUT_LIST == fs_g_status )
    00192          fs_g_status = FS_ERR_EOF;  // translate the error
    00193       return FALSE;
    00194    }
    00195    // If the segment is too large then truncate it
    00196    if( (segment->u16_size != 0)                          // if no limit then no truncate
    00197    &&  (segment->u16_size < fs_g_seg.u32_size_or_pos) )
    00198    {
    00199       u8_nb_sector_truncated   = fs_g_seg.u32_size_or_pos - segment->u16_size;
    00200       fs_g_seg.u32_size_or_pos = segment->u16_size ;
    00201    }else{
    00202       u8_nb_sector_truncated = 0;
    00203    }
    00204
    00205    // Update file position
    00206    fs_g_nav_entry.u32_pos_in_file += (U32)fs_g_seg.u32_size_or_pos * FS_512B;
    00207    if( fs_g_nav_entry.u32_size < fs_g_nav_entry.u32_pos_in_file )
    00208    {
    00209       // The segment is more larger then file
    00210       // case possible: if the file don't use all cluster space
    00211       // then compute sectors not used in last cluster of file cluster list
    00212       U8 u8_nb_sector_not_used;
    00213
    00214       // Compute the number of sector used in last cluster
    00215       // remark: also the two first bytes of size is used, because the cluster size can't be more larger then 64KB
    00216       u8_nb_sector_not_used = LSB1( fs_g_nav_entry.u32_size ) >> (FS_512B_SHIFT_BIT-8);
    00217       if( 0 != (fs_g_nav_entry.u32_size & FS_512B_MASK) )
    00218       {  // last sector of file isn't full, but it must been read
    00219          u8_nb_sector_not_used++;
    00220       }
    00221
    00222       // Compute the number of sector not used in last cluster
    00223       u8_nb_sector_not_used = fs_g_nav.u8_BPB_SecPerClus - (u8_nb_sector_not_used % fs_g_nav.u8_BPB_SecPerClus);
    00224       // if all space of cluster isn't used, then it is wrong
    00225       if( u8_nb_sector_not_used == fs_g_nav.u8_BPB_SecPerClus )
    00226          u8_nb_sector_not_used = 0; // The file uses all last cluster space
    00227
    00228       // Subtract this value a the file position and segment size
    00229       u8_nb_sector_not_used -= u8_nb_sector_truncated;
    00230       fs_g_seg.u32_size_or_pos -= u8_nb_sector_not_used;                                     // unit sector
    00231       fs_g_nav_entry.u32_pos_in_file -= ((U16)u8_nb_sector_not_used) << FS_512B_SHIFT_BIT;   // unit byte
    00232    }
    00233    file_load_segment_value( segment );
    00234    return TRUE;
    00235 }
    00236
    00237
    00246 U16   file_read_buf( U8 _MEM_TYPE_SLOW_ *buffer , U16 u16_buf_size )
    00247 {
    00248    _MEM_TYPE_FAST_ U16 u16_nb_read_tmp;
    00249    _MEM_TYPE_FAST_ U16 u16_nb_read;
    00250    _MEM_TYPE_FAST_ U16 u16_pos_in_sector;
    00251    _MEM_TYPE_FAST_ U32 u32_byte_remaining;
    00252
    00253    if( !fat_check_mount_select_open())
    00254       return FALSE;
    00255
    00256    if(!(FOPEN_READ_ACCESS & fs_g_nav_entry.u8_open_mode))
    00257    {
    00258       fs_g_status = FS_ERR_WRITE_ONLY;
    00259       return FALSE;
    00260    }
    00261
    00262    u16_nb_read = 0;
    00263
    00264    while( 0 != u16_buf_size )
    00265    {
    00266       if ( file_eof() )
    00267       {
    00268          fs_g_status = FS_ERR_EOF;
    00269          return u16_nb_read;     // End of the file
    00270       }
    00271       u32_byte_remaining = fs_g_nav_entry.u32_size-fs_g_nav_entry.u32_pos_in_file;
    00272       u16_pos_in_sector = fs_g_nav_entry.u32_pos_in_file % FS_512B;
    00273
    00274       if( (0== u16_pos_in_sector)
    00275       &&  (FS_512B <= u32_byte_remaining)
    00276       &&  (FS_512B <= u16_buf_size)
    00277 #if __GNUC__ && __AVR32__ || __ICCAVR32__
    00278       &&  (Test_align((U32)buffer, sizeof(U32)))
    00279 #endif
    00280       )
    00281       {
    00282          // The file data sector can been directly transfer from memory to buffer (don't use internal cache)
    00283          if( u16_buf_size <= u32_byte_remaining)
    00284          {
    00285             u16_nb_read_tmp = u16_buf_size;
    00286          }else{
    00287             u16_nb_read_tmp = u32_byte_remaining;
    00288          }
    00289          u16_nb_read_tmp = u16_nb_read_tmp / FS_512B;  // read a modulo sector size
    00290
    00291          // Get following sector segment of file
    00292          if( !fat_read_file(FS_CLUST_ACT_SEG))
    00293          {
    00294             if( FS_ERR_OUT_LIST == fs_g_status )
    00295                fs_g_status = FS_ERR_EOF;  // translate the error
    00296             return u16_nb_read;
    00297          }
    00298          // Truncate the segment size found if more larger than asked size
    00299          if( u16_nb_read_tmp > fs_g_seg.u32_size_or_pos )
    00300          {
    00301             u16_nb_read_tmp = fs_g_seg.u32_size_or_pos;
    00302          }else{
    00303             fs_g_seg.u32_size_or_pos = u16_nb_read_tmp;
    00304          }
    00305
    00306          // Directly data tranfert from memory to buffer
    00307          while( 0 != fs_g_seg.u32_size_or_pos )
    00308          {
    00309             if( CTRL_GOOD != memory_2_ram( fs_g_nav.u8_lun  , fs_g_seg.u32_addr, buffer))
    00310             {
    00311                fs_g_status = FS_ERR_HW;
    00312                return u16_nb_read;
    00313             }
    00314             fs_g_seg.u32_size_or_pos--;
    00315             fs_g_seg.u32_addr++;
    00316             buffer += FS_512B;
    00317          }
    00318          // Translate from sector unit to byte unit
    00319          u16_nb_read_tmp *= FS_512B;
    00320       }
    00321       else
    00322       {
    00323          // The file data can't been directly transfer from memory to buffer, the internal cache must be used
    00324
    00325          // Tranfer data from memory to internal cache
    00326          if( !fat_read_file( FS_CLUST_ACT_ONE ))
    00327          {
    00328             if( FS_ERR_OUT_LIST == fs_g_status )
    00329             {  // Translate the error
    00330                fs_g_status = FS_ERR_EOF;   // End of file
    00331             }
    00332             return u16_nb_read;
    00333          }
    00334
    00335          // Compute the number of data to transfer
    00336          u16_nb_read_tmp = FS_512B - u16_pos_in_sector;  // The number is limited at sector size
    00337          if( u16_nb_read_tmp > u32_byte_remaining )
    00338             u16_nb_read_tmp = u32_byte_remaining;
    00339          if( u16_nb_read_tmp > u16_buf_size )
    00340             u16_nb_read_tmp = u16_buf_size;
    00341
    00342          // Tranfer data from internal cache to buffer
    00343          memcpy_ram2ram( buffer , &fs_g_sector[ u16_pos_in_sector ], u16_nb_read_tmp );
    00344          buffer += u16_nb_read_tmp;
    00345       }
    00346       // Update positions
    00347       fs_g_nav_entry.u32_pos_in_file   += u16_nb_read_tmp;
    00348       u16_nb_read                      += u16_nb_read_tmp;
    00349       u16_buf_size                     -= u16_nb_read_tmp;
    00350    }
    00351    return u16_nb_read;  // Buffer is full
    00352 }
    00353
    00354
    00360 U16   file_getc( void )
    00361 {
    00362    U16   u16_byte;
    00363
    00364    while(1)
    00365    {
    00366       if(!(FOPEN_READ_ACCESS & fs_g_nav_entry.u8_open_mode))
    00367       {
    00368          fs_g_status = FS_ERR_WRITE_ONLY;
    00369          break;
    00370       }
    00371       if( fs_g_nav_entry.u32_size <= fs_g_nav_entry.u32_pos_in_file )
    00372       {
    00373          fs_g_status = FS_ERR_EOF;
    00374          break;
    00375       }
    00376
    00377       if( !fat_read_file( FS_CLUST_ACT_ONE ))
    00378       {
    00379          if( FS_ERR_OUT_LIST == fs_g_status )
    00380          {  // Translate the error
    00381             fs_g_status = FS_ERR_EOF;   // End of file
    00382          }
    00383          break;
    00384       }
    00385
    00386       u16_byte = fs_g_sector[ fs_g_nav_entry.u32_pos_in_file & FS_512B_MASK ];
    00387       fs_g_nav_entry.u32_pos_in_file++;
    00388       return u16_byte;
    00389    }
    00390    return FS_EOF;   // No data readed
    00391 }
    00392
    00393
    00394 #if (FSFEATURE_WRITE == (FS_LEVEL_FEATURES & FSFEATURE_WRITE))
    00412 Bool  file_write( Fs_file_segment _MEM_TYPE_SLOW_ *segment )
    00413 {
    00414    if( !fat_check_mount_select_open())
    00415       return FALSE;
    00416
    00417    if(!(FOPEN_WRITE_ACCESS & fs_g_nav_entry.u8_open_mode))
    00418    {
    00419       fs_g_status = FS_ERR_READ_ONLY;
    00420       return FALSE;
    00421    }
    00422
    00423    if( !fat_write_file( FS_CLUST_ACT_SEG , segment->u16_size ))
    00424       return FALSE;
    00425
    00426    // If the segment is too large then truncate it
    00427    if( (segment->u16_size != 0)  // if not undefine limit
    00428    &&  (segment->u16_size < fs_g_seg.u32_size_or_pos) )
    00429    {
    00430       fs_g_seg.u32_size_or_pos = segment->u16_size ;
    00431    }
    00432
    00433    // Update file position
    00434    fs_g_nav_entry.u32_pos_in_file += ((U32)fs_g_seg.u32_size_or_pos * FS_512B);
    00435
    00436    // Update size file
    00437    if( fs_g_nav_entry.u32_pos_in_file > fs_g_nav_entry.u32_size )
    00438    {
    00439       fs_g_nav_entry.u32_size = fs_g_nav_entry.u32_pos_in_file;
    00440    }
    00441    file_load_segment_value( segment );
    00442    return TRUE;
    00443 }
    00444
    00445
    00457 Bool  file_set_eof( void )
    00458 {
    00459    if( !fat_check_mount_select_open())
    00460       return FALSE;
    00461
    00462    if(!(FOPEN_WRITE_ACCESS & fs_g_nav_entry.u8_open_mode))
    00463    {
    00464       fs_g_status = FS_ERR_READ_ONLY;
    00465       return FALSE;
    00466    }
    00467
    00468    // Update the file size
    00469    fs_g_nav_entry.u32_size = fs_g_nav_entry.u32_pos_in_file;
    00470
    00471    if( !fat_read_file( FS_CLUST_ACT_CLR ))
    00472       return FALSE;
    00473
    00474    return fat_cache_flush();
    00475 }
    00476
    00477
    00486 U16   file_write_buf( U8 _MEM_TYPE_SLOW_ *buffer , U16 u16_buf_size )
    00487 {
    00488    _MEM_TYPE_FAST_ U16 u16_nb_write_tmp;
    00489    _MEM_TYPE_FAST_ U16 u16_nb_write;
    00490    _MEM_TYPE_FAST_ U16 u16_pos_in_sector;
    00491
    00492    if( !fat_check_mount_select_open())
    00493       return FALSE;
    00494
    00495    if(!(FOPEN_WRITE_ACCESS & fs_g_nav_entry.u8_open_mode))
    00496    {
    00497       fs_g_status = FS_ERR_READ_ONLY;
    00498       return FALSE;
    00499    }
    00500
    00501    u16_nb_write = 0;
    00502
    00503    while( 0 != u16_buf_size )
    00504    {
    00505       // The file data sector can been directly transfer from buffer to memory (don't use internal cache)
    00506       u16_pos_in_sector = fs_g_nav_entry.u32_pos_in_file % FS_512B;
    00507       if( (0== u16_pos_in_sector)
    00508       &&  (FS_512B <= u16_buf_size)
    00509 #if __GNUC__ && __AVR32__ || __ICCAVR32__
    00510       &&  (Test_align((U32)buffer, sizeof(U32)))
    00511 #endif
    00512       )
    00513       {
    00514          u16_nb_write_tmp = u16_buf_size / FS_512B;  // read a modulo sector size
    00515
    00516          // Get and eventually alloc the following sector segment of file
    00517          if( !fat_write_file( FS_CLUST_ACT_SEG , u16_nb_write_tmp ))
    00518             return FALSE;
    00519          // Truncate the segment found if more larger than asked size
    00520          if( u16_nb_write_tmp < fs_g_seg.u32_size_or_pos)
    00521          {
    00522             fs_g_seg.u32_size_or_pos = u16_nb_write_tmp;
    00523          }else{
    00524             u16_nb_write_tmp = fs_g_seg.u32_size_or_pos;
    00525          }
    00526
    00527          // Directly data tranfert from buffer to memory
    00528          while( 0 != fs_g_seg.u32_size_or_pos )
    00529          {
    00530             if( CTRL_GOOD != ram_2_memory( fs_g_nav.u8_lun  , fs_g_seg.u32_addr, buffer))
    00531             {
    00532                fs_g_status = FS_ERR_HW;
    00533                return u16_nb_write;
    00534             }
    00535             fs_g_seg.u32_size_or_pos--;
    00536             fs_g_seg.u32_addr++;
    00537             buffer += FS_512B;
    00538          }
    00539          // Translate from sector unit to byte unit
    00540          u16_nb_write_tmp *= FS_512B;
    00541       }
    00542       else
    00543       {
    00544          // The file data can't been directly transfer from buffer to memory, the internal cache must be used
    00545
    00546          // Tranfer and eventually alloc a data sector from internal cache to memory
    00547          if((fs_g_nav_entry.u32_pos_in_file == fs_g_nav_entry.u32_size)
    00548          && (0==u16_pos_in_sector) )
    00549          {
    00550             // Eventually alloc one new sector for the file
    00551             if( !fat_write_file( FS_CLUST_ACT_SEG  , 1 ))
    00552                return FALSE;
    00553             // Update the cache
    00554             fs_gu32_addrsector = fs_g_seg.u32_addr;
    00555             if( !fat_cache_read_sector( FALSE ))         // The memory is not readed because it is a new sector
    00556                return FALSE;
    00557          }else{
    00558             // The sector must existed then alloc no necessary
    00559             if( !fat_write_file( FS_CLUST_ACT_ONE  , 1 ))
    00560                return FALSE;
    00561          }
    00562
    00563          // Flag internal cache modified
    00564          fat_cache_mark_sector_as_dirty();
    00565
    00566          // Compute the number of data to transfer
    00567          u16_nb_write_tmp = FS_512B - u16_pos_in_sector; // The number is limited at sector size
    00568          if( u16_nb_write_tmp > u16_buf_size )
    00569             u16_nb_write_tmp = u16_buf_size;
    00570
    00571          // Tranfer data from buffer to internal cache
    00572          memcpy_ram2ram( &fs_g_sector[ u16_pos_in_sector ], buffer , u16_nb_write_tmp );
    00573          buffer += u16_nb_write_tmp;
    00574       }
    00575       // Update positions
    00576       fs_g_nav_entry.u32_pos_in_file+= u16_nb_write_tmp;
    00577       u16_nb_write                  += u16_nb_write_tmp;
    00578       u16_buf_size                  -= u16_nb_write_tmp;
    00579       // Update file size
    00580       if( fs_g_nav_entry.u32_pos_in_file > fs_g_nav_entry.u32_size )
    00581       {
    00582          fs_g_nav_entry.u32_size = fs_g_nav_entry.u32_pos_in_file;
    00583       }
    00584    }
    00585    return u16_nb_write;  // All buffer is writed
    00586 }
    00587
    00588
    00596 Bool  file_putc( U8 u8_byte )
    00597 {
    00598    if( !fat_check_mount_select_open())
    00599       return FALSE;
    00600
    00601    if(!(FOPEN_WRITE_ACCESS & fs_g_nav_entry.u8_open_mode))
    00602    {
    00603       fs_g_status = FS_ERR_READ_ONLY;
    00604       return FALSE;
    00605    }
    00606
    00607    if( !fat_write_file( FS_CLUST_ACT_ONE  , 1 ))
    00608       return FALSE;
    00609
    00610    // Write the data in the internal cache
    00611    fat_cache_mark_sector_as_dirty();
    00612    fs_g_sector[ fs_g_nav_entry.u32_pos_in_file & FS_512B_MASK ]    = u8_byte;
    00613    fs_g_nav_entry.u32_pos_in_file++;
    00614
    00615    // Update the file size
    00616    if( fs_g_nav_entry.u32_pos_in_file > fs_g_nav_entry.u32_size )
    00617    {
    00618       fs_g_nav_entry.u32_size = fs_g_nav_entry.u32_pos_in_file;
    00619    }
    00620    return TRUE;
    00621 }
    00622 #endif  // FS_LEVEL_FEATURES
    00623
    00624
    00629 U32   file_getpos( void )
    00630 {
    00631    if( !fat_check_mount_select_open() )
    00632       return 0;
    00633
    00634    return fs_g_nav_entry.u32_pos_in_file;
    00635 }
    00636
    00637
    00650 Bool  file_seek( U32 u32_pos , U8 u8_whence )
    00651 {
    00652    if( !fat_check_mount_select_open())
    00653       return FALSE;
    00654
    00655    switch(u8_whence)
    00656    {
    00657       case FS_SEEK_CUR_RE:
    00658       if( fs_g_nav_entry.u32_pos_in_file < u32_pos )
    00659       {  // Out of the limit
    00660          fs_g_status = FS_ERR_BAD_POS;
    00661          return FALSE;
    00662       }
    00663       // update the position
    00664       fs_g_nav_entry.u32_pos_in_file -= u32_pos;
    00665       break;
    00666
    00667       case FS_SEEK_SET:
    00668       if( fs_g_nav_entry.u32_size < u32_pos )
    00669       {  // Out of the limit
    00670          fs_g_status = FS_ERR_BAD_POS;
    00671          return FALSE;
    00672       }
    00673       // update the position
    00674       fs_g_nav_entry.u32_pos_in_file = u32_pos;
    00675       break;
    00676
    00677       case FS_SEEK_END:
    00678       if( fs_g_nav_entry.u32_size < u32_pos )
    00679       {  // Out of the limit
    00680          fs_g_status = FS_ERR_BAD_POS;
    00681          return FALSE;
    00682       }
    00683       // update the position
    00684       fs_g_nav_entry.u32_pos_in_file = fs_g_nav_entry.u32_size - u32_pos;
    00685       break;
    00686
    00687       case FS_SEEK_CUR_FW:
    00688       u32_pos += fs_g_nav_entry.u32_pos_in_file;
    00689       if( fs_g_nav_entry.u32_size < u32_pos )
    00690       {  // Out of the limit
    00691          fs_g_status = FS_ERR_BAD_POS;
    00692          return FALSE;
    00693       }
    00694       // update the position
    00695       fs_g_nav_entry.u32_pos_in_file = u32_pos;
    00696       break;
    00697    }
    00698    return TRUE;
    00699 }
    00700
    00701
    00708 U8    file_bof( void )
    00709 {
    00710    if( !fat_check_mount_select_open() )
    00711       return 0xFF;
    00712
    00713    return (0 == fs_g_nav_entry.u32_pos_in_file );
    00714 }
    00715
    00716
    00723 U8    file_eof( void )
    00724 {
    00725    if( !fat_check_mount_select_open() )
    00726       return 0xFF;
    00727    return (fs_g_nav_entry.u32_size <= fs_g_nav_entry.u32_pos_in_file );
    00728 }
    00729
    00730
    00733 void  file_flush( void )
    00734 {
    00735    U8 save_open_mode;
    00736    save_open_mode = fs_g_nav_entry.u8_open_mode;
    00737    file_close();
    00738    fs_g_nav_entry.u8_open_mode = save_open_mode;
    00739 }
    00740
    00741
    00744 void  file_close( void )
    00745 {
    00746    // If a file is opened, then close this one
    00747    if( fat_check_mount_select_open() )
    00748    {
    00749
    00750 #if (FSFEATURE_WRITE == (FS_LEVEL_FEATURES & FSFEATURE_WRITE))
    00751       if( FOPEN_WRITE_ACCESS & fs_g_nav_entry.u8_open_mode )
    00752       {
    00753          // Write file information
    00754          if( !fat_read_dir() )
    00755             return;           // error
    00756          fat_write_entry_file();
    00757          fat_cache_flush();   // In case of error during writing data, flush the data before exit function
    00758       }
    00759 #endif  // FS_LEVEL_FEATURES
    00760       Fat_file_close();
    00761    }
    00762 }