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

# navigation.c

Go to the documentation of this file.

    00001 /*This file has been prepared for Doxygen automatic documentation generation.*/
    00013 /* Copyright (C) 2006-2008, Atmel Corporation All rights reserved.
    00014  *
    00015  * Redistribution and use in source and binary forms, with or without
    00016  * modification, are permitted provided that the following conditions are met:
    00017  *
    00018  * 1. Redistributions of source code must retain the above copyright notice,
    00019  * this list of conditions and the following disclaimer.
    00020  *
    00021  * 2. Redistributions in binary form must reproduce the above copyright notice,
    00022  * this list of conditions and the following disclaimer in the documentation
    00023  * and/or other materials provided with the distribution.
    00024  *
    00025  * 3. The name of ATMEL may not be used to endorse or promote products derived
    00026  * from this software without specific prior written permission.
    00027  *
    00028  * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
    00029  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    00030  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE EXPRESSLY AND
    00031  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
    00032  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    00033  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    00034  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    00035  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    00036  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    00037  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    00038  */
    00039
    00040 //_____  I N C L U D E S ___________________________________________________
    00041 #include <ctype.h> // Use of toupper
    00042
    00043 #include "conf_explorer.h"
    00044 #include "navigation.h"
    00045 #include "file.h"
    00046 #include LIB_CTRLACCESS
    00047
    00048
    00049 //_____ M A C R O S ________________________________________________________
    00050
    00051
    00052 //_____ D E F I N I T I O N S ______________________________________________
    00053
    00054 #if (FSFEATURE_WRITE == (FS_LEVEL_FEATURES & FSFEATURE_WRITE))
    00056    _MEM_TYPE_SLOW_ U8 g_id_trans_memtomem = ID_STREAM_ERR;
    00057 #endif
    00058
    00059 #if (FS_NB_NAVIGATOR > 1)
    00061    _MEM_TYPE_SLOW_ U8 fs_g_u8_nav_selected;
    00062 #endif
    00063
    00064 #if (FSFEATURE_WRITE == (FS_LEVEL_FEATURES & FSFEATURE_WRITE))
    00065    _MEM_TYPE_SLOW_ Fs_file_segment g_segment_src;
    00066    _MEM_TYPE_SLOW_ Fs_file_segment g_segment_dest;
    00067 #endif
    00068
    00069 #define SIZE_OF_SPLIT_COPY    ((1*1024*1024L)/512L)    // 1MB - Unit sector (max = 0xFFFF)
    00070
    00071
    00072 //_____ D E C L A R A T I O N S ____________________________________________
    00073
    00074 //**********************************************************************
    00075 //************************ String format select ************************
    00076 #if( (FS_ASCII == ENABLED) && (FS_UNICODE == ENABLED))
    00084 void  nav_string_unicode( void )
    00085 {
    00086    g_b_unicode = TRUE;
    00087 }
    00095 void  nav_string_ascii( void )
    00096 {
    00097    g_b_unicode = FALSE;
    00098 }
    00099 #endif
    00100
    00108 void  nav_string_length_enable( void )
    00109 {
    00110    g_b_string_length = TRUE;
    00111 }
    00119 void  nav_string_length_disable( void )
    00120 {
    00121    g_b_string_length = FALSE;
    00122 }
    00123
    00124 //**********************************************************************
    00125 //********************** To optimize speed access **********************
    00126
    00134 void  nav_checkdisk_disable( void )
    00135 {
    00136    g_b_no_check_disk = TRUE;
    00137 }
    00138
    00146 void  nav_checkdisk_enable( void )
    00147 {
    00148    g_b_no_check_disk = FALSE;
    00149 }
    00150
    00151
    00152 //**********************************************************************
    00153 //************** Initialise or Stop navigation module ******************
    00154
    00155
    00162 void  nav_reset( void )
    00163 {
    00164 #if ( (FS_ASCII   == ENABLED) && (FS_UNICODE == ENABLED))
    00165    g_b_unicode = TRUE;
    00166 #endif
    00167    g_b_string_length = FALSE;
    00168    g_b_no_check_disk = FALSE;
    00169
    00170    fat_cache_reset();
    00171    fat_cache_clusterlist_reset();
    00172
    00173 #if (FS_NB_NAVIGATOR > 1)
    00174    {
    00175    U8 i;
    00176    // Reset variables of each navigators
    00177    for( i=0 ; i!=FS_NB_NAVIGATOR ; i++ )
    00178    {
    00179       nav_select(i);
    00180       fs_g_nav_fast.u8_type_fat = FS_TYPE_FAT_UNM; // By default the fat isn't mounted
    00181       fs_g_nav.u8_lun = 0xFF;                      // By default don't select a drive
    00182 #if (FS_MULTI_PARTITION  ==  ENABLED)
    00183       fs_g_nav.u8_partition=0;                     // By default select the first partition
    00184 #endif
    00185       Fat_file_close();                            // By default no file is opened
    00186       fs_g_nav.b_mode_nav_single = FALSE;          // By default display files and directories
    00187    }
    00188    // By default select the navigator 0
    00189    fs_g_u8_nav_selected = 0;
    00190    }
    00191 #else
    00192    fs_g_nav_fast.u8_type_fat = FS_TYPE_FAT_UNM;    // By default the fat isn't mounted
    00193    fs_g_nav.u8_lun = 0xFF;                         // By default don't select a drive
    00194 #  if (FS_MULTI_PARTITION  ==  ENABLED)
    00195    fs_g_nav.u8_partition=0;                        // By default select the first partition
    00196 #  endif
    00197    Fat_file_close();                               // By default no file is opened
    00198 #endif // (FS_NB_NAVIGATOR > 1)
    00199 }
    00200
    00201
    00208 void  nav_exit( void )
    00209 {
    00210    // If you have opened files then close them
    00211 #if (FS_NB_NAVIGATOR > 1)
    00212    U8 u8_i;
    00213    for( u8_i=0; u8_i<FS_NB_NAVIGATOR; u8_i++)
    00214    {
    00215       nav_select(u8_i);
    00216       file_close();
    00217    }
    00218 #else
    00219    nav_select(0);
    00220    file_close();
    00221 #endif
    00222    // Flush data eventually present in FAT cache
    00223    fat_cache_flush();
    00224 }
    00225
    00226
    00234 Bool  nav_select( U8 u8_idnav )
    00235 {
    00236    if( FS_NB_NAVIGATOR <= u8_idnav )
    00237    {
    00238       fs_g_status = FS_ERR_BAD_NAV;             // The navigator doesn't exist
    00239       return FALSE;
    00240    }
    00241 #if (FS_NB_NAVIGATOR > 1)
    00242    if( fs_g_u8_nav_selected != u8_idnav )
    00243    {
    00244       fat_invert_nav( fs_g_u8_nav_selected );   // Deselect previous navigator = Select default navigator
    00245       fat_invert_nav( u8_idnav );               // Select new navigator
    00246       fs_g_u8_nav_selected = u8_idnav;
    00247    }
    00248 #endif
    00249    return TRUE;
    00250 }
    00251
    00252
    00257 U8    nav_get( void )
    00258 {
    00259 #if (FS_NB_NAVIGATOR > 1)
    00260    return fs_g_u8_nav_selected;
    00261 #else
    00262    return 0;
    00263 #endif
    00264 }
    00265
    00266
    00278 Bool  nav_copy( U8 u8_idnav )
    00279 {
    00280 #if (FS_NB_NAVIGATOR > 1)
    00281    if( fs_g_u8_nav_selected == u8_idnav )
    00282       return FALSE;                    // It is the source and destination is the same navigator
    00283    if( 0 == u8_idnav )
    00284       u8_idnav = fs_g_u8_nav_selected; // the default navigator is invert with the current navigator
    00285    if( 0 == u8_idnav)
    00286       return FALSE;                    // It is the source and destination is the same navigator
    00287    fat_copy_nav( u8_idnav );
    00288    return TRUE;
    00289 #else
    00290    u8_idnav++;
    00291    return FALSE;                       // Copy impossible because only one navigator is available
    00292 #endif
    00293 }
    00294
    00295
    00296 //**********************************************************************
    00297 //********************* Drive navigation functions *********************
    00298
    00299
    00308 U8    nav_drive_nb( void )
    00309 {
    00310    return get_nb_lun(); // Number of devices = Number of lun
    00311 }
    00312
    00313
    00321 Bool  nav_drive_set( U8 u8_number )
    00322 {
    00323    if ( !fat_check_noopen() )
    00324       return FALSE;
    00325
    00326    if (u8_number >= get_nb_lun() )
    00327    {
    00328       fs_g_status = FS_ERR_END_OF_DRIVE;   // The drive number is bad
    00329       return FALSE;
    00330    }
    00331
    00332    if ( fs_g_nav.u8_lun == u8_number)
    00333       return TRUE;   // It is the same drive number
    00334
    00335    // Go to the device
    00336    fs_g_nav.u8_lun = u8_number;
    00337    fs_g_nav_fast.u8_type_fat = FS_TYPE_FAT_UNM;
    00338 #if (FS_MULTI_PARTITION  ==  ENABLED)
    00339    fs_g_nav.u8_partition=0;   // by default select the first partition
    00340 #endif
    00341    return TRUE;
    00342 }
    00343
    00344
    00350 U8    nav_drive_get( void )
    00351 {
    00352 #if (FS_MULTI_PARTITION  ==  ENABLED)
    00353    if(0xFF == fs_g_nav.u8_lun)
    00354       return 0xFF;
    00355    return ((fs_g_nav.u8_lun*4) + fs_g_nav.u8_partition); // Maximum 4 partitions per device
    00356 #else
    00357    return (fs_g_nav.u8_lun);
    00358 #endif
    00359 }
    00360
    00361
    00367 U8    nav_drive_getname( void )
    00368 {
    00369    if(0xFF == fs_g_nav.u8_lun)
    00370       return 'X';
    00371 #if (FS_MULTI_PARTITION  ==  ENABLED)
    00372    return ('A' + (fs_g_nav.u8_lun*4) + fs_g_nav.u8_partition); // Maximum 4 partitions per device
    00373 #else
    00374    return ('A' + fs_g_nav.u8_lun);
    00375 #endif
    00376 }
    00377
    00378
    00379 #if (FSFEATURE_WRITE_COMPLET == (FS_LEVEL_FEATURES & FSFEATURE_WRITE_COMPLET))
    00396 Bool  nav_drive_format( U8 u8_fat_type )
    00397 {
    00398    if ( !fat_check_noopen() )
    00399       return FALSE;
    00400    if ( !fat_check_nav_access_disk() )
    00401       return FALSE;
    00402    if ( !fat_format( u8_fat_type ) )
    00403       return FALSE;
    00404    return fat_mount();
    00405 }
    00406 #endif  // FS_LEVEL_FEATURES
    00407
    00408
    00409 //**********************************************************************
    00410 //******************* Partition navigation functions *******************
    00411
    00412
    00413 #if (FS_MULTI_PARTITION  ==  ENABLED)
    00418 U8    nav_partition_nb( void )
    00419 {
    00420    return fat_get_nbpartition();
    00421 }
    00422
    00423
    00431 Bool  nav_partition_set( U8 partition_number )
    00432 {
    00433    if ( fs_g_nav.u8_partition == partition_number)
    00434       return TRUE;   // It is the same
    00435
    00436    if ( !fat_check_noopen() )
    00437       return FALSE;
    00438
    00439    // Go to partition
    00440    fs_g_nav.u8_partition = partition_number;
    00441    fs_g_nav_fast.u8_type_fat = FS_TYPE_FAT_UNM;
    00442    return TRUE;
    00443 }
    00444 #endif
    00445
    00446
    00458 Bool  nav_partition_mount( void )
    00459 {
    00460    if ( !fat_check_noopen() )
    00461       return FALSE;
    00462
    00463    if( FS_TYPE_FAT_UNM != fs_g_nav_fast.u8_type_fat)
    00464    {
    00465       // Already mounted
    00466       // Go to root directory
    00467       fs_g_nav.u32_cluster_sel_dir   = 0;
    00468       // No file is selected by default
    00469       fat_clear_entry_info_and_ptr();
    00470       return TRUE;
    00471    }
    00472
    00473    return fat_mount();
    00474 }
    00475
    00476
    00482 U8    nav_partition_type( void )
    00483 {
    00484    fat_check_device();
    00485    if( FS_TYPE_FAT_UNM == fs_g_nav_fast.u8_type_fat)
    00486    {
    00487       nav_partition_mount();
    00488    }
    00489    return fs_g_nav_fast.u8_type_fat;
    00490 }
    00491
    00492
    00505 Bool  nav_partition_serialnumber( Bool b_action , U8 _MEM_TYPE_SLOW_ *a_u8_sn )
    00506 {
    00507    if( !fat_check_mount())
    00508       return FALSE;
    00509
    00510    return fat_serialnumber( b_action , a_u8_sn );
    00511 }
    00512
    00513
    00526 Bool  nav_partition_label( Bool b_action , FS_STRING sz_label )
    00527 {
    00528    _MEM_TYPE_SLOW_   Fs_index index;
    00529    Bool status = TRUE;
    00530
    00531    index = nav_getindex();    // Save current position
    00532
    00533    // Go to root dir
    00534    if( nav_dir_root())
    00535    {
    00536       // Find field label
    00537       fs_g_nav_fast.u16_entry_pos_sel_file = 0; // Go to first entry
    00538       while( 1 )
    00539       {
    00540          if ( !fat_read_dir())
    00541          {
    00542             status = FALSE;
    00543             break;               // error
    00544          }
    00545          if( fat_entry_label( FS_LABEL_READ , NULL ) )
    00546             break;
    00547          if( FS_ERR_ENTRY_EMPTY == fs_g_status )
    00548             break;
    00549          fs_g_nav_fast.u16_entry_pos_sel_file++;
    00550       }
    00551       if( TRUE == status )
    00552       {
    00553          // Find OK
    00554          if( FS_LABEL_READ == b_action )
    00555          {
    00556             // Read field label
    00557             if( !fat_entry_label( FS_LABEL_READ , sz_label ) )
    00558                sz_label[0]=0;    // empty name
    00559          }else{
    00560             // Change field label
    00561             status = fat_entry_label( FS_LABEL_WRITE , sz_label );
    00562          }
    00563       }
    00564    }
    00565    nav_gotoindex( &index );   // Restore the position
    00566    return status;
    00567 }
    00568
    00569
    00579 U32   nav_partition_space( void )
    00580 {
    00581    fat_check_device();
    00582    if (FS_TYPE_FAT_UNM == fs_g_nav_fast.u8_type_fat)
    00583       return 0;
    00584    return (fs_g_nav.u32_CountofCluster * fs_g_nav.u8_BPB_SecPerClus);
    00585 }
    00586
    00587
    00592 U8    nav_partition_cluster_size( void )
    00593 {
    00594    return fs_g_nav.u8_BPB_SecPerClus;
    00595 }
    00596
    00606 U32   nav_partition_freespace( void )
    00607 {
    00608    fat_check_device();
    00609    if (FS_TYPE_FAT_UNM == fs_g_nav_fast.u8_type_fat)
    00610       return 0;
    00611    return fat_getfreespace();
    00612 }
    00613
    00614
    00624 U8    nav_partition_freespace_percent( void )
    00625 {
    00626    fat_check_device();
    00627    if (FS_TYPE_FAT_UNM == fs_g_nav_fast.u8_type_fat)
    00628       return 0;
    00629    return fat_getfreespace_percent();
    00630 }
    00631
    00632
    00633 //**********************************************************************
    00634 //****************** File list navigation functions ********************
    00635
    00636
    00645 Bool  nav_filelist_single_enable( Bool b_type )
    00646 {
    00647    if ( !nav_filelist_reset())
    00648       return FALSE;
    00649
    00650    fs_g_nav.b_mode_nav_single = TRUE;
    00651    fs_g_nav.b_mode_nav        = b_type;
    00652    return TRUE;
    00653 }
    00654
    00655
    00661 Bool  nav_filelist_single_disable( void )
    00662 {
    00663    fs_g_nav.b_mode_nav_single = FALSE;
    00664    return nav_filelist_reset();
    00665 }
    00666
    00667
    00673 Bool  nav_filelist_reset( void )
    00674 {
    00675    if ( !fat_check_mount_noopen())
    00676       return FALSE;
    00677
    00678    // No file selected and reset navigation
    00679    fat_clear_entry_info_and_ptr();
    00680    return TRUE;
    00681 }
    00682
    00683
    00689 Bool  nav_filelist_validpos( void )
    00690 {
    00691    return fat_check_mount_select_noopen();
    00692 }
    00693
    00694
    00700 Bool  nav_filelist_fileisnotopen( void )
    00701 {
    00702    return fat_check_noopen();
    00703 }
    00704
    00705
    00723 Bool  nav_filelist_set( U16 u16_nb , Bool b_direction )
    00724 {
    00725    U16   u16_ptr_save_entry;
    00726    U16   u16_save_pos_sel_file;
    00727    Bool  b_save_entry_type;
    00728    Bool  b_find_last_entry = FALSE;
    00729
    00730    if ( !fat_check_mount_noopen())
    00731       return FALSE;
    00732
    00733    // Save the current selection
    00734    u16_ptr_save_entry      = fs_g_nav_fast.u16_entry_pos_sel_file;
    00735    u16_save_pos_sel_file   = fs_g_nav.u16_pos_sel_file;
    00736    b_save_entry_type       = fs_g_nav.b_mode_nav;
    00737
    00738    // Loop in directory
    00739    while( 1 )
    00740    {
    00741       if(( FS_FIND_NEXT == b_direction )
    00742       || ( b_find_last_entry ) )
    00743       {
    00744          if ( FS_END_FIND == fs_g_nav_fast.u16_entry_pos_sel_file )
    00745          {
    00746             // Too many files in directory (case impossible)
    00747             fs_g_status = FS_ERR_FS;
    00748             break;
    00749          }
    00750          fs_g_nav_fast.u16_entry_pos_sel_file++;      // Update entry position
    00751       }
    00752       else
    00753       {
    00754          if ( FS_NO_SEL == fs_g_nav_fast.u16_entry_pos_sel_file )
    00755          {
    00756             // No selected file then previous action impossible
    00757             fs_g_status = FS_ERR_NO_FIND;
    00758             break;
    00759          }
    00760          if ( 0 == fs_g_nav_fast.u16_entry_pos_sel_file )
    00761          {
    00762             // beginning of directory
    00763             if ( (FS_DIR == fs_g_nav.b_mode_nav ) || fs_g_nav.b_mode_nav_single )
    00764             {
    00765                // End of directory scan, then no previous action possible
    00766                fs_g_status = FS_ERR_NO_FIND;
    00767                break;
    00768             }
    00769             // End of file scan, then find last directory
    00770             b_find_last_entry = TRUE;
    00771          }else{
    00772             fs_g_nav_fast.u16_entry_pos_sel_file--;   // Update entry position
    00773          }
    00774       }
    00775
    00776       if( !fat_read_dir())
    00777       {
    00778          if( FS_ERR_OUT_LIST != fs_g_status )
    00779             break; // Error
    00780       }else{
    00781          if ( fat_entry_check( fs_g_nav.b_mode_nav ) )
    00782          {
    00783            // HERE, the file entry match with the type seached
    00784
    00785            if( b_find_last_entry )
    00786              continue;  // The search of last directory is on going then continue the search
    00787
    00788            // Update position in directory
    00789            if ( FS_FIND_NEXT == b_direction )
    00790               fs_g_nav.u16_pos_sel_file++;
    00791            else
    00792               fs_g_nav.u16_pos_sel_file--;
    00793
    00794            if (0 == u16_nb)
    00795            {
    00796               // It is the end of move then update file information
    00797               fat_get_entry_info();
    00798               return TRUE;         // NB FILE FIND
    00799            }
    00800            u16_nb--;
    00801            continue;
    00802          }
    00803       }
    00804
    00805       // Here error, check type of error
    00806       if(( FS_ERR_ENTRY_EMPTY == fs_g_status )
    00807       || ( FS_ERR_OUT_LIST    == fs_g_status ) )
    00808       {
    00809          // Here, end of the directory
    00810          if( b_find_last_entry )
    00811          {
    00812             // Re enable the previous command at the end of directory to find the last directory entry
    00813             b_find_last_entry = FALSE;
    00814             fs_g_nav.b_mode_nav = FS_DIR;
    00815             continue;
    00816          }
    00817          // Here, a next action is on going
    00818          if ( (FS_FILE == fs_g_nav.b_mode_nav) || fs_g_nav.b_mode_nav_single )
    00819          {
    00820             // End of next file action then end of next action
    00821             fs_g_status = FS_ERR_NO_FIND; // No file found
    00822             break;                        // end of search
    00823          }else{
    00824             // End of next dir action then starts the next file action at the beginning of directory
    00825             fs_g_nav_fast.u16_entry_pos_sel_file = 0xFFFF;
    00826             fs_g_nav.b_mode_nav = FS_FILE;
    00827          }
    00828       }
    00829    }  // end of loop while(1)
    00830
    00831    fs_g_nav.b_mode_nav                    = b_save_entry_type;
    00832    fs_g_nav_fast.u16_entry_pos_sel_file   = u16_ptr_save_entry;
    00833    fs_g_nav.u16_pos_sel_file              = u16_save_pos_sel_file;
    00834    return FALSE;
    00835 }
    00836
    00837
    00843 U16   nav_filelist_get( void )
    00844 {
    00845    return fs_g_nav.u16_pos_sel_file;
    00846 }
    00847
    00848
    00856 Bool  nav_filelist_goto( U16 u16_newpos )
    00857 {
    00858    U16 u16_current_pos;
    00859
    00860    if( FS_NO_SEL == u16_newpos )
    00861       return nav_filelist_reset();
    00862
    00863    u16_current_pos = nav_filelist_get();
    00864    if( u16_newpos < (u16_current_pos/2) )
    00865    {
    00866       // Restart at the beginning of list to accelerate the search
    00867       if( !nav_filelist_reset() )
    00868          return FALSE;
    00869       u16_current_pos = FS_NO_SEL;
    00870    }
    00871    if (FS_NO_SEL == u16_current_pos)
    00872    {
    00873       return nav_filelist_set( u16_newpos, FS_FIND_NEXT );
    00874    }
    00875    else
    00876    {
    00877       if (u16_newpos < u16_current_pos)
    00878       {
    00879          return nav_filelist_set( u16_current_pos -u16_newpos -1 , FS_FIND_PREV );
    00880       }
    00881       if (u16_newpos > u16_current_pos)
    00882       {
    00883          return nav_filelist_set( u16_newpos -u16_current_pos - 1 , FS_FIND_NEXT );
    00884       }
    00885    }
    00886    return TRUE;
    00887 }
    00888
    00889
    00903 Bool  nav_filelist_findname( const FS_STRING sz_name , Bool b_match_case )
    00904 {
    00905    while( 1 )
    00906    {
    00907       if ( !nav_filelist_set( 0, FS_FIND_NEXT ))
    00908          return FALSE;
    00909       if ( nav_file_name( sz_name , 0 , FS_NAME_CHECK , b_match_case ))
    00910          return TRUE;
    00911    }
    00912 }
    00913
    00914
    00920 Bool  nav_filelist_eol( void )
    00921 {
    00922    if( FALSE == nav_filelist_set( 0 , FS_FIND_NEXT ) )
    00923       return TRUE;   // End of list or error (remark: the position haven't changed)
    00924
    00925    if( 0 != fs_g_nav.u16_pos_sel_file )
    00926    {
    00927       // Go to previous position
    00928       nav_filelist_set( 0 , FS_FIND_PREV );
    00929    }else{
    00930       // No select file before, then reset position
    00931       fs_g_nav_fast.u16_entry_pos_sel_file= FS_NO_SEL;
    00932       fs_g_nav.u16_pos_sel_file           = FS_NO_SEL;
    00933       fs_g_nav.b_mode_nav                 = FS_DIR;
    00934    }
    00935    return FALSE;
    00936 }
    00937
    00938
    00944 Bool  nav_filelist_bol( void )
    00945 {
    00946    if( FALSE == nav_filelist_set( 0 , FS_FIND_PREV ) )
    00947       return TRUE;   // End of list or error (remark: the position haven't changed)
    00948    // Go to previous position
    00949    nav_filelist_set( 0 , FS_FIND_NEXT );
    00950    return FALSE;
    00951 }
    00952
    00953
    00962 Bool  nav_filelist_exist( Bool b_type )
    00963 {
    00964    Bool status;
    00965    U16   u16_save_position;
    00966
    00967    // Save current position
    00968    u16_save_position = fs_g_nav.u16_pos_sel_file;
    00969    // Go to first file or directory
    00970    status = nav_filelist_first( b_type );
    00971    // Restore previous position
    00972    nav_filelist_reset();
    00973    if ( u16_save_position != FS_NO_SEL )
    00974    {
    00975       nav_filelist_set( u16_save_position , FS_FIND_NEXT );
    00976    }
    00977    return status;
    00978 }
    00979
    00980
    00988 U16   nav_filelist_nb( Bool b_type )
    00989 {
    00990    U16   u16_save_position;
    00991    U16   u16_save_number_dir;
    00992    U16   u16_save_number_file;
    00993
    00994    // Save current position
    00995    u16_save_position = fs_g_nav.u16_pos_sel_file;
    00996    // Reset position
    00997    if ( !nav_filelist_reset())
    00998       return 0;
    00999    // Scan all directory
    01000    u16_save_number_dir  = 0;
    01001    u16_save_number_file = 0;
    01002    while( nav_filelist_set( 0 , FS_FIND_NEXT ) )
    01003    {
    01004       if( FS_FILE == fs_g_nav.b_mode_nav )
    01005          u16_save_number_file++;    // It is a file
    01006       else
    01007          u16_save_number_dir++;     // It is a directory
    01008    }
    01009    // Restore previous position
    01010    nav_filelist_reset();
    01011    if ( u16_save_position != FS_NO_SEL )
    01012    {
    01013       nav_filelist_set( u16_save_position , FS_FIND_NEXT );
    01014    }
    01015    // Return the value asked
    01016    if( FS_FILE == b_type )
    01017       return u16_save_number_file;
    01018    else
    01019       return u16_save_number_dir;
    01020 }
    01021
    01022
    01031 Bool  nav_filelist_first( Bool b_type )
    01032 {
    01033    // Reset position
    01034    if ( !nav_filelist_reset())
    01035       return FALSE;
    01036    // Find the first file or directory
    01037    while( nav_filelist_set( 0 , FS_FIND_NEXT ) )
    01038    {
    01039       if( b_type == fs_g_nav.b_mode_nav )
    01040          return TRUE;   // First file or directory found
    01041    }
    01042    fs_g_status = FS_ERR_NO_FIND;
    01043    return FALSE;
    01044 }
    01045
    01046
    01055 Bool  nav_filelist_last( Bool b_type )
    01056 {
    01057    U16 u16_nb;
    01058
    01059    // Get number of file or directory
    01060    u16_nb = nav_filelist_nb( b_type  );
    01061    if( 0 == u16_nb )
    01062    {
    01063       fs_g_status = FS_ERR_NO_FIND;
    01064       return FALSE;  // NO FILE FOUND
    01065    }
    01066    // Go to the first file or directory
    01067    if ( !nav_filelist_first( b_type ))
    01068       return FALSE;
    01069    // If there are more one file or directory, then go to at the last of list
    01070    if( 1 == u16_nb )
    01071       return TRUE;
    01072    u16_nb -= 2;
    01073    return nav_filelist_set( u16_nb , FS_FIND_NEXT );
    01074 }
    01075
    01076
    01077 //**********************************************************************
    01078 //************************ Index functions *****************************
    01079
    01080
    01090 Fs_index nav_getindex( void )
    01091 {
    01092    Fs_index index;
    01093
    01094    // Fill index structure
    01095    index.u8_lun                  = fs_g_nav.u8_lun;
    01096 #if (FS_MULTI_PARTITION  ==  ENABLED)
    01097    index.u8_partition            = fs_g_nav.u8_partition;
    01098 #endif
    01099    index.u32_cluster_sel_dir     = fs_g_nav.u32_cluster_sel_dir;
    01100    index.u16_entry_pos_sel_file  = fs_g_nav_fast.u16_entry_pos_sel_file;
    01101    return index;
    01102 }
    01103
    01104
    01117 Bool  nav_gotoindex( const Fs_index _MEM_TYPE_SLOW_ *index )
    01118 {
    01119    // Select the drive and partition corresponding at file index
    01120    if( !nav_drive_set( index->u8_lun ))
    01121       return FALSE;
    01122 #if (FS_MULTI_PARTITION  ==  ENABLED)
    01123    if( !nav_partition_set(index->u8_partition))
    01124       return FALSE;
    01125 #endif
    01126    if( !nav_partition_mount())
    01127       return FALSE;
    01128
    01129    // Select the directory corresponding at file index
    01130    fs_g_nav.u32_cluster_sel_dir   = index->u32_cluster_sel_dir;
    01131
    01132    // Search the file position corresponding at file index
    01133    if ( !nav_filelist_reset())
    01134       return FALSE;
    01135    while( fs_g_nav_fast.u16_entry_pos_sel_file != index->u16_entry_pos_sel_file )
    01136    {
    01137       if( !nav_filelist_set( 0 , FS_FIND_NEXT ) )
    01138       {
    01139          nav_filelist_reset();
    01140          return FALSE;
    01141       }
    01142    }
    01143    return TRUE;
    01144 }
    01145
    01146
    01147 //**********************************************************************
    01148 //************************ Directory functions *************************
    01149
    01150
    01156 Bool  nav_dir_root( void )
    01157 {
    01158    return nav_partition_mount();
    01159 }
    01160
    01161
    01167 Bool  nav_dir_is_root( void )
    01168 {
    01169    if (!fat_check_mount_noopen())
    01170       return FALSE;
    01171
    01172    return (0 == fs_g_nav.u32_cluster_sel_dir);
    01173 }
    01174
    01175
    01186 Bool  nav_dir_cd( void )
    01187 {
    01188    if ( !fat_check_mount_select_noopen())
    01189       return FALSE;
    01190
    01191    // The current selection, is it a directory ?
    01192    if ( !fat_entry_is_dir())
    01193       return FALSE;
    01194
    01195    // Select the current directory
    01196    fs_g_nav.u16_entry_pos_sel_dir = fs_g_nav_fast.u16_entry_pos_sel_file;
    01197    fs_g_nav.u32_cluster_sel_dir = fs_g_nav_entry.u32_cluster;
    01198
    01199    // Reset file list
    01200    if( FALSE == nav_filelist_reset())
    01201       return FALSE;
    01202    return TRUE;
    01203 }
    01204
    01205
    01216 Bool  nav_dir_gotoparent( void )
    01217 {
    01218    U32 u32_cluster_old_dir;
    01219
    01220    if (!fat_check_mount_noopen())
    01221       return FALSE;
    01222
    01223    if (0 == fs_g_nav.u32_cluster_sel_dir)
    01224    {
    01225       fs_g_status = FS_ERR_IS_ROOT;        // There aren't parent
    01226       return FALSE;
    01227    }
    01228
    01229    // Select and read information about directory ".."
    01230    fs_g_nav_fast.u16_entry_pos_sel_file = 1;
    01231    if ( !fat_read_dir())
    01232       return FALSE;
    01233    fat_get_entry_info();
    01234    // Save the children directory cluster
    01235    u32_cluster_old_dir = fs_g_nav.u32_cluster_sel_dir;
    01236
    01237    // Select the parent directory via information present in the current directory ".."
    01238    fs_g_nav.u32_cluster_sel_dir = fs_g_nav_entry.u32_cluster;
    01239
    01240    // Select the children directory in new directory (=parent directory)
    01241    if( FALSE == nav_filelist_reset())
    01242       return FALSE;
    01243    if( fs_g_nav.b_mode_nav_single && (FS_DIR != fs_g_nav.b_mode_nav) )
    01244       return TRUE;
    01245
    01246    while( nav_filelist_set( 0 , FS_FIND_NEXT ) )
    01247    {
    01248       if (fs_g_nav_entry.u32_cluster == u32_cluster_old_dir)
    01249          return TRUE;         // It is the children directory
    01250    }
    01251    fs_g_status = FS_ERR_FS;
    01252    return FALSE;
    01253 }
    01254
    01255
    01264 Bool  nav_dir_name( FS_STRING sz_path  , U8 u8_size_max  )
    01265 {
    01266    U8 u8_i, u8_character;
    01267    Bool status = FALSE;
    01268    U16 save_u16_entry_pos_sel_file;
    01269    U32 save_u32_cluster_sel_dir;
    01270    U8  save_u8_attr          ;
    01271    U32 save_u32_cluster      ;
    01272    U32 save_u32_size         ;
    01273    Bool b_mode_nav_single_save;
    01274    Bool b_mode_nav_mode_save;
    01275
    01276    if ( !fat_check_mount_noopen())
    01277       return FALSE;
    01278
    01279    if (0 != fs_g_nav.u32_cluster_sel_dir)
    01280    {
    01281       // Save context
    01282       save_u16_entry_pos_sel_file= fs_g_nav_fast.u16_entry_pos_sel_file;
    01283       save_u32_cluster_sel_dir   = fs_g_nav.u32_cluster_sel_dir        ;
    01284       save_u8_attr               = fs_g_nav_entry.u8_attr              ;
    01285       save_u32_cluster           = fs_g_nav_entry.u32_cluster          ;
    01286       save_u32_size              = fs_g_nav_entry.u32_size             ;
    01287       b_mode_nav_single_save = fs_g_nav.b_mode_nav_single;
    01288       b_mode_nav_mode_save   = fs_g_nav.b_mode_nav;
    01289       fs_g_nav.b_mode_nav_single = TRUE;
    01290       fs_g_nav.b_mode_nav = FS_FILE;
    01291       // Go to parent directory and select the children directory
    01292       if( !nav_dir_gotoparent() )
    01293       {
    01294          fs_g_nav.b_mode_nav_single = b_mode_nav_single_save;
    01295          fs_g_nav.b_mode_nav = b_mode_nav_mode_save;
    01296          return FALSE;
    01297       }
    01298       fs_g_nav.b_mode_nav_single = b_mode_nav_single_save ;
    01299       fs_g_nav.b_mode_nav = b_mode_nav_mode_save;
    01300       // Go to directory name position
    01301       fs_g_nav_fast.u16_entry_pos_sel_file = fs_g_nav.u16_entry_pos_sel_dir;
    01302       status = nav_file_name( sz_path  , u8_size_max , FS_NAME_GET , FALSE  );
    01303       // Restore previous context
    01304       fs_g_nav_fast.u16_entry_pos_sel_file= save_u16_entry_pos_sel_file;
    01305       fs_g_nav.u32_cluster_sel_dir        = save_u32_cluster_sel_dir   ;
    01306       fs_g_nav_entry.u8_attr              = save_u8_attr               ;
    01307       fs_g_nav_entry.u32_cluster          = save_u32_cluster           ;
    01308       fs_g_nav_entry.u32_size             = save_u32_size              ;
    01309    }
    01310    else
    01311    {
    01312       // No parent directory, then it is the root directory
    01313       if( g_b_string_length )
    01314       {
    01315          ((FS_STR_UNICODE)sz_path )[0] = 3;  // 3 chars for path "x:"
    01316          status = TRUE;
    01317       }else
    01318
    01319       // Create a device name
    01320       for( u8_i = 0 ; u8_i<3 ; u8_i++ )
    01321       {
    01322          switch( u8_i )
    01323          {
    01324             case 0:
    01325             u8_character = nav_drive_getname();    // Letter
    01326             break;
    01327             case 1:
    01328             u8_character = ':';                     // ":"
    01329             break;
    01330             case 2:
    01331             default:
    01332             u8_character = 0;                       // end of string
    01333             break;
    01334          }
    01335          if( Is_unicode )
    01336          {
    01337             ((FS_STR_UNICODE)sz_path )[0] = u8_character;
    01338          }else{
    01339             sz_path [0] = u8_character;
    01340          }
    01341          sz_path  += (Is_unicode? 2 : 1 );
    01342       }
    01343       status = TRUE;
    01344
    01345    }
    01346    return status;
    01347 }
    01348
    01349
    01350 #if (FSFEATURE_WRITE_COMPLET == (FS_LEVEL_FEATURES & FSFEATURE_WRITE_COMPLET))
    01358 Bool  nav_dir_make( const FS_STRING sz_name  )
    01359 {
    01360    if ( !fat_check_mount_noopen())
    01361       return FALSE;
    01362
    01363    // Create an entry file
    01364    if ( !nav_file_create( sz_name ))
    01365       return FALSE;
    01366
    01367    // Allocate one cluster for the new directory
    01368    MSB0(fs_g_seg.u32_addr)=0xFF;    // It is a new cluster list
    01369    fs_g_seg.u32_size_or_pos = 1;    // Only one sector (= one cluster)
    01370    if ( !fat_allocfreespace())
    01371    {
    01372       fat_delete_file( FALSE );
    01373       fat_cache_flush();
    01374       return FALSE;
    01375    }
    01376
    01377    // Save information about the new directory
    01378    fs_g_nav_entry.u32_cluster = fs_g_seg.u32_addr; // First cluster of the directory returned by alloc_free_space
    01379    fs_g_nav_entry.u32_size    = 0;                 // The directory size is null
    01380    fs_g_nav_entry.u8_attr     = FS_ATTR_DIRECTORY; // Directory attribut
    01381
    01382    // Initialize the values in the new directory
    01383    if ( !fat_initialize_dir())
    01384       return FALSE;
    01385
    01386    // Write directory information in her entry file
    01387    if ( !fat_read_dir())
    01388       return FALSE;
    01389    fat_write_entry_file();
    01390    if( !fat_cache_flush())
    01391       return FALSE;
    01392
    01393    // Go to position of new directory (it is the last directory)
    01394    return nav_filelist_last( FS_DIR );
    01395 }
    01396 #endif  // FS_LEVEL_FEATURES
    01397
    01398
    01408 Bool  nav_getcwd( FS_STRING sz_path  , U8 u8_size_path , Bool b_view_file_select  )
    01409 {
    01410    _MEM_TYPE_SLOW_   Fs_index index;
    01411    _MEM_TYPE_SLOW_   U16 u16_lgt=0;    // Only used if LENGTH string mode enabled
    01412    U8 u8_save_size_path=0, u8_i;
    01413    Bool status = FALSE;                // Error by default
    01414
    01415    if ( !fat_check_mount_noopen())
    01416       return FALSE;
    01417
    01418    index = nav_getindex();             // Save current position
    01419
    01420    if( g_b_string_length )
    01421    {
    01422       u16_lgt = 1;   // 1 for NULL terminate
    01423    }
    01424    else
    01425    {
    01426       u8_save_size_path = u8_size_path;
    01427       // Set NULL terminator at the end of path
    01428       u8_size_path--;
    01429       if( Is_unicode )
    01430       {
    01431          ((FS_STR_UNICODE)sz_path )[u8_size_path] = 0;
    01432       }else{
    01433          sz_path [u8_size_path]   = 0;
    01434       }
    01435    }
    01436
    01437    // For each directory of path
    01438    while( 1 )
    01439    {
    01440       if( b_view_file_select )
    01441       {
    01442          // Write the selected file or directory in path
    01443          b_view_file_select = FALSE;
    01444          if( !fat_check_select() )
    01445             continue;   // No selected file or directory, then restart loop to go at the first directory of path
    01446       }
    01447       else
    01448       {
    01449          // Go to parent directory and selects the children directory
    01450          if( !nav_dir_gotoparent() )
    01451             break;
    01452       }
    01453
    01454       // Read name of selected file or directory
    01455       if( !nav_file_name( sz_path  , u8_size_path , FS_NAME_GET, FALSE  ))
    01456          break;
    01457
    01458       if( g_b_string_length )
    01459       {
    01460          // Update total length
    01461          u16_lgt += ((FS_STR_UNICODE)sz_path )[0]; // 0 = -1 to remove NULL terminated and +1 for '\\'
    01462          continue;
    01463       }
    01464
    01465       // Compute the size of name
    01466       u8_i = 0;
    01467       while( 1 )
    01468       {
    01469          if( Is_unicode )
    01470          {
    01471             if( 0 == ((FS_STR_UNICODE)sz_path )[u8_i])
    01472                break;
    01473          }else{
    01474             if( 0 == sz_path [u8_i])
    01475                break;
    01476          }
    01477          u8_i++;
    01478       }
    01479
    01480       // Check the string size
    01481       if( (u8_i+1) == u8_size_path )
    01482       {
    01483          fs_g_status = FS_ERR_BUFFER_FULL;   // The path string is full
    01484          break;
    01485       }
    01486
    01487       // Move the name at the end of path
    01488       while( 0 != u8_i )
    01489       {
    01490          u8_i--;
    01491          u8_size_path--;
    01492          if( Is_unicode )
    01493          {
    01494             ((FS_STR_UNICODE)sz_path )[u8_size_path] = ((FS_STR_UNICODE)sz_path )[u8_i];
    01495          }else{
    01496             sz_path [u8_size_path]   = sz_path [u8_i];
    01497          }
    01498       }
    01499       // Set '\' char before the name
    01500       u8_size_path--;
    01501       if( Is_unicode )
    01502       {
    01503          ((FS_STR_UNICODE)sz_path )[u8_size_path] = '\\';
    01504       }else{
    01505          sz_path [u8_size_path]   = '\\';
    01506       }
    01507    }
    01508
    01509    if ( FS_ERR_IS_ROOT == fs_g_status )
    01510    {
    01511       if( g_b_string_length )
    01512       {
    01513          // Update and write total length
    01514          ((FS_STR_UNICODE)sz_path )[0] = u16_lgt +2 ; //+2 for "x:"
    01515          status = TRUE;
    01516       }
    01517       else
    01518       {
    01519          // End of path then add device name
    01520          if( 2 > u8_size_path )
    01521          {
    01522             fs_g_status = FS_ERR_BUFFER_FULL;   // The path string is full
    01523          }
    01524          else
    01525          {
    01526             // Create a device name
    01527             if( Is_unicode )
    01528             {
    01529                ((FS_STR_UNICODE)sz_path )[0] = nav_drive_getname();    // Letter
    01530                ((FS_STR_UNICODE)sz_path )[1] = ':';                   // ":"
    01531             }else{
    01532                sz_path [0] = nav_drive_getname();    // Letter
    01533                sz_path [1] = ':';                      // ":"
    01534             }
    01535
    01536             // The path is stored at the end, then move the path at the beginning
    01537             u8_i = 2;
    01538             while( u8_save_size_path != u8_size_path )
    01539             {
    01540                if( Is_unicode )
    01541                {
    01542                   ((FS_STR_UNICODE)sz_path )[u8_i] = ((FS_STR_UNICODE)sz_path )[u8_size_path];
    01543                }else{
    01544                   sz_path [u8_i] = sz_path [u8_size_path];
    01545                }
    01546                u8_i++;
    01547                u8_size_path++;
    01548             }
    01549             status = TRUE;
    01550          }
    01551       }
    01552    } // else Error system
    01553
    01554    nav_gotoindex( &index );   // Restore the position
    01555    return status;
    01556 }
    01557
    01558
    01575 Bool  nav_setcwd( FS_STRING sz_path , Bool b_match_case , Bool b_create )
    01576 {
    01577    _MEM_TYPE_SLOW_   Fs_index index;
    01578 #if (FSFEATURE_WRITE == (FS_LEVEL_FEATURES & FSFEATURE_WRITE)) ||              \
    01579     (FSFEATURE_WRITE_COMPLET == (FS_LEVEL_FEATURES & FSFEATURE_WRITE_COMPLET))
    01580    FS_STRING sz_save_path = 0;
    01581 #endif
    01582    Bool b_create_name = FALSE;
    01583
    01584    if ( !fat_check_noopen())
    01585       return FALSE;
    01586
    01587    index = nav_getindex();             // Save current position
    01588
    01589    // Check syntact "\path..."
    01590    if( (( Is_unicode) && (('\\'  == ((FS_STR_UNICODE)sz_path )[0]) || ('/'  == ((FS_STR_UNICODE)sz_path )[0])) )
    01591    ||  ((!Is_unicode) && (('\\'  == sz_path [0]) || ('/'  == sz_path [0])) ) )
    01592    {
    01593       // Go to the root of current drive
    01594       if( !nav_dir_root())
    01595          goto nav_setcwd_fail;
    01596       sz_path  += (Is_unicode? 2 : 1 );
    01597    }else
    01598
    01599    // Check syntact "x:\path..."
    01600    if( (( Is_unicode) && (( ':'  == ((FS_STR_UNICODE)sz_path )[1] ) && (('\\'  == ((FS_STR_UNICODE)sz_path )[2] ) || ('/'  == ((FS_STR_UNICODE)sz_path )[2]))) )
    01601    ||  ((!Is_unicode) && (( ':'  == sz_path [1] ) && (('\\'  == sz_path [2] ) || ('/'  == sz_path [2]))) ) )
    01602    {
    01603       // Go to the drive
    01604       if( Is_unicode )
    01605       {
    01606          if( !nav_drive_set( toupper(((FS_STR_UNICODE)sz_path )[0])-'A' ) )
    01607             goto nav_setcwd_fail;
    01608       }else{
    01609          if( !nav_drive_set( toupper(sz_path [0])-'A' ) )
    01610             goto nav_setcwd_fail;
    01611       }
    01612       if( !nav_partition_mount())
    01613          goto nav_setcwd_fail;
    01614       sz_path  += 3*(Is_unicode? 2 : 1 );
    01615    }else
    01616
    01617    // Check syntact ".\path..."
    01618    if( (( Is_unicode) && (( '.'  == ((FS_STR_UNICODE)sz_path )[0] ) && (('\\'  == ((FS_STR_UNICODE)sz_path )[1] ) || ('/'  == ((FS_STR_UNICODE)sz_path )[1] ))) )
    01619    ||  ((!Is_unicode) && (( '.'  == sz_path [0] ) && (('\\'  == sz_path [1] ) || ('/'  == sz_path [1] ))) ) )
    01620    {
    01621       // Search in current directory
    01622       sz_path  += 2*(Is_unicode? 2 : 1 );
    01623    }else
    01624
    01625    {
    01626       // Check syntact "..\..\path..."
    01627       if( Is_unicode )
    01628       {
    01629          while(( '.'  == ((FS_STR_UNICODE)sz_path )[0] )
    01630          &&    ( '.'  == ((FS_STR_UNICODE)sz_path )[1] )
    01631          &&    (('\\'  == ((FS_STR_UNICODE)sz_path )[2]) || ('/'  == ((FS_STR_UNICODE)sz_path )[2]) || (0  == ((FS_STR_UNICODE)sz_path )[2])) )
    01632          {
    01633             // Go to parent directory
    01634             if( !nav_dir_gotoparent() )
    01635                goto nav_setcwd_fail;
    01636             sz_path  += (2*2); // jump ".."
    01637             if( 0 != ((FS_STR_UNICODE)sz_path )[0])
    01638                sz_path  += (2*1); // jump "/"
    01639          }
    01640       }else{
    01641          while(( '.'  == sz_path [0] )
    01642          &&    ( '.'  == sz_path [1] )
    01643          &&    (('\\'  == sz_path [2]) || ('/'  == sz_path [2]) || (0  == sz_path [2])) )
    01644          {
    01645          // Go to parent directory
    01646          if( !nav_dir_gotoparent() )
    01647             goto nav_setcwd_fail;
    01648             sz_path  += 2; // jump ".."
    01649             if( 0 != sz_path [0])
    01650                sz_path  +=1; // jump "/"
    01651          }
    01652       }
    01653    }
    01654
    01655    // Reset list to start the search at the beginning
    01656    if( !nav_filelist_reset())
    01657       goto nav_setcwd_fail;
    01658
    01659    while( 1 )
    01660    {
    01661       if( (( Is_unicode) && ( 0 == ((FS_STR_UNICODE)sz_path )[0] ) )
    01662       ||  ((!Is_unicode) && ( 0 == sz_path [0] ) ) )
    01663       {
    01664          return TRUE;   // path (without file) is found or create
    01665       }
    01666       if( !nav_filelist_findname( sz_path  , b_match_case  ))
    01667       {
    01668          // The file or directory is not found
    01669          if( !b_create )
    01670             goto nav_setcwd_fail;   // don't creat the directory then exit
    01671          // Set flag to create the directory
    01672          b_create_name = TRUE;
    01673 #if (FSFEATURE_WRITE == (FS_LEVEL_FEATURES & FSFEATURE_WRITE)) ||              \
    01674     (FSFEATURE_WRITE_COMPLET == (FS_LEVEL_FEATURES & FSFEATURE_WRITE_COMPLET))
    01675          sz_save_path = sz_path;
    01676 #endif
    01677       }
    01678
    01679       while( 1 )
    01680       {
    01681          sz_path  += (Is_unicode? 2 : 1 );
    01682          if( (( Is_unicode) && ( 0 == ((FS_STR_UNICODE)sz_path )[0] ) )
    01683          ||  ((!Is_unicode) && ( 0 == sz_path [0] ) ) )
    01684          {
    01685             // Is it the last name of path and it is a file
    01686             if( b_create_name )
    01687             {
    01688 #if (FSFEATURE_WRITE == (FS_LEVEL_FEATURES & FSFEATURE_WRITE))
    01689                // The file must be created
    01690                if( !nav_file_create( sz_save_path ) )
    01691                   goto nav_setcwd_fail;
    01692 #else
    01693                goto nav_setcwd_fail;
    01694 #endif
    01695             }
    01696             break;   // The file include in path is found or created, then end of set_cwd
    01697          }
    01698
    01699          if( (( Is_unicode) && (('\\' == ((FS_STR_UNICODE)sz_path )[0] ) || ('/' == ((FS_STR_UNICODE)sz_path )[0] )) )
    01700          ||  ((!Is_unicode) && (('\\' == sz_path [0] ) || ('/' == sz_path [0] )) ) )
    01701          {
    01702             // Is it a folder name
    01703             if( b_create_name )
    01704             {
    01705 #if (FSFEATURE_WRITE_COMPLET == (FS_LEVEL_FEATURES & FSFEATURE_WRITE_COMPLET))
    01706                // The folder doesn't exist and it must be created
    01707                if( !nav_dir_make( sz_save_path ))
    01708                   goto nav_setcwd_fail;
    01709 #else
    01710                goto nav_setcwd_fail;
    01711 #endif
    01712             }
    01713             if( !fat_entry_is_dir() )
    01714                goto nav_setcwd_fail;
    01715             // jump '\'
    01716             sz_path  += (Is_unicode? 2 : 1 );
    01717             if( !nav_dir_cd())
    01718                goto nav_setcwd_fail;
    01719             break;
    01720          }
    01721       }
    01722
    01723    }
    01724
    01725 nav_setcwd_fail:
    01726    nav_gotoindex( &index );   // Restore the position
    01727    return FALSE;
    01728 }
    01729
    01730
    01731
    01732
    01733 //**********************************************************************
    01734 //*********************** File control functions ***********************
    01735
    01736
    01745 Bool nav_file_getname( FS_STRING sz_name, U8 u8_size_max )
    01746 {
    01747    return nav_file_name( sz_name, u8_size_max, FS_NAME_GET, FALSE );
    01748 }
    01749
    01750
    01766 Bool  nav_file_name( FS_STRING sz_name , U8 u8_size_max , Bool b_mode , Bool b_match_case  )
    01767 {
    01768    _MEM_TYPE_SLOW_   U16 u16_lgt;   // Only used if LENGTH string mode enabled
    01769    U16  u16_ptr_save_entry;
    01770    Bool  b_readshortname = FALSE;
    01771
    01772    if ( !fat_check_mount_select())
    01773       return FALSE;
    01774
    01775    // Check if the string size is not 0
    01776    if( (FS_NAME_GET == b_mode)
    01777    &&  (0 == u8_size_max) )
    01778    {
    01779       return TRUE;
    01780    }
    01781
    01782    // Save the current entry position
    01783    u16_ptr_save_entry = fs_g_nav_fast.u16_entry_pos_sel_file;
    01784    // if it is the beginning of the directory
    01785    if ( 0 == fs_g_nav_fast.u16_entry_pos_sel_file )
    01786    {
    01787       b_readshortname = TRUE;                   // It isn't possibled to have a long name
    01788    }
    01789    else
    01790    {
    01791       fs_g_nav_fast.u16_entry_pos_sel_file--;   // Initialize entry position to search the first long name entry
    01792    }
    01793
    01794    // Loop in directory entry
    01795    u16_lgt = 0;
    01796    while( 1 )
    01797    {
    01798       if ( !fat_read_dir())
    01799          break; // error
    01800
    01801       if ( b_readshortname )
    01802       {
    01803          // No long name present then read short name
    01804          return fat_entry_shortname( sz_name , u8_size_max , b_mode  );
    01805       }
    01806
    01807       // Check or read the part of long file name in this entry
    01808       if ( fat_entry_longname( sz_name , u8_size_max , b_mode , b_match_case  ))
    01809       {
    01810          if( g_b_string_length )
    01811          {
    01812             ((FS_STR_UNICODE)sz_name )[0] += u16_lgt;
    01813          }
    01814          fs_g_nav_fast.u16_entry_pos_sel_file = u16_ptr_save_entry;
    01815          return TRUE;
    01816       }
    01817
    01818       if ( FS_NO_LAST_LFN_ENTRY != fs_g_status )
    01819       {
    01820          // Go to the main entry file (=short name entry)
    01821          fs_g_nav_fast.u16_entry_pos_sel_file = u16_ptr_save_entry;
    01822
    01823          if ( FS_ERR_ENTRY_BAD == fs_g_status )
    01824          {
    01825             // It isn't a long name entry then there aren't long file name
    01826             b_readshortname = TRUE;   // It is mandatory to use the short name
    01827             continue;                 // restart the loop
    01828          }
    01829          // here, it is a error system or the string don't match with the file name
    01830          break;
    01831       }
    01832       if( g_b_string_length )
    01833       {
    01834          u16_lgt += FS_SIZE_LFN_ENTRY;
    01835       }
    01836       else
    01837       {
    01838          // Increment the string to store the next part of file name
    01839          sz_name += FS_SIZE_LFN_ENTRY * (Is_unicode? 2 : 1 );
    01840          u8_size_max -= FS_SIZE_LFN_ENTRY;
    01841       }
    01842       fs_g_nav_fast.u16_entry_pos_sel_file--;   // Go to the next part of long file name
    01843
    01844    }  // end of loop while(1)
    01845    return FALSE;
    01846 }
    01847
    01848
    01853 U32   nav_file_lgt( void )
    01854 {
    01855    return fs_g_nav_entry.u32_size;
    01856 }
    01857
    01858
    01863 U16   nav_file_lgtsector( void )
    01864 {
    01865    return (fs_g_nav_entry.u32_size >> FS_512B_SHIFT_BIT);
    01866 }
    01867
    01868
    01874 Bool  nav_file_isreadonly( void )
    01875 {
    01876    if( !fat_check_mount_select() )
    01877       return TRUE;   // No file selected
    01878    if( mem_wr_protect( fs_g_nav.u8_lun ) )
    01879       return TRUE;   // Disk protected
    01880    return (0!=(FS_ATTR_READ_ONLY & fs_g_nav_entry.u8_attr));   // Check attribut "read only"
    01881 }
    01882
    01883
    01889 Bool  nav_file_isdir( void )
    01890 {
    01891    return fat_entry_is_dir();
    01892 }
    01893
    01894
    01902 Bool  nav_file_checkext( const FS_STRING sz_filterext )
    01903 {
    01904    if ( fat_check_mount_select() )
    01905    {
    01906       // Read selected entry (=short name entry) in directory
    01907       if ( fat_read_dir())
    01908       {
    01909          // Check the extension with filter
    01910          if ( fat_entry_checkext( (FS_STRING) sz_filterext ) )
    01911             return TRUE;
    01912       }
    01913    }
    01914    return FALSE;
    01915 }
    01916
    01917
    01928 Bool  nav_file_dateget( FS_STRING sz_date , Bool type_date )
    01929 {
    01930    if ( !fat_check_mount_select())
    01931       return FALSE;
    01932
    01933    // Read selected entry in directory
    01934    if ( !fat_read_dir())
    01935       return FALSE;
    01936    fat_get_date( sz_date , type_date );
    01937    return TRUE;
    01938 }
    01939
    01940
    01945 U8    nav_file_attributget( void )
    01946 {
    01947    return fs_g_nav_entry.u8_attr;
    01948 }
    01949
    01950
    01951
    01952 #if (FSFEATURE_WRITE_COMPLET == (FS_LEVEL_FEATURES & FSFEATURE_WRITE_COMPLET))
    01963 Bool  nav_file_dateset( const FS_STRING sz_date , Bool type_date )
    01964 {
    01965    if ( !fat_check_mount_select())
    01966       return FALSE;
    01967
    01968    // Read selected entry in directory
    01969    if ( !fat_read_dir())
    01970       return FALSE;
    01971    fat_set_date( sz_date , type_date );
    01972    return fat_cache_flush();  // To write all data and check write access before exit function
    01973 }
    01974 #endif  // FS_LEVEL_FEATURES
    01975
    01976
    01977 #if (FSFEATURE_WRITE_COMPLET == (FS_LEVEL_FEATURES & FSFEATURE_WRITE_COMPLET))
    01985 Bool  nav_file_attributset( U8 u8_attribut )
    01986 {
    01987    if ( !fat_check_mount_select())
    01988       return FALSE;
    01989
    01990    // Read selected entry in directory
    01991    if ( !fat_read_dir())
    01992       return FALSE;
    01993
    01994    // Write the new attribut
    01995    fs_g_nav_entry.u8_attr &= (~(FS_ATTR_READ_ONLY|FS_ATTR_HIDDEN|FS_ATTR_SYSTEM|FS_ATTR_ARCHIVE));
    01996    fs_g_nav_entry.u8_attr |= u8_attribut & (FS_ATTR_READ_ONLY|FS_ATTR_HIDDEN|FS_ATTR_SYSTEM|FS_ATTR_ARCHIVE);
    01997    fat_write_entry_file();
    01998    return fat_cache_flush();  // To write all data and check write access before exit function
    01999 }
    02000 #endif  // FS_LEVEL_FEATURES
    02001
    02002
    02003 #if (FSFEATURE_WRITE == (FS_LEVEL_FEATURES & FSFEATURE_WRITE))
    02013 Bool  nav_file_del( Bool b_only_empty )
    02014 {
    02015    U8 u8_folder_level = 0xFF;
    02016
    02017    if ( !fat_check_mount_select_noopen())
    02018       return FALSE;
    02019
    02020    if( 0xFF == u8_folder_level )  // to remove a eventually compile warning
    02021      goto nav_file_del_test_dir_or_file;
    02022
    02023    // loop to scan and delete ALL folders and ALL files
    02024    while(1)
    02025    {
    02026       while(1)
    02027       {
    02028          if( nav_filelist_set( 0 , FS_FIND_NEXT ) )
    02029          {
    02030             // Directory no empty
    02031             if( b_only_empty )
    02032             {
    02033                fs_g_status = FS_ERR_DIR_NOT_EMPTY;      // Erase only the empty directory
    02034                return FALSE;
    02035             }
    02036             break; // Exit loop to delete files or directories present
    02037          }
    02038          // HERE, directory empty
    02039
    02040          // Go to parent directory and this one select the children directory
    02041          if( !nav_dir_gotoparent() )
    02042             return FALSE;
    02043
    02044          // Delete children directory name and her cluster list
    02045          if ( !fat_delete_file( TRUE ))
    02046             return FALSE;
    02047
    02048          if( 0 == u8_folder_level )
    02049          {
    02050             // All directory tree is deleted
    02051             return TRUE; //********* END OF DEL TREE **************
    02052          }
    02053          u8_folder_level--;
    02054
    02055       } // end of second while (1)
    02056
    02057 nav_file_del_test_dir_or_file:
    02058       if( nav_file_isdir())
    02059       {
    02060          // here, a directory is found and is selected
    02061          if( !nav_dir_cd())
    02062             return FALSE;
    02063          u8_folder_level++;
    02064       }
    02065       else
    02066       {
    02067          // here, a file is found and is selected
    02068          if( !fat_check_nav_access_file( TRUE ) )
    02069             return FALSE;
    02070          // delete file entry name and cluster list
    02071          if ( !fat_delete_file( TRUE ))
    02072             return FALSE;
    02073          if( 0xFF == u8_folder_level )
    02074             break;   // only one file to delete
    02075       } // if dir OR file
    02076    } // end of first while(1)
    02077
    02078    // Reset selection
    02079    nav_filelist_reset();
    02080    return fat_cache_flush();  // To write all data and check write access before exit function
    02081 }
    02082 #endif  // FS_LEVEL_FEATURES
    02083
    02084
    02085 #if (FSFEATURE_WRITE_COMPLET == (FS_LEVEL_FEATURES & FSFEATURE_WRITE_COMPLET))
    02093 Bool  nav_file_rename( const FS_STRING sz_name  )
    02094 {
    02095    U16 u16_save_entry_pos;
    02096    Bool b_save_entry_type;
    02097    U8 u8_attr;
    02098    U32 u32_cluster;
    02099    U32 u32_size;
    02100
    02101    if ( !fat_check_mount_select_noopen())
    02102       return FALSE;
    02103
    02104    if( !fat_check_nav_access_file( TRUE ) )
    02105       return FALSE;
    02106
    02107    // Note: in case of error, create the new name before delete the current name
    02108
    02109    // Save information about current name poisition
    02110    u16_save_entry_pos = fs_g_nav_fast.u16_entry_pos_sel_file;
    02111    b_save_entry_type  = fs_g_nav.b_mode_nav;
    02112    // Save information about file
    02113    u8_attr           = fs_g_nav_entry.u8_attr;
    02114    u32_cluster       = fs_g_nav_entry.u32_cluster;
    02115    u32_size          = fs_g_nav_entry.u32_size;
    02116
    02117    // Create a name
    02118    if ( !nav_file_create( sz_name  ))
    02119       return FALSE; // error
    02120    // Restore information about file or directory on the new name entry
    02121    if ( !fat_read_dir())
    02122       return FALSE;
    02123    fs_g_nav_entry.u8_attr = u8_attr;
    02124    fs_g_nav_entry.u32_cluster = u32_cluster;
    02125    fs_g_nav_entry.u32_size = u32_size;
    02126    fat_write_entry_file();
    02127
    02128    // Delete old entry name
    02129    fs_g_nav_fast.u16_entry_pos_sel_file = u16_save_entry_pos; // go to old entry name
    02130    if ( !fat_delete_file(FALSE) )
    02131       return FALSE;
    02132    if ( !fat_cache_flush() )
    02133       return FALSE;
    02134
    02135    // Go to at the position of the new name entry (it is the last file or directory )
    02136    return nav_filelist_last( b_save_entry_type );
    02137 }
    02138 #endif  // FS_LEVEL_FEATURES
    02139
    02140 #if (FSFEATURE_WRITE == (FS_LEVEL_FEATURES & FSFEATURE_WRITE))
    02141
    02153 Bool  nav_file_create( const FS_STRING sz_name  )
    02154 {
    02155    // Check if the name already exists
    02156    if (!nav_filelist_reset())
    02157       return FALSE;
    02158    if (nav_filelist_findname(sz_name , FALSE))
    02159    {
    02160       fs_g_status = FS_ERR_FILE_EXIST;
    02161       return FALSE;  // File exist -> it is not possible to create this name
    02162    }
    02163    // FYC: here, the selection is at the end of the list
    02164    // Create name entrys
    02165    if ( !fat_create_entry_file_name( sz_name ))
    02166       return FALSE; // error
    02167    // By default the information about the new file is NULL
    02168    fs_g_nav_entry.u32_cluster = 0;     // No first cluster
    02169    fs_g_nav_entry.u32_size    = 0;     // The size is null
    02170    fs_g_nav_entry.u8_attr     = 0;     // Attribut is a file
    02171
    02172    // It is the last FILE of the list
    02173    fs_g_nav.u16_pos_sel_file++;
    02174    fs_g_nav.b_mode_nav = FS_FILE;
    02175    return fat_cache_flush();
    02176 }
    02177
    02178
    02188 Bool  nav_file_copy( void )
    02189 {
    02190    if( nav_file_isdir() )
    02191    {
    02192       fs_g_status = FS_ERR_COPY_DIR; // Impossible to copy a directory
    02193       return FALSE;
    02194    }
    02195    // In "copy file" navigator select the file
    02196    nav_copy( FS_NAV_ID_COPYFILE );
    02197    return TRUE;
    02198 }
    02199
    02200
    02212 Bool  nav_file_paste_start( const FS_STRING sz_name  )
    02213 {
    02214    U8 nav_id_save;
    02215    Bool status;
    02216
    02217    if( ID_STREAM_ERR != g_id_trans_memtomem )
    02218    {
    02219
    02220       fs_g_status = FS_ERR_COPY_RUNNING;  // A copy action is always running
    02221       return FALSE;
    02222    }
    02223
    02224    // Create the file to paste
    02225    if( !nav_file_create( sz_name  ) )
    02226       return FALSE;
    02227    // Open the file in write mode with size 0
    02228    if( !file_open( FOPEN_MODE_W_PLUS ))
    02229       return FALSE;
    02230
    02231    // Open the file to copy
    02232    nav_id_save = nav_get();
    02233    nav_select( FS_NAV_ID_COPYFILE );
    02234    status = file_open(FOPEN_MODE_R);
    02235    nav_select( nav_id_save );
    02236
    02237    // If error then close "paste file"
    02238    if( !status )
    02239    {
    02240       file_close();
    02241       return FALSE;
    02242    }else{
    02243       // Signal start copy
    02244       g_id_trans_memtomem = ID_STREAM_ERR-1;
    02245       g_segment_src.u16_size = 0;
    02246       return TRUE;
    02247    }
    02248 }
    02249
    02250
    02260 U8    nav_file_paste_state( Bool b_stop )
    02261 {
    02262    Ctrl_status status_stream;
    02263    U8 status_copy;
    02264    U8 nav_id_save;
    02265    _MEM_TYPE_SLOW_ U16 u16_nb_sector_trans;
    02266
    02267    nav_id_save = nav_get();
    02268
    02269    // Check, if the copy is running
    02270    if( ID_STREAM_ERR == g_id_trans_memtomem )
    02271       return COPY_FAIL;
    02272
    02273    if( b_stop )
    02274    {
    02275       status_copy = COPY_FAIL;
    02276    }
    02277    else
    02278    {
    02279       if( (ID_STREAM_ERR-1) != g_id_trans_memtomem )
    02280       {
    02281          // It isn't the beginning of copy action, then check current stream
    02282          status_stream = stream_state( g_id_trans_memtomem );
    02283          switch( status_stream )
    02284          {
    02285          case CTRL_BUSY:
    02286             status_copy = COPY_BUSY;
    02287             break;
    02288          case CTRL_GOOD:
    02289             status_copy = COPY_FINISH;
    02290             break;
    02291          case CTRL_FAIL:
    02292          default:
    02293             status_copy = COPY_FAIL;
    02294             break;
    02295          }
    02296       }else{
    02297          status_copy = COPY_FINISH;
    02298       }
    02299
    02300       // Compute the new segment to copy
    02301       if( COPY_FINISH == status_copy )
    02302       {
    02303          stream_stop( g_id_trans_memtomem );
    02304
    02305          if( 0 != g_segment_src.u16_size )
    02306          {
    02307             status_copy = COPY_BUSY;            // start the next continue stream
    02308          }
    02309          else
    02310          {
    02311             // check eof source file
    02312             nav_select( FS_NAV_ID_COPYFILE );
    02313             if( 0 == file_eof() )
    02314             {
    02315                status_copy = COPY_BUSY;
    02316                g_segment_src.u16_size = 0xFFFF; // Get the maximum segment supported by navigation (U16)
    02317                if( !file_read( &g_segment_src ))
    02318                {
    02319                   status_copy = COPY_FAIL;
    02320                }
    02321             }
    02322             nav_select( nav_id_save );
    02323
    02324             // Check destination file
    02325             if( COPY_BUSY == status_copy )
    02326             {
    02327                 g_segment_dest.u16_size = g_segment_src.u16_size; // Ask the segment no more larger than source segment
    02328                 if( !file_write( &g_segment_dest ))
    02329                {
    02330                   status_copy = COPY_FAIL;
    02331                }
    02332             }
    02333
    02334             // Start new segment copy
    02335             if( COPY_BUSY == status_copy )
    02336             {
    02337                // Compute a minimal segment
    02338                 if( g_segment_src.u16_size > g_segment_dest.u16_size )
    02339                {
    02340                   // Reposition source file
    02341                   nav_select( FS_NAV_ID_COPYFILE );
    02342                    if( !file_seek( (U32)(g_segment_src.u16_size - g_segment_dest.u16_size)*FS_512B , FS_SEEK_CUR_RE ))
    02343                   {
    02344                      status_copy = COPY_FAIL;
    02345                   }
    02346                   nav_select( nav_id_save );
    02347                    g_segment_src.u16_size = g_segment_dest.u16_size; // Update source to start a correct transfer
    02348                }
    02349             }
    02350          }
    02351          if( COPY_BUSY == status_copy )
    02352          {
    02353             // Split transfer by step of SIZE_OF_SPLIT_COPY
    02354             if( g_segment_src.u16_size < SIZE_OF_SPLIT_COPY )
    02355                u16_nb_sector_trans = g_segment_src.u16_size;
    02356             else
    02357                u16_nb_sector_trans = SIZE_OF_SPLIT_COPY;
    02358
    02359             g_id_trans_memtomem = stream_mem_to_mem( g_segment_src.u8_lun , g_segment_src.u32_addr , g_segment_dest.u8_lun , g_segment_dest.u32_addr , u16_nb_sector_trans );
    02360             if( ID_STREAM_ERR == g_id_trans_memtomem )
    02361                   status_copy = COPY_FAIL;
    02362             g_segment_src.u32_addr +=u16_nb_sector_trans;
    02363             g_segment_dest.u32_addr+=u16_nb_sector_trans;
    02364             g_segment_src.u16_size -=u16_nb_sector_trans;
    02365          }
    02366       }
    02367    }
    02368
    02369    // Check end of copy
    02370    if( COPY_BUSY != status_copy )
    02371    {
    02372       U32 u32_size_exact;
    02373
    02374       // Stop copy
    02375       stream_stop( g_id_trans_memtomem );
    02376       g_id_trans_memtomem = ID_STREAM_ERR;
    02377
    02378       // Get exact size and close the source file
    02379       nav_select( FS_NAV_ID_COPYFILE );
    02380       u32_size_exact = nav_file_lgt();
    02381       file_close();
    02382       nav_select( nav_id_save );
    02383
    02384       // If no error then set the exact size on the destination file
    02385       if( COPY_FINISH == status_copy )
    02386       {
    02387          if( !file_seek( u32_size_exact , FS_SEEK_SET ))
    02388          {
    02389             status_copy = COPY_FAIL;
    02390          }else{
    02391             if( !file_set_eof() )
    02392             {
    02393                status_copy = COPY_FAIL;
    02394             }
    02395          }
    02396       }
    02397       file_close();
    02398       // If error then delete the destination file
    02399       if( COPY_FAIL == status_copy )
    02400       {
    02401          nav_file_del( TRUE );
    02402       }
    02403    }
    02404    return status_copy;
    02405 }
    02406 #endif  // FS_LEVEL_FEATURES