ATMEL: navigation.c Source File

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

# navigation.c

Go to the documentation of this file.

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