Ignore:
Timestamp:
Jul 19, 2017, 3:31:39 PM (7 years ago)
Author:
alain
Message:

Fixing bugs in vfs_lookup()

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/kernel/vfs/fatfs.c

    r188 r238  
    22 * fatfs.c - FATFS file system API implementation.
    33 *
    4  * Author    Mohamed Lamine Karaoui (2014,2015)
    5  *           Alain Greiner (2016,2017)
     4 * Author    Alain Greiner (2016,2017)
    65 *
    76 * Copyright (c) UPMC Sorbonne Universites
     
    3029#include <ppm.h>
    3130#include <vfs.h>
     31#include <string.h>
    3232#include <rpc.h>
    3333#include <mapper.h>
     
    4646 
    4747//////////////////////////////////////////////////////////////////////////////////////////
    48 //              FATFS private functions
    49 //////////////////////////////////////////////////////////////////////////////////////////
     48//              FATFS private and static functions
     49//////////////////////////////////////////////////////////////////////////////////////////
     50
     51//////////////////////////////////////////////////////////////////////////////////////////
     52// These functions return the "offset" and "length" values of an
     53// [offset,length] constant defined in the fatfs.h file.
     54//////////////////////////////////////////////////////////////////////////////////////////
     55
     56static inline int get_length( int offset , int length ) { return length; }
     57
     58static inline int get_offset( int offset , int length ) { return offset; }
     59
    5060
    5161//////////////////////////////////////////////////////////////////////////////////////////
     
    6373}
    6474
    65 /////////////////////////////////////////////
    66 error_t fatfs_get_cluster( mapper_t * mapper,
    67                            uint32_t   first_cluster,
    68                            uint32_t   searched_page,
    69                            uint32_t * cluster )
    70 {
    71     page_t   * current_page_desc;      // pointer on current page descriptor
    72     uint32_t * current_page_buffer;    // pointer on current page (array of uint32_t)
    73     uint32_t   current_page_index;     // index of current page in mapper
    74     uint32_t   current_page_offset;    // offset of slot in current page
    75     uint32_t   page_count_in_file;     // index of page in file (index in linked list)
    76     uint32_t   current_cluster;        // content of current FAT slot
    77 
    78     // compute number of FAT slots per PPM page
    79     uint32_t slots_per_page = CONFIG_PPM_PAGE_SIZE >> 2;
    80 
    81     // initialize loop variable
    82     current_page_index  = first_cluster / slots_per_page;
    83     current_page_offset = first_cluster % slots_per_page;
    84     page_count_in_file  = 0;
    85 
    86     // scan FAT (i.e. traverse FAT linked list)
    87     while( page_count_in_file <= searched_page )
    88     {
    89         // get pointer on current page descriptor
    90         current_page_desc = mapper_get_page( mapper , current_page_index );
    91 
    92         if( current_page_desc == NULL ) return EIO;
    93 
    94         // get pointer on buffer for current page
    95         current_page_buffer = (uint32_t *)ppm_page2vaddr( current_page_desc );
    96 
    97         // get FAT slot content
    98         current_cluster = current_page_buffer[current_page_offset];
    99 
    100         // update loop variables
    101         current_page_index  = current_cluster / slots_per_page;
    102         current_page_offset = current_cluster % slots_per_page;
    103         page_count_in_file++;
    104     }
    105    
    106     // return success
    107     *cluster = current_cluster;
    108     return 0;
    109 
    110 }  // end fatfs_get_cluster()
    111 
    112 ///////////////////////////////////////////////////////////////////////////////////////
    113 // This static function return an integer record value (one, two, or four bytes)
     75
     76//////////////////////////////////////////////////////////////////////////////////////////
     77// This function return an integer record value (one, two, or four bytes)
    11478// from a memory buffer, taking into account endianness.
    115 ///////////////////////////////////////////////////////////////////////////////////////
     79//////////////////////////////////////////////////////////////////////////////////////////
    11680// @ offset        : first byte of record in buffer.
    11781// @ size          : record length in bytes (1/2/4).
     
    11983// @ little endian : the most significant byte has the highest address when true.
    12084// @ return the integer value in a 32 bits word.
    121 ///////////////////////////////////////////////////////////////////////////////////////
    122 static uint32_t get_record_from_buffer( uint32_t    offset,
    123                                         uint32_t    size,
    124                                         uint8_t   * buffer,
    125                                         uint32_t    little_endian )
     85//////////////////////////////////////////////////////////////////////////////////////////
     86static uint32_t fatfs_get_record( uint32_t    offset,
     87                                  uint32_t    size,
     88                                  uint8_t   * buffer,
     89                                  uint32_t    little_endian )
    12690{
    12791    uint32_t n;
     
    138102    return res;
    139103
    140 }  // end get_record_from_buffer()
    141 
    142 
    143 
    144 ////////////////////////////////////////////////////////////////////////////////////////
     104}  // end fatfs_get_record()
     105
     106//////////////////////////////////////////////////////////////////////////////////////////
     107// This static function retun in the <name> buffer a short name stored in
     108// a SFN FATFS directory entry.
     109/////////////////////////i////////////////////////////////////////////////////////////////
     110// @ buffer   : pointer on buffer containing the directory entry.
     111// @ name     : [out] buffer allocated by the caller.
     112//////////////////////////////////////////////////////////////////////////////////////////
     113static void fatfs_get_name_from_short( uint8_t * buffer,
     114                                       char    * name )
     115{
     116    uint32_t i;
     117    uint32_t j = 0;
     118
     119    // get name
     120    for ( i = 0; i < 8 && buffer[i] != ' '; i++ )
     121    {
     122        name[j] = to_lower( buffer[i] );
     123        j++;
     124    }
     125
     126    // get extension
     127    for ( i = 8; i < 8 + 3 && buffer[i] != ' '; i++ )
     128    {
     129        // we entered the loop so there is an extension. add the dot
     130        if ( i == 8 )
     131        {
     132            name[j] = '.';
     133            j++;
     134        }
     135
     136        name[j] = to_lower( buffer[i] );
     137        j++;
     138    }
     139
     140    name[j] = '\0';
     141}
     142
     143//////////////////////////////////////////////////////////////////////////////////////////
     144// This static function retun in the <name> buffer a partial name stored in
     145// a LFN FATFS directory entry.
     146/////////////////////////i////////////////////////////////////////////////////////////////
     147// @ buffer   : pointer on buffer containing the directory entry.
     148// @ name     : [out] buffer allocated by the caller.
     149//////////////////////////////////////////////////////////////////////////////////////////
     150static void fatfs_get_name_from_long( uint8_t * buffer,
     151                                      char    * name )
     152{
     153    uint32_t   name_offset   = 0;
     154    uint32_t   buffer_offset = get_length(LDIR_ORD);
     155    uint32_t   l_name_1      = get_length(LDIR_NAME_1);
     156    uint32_t   l_name_2      = get_length(LDIR_NAME_2);
     157    uint32_t   l_name_3      = get_length(LDIR_NAME_3);
     158    uint32_t   l_attr        = get_length(LDIR_ATTR);
     159    uint32_t   l_type        = get_length(LDIR_TYPE);
     160    uint32_t   l_chksum      = get_length(LDIR_CHKSUM);
     161    uint32_t   l_rsvd        = get_length(LDIR_RSVD);
     162
     163    uint32_t   j             = 0;
     164    uint32_t   eof           = 0;
     165
     166    while ( (buffer_offset != DIR_ENTRY_SIZE)  && (!eof) )
     167    {
     168        while (j != l_name_1 && !eof )
     169        {
     170            if ( (buffer[buffer_offset] == 0x00) ||
     171                 (buffer[buffer_offset] == 0xFF) )
     172            {
     173                eof = 1;
     174                continue;
     175            }
     176            name[name_offset] = buffer[buffer_offset];
     177            buffer_offset += 2;
     178            j += 2;
     179            name_offset++;
     180        }
     181
     182        buffer_offset += (l_attr + l_type + l_chksum);
     183        j = 0;
     184
     185        while (j != l_name_2 && !eof )
     186        {
     187            if ( (buffer[buffer_offset] == 0x00) ||
     188                 (buffer[buffer_offset] == 0xFF) )
     189            {
     190                eof = 1;
     191                continue;
     192            }
     193            name[name_offset] = buffer[buffer_offset];
     194            buffer_offset += 2;
     195            j += 2;
     196            name_offset++;
     197        }
     198
     199        buffer_offset += l_rsvd;
     200        j = 0;
     201
     202        while (j != l_name_3 && !eof )
     203        {
     204            if ( (buffer[buffer_offset] == 0x00) ||
     205                 (buffer[buffer_offset] == 0xFF) )
     206            {
     207                eof = 1;
     208                continue;
     209            }
     210            name[name_offset] = buffer[buffer_offset];
     211            buffer_offset += 2;
     212            j += 2;
     213            name_offset++;
     214        }
     215    }
     216    name[name_offset] = 0;
     217
     218} // end get_name_from_long()
     219
     220//////////////////////////////////////////////////////////////////////////////////////////
    145221// This function returns the FATFS cluster index of a page identified by its page
    146222// index in the file, using the FAT mapper. It scans the FAT mapper, starting from the
     
    152228// in the cluster containing the FAT mapper, and the RPC latency is not critical
    153229// compared to the device access latency.
    154 ////////////////////////////////////////////////////////////////////////////////////////
     230//////////////////////////////////////////////////////////////////////////////////////////
    155231// @ ctx               : pointer on local FATFS context.
    156232// @ first_cluster : first cluster allocated to a file in FATFS.
     
    158234// @ cluster_index : [out] pointer on buffer for FATFS cluster index.
    159235// @ return 0 if success / return EIO if a FAT cluster miss cannot be solved.
    160 ////////////////////////////////////////////////////////////////////////////////////////
     236//////////////////////////////////////////////////////////////////////////////////////////
    161237static error_t fatfs_cluster_from_index( fatfs_ctx_t * ctx,
    162238                                         uint32_t      first_cluster,
     
    203279}  // end fatfs_cluster_from_index()
    204280
     281//////////////////////////////////////////////////////////////////////////////////////////
     282//              FATFS specific but public functions (used by RPC_FATFS_GET_CLUSTER)
     283//////////////////////////////////////////////////////////////////////////////////////////
     284
     285/////////////////////////////////////////////
     286error_t fatfs_get_cluster( mapper_t * mapper,
     287                           uint32_t   first_cluster,
     288                           uint32_t   searched_page,
     289                           uint32_t * cluster )
     290{
     291    page_t   * current_page_desc;      // pointer on current page descriptor
     292    uint32_t * current_page_buffer;    // pointer on current page (array of uint32_t)
     293    uint32_t   current_page_index;     // index of current page in mapper
     294    uint32_t   current_page_offset;    // offset of slot in current page
     295    uint32_t   page_count_in_file;     // index of page in file (index in linked list)
     296    uint32_t   current_cluster;        // content of current FAT slot
     297
     298    // compute number of FAT slots per PPM page
     299    uint32_t slots_per_page = CONFIG_PPM_PAGE_SIZE >> 2;
     300
     301    // initialize loop variable
     302    current_page_index  = first_cluster / slots_per_page;
     303    current_page_offset = first_cluster % slots_per_page;
     304    page_count_in_file  = 0;
     305
     306    // scan FAT (i.e. traverse FAT linked list)
     307    while( page_count_in_file <= searched_page )
     308    {
     309        // get pointer on current page descriptor
     310        current_page_desc = mapper_get_page( mapper , current_page_index );
     311
     312        if( current_page_desc == NULL ) return EIO;
     313
     314        // get pointer on buffer for current page
     315        current_page_buffer = (uint32_t *)ppm_page2vaddr( current_page_desc );
     316
     317        // get FAT slot content
     318        current_cluster = current_page_buffer[current_page_offset];
     319
     320        // update loop variables
     321        current_page_index  = current_cluster / slots_per_page;
     322        current_page_offset = current_cluster % slots_per_page;
     323        page_count_in_file++;
     324    }
     325   
     326    // return success
     327    *cluster = current_cluster;
     328    return 0;
     329
     330}  // end fatfs_get_cluster()
    205331
    206332
    207333
    208334///////////////////////////////////////////////////////////////////////////////////////
    209 // Generic API : the following functions are called by the kernel
     335// Generic API : the following functions are called by the kernel (VFS)
    210336//               and must be defined by all supported file systems.
    211337///////////////////////////////////////////////////////////////////////////////////////
     
    275401
    276402    // check sector size from boot record
    277     uint32_t sector_size = get_record_from_buffer( BPB_BYTSPERSEC , buffer , 1 );
     403    uint32_t sector_size = fatfs_get_record( BPB_BYTSPERSEC , buffer , 1 );
    278404
    279405    nolock_assert( (sector_size == 512) , __FUNCTION__ ,
     
    281407
    282408    // check cluster size from boot record
    283     uint32_t nb_sectors = get_record_from_buffer( BPB_SECPERCLUS , buffer , 1 );
     409    uint32_t nb_sectors = fatfs_get_record( BPB_SECPERCLUS , buffer , 1 );
    284410
    285411    nolock_assert( (nb_sectors == 8) , __FUNCTION__ ,
     
    287413
    288414    // check number of FAT copies from boot record
    289     uint32_t nb_fats = get_record_from_buffer( BPB_NUMFATS , buffer , 1 );
     415    uint32_t nb_fats = fatfs_get_record( BPB_NUMFATS , buffer , 1 );
    290416
    291417    nolock_assert( (nb_fats == 1) , __FUNCTION__ ,
     
    293419
    294420    // get & check number of sectors in FAT from boot record
    295     uint32_t fat_sectors = get_record_from_buffer( BPB_FAT32_FATSZ32 , buffer , 1 );
     421    uint32_t fat_sectors = fatfs_get_record( BPB_FAT32_FATSZ32 , buffer , 1 );
    296422
    297423    nolock_assert( ((fat_sectors & 0xF) == 0) , __FUNCTION__ ,
     
    299425
    300426    // get and check root cluster from boot record
    301     uint32_t root_cluster = get_record_from_buffer( BPB_FAT32_ROOTCLUS , buffer , 1 );
     427    uint32_t root_cluster = fatfs_get_record( BPB_FAT32_ROOTCLUS , buffer , 1 );
    302428
    303429    nolock_assert( (root_cluster == 2) , __FUNCTION__ ,
     
    305431
    306432    // get FAT lba from boot record
    307     uint32_t fat_lba = get_record_from_buffer( BPB_RSVDSECCNT , buffer , 1 );
     433    uint32_t fat_lba = fatfs_get_record( BPB_RSVDSECCNT , buffer , 1 );
    308434
    309435    // release the 512 bytes buffer
     
    353479}
    354480
    355 ////////////////////////////////////////////////
    356 static error_t fatfs_access_page( page_t * page,
    357                                   bool_t   is_read )
     481///////////////////////////////////////
     482error_t fatfs_move_page( page_t * page,
     483                         bool_t   to_mapper )
    358484{
    359485    // get memory buffer base address
     
    388514
    389515    // access device
    390     if( is_read ) error = dev_ioc_read ( buffer , lba , count );
    391     else          error = dev_ioc_write( buffer , lba , count );     
     516    if( to_mapper ) error = dev_ioc_read ( buffer , lba , count );
     517    else            error = dev_ioc_write( buffer , lba , count );     
    392518
    393519    if( error )
     
    401527}
    402528
    403 ////////////////////////////////////////////////
    404 error_t fatfs_write_page( struct page_s * page )
    405 {
    406     bool_t is_read = false;
    407     return fatfs_access_page( page , is_read );
    408 }
    409 
    410 ///////////////////////////////////////////////
    411 error_t fatfs_read_page( struct page_s * page )
    412 {
    413     bool_t is_read = true;
    414     return fatfs_access_page( page , is_read );
    415 }
    416 
     529/////////////////////////////////////////////////////////////////
     530error_t fatfs_inode_load( vfs_inode_t * parent_inode,
     531                          char        * name,
     532                          xptr_t        child_inode_xp )
     533{
     534    // Two embedded loops:
     535    // - scan the parent mapper pages
     536    // - scan the directory entries in each 4 Kbytes page
     537
     538    fatfs_dmsg("\n[INFO] %s : enter for child <%s> in parent inode %l\n",
     539               __FUNCTION__ , name , child_inode_xp );
     540
     541    mapper_t * mapper = parent_inode->mapper;
     542
     543    assert( (mapper != NULL) , __FUNCTION__ , "parent mapper undefined\n");
     544   
     545    char       cname[CONFIG_VFS_MAX_NAME_LENGTH];  // name extracter from each directory entry
     546
     547    char       lfn1[16];         // buffer for one partial cname
     548    char       lfn2[16];         // buffer for one partial cname
     549    char       lfn3[16];         // buffer for one partial cname
     550    page_t   * page;             // pointer on current page descriptor
     551    uint8_t  * base;             // pointer on current page base
     552    uint32_t   offset  = 0;      // byte offset in page
     553    uint32_t   index   = 0;      // page index in mapper
     554    uint32_t   attr;             // directory entry ATTR field
     555    uint32_t   ord;              // directory entry ORD field
     556    uint32_t   seq;              // sequence index
     557    uint32_t   lfn     = 0;      // LFN entries number
     558    uint32_t   size    = 0;      // searched file/dir size (bytes)
     559    uint32_t   cluster = 0;      // searched file/dir cluster index
     560    uint32_t   is_dir  = 0;      // searched file/dir type
     561    uint32_t   dentry;           // directory entry index
     562    int32_t    found   = 0;      // not found (0) / name found (1) / end of dir (-1)
     563
     564    // scan the parent directory mapper
     565    while ( found == 0 )
     566    {
     567        // get one page
     568        page = mapper_get_page( mapper , index );
     569
     570        assert( (page != NULL) , __FUNCTION__ , "bad parent mapper\n");
     571
     572        // get page base
     573        base = ppm_page2vaddr( page );
     574
     575        // scan this page until end of directory, end of page, or name found
     576        while( (offset < 4096) && (found == 0) )
     577        {
     578            attr = fatfs_get_record( DIR_ATTR , base + offset , 0 );   
     579            ord  = fatfs_get_record( LDIR_ORD , base + offset , 0 );   
     580
     581            if (ord == NO_MORE_ENTRY)                 // no more entry => break
     582            {
     583                found = -1;
     584            }
     585            else if ( ord == FREE_ENTRY )             // free entry => skip
     586            {
     587                offset = offset + 32;
     588            }
     589            else if ( attr == ATTR_LONG_NAME_MASK )   // LFN entry => get partial cname
     590            {
     591                seq = ord & 0x3;
     592                lfn = (seq > lfn) ? seq : lfn;   
     593                if      ( seq == 1 ) fatfs_get_name_from_long( base + offset, lfn1 );
     594                else if ( seq == 2 ) fatfs_get_name_from_long( base + offset, lfn2 );
     595                else if ( seq == 3 ) fatfs_get_name_from_long( base + offset, lfn3 );
     596                offset = offset + 32;
     597            }
     598            else                                 // NORMAL entry
     599            {
     600                // build the extracted name
     601                if      ( lfn == 0 )
     602                {
     603                    fatfs_get_name_from_short( base + offset , cname );
     604                }
     605                else if ( lfn == 1 )
     606                {
     607                    strcpy( cname      , lfn1 );
     608                }   
     609                else if ( lfn == 2 )
     610                {
     611                    strcpy( cname      , lfn1 );
     612                    strcpy( cname + 13 , lfn2 );
     613                }
     614                else if ( lfn == 3 )
     615                {
     616                    strcpy( cname      , lfn1 );
     617                    strcpy( cname + 13 , lfn2 );
     618                    strcpy( cname + 26 , lfn3 );
     619                }
     620
     621                // get dentry arguments if extracted cname == searched name
     622                if ( strcmp( name , cname ) == 0 )
     623                {
     624                    cluster = (fatfs_get_record( DIR_FST_CLUS_HI , base + offset , 1 ) << 16) |
     625                              (fatfs_get_record( DIR_FST_CLUS_LO , base + offset , 1 )      ) ;
     626                    dentry  = ((index<<12) + offset)>>5;
     627                    is_dir  = ((attr & ATTR_DIRECTORY) == ATTR_DIRECTORY);
     628                    size    = fatfs_get_record( DIR_FILE_SIZE , base + offset , 1 );
     629                    found   = 1;
     630                }
     631                offset = offset + 32;
     632                lfn    = 0;
     633            }
     634        }  // end loop on directory entries
     635        index++;
     636        offset = 0;
     637    }  // end loop on pages
     638
     639    // analyse the result of scan
     640
     641    if ( found == -1 )  // found end of directory => failure
     642    {
     643        fatfs_dmsg("\n[INFO] %s : child <%s> not found in parent inode %l\n",
     644                   __FUNCTION__ , name , parent_inode_xp );
     645
     646        return ENOENT;
     647    }
     648    else               // found searched child name
     649    {
     650        fatfs_dmsg("\n[INFO] %s : child <%s> found in parent inode %l\n",
     651                   __FUNCTION__ , name , parent_inode_xp );
     652
     653        // get child inode cluster and local pointer
     654        cxy_t         child_cxy = GET_CXY( child_inode_xp );
     655        vfs_inode_t * child_ptr = (vfs_inode_t *)GET_PTR( child_inode_xp );
     656
     657        // update the child inode "type", "size", and "extend" fields
     658        vfs_inode_type_t type = (is_dir) ? INODE_TYPE_DIR : INODE_TYPE_FILE;
     659
     660        hal_remote_sw( XPTR( child_cxy , &child_ptr->type   ) , type );
     661        hal_remote_sw( XPTR( child_cxy , &child_ptr->size   ) , size );
     662        hal_remote_sw( XPTR( child_cxy , &child_ptr->extend ) , cluster );
     663
     664        return 0;
     665    }
     666}  // end fatfs_inode_load()
Note: See TracChangeset for help on using the changeset viewer.