Ignore:
Timestamp:
Jan 11, 2019, 6:35:07 PM (5 years ago)
Author:
alain
Message:

Fix several bugs in vfs.c, fatfs.c, and devfs.c to support
the <.> and <..> directory entries.

File:
1 edited

Legend:

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

    r611 r612  
    13591359}  // end fatfs_remove_dentry
    13601360
    1361 ////////////////////////////////////////////////////////////////
    1362 error_t fatfs_child_init( vfs_inode_t * parent_inode,
     1361/////////////////////////////////////////////////////
     1362error_t fatfs_get_dentry( vfs_inode_t * parent_inode,
    13631363                          char        * name,
    13641364                          xptr_t        child_inode_xp )
     
    13681368    // - scan the directory entries in each 4 Kbytes page
    13691369
    1370 #if DEBUG_FATFS_CHILD_INIT
     1370#if DEBUG_FATFS_GET_DENTRY
    13711371char       parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
    13721372uint32_t   cycle = (uint32_t)hal_get_cycles();
    13731373thread_t * this  = CURRENT_THREAD;
    13741374vfs_inode_get_name( XPTR( local_cxy , parent_inode ) , parent_name );
    1375 if( DEBUG_FATFS_CHILD_INIT < cycle )
     1375if( DEBUG_FATFS_GET_DENTRY < cycle )
    13761376printk("\n[%s]  thread[%x,%x] enter for child <%s> in parent <%s> / cycle %d\n",
    13771377__FUNCTION__, this->process->pid, this->trdid, name , parent_name , cycle );
     
    14201420        base    = (uint8_t *)GET_PTR( base_xp );
    14211421
    1422 #if (DEBUG_FATFS_CHILD_INIT & 0x1)
    1423 if( DEBUG_FATFS_CHILD_INIT < cycle )
    1424 {
    1425     uint32_t * buf = (uint32_t *)base;
    1426     uint32_t line , word;
    1427     printk("\n[%s] First 16 dentries for <%s>\n",
    1428     __FUNCTION__ , parent_name );
    1429     for( line = 0 ; line < 16 ; line++ )
    1430     {
    1431         printk("%X : ", line );
    1432         for( word = 0 ; word < 8 ; word++ ) printk("%X ", buf[(line<<4) + word] );
    1433         printk("\n");
    1434     }
    1435 }
     1422#if (DEBUG_FATFS_GET_DENTRY & 0x1)
     1423if( DEBUG_FATFS_GET_DENTRY < cycle )
     1424mapper_display_page( mapper_xp , page_id , 256 , parent_name );
    14361425#endif
    14371426        // scan this page until end of directory, end of page, or name found
     
    15061495    {
    15071496
    1508 #if DEBUG_FATFS_CHILD_INIT
     1497#if DEBUG_FATFS_GET_DENTRY
    15091498cycle = (uint32_t)hal_get_cycles();
    1510 if( DEBUG_FATFS_CHILD_INIT < cycle )
     1499if( DEBUG_FATFS_GET_DENTRY < cycle )
    15111500printk("\n[%s]  thread[%x,%x] exit / child <%s> not found / cycle %d\n",
    15121501__FUNCTION__, this->process->pid, this->trdid, name, cycle );
     
    15441533    dentry_ptr->extend = (void *)(intptr_t)dentry_id;
    15451534
    1546 #if DEBUG_FATFS_CHILD_INIT
     1535#if DEBUG_FATFS_GET_DENTRY
    15471536cycle = (uint32_t)hal_get_cycles();
    1548 if( DEBUG_FATFS_CHILD_INIT < cycle )
     1537if( DEBUG_FATFS_GET_DENTRY < cycle )
    15491538printk("\n[%s]  thread[%x,%x] exit / child <%s> loaded in <%s> / cycle %d\n",
    15501539__FUNCTION__, this->process->pid, this->trdid, name, parent_name, cycle );
     
    15531542    return 0;
    15541543
    1555 }  // end fatfs_child_init()
     1544}  // end fatfs_get_dentry()
     1545
     1546///////////////////////////////////////////////////////
     1547error_t fatfs_get_user_dir( struct vfs_inode_s * inode,
     1548                            struct dirent      * array,
     1549                            uint32_t             max_dirent,
     1550                            uint32_t             min_dentry,
     1551                            bool_t               detailed,
     1552                            uint32_t           * entries,
     1553                            bool_t             * done )
     1554{
     1555    // Two embedded loops to scan the directory mapper:
     1556    // - scan the parent directory mapper pages starting always from page 0
     1557    // - scan the 32 bytes NORMAL/LFN directory entries in each page
     1558    // Only valid dentries are copied : dentry_id >= min_dentry && dirent_id < dirent_max
     1559
     1560#if DEBUG_FATFS_GET_USER_DIR
     1561char       inode_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1562uint32_t   cycle = (uint32_t)hal_get_cycles();
     1563thread_t * this  = CURRENT_THREAD;
     1564vfs_inode_get_name( XPTR( local_cxy , inode ) , inode_name );
     1565if( DEBUG_FATFS_GET_USER_DIR < cycle )
     1566printk("\n[%s]  thread[%x,%x] enter for inode <%s> / cycle %d\n",
     1567__FUNCTION__, this->process->pid, this->trdid, inode_name , cycle );
     1568#endif
     1569
     1570    mapper_t * mapper    = inode->mapper;
     1571    xptr_t     mapper_xp = XPTR( local_cxy , mapper );
     1572
     1573// check mapper pointer
     1574assert( (mapper != NULL) , "mapper is NULL\n");
     1575   
     1576// TODO handle the detailed flag
     1577assert( (detailed == false), "detailed argument not supported/n");
     1578
     1579    char       cname[CONFIG_VFS_MAX_NAME_LENGTH];  // name extracter from each directory entry
     1580
     1581    char       lfn1[16];           // buffer for one partial cname
     1582    char       lfn2[16];           // buffer for one partial cname
     1583    char       lfn3[16];           // buffer for one partial cname
     1584    xptr_t     page_xp;            // extended pointer on page descriptor
     1585    xptr_t     base_xp;            // extended pointer on page base
     1586    uint8_t  * base;               // local pointer on page base
     1587    uint32_t   attr;               // directory entry ATTR field
     1588    uint32_t   ord;                // directory entry ORD field
     1589    uint32_t   seq;                // sequence index
     1590    uint32_t   lfn       = 0;      // LFN entries number
     1591    uint32_t   offset    = 0;      // byte offset in page
     1592    uint32_t   page_id   = 0;      // page index in mapper
     1593    uint32_t   dentry_id = 0;      // valid (i.e. copied) dentry index in mapper
     1594    uint32_t   dirent_id = 0;      // slot index in dirent array to initialize
     1595    bool_t     end       = false;  // true if end of directory found
     1596
     1597    // loop on mapper pages
     1598    while ( (end == false) && (dirent_id < max_dirent) )
     1599    {
     1600        // get one page from mapper
     1601        page_xp = mapper_remote_get_page( mapper_xp , page_id );
     1602
     1603        if( page_xp == XPTR_NULL) return -1;
     1604
     1605        // get page base
     1606        base_xp = ppm_page2base( page_xp );
     1607        base    = (uint8_t *)GET_PTR( base_xp );
     1608
     1609#if (DEBUG_FATFS_GET_USER_DIR & 0x1)
     1610if( DEBUG_FATFS_GET_USER_DIR < cycle )
     1611mapper_display_page( mapper_xp , page_id , 256 , inode_name );
     1612#endif
     1613        // loop on NORMAL/LFN (32 bytes) directory entries in this page
     1614        while( (end == false) && (offset < 4096) )
     1615        {
     1616            // compute condition to copy one dentry to dirent array
     1617            bool_t valid = (dentry_id >= min_dentry) && (dirent_id <  max_dirent );
     1618
     1619            attr = fatfs_get_record( DIR_ATTR , base + offset , 0 );   
     1620            ord  = fatfs_get_record( LDIR_ORD , base + offset , 0 );   
     1621
     1622            if (ord == NO_MORE_ENTRY)                 // no more entry => break
     1623            {
     1624                end = true;
     1625            }
     1626            else if ( ord == FREE_ENTRY )             // free entry => skip
     1627            {
     1628                offset = offset + 32;
     1629            }
     1630            else if ( attr == ATTR_LONG_NAME_MASK )   // LFN entry
     1631            {
     1632                if( valid )
     1633                {
     1634                    // get partial cname
     1635                    seq = ord & 0x3;
     1636                    lfn = (seq > lfn) ? seq : lfn;   
     1637                    if      ( seq == 1 ) fatfs_get_name_from_long( base + offset, lfn1 );
     1638                    else if ( seq == 2 ) fatfs_get_name_from_long( base + offset, lfn2 );
     1639                    else if ( seq == 3 ) fatfs_get_name_from_long( base + offset, lfn3 );
     1640                }
     1641                offset = offset + 32;
     1642            }
     1643            else                                     // NORMAL entry
     1644            {
     1645                // increment dentry_id
     1646                dentry_id++;
     1647
     1648                if( valid )
     1649                {
     1650                    // build the complete cname
     1651                    if      ( lfn == 0 )
     1652                    {
     1653                        fatfs_get_name_from_short( base + offset , cname );
     1654                    }
     1655                    else if ( lfn == 1 )
     1656                    {
     1657                        strcpy( cname      , lfn1 );
     1658                    }   
     1659                    else if ( lfn == 2 )
     1660                    {
     1661                        strcpy( cname      , lfn1 );
     1662                        strcpy( cname + 13 , lfn2 );
     1663                    }
     1664                    else if ( lfn == 3 )
     1665                    {
     1666                        strcpy( cname      , lfn1 );
     1667                        strcpy( cname + 13 , lfn2 );
     1668                        strcpy( cname + 26 , lfn3 );
     1669                    }
     1670                   
     1671                    // copy cname into dirent array
     1672                    strcpy( array[dirent_id].d_name , cname );
     1673
     1674                    // increment dirent_id
     1675                    dirent_id++;
     1676                }
     1677                offset = offset + 32;
     1678                lfn    = 0;
     1679            }
     1680        }  // end loop on directory entries in page
     1681
     1682        page_id++;
     1683        offset = 0;
     1684
     1685    }  // end loop on pages
     1686
     1687    // return result of scan
     1688    *done    = end;
     1689    *entries = dirent_id;
     1690
     1691#if DEBUG_FATFS_GET_USER_DIR
     1692cycle = (uint32_t)hal_get_cycles();
     1693if( DEBUG_FATFS_GET_USER_DIR < cycle )
     1694printk("\n[%s]  thread[%x,%x] exit for inode <%s> / %d entries / cycle %d\n",
     1695__FUNCTION__, this->process->pid, this->trdid, inode_name, entries, cycle );
     1696#endif
     1697
     1698    return 0;
     1699
     1700}  // end fatfs_get_user_dir()
    15561701
    15571702///////////////////////////////////////////////
Note: See TracChangeset for help on using the changeset viewer.