⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fatfs_supp.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    GET_WORD(data,  fde->crt_date,    0x10);
    GET_WORD(data,  fde->acc_date,    0x12);
    GET_WORD(data,  fde->cluster_HI,  0x14);
    GET_WORD(data,  fde->wrt_time,    0x16);
    GET_WORD(data,  fde->wrt_date,    0x18);
    GET_WORD(data,  fde->cluster,     0x1A);
    GET_DWORD(data, fde->size,        0x1C);

     // Zero terminate strings
    fde->name[8] = '\0';    
    fde->ext[3]  = '\0';    
  
    // Store position
    fde->pos = *dpos;
       
#if TDE    
    print_dentry(fde);
#endif

    return ENOERR;
}

// -------------------------------------------------------------------------
// write_dentry()
// Writes dir entry to disk. 
// If cluster is 0 writes to root dir.
 
static int
write_dentry(fatfs_disk_t     *disk,
             fatfs_data_pos_t *dpos, 
             fat_dir_entry_t  *fde)
{
    unsigned char data[DENTRY_SIZE];
    cyg_uint32 apos;
    int len, err;
    
    // Check if we are writting to the root directory
    if (0 == dpos->cluster)
        apos = disk->fat_root_dir_pos + dpos->cluster_pos;
    else
        apos = get_data_disk_apos(disk, dpos->cluster, dpos->cluster_pos);    
 
    CYG_TRACE3(TDE, "cluster=%d pos=%d apos=%d",
                    dpos->cluster, dpos->cluster_pos, apos); 

    SET_BYTES(data, fde->name,     8, 0x00);
    SET_BYTES(data, fde->ext,      3, 0x08);
    SET_BYTE(data,  fde->attr,        0x0B);
    SET_BYTE(data,  fde->nt_reserved, 0x0C);
    SET_BYTE(data,  fde->crt_sec_100, 0x0D);
    SET_WORD(data,  fde->crt_time,    0x0E);
    SET_WORD(data,  fde->crt_date,    0x10);
    SET_WORD(data,  fde->acc_date,    0x12);
    SET_WORD(data,  fde->cluster_HI,  0x14);
    SET_WORD(data,  fde->wrt_time,    0x16);
    SET_WORD(data,  fde->wrt_date,    0x18);
    SET_WORD(data,  fde->cluster,     0x1A);
    SET_DWORD(data, fde->size,        0x1C);
   
    len = DENTRY_SIZE;
    err = cyg_blib_write(&disk->blib, (void*)data, &len, 0, apos);
    if (err != ENOERR)
        return err;

#if TDE    
    print_dentry(fde);
#endif

    return ENOERR;
}

// -------------------------------------------------------------------------
// dentry_set_deleted()
// Sets the dentry filename first char to 0xE5 (ie deleted). 
 
static __inline__ void 
dentry_set_deleted(fatfs_disk_t *disk, fat_dir_entry_t *dentry)
{
    dentry->name[0] = 0xE5;
}

// -------------------------------------------------------------------------
// get_dentry_filename()
// Gets the filename from given dir entry. 
 
static void 
get_dentry_filename(fat_dir_entry_t *fde, char *name)
{
    int i = 0;
    char *cptr  = fde->name;
    char *cname = name;

    while (*cptr != ' ' && i < 8)
    {
        *cname++ = *cptr++; i++;
    }
    cptr = fde->ext;

    if (*cptr != ' ')
    {
        *cname++ = '.'; i = 0;
        while (*cptr != ' ' && i < 3)
        {
            *cname++ = *cptr++; i++;
        }
    }
    *cname = '\0';

    CYG_TRACE3(TDE, "dos_name='%s' dos_ext='%s' filename='%s'",
                    fde->name, fde->ext, name);
}

// -------------------------------------------------------------------------
// set_dentry_filename()
// Sets the filename to given dir entry. 
 
static void 
set_dentry_filename(fat_dir_entry_t *fde, const char *name, int namelen)
{
    int i, nidx;
    const char *cname;
    char *cptr;

    // Special case check
    if (name[0] == '.')
    {
        if (name[1] == '\0')
        {
            strcpy(fde->name, ".       ");
            strcpy(fde->ext,  "   ");
            return;
        }
        else if (name[1] == '.' && name[2] == '\0')
        {
            strcpy(fde->name, "..      ");
            strcpy(fde->ext,  "   ");
            return;
        }
    }
    
    if (0 == namelen)
        namelen = 9999;
    
    nidx  = 0;
    cname = name;
    cptr  = fde->name;
    for (i = 0; i < 8; i++)
    {
        if (*cname != '.' && *cname != '\0' && nidx++ < namelen)
            *cptr++ = toupper(*cname++);
        else
            *cptr++ = ' ';
    }
    *cptr = '\0';
    
    while (*cname != '.' && *cname != '\0' && nidx++ < namelen)
        cname++;
   
    if (*cname == '.' && nidx++ < namelen) 
        cname++;
    
    cptr = fde->ext;
    for (i = 0; i < 3; i++)
    {
        if (*cname != '.' && *cname != '\0' && nidx++ < namelen)
            *cptr++ = toupper(*cname++);
        else
            *cptr++ = ' ';
    }
    *cptr = '\0';

    CYG_TRACE4(TDE, "filename='%s' namelen=%d dos_name='%s' dos_ext='%s'", 
                    name, namelen, fde->name, fde->ext);
}

// -------------------------------------------------------------------------
// get_next_dentry()
// Gets next dir entry searching from given position to the end.
// Position is expected in DENTRY_SIZE units.
// If EEOF is returned there are no more extries in given dir.
 
static int
get_next_dentry(fatfs_disk_t    *disk,
                fatfs_node_t    *dir,
                cyg_uint32      *pos,
                fat_dir_entry_t *dentry)
{
    fatfs_data_pos_t dpos;
    cyg_uint32 off;
    int err = ENOERR;

    // Calculate dentry offset
    off = *pos * DENTRY_SIZE;
    
    CYG_TRACE4(TDE, "pos=%d off=%d dir=%p cluster=%d",
                    off, *pos, dir, dir->cluster);

    // Root dir check
    if (0 == dir->cluster)
    {
        dpos.cluster      = 0;
        dpos.cluster_snum = 0;
        dpos.cluster_pos  = off;
    }
    else
    {
        err = get_data_position_from_off(disk, dir->cluster, 
            off, &dpos, &dir->tcache, false);
        if (err != ENOERR)
            return err;
    }

    while (true)
    {
        // Root dir check
        if (0 != dir->cluster) 
        {
            // Change cluster if needed
            if (!is_pos_inside_cluster(disk, dpos.cluster_pos))
                err = get_next_cluster(disk, &dpos, &dir->tcache, CO_NONE);
        }
        else
        {
            if (*pos >= disk->fat_root_dir_nents)
                err = EEOF;
        }

        if (err != ENOERR)
            break;

        err = read_dentry(disk, &dpos, dentry);
        if (err != ENOERR)
            return err;

        if (DENTRY_IS_ZERO(dentry))
        {
            // If we get a ZERO dir entry, we assume that
            // there are no more entries in current dir
            CYG_TRACE0(TDE, "ZERO dentry"); 
            err = EEOF;
            break;
        }
        else if (!DENTRY_IS_DELETED(dentry))
        {
            // Dir entry found
            CYG_TRACE3(TDE, "dentry_pos=%d cluster=%d pos=%d",
                            *pos, dpos.cluster, dpos.cluster_pos);
            break;
        }

        // Increment offset and position
        dpos.cluster_pos += DENTRY_SIZE;
        (*pos)++;
    }

    if (EEOF == err) CYG_TRACE0(TDE, "end of dir");
            
    // EEOF could be returned if there are no more entries in this
    // dir - this should be cought by the calling function 
    return err;
}

// -------------------------------------------------------------------------
// get_free_dentry()
// Gets free dir entry slot searching from given position.
// If an deleated entry is found, its clusters are freed and the
// entry is reused. 
// The directory is extended if needed.

static int
get_free_dentry(fatfs_disk_t     *disk, 
                fatfs_data_pos_t *dpos,
                fatfs_tcache_t   *tcache)
{
    fat_dir_entry_t  dentry;
    fatfs_data_pos_t cdpos;
    int err = ENOERR;
    
    CYG_TRACE3(TDE, "cluster=%d cluster_snum=%d cluster_pos=%d", 
                    dpos->cluster, dpos->cluster_snum, dpos->cluster_pos);
    cdpos = *dpos;

    while (true)
    {
        // Root dir check
        if (0 != cdpos.cluster) 
        {
            // Change cluster if needed
            if (!is_pos_inside_cluster(disk, cdpos.cluster_pos))
                err = get_next_cluster(disk, &cdpos, tcache, 
                                       CO_EXTEND | CO_ERASE_NEW);
        }
        else
        {
            if (cdpos.cluster_pos >= disk->fat_root_dir_size)
                err = ENOSPC;
        }

        if (err != ENOERR)
            return err;

        err = read_dentry(disk, &cdpos, &dentry);
        if (err != ENOERR)
            return err;

        if (DENTRY_IS_DELETED(&dentry))
        {
            CYG_TRACE3(TDE, "deleted dentry at cluster=%d cluster_snum=%d "
                            "cluster_pos=%d", cdpos.cluster, cdpos.cluster_snum,
                            cdpos.cluster_pos);

            // Retrun found dentry position
            *dpos = cdpos;
            return ENOERR;
        }
        else if (DENTRY_IS_ZERO(&dentry))
        {
            CYG_TRACE3(TDE, "zero dentry at cluster=%d cluster_snum=%d "
                            "cluster_pos=%d", cdpos.cluster, cdpos.cluster_snum,
                            cdpos.cluster_pos);

            // Retrun found dentry position
            *dpos = cdpos;
            return ENOERR;  
        }
       
        // Increment current position
        cdpos.cluster_pos += DENTRY_SIZE;
    }
}
 
// -------------------------------------------------------------------------
// dentry_to_node()
// Converts FAT dir entry to node. 
 
static void
dentry_to_node(fat_dir_entry_t *dentry, 
               fatfs_node_t    *node)
{
    get_dentry_filename(dentry, node->filename);

    if (DENTRY_IS_DIR(dentry))
        node->mode = __stat_mode_DIR;
    else
        node->mode = __stat_mode_REG;
    
    date_dos2unix(dentry->crt_time, dentry->crt_date, &node->ctime);
    date_dos2unix(0,                dentry->acc_date, &node->atime);
    date_dos2unix(dentry->wrt_time, dentry->wrt_date, &node->mtime);
    
    node->size       = dentry->size;
    node->priv_data  = dentry->nt_reserved;
    node->cluster    = dentry->cluster;
    node->dentry_pos = dentry->pos;
}

// -------------------------------------------------------------------------
// node_to_dentry()
// Converts node to FAT dir entry. 
 
static void
node_to_dentry(fatfs_node_t *node, fat_dir_entry_t *dentry)
{
    set_dentry_filename(dentry, node->filename, 0);

    if (node->mode == __stat_mode_DIR)
        dentry->attr = DENTRY_ATTR_DIR;
    else
        dentry->attr = DENTRY_ATTR_ARCHIVE;
        
    date_unix2dos(node->ctime, &dentry->crt_time, &dentry->crt_date);
    date_unix2dos(node->atime, NULL,              &dentry->acc_date);
    date_unix2dos(node->mtime, &dentry->wrt_time, &dentry->wrt_date);
    
    dentry->crt_sec_100 = 0; //FIXME
    dentry->size        = node->size;
    dentry->nt_reserved = node->priv_data;
    dentry->cluster     = node->cluster;
    dentry->cluster_HI  = 0;
    dentry->pos         = node->dentry_pos;
}

//==========================================================================
// FAT data functions 

// -------------------------------------------------------------------------
// read_data()
// Reads data from given position. 
 
static int
read_data(fatfs_disk_t     *disk,
          void             *data,
          cyg_uint32       *len,
          fatfs_data_pos_t *dpos,
          fatfs_tcache_t   *tcache)
{
    unsigned char *buf;
    cyg_uint32 apos;
    cyg_uint32 size;
    int err;

    // Initialize variables and get the absolute starting pos on disk
    buf   = (unsigned char *)data;
    size  = *len;
    apos  = get_data_disk_apos(disk, dpos->cluster, dpos->cluster_pos);
    err   = ENOERR;
  
    CYG_TRACE5(TDO, "len=%d cluster=%d cluster_pos=%d "
                    "cluster_snum=%d apos=%d", *len, dpos->cluster, 
                    dpos->cluster_pos, dpos->cluster_snum, apos);

    while (size > 0)
    {
        cyg_uint32 csize;

        // Check if we are still inside current cluster
        if (!is_pos_inside_cluster(disk, dpos->cluster_pos))
        {
            // Get next cluster of file and adjust absolute disk position 
            err = get_next_cluster(disk, dpos, tcache, CO_NONE);
            if (err != ENOERR)
                goto out;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -