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

📄 fatfs_supp.c

📁 嵌入式FAT文件系统
💻 C
📖 第 1 页 / 共 5 页
字号:
} 

// -------------------------------------------------------------------------
// free_cluster_chain()
// Marks all clusters FREE from given cluster to the last cluster in chain.

static int
free_cluster_chain(fatfs_disk_t *disk, cyg_uint32 start_cluster)
{
    cyg_uint32 c, next_c, tentry;
    bool       last;
    int        err;

    CYG_TRACE1(TCL, "start cluster=%d", start_cluster);

    c = next_c = start_cluster;
    last = false;
    while (!last)
    {
        err = read_tentry(disk, c, &tentry);
        if (err != ENOERR)
            return err;

        switch (get_tentry_type(disk, tentry))
        {
            case TENTRY_LAST:
                // Last cluster in chain
                last = true;
                break;
            case TENTRY_REGULAR:
                // Get next cluster in chain
                next_c = get_tentry_next_cluster(disk, tentry);
                break;
            default:
                CYG_TRACE2(TCL, "!!! inconsistant FAT tentry=%x c=%d", 
                                tentry, c);
                return EIO;
        }

        // Set the current tentry to FREE 
        set_tentry_type(disk, &tentry, TENTRY_FREE);
        err = write_tentry(disk, c, &tentry);
        if (err != ENOERR)
            return err;

        // Next cluster in chain
        c = next_c; 
    }

    CYG_TRACE1(TCL, "last cluster=%d", c);
    
    return ENOERR;
}

//==========================================================================
// FAT dir entry functions 

// -------------------------------------------------------------------------
// print_raw_dentry()
// Prints FAT directory entry. 

#if TDE
static void
print_raw_dentry(fat_raw_dir_entry_t* dentry)
{
    if (DENTRY_IS_DELETED(dentry))
        diag_printf("FAT: FDE name:    '?%.7s'\n", &dentry->name[1]);
    else    
        diag_printf("FAT: FDE name:    '%.8s'\n", dentry->name);
    diag_printf("FAT: FDE ext:     '%.3s'\n", dentry->ext);
    diag_printf("FAT: FDE attr:     %c%c%c%c%c%c\n", 
                (DENTRY_IS_RDONLY(dentry)  ? 'R' : '-'),
                (DENTRY_IS_HIDDEN(dentry)  ? 'H' : '-'),
                (DENTRY_IS_SYSTEM(dentry)  ? 'S' : '-'),
                (DENTRY_IS_VOLUME(dentry)  ? 'V' : '-'),
                (DENTRY_IS_DIR(dentry)     ? 'D' : '-'),
                (DENTRY_IS_ARCHIVE(dentry) ? 'A' : '-'));
    diag_printf("FAT: FDE crt time: %u\n", dentry->crt_time);
    diag_printf("FAT: FDE crt date: %u\n", dentry->crt_date);
    diag_printf("FAT: FDE acc date: %u\n", dentry->acc_date);
    diag_printf("FAT: FDE wrt time: %u\n", dentry->wrt_time);
    diag_printf("FAT: FDE wrt date: %u\n", dentry->wrt_date);
    diag_printf("FAT: FDE cluster:  %u\n", (dentry->cluster_HI << 16) | dentry->cluster);
    diag_printf("FAT: FDE size:     %u\n", dentry->size);
}
#endif // TDE

// -------------------------------------------------------------------------
// read_raw_dentry()
// Reads dir entry from disk.
 
static int
read_raw_dentry(fatfs_disk_t        *disk,
                fatfs_data_pos_t    *pos, 
                fat_raw_short_dir_entry_t *dentry)
{
    cyg_uint8  data[DENTRY_SIZE];
    cyg_uint32 len;
    int err;

    CYG_TRACE3(TDE, "cluster=%d snum=%d pos=%d",
               pos->cluster, pos->cluster_snum, pos->cluster_pos); 
   
    len = DENTRY_SIZE;

    // Check if we are reading the FAT12/16 root directory
    if (0 == pos->cluster)
        err = disk_read(disk, (void*)data, &len,  
                        disk->fat_root_dir_pos + pos->cluster_pos);
    else
        err = disk_cluster_read(disk, (void*)data, &len, 
                                pos->cluster, pos->cluster_pos);
    if (err != ENOERR)
        return err;

    GET_BYTES(data, dentry->name,     8, 0x00);
    GET_BYTES(data, dentry->ext,      3, 0x08);
    GET_BYTE(data,  dentry->attr,        0x0B);
    GET_BYTE(data,  dentry->nt_reserved, 0x0C);
    GET_BYTE(data,  dentry->crt_sec_100, 0x0D);
    GET_WORD(data,  dentry->crt_time,    0x0E);
    GET_WORD(data,  dentry->crt_date,    0x10);
    GET_WORD(data,  dentry->acc_date,    0x12);
    GET_WORD(data,  dentry->cluster_HI,  0x14);
    GET_WORD(data,  dentry->wrt_time,    0x16);
    GET_WORD(data,  dentry->wrt_date,    0x18);
    GET_WORD(data,  dentry->cluster,     0x1A);
    GET_DWORD(data, dentry->size,        0x1C);

     // Zero terminate strings
    dentry->name[8] = '\0';    
    dentry->ext[3]  = '\0';    
  
#if TDE    
    print_raw_dentry(dentry);
#endif

    return ENOERR;
}


// -------------------------------------------------------------------------
// write_raw_dentry()
// Writes raw dir entry to disk. 
 
static int
write_raw_dentry(fatfs_disk_t        *disk,
                 fatfs_data_pos_t    *pos, 
                 fat_raw_short_dir_entry_t *dentry)
{
    cyg_uint8  data[DENTRY_SIZE];
    cyg_uint32 len;
    int err;

    CYG_TRACE3(TDE, "cluster=%d snum=%d pos=%d",
               pos->cluster, pos->cluster_snum, pos->cluster_pos); 
   
    SET_BYTES(data, dentry->name,     8, 0x00);
    SET_BYTES(data, dentry->ext,      3, 0x08);
    SET_BYTE(data,  dentry->attr,        0x0B);
    SET_BYTE(data,  dentry->nt_reserved, 0x0C);
    SET_BYTE(data,  dentry->crt_sec_100, 0x0D);
    SET_WORD(data,  dentry->crt_time,    0x0E);
    SET_WORD(data,  dentry->crt_date,    0x10);
    SET_WORD(data,  dentry->acc_date,    0x12);
    SET_WORD(data,  dentry->cluster_HI,  0x14);
    SET_WORD(data,  dentry->wrt_time,    0x16);
    SET_WORD(data,  dentry->wrt_date,    0x18);
    SET_WORD(data,  dentry->cluster,     0x1A);
    SET_DWORD(data, dentry->size,        0x1C);
   
    len = DENTRY_SIZE;

    // Check if we are writting to the FAT12/16 root directory
    if (0 == pos->cluster)
        err = disk_write(disk, (void*)data, &len, 
                         disk->fat_root_dir_pos + pos->cluster_pos);
    else
        err = disk_cluster_write(disk, (void*)data, &len,
                                 pos->cluster, pos->cluster_pos); 
    if (err != ENOERR)
        return err;

#if TDE    
    print_raw_dentry(dentry);
#endif

    return ENOERR;
}
static int
write_raw_dentry_long_name(fatfs_disk_t        *disk,
                 fatfs_data_pos_t    *pos, 
                 fat_raw_long_dir_entry_t *ldentry)
{
    cyg_uint8  data[DENTRY_SIZE];
    cyg_uint32 len;
    int err;

    CYG_TRACE3(TDE, "cluster=%d snum=%d pos=%d",
               pos->cluster, pos->cluster_snum, pos->cluster_pos); 
   
    SET_BYTE(data, ldentry->LDIR_Ord,0x00);
    SET_BYTES(data, ldentry->LDIR_Name1, 10, 0x01);
    SET_BYTE(data,  ldentry->attr,        11);
    SET_BYTE(data,  ldentry->LDIR_Type, 12);
    SET_BYTE(data,  ldentry->LDIR_Chksum, 13);
    SET_BYTES(data,  ldentry->LDIR_Name2,12,14);
    SET_WORD(data,  ldentry->LDIR_FstClusLO, 26);
    SET_BYTES(data,  ldentry->LDIR_Name3,4,28);
   
    len = DENTRY_SIZE;

    // Check if we are writting to the FAT12/16 root directory
    if (0 == pos->cluster)
        err = disk_write(disk, (void*)data, &len, 
                         disk->fat_root_dir_pos + pos->cluster_pos);
    else
        err = disk_cluster_write(disk, (void*)data, &len,
                                 pos->cluster, pos->cluster_pos); 
    if (err != ENOERR)
        return err;

#if TDE    
    print_raw_dentry(ldentry);
#endif

    return ENOERR;
}

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

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

    while (*cptr != ' ' && i < 8)
    {
        *cname++ = *cptr++; i++;
    }
    cptr = dentry->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'",
                    dentry->name, dentry->ext, name);
}

// -------------------------------------------------------------------------
// set_raw_dentry_filename()
// Sets the filename of given dir entry. 
 
static void 
set_raw_dentry_filename(fat_raw_short_dir_entry_t *dentry, 
                        const char          *name, 
                        int                  namelen)
{
    int         i, nidx;
    const char *cname;
    char       *cptr;

    // Special case check
    if ('.' == name[0])
    {
        if ('\0' == name[1])
        {
            strcpy(dentry->name, ".       ");
            strcpy(dentry->ext,  "   ");
            return;
        }
        else if ('.' == name[1] && '\0' == name[2])
        {
            strcpy(dentry->name, "..      ");
            strcpy(dentry->ext,  "   ");
            return;
        }
    }
    
    if (0 == namelen)
        namelen = 9999;
    
    nidx  = 0;
    cname = name;
    cptr  = dentry->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 = dentry->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, dentry->name, dentry->ext);
}

// -------------------------------------------------------------------------
// read_next_raw_dentry()
// Gets next dir entry searching from given position to the end.
// If EEOF is returned there are no more entries in given dir.
 
static int
read_next_raw_dentry(fatfs_disk_t        *disk,
                     fatfs_data_pos_t    *pos,
                     fat_raw_short_dir_entry_t *dentry,int flow)
{
    int err = ENOERR;

    // If we are reading the root dir on FAT32 we have
    // to correct the position to the root dir cluster
    if (FATFS_FAT32 == disk->fat_type && 0 == pos->cluster)
        pos->cluster = disk->fat_root_dir_cluster;
        
    while (true)
    {
        // FAT12/16 root dir check
        if (0 == pos->cluster) 
        {
            if (pos->cluster_pos >= disk->fat_root_dir_size)
                err = EEOF;
        }
        else
        {
            // Change cluster if needed
            if (pos->cluster_pos >= disk->cluster_size)
                err = get_next_cluster(disk, pos, CO_NONE);
        }

        if (err != ENOERR)
            break;

        err = read_raw_dentry(disk, pos, 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, "end of dir"); 
            err = EEOF;
            break;
        }
        else if (!DENTRY_IS_DELETED(dentry))
        {
            // Dir entry found
            CYG_TRACE3(TDE, "found new dentry at cluster=%d snum=%d pos=%d",
                            pos->cluster, pos->cluster_snum, pos->cluster_pos);
            break;
        }
        if(flow!=0)
        {
		return EEOF;
	 }
        pos->cluster_pos += DENTRY_SIZE;
    }

    // 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_raw_dentry()
// Gets free dir entry slot searching from given position extending the
// directory if needed. If an deleated entry is found it is reused.

static int
get_free_raw_dentry(fatfs_disk_t     *disk, 
                    fatfs_data_pos_t *pos,int len)
{
    fat_raw_short_dir_entry_t raw_dentry;
    fatfs_data_pos_t    cpos,cpos1;
    int                 err = ENOERR;
    int namelen=len;
    cpos = *pos;
 
    // If we are reading the root dir on FAT32 we have
    // to correct the position to the root dir cluster
    if (FATFS_FAT32 == disk->fat_type && 0 == cpos.cluster)

⌨️ 快捷键说明

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