fatfs_supp.c

来自「eCos操作系统源码」· C语言 代码 · 共 2,180 行 · 第 1/5 页

C
2,180
字号
    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 intget_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 intget_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 voiddentry_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 voidnode_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 intread_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;            apos = get_data_disk_apos(disk, dpos->cluster, dpos->cluster_pos);        }                // Adjust the data chunk size to be read to the cluster boundary        if (size > (disk->cluster_size - dpos->cluster_pos))            csize = disk->cluster_size - dpos->cluster_pos;        else            csize = size;        CYG_TRACE5(TDO, "-- len=%d cluster=%d cluster_pos=%d "                        "cluster_snum=%d apos=%d", csize, dpos->cluster,                        dpos->cluster_pos, dpos->cluster_snum, apos);        // Read data chunk         err = cyg_blib_read(&disk->blib, (void*)buf, &csize, 0, apos);        if (err != ENOERR)            goto out;        // Adjust running variables        buf               += csize;        dpos->cluster_pos += csize;        apos              += csize;        size              -= csize;        }    out:    *len -= size;    CYG_TRACE1(TDO, "total len=%d", *len);    return err;}// -------------------------------------------------------------------------// write_data()// Writes data to given position.  static intwrite_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;  

⌨️ 快捷键说明

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