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

📄 ff.c

📁 非常好用的嵌入式系统用的fat文件系统,支持fat12 fat16 fat32
💻 C
📖 第 1 页 / 共 5 页
字号:
        if (wcnt > btw) wcnt = btw;
        memcpy(&fp->buffer[fp->fptr & (S_SIZ - 1)], wbuff, wcnt);
        fp->flag |= FA__DIRTY;
    }

    if (fp->fptr > fp->fsize) fp->fsize = fp->fptr;    /* Update file size if needed */
    fp->flag |= FA__WRITTEN;                        /* Set file changed flag */
    return FR_OK;

fw_error:    /* Abort this file due to an unrecoverable error */
    fp->flag |= FA__ERROR;
    return FR_RW_ERROR;
}




/*-----------------------------------------------------------------------*/
/* Synchronize between File and Disk                                     */
/*-----------------------------------------------------------------------*/

FRESULT f_sync (
    FIL *fp        /* Pointer to the file object */
)
{
    DWORD tim;
    BYTE *dir;
    FRESULT res;
    FATFS *fs = fp->fs;


    res = validate(fs, fp->id);            /* Check validity of the object */
    if (res == FR_OK) {
        if (fp->flag & FA__WRITTEN) {    /* Has the file been written? */
            /* Write back data buffer if needed */
            if (fp->flag & FA__DIRTY) {
                if (disk_write(fs->drive, fp->buffer, fp->curr_sect, 1) != RES_OK)
                    return FR_RW_ERROR;
                fp->flag &= ~FA__DIRTY;
            }
            /* Update the directory entry */
            if (!move_window(fs, fp->dir_sect))
                return FR_RW_ERROR;
            dir = fp->dir_ptr;
            dir[DIR_Attr] |= AM_ARC;                        /* Set archive bit */
            ST_DWORD(&dir[DIR_FileSize], fp->fsize);        /* Update file size */
            ST_WORD(&dir[DIR_FstClusLO], fp->org_clust);    /* Update start cluster */
            ST_WORD(&dir[DIR_FstClusHI], fp->org_clust >> 16);
            tim = get_fattime();                    /* Updated time */
            ST_DWORD(&dir[DIR_WrtTime], tim);
            fp->flag &= ~FA__WRITTEN;
            res = sync(fs);
        }
    }
    return res;
}

#endif /* !_FS_READONLY */




/*-----------------------------------------------------------------------*/
/* Close File                                                            */
/*-----------------------------------------------------------------------*/

FRESULT f_close (
    FIL *fp        /* Pointer to the file object to be closed */
)
{
    FRESULT res;


#if !_FS_READONLY
    res = f_sync(fp);
#else
    res = validate(fp->fs, fp->id);
#endif
    if (res == FR_OK)
        fp->fs = NULL;
    return res;
}




#if _FS_MINIMIZE <= 2
/*-----------------------------------------------------------------------*/
/* Seek File R/W Pointer                                                 */
/*-----------------------------------------------------------------------*/

FRESULT f_lseek (
    FIL *fp,        /* Pointer to the file object */
    DWORD ofs        /* File pointer from top of file */
)
{
    DWORD clust, csize;
    BYTE csect;
    FRESULT res;
    FATFS *fs = fp->fs;


    res = validate(fs, fp->id);            /* Check validity of the object */
    if (res) return res;
    if (fp->flag & FA__ERROR) return FR_RW_ERROR;
#if !_FS_READONLY
    if (fp->flag & FA__DIRTY) {            /* Write-back dirty buffer if needed */
        if (disk_write(fs->drive, fp->buffer, fp->curr_sect, 1) != RES_OK)
            goto fk_error;
        fp->flag &= ~FA__DIRTY;
    }
    if (ofs > fp->fsize && !(fp->flag & FA_WRITE))
#else
    if (ofs > fp->fsize)
#endif
        ofs = fp->fsize;
    fp->fptr = 0; fp->sect_clust = 1;        /* Set file R/W pointer to top of the file */

    /* Move file R/W pointer if needed */
    if (ofs) {
        clust = fp->org_clust;    /* Get start cluster */
#if !_FS_READONLY
        if (!clust) {            /* If the file does not have a cluster chain, create new cluster chain */
            clust = create_chain(fs, 0);
            if (clust == 1) goto fk_error;
            fp->org_clust = clust;
        }
#endif
        if (clust) {            /* If the file has a cluster chain, it can be followed */
            csize = (DWORD)fs->sects_clust * S_SIZ;        /* Cluster size in unit of byte */
            for (;;) {                                    /* Loop to skip leading clusters */
                fp->curr_clust = clust;                    /* Update current cluster */
                if (ofs <= csize) break;
#if !_FS_READONLY
                if (fp->flag & FA_WRITE)                /* Check if in write mode or not */
                    clust = create_chain(fs, clust);    /* Force streached if in write mode */
                else
#endif
                    clust = get_cluster(fs, clust);        /* Only follow cluster chain if not in write mode */
                if (clust == 0) {                        /* Stop if could not follow the cluster chain */
                    ofs = csize; break;
                }
                if (clust == 1 || clust >= fs->max_clust) goto fk_error;
                fp->fptr += csize;                        /* Update R/W pointer */
                ofs -= csize;
            }
            csect = (BYTE)((ofs - 1) / S_SIZ);            /* Sector offset in the cluster */
            fp->curr_sect = clust2sect(fs, clust) + csect;    /* Current sector */
            if ((ofs & (S_SIZ - 1)) &&                    /* Load current sector if needed */
                disk_read(fs->drive, fp->buffer, fp->curr_sect, 1) != RES_OK)
                goto fk_error;
            fp->sect_clust = fs->sects_clust - csect;    /* Left sector counter in the cluster */
            fp->fptr += ofs;                            /* Update file R/W pointer */
        }
    }
#if !_FS_READONLY
    if ((fp->flag & FA_WRITE) && fp->fptr > fp->fsize) {    /* Set updated flag if in write mode */
        fp->fsize = fp->fptr;
        fp->flag |= FA__WRITTEN;
    }
#endif

    return FR_OK;

fk_error:    /* Abort this file due to an unrecoverable error */
    fp->flag |= FA__ERROR;
    return FR_RW_ERROR;
}




#if _FS_MINIMIZE <= 1
/*-----------------------------------------------------------------------*/
/* Create a directroy object                                             */
/*-----------------------------------------------------------------------*/

FRESULT f_opendir (
    DIR *dirobj,        /* Pointer to directory object to create */
    const char *path    /* Pointer to the directory path */
)
{
    BYTE *dir;
    char fn[8+3+1];
    FRESULT res;
    FATFS *fs;


    res = auto_mount(&path, &fs, 0);
    if (res != FR_OK) return res;
    dirobj->fs = fs;

    res = trace_path(dirobj, fn, path, &dir);    /* Trace the directory path */
    if (res == FR_OK) {                        /* Trace completed */
        if (dir != NULL) {                    /* It is not the root dir */
            if (dir[DIR_Attr] & AM_DIR) {        /* The entry is a directory */
                dirobj->clust = ((DWORD)LD_WORD(&dir[DIR_FstClusHI]) << 16) | LD_WORD(&dir[DIR_FstClusLO]);
                dirobj->sect = clust2sect(fs, dirobj->clust);
                dirobj->index = 2;
            } else {                        /* The entry is not a directory */
                res = FR_NO_FILE;
            }
        }
        dirobj->id = fs->id;
    }
    return res;
}




/*-----------------------------------------------------------------------*/
/* Read Directory Entry in Sequense                                      */
/*-----------------------------------------------------------------------*/

FRESULT f_readdir (
    DIR *dirobj,        /* Pointer to the directory object */
    FILINFO *finfo        /* Pointer to file information to return */
)
{
    BYTE *dir, c, res;
    FATFS *fs = dirobj->fs;


    res = validate(fs, dirobj->id);            /* Check validity of the object */
    if (res) return res;

    finfo->fname[0] = 0;
    while (dirobj->sect) {
        if (!move_window(fs, dirobj->sect))
            return FR_RW_ERROR;
        dir = &fs->win[(dirobj->index & ((S_SIZ - 1) >> 5)) * 32];    /* pointer to the directory entry */
        c = *dir;
        if (c == 0) break;                                /* Has it reached to end of dir? */
        if (c != 0xE5 && !(dir[DIR_Attr] & AM_VOL))        /* Is it a valid entry? */
            get_fileinfo(finfo, dir);
        if (!next_dir_entry(dirobj)) dirobj->sect = 0;    /* Next entry */
        if (finfo->fname[0]) break;                        /* Found valid entry */
    }

    return FR_OK;
}




#if _FS_MINIMIZE == 0
/*-----------------------------------------------------------------------*/
/* Get File Status                                                       */
/*-----------------------------------------------------------------------*/

FRESULT f_stat (
    const char *path,    /* Pointer to the file path */
    FILINFO *finfo        /* Pointer to file information to return */
)
{
    BYTE *dir;
    char fn[8+3+1];
    FRESULT res;
    DIR dirobj;
    FATFS *fs;


    res = auto_mount(&path, &fs, 0);
    if (res != FR_OK) return res;
    dirobj.fs = fs;

    res = trace_path(&dirobj, fn, path, &dir);    /* Trace the file path */
    if (res == FR_OK) {                            /* Trace completed */
        if (dir)    /* Found an object */
            get_fileinfo(finfo, dir);
        else        /* It is root dir */
            res = FR_INVALID_NAME;
    }

    return res;
}



#if !_FS_READONLY
/*-----------------------------------------------------------------------*/
/* Get Number of Free Clusters                                           */
/*-----------------------------------------------------------------------*/

FRESULT f_getfree (
    const char *drv,    /* Logical drive number */
    DWORD *nclust,        /* Pointer to the double word to return number of free clusters */
    FATFS **fatfs        /* Pointer to pointer to the file system object to return */
)
{
    DWORD n, clust, sect;
    BYTE fat, f, *p;
    FRESULT res;
    FATFS *fs;


    /* Get drive number */
    res = auto_mount(&drv, &fs, 0);
    if (res != FR_OK) return res;
    *fatfs = fs;

    /* If number of free cluster is valid, return it without cluster scan. */
    if (fs->free_clust <= fs->max_clust - 2) {
        *nclust = fs->free_clust;
        return FR_OK;
    }

    /* Count number of free clusters */
    fat = fs->fs_type;
    n = 0;
    if (fat == FS_FAT12) {
        clust = 2;
        do {
            if ((WORD)get_cluster(fs, clust) == 0) n++;
        } while (++clust < fs->max_clust);
    } else {
        clust = fs->max_clust;
        sect = fs->fatbase;
        f = 0; p = 0;
        do {
            if (!f) {
                if (!move_window(fs, sect++)) return FR_RW_ERROR;
                p = fs->win;
            }
            if (fat == FS_FAT16) {
                if (LD_WORD(p) == 0) n++;
                p += 2; f += 1;
            } else {
                if (LD_DWORD(p) == 0) n++;
                p += 4; f += 2;
            }
        } while (--clust);
    }
    fs->free_clust = n;
#if _USE_FSINFO
    if (fat == FS_FAT32) fs->fsi_flag = 1;
#endif

    *nclust = n;
    return FR_OK;
}

⌨️ 快捷键说明

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