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

📄 ff.c

📁 非常好用的嵌入式系统用的fat文件系统,支持fat12 fat16 fat32
💻 C
📖 第 1 页 / 共 5 页
字号:



/*-----------------------------------------------------------------------*/
/* Delete a File or a Directory                                          */
/*-----------------------------------------------------------------------*/

FRESULT f_unlink (
    const char *path            /* Pointer to the file or directory path */
)
{
    BYTE *dir, *sdir;
    DWORD dclust, dsect;
    char fn[8+3+1];
    FRESULT res;
    DIR dirobj;
    FATFS *fs;


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

    res = trace_path(&dirobj, fn, path, &dir);    /* Trace the file path */
    if (res != FR_OK) return res;                /* Trace failed */
    if (dir == NULL) return FR_INVALID_NAME;    /* It is the root directory */
    if (dir[DIR_Attr] & AM_RDO) return FR_DENIED;    /* It is a R/O object */
    dsect = fs->winsect;
    dclust = ((DWORD)LD_WORD(&dir[DIR_FstClusHI]) << 16) | LD_WORD(&dir[DIR_FstClusLO]);

    if (dir[DIR_Attr] & AM_DIR) {                /* It is a sub-directory */
        dirobj.clust = dclust;                    /* Check if the sub-dir is empty or not */
        dirobj.sect = clust2sect(fs, dclust);
        dirobj.index = 2;
        do {
            if (!move_window(fs, dirobj.sect)) return FR_RW_ERROR;
            sdir = &fs->win[(dirobj.index & ((S_SIZ - 1) >> 5)) * 32];
            if (sdir[DIR_Name] == 0) break;
            if (sdir[DIR_Name] != 0xE5 && !(sdir[DIR_Attr] & AM_VOL))
                return FR_DENIED;    /* The directory is not empty */
        } while (next_dir_entry(&dirobj));
    }

    if (!move_window(fs, dsect)) return FR_RW_ERROR;    /* Mark the directory entry 'deleted' */
    dir[DIR_Name] = 0xE5;
    fs->winflag = 1;
    if (!remove_chain(fs, dclust)) return FR_RW_ERROR;    /* Remove the cluster chain */

    return sync(fs);
}




/*-----------------------------------------------------------------------*/
/* Create a Directory                                                    */
/*-----------------------------------------------------------------------*/

FRESULT f_mkdir (
    const char *path        /* Pointer to the directory path */
)
{
    BYTE *dir, *fw, n;
    char fn[8+3+1];
    DWORD sect, dsect, dclust, pclust, tim;
    FRESULT res;
    DIR dirobj;
    FATFS *fs;


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

    res = trace_path(&dirobj, fn, path, &dir);    /* Trace the file path */
    if (res == FR_OK) return FR_EXIST;            /* Any file or directory is already existing */
    if (res != FR_NO_FILE) return res;

    res = reserve_direntry(&dirobj, &dir);         /* Reserve a directory entry */
    if (res != FR_OK) return res;
    sect = fs->winsect;
    dclust = create_chain(fs, 0);                /* Allocate a cluster for new directory table */
    if (dclust == 1) return FR_RW_ERROR;
    dsect = clust2sect(fs, dclust);
    if (!dsect) return FR_DENIED;
    if (!move_window(fs, dsect)) return FR_RW_ERROR;

    fw = fs->win;
    memset(fw, 0, S_SIZ);                        /* Clear the new directory table */
    for (n = 1; n < fs->sects_clust; n++) {
        if (disk_write(fs->drive, fw, ++dsect, 1) != RES_OK)
            return FR_RW_ERROR;
    }
    memset(&fw[DIR_Name], ' ', 8+3);            /* Create "." entry */
    fw[DIR_Name] = '.';
    fw[DIR_Attr] = AM_DIR;
    tim = get_fattime();
    ST_DWORD(&fw[DIR_WrtTime], tim);
    memcpy(&fw[32], &fw[0], 32); fw[33] = '.';    /* Create ".." entry */
    pclust = dirobj.sclust;
#if _FAT32
    ST_WORD(&fw[   DIR_FstClusHI], dclust >> 16);
    if (fs->fs_type == FS_FAT32 && pclust == fs->dirbase) pclust = 0;
    ST_WORD(&fw[32+DIR_FstClusHI], pclust >> 16);
#endif
    ST_WORD(&fw[   DIR_FstClusLO], dclust);
    ST_WORD(&fw[32+DIR_FstClusLO], pclust);
    fs->winflag = 1;

    if (!move_window(fs, sect)) return FR_RW_ERROR;
    memset(&dir[0], 0, 32);                        /* Initialize the new entry */
    memcpy(&dir[DIR_Name], fn, 8+3);            /* Name */
    dir[DIR_NTres] = fn[11];
    dir[DIR_Attr] = AM_DIR;                        /* Attribute */
    ST_DWORD(&dir[DIR_WrtTime], tim);            /* Crated time */
    ST_WORD(&dir[DIR_FstClusLO], dclust);        /* Table start cluster */
    ST_WORD(&dir[DIR_FstClusHI], dclust >> 16);

    return sync(fs);
}




/*-----------------------------------------------------------------------*/
/* Change File Attribute                                                 */
/*-----------------------------------------------------------------------*/

FRESULT f_chmod (
    const char *path,    /* Pointer to the file path */
    BYTE value,            /* Attribute bits */
    BYTE mask            /* Attribute mask to change */
)
{
    FRESULT res;
    BYTE *dir;
    DIR dirobj;
    char fn[8+3+1];
    FATFS *fs;


    res = auto_mount(&path, &fs, 1);
    if (res == FR_OK) {
        dirobj.fs = fs;
        res = trace_path(&dirobj, fn, path, &dir);    /* Trace the file path */
        if (res == FR_OK) {            /* Trace completed */
            if (dir == NULL) {
                res = FR_INVALID_NAME;
            } else {
                mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC;    /* Valid attribute mask */
                dir[DIR_Attr] = (value & mask) | (dir[DIR_Attr] & (BYTE)~mask);    /* Apply attribute change */
                res = sync(fs);
            }
        }
    }
    return res;
}




/*-----------------------------------------------------------------------*/
/* Rename File/Directory                                                 */
/*-----------------------------------------------------------------------*/

FRESULT f_rename (
    const char *path_old,    /* Pointer to the old name */
    const char *path_new    /* Pointer to the new name */
)
{
    FRESULT res;
    DWORD sect_old;
    BYTE *dir_old, *dir_new, direntry[32-11];
    DIR dirobj;
    char fn[8+3+1];
    FATFS *fs;


    res = auto_mount(&path_old, &fs, 1);
    if (res != FR_OK) return res;
    dirobj.fs = fs;

    res = trace_path(&dirobj, fn, path_old, &dir_old);    /* Check old object */
    if (res != FR_OK) return res;            /* The old object is not found */
    if (!dir_old) return FR_NO_FILE;
    sect_old = fs->winsect;                    /* Save the object information */
    memcpy(direntry, &dir_old[DIR_Attr], 32-11);

    res = trace_path(&dirobj, fn, path_new, &dir_new);    /* Check new object */
    if (res == FR_OK) return FR_EXIST;            /* The new object name is already existing */
    if (res != FR_NO_FILE) return res;            /* Is there no old name? */
    res = reserve_direntry(&dirobj, &dir_new);     /* Reserve a directory entry */
    if (res != FR_OK) return res;

    memcpy(&dir_new[DIR_Attr], direntry, 32-11);    /* Create new entry */
    memcpy(&dir_new[DIR_Name], fn, 8+3);
    dir_new[DIR_NTres] = fn[11];
    fs->winflag = 1;

    if (!move_window(fs, sect_old)) return FR_RW_ERROR;    /* Remove old entry */
    dir_old[DIR_Name] = 0xE5;

    return sync(fs);
}



#if _USE_MKFS
/*-----------------------------------------------------------------------*/
/* Create File System on the Drive                                       */
/*-----------------------------------------------------------------------*/

#define N_ROOTDIR 512
#define N_FATS 1
#define MAX_SECTOR 64000000UL
#define MIN_SECTOR 2000UL
#define ERASE_BLK 32


FRESULT f_mkfs (
    BYTE drv,            /* Logical drive number */
    BYTE partition,        /* Partitioning rule 0:FDISK, 1:SFD */
    BYTE allocsize        /* Allocation unit size [sectors] */
)
{
    BYTE fmt, m, *tbl;
    DWORD b_part, b_fat, b_dir, b_data;        /* Area offset (LBA) */
    DWORD n_part, n_rsv, n_fat, n_dir;        /* Area size */
    DWORD n_clust, n;
    FATFS *fs;
    DSTATUS stat;


    /* Check and mounted drive and clear work area */
    if (drv >= _DRIVES) return FR_INVALID_DRIVE;
    fs = FatFs[drv];
    if (!fs) return FR_NOT_ENABLED;
    memset(fs, 0, sizeof(FATFS));
    drv = LD2PD(drv);

    /* Check validity of the parameters */
    for (n = 1; n <= 64 && allocsize != n; n <<= 1);
    if (n > 64 || partition >= 2) return FR_MKFS_ABORTED;

    /* Get disk statics */
    stat = disk_initialize(drv);
    if (stat & STA_NOINIT) return FR_NOT_READY;
    if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
    if (disk_ioctl(drv, GET_SECTOR_COUNT, &n_part) != RES_OK || n_part < MIN_SECTOR)
        return FR_MKFS_ABORTED;
    if (n_part > MAX_SECTOR) n_part = MAX_SECTOR;
    b_part = (!partition) ? 63 : 0;
    n_part -= b_part;
#if S_MAX_SIZ > 512                        /* Check disk sector size */
    if (disk_ioctl(drv, GET_SECTOR_SIZE, &S_SIZ) != RES_OK
        || S_SIZ > S_MAX_SIZ
        || (DWORD)S_SIZ * allocsize > 32768U)
        return FR_MKFS_ABORTED;
#endif

    /* Pre-compute number of clusters and FAT type */
    n_clust = n_part / allocsize;
    fmt = FS_FAT12;
    if (n_clust >= 0xFF7) fmt = FS_FAT16;
    if (n_clust >= 0xFFF7) fmt = FS_FAT32;
    switch (fmt) {
    case FS_FAT12:
        n_fat = ((n_clust * 3 + 1) / 2 + 3 + S_SIZ - 1) / S_SIZ;
        n_rsv = 1 + partition;
        n_dir = N_ROOTDIR * 32 / S_SIZ;
        break;
    case FS_FAT16:
        n_fat = ((n_clust * 2) + 4 + S_SIZ - 1) / S_SIZ;
        n_rsv = 1 + partition;
        n_dir = N_ROOTDIR * 32 / S_SIZ;
        break;
    default:
        n_fat = ((n_clust * 4) + 8 + S_SIZ - 1) / S_SIZ;
        n_rsv = 33 - partition;
        n_dir = 0;
    }
    b_fat = b_part + n_rsv;            /* FATs start sector */
    b_dir = b_fat + n_fat * N_FATS;    /* Directory start sector */
    b_data = b_dir + n_dir;            /* Data start sector */

#ifdef ERASE_BLK
    /* Round up data start sector to erase block boundary */
    n = (b_data + ERASE_BLK - 1) & ~(ERASE_BLK - 1);
    b_dir += n - b_data;
    n_fat += (n - b_data) / N_FATS;
#endif
    /* Determine number of cluster and final check of validity of the FAT type */
    n_clust = (n_part - n_rsv - n_fat * 2 - n_dir) / allocsize;
    if (   (fmt == FS_FAT16 && n_clust < 0xFF7)
        || (fmt == FS_FAT32 && n_clust < 0xFFF7))
        return FR_MKFS_ABORTED;

    /* Create partition table if needed */
    if (!partition) {
        DWORD n_disk = b_part + n_part;

        tbl = &fs->win[MBR_Table];
        ST_DWORD(&tbl[0], 0x00010180);    /* Partition start in CHS */
        if (n_disk < 63UL * 255 * 1024) {    /* Partition end in CHS */
            n_disk = n_disk / 63 / 255;
            tbl[7] = (BYTE)n_disk;
            tbl[6] = (BYTE)((n_disk >> 2) | 63);
        } else {
            ST_WORD(&tbl[6], 0xFFFF);
        }
        tbl[5] = 254;
        if (fmt != FS_FAT32)            /* System ID */
            tbl[4] = (n_part < 0x10000) ? 0x04 : 0x06;
        else
            tbl[4] = 0x0c;
        ST_DWORD(&tbl[8], 63);            /* Partition start in LBA */
        ST_DWORD(&tbl[12], n_part);        /* Partition size in LBA */
        ST_WORD(&tbl[64], 0xAA55);        /* Signature */
        if (disk_write(drv, fs->win, 0, 1) != RES_OK)
            return FR_RW_ERROR;
    }

    /* Create boot record */
    memset(tbl = fs->win, 0, S_SIZ);
    ST_DWORD(&tbl[BS_jmpBoot], 0x90FEEB);        /* Boot code (jmp $, nop) */
    ST_WORD(&tbl[BPB_BytsPerSec], S_SIZ);        /* Sector size */
    tbl[BPB_SecPerClus] = (BYTE)allocsize;        /* Sectors per cluster */
    ST_WORD(&tbl[BPB_RsvdSecCnt], n_rsv);        /* Reserved sectors */
    tbl[BPB_NumFATs] = N_FATS;                    /* Number of FATs */
    ST_WORD(&tbl[BPB_RootEntCnt], S_SIZ / 32 * n_dir); /* Number of rootdir entries */
    if (n_part < 0x10000) {                        /* Number of total sectors */
        ST_WORD(&tbl[BPB_TotSec16], n_part);
    } else {
        ST_DWORD(&tbl[BPB_TotSec32], n_part);
    }
    tbl[BPB_Media] = 0xF8;                        /* Media descripter */
    ST_WORD(&tbl[BPB_SecPerTrk], 63);            /* Number of sectors per track */
    ST_WORD(&tbl[BPB_NumHeads], 255);            /* Number of heads */
    ST_DWORD(&tbl[BPB_HiddSec], b_part);        /* Hidden sectors */
    if (fmt != FS_FAT32) {
        ST_WORD(&tbl[BPB_FATSz16], n_fat);        /* Number of secters per FAT */
        tbl[BS_DrvNum] = 0x80;                    /* Drive number */
        tbl[BS_BootSig] = 0x29;                    /* 

⌨️ 快捷键说明

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