📄 ff.c
字号:
}
} while (--clust);
}
*nclust = n;
return FR_OK;
}
/*-----------------------------------------------------------------------*/
/* 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;
if ((res = auto_mount(&path, &fs, 1)) != 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_NO_FILE; /* It is a root directory */
if (*(dir+11) & AM_RDO) return FR_DENIED; /* It is a R/O item */
dsect = fs->winsect;
dclust = ((DWORD)LD_WORD(dir+20) << 16) | LD_WORD(dir+26);
if (*(dir+11) & 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 = 0;
do {
if (!move_window(fs, dirobj.sect)) return FR_RW_ERROR;
sdir = &fs->win[(dirobj.index & 15) * 32];
if (*sdir == 0) break;
if (!((*sdir == 0xE5) || *sdir == '.') && !(*(sdir+11) & 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 = 0xE5;
fs->winflag = 1;
if (!remove_chain(fs, dclust)) return FR_RW_ERROR; /* Remove the cluster chain */
if (!move_window(fs, 0)) return FR_RW_ERROR;
return FR_OK;
}
/*-----------------------------------------------------------------------*/
/* Create a Directory */
/*-----------------------------------------------------------------------*/
FRESULT f_mkdir (
const char *path /* Pointer to the directory path */
)
{
BYTE *dir, *w, n;
char fn[8+3+1];
DWORD sect, dsect, dclust, pclust, tim;
FRESULT res;
DIR dirobj;
FATFS *fs;
if ((res = auto_mount(&path, &fs, 1)) != FR_OK)
return res;
dirobj.fs = fs;
res = trace_path(&dirobj, fn, path, &dir); /* Trace the file path */
if (res == FR_OK) return FR_DENIED; /* Any file or directory is already existing */
if (res != FR_NO_FILE) return res;
dir = reserve_direntry(&dirobj); /* Reserve a directory entry */
if (dir == NULL) return FR_DENIED;
sect = fs->winsect;
dsect = clust2sect(fs, dclust = create_chain(fs, 0)); /* Get a new cluster for new directory */
if (!dsect) return FR_DENIED;
if (!move_window(fs, 0)) return 0;
w = fs->win;
memset(w, 0, 512); /* Initialize the directory table */
for (n = fs->sects_clust - 1; n; n--) {
if (disk_write(fs->drive, w, dsect+n, 1) != RES_OK)
return FR_RW_ERROR;
}
fs->winsect = dsect; /* Create dot directories */
memset(w, ' ', 8+3);
*w = '.';
*(w+11) = AM_DIR;
tim = get_fattime();
ST_DWORD(w+22, tim);
ST_WORD(w+26, dclust);
ST_WORD(w+20, dclust >> 16);
memcpy(w+32, w, 32); *(w+33) = '.';
pclust = dirobj.sclust;
if (fs->fs_type == FS_FAT32 && pclust == fs->dirbase) pclust = 0;
ST_WORD(w+32+26, pclust);
ST_WORD(w+32+20, pclust >> 16);
fs->winflag = 1;
if (!move_window(fs, sect)) return FR_RW_ERROR;
memcpy(dir, fn, 8+3); /* Initialize the new entry */
*(dir+11) = AM_DIR;
*(dir+12) = fn[11];
memset(dir+13, 0, 32-13);
ST_DWORD(dir+22, tim); /* Crated time */
ST_WORD(dir+26, dclust); /* Table start cluster */
ST_WORD(dir+20, dclust >> 16);
fs->winflag = 1;
if (!move_window(fs, 0)) return FR_RW_ERROR;
return FR_OK;
}
/*-----------------------------------------------------------------------*/
/* 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;
if ((res = auto_mount(&path, &fs, 1)) != 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 == NULL) {
res = FR_NO_FILE;
} else {
mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */
*(dir+11) = (value & mask) | (*(dir+11) & ~mask); /* Apply attribute change */
fs->winflag = 1;
if (!move_window(fs, 0)) res = FR_RW_ERROR;
}
}
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;
if ((res = auto_mount(&path_old, &fs, 1)) != 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+11, 32-11);
res = trace_path(&dirobj, fn, path_new, &dir_new); /* Check new object */
if (res == FR_OK) return FR_DENIED; /* The new object name is already existing */
if (res != FR_NO_FILE) return res;
dir_new = reserve_direntry(&dirobj); /* Reserve a directory entry */
if (dir_new == NULL) return FR_DENIED;
memcpy(dir_new+11, direntry, 32-11); /* Create new entry */
memcpy(dir_new, fn, 8+3);
*(dir_new+12) = fn[11];
fs->winflag = 1;
if (!move_window(fs, sect_old)) return FR_RW_ERROR; /* Remove old entry */
*dir_old = 0xE5;
fs->winflag = 1;
if (!move_window(fs, 0)) return FR_RW_ERROR;
return FR_OK;
}
#ifdef _USE_MKFS
/*-----------------------------------------------------------------------*/
/* Create File System on the Drive */
/*-----------------------------------------------------------------------*/
#define ERASE_BLK 32
#define N_ROOTDIR 512
#define N_FATS 2
FRESULT f_mkfs (
BYTE drv, /* Logical drive number */
BYTE partition, /* Partitioning rule 0:FDISK, 1:SFD */
BYTE allocsize /* Allocation unit size */
)
{
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;
static const BYTE tbl_alloc[] = {1,2,4,8,16,32,64,0};
FATFS *fs;
DSTATUS stat;
/* Check mounted drive */
if (drv >= _DRIVES) return FR_INVALID_DRIVE;
if (!(fs = FatFs[drv])) return FR_NOT_ENABLED;
memset(fs, 0, sizeof(FATFS));
drv = ld2pd(drv);
/* Check validity of the parameters */
for (n = 0; allocsize != tbl_alloc[n] && tbl_alloc[n]; n++);
if (!tbl_alloc[n] || partition >= 2) return FR_MKFS_ABORTED;
/* Get disk size */
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_SECTORS, &n_part) != RES_OK || n_part < 1000)
return FR_MKFS_ABORTED;
b_part = (!partition) ? 63 : 0;
n_part -= b_part;
/* 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 * 2 + 1) / 3 + 3 + 511) / 512;
n_rsv = 1 + partition;
n_dir = N_ROOTDIR * 32 / 512;
break;
case FS_FAT16:
n_fat = ((n_clust * 2) + 4 + 511) / 512;
n_rsv = 1 + partition;
n_dir = N_ROOTDIR * 32 / 512;
break;
default:
n_fat = ((n_clust * 4) + 8 + 511) / 512;
n_rsv = 33 - partition;
n_dir = 0;
}
b_fat = b_part + n_rsv;
b_dir = b_fat + n_fat * N_FATS;
b_data = b_dir + n_dir;
#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[0x1BE];
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, 512);
ST_DWORD(tbl+0, 0x0090FEEB); /* Boot code (jmp $) */
ST_WORD(tbl+11, 512); /* Sector size */
*(tbl+13) = (BYTE)allocsize; /* Cluster size */
ST_WORD(tbl+14, n_rsv); /* Reserved sectors */
*(tbl+16) = N_FATS; /* Number of FATs */
ST_WORD(tbl+17, n_dir * 16); /* Number of rootdir entries */
if (n_part < 0x10000) { /* Number of total sectors */
ST_WORD(tbl+19, n_part);
} else {
ST_DWORD(tbl+32, n_part);
}
*(tbl+21) = 0xF8; /* Media descripter */
ST_WORD(tbl+24, 63); /* Number of sectors per track */
ST_WORD(tbl+26, 255); /* Number of heads */
ST_DWORD(tbl+28, b_part); /* Hidden sectors */
if (fmt != FS_FAT32) {
ST_WORD(tbl+22, n_fat); /* Number of secters per FAT */
*(tbl+36) = 0x80; /* Drive number */
*(tbl+38) = 0x29; /* Extended boot signature */
memcpy(tbl+43, "NO NAME ", 11); /* Volume lavel */
memcpy(tbl+54, (fmt == FS_FAT12) ? /* FAT signature */
"FAT12 " : "FAT16 ", 8);
} else {
ST_DWORD(tbl+36, n_fat); /* Number of secters per FAT */
ST_DWORD(tbl+44, 2); /* Root directory cluster */
ST_WORD(tbl+48, 1); /* FSInfo record */
ST_WORD(tbl+50, 6); /* Backup boot record */
*(tbl+64) = 0x80; /* Drive number */
*(tbl+66) = 0x29; /* Extended boot signature */
memcpy(tbl+71, "NO NAME ", 11); /* Volume lavel */
memcpy(tbl+82, "FAT32 ", 8); /* FAT signature */
}
*(WORD*)(tbl+510) = 0xAA55; /* Signature */
if (disk_write(drv, tbl, b_part, 1) != RES_OK)
return FR_RW_ERROR;
if (fmt == FS_FAT32)
disk_write(drv, tbl, b_part+6, 1);
/* Create FSInfo record if needed */
if (fmt == FS_FAT32) {
memset(tbl, 0, 510);
ST_DWORD(tbl, 0x41615252);
ST_DWORD(tbl+484, 0x61417272);
ST_DWORD(tbl+488, 0xFFFFFFFF);
ST_DWORD(tbl+492, 0xFFFFFFFF);
if (disk_write(drv, tbl, b_part+1, 1) != RES_OK)
return FR_RW_ERROR;
disk_write(drv, tbl, b_part+7, 1);
}
/* Initialize FAT area */
for (m = 0; m < N_FATS; m++) {
memset(tbl, 0, 512); /* 1st sector of the FAT */
if (fmt != FS_FAT32) {
n = (fmt == FS_FAT12) ? 0xFFFFF8 : 0xFFFFFFF8;
ST_DWORD(tbl+0, n);
} else {
ST_DWORD(tbl+0, 0xFFFFFFF8);
ST_DWORD(tbl+4, 0xFFFFFFFF);
ST_DWORD(tbl+8, 0x0FFFFFFF);
}
if (disk_write(drv, tbl, b_fat++, 1) != RES_OK)
return FR_RW_ERROR;
memset(tbl, 0, 512); /* Following sectors */
for (n = 1; n < n_fat; n++) {
if (disk_write(drv, tbl, b_fat++, 1) != RES_OK)
return FR_RW_ERROR;
}
}
/* Initialize Root directory */
for (m = 0; m < 64; m++) {
if (disk_write(drv, tbl, b_fat++, 1) != RES_OK)
return FR_RW_ERROR;
}
return FR_OK;
}
#endif /* _USE_MKFS */
#endif /* _FS_READONLY == 0 */
#endif /* _FS_MINIMIZE == 0 */
#endif /* _FS_MINIMIZE <= 1 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -